1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <fmd_alloc.h> 30*7c478bd9Sstevel@tonic-gate #include <fmd_string.h> 31*7c478bd9Sstevel@tonic-gate #include <fmd_subr.h> 32*7c478bd9Sstevel@tonic-gate #include <fmd_api.h> 33*7c478bd9Sstevel@tonic-gate #include <fmd_serd.h> 34*7c478bd9Sstevel@tonic-gate #include <fmd.h> 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate static fmd_serd_eng_t * 37*7c478bd9Sstevel@tonic-gate fmd_serd_eng_alloc(const char *name, uint64_t n, hrtime_t t) 38*7c478bd9Sstevel@tonic-gate { 39*7c478bd9Sstevel@tonic-gate fmd_serd_eng_t *sgp = fmd_zalloc(sizeof (fmd_serd_eng_t), FMD_SLEEP); 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate sgp->sg_name = fmd_strdup(name, FMD_SLEEP); 42*7c478bd9Sstevel@tonic-gate sgp->sg_flags = FMD_SERD_DIRTY; 43*7c478bd9Sstevel@tonic-gate sgp->sg_n = n; 44*7c478bd9Sstevel@tonic-gate sgp->sg_t = t; 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate return (sgp); 47*7c478bd9Sstevel@tonic-gate } 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate static void 50*7c478bd9Sstevel@tonic-gate fmd_serd_eng_free(fmd_serd_eng_t *sgp) 51*7c478bd9Sstevel@tonic-gate { 52*7c478bd9Sstevel@tonic-gate fmd_serd_eng_reset(sgp); 53*7c478bd9Sstevel@tonic-gate fmd_strfree(sgp->sg_name); 54*7c478bd9Sstevel@tonic-gate fmd_free(sgp, sizeof (fmd_serd_eng_t)); 55*7c478bd9Sstevel@tonic-gate } 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate void 58*7c478bd9Sstevel@tonic-gate fmd_serd_hash_create(fmd_serd_hash_t *shp) 59*7c478bd9Sstevel@tonic-gate { 60*7c478bd9Sstevel@tonic-gate shp->sh_hashlen = fmd.d_str_buckets; 61*7c478bd9Sstevel@tonic-gate shp->sh_hash = fmd_zalloc(sizeof (void *) * shp->sh_hashlen, FMD_SLEEP); 62*7c478bd9Sstevel@tonic-gate shp->sh_count = 0; 63*7c478bd9Sstevel@tonic-gate } 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate void 66*7c478bd9Sstevel@tonic-gate fmd_serd_hash_destroy(fmd_serd_hash_t *shp) 67*7c478bd9Sstevel@tonic-gate { 68*7c478bd9Sstevel@tonic-gate fmd_serd_eng_t *sgp, *ngp; 69*7c478bd9Sstevel@tonic-gate uint_t i; 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate for (i = 0; i < shp->sh_hashlen; i++) { 72*7c478bd9Sstevel@tonic-gate for (sgp = shp->sh_hash[i]; sgp != NULL; sgp = ngp) { 73*7c478bd9Sstevel@tonic-gate ngp = sgp->sg_next; 74*7c478bd9Sstevel@tonic-gate fmd_serd_eng_free(sgp); 75*7c478bd9Sstevel@tonic-gate } 76*7c478bd9Sstevel@tonic-gate } 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate fmd_free(shp->sh_hash, sizeof (void *) * shp->sh_hashlen); 79*7c478bd9Sstevel@tonic-gate bzero(shp, sizeof (fmd_serd_hash_t)); 80*7c478bd9Sstevel@tonic-gate } 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate void 83*7c478bd9Sstevel@tonic-gate fmd_serd_hash_apply(fmd_serd_hash_t *shp, fmd_serd_eng_f *func, void *arg) 84*7c478bd9Sstevel@tonic-gate { 85*7c478bd9Sstevel@tonic-gate fmd_serd_eng_t *sgp; 86*7c478bd9Sstevel@tonic-gate uint_t i; 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate for (i = 0; i < shp->sh_hashlen; i++) { 89*7c478bd9Sstevel@tonic-gate for (sgp = shp->sh_hash[i]; sgp != NULL; sgp = sgp->sg_next) 90*7c478bd9Sstevel@tonic-gate func(sgp, arg); 91*7c478bd9Sstevel@tonic-gate } 92*7c478bd9Sstevel@tonic-gate } 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate uint_t 95*7c478bd9Sstevel@tonic-gate fmd_serd_hash_count(fmd_serd_hash_t *shp) 96*7c478bd9Sstevel@tonic-gate { 97*7c478bd9Sstevel@tonic-gate return (shp->sh_count); 98*7c478bd9Sstevel@tonic-gate } 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate int 101*7c478bd9Sstevel@tonic-gate fmd_serd_hash_contains(fmd_serd_hash_t *shp, fmd_event_t *ep) 102*7c478bd9Sstevel@tonic-gate { 103*7c478bd9Sstevel@tonic-gate fmd_serd_eng_t *sgp; 104*7c478bd9Sstevel@tonic-gate uint_t i; 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate for (i = 0; i < shp->sh_hashlen; i++) { 107*7c478bd9Sstevel@tonic-gate for (sgp = shp->sh_hash[i]; sgp != NULL; sgp = sgp->sg_next) { 108*7c478bd9Sstevel@tonic-gate if (fmd_serd_eng_contains(sgp, ep)) { 109*7c478bd9Sstevel@tonic-gate fmd_event_transition(ep, FMD_EVS_ACCEPTED); 110*7c478bd9Sstevel@tonic-gate return (1); 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate } 113*7c478bd9Sstevel@tonic-gate } 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate return (0); 116*7c478bd9Sstevel@tonic-gate } 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate fmd_serd_eng_t * 119*7c478bd9Sstevel@tonic-gate fmd_serd_eng_insert(fmd_serd_hash_t *shp, 120*7c478bd9Sstevel@tonic-gate const char *name, uint_t n, hrtime_t t) 121*7c478bd9Sstevel@tonic-gate { 122*7c478bd9Sstevel@tonic-gate uint_t h = fmd_strhash(name) % shp->sh_hashlen; 123*7c478bd9Sstevel@tonic-gate fmd_serd_eng_t *sgp = fmd_serd_eng_alloc(name, n, t); 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate sgp->sg_next = shp->sh_hash[h]; 126*7c478bd9Sstevel@tonic-gate shp->sh_hash[h] = sgp; 127*7c478bd9Sstevel@tonic-gate shp->sh_count++; 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate return (sgp); 130*7c478bd9Sstevel@tonic-gate } 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate fmd_serd_eng_t * 133*7c478bd9Sstevel@tonic-gate fmd_serd_eng_lookup(fmd_serd_hash_t *shp, const char *name) 134*7c478bd9Sstevel@tonic-gate { 135*7c478bd9Sstevel@tonic-gate uint_t h = fmd_strhash(name) % shp->sh_hashlen; 136*7c478bd9Sstevel@tonic-gate fmd_serd_eng_t *sgp; 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate for (sgp = shp->sh_hash[h]; sgp != NULL; sgp = sgp->sg_next) { 139*7c478bd9Sstevel@tonic-gate if (strcmp(name, sgp->sg_name) == 0) 140*7c478bd9Sstevel@tonic-gate return (sgp); 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate return (NULL); 144*7c478bd9Sstevel@tonic-gate } 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate void 147*7c478bd9Sstevel@tonic-gate fmd_serd_eng_delete(fmd_serd_hash_t *shp, const char *name) 148*7c478bd9Sstevel@tonic-gate { 149*7c478bd9Sstevel@tonic-gate uint_t h = fmd_strhash(name) % shp->sh_hashlen; 150*7c478bd9Sstevel@tonic-gate fmd_serd_eng_t *sgp, **pp = &shp->sh_hash[h]; 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate for (sgp = *pp; sgp != NULL; sgp = sgp->sg_next) { 153*7c478bd9Sstevel@tonic-gate if (strcmp(sgp->sg_name, name) != 0) 154*7c478bd9Sstevel@tonic-gate pp = &sgp->sg_next; 155*7c478bd9Sstevel@tonic-gate else 156*7c478bd9Sstevel@tonic-gate break; 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate if (sgp != NULL) { 160*7c478bd9Sstevel@tonic-gate *pp = sgp->sg_next; 161*7c478bd9Sstevel@tonic-gate fmd_serd_eng_free(sgp); 162*7c478bd9Sstevel@tonic-gate ASSERT(shp->sh_count != 0); 163*7c478bd9Sstevel@tonic-gate shp->sh_count--; 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate } 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate static void 168*7c478bd9Sstevel@tonic-gate fmd_serd_eng_discard(fmd_serd_eng_t *sgp, fmd_serd_elem_t *sep) 169*7c478bd9Sstevel@tonic-gate { 170*7c478bd9Sstevel@tonic-gate fmd_list_delete(&sgp->sg_list, sep); 171*7c478bd9Sstevel@tonic-gate sgp->sg_count--; 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate fmd_event_rele(sep->se_event); 174*7c478bd9Sstevel@tonic-gate fmd_free(sep, sizeof (fmd_serd_elem_t)); 175*7c478bd9Sstevel@tonic-gate } 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate int 178*7c478bd9Sstevel@tonic-gate fmd_serd_eng_contains(fmd_serd_eng_t *sgp, fmd_event_t *ep) 179*7c478bd9Sstevel@tonic-gate { 180*7c478bd9Sstevel@tonic-gate fmd_serd_elem_t *sep; 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate for (sep = fmd_list_next(&sgp->sg_list); 183*7c478bd9Sstevel@tonic-gate sep != NULL; sep = fmd_list_next(sep)) { 184*7c478bd9Sstevel@tonic-gate if (fmd_event_equal(sep->se_event, ep)) 185*7c478bd9Sstevel@tonic-gate return (1); 186*7c478bd9Sstevel@tonic-gate } 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate return (0); 189*7c478bd9Sstevel@tonic-gate } 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate int 192*7c478bd9Sstevel@tonic-gate fmd_serd_eng_record(fmd_serd_eng_t *sgp, fmd_event_t *ep) 193*7c478bd9Sstevel@tonic-gate { 194*7c478bd9Sstevel@tonic-gate fmd_serd_elem_t *sep, *oep; 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate /* 197*7c478bd9Sstevel@tonic-gate * If the fired flag is already set, return false and discard the 198*7c478bd9Sstevel@tonic-gate * event. This means that the caller will only see the engine "fire" 199*7c478bd9Sstevel@tonic-gate * once until fmd_serd_eng_reset() is called. The fmd_serd_eng_fired() 200*7c478bd9Sstevel@tonic-gate * function can also be used in combination with fmd_serd_eng_record(). 201*7c478bd9Sstevel@tonic-gate */ 202*7c478bd9Sstevel@tonic-gate if (sgp->sg_flags & FMD_SERD_FIRED) 203*7c478bd9Sstevel@tonic-gate return (FMD_B_FALSE); 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate while (sgp->sg_count > sgp->sg_n) 206*7c478bd9Sstevel@tonic-gate fmd_serd_eng_discard(sgp, fmd_list_next(&sgp->sg_list)); 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate fmd_event_hold(ep); 209*7c478bd9Sstevel@tonic-gate fmd_event_transition(ep, FMD_EVS_ACCEPTED); 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate sep = fmd_alloc(sizeof (fmd_serd_elem_t), FMD_SLEEP); 212*7c478bd9Sstevel@tonic-gate sep->se_event = ep; 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate fmd_list_append(&sgp->sg_list, sep); 215*7c478bd9Sstevel@tonic-gate sgp->sg_count++; 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate /* 218*7c478bd9Sstevel@tonic-gate * Pick up the oldest element pointer for comparison to 'sep'. We must 219*7c478bd9Sstevel@tonic-gate * do this after adding 'sep' because 'oep' and 'sep' can be the same. 220*7c478bd9Sstevel@tonic-gate */ 221*7c478bd9Sstevel@tonic-gate oep = fmd_list_next(&sgp->sg_list); 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate if (sgp->sg_count > sgp->sg_n && 224*7c478bd9Sstevel@tonic-gate fmd_event_delta(oep->se_event, sep->se_event) <= sgp->sg_t) { 225*7c478bd9Sstevel@tonic-gate sgp->sg_flags |= FMD_SERD_FIRED | FMD_SERD_DIRTY; 226*7c478bd9Sstevel@tonic-gate return (FMD_B_TRUE); 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate sgp->sg_flags |= FMD_SERD_DIRTY; 230*7c478bd9Sstevel@tonic-gate return (FMD_B_FALSE); 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate int 234*7c478bd9Sstevel@tonic-gate fmd_serd_eng_fired(fmd_serd_eng_t *sgp) 235*7c478bd9Sstevel@tonic-gate { 236*7c478bd9Sstevel@tonic-gate return (sgp->sg_flags & FMD_SERD_FIRED); 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate int 240*7c478bd9Sstevel@tonic-gate fmd_serd_eng_empty(fmd_serd_eng_t *sgp) 241*7c478bd9Sstevel@tonic-gate { 242*7c478bd9Sstevel@tonic-gate return (sgp->sg_count == 0); 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate void 246*7c478bd9Sstevel@tonic-gate fmd_serd_eng_reset(fmd_serd_eng_t *sgp) 247*7c478bd9Sstevel@tonic-gate { 248*7c478bd9Sstevel@tonic-gate while (sgp->sg_count != 0) 249*7c478bd9Sstevel@tonic-gate fmd_serd_eng_discard(sgp, fmd_list_next(&sgp->sg_list)); 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate sgp->sg_flags &= ~FMD_SERD_FIRED; 252*7c478bd9Sstevel@tonic-gate sgp->sg_flags |= FMD_SERD_DIRTY; 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate void 256*7c478bd9Sstevel@tonic-gate fmd_serd_eng_gc(fmd_serd_eng_t *sgp) 257*7c478bd9Sstevel@tonic-gate { 258*7c478bd9Sstevel@tonic-gate fmd_serd_elem_t *sep, *nep; 259*7c478bd9Sstevel@tonic-gate hrtime_t hrt; 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate if (sgp->sg_count == 0 || (sgp->sg_flags & FMD_SERD_FIRED)) 262*7c478bd9Sstevel@tonic-gate return; /* no garbage collection needed if empty or fired */ 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate sep = fmd_list_prev(&sgp->sg_list); 265*7c478bd9Sstevel@tonic-gate hrt = fmd_event_hrtime(sep->se_event) - sgp->sg_t; 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate for (sep = fmd_list_next(&sgp->sg_list); sep != NULL; sep = nep) { 268*7c478bd9Sstevel@tonic-gate if (fmd_event_hrtime(sep->se_event) >= hrt) 269*7c478bd9Sstevel@tonic-gate break; /* sep and subsequent events are all within T */ 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate nep = fmd_list_next(sep); 272*7c478bd9Sstevel@tonic-gate fmd_serd_eng_discard(sgp, sep); 273*7c478bd9Sstevel@tonic-gate sgp->sg_flags |= FMD_SERD_DIRTY; 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate void 278*7c478bd9Sstevel@tonic-gate fmd_serd_eng_commit(fmd_serd_eng_t *sgp) 279*7c478bd9Sstevel@tonic-gate { 280*7c478bd9Sstevel@tonic-gate fmd_serd_elem_t *sep; 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate if (!(sgp->sg_flags & FMD_SERD_DIRTY)) 283*7c478bd9Sstevel@tonic-gate return; /* engine has not changed since last commit */ 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate for (sep = fmd_list_next(&sgp->sg_list); sep != NULL; 286*7c478bd9Sstevel@tonic-gate sep = fmd_list_next(sep)) 287*7c478bd9Sstevel@tonic-gate fmd_event_commit(sep->se_event); 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate sgp->sg_flags &= ~FMD_SERD_DIRTY; 290*7c478bd9Sstevel@tonic-gate } 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate void 293*7c478bd9Sstevel@tonic-gate fmd_serd_eng_clrdirty(fmd_serd_eng_t *sgp) 294*7c478bd9Sstevel@tonic-gate { 295*7c478bd9Sstevel@tonic-gate sgp->sg_flags &= ~FMD_SERD_DIRTY; 296*7c478bd9Sstevel@tonic-gate } 297