1*fcf3ce44SJohn Forte /* 2*fcf3ce44SJohn Forte * CDDL HEADER START 3*fcf3ce44SJohn Forte * 4*fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5*fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6*fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7*fcf3ce44SJohn Forte * 8*fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10*fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11*fcf3ce44SJohn Forte * and limitations under the License. 12*fcf3ce44SJohn Forte * 13*fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14*fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16*fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17*fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18*fcf3ce44SJohn Forte * 19*fcf3ce44SJohn Forte * CDDL HEADER END 20*fcf3ce44SJohn Forte */ 21*fcf3ce44SJohn Forte 22*fcf3ce44SJohn Forte /* 23*fcf3ce44SJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24*fcf3ce44SJohn Forte * Use is subject to license terms. 25*fcf3ce44SJohn Forte */ 26*fcf3ce44SJohn Forte 27*fcf3ce44SJohn Forte #include <stdio.h> 28*fcf3ce44SJohn Forte #include <stdlib.h> 29*fcf3ce44SJohn Forte #include <string.h> 30*fcf3ce44SJohn Forte #include <sys/types.h> 31*fcf3ce44SJohn Forte #include <pthread.h> 32*fcf3ce44SJohn Forte #include <libelf.h> 33*fcf3ce44SJohn Forte #include <libelf.h> 34*fcf3ce44SJohn Forte 35*fcf3ce44SJohn Forte #include "isns_server.h" 36*fcf3ce44SJohn Forte #include "isns_cache.h" 37*fcf3ce44SJohn Forte #include "isns_htab.h" 38*fcf3ce44SJohn Forte #include "isns_log.h" 39*fcf3ce44SJohn Forte 40*fcf3ce44SJohn Forte #define UID_REUSABLE(T, X) ((T) - (X)->t >= ONE_DAY) 41*fcf3ce44SJohn Forte 42*fcf3ce44SJohn Forte /* 43*fcf3ce44SJohn Forte * external variables. 44*fcf3ce44SJohn Forte */ 45*fcf3ce44SJohn Forte extern int cache_flag; 46*fcf3ce44SJohn Forte 47*fcf3ce44SJohn Forte /* 48*fcf3ce44SJohn Forte * **************************************************************************** 49*fcf3ce44SJohn Forte * avl_search: 50*fcf3ce44SJohn Forte * search a node from an AVL tree. 51*fcf3ce44SJohn Forte * 52*fcf3ce44SJohn Forte * tab - the hash table. 53*fcf3ce44SJohn Forte * uid - the object UID. 54*fcf3ce44SJohn Forte * return - the node which matches the object UID. 55*fcf3ce44SJohn Forte * 56*fcf3ce44SJohn Forte * **************************************************************************** 57*fcf3ce44SJohn Forte */ 58*fcf3ce44SJohn Forte static htab_itemx_t * 59*fcf3ce44SJohn Forte avl_search( 60*fcf3ce44SJohn Forte const htab_t *tab, 61*fcf3ce44SJohn Forte const uint32_t uid 62*fcf3ce44SJohn Forte ) 63*fcf3ce44SJohn Forte { 64*fcf3ce44SJohn Forte htab_itemx_t *x = tab->avlt; 65*fcf3ce44SJohn Forte 66*fcf3ce44SJohn Forte while (x != NULL) { 67*fcf3ce44SJohn Forte if (x->uid > uid) { 68*fcf3ce44SJohn Forte x = x->l; 69*fcf3ce44SJohn Forte } else if (x->uid < uid) { 70*fcf3ce44SJohn Forte x = x->r; 71*fcf3ce44SJohn Forte } else { 72*fcf3ce44SJohn Forte break; 73*fcf3ce44SJohn Forte } 74*fcf3ce44SJohn Forte } 75*fcf3ce44SJohn Forte 76*fcf3ce44SJohn Forte return (x); 77*fcf3ce44SJohn Forte } 78*fcf3ce44SJohn Forte 79*fcf3ce44SJohn Forte /* 80*fcf3ce44SJohn Forte * **************************************************************************** 81*fcf3ce44SJohn Forte * avl_search_next: 82*fcf3ce44SJohn Forte * search a node from an AVL tree, the object UID of the node 83*fcf3ce44SJohn Forte * is next to the previous object UID. 84*fcf3ce44SJohn Forte * 85*fcf3ce44SJohn Forte * tab - the hash table. 86*fcf3ce44SJohn Forte * uid - the previous object UID. 87*fcf3ce44SJohn Forte * return - the next node. 88*fcf3ce44SJohn Forte * 89*fcf3ce44SJohn Forte * **************************************************************************** 90*fcf3ce44SJohn Forte */ 91*fcf3ce44SJohn Forte static htab_itemx_t * 92*fcf3ce44SJohn Forte avl_search_next( 93*fcf3ce44SJohn Forte const htab_t *tab, 94*fcf3ce44SJohn Forte const uint32_t uid 95*fcf3ce44SJohn Forte ) 96*fcf3ce44SJohn Forte { 97*fcf3ce44SJohn Forte htab_itemx_t *p = NULL; 98*fcf3ce44SJohn Forte htab_itemx_t *x = tab->avlt; 99*fcf3ce44SJohn Forte 100*fcf3ce44SJohn Forte while (x != NULL) { 101*fcf3ce44SJohn Forte if (x->uid > uid) { 102*fcf3ce44SJohn Forte p = x; 103*fcf3ce44SJohn Forte x = x->l; 104*fcf3ce44SJohn Forte } else if (x->uid <= uid) { 105*fcf3ce44SJohn Forte x = x->r; 106*fcf3ce44SJohn Forte } 107*fcf3ce44SJohn Forte } 108*fcf3ce44SJohn Forte 109*fcf3ce44SJohn Forte return (p); 110*fcf3ce44SJohn Forte } 111*fcf3ce44SJohn Forte 112*fcf3ce44SJohn Forte /* 113*fcf3ce44SJohn Forte * **************************************************************************** 114*fcf3ce44SJohn Forte * avl_ll: 115*fcf3ce44SJohn Forte * perform LL balance rotation on an AVL tree (or the subtree). 116*fcf3ce44SJohn Forte * 117*fcf3ce44SJohn Forte * a - the left child. 118*fcf3ce44SJohn Forte * b - the right child. 119*fcf3ce44SJohn Forte * return - the new root. 120*fcf3ce44SJohn Forte * 121*fcf3ce44SJohn Forte * **************************************************************************** 122*fcf3ce44SJohn Forte */ 123*fcf3ce44SJohn Forte static htab_itemx_t * 124*fcf3ce44SJohn Forte avl_ll( 125*fcf3ce44SJohn Forte htab_itemx_t *a, 126*fcf3ce44SJohn Forte htab_itemx_t *b 127*fcf3ce44SJohn Forte ) 128*fcf3ce44SJohn Forte { 129*fcf3ce44SJohn Forte /* rotate right */ 130*fcf3ce44SJohn Forte a->l = b->r; 131*fcf3ce44SJohn Forte a->bf = 0; 132*fcf3ce44SJohn Forte b->r = a; 133*fcf3ce44SJohn Forte b->bf = 0; 134*fcf3ce44SJohn Forte 135*fcf3ce44SJohn Forte return (b); 136*fcf3ce44SJohn Forte } 137*fcf3ce44SJohn Forte 138*fcf3ce44SJohn Forte /* 139*fcf3ce44SJohn Forte * **************************************************************************** 140*fcf3ce44SJohn Forte * avl_rr: 141*fcf3ce44SJohn Forte * perform RR balance rotation on an AVL tree (or the subtree). 142*fcf3ce44SJohn Forte * 143*fcf3ce44SJohn Forte * a - the left child. 144*fcf3ce44SJohn Forte * b - the right child. 145*fcf3ce44SJohn Forte * return - the new root. 146*fcf3ce44SJohn Forte * 147*fcf3ce44SJohn Forte * **************************************************************************** 148*fcf3ce44SJohn Forte */ 149*fcf3ce44SJohn Forte static htab_itemx_t * 150*fcf3ce44SJohn Forte avl_rr( 151*fcf3ce44SJohn Forte htab_itemx_t *a, 152*fcf3ce44SJohn Forte htab_itemx_t *b 153*fcf3ce44SJohn Forte ) 154*fcf3ce44SJohn Forte { 155*fcf3ce44SJohn Forte /* rotate left */ 156*fcf3ce44SJohn Forte a->r = b->l; 157*fcf3ce44SJohn Forte a->bf = 0; 158*fcf3ce44SJohn Forte b->l = a; 159*fcf3ce44SJohn Forte b->bf = 0; 160*fcf3ce44SJohn Forte 161*fcf3ce44SJohn Forte return (b); 162*fcf3ce44SJohn Forte } 163*fcf3ce44SJohn Forte 164*fcf3ce44SJohn Forte /* 165*fcf3ce44SJohn Forte * **************************************************************************** 166*fcf3ce44SJohn Forte * avl_lr: 167*fcf3ce44SJohn Forte * perform LR balance rotation on an AVL tree (or the subtree). 168*fcf3ce44SJohn Forte * 169*fcf3ce44SJohn Forte * a - the left child. 170*fcf3ce44SJohn Forte * b - the right child. 171*fcf3ce44SJohn Forte * return - the new root. 172*fcf3ce44SJohn Forte * 173*fcf3ce44SJohn Forte * **************************************************************************** 174*fcf3ce44SJohn Forte */ 175*fcf3ce44SJohn Forte static htab_itemx_t * 176*fcf3ce44SJohn Forte avl_lr( 177*fcf3ce44SJohn Forte htab_itemx_t *a, 178*fcf3ce44SJohn Forte htab_itemx_t *b 179*fcf3ce44SJohn Forte ) 180*fcf3ce44SJohn Forte { 181*fcf3ce44SJohn Forte htab_itemx_t *c; 182*fcf3ce44SJohn Forte 183*fcf3ce44SJohn Forte c = b->r; 184*fcf3ce44SJohn Forte 185*fcf3ce44SJohn Forte /* rotate left and then right */ 186*fcf3ce44SJohn Forte a->l = c->r; 187*fcf3ce44SJohn Forte c->r = a; 188*fcf3ce44SJohn Forte b->r = c->l; 189*fcf3ce44SJohn Forte c->l = b; 190*fcf3ce44SJohn Forte 191*fcf3ce44SJohn Forte /* update balance factor */ 192*fcf3ce44SJohn Forte switch (c->bf) { 193*fcf3ce44SJohn Forte case -1: 194*fcf3ce44SJohn Forte /* on c's right */ 195*fcf3ce44SJohn Forte a->bf = 0; 196*fcf3ce44SJohn Forte b->bf = 1; 197*fcf3ce44SJohn Forte break; 198*fcf3ce44SJohn Forte case 0: 199*fcf3ce44SJohn Forte /* on c itself */ 200*fcf3ce44SJohn Forte a->bf = 0; 201*fcf3ce44SJohn Forte b->bf = 0; 202*fcf3ce44SJohn Forte break; 203*fcf3ce44SJohn Forte case 1: 204*fcf3ce44SJohn Forte /* on c's left */ 205*fcf3ce44SJohn Forte a->bf = -1; 206*fcf3ce44SJohn Forte b->bf = 0; 207*fcf3ce44SJohn Forte break; 208*fcf3ce44SJohn Forte } 209*fcf3ce44SJohn Forte c->bf = 0; 210*fcf3ce44SJohn Forte 211*fcf3ce44SJohn Forte return (c); 212*fcf3ce44SJohn Forte } 213*fcf3ce44SJohn Forte 214*fcf3ce44SJohn Forte /* 215*fcf3ce44SJohn Forte * **************************************************************************** 216*fcf3ce44SJohn Forte * avl_rl: 217*fcf3ce44SJohn Forte * perform RL balance rotation on an AVL tree (or the subtree). 218*fcf3ce44SJohn Forte * 219*fcf3ce44SJohn Forte * a - the left child. 220*fcf3ce44SJohn Forte * b - the right child. 221*fcf3ce44SJohn Forte * return - the new root. 222*fcf3ce44SJohn Forte * 223*fcf3ce44SJohn Forte * **************************************************************************** 224*fcf3ce44SJohn Forte */ 225*fcf3ce44SJohn Forte static htab_itemx_t * 226*fcf3ce44SJohn Forte avl_rl( 227*fcf3ce44SJohn Forte htab_itemx_t *a, 228*fcf3ce44SJohn Forte htab_itemx_t *b 229*fcf3ce44SJohn Forte ) 230*fcf3ce44SJohn Forte { 231*fcf3ce44SJohn Forte htab_itemx_t *c; 232*fcf3ce44SJohn Forte 233*fcf3ce44SJohn Forte c = b->l; 234*fcf3ce44SJohn Forte 235*fcf3ce44SJohn Forte /* rotate right and then left */ 236*fcf3ce44SJohn Forte a->r = c->l; 237*fcf3ce44SJohn Forte c->l = a; 238*fcf3ce44SJohn Forte b->l = c->r; 239*fcf3ce44SJohn Forte c->r = b; 240*fcf3ce44SJohn Forte 241*fcf3ce44SJohn Forte /* update balance factor */ 242*fcf3ce44SJohn Forte switch (c->bf) { 243*fcf3ce44SJohn Forte case -1: 244*fcf3ce44SJohn Forte /* on c's right */ 245*fcf3ce44SJohn Forte a->bf = 1; 246*fcf3ce44SJohn Forte b->bf = 0; 247*fcf3ce44SJohn Forte break; 248*fcf3ce44SJohn Forte case 0: 249*fcf3ce44SJohn Forte /* on c itself */ 250*fcf3ce44SJohn Forte a->bf = 0; 251*fcf3ce44SJohn Forte b->bf = 0; 252*fcf3ce44SJohn Forte break; 253*fcf3ce44SJohn Forte case 1: 254*fcf3ce44SJohn Forte /* on c's left */ 255*fcf3ce44SJohn Forte a->bf = 0; 256*fcf3ce44SJohn Forte b->bf = -1; 257*fcf3ce44SJohn Forte break; 258*fcf3ce44SJohn Forte } 259*fcf3ce44SJohn Forte c->bf = 0; 260*fcf3ce44SJohn Forte 261*fcf3ce44SJohn Forte return (c); 262*fcf3ce44SJohn Forte } 263*fcf3ce44SJohn Forte 264*fcf3ce44SJohn Forte /* 265*fcf3ce44SJohn Forte * **************************************************************************** 266*fcf3ce44SJohn Forte * avl_insert: 267*fcf3ce44SJohn Forte * insert a node into an AVL tree. 268*fcf3ce44SJohn Forte * 269*fcf3ce44SJohn Forte * tab - the hash table. 270*fcf3ce44SJohn Forte * x - the node being added. 271*fcf3ce44SJohn Forte * 272*fcf3ce44SJohn Forte * **************************************************************************** 273*fcf3ce44SJohn Forte */ 274*fcf3ce44SJohn Forte static void 275*fcf3ce44SJohn Forte avl_insert( 276*fcf3ce44SJohn Forte htab_t *tab, 277*fcf3ce44SJohn Forte htab_itemx_t *x 278*fcf3ce44SJohn Forte ) 279*fcf3ce44SJohn Forte { 280*fcf3ce44SJohn Forte htab_itemx_t *f, *a, *p, *q, *b, *c; 281*fcf3ce44SJohn Forte int d; 282*fcf3ce44SJohn Forte 283*fcf3ce44SJohn Forte /* initialize the new one */ 284*fcf3ce44SJohn Forte x->bf = 0; 285*fcf3ce44SJohn Forte x->l = NULL; 286*fcf3ce44SJohn Forte x->r = NULL; 287*fcf3ce44SJohn Forte 288*fcf3ce44SJohn Forte if (tab->avlt == NULL) { 289*fcf3ce44SJohn Forte tab->avlt = x; 290*fcf3ce44SJohn Forte } else { 291*fcf3ce44SJohn Forte /* locate the position */ 292*fcf3ce44SJohn Forte f = NULL; 293*fcf3ce44SJohn Forte a = tab->avlt; 294*fcf3ce44SJohn Forte p = tab->avlt; 295*fcf3ce44SJohn Forte q = NULL; 296*fcf3ce44SJohn Forte while (p != NULL) { 297*fcf3ce44SJohn Forte if (p->bf != 0) { 298*fcf3ce44SJohn Forte a = p; 299*fcf3ce44SJohn Forte f = q; 300*fcf3ce44SJohn Forte } 301*fcf3ce44SJohn Forte q = p; 302*fcf3ce44SJohn Forte if (x->uid < q->uid) { 303*fcf3ce44SJohn Forte p = p->l; 304*fcf3ce44SJohn Forte } else { 305*fcf3ce44SJohn Forte p = p->r; 306*fcf3ce44SJohn Forte } 307*fcf3ce44SJohn Forte } 308*fcf3ce44SJohn Forte /* insert it */ 309*fcf3ce44SJohn Forte if (x->uid < q->uid) { 310*fcf3ce44SJohn Forte q->l = x; 311*fcf3ce44SJohn Forte } else { 312*fcf3ce44SJohn Forte q->r = x; 313*fcf3ce44SJohn Forte } 314*fcf3ce44SJohn Forte /* update the balance factor between a to x */ 315*fcf3ce44SJohn Forte if (x->uid < a->uid) { 316*fcf3ce44SJohn Forte p = a->l; 317*fcf3ce44SJohn Forte d = 1; 318*fcf3ce44SJohn Forte } else { 319*fcf3ce44SJohn Forte p = a->r; 320*fcf3ce44SJohn Forte d = -1; 321*fcf3ce44SJohn Forte } 322*fcf3ce44SJohn Forte b = p; 323*fcf3ce44SJohn Forte while (p != x) { 324*fcf3ce44SJohn Forte if (x->uid < p->uid) { 325*fcf3ce44SJohn Forte p->bf = 1; 326*fcf3ce44SJohn Forte p = p->l; 327*fcf3ce44SJohn Forte } else { 328*fcf3ce44SJohn Forte p->bf = -1; 329*fcf3ce44SJohn Forte p = p->r; 330*fcf3ce44SJohn Forte } 331*fcf3ce44SJohn Forte } 332*fcf3ce44SJohn Forte /* brance is not broken */ 333*fcf3ce44SJohn Forte if (a->bf == 0) { 334*fcf3ce44SJohn Forte a->bf = d; 335*fcf3ce44SJohn Forte goto bal_done; 336*fcf3ce44SJohn Forte } else if (a->bf + d == 0) { 337*fcf3ce44SJohn Forte a->bf = 0; 338*fcf3ce44SJohn Forte goto bal_done; 339*fcf3ce44SJohn Forte } 340*fcf3ce44SJohn Forte /* rotate the tree */ 341*fcf3ce44SJohn Forte if (d == 1) { 342*fcf3ce44SJohn Forte if (b->bf == 1) { 343*fcf3ce44SJohn Forte /* LL rotate */ 344*fcf3ce44SJohn Forte c = avl_ll(a, b); 345*fcf3ce44SJohn Forte } else if (b->bf == -1) { 346*fcf3ce44SJohn Forte /* LR rotate */ 347*fcf3ce44SJohn Forte c = avl_lr(a, b); 348*fcf3ce44SJohn Forte } 349*fcf3ce44SJohn Forte } else { 350*fcf3ce44SJohn Forte if (b->bf == -1) { 351*fcf3ce44SJohn Forte /* RR rotate */ 352*fcf3ce44SJohn Forte c = avl_rr(a, b); 353*fcf3ce44SJohn Forte } else if (b->bf == 1) { 354*fcf3ce44SJohn Forte /* RL rotate */ 355*fcf3ce44SJohn Forte c = avl_rl(a, b); 356*fcf3ce44SJohn Forte } 357*fcf3ce44SJohn Forte } 358*fcf3ce44SJohn Forte /* update the parent */ 359*fcf3ce44SJohn Forte if (f == NULL) { 360*fcf3ce44SJohn Forte tab->avlt = c; 361*fcf3ce44SJohn Forte } else if (f->l == a) { 362*fcf3ce44SJohn Forte f->l = c; 363*fcf3ce44SJohn Forte } else if (f->r == a) { 364*fcf3ce44SJohn Forte f->r = c; 365*fcf3ce44SJohn Forte } 366*fcf3ce44SJohn Forte } 367*fcf3ce44SJohn Forte 368*fcf3ce44SJohn Forte bal_done: 369*fcf3ce44SJohn Forte if (x->uid > tab->buid) { 370*fcf3ce44SJohn Forte tab->buid = x->uid; 371*fcf3ce44SJohn Forte } 372*fcf3ce44SJohn Forte } 373*fcf3ce44SJohn Forte 374*fcf3ce44SJohn Forte /* 375*fcf3ce44SJohn Forte * **************************************************************************** 376*fcf3ce44SJohn Forte * new_uid: 377*fcf3ce44SJohn Forte * allocate new node(s) of the avl tree. 378*fcf3ce44SJohn Forte * 379*fcf3ce44SJohn Forte * tab - the hash table. 380*fcf3ce44SJohn Forte * uid - the UID of the node. 381*fcf3ce44SJohn Forte * return - the newly allocated UID node. 382*fcf3ce44SJohn Forte * 383*fcf3ce44SJohn Forte * **************************************************************************** 384*fcf3ce44SJohn Forte */ 385*fcf3ce44SJohn Forte static htab_itemx_t * 386*fcf3ce44SJohn Forte new_uid( 387*fcf3ce44SJohn Forte htab_t *tab, 388*fcf3ce44SJohn Forte uint32_t uid 389*fcf3ce44SJohn Forte ) 390*fcf3ce44SJohn Forte { 391*fcf3ce44SJohn Forte htab_itemx_t *x = NULL; 392*fcf3ce44SJohn Forte 393*fcf3ce44SJohn Forte uint32_t start, end; 394*fcf3ce44SJohn Forte 395*fcf3ce44SJohn Forte /* overflow happened */ 396*fcf3ce44SJohn Forte if (uid == 0) { 397*fcf3ce44SJohn Forte /* search for an unused one */ 398*fcf3ce44SJohn Forte uid ++; 399*fcf3ce44SJohn Forte while (uid != 0 && 400*fcf3ce44SJohn Forte avl_search(tab, uid) != NULL) { 401*fcf3ce44SJohn Forte uid ++; 402*fcf3ce44SJohn Forte } 403*fcf3ce44SJohn Forte if (uid == 0) { 404*fcf3ce44SJohn Forte /* all are used up, sigh! */ 405*fcf3ce44SJohn Forte return (NULL); 406*fcf3ce44SJohn Forte } 407*fcf3ce44SJohn Forte } 408*fcf3ce44SJohn Forte 409*fcf3ce44SJohn Forte /* check if there is a gap and the gap needs to be filled up */ 410*fcf3ce44SJohn Forte if (uid > tab->buid && 411*fcf3ce44SJohn Forte (tab->flags & UID_FLAGS_SEQ) != 0) { 412*fcf3ce44SJohn Forte start = tab->buid + 1; 413*fcf3ce44SJohn Forte } else { 414*fcf3ce44SJohn Forte start = uid; 415*fcf3ce44SJohn Forte } 416*fcf3ce44SJohn Forte end = uid; 417*fcf3ce44SJohn Forte 418*fcf3ce44SJohn Forte /* make new UID(s) */ 419*fcf3ce44SJohn Forte do { 420*fcf3ce44SJohn Forte if (x != NULL) { 421*fcf3ce44SJohn Forte x->hval = BAD_HVAL_MASK; 422*fcf3ce44SJohn Forte x->t = 0; 423*fcf3ce44SJohn Forte /* put it to the start of the fifo list */ 424*fcf3ce44SJohn Forte x->n = tab->list; 425*fcf3ce44SJohn Forte tab->list = x; 426*fcf3ce44SJohn Forte if (tab->tail == NULL) { 427*fcf3ce44SJohn Forte tab->tail = x; 428*fcf3ce44SJohn Forte } 429*fcf3ce44SJohn Forte } 430*fcf3ce44SJohn Forte x = (htab_itemx_t *)malloc(sizeof (htab_itemx_t)); 431*fcf3ce44SJohn Forte if (x != NULL) { 432*fcf3ce44SJohn Forte x->uid = start; 433*fcf3ce44SJohn Forte x->n = NULL; 434*fcf3ce44SJohn Forte /* insert it to the tree */ 435*fcf3ce44SJohn Forte avl_insert(tab, x); 436*fcf3ce44SJohn Forte } 437*fcf3ce44SJohn Forte start ++; 438*fcf3ce44SJohn Forte } while (x != NULL && start <= end && start != 0); 439*fcf3ce44SJohn Forte 440*fcf3ce44SJohn Forte return (x); 441*fcf3ce44SJohn Forte } 442*fcf3ce44SJohn Forte 443*fcf3ce44SJohn Forte /* 444*fcf3ce44SJohn Forte * **************************************************************************** 445*fcf3ce44SJohn Forte * uid_insert: 446*fcf3ce44SJohn Forte * insert a new UID node to the avl tree. 447*fcf3ce44SJohn Forte * 448*fcf3ce44SJohn Forte * tab - the hash table. 449*fcf3ce44SJohn Forte * uid_p- the pointer of the UID. 450*fcf3ce44SJohn Forte * hval - the hash value of the new node. 451*fcf3ce44SJohn Forte * return - 0: no UID value assigned; 452*fcf3ce44SJohn Forte * 1: assigned an UID. 453*fcf3ce44SJohn Forte * -1: no memory. 454*fcf3ce44SJohn Forte * -2: invalid UID. 455*fcf3ce44SJohn Forte * 456*fcf3ce44SJohn Forte * **************************************************************************** 457*fcf3ce44SJohn Forte */ 458*fcf3ce44SJohn Forte static int 459*fcf3ce44SJohn Forte uid_insert( 460*fcf3ce44SJohn Forte htab_t *tab, 461*fcf3ce44SJohn Forte uint32_t *const uid_p, 462*fcf3ce44SJohn Forte const uint32_t hval 463*fcf3ce44SJohn Forte ) 464*fcf3ce44SJohn Forte { 465*fcf3ce44SJohn Forte int assignx = 0; 466*fcf3ce44SJohn Forte 467*fcf3ce44SJohn Forte uint32_t uid = *uid_p; 468*fcf3ce44SJohn Forte 469*fcf3ce44SJohn Forte htab_itemx_t *x, *n; 470*fcf3ce44SJohn Forte 471*fcf3ce44SJohn Forte if (uid != 0) { 472*fcf3ce44SJohn Forte /* search the existing one from the tree */ 473*fcf3ce44SJohn Forte x = avl_search(tab, uid); 474*fcf3ce44SJohn Forte if (x == NULL) { 475*fcf3ce44SJohn Forte x = new_uid(tab, uid); 476*fcf3ce44SJohn Forte } else if (!BAD_HVAL(x->hval) && 477*fcf3ce44SJohn Forte x->hval != hval) { 478*fcf3ce44SJohn Forte /* the item with this uid will override an */ 479*fcf3ce44SJohn Forte /* existing item, we treat this as an error */ 480*fcf3ce44SJohn Forte return (-2); 481*fcf3ce44SJohn Forte } 482*fcf3ce44SJohn Forte } else { 483*fcf3ce44SJohn Forte /* assign a value */ 484*fcf3ce44SJohn Forte x = tab->list; 485*fcf3ce44SJohn Forte /* strip off the used ones */ 486*fcf3ce44SJohn Forte while (x != NULL && 487*fcf3ce44SJohn Forte !BAD_HVAL(x->hval)) { 488*fcf3ce44SJohn Forte n = x->n; 489*fcf3ce44SJohn Forte x->n = NULL; 490*fcf3ce44SJohn Forte x = n; 491*fcf3ce44SJohn Forte } 492*fcf3ce44SJohn Forte 493*fcf3ce44SJohn Forte if (x == NULL || 494*fcf3ce44SJohn Forte UID_REUSABLE(tab->c->timestamp(), x) == 0) { 495*fcf3ce44SJohn Forte /* none is available, make a new one */ 496*fcf3ce44SJohn Forte tab->list = x; 497*fcf3ce44SJohn Forte x = new_uid(tab, tab->buid + 1); 498*fcf3ce44SJohn Forte } else { 499*fcf3ce44SJohn Forte n = x->n; 500*fcf3ce44SJohn Forte x->n = NULL; 501*fcf3ce44SJohn Forte tab->list = n; 502*fcf3ce44SJohn Forte } 503*fcf3ce44SJohn Forte /* update the available list */ 504*fcf3ce44SJohn Forte if (tab->list == NULL) { 505*fcf3ce44SJohn Forte tab->tail = NULL; 506*fcf3ce44SJohn Forte } 507*fcf3ce44SJohn Forte assignx = 1; 508*fcf3ce44SJohn Forte if (x != NULL) { 509*fcf3ce44SJohn Forte *uid_p = x->uid; 510*fcf3ce44SJohn Forte } 511*fcf3ce44SJohn Forte } 512*fcf3ce44SJohn Forte 513*fcf3ce44SJohn Forte if (x == NULL) { 514*fcf3ce44SJohn Forte return (-1); /* no memory */ 515*fcf3ce44SJohn Forte } 516*fcf3ce44SJohn Forte 517*fcf3ce44SJohn Forte x->hval = hval; 518*fcf3ce44SJohn Forte x->t = 0; /* registration initial time */ 519*fcf3ce44SJohn Forte 520*fcf3ce44SJohn Forte return (assignx); 521*fcf3ce44SJohn Forte } 522*fcf3ce44SJohn Forte 523*fcf3ce44SJohn Forte /* 524*fcf3ce44SJohn Forte * **************************************************************************** 525*fcf3ce44SJohn Forte * enlarge_htab: 526*fcf3ce44SJohn Forte * enlarge the hash table when it gets too full. 527*fcf3ce44SJohn Forte * 528*fcf3ce44SJohn Forte * tab - the hash table. 529*fcf3ce44SJohn Forte * 530*fcf3ce44SJohn Forte * **************************************************************************** 531*fcf3ce44SJohn Forte */ 532*fcf3ce44SJohn Forte static void 533*fcf3ce44SJohn Forte enlarge_htab( 534*fcf3ce44SJohn Forte htab_t *tab 535*fcf3ce44SJohn Forte ) 536*fcf3ce44SJohn Forte { 537*fcf3ce44SJohn Forte htab_item_t **items; 538*fcf3ce44SJohn Forte uint16_t logsize; 539*fcf3ce44SJohn Forte uint32_t oldsz, newsz, mask; 540*fcf3ce44SJohn Forte htab_item_t *item, *tmp, **itemp; 541*fcf3ce44SJohn Forte uint16_t i; 542*fcf3ce44SJohn Forte uint32_t j; 543*fcf3ce44SJohn Forte 544*fcf3ce44SJohn Forte uint32_t uid; 545*fcf3ce44SJohn Forte 546*fcf3ce44SJohn Forte /* enlarge the logsize by one */ 547*fcf3ce44SJohn Forte logsize = tab->logsize + 1; 548*fcf3ce44SJohn Forte newsz = (1 << logsize); 549*fcf3ce44SJohn Forte items = (htab_item_t **)calloc( 550*fcf3ce44SJohn Forte newsz * tab->chunks, sizeof (htab_item_t *)); 551*fcf3ce44SJohn Forte /* re-hash all items to the new table */ 552*fcf3ce44SJohn Forte if (items != NULL) { 553*fcf3ce44SJohn Forte mask = newsz - 1; 554*fcf3ce44SJohn Forte oldsz = (1 << tab->logsize); 555*fcf3ce44SJohn Forte i = 0; 556*fcf3ce44SJohn Forte while (i < tab->chunks) { 557*fcf3ce44SJohn Forte j = 0; 558*fcf3ce44SJohn Forte while (j < oldsz) { 559*fcf3ce44SJohn Forte item = tab->items[(i * oldsz) + j]; 560*fcf3ce44SJohn Forte while (item != NULL) { 561*fcf3ce44SJohn Forte tmp = item->next; 562*fcf3ce44SJohn Forte itemp = &items[(i * newsz) + 563*fcf3ce44SJohn Forte (item->hval & mask)]; 564*fcf3ce44SJohn Forte uid = tab->c->get_uid(item->p); 565*fcf3ce44SJohn Forte while (*itemp != NULL && 566*fcf3ce44SJohn Forte tab->c->get_uid((*itemp)->p) > 567*fcf3ce44SJohn Forte uid) { 568*fcf3ce44SJohn Forte itemp = &(*itemp)->next; 569*fcf3ce44SJohn Forte } 570*fcf3ce44SJohn Forte item->next = *itemp; 571*fcf3ce44SJohn Forte *itemp = item; 572*fcf3ce44SJohn Forte item = tmp; 573*fcf3ce44SJohn Forte } 574*fcf3ce44SJohn Forte j ++; 575*fcf3ce44SJohn Forte } 576*fcf3ce44SJohn Forte i ++; 577*fcf3ce44SJohn Forte } 578*fcf3ce44SJohn Forte free(tab->items); 579*fcf3ce44SJohn Forte tab->items = items; 580*fcf3ce44SJohn Forte tab->logsize = logsize; 581*fcf3ce44SJohn Forte tab->mask = mask; 582*fcf3ce44SJohn Forte } else { 583*fcf3ce44SJohn Forte isnslog(LOG_DEBUG, "enlarge_htab", "calloc() failed."); 584*fcf3ce44SJohn Forte } 585*fcf3ce44SJohn Forte } 586*fcf3ce44SJohn Forte 587*fcf3ce44SJohn Forte /* 588*fcf3ce44SJohn Forte * **************************************************************************** 589*fcf3ce44SJohn Forte * htab_init: 590*fcf3ce44SJohn Forte * some generic initialization for the hash table. 591*fcf3ce44SJohn Forte * 592*fcf3ce44SJohn Forte * **************************************************************************** 593*fcf3ce44SJohn Forte */ 594*fcf3ce44SJohn Forte void 595*fcf3ce44SJohn Forte htab_init( 596*fcf3ce44SJohn Forte ) 597*fcf3ce44SJohn Forte { 598*fcf3ce44SJohn Forte /* do nothing */ 599*fcf3ce44SJohn Forte } 600*fcf3ce44SJohn Forte 601*fcf3ce44SJohn Forte /* 602*fcf3ce44SJohn Forte * **************************************************************************** 603*fcf3ce44SJohn Forte * htab_create: 604*fcf3ce44SJohn Forte * create a new hash table. 605*fcf3ce44SJohn Forte * 606*fcf3ce44SJohn Forte * flags - UID_FLAGS_SEQ: the UID in the table needs to be sequential. 607*fcf3ce44SJohn Forte * logsize - the hash table logsize. 608*fcf3ce44SJohn Forte * chunks - the number of seperated chunks of the table. 609*fcf3ce44SJohn Forte * return - the newly created hash table. 610*fcf3ce44SJohn Forte * 611*fcf3ce44SJohn Forte * **************************************************************************** 612*fcf3ce44SJohn Forte */ 613*fcf3ce44SJohn Forte htab_t * 614*fcf3ce44SJohn Forte htab_create( 615*fcf3ce44SJohn Forte int flags, 616*fcf3ce44SJohn Forte uint16_t logsize, 617*fcf3ce44SJohn Forte uint16_t chunks 618*fcf3ce44SJohn Forte ) 619*fcf3ce44SJohn Forte { 620*fcf3ce44SJohn Forte htab_t *tab = NULL; 621*fcf3ce44SJohn Forte htab_item_t **items = NULL; 622*fcf3ce44SJohn Forte uint32_t count; 623*fcf3ce44SJohn Forte 624*fcf3ce44SJohn Forte /* do not enlarge it if the logsize reaches the maximum */ 625*fcf3ce44SJohn Forte if (logsize <= MAX_LOGSIZE && 626*fcf3ce44SJohn Forte chunks > 0) { 627*fcf3ce44SJohn Forte tab = (htab_t *)calloc(1, sizeof (htab_t)); 628*fcf3ce44SJohn Forte if (tab != NULL) { 629*fcf3ce44SJohn Forte count = (1 << logsize); 630*fcf3ce44SJohn Forte items = (htab_item_t **)calloc( 631*fcf3ce44SJohn Forte count * chunks, sizeof (htab_item_t *)); 632*fcf3ce44SJohn Forte if (items != NULL) { 633*fcf3ce44SJohn Forte tab->flags = flags; 634*fcf3ce44SJohn Forte tab->items = items; 635*fcf3ce44SJohn Forte tab->logsize = logsize; 636*fcf3ce44SJohn Forte tab->chunks = chunks; 637*fcf3ce44SJohn Forte tab->mask = count - 1; 638*fcf3ce44SJohn Forte tab->count = 1; /* reserve one */ 639*fcf3ce44SJohn Forte tab->avlt = NULL; 640*fcf3ce44SJohn Forte tab->buid = 0; 641*fcf3ce44SJohn Forte tab->list = NULL; 642*fcf3ce44SJohn Forte tab->tail = NULL; 643*fcf3ce44SJohn Forte } else { 644*fcf3ce44SJohn Forte free(tab); 645*fcf3ce44SJohn Forte tab = NULL; 646*fcf3ce44SJohn Forte } 647*fcf3ce44SJohn Forte } 648*fcf3ce44SJohn Forte } 649*fcf3ce44SJohn Forte 650*fcf3ce44SJohn Forte return (tab); 651*fcf3ce44SJohn Forte } 652*fcf3ce44SJohn Forte 653*fcf3ce44SJohn Forte /* 654*fcf3ce44SJohn Forte * **************************************************************************** 655*fcf3ce44SJohn Forte * htab_compute_hval: 656*fcf3ce44SJohn Forte * compute a hash value for the specified key. 657*fcf3ce44SJohn Forte * 658*fcf3ce44SJohn Forte * key - the key of the hash. 659*fcf3ce44SJohn Forte * return - the hash value. 660*fcf3ce44SJohn Forte * 661*fcf3ce44SJohn Forte * **************************************************************************** 662*fcf3ce44SJohn Forte */ 663*fcf3ce44SJohn Forte uint32_t 664*fcf3ce44SJohn Forte htab_compute_hval( 665*fcf3ce44SJohn Forte const uchar_t *key 666*fcf3ce44SJohn Forte ) 667*fcf3ce44SJohn Forte { 668*fcf3ce44SJohn Forte /* use classic Dan Bernstein hash alorigthm */ 669*fcf3ce44SJohn Forte uint32_t hash = 5381; 670*fcf3ce44SJohn Forte int c; 671*fcf3ce44SJohn Forte 672*fcf3ce44SJohn Forte while ((c = *key++) != 0) { 673*fcf3ce44SJohn Forte hash = ((hash << 5) + hash) + c; 674*fcf3ce44SJohn Forte } 675*fcf3ce44SJohn Forte 676*fcf3ce44SJohn Forte return (hash); 677*fcf3ce44SJohn Forte } 678*fcf3ce44SJohn Forte 679*fcf3ce44SJohn Forte /* 680*fcf3ce44SJohn Forte * **************************************************************************** 681*fcf3ce44SJohn Forte * htab_add: 682*fcf3ce44SJohn Forte * add an object to the hash table. 683*fcf3ce44SJohn Forte * 684*fcf3ce44SJohn Forte * tab - the hash table. 685*fcf3ce44SJohn Forte * p - the object. 686*fcf3ce44SJohn Forte * flag - 0: not an association object; otherwise association object. 687*fcf3ce44SJohn Forte * uid_p- pointer of UID for returning. 688*fcf3ce44SJohn Forte * update_p - pointer of update flag for returning. 689*fcf3ce44SJohn Forte * return - error code. 690*fcf3ce44SJohn Forte * 691*fcf3ce44SJohn Forte * **************************************************************************** 692*fcf3ce44SJohn Forte */ 693*fcf3ce44SJohn Forte int 694*fcf3ce44SJohn Forte htab_add( 695*fcf3ce44SJohn Forte htab_t *tab, 696*fcf3ce44SJohn Forte void *p, 697*fcf3ce44SJohn Forte int flag, 698*fcf3ce44SJohn Forte uint32_t *uid_p, 699*fcf3ce44SJohn Forte int *update_p 700*fcf3ce44SJohn Forte ) 701*fcf3ce44SJohn Forte { 702*fcf3ce44SJohn Forte int ec = 0; 703*fcf3ce44SJohn Forte 704*fcf3ce44SJohn Forte htab_item_t *items = NULL, **itemp; 705*fcf3ce44SJohn Forte uint32_t chunksz; 706*fcf3ce44SJohn Forte uint32_t flags = 0; 707*fcf3ce44SJohn Forte uint32_t hval; 708*fcf3ce44SJohn Forte uint32_t uid = 0; 709*fcf3ce44SJohn Forte int i; 710*fcf3ce44SJohn Forte 711*fcf3ce44SJohn Forte /* compute the hash value */ 712*fcf3ce44SJohn Forte hval = VALID_HVAL(tab->c->get_hval(p, 0, &flags)); 713*fcf3ce44SJohn Forte 714*fcf3ce44SJohn Forte /* check for duplicate */ 715*fcf3ce44SJohn Forte items = tab->items[hval & tab->mask]; 716*fcf3ce44SJohn Forte while (items != NULL) { 717*fcf3ce44SJohn Forte if (tab->c->cmp(items->p, p, 0) == 0) { 718*fcf3ce44SJohn Forte if (flag == 0) { 719*fcf3ce44SJohn Forte ec = tab->c->replace_hook(items->p, p, uid_p, 720*fcf3ce44SJohn Forte update_p == NULL ? 1 : 0); 721*fcf3ce44SJohn Forte } 722*fcf3ce44SJohn Forte if (update_p != NULL) { 723*fcf3ce44SJohn Forte *update_p = 1; 724*fcf3ce44SJohn Forte } 725*fcf3ce44SJohn Forte items = NULL; 726*fcf3ce44SJohn Forte goto add_done; 727*fcf3ce44SJohn Forte } 728*fcf3ce44SJohn Forte items = items->next; 729*fcf3ce44SJohn Forte } 730*fcf3ce44SJohn Forte 731*fcf3ce44SJohn Forte /* add new object */ 732*fcf3ce44SJohn Forte if (update_p != NULL) { 733*fcf3ce44SJohn Forte *update_p = 0; 734*fcf3ce44SJohn Forte } 735*fcf3ce44SJohn Forte 736*fcf3ce44SJohn Forte /* make new items for the object */ 737*fcf3ce44SJohn Forte items = (htab_item_t *)calloc(tab->chunks, sizeof (htab_item_t)); 738*fcf3ce44SJohn Forte 739*fcf3ce44SJohn Forte if (items == NULL || 740*fcf3ce44SJohn Forte tab->count == 0 || 741*fcf3ce44SJohn Forte (++tab->count) == 0) { 742*fcf3ce44SJohn Forte /* no memory or table is full */ 743*fcf3ce44SJohn Forte ec = ISNS_RSP_INTERNAL_ERROR; 744*fcf3ce44SJohn Forte goto add_done; 745*fcf3ce44SJohn Forte } 746*fcf3ce44SJohn Forte 747*fcf3ce44SJohn Forte /* check if the table needs is too full */ 748*fcf3ce44SJohn Forte chunksz = (1 << tab->logsize); 749*fcf3ce44SJohn Forte if (tab->count >= (chunksz * HASH_RATIO) && 750*fcf3ce44SJohn Forte tab->logsize < MAX_LOGSIZE) { 751*fcf3ce44SJohn Forte enlarge_htab(tab); 752*fcf3ce44SJohn Forte chunksz = (1 << tab->logsize); 753*fcf3ce44SJohn Forte } 754*fcf3ce44SJohn Forte 755*fcf3ce44SJohn Forte /* put the UID of the object to the avl tree */ 756*fcf3ce44SJohn Forte uid = tab->c->get_uid(p); 757*fcf3ce44SJohn Forte switch (uid_insert(tab, &uid, hval)) { 758*fcf3ce44SJohn Forte case -2: 759*fcf3ce44SJohn Forte ec = ISNS_RSP_INVALID_REGIS; 760*fcf3ce44SJohn Forte goto add_done; 761*fcf3ce44SJohn Forte case -1: 762*fcf3ce44SJohn Forte ec = ISNS_RSP_INTERNAL_ERROR; 763*fcf3ce44SJohn Forte goto add_done; 764*fcf3ce44SJohn Forte case 0: 765*fcf3ce44SJohn Forte break; 766*fcf3ce44SJohn Forte case 1: 767*fcf3ce44SJohn Forte tab->c->set_uid(p, uid); 768*fcf3ce44SJohn Forte break; 769*fcf3ce44SJohn Forte default: 770*fcf3ce44SJohn Forte break; 771*fcf3ce44SJohn Forte } 772*fcf3ce44SJohn Forte 773*fcf3ce44SJohn Forte /* update data store before putting to hash table */ 774*fcf3ce44SJohn Forte if (flag == 0) { 775*fcf3ce44SJohn Forte /* not association object */ 776*fcf3ce44SJohn Forte ec = tab->c->add_hook(p); 777*fcf3ce44SJohn Forte } 778*fcf3ce44SJohn Forte 779*fcf3ce44SJohn Forte /* put the object to the table */ 780*fcf3ce44SJohn Forte for (i = 0; ec == 0; ) { 781*fcf3ce44SJohn Forte items[i].hval = hval; 782*fcf3ce44SJohn Forte items[i].p = p; 783*fcf3ce44SJohn Forte itemp = &tab->items[(i * chunksz) + (hval & tab->mask)]; 784*fcf3ce44SJohn Forte while (*itemp != NULL && 785*fcf3ce44SJohn Forte tab->c->get_uid((*itemp)->p) > uid) { 786*fcf3ce44SJohn Forte itemp = &(*itemp)->next; 787*fcf3ce44SJohn Forte } 788*fcf3ce44SJohn Forte items[i].next = *itemp; 789*fcf3ce44SJohn Forte *itemp = &items[i]; 790*fcf3ce44SJohn Forte i ++; 791*fcf3ce44SJohn Forte if (i < tab->chunks) { 792*fcf3ce44SJohn Forte hval = VALID_HVAL(tab->c->get_hval(p, i, &flags)); 793*fcf3ce44SJohn Forte } else { 794*fcf3ce44SJohn Forte break; 795*fcf3ce44SJohn Forte } 796*fcf3ce44SJohn Forte } 797*fcf3ce44SJohn Forte 798*fcf3ce44SJohn Forte /* cache has been successfully updated */ 799*fcf3ce44SJohn Forte SET_CACHE_UPDATED(); 800*fcf3ce44SJohn Forte 801*fcf3ce44SJohn Forte /* successfully added */ 802*fcf3ce44SJohn Forte items = NULL; 803*fcf3ce44SJohn Forte 804*fcf3ce44SJohn Forte if (ec == 0) { 805*fcf3ce44SJohn Forte /* perform the Default DD behavior */ 806*fcf3ce44SJohn Forte tab->c->ddd(p, '+'); 807*fcf3ce44SJohn Forte 808*fcf3ce44SJohn Forte /* set the return uid */ 809*fcf3ce44SJohn Forte if (uid_p != NULL) { 810*fcf3ce44SJohn Forte *uid_p = uid; 811*fcf3ce44SJohn Forte } 812*fcf3ce44SJohn Forte } 813*fcf3ce44SJohn Forte add_done: 814*fcf3ce44SJohn Forte if (ec != 0 && items != NULL) { 815*fcf3ce44SJohn Forte free(items); 816*fcf3ce44SJohn Forte } 817*fcf3ce44SJohn Forte 818*fcf3ce44SJohn Forte return (ec); 819*fcf3ce44SJohn Forte } 820*fcf3ce44SJohn Forte 821*fcf3ce44SJohn Forte /* 822*fcf3ce44SJohn Forte * **************************************************************************** 823*fcf3ce44SJohn Forte * htab_remove: 824*fcf3ce44SJohn Forte * remove an object from the hash table. 825*fcf3ce44SJohn Forte * 826*fcf3ce44SJohn Forte * tab - the hash table. 827*fcf3ce44SJohn Forte * p - the lookup control for the object. 828*fcf3ce44SJohn Forte * uid - the UID of the object. 829*fcf3ce44SJohn Forte * clone_flag - indicate if the removing is for an association object. 830*fcf3ce44SJohn Forte * return - the removed object. 831*fcf3ce44SJohn Forte * 832*fcf3ce44SJohn Forte * **************************************************************************** 833*fcf3ce44SJohn Forte */ 834*fcf3ce44SJohn Forte isns_obj_t * 835*fcf3ce44SJohn Forte htab_remove( 836*fcf3ce44SJohn Forte htab_t *tab, 837*fcf3ce44SJohn Forte void *p, 838*fcf3ce44SJohn Forte uint32_t uid, 839*fcf3ce44SJohn Forte int clone_flag 840*fcf3ce44SJohn Forte ) 841*fcf3ce44SJohn Forte { 842*fcf3ce44SJohn Forte void *zhizi = NULL; 843*fcf3ce44SJohn Forte void *clone = NULL; 844*fcf3ce44SJohn Forte htab_item_t *items = NULL; 845*fcf3ce44SJohn Forte htab_item_t *item, **itemp; 846*fcf3ce44SJohn Forte htab_itemx_t *x = NULL; 847*fcf3ce44SJohn Forte uint32_t chunksz; 848*fcf3ce44SJohn Forte uint32_t flags; 849*fcf3ce44SJohn Forte uint32_t hval; 850*fcf3ce44SJohn Forte int i; 851*fcf3ce44SJohn Forte 852*fcf3ce44SJohn Forte /* get the object hash value */ 853*fcf3ce44SJohn Forte if (uid != 0) { 854*fcf3ce44SJohn Forte x = avl_search(tab, uid); 855*fcf3ce44SJohn Forte if (x != NULL && !BAD_HVAL(x->hval)) { 856*fcf3ce44SJohn Forte hval = x->hval; 857*fcf3ce44SJohn Forte } else { 858*fcf3ce44SJohn Forte goto remove_done; 859*fcf3ce44SJohn Forte } 860*fcf3ce44SJohn Forte } else { 861*fcf3ce44SJohn Forte flags = 0 | FLAGS_CTRL_MASK; 862*fcf3ce44SJohn Forte hval = VALID_HVAL(tab->c->get_hval(p, 0, &flags)); 863*fcf3ce44SJohn Forte } 864*fcf3ce44SJohn Forte 865*fcf3ce44SJohn Forte /* search the object from the table */ 866*fcf3ce44SJohn Forte flags = 0; 867*fcf3ce44SJohn Forte chunksz = (1 << tab->logsize); 868*fcf3ce44SJohn Forte for (i = 0; ; ) { 869*fcf3ce44SJohn Forte itemp = &tab->items[(i * chunksz) + (hval & tab->mask)]; 870*fcf3ce44SJohn Forte item = *itemp; 871*fcf3ce44SJohn Forte while (item != NULL) { 872*fcf3ce44SJohn Forte /* found it */ 873*fcf3ce44SJohn Forte if (tab->c->cmp(item->p, p, 1) == 0) { 874*fcf3ce44SJohn Forte /* make an association object if the object */ 875*fcf3ce44SJohn Forte /* has membership in user-defined DD(s). */ 876*fcf3ce44SJohn Forte if (i == 0) { 877*fcf3ce44SJohn Forte if ((clone = tab->c->clone(item->p, 878*fcf3ce44SJohn Forte clone_flag)) == NULL) { 879*fcf3ce44SJohn Forte tab->c->ddd(item->p, '-'); 880*fcf3ce44SJohn Forte tab->count --; 881*fcf3ce44SJohn Forte items = item; 882*fcf3ce44SJohn Forte zhizi = item->p; 883*fcf3ce44SJohn Forte } 884*fcf3ce44SJohn Forte } 885*fcf3ce44SJohn Forte if (clone == NULL) { 886*fcf3ce44SJohn Forte /* remove it */ 887*fcf3ce44SJohn Forte *itemp = item->next; 888*fcf3ce44SJohn Forte } else if (clone == item->p) { 889*fcf3ce44SJohn Forte /* itself is an association object */ 890*fcf3ce44SJohn Forte goto remove_done; 891*fcf3ce44SJohn Forte } else { 892*fcf3ce44SJohn Forte /* replace it with association */ 893*fcf3ce44SJohn Forte zhizi = item->p; 894*fcf3ce44SJohn Forte item->p = clone; 895*fcf3ce44SJohn Forte } 896*fcf3ce44SJohn Forte if (i == 0) { 897*fcf3ce44SJohn Forte /* obj has been removed or updated */ 898*fcf3ce44SJohn Forte SET_CACHE_UPDATED(); 899*fcf3ce44SJohn Forte } 900*fcf3ce44SJohn Forte break; 901*fcf3ce44SJohn Forte } 902*fcf3ce44SJohn Forte itemp = &item->next; 903*fcf3ce44SJohn Forte item = *itemp; 904*fcf3ce44SJohn Forte } 905*fcf3ce44SJohn Forte i ++; 906*fcf3ce44SJohn Forte if (zhizi != NULL && i < tab->chunks) { 907*fcf3ce44SJohn Forte hval = VALID_HVAL(tab->c->get_hval( 908*fcf3ce44SJohn Forte zhizi, i, &flags)); 909*fcf3ce44SJohn Forte } else { 910*fcf3ce44SJohn Forte break; 911*fcf3ce44SJohn Forte } 912*fcf3ce44SJohn Forte } 913*fcf3ce44SJohn Forte 914*fcf3ce44SJohn Forte /* update the node in the avl tree */ 915*fcf3ce44SJohn Forte if (items != NULL) { 916*fcf3ce44SJohn Forte if (x == NULL) { 917*fcf3ce44SJohn Forte uid = tab->c->get_uid(zhizi); 918*fcf3ce44SJohn Forte ASSERT(uid != 0); 919*fcf3ce44SJohn Forte x = avl_search(tab, uid); 920*fcf3ce44SJohn Forte } 921*fcf3ce44SJohn Forte ASSERT(x != NULL && !BAD_HVAL(x->hval)); 922*fcf3ce44SJohn Forte /* mark the uid item as invalid */ 923*fcf3ce44SJohn Forte x->hval |= BAD_HVAL_MASK; 924*fcf3ce44SJohn Forte /* update the timestamp */ 925*fcf3ce44SJohn Forte x->t = tab->c->timestamp(); 926*fcf3ce44SJohn Forte /* put it to the end of fifo list */ 927*fcf3ce44SJohn Forte if (tab->list != NULL) { 928*fcf3ce44SJohn Forte tab->tail->n = x; 929*fcf3ce44SJohn Forte } else { 930*fcf3ce44SJohn Forte tab->list = x; 931*fcf3ce44SJohn Forte } 932*fcf3ce44SJohn Forte tab->tail = x; 933*fcf3ce44SJohn Forte } 934*fcf3ce44SJohn Forte 935*fcf3ce44SJohn Forte remove_done: 936*fcf3ce44SJohn Forte if (items != NULL) { 937*fcf3ce44SJohn Forte free(items); 938*fcf3ce44SJohn Forte } 939*fcf3ce44SJohn Forte 940*fcf3ce44SJohn Forte return (zhizi); 941*fcf3ce44SJohn Forte } 942*fcf3ce44SJohn Forte 943*fcf3ce44SJohn Forte /* 944*fcf3ce44SJohn Forte * **************************************************************************** 945*fcf3ce44SJohn Forte * htab_lookup: 946*fcf3ce44SJohn Forte * lookup an object from the hash table. 947*fcf3ce44SJohn Forte * 948*fcf3ce44SJohn Forte * tab - the hash table. 949*fcf3ce44SJohn Forte * p - the lookup control for the item. 950*fcf3ce44SJohn Forte * uid - the UID of the object. 951*fcf3ce44SJohn Forte * uid_p- the pointer of UID for returning. 952*fcf3ce44SJohn Forte * callback - callback function if the object is found. 953*fcf3ce44SJohn Forte * rekey - flag that indicates if the callback function will update 954*fcf3ce44SJohn Forte * the key of the object. 955*fcf3ce44SJohn Forte * return - error code. 956*fcf3ce44SJohn Forte * 957*fcf3ce44SJohn Forte * **************************************************************************** 958*fcf3ce44SJohn Forte */ 959*fcf3ce44SJohn Forte int 960*fcf3ce44SJohn Forte htab_lookup( 961*fcf3ce44SJohn Forte htab_t *tab, 962*fcf3ce44SJohn Forte void *p, 963*fcf3ce44SJohn Forte uint32_t uid, 964*fcf3ce44SJohn Forte uint32_t *uid_p, 965*fcf3ce44SJohn Forte int (*callback)(void *, void *), 966*fcf3ce44SJohn Forte int rekey 967*fcf3ce44SJohn Forte ) 968*fcf3ce44SJohn Forte { 969*fcf3ce44SJohn Forte uint32_t ret = 0; 970*fcf3ce44SJohn Forte void *zhizi = NULL; 971*fcf3ce44SJohn Forte htab_item_t *item, **itemp; 972*fcf3ce44SJohn Forte htab_itemx_t *x = NULL; 973*fcf3ce44SJohn Forte uint32_t chunksz; 974*fcf3ce44SJohn Forte uint32_t flags = 0 | FLAGS_CTRL_MASK; 975*fcf3ce44SJohn Forte uint32_t hval; 976*fcf3ce44SJohn Forte int i; 977*fcf3ce44SJohn Forte 978*fcf3ce44SJohn Forte /* compute the hash value */ 979*fcf3ce44SJohn Forte if (uid != 0) { 980*fcf3ce44SJohn Forte x = avl_search(tab, uid); 981*fcf3ce44SJohn Forte if (x != NULL) { 982*fcf3ce44SJohn Forte hval = x->hval; 983*fcf3ce44SJohn Forte } else { 984*fcf3ce44SJohn Forte hval = BAD_HVAL_MASK; 985*fcf3ce44SJohn Forte } 986*fcf3ce44SJohn Forte } else { 987*fcf3ce44SJohn Forte hval = VALID_HVAL(tab->c->get_hval(p, 0, &flags)); 988*fcf3ce44SJohn Forte } 989*fcf3ce44SJohn Forte 990*fcf3ce44SJohn Forte /* find the object */ 991*fcf3ce44SJohn Forte if (!BAD_HVAL(hval)) { 992*fcf3ce44SJohn Forte i = flags & FLAGS_CHUNK_MASK; 993*fcf3ce44SJohn Forte chunksz = (1 << tab->logsize); 994*fcf3ce44SJohn Forte itemp = &tab->items[(i * chunksz) + (hval & tab->mask)]; 995*fcf3ce44SJohn Forte item = *itemp; 996*fcf3ce44SJohn Forte while (item != NULL) { 997*fcf3ce44SJohn Forte if (tab->c->cmp(item->p, p, 1) == 0) { 998*fcf3ce44SJohn Forte zhizi = item->p; 999*fcf3ce44SJohn Forte break; 1000*fcf3ce44SJohn Forte } 1001*fcf3ce44SJohn Forte itemp = &item->next; 1002*fcf3ce44SJohn Forte item = *itemp; 1003*fcf3ce44SJohn Forte } 1004*fcf3ce44SJohn Forte } 1005*fcf3ce44SJohn Forte 1006*fcf3ce44SJohn Forte /* found it */ 1007*fcf3ce44SJohn Forte if (zhizi != NULL) { 1008*fcf3ce44SJohn Forte /* set the return uid */ 1009*fcf3ce44SJohn Forte if (uid_p != NULL) { 1010*fcf3ce44SJohn Forte *uid_p = tab->c->get_uid(zhizi); 1011*fcf3ce44SJohn Forte } 1012*fcf3ce44SJohn Forte /* invoke callback */ 1013*fcf3ce44SJohn Forte if (callback != NULL) { 1014*fcf3ce44SJohn Forte ret = callback(zhizi, p); 1015*fcf3ce44SJohn Forte } 1016*fcf3ce44SJohn Forte if (rekey != 0 && ret == 0) { 1017*fcf3ce44SJohn Forte /* Rekey works for one-chunk hash table only. */ 1018*fcf3ce44SJohn Forte ASSERT(tab->chunks == 1 && x != NULL); 1019*fcf3ce44SJohn Forte /* remove from previous slot */ 1020*fcf3ce44SJohn Forte *itemp = item->next; 1021*fcf3ce44SJohn Forte /* add it to the new slot */ 1022*fcf3ce44SJohn Forte flags = 0; 1023*fcf3ce44SJohn Forte hval = VALID_HVAL(tab->c->get_hval(zhizi, 0, &flags)); 1024*fcf3ce44SJohn Forte x->hval = hval; 1025*fcf3ce44SJohn Forte item->hval = hval; 1026*fcf3ce44SJohn Forte itemp = &tab->items[(hval & tab->mask)]; 1027*fcf3ce44SJohn Forte while (*itemp != NULL && 1028*fcf3ce44SJohn Forte (tab->c->get_uid((*itemp)->p) > 1029*fcf3ce44SJohn Forte tab->c->get_uid(zhizi))) { 1030*fcf3ce44SJohn Forte itemp = &(*itemp)->next; 1031*fcf3ce44SJohn Forte } 1032*fcf3ce44SJohn Forte item->next = *itemp; 1033*fcf3ce44SJohn Forte *itemp = item; 1034*fcf3ce44SJohn Forte } 1035*fcf3ce44SJohn Forte } else if (uid_p != NULL) { 1036*fcf3ce44SJohn Forte /* set the return uid to 0 */ 1037*fcf3ce44SJohn Forte *uid_p = 0; 1038*fcf3ce44SJohn Forte } 1039*fcf3ce44SJohn Forte 1040*fcf3ce44SJohn Forte return (ret); 1041*fcf3ce44SJohn Forte } 1042*fcf3ce44SJohn Forte 1043*fcf3ce44SJohn Forte /* 1044*fcf3ce44SJohn Forte * **************************************************************************** 1045*fcf3ce44SJohn Forte * htab_get_next: 1046*fcf3ce44SJohn Forte * get the next object UID from the hash table. 1047*fcf3ce44SJohn Forte * 1048*fcf3ce44SJohn Forte * tab - the hash table. 1049*fcf3ce44SJohn Forte * uid - the previous objet UID. 1050*fcf3ce44SJohn Forte * return - the next object UID. 1051*fcf3ce44SJohn Forte * 1052*fcf3ce44SJohn Forte * **************************************************************************** 1053*fcf3ce44SJohn Forte */ 1054*fcf3ce44SJohn Forte uint32_t 1055*fcf3ce44SJohn Forte htab_get_next( 1056*fcf3ce44SJohn Forte htab_t *tab, 1057*fcf3ce44SJohn Forte uint32_t uid 1058*fcf3ce44SJohn Forte ) 1059*fcf3ce44SJohn Forte { 1060*fcf3ce44SJohn Forte htab_itemx_t *x; 1061*fcf3ce44SJohn Forte 1062*fcf3ce44SJohn Forte do { 1063*fcf3ce44SJohn Forte /* search the next node from the avl tree */ 1064*fcf3ce44SJohn Forte x = avl_search_next(tab, uid); 1065*fcf3ce44SJohn Forte if (x != NULL) { 1066*fcf3ce44SJohn Forte uid = x->uid; 1067*fcf3ce44SJohn Forte /* validate the node */ 1068*fcf3ce44SJohn Forte if (!BAD_HVAL(x->hval)) { 1069*fcf3ce44SJohn Forte return (uid); 1070*fcf3ce44SJohn Forte } 1071*fcf3ce44SJohn Forte } 1072*fcf3ce44SJohn Forte } while (x != NULL); 1073*fcf3ce44SJohn Forte 1074*fcf3ce44SJohn Forte /* no more node is available */ 1075*fcf3ce44SJohn Forte return (0); 1076*fcf3ce44SJohn Forte } 1077*fcf3ce44SJohn Forte 1078*fcf3ce44SJohn Forte /* 1079*fcf3ce44SJohn Forte * **************************************************************************** 1080*fcf3ce44SJohn Forte * htab_dump: 1081*fcf3ce44SJohn Forte * dump all objects stored in the hash table for debug purpose. 1082*fcf3ce44SJohn Forte * 1083*fcf3ce44SJohn Forte * tab - the hash table. 1084*fcf3ce44SJohn Forte * 1085*fcf3ce44SJohn Forte * **************************************************************************** 1086*fcf3ce44SJohn Forte */ 1087*fcf3ce44SJohn Forte #ifdef DEBUG 1088*fcf3ce44SJohn Forte void 1089*fcf3ce44SJohn Forte htab_dump( 1090*fcf3ce44SJohn Forte htab_t *tab 1091*fcf3ce44SJohn Forte ) 1092*fcf3ce44SJohn Forte { 1093*fcf3ce44SJohn Forte uint32_t chunksz; 1094*fcf3ce44SJohn Forte htab_item_t *items; 1095*fcf3ce44SJohn Forte 1096*fcf3ce44SJohn Forte uint32_t i; 1097*fcf3ce44SJohn Forte 1098*fcf3ce44SJohn Forte chunksz = (1 << tab->logsize); 1099*fcf3ce44SJohn Forte 1100*fcf3ce44SJohn Forte for (i = 0; i < chunksz; i++) { 1101*fcf3ce44SJohn Forte items = tab->items[i]; 1102*fcf3ce44SJohn Forte while (items != NULL) { 1103*fcf3ce44SJohn Forte tab->c->dump(items->p); 1104*fcf3ce44SJohn Forte items = items->next; 1105*fcf3ce44SJohn Forte } 1106*fcf3ce44SJohn Forte } 1107*fcf3ce44SJohn Forte } 1108*fcf3ce44SJohn Forte #endif 1109