xref: /illumos-gate/usr/src/cmd/isns/isnsd/htable.c (revision fcf3ce44)
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 *
avl_search(const htab_t * tab,const uint32_t uid)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 *
avl_search_next(const htab_t * tab,const uint32_t uid)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 *
avl_ll(htab_itemx_t * a,htab_itemx_t * b)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 *
avl_rr(htab_itemx_t * a,htab_itemx_t * b)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 *
avl_lr(htab_itemx_t * a,htab_itemx_t * b)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 *
avl_rl(htab_itemx_t * a,htab_itemx_t * b)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
avl_insert(htab_t * tab,htab_itemx_t * x)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 *
new_uid(htab_t * tab,uint32_t uid)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
uid_insert(htab_t * tab,uint32_t * const uid_p,const uint32_t hval)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
enlarge_htab(htab_t * tab)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
htab_init()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 *
htab_create(int flags,uint16_t logsize,uint16_t chunks)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
htab_compute_hval(const uchar_t * key)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
htab_add(htab_t * tab,void * p,int flag,uint32_t * uid_p,int * update_p)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 *
htab_remove(htab_t * tab,void * p,uint32_t uid,int clone_flag)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
htab_lookup(htab_t * tab,void * p,uint32_t uid,uint32_t * uid_p,int (* callback)(void *,void *),int rekey)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
htab_get_next(htab_t * tab,uint32_t uid)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
htab_dump(htab_t * tab)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