xref: /csrg-svn/lib/libc/db/btree/bt_utils.c (revision 46137)
1*46137Smao /*-
2*46137Smao  * Copyright (c) 1990 The Regents of the University of California.
3*46137Smao  * All rights reserved.
4*46137Smao  *
5*46137Smao  * This code is derived from software contributed to Berkeley by
6*46137Smao  * Mike Olson.
7*46137Smao  *
8*46137Smao  * %sccs.include.redist.c%
9*46137Smao  */
10*46137Smao 
11*46137Smao #if defined(LIBC_SCCS) && !defined(lint)
12*46137Smao static char sccsid[] = "@(#)bt_utils.c	5.1 (Berkeley) 01/23/91";
13*46137Smao #endif /* LIBC_SCCS and not lint */
14*46137Smao 
15*46137Smao #include <sys/types.h>
16*46137Smao #include <db.h>
17*46137Smao #include "btree.h"
18*46137Smao 
19*46137Smao /*
20*46137Smao  *  _BT_BUILDRET -- Build return key/data pair as a result of search or scan.
21*46137Smao  *
22*46137Smao  *	This routine manages the statically allocated buffers in which we
23*46137Smao  *	return data to the user.
24*46137Smao  *
25*46137Smao  *	Parameters:
26*46137Smao  *		t -- btree from which to return datum
27*46137Smao  *		d -- DATUM to be returned to the user.
28*46137Smao  *		data -- data argument supplied by user for return
29*46137Smao  *		key -- key argument supplied by user for return
30*46137Smao  *
31*46137Smao  *	Returns:
32*46137Smao  *		RET_SUCCESS, RET_ERROR.
33*46137Smao  *
34*46137Smao  *	Side Effects:
35*46137Smao  *		May free and reallocate static buffers, if the data
36*46137Smao  *		we want to return is bigger than the space we have to
37*46137Smao  *		do so.
38*46137Smao  */
39*46137Smao 
40*46137Smao int
41*46137Smao _bt_buildret(t, d, data, key)
42*46137Smao 	BTREE_P t;
43*46137Smao 	DATUM *d;
44*46137Smao 	DBT *data;
45*46137Smao 	DBT *key;
46*46137Smao {
47*46137Smao 	static int _data_s = 0;
48*46137Smao 	static int _key_s = 0;
49*46137Smao 	static char *_data = (char *) NULL;
50*46137Smao 	static char *_key = (char *) NULL;
51*46137Smao 	pgno_t chain;
52*46137Smao 
53*46137Smao 	if (d->d_flags & D_BIGKEY) {
54*46137Smao 		if (_key != (char *) NULL)
55*46137Smao 			(void) free(_key);
56*46137Smao 		(void) bcopy((char *) &(d->d_bytes[0]),
57*46137Smao 		      	     (char *) &chain,
58*46137Smao 		      	     sizeof(chain));
59*46137Smao 		if (_bt_getbig(t, chain, &_key, &_key_s) == RET_ERROR)
60*46137Smao 			return (RET_ERROR);
61*46137Smao 		key->data = _key;
62*46137Smao 		key->size = _key_s;
63*46137Smao 	} else {
64*46137Smao 		/* need more space for key? */
65*46137Smao 		if (d->d_ksize > _key_s) {
66*46137Smao 			if (_key != (char *) NULL)
67*46137Smao 				(void) free (_key);
68*46137Smao 			if ((_key = (char *) malloc((unsigned) d->d_ksize))
69*46137Smao 			    == (char *) NULL)
70*46137Smao 				return (RET_ERROR);
71*46137Smao 			_key_s = d->d_ksize;
72*46137Smao 		}
73*46137Smao 
74*46137Smao 		key->data = _key;
75*46137Smao 		if ((key->size = d->d_ksize) > 0)
76*46137Smao 			(void) bcopy(&(d->d_bytes[0]),
77*46137Smao 				     _key,
78*46137Smao 				     (int) d->d_ksize);
79*46137Smao 	}
80*46137Smao 
81*46137Smao 	if (d->d_flags & D_BIGDATA) {
82*46137Smao 		if (_data != (char *) NULL)
83*46137Smao 			(void) free(_data);
84*46137Smao 		(void) bcopy(&(d->d_bytes[d->d_ksize]),
85*46137Smao 		      	     (char *) &chain,
86*46137Smao 		      	     sizeof(chain));
87*46137Smao 		if (_bt_getbig(t, chain, &_data, &_data_s) == RET_ERROR)
88*46137Smao 			return (RET_ERROR);
89*46137Smao 		data->data = _data;
90*46137Smao 		data->size = _data_s;
91*46137Smao 	} else {
92*46137Smao 		/* need more space for data? */
93*46137Smao 		if (d->d_dsize > _data_s) {
94*46137Smao 			if (_data != (char *) NULL)
95*46137Smao 				(void) free (_data);
96*46137Smao 			if ((_data = (char *) malloc((unsigned) d->d_dsize))
97*46137Smao 			    == (char *) NULL)
98*46137Smao 				return (RET_ERROR);
99*46137Smao 			_data_s = d->d_dsize;
100*46137Smao 		}
101*46137Smao 
102*46137Smao 		data->data = _data;
103*46137Smao 
104*46137Smao 		if ((data->size = d->d_dsize) > 0)
105*46137Smao 			(void) bcopy(&(d->d_bytes[d->d_ksize]),
106*46137Smao 				      _data,
107*46137Smao 				      (size_t) (d->d_dsize));
108*46137Smao 	}
109*46137Smao 
110*46137Smao 	return (RET_SUCCESS);
111*46137Smao }
112*46137Smao 
113*46137Smao /*
114*46137Smao  *  _BT_CMP -- Compare a key to a given item on the current page.
115*46137Smao  *
116*46137Smao  *	This routine is a wrapper for the user's comparison function.
117*46137Smao  *
118*46137Smao  *	Parameters:
119*46137Smao  *		t -- tree in which to do comparison
120*46137Smao  *		p -- pointer to one argument for the comparison function
121*46137Smao  *		n -- index of item to supply second arg to comparison function
122*46137Smao  *
123*46137Smao  *	Returns:
124*46137Smao  *		< 0 if p is < item at n
125*46137Smao  *		= 0 if p is = item at n
126*46137Smao  *		> 0 if p is > item at n
127*46137Smao  */
128*46137Smao 
129*46137Smao int
130*46137Smao _bt_cmp(t, p, n)
131*46137Smao 	BTREE_P t;
132*46137Smao 	char *p;
133*46137Smao 	index_t n;
134*46137Smao {
135*46137Smao 	BTHEADER *h;
136*46137Smao 	IDATUM *id;
137*46137Smao 	DATUM *d;
138*46137Smao 	char *arg;
139*46137Smao 	int ignore;
140*46137Smao 	int free_arg;
141*46137Smao 	pgno_t chain;
142*46137Smao 	int r;
143*46137Smao 
144*46137Smao 	h = t->bt_curpage;
145*46137Smao 
146*46137Smao 	/*
147*46137Smao 	 *  The left-most key at any level of the tree on internal pages
148*46137Smao 	 *  is guaranteed (artificially, by the code here) to be less than
149*46137Smao 	 *  any user key.  This saves us from having to update the leftmost
150*46137Smao 	 *  key when the user inserts a new key in the tree smaller than
151*46137Smao 	 *  anything we've seen yet.
152*46137Smao 	 */
153*46137Smao 
154*46137Smao 	if (h->h_prevpg == P_NONE && !(h->h_flags & F_LEAF) && n == 0)
155*46137Smao 		return (1);
156*46137Smao 
157*46137Smao 	if (h->h_flags & F_LEAF) {
158*46137Smao 		d = (DATUM *) GETDATUM(h,n);
159*46137Smao 		if (d->d_flags & D_BIGKEY) {
160*46137Smao 			free_arg = TRUE;
161*46137Smao 			bcopy(&(d->d_bytes[0]), (char *) &chain, sizeof(chain));
162*46137Smao 			if (_bt_getbig(t, chain, &arg, &ignore) == RET_ERROR)
163*46137Smao 				return (RET_ERROR);
164*46137Smao 		} else {
165*46137Smao 			free_arg = FALSE;
166*46137Smao 			arg = &(d->d_bytes[0]);
167*46137Smao 		}
168*46137Smao 	} else {
169*46137Smao 		id = (IDATUM *) GETDATUM(h,n);
170*46137Smao 		if (id->i_flags & D_BIGKEY) {
171*46137Smao 			free_arg = TRUE;
172*46137Smao 			bcopy(&(id->i_bytes[0]),
173*46137Smao 			      (char *) &chain,
174*46137Smao 			      sizeof(chain));
175*46137Smao 			if (_bt_getbig(t, chain, &arg, &ignore) == RET_ERROR)
176*46137Smao 				return (RET_ERROR);
177*46137Smao 		} else {
178*46137Smao 			free_arg = FALSE;
179*46137Smao 			arg = &(id->i_bytes[0]);
180*46137Smao 		}
181*46137Smao 	}
182*46137Smao 	r = (*(t->bt_compare))(p, arg);
183*46137Smao 
184*46137Smao 	if (free_arg)
185*46137Smao 		(void) free(arg);
186*46137Smao 
187*46137Smao 	return (r);
188*46137Smao }
189*46137Smao 
190*46137Smao /*
191*46137Smao  *  _BT_PUSH/_BT_POP -- Push/pop a parent page number on the parent stack.
192*46137Smao  *
193*46137Smao  *	When we descend the tree, we keep track of parent pages in order
194*46137Smao  *	to handle splits on insertions.
195*46137Smao  *
196*46137Smao  *	Parameters:
197*46137Smao  *		t -- tree for which to push parent
198*46137Smao  *		pgno -- page number to push (_bt_push only)
199*46137Smao  *
200*46137Smao  *	Returns:
201*46137Smao  *		RET_SUCCESS, RET_ERROR.
202*46137Smao  */
203*46137Smao 
204*46137Smao int
205*46137Smao _bt_push(t, pgno)
206*46137Smao 	BTREE_P t;
207*46137Smao 	pgno_t pgno;
208*46137Smao {
209*46137Smao 	BTSTACK *new;
210*46137Smao 
211*46137Smao 	if ((new = (BTSTACK *) malloc((unsigned) sizeof(BTSTACK)))
212*46137Smao 	    ==  (BTSTACK *) NULL)
213*46137Smao 		return (RET_ERROR);
214*46137Smao 	new->bts_pgno = pgno;
215*46137Smao 	new->bts_next = t->bt_stack;
216*46137Smao 	t->bt_stack = new;
217*46137Smao 
218*46137Smao 	return (RET_SUCCESS);
219*46137Smao }
220*46137Smao 
221*46137Smao pgno_t
222*46137Smao _bt_pop(t)
223*46137Smao 	BTREE_P t;
224*46137Smao {
225*46137Smao 	BTSTACK *s;
226*46137Smao 	pgno_t p = P_NONE;
227*46137Smao 
228*46137Smao 	if ((s = t->bt_stack) != (BTSTACK *) NULL) {
229*46137Smao 		p = s->bts_pgno;
230*46137Smao 		t->bt_stack = s->bts_next;
231*46137Smao 		(void) free ((char *) s);
232*46137Smao 	}
233*46137Smao 	return (p);
234*46137Smao }
235*46137Smao 
236*46137Smao #ifdef DEBUG
237*46137Smao void
238*46137Smao _btdump(tree)
239*46137Smao 	BTREE tree;
240*46137Smao {
241*46137Smao 	BTREE_P t = (BTREE_P) tree;
242*46137Smao 	DATUM *d;
243*46137Smao 	IDATUM *id;
244*46137Smao 	BTHEADER *h;
245*46137Smao 	pgno_t npages;
246*46137Smao 	pgno_t i;
247*46137Smao 	index_t cur, top;
248*46137Smao 
249*46137Smao 	npages = t->bt_npages;
250*46137Smao 	(void) printf("\"%s\" fd %d pgsz %d curpg %d @ 0x%lx",
251*46137Smao 		t->bt_fname, t->bt_s.bt_d.d_fd,
252*46137Smao 		t->bt_psize, t->bt_curpage);
253*46137Smao 	(void) printf("npg %d cmp 0x%lx flags=(", npages, t->bt_compare);
254*46137Smao 	if (t->bt_flags & BTF_SEQINIT)
255*46137Smao 		(void) printf("BTF_SEQINIT");
256*46137Smao 	(void) printf(")\n");
257*46137Smao 
258*46137Smao 	for (i = P_ROOT; i <= npages; i++) {
259*46137Smao 		if (_bt_getpage(t, i) == RET_ERROR)
260*46137Smao 			_punt();
261*46137Smao 		h = t->bt_curpage;
262*46137Smao 		top = NEXTINDEX(h);
263*46137Smao 		(void) printf("    page %d:\n", i);
264*46137Smao 		(void) printf("\tpgno %d prev %d next %d\n",
265*46137Smao 			h->h_pgno, h->h_prevpg, h->h_nextpg);
266*46137Smao 		(void) printf("\tlower %d upper %d nextind %d flags (",
267*46137Smao 			h->h_lower, h->h_upper, top);
268*46137Smao 		if (h->h_flags & F_LEAF)
269*46137Smao 			(void) printf("F_LEAF");
270*46137Smao 		else
271*46137Smao 			(void) printf("<internal>");
272*46137Smao 		if (h->h_flags & F_DIRTY)
273*46137Smao 			(void) printf("|F_DIRTY");
274*46137Smao 		if (h->h_flags & F_PRESERVE)
275*46137Smao 			(void) printf("|F_PRESERVE");
276*46137Smao 		if (h->h_flags & F_CONT) {
277*46137Smao 			(void) printf("|F_CONT)");
278*46137Smao 			if (h->h_prevpg == P_NONE) {
279*46137Smao 				size_t longsz;
280*46137Smao 				(void) bcopy((char *) &(h->h_linp[0]),
281*46137Smao 					      (char *) &longsz,
282*46137Smao 					      sizeof(longsz));
283*46137Smao 				printf("\n\t\t(chain start, data length %ld)",
284*46137Smao 					longsz);
285*46137Smao 			}
286*46137Smao 			printf("\n");
287*46137Smao 			continue;
288*46137Smao 		}
289*46137Smao 		(void) printf(")\n");
290*46137Smao 		for (cur = 0; cur < top; cur++) {
291*46137Smao 			(void) printf("\t  [%d] off %d ", cur, h->h_linp[cur]);
292*46137Smao 			if (h->h_flags & F_LEAF) {
293*46137Smao 				d = (DATUM *) GETDATUM(h,cur);
294*46137Smao 				(void) printf("ksize %d", d->d_ksize);
295*46137Smao 				if (d->d_flags & D_BIGKEY)
296*46137Smao 					(void) printf(" (indirect)");
297*46137Smao 				(void) printf("; dsize %d", d->d_dsize);
298*46137Smao 				if (d->d_flags & D_BIGDATA)
299*46137Smao 					(void) printf(" (indirect)");
300*46137Smao 			} else {
301*46137Smao 				id = (IDATUM *) GETDATUM(h,cur);
302*46137Smao 				(void) printf("size %d pgno %d",
303*46137Smao 					id->i_size, id->i_pgno);
304*46137Smao 				if (id->i_flags & D_BIGKEY)
305*46137Smao 					(void) printf(" (indirect)");
306*46137Smao 			}
307*46137Smao 			(void) printf("\n");
308*46137Smao 		}
309*46137Smao 		(void) printf("\n");
310*46137Smao 	}
311*46137Smao }
312*46137Smao #endif /* DEBUG */
313*46137Smao 
314*46137Smao #ifdef DEBUG
315*46137Smao _punt()
316*46137Smao {
317*46137Smao 	int pid;
318*46137Smao 
319*46137Smao 	pid = getpid();
320*46137Smao 	(void) kill(pid, SIGILL);
321*46137Smao }
322*46137Smao #endif /* DEBUG */
323