xref: /csrg-svn/lib/libc/db/btree/bt_utils.c (revision 46561)
146137Smao /*-
246137Smao  * Copyright (c) 1990 The Regents of the University of California.
346137Smao  * All rights reserved.
446137Smao  *
546137Smao  * This code is derived from software contributed to Berkeley by
646137Smao  * Mike Olson.
746137Smao  *
846137Smao  * %sccs.include.redist.c%
946137Smao  */
1046137Smao 
1146137Smao #if defined(LIBC_SCCS) && !defined(lint)
12*46561Sbostic static char sccsid[] = "@(#)bt_utils.c	5.2 (Berkeley) 02/22/91";
1346137Smao #endif /* LIBC_SCCS and not lint */
1446137Smao 
1546137Smao #include <sys/types.h>
1646137Smao #include <db.h>
17*46561Sbostic #include <stdlib.h>
18*46561Sbostic #include <string.h>
1946137Smao #include "btree.h"
2046137Smao 
2146137Smao /*
2246137Smao  *  _BT_BUILDRET -- Build return key/data pair as a result of search or scan.
2346137Smao  *
2446137Smao  *	This routine manages the statically allocated buffers in which we
2546137Smao  *	return data to the user.
2646137Smao  *
2746137Smao  *	Parameters:
2846137Smao  *		t -- btree from which to return datum
2946137Smao  *		d -- DATUM to be returned to the user.
3046137Smao  *		data -- data argument supplied by user for return
3146137Smao  *		key -- key argument supplied by user for return
3246137Smao  *
3346137Smao  *	Returns:
3446137Smao  *		RET_SUCCESS, RET_ERROR.
3546137Smao  *
3646137Smao  *	Side Effects:
3746137Smao  *		May free and reallocate static buffers, if the data
3846137Smao  *		we want to return is bigger than the space we have to
3946137Smao  *		do so.
4046137Smao  */
4146137Smao 
4246137Smao int
4346137Smao _bt_buildret(t, d, data, key)
4446137Smao 	BTREE_P t;
4546137Smao 	DATUM *d;
4646137Smao 	DBT *data;
4746137Smao 	DBT *key;
4846137Smao {
4946137Smao 	static int _data_s = 0;
5046137Smao 	static int _key_s = 0;
5146137Smao 	static char *_data = (char *) NULL;
5246137Smao 	static char *_key = (char *) NULL;
5346137Smao 	pgno_t chain;
5446137Smao 
5546137Smao 	if (d->d_flags & D_BIGKEY) {
5646137Smao 		if (_key != (char *) NULL)
5746137Smao 			(void) free(_key);
5846137Smao 		(void) bcopy((char *) &(d->d_bytes[0]),
5946137Smao 		      	     (char *) &chain,
6046137Smao 		      	     sizeof(chain));
6146137Smao 		if (_bt_getbig(t, chain, &_key, &_key_s) == RET_ERROR)
6246137Smao 			return (RET_ERROR);
6346137Smao 		key->data = _key;
6446137Smao 		key->size = _key_s;
6546137Smao 	} else {
6646137Smao 		/* need more space for key? */
6746137Smao 		if (d->d_ksize > _key_s) {
6846137Smao 			if (_key != (char *) NULL)
6946137Smao 				(void) free (_key);
7046137Smao 			if ((_key = (char *) malloc((unsigned) d->d_ksize))
7146137Smao 			    == (char *) NULL)
7246137Smao 				return (RET_ERROR);
7346137Smao 			_key_s = d->d_ksize;
7446137Smao 		}
7546137Smao 
7646137Smao 		key->data = _key;
7746137Smao 		if ((key->size = d->d_ksize) > 0)
7846137Smao 			(void) bcopy(&(d->d_bytes[0]),
7946137Smao 				     _key,
8046137Smao 				     (int) d->d_ksize);
8146137Smao 	}
8246137Smao 
8346137Smao 	if (d->d_flags & D_BIGDATA) {
8446137Smao 		if (_data != (char *) NULL)
8546137Smao 			(void) free(_data);
8646137Smao 		(void) bcopy(&(d->d_bytes[d->d_ksize]),
8746137Smao 		      	     (char *) &chain,
8846137Smao 		      	     sizeof(chain));
8946137Smao 		if (_bt_getbig(t, chain, &_data, &_data_s) == RET_ERROR)
9046137Smao 			return (RET_ERROR);
9146137Smao 		data->data = _data;
9246137Smao 		data->size = _data_s;
9346137Smao 	} else {
9446137Smao 		/* need more space for data? */
9546137Smao 		if (d->d_dsize > _data_s) {
9646137Smao 			if (_data != (char *) NULL)
9746137Smao 				(void) free (_data);
9846137Smao 			if ((_data = (char *) malloc((unsigned) d->d_dsize))
9946137Smao 			    == (char *) NULL)
10046137Smao 				return (RET_ERROR);
10146137Smao 			_data_s = d->d_dsize;
10246137Smao 		}
10346137Smao 
10446137Smao 		data->data = _data;
10546137Smao 
10646137Smao 		if ((data->size = d->d_dsize) > 0)
10746137Smao 			(void) bcopy(&(d->d_bytes[d->d_ksize]),
10846137Smao 				      _data,
10946137Smao 				      (size_t) (d->d_dsize));
11046137Smao 	}
11146137Smao 
11246137Smao 	return (RET_SUCCESS);
11346137Smao }
11446137Smao 
11546137Smao /*
11646137Smao  *  _BT_CMP -- Compare a key to a given item on the current page.
11746137Smao  *
11846137Smao  *	This routine is a wrapper for the user's comparison function.
11946137Smao  *
12046137Smao  *	Parameters:
12146137Smao  *		t -- tree in which to do comparison
12246137Smao  *		p -- pointer to one argument for the comparison function
12346137Smao  *		n -- index of item to supply second arg to comparison function
12446137Smao  *
12546137Smao  *	Returns:
12646137Smao  *		< 0 if p is < item at n
12746137Smao  *		= 0 if p is = item at n
12846137Smao  *		> 0 if p is > item at n
12946137Smao  */
13046137Smao 
13146137Smao int
13246137Smao _bt_cmp(t, p, n)
13346137Smao 	BTREE_P t;
13446137Smao 	char *p;
13546137Smao 	index_t n;
13646137Smao {
13746137Smao 	BTHEADER *h;
13846137Smao 	IDATUM *id;
13946137Smao 	DATUM *d;
14046137Smao 	char *arg;
14146137Smao 	int ignore;
14246137Smao 	int free_arg;
14346137Smao 	pgno_t chain;
14446137Smao 	int r;
14546137Smao 
14646137Smao 	h = t->bt_curpage;
14746137Smao 
14846137Smao 	/*
14946137Smao 	 *  The left-most key at any level of the tree on internal pages
15046137Smao 	 *  is guaranteed (artificially, by the code here) to be less than
15146137Smao 	 *  any user key.  This saves us from having to update the leftmost
15246137Smao 	 *  key when the user inserts a new key in the tree smaller than
15346137Smao 	 *  anything we've seen yet.
15446137Smao 	 */
15546137Smao 
15646137Smao 	if (h->h_prevpg == P_NONE && !(h->h_flags & F_LEAF) && n == 0)
15746137Smao 		return (1);
15846137Smao 
15946137Smao 	if (h->h_flags & F_LEAF) {
16046137Smao 		d = (DATUM *) GETDATUM(h,n);
16146137Smao 		if (d->d_flags & D_BIGKEY) {
16246137Smao 			free_arg = TRUE;
16346137Smao 			bcopy(&(d->d_bytes[0]), (char *) &chain, sizeof(chain));
16446137Smao 			if (_bt_getbig(t, chain, &arg, &ignore) == RET_ERROR)
16546137Smao 				return (RET_ERROR);
16646137Smao 		} else {
16746137Smao 			free_arg = FALSE;
16846137Smao 			arg = &(d->d_bytes[0]);
16946137Smao 		}
17046137Smao 	} else {
17146137Smao 		id = (IDATUM *) GETDATUM(h,n);
17246137Smao 		if (id->i_flags & D_BIGKEY) {
17346137Smao 			free_arg = TRUE;
17446137Smao 			bcopy(&(id->i_bytes[0]),
17546137Smao 			      (char *) &chain,
17646137Smao 			      sizeof(chain));
17746137Smao 			if (_bt_getbig(t, chain, &arg, &ignore) == RET_ERROR)
17846137Smao 				return (RET_ERROR);
17946137Smao 		} else {
18046137Smao 			free_arg = FALSE;
18146137Smao 			arg = &(id->i_bytes[0]);
18246137Smao 		}
18346137Smao 	}
18446137Smao 	r = (*(t->bt_compare))(p, arg);
18546137Smao 
18646137Smao 	if (free_arg)
18746137Smao 		(void) free(arg);
18846137Smao 
18946137Smao 	return (r);
19046137Smao }
19146137Smao 
19246137Smao /*
19346137Smao  *  _BT_PUSH/_BT_POP -- Push/pop a parent page number on the parent stack.
19446137Smao  *
19546137Smao  *	When we descend the tree, we keep track of parent pages in order
19646137Smao  *	to handle splits on insertions.
19746137Smao  *
19846137Smao  *	Parameters:
19946137Smao  *		t -- tree for which to push parent
20046137Smao  *		pgno -- page number to push (_bt_push only)
20146137Smao  *
20246137Smao  *	Returns:
20346137Smao  *		RET_SUCCESS, RET_ERROR.
20446137Smao  */
20546137Smao 
20646137Smao int
20746137Smao _bt_push(t, pgno)
20846137Smao 	BTREE_P t;
20946137Smao 	pgno_t pgno;
21046137Smao {
21146137Smao 	BTSTACK *new;
21246137Smao 
21346137Smao 	if ((new = (BTSTACK *) malloc((unsigned) sizeof(BTSTACK)))
21446137Smao 	    ==  (BTSTACK *) NULL)
21546137Smao 		return (RET_ERROR);
21646137Smao 	new->bts_pgno = pgno;
21746137Smao 	new->bts_next = t->bt_stack;
21846137Smao 	t->bt_stack = new;
21946137Smao 
22046137Smao 	return (RET_SUCCESS);
22146137Smao }
22246137Smao 
22346137Smao pgno_t
22446137Smao _bt_pop(t)
22546137Smao 	BTREE_P t;
22646137Smao {
22746137Smao 	BTSTACK *s;
22846137Smao 	pgno_t p = P_NONE;
22946137Smao 
23046137Smao 	if ((s = t->bt_stack) != (BTSTACK *) NULL) {
23146137Smao 		p = s->bts_pgno;
23246137Smao 		t->bt_stack = s->bts_next;
23346137Smao 		(void) free ((char *) s);
23446137Smao 	}
23546137Smao 	return (p);
23646137Smao }
23746137Smao 
23846137Smao #ifdef DEBUG
23946137Smao void
24046137Smao _btdump(tree)
24146137Smao 	BTREE tree;
24246137Smao {
24346137Smao 	BTREE_P t = (BTREE_P) tree;
24446137Smao 	DATUM *d;
24546137Smao 	IDATUM *id;
24646137Smao 	BTHEADER *h;
24746137Smao 	pgno_t npages;
24846137Smao 	pgno_t i;
24946137Smao 	index_t cur, top;
25046137Smao 
25146137Smao 	npages = t->bt_npages;
25246137Smao 	(void) printf("\"%s\" fd %d pgsz %d curpg %d @ 0x%lx",
25346137Smao 		t->bt_fname, t->bt_s.bt_d.d_fd,
25446137Smao 		t->bt_psize, t->bt_curpage);
25546137Smao 	(void) printf("npg %d cmp 0x%lx flags=(", npages, t->bt_compare);
25646137Smao 	if (t->bt_flags & BTF_SEQINIT)
25746137Smao 		(void) printf("BTF_SEQINIT");
25846137Smao 	(void) printf(")\n");
25946137Smao 
26046137Smao 	for (i = P_ROOT; i <= npages; i++) {
26146137Smao 		if (_bt_getpage(t, i) == RET_ERROR)
26246137Smao 			_punt();
26346137Smao 		h = t->bt_curpage;
26446137Smao 		top = NEXTINDEX(h);
26546137Smao 		(void) printf("    page %d:\n", i);
26646137Smao 		(void) printf("\tpgno %d prev %d next %d\n",
26746137Smao 			h->h_pgno, h->h_prevpg, h->h_nextpg);
26846137Smao 		(void) printf("\tlower %d upper %d nextind %d flags (",
26946137Smao 			h->h_lower, h->h_upper, top);
27046137Smao 		if (h->h_flags & F_LEAF)
27146137Smao 			(void) printf("F_LEAF");
27246137Smao 		else
27346137Smao 			(void) printf("<internal>");
27446137Smao 		if (h->h_flags & F_DIRTY)
27546137Smao 			(void) printf("|F_DIRTY");
27646137Smao 		if (h->h_flags & F_PRESERVE)
27746137Smao 			(void) printf("|F_PRESERVE");
27846137Smao 		if (h->h_flags & F_CONT) {
27946137Smao 			(void) printf("|F_CONT)");
28046137Smao 			if (h->h_prevpg == P_NONE) {
28146137Smao 				size_t longsz;
28246137Smao 				(void) bcopy((char *) &(h->h_linp[0]),
28346137Smao 					      (char *) &longsz,
28446137Smao 					      sizeof(longsz));
28546137Smao 				printf("\n\t\t(chain start, data length %ld)",
28646137Smao 					longsz);
28746137Smao 			}
28846137Smao 			printf("\n");
28946137Smao 			continue;
29046137Smao 		}
29146137Smao 		(void) printf(")\n");
29246137Smao 		for (cur = 0; cur < top; cur++) {
29346137Smao 			(void) printf("\t  [%d] off %d ", cur, h->h_linp[cur]);
29446137Smao 			if (h->h_flags & F_LEAF) {
29546137Smao 				d = (DATUM *) GETDATUM(h,cur);
29646137Smao 				(void) printf("ksize %d", d->d_ksize);
29746137Smao 				if (d->d_flags & D_BIGKEY)
29846137Smao 					(void) printf(" (indirect)");
29946137Smao 				(void) printf("; dsize %d", d->d_dsize);
30046137Smao 				if (d->d_flags & D_BIGDATA)
30146137Smao 					(void) printf(" (indirect)");
30246137Smao 			} else {
30346137Smao 				id = (IDATUM *) GETDATUM(h,cur);
30446137Smao 				(void) printf("size %d pgno %d",
30546137Smao 					id->i_size, id->i_pgno);
30646137Smao 				if (id->i_flags & D_BIGKEY)
30746137Smao 					(void) printf(" (indirect)");
30846137Smao 			}
30946137Smao 			(void) printf("\n");
31046137Smao 		}
31146137Smao 		(void) printf("\n");
31246137Smao 	}
31346137Smao }
31446137Smao #endif /* DEBUG */
31546137Smao 
31646137Smao #ifdef DEBUG
31746137Smao _punt()
31846137Smao {
31946137Smao 	int pid;
32046137Smao 
32146137Smao 	pid = getpid();
32246137Smao 	(void) kill(pid, SIGILL);
32346137Smao }
32446137Smao #endif /* DEBUG */
325