xref: /csrg-svn/lib/libc/db/recno/rec_search.c (revision 57447)
150995Sbostic /*-
250995Sbostic  * Copyright (c) 1990 The Regents of the University of California.
350995Sbostic  * All rights reserved.
450995Sbostic  *
550995Sbostic  * %sccs.include.redist.c%
650995Sbostic  */
750995Sbostic 
850995Sbostic #if defined(LIBC_SCCS) && !defined(lint)
9*57447Sbostic static char sccsid[] = "@(#)rec_search.c	5.6 (Berkeley) 01/10/93";
1050995Sbostic #endif /* LIBC_SCCS and not lint */
1150995Sbostic 
1250995Sbostic #include <sys/types.h>
1356759Sbostic 
1456759Sbostic #include <db.h>
1550995Sbostic #include <errno.h>
1650995Sbostic #include <stdio.h>
1756759Sbostic 
1851092Sbostic #include "recno.h"
1950995Sbostic 
2050995Sbostic /*
2150995Sbostic  * __REC_SEARCH -- Search a btree for a key.
2250995Sbostic  *
2350995Sbostic  * Parameters:
2450995Sbostic  *	t:	tree to search
2554284Sbostic  *	recno:	key to find
2651092Sbostic  *	op: 	search operation
2750995Sbostic  *
2850995Sbostic  * Returns:
2950995Sbostic  *	EPG for matching record, if any, or the EPG for the location of the
3050995Sbostic  *	key, if it were inserted into the tree.
3150995Sbostic  *
3250995Sbostic  * Warnings:
3350995Sbostic  *	The EPG returned is in static memory, and will be overwritten by the
3450995Sbostic  *	next search of any kind in any tree.
3550995Sbostic  */
3650995Sbostic EPG *
3751092Sbostic __rec_search(t, recno, op)
3850995Sbostic 	BTREE *t;
3950995Sbostic 	recno_t recno;
4051092Sbostic 	enum SRCHOP op;
4150995Sbostic {
4250995Sbostic 	static EPG e;
4350995Sbostic 	register index_t index;
4450995Sbostic 	register PAGE *h;
4551092Sbostic 	EPGNO *parent;
4650995Sbostic 	RINTERNAL *r;
4750995Sbostic 	pgno_t pg;
4850995Sbostic 	index_t top;
4950995Sbostic 	recno_t total;
5051092Sbostic 	int serrno;
5150995Sbostic 
52*57447Sbostic 	BT_CLR(t);
5350995Sbostic 	for (pg = P_ROOT, total = 0;;) {
5450995Sbostic 		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
5551092Sbostic 			goto err;
5650995Sbostic 		if (h->flags & P_RLEAF) {
5750995Sbostic 			e.page = h;
5850995Sbostic 			e.index = recno - total;
5950995Sbostic 			return (&e);
6050995Sbostic 		}
6150995Sbostic 		for (index = 0, top = NEXTINDEX(h);;) {
6250995Sbostic 			r = GETRINTERNAL(h, index);
6356042Sbostic 			if (++index == top || total + r->nrecs > recno)
6450995Sbostic 				break;
6550995Sbostic 			total += r->nrecs;
6650995Sbostic 		}
6750995Sbostic 
6854284Sbostic 		if (__bt_push(t, pg, index - 1) == RET_ERROR)
6950995Sbostic 			return (NULL);
7051092Sbostic 
7151092Sbostic 		pg = r->pgno;
7251092Sbostic 		switch (op) {
7351092Sbostic 		case SDELETE:
7456042Sbostic 			--GETRINTERNAL(h, (index - 1))->nrecs;
7551092Sbostic 			mpool_put(t->bt_mp, h, MPOOL_DIRTY);
7651092Sbostic 			break;
7751092Sbostic 		case SINSERT:
7856042Sbostic 			++GETRINTERNAL(h, (index - 1))->nrecs;
7951092Sbostic 			mpool_put(t->bt_mp, h, MPOOL_DIRTY);
8051092Sbostic 			break;
8151092Sbostic 		case SEARCH:
8251092Sbostic 			mpool_put(t->bt_mp, h, 0);
8351092Sbostic 			break;
8451092Sbostic 		}
8550995Sbostic 
8650995Sbostic 	}
8751092Sbostic 	/* Try and recover the tree. */
8851092Sbostic err:	serrno = errno;
8951092Sbostic 	if (op != SEARCH)
9051092Sbostic 		while  ((parent = BT_POP(t)) != NULL) {
9151092Sbostic 			if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
9251092Sbostic 				break;
9351092Sbostic 			if (op == SINSERT)
9451092Sbostic 				--GETRINTERNAL(h, parent->index)->nrecs;
9551092Sbostic 			else
9651092Sbostic 				++GETRINTERNAL(h, parent->index)->nrecs;
9751092Sbostic                         mpool_put(t->bt_mp, h, MPOOL_DIRTY);
9851092Sbostic                 }
9951092Sbostic 	errno = serrno;
10051092Sbostic 	return (NULL);
10150995Sbostic }
102