xref: /csrg-svn/lib/libc/db/recno/rec_search.c (revision 56759)
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*56759Sbostic static char sccsid[] = "@(#)rec_search.c	5.5 (Berkeley) 11/13/92";
1050995Sbostic #endif /* LIBC_SCCS and not lint */
1150995Sbostic 
1250995Sbostic #include <sys/types.h>
13*56759Sbostic 
14*56759Sbostic #include <db.h>
1550995Sbostic #include <errno.h>
1650995Sbostic #include <stdio.h>
17*56759Sbostic 
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 
5250995Sbostic 	for (pg = P_ROOT, total = 0;;) {
5350995Sbostic 		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
5451092Sbostic 			goto err;
5550995Sbostic 		if (h->flags & P_RLEAF) {
5650995Sbostic 			e.page = h;
5750995Sbostic 			e.index = recno - total;
5850995Sbostic 			return (&e);
5950995Sbostic 		}
6050995Sbostic 		for (index = 0, top = NEXTINDEX(h);;) {
6150995Sbostic 			r = GETRINTERNAL(h, index);
6256042Sbostic 			if (++index == top || total + r->nrecs > recno)
6350995Sbostic 				break;
6450995Sbostic 			total += r->nrecs;
6550995Sbostic 		}
6650995Sbostic 
6754284Sbostic 		if (__bt_push(t, pg, index - 1) == RET_ERROR)
6850995Sbostic 			return (NULL);
6951092Sbostic 
7051092Sbostic 		pg = r->pgno;
7151092Sbostic 		switch (op) {
7251092Sbostic 		case SDELETE:
7356042Sbostic 			--GETRINTERNAL(h, (index - 1))->nrecs;
7451092Sbostic 			mpool_put(t->bt_mp, h, MPOOL_DIRTY);
7551092Sbostic 			break;
7651092Sbostic 		case SINSERT:
7756042Sbostic 			++GETRINTERNAL(h, (index - 1))->nrecs;
7851092Sbostic 			mpool_put(t->bt_mp, h, MPOOL_DIRTY);
7951092Sbostic 			break;
8051092Sbostic 		case SEARCH:
8151092Sbostic 			mpool_put(t->bt_mp, h, 0);
8251092Sbostic 			break;
8351092Sbostic 		}
8450995Sbostic 
8550995Sbostic 	}
8651092Sbostic 	/* Try and recover the tree. */
8751092Sbostic err:	serrno = errno;
8851092Sbostic 	if (op != SEARCH)
8951092Sbostic 		while  ((parent = BT_POP(t)) != NULL) {
9051092Sbostic 			if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
9151092Sbostic 				break;
9251092Sbostic 			if (op == SINSERT)
9351092Sbostic 				--GETRINTERNAL(h, parent->index)->nrecs;
9451092Sbostic 			else
9551092Sbostic 				++GETRINTERNAL(h, parent->index)->nrecs;
9651092Sbostic                         mpool_put(t->bt_mp, h, MPOOL_DIRTY);
9751092Sbostic                 }
9851092Sbostic 	errno = serrno;
9951092Sbostic 	return (NULL);
10050995Sbostic }
101