150995Sbostic /*-
261207Sbostic * Copyright (c) 1990, 1993
361207Sbostic * The Regents of the University of California. All rights reserved.
450995Sbostic *
550995Sbostic * %sccs.include.redist.c%
650995Sbostic */
750995Sbostic
850995Sbostic #if defined(LIBC_SCCS) && !defined(lint)
9*66195Sbostic static char sccsid[] = "@(#)rec_search.c 8.3 (Berkeley) 02/21/94";
1050995Sbostic #endif /* LIBC_SCCS and not lint */
1150995Sbostic
1250995Sbostic #include <sys/types.h>
1356759Sbostic
1450995Sbostic #include <errno.h>
1550995Sbostic #include <stdio.h>
1656759Sbostic
1757933Sbostic #include <db.h>
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 *
3264485Sbostic * Returns:
3364485Sbostic * The EPG for matching record, if any, or the EPG for the location
3464485Sbostic * of the key, if it were inserted into the tree, is entered into
3564485Sbostic * the bt_cur field of the tree. A pointer to the field is returned.
3650995Sbostic */
3750995Sbostic EPG *
__rec_search(t,recno,op)3851092Sbostic __rec_search(t, recno, op)
3950995Sbostic BTREE *t;
4050995Sbostic recno_t recno;
4151092Sbostic enum SRCHOP op;
4250995Sbostic {
4357988Sbostic register indx_t index;
4450995Sbostic register PAGE *h;
4551092Sbostic EPGNO *parent;
4650995Sbostic RINTERNAL *r;
4750995Sbostic pgno_t pg;
4857988Sbostic indx_t top;
4950995Sbostic recno_t total;
50*66195Sbostic int sverrno;
5150995Sbostic
5257447Sbostic 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) {
5764485Sbostic t->bt_cur.page = h;
5864485Sbostic t->bt_cur.index = recno - total;
5964485Sbostic return (&t->bt_cur);
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. */
88*66195Sbostic err: sverrno = 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 }
99*66195Sbostic errno = sverrno;
10051092Sbostic return (NULL);
10150995Sbostic }
102