158f0484fSRodney W. Grimes /*- 258f0484fSRodney W. Grimes * Copyright (c) 1990, 1993 358f0484fSRodney W. Grimes * The Regents of the University of California. All rights reserved. 458f0484fSRodney W. Grimes * 558f0484fSRodney W. Grimes * This code is derived from software contributed to Berkeley by 658f0484fSRodney W. Grimes * Mike Olson. 758f0484fSRodney W. Grimes * 858f0484fSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 958f0484fSRodney W. Grimes * modification, are permitted provided that the following conditions 1058f0484fSRodney W. Grimes * are met: 1158f0484fSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 1258f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 1358f0484fSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 1458f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 1558f0484fSRodney W. Grimes * documentation and/or other materials provided with the distribution. 1658f0484fSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 1758f0484fSRodney W. Grimes * must display the following acknowledgement: 1858f0484fSRodney W. Grimes * This product includes software developed by the University of 1958f0484fSRodney W. Grimes * California, Berkeley and its contributors. 2058f0484fSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 2158f0484fSRodney W. Grimes * may be used to endorse or promote products derived from this software 2258f0484fSRodney W. Grimes * without specific prior written permission. 2358f0484fSRodney W. Grimes * 2458f0484fSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2558f0484fSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2658f0484fSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2758f0484fSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2858f0484fSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2958f0484fSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3058f0484fSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3158f0484fSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3258f0484fSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3358f0484fSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3458f0484fSRodney W. Grimes * SUCH DAMAGE. 3558f0484fSRodney W. Grimes */ 3658f0484fSRodney W. Grimes 3758f0484fSRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint) 3858f0484fSRodney W. Grimes static char sccsid[] = "@(#)bt_get.c 8.2 (Berkeley) 9/7/93"; 3958f0484fSRodney W. Grimes #endif /* LIBC_SCCS and not lint */ 4058f0484fSRodney W. Grimes 4158f0484fSRodney W. Grimes #include <sys/types.h> 4258f0484fSRodney W. Grimes 4358f0484fSRodney W. Grimes #include <errno.h> 4458f0484fSRodney W. Grimes #include <stddef.h> 4558f0484fSRodney W. Grimes #include <stdio.h> 4658f0484fSRodney W. Grimes 4758f0484fSRodney W. Grimes #include <db.h> 4858f0484fSRodney W. Grimes #include "btree.h" 4958f0484fSRodney W. Grimes 5058f0484fSRodney W. Grimes /* 5158f0484fSRodney W. Grimes * __BT_GET -- Get a record from the btree. 5258f0484fSRodney W. Grimes * 5358f0484fSRodney W. Grimes * Parameters: 5458f0484fSRodney W. Grimes * dbp: pointer to access method 5558f0484fSRodney W. Grimes * key: key to find 5658f0484fSRodney W. Grimes * data: data to return 5758f0484fSRodney W. Grimes * flag: currently unused 5858f0484fSRodney W. Grimes * 5958f0484fSRodney W. Grimes * Returns: 6058f0484fSRodney W. Grimes * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. 6158f0484fSRodney W. Grimes */ 6258f0484fSRodney W. Grimes int 6358f0484fSRodney W. Grimes __bt_get(dbp, key, data, flags) 6458f0484fSRodney W. Grimes const DB *dbp; 6558f0484fSRodney W. Grimes const DBT *key; 6658f0484fSRodney W. Grimes DBT *data; 6758f0484fSRodney W. Grimes u_int flags; 6858f0484fSRodney W. Grimes { 6958f0484fSRodney W. Grimes BTREE *t; 7058f0484fSRodney W. Grimes EPG *e; 7158f0484fSRodney W. Grimes int exact, status; 7258f0484fSRodney W. Grimes 7358f0484fSRodney W. Grimes t = dbp->internal; 7458f0484fSRodney W. Grimes 7558f0484fSRodney W. Grimes /* Toss any page pinned across calls. */ 7658f0484fSRodney W. Grimes if (t->bt_pinned != NULL) { 7758f0484fSRodney W. Grimes mpool_put(t->bt_mp, t->bt_pinned, 0); 7858f0484fSRodney W. Grimes t->bt_pinned = NULL; 7958f0484fSRodney W. Grimes } 8058f0484fSRodney W. Grimes 8158f0484fSRodney W. Grimes /* Get currently doesn't take any flags. */ 8258f0484fSRodney W. Grimes if (flags) { 8358f0484fSRodney W. Grimes errno = EINVAL; 8458f0484fSRodney W. Grimes return (RET_ERROR); 8558f0484fSRodney W. Grimes } 8658f0484fSRodney W. Grimes 8758f0484fSRodney W. Grimes if ((e = __bt_search(t, key, &exact)) == NULL) 8858f0484fSRodney W. Grimes return (RET_ERROR); 8958f0484fSRodney W. Grimes if (!exact) { 9058f0484fSRodney W. Grimes mpool_put(t->bt_mp, e->page, 0); 9158f0484fSRodney W. Grimes return (RET_SPECIAL); 9258f0484fSRodney W. Grimes } 9358f0484fSRodney W. Grimes 9458f0484fSRodney W. Grimes /* 9558f0484fSRodney W. Grimes * A special case is if we found the record but it's flagged for 9658f0484fSRodney W. Grimes * deletion. In this case, we want to find another record with the 9758f0484fSRodney W. Grimes * same key, if it exists. Rather than look around the tree we call 9858f0484fSRodney W. Grimes * __bt_first and have it redo the search, as __bt_first will not 9958f0484fSRodney W. Grimes * return keys marked for deletion. Slow, but should never happen. 10058f0484fSRodney W. Grimes */ 10158f0484fSRodney W. Grimes if (ISSET(t, B_DELCRSR) && e->page->pgno == t->bt_bcursor.pgno && 10258f0484fSRodney W. Grimes e->index == t->bt_bcursor.index) { 10358f0484fSRodney W. Grimes mpool_put(t->bt_mp, e->page, 0); 10458f0484fSRodney W. Grimes if ((e = __bt_first(t, key, &exact)) == NULL) 10558f0484fSRodney W. Grimes return (RET_ERROR); 10658f0484fSRodney W. Grimes if (!exact) 10758f0484fSRodney W. Grimes return (RET_SPECIAL); 10858f0484fSRodney W. Grimes } 10958f0484fSRodney W. Grimes 11058f0484fSRodney W. Grimes status = __bt_ret(t, e, NULL, data); 11158f0484fSRodney W. Grimes /* 11258f0484fSRodney W. Grimes * If the user is doing concurrent access, we copied the 11358f0484fSRodney W. Grimes * key/data, toss the page. 11458f0484fSRodney W. Grimes */ 11558f0484fSRodney W. Grimes if (ISSET(t, B_DB_LOCK)) 11658f0484fSRodney W. Grimes mpool_put(t->bt_mp, e->page, 0); 11758f0484fSRodney W. Grimes else 11858f0484fSRodney W. Grimes t->bt_pinned = e->page; 11958f0484fSRodney W. Grimes return (status); 12058f0484fSRodney W. Grimes } 12158f0484fSRodney W. Grimes 12258f0484fSRodney W. Grimes /* 12358f0484fSRodney W. Grimes * __BT_FIRST -- Find the first entry. 12458f0484fSRodney W. Grimes * 12558f0484fSRodney W. Grimes * Parameters: 12658f0484fSRodney W. Grimes * t: the tree 12758f0484fSRodney W. Grimes * key: the key 12858f0484fSRodney W. Grimes * 12958f0484fSRodney W. Grimes * Returns: 13058f0484fSRodney W. Grimes * The first entry in the tree greater than or equal to key. 13158f0484fSRodney W. Grimes */ 13258f0484fSRodney W. Grimes EPG * 13358f0484fSRodney W. Grimes __bt_first(t, key, exactp) 13458f0484fSRodney W. Grimes BTREE *t; 13558f0484fSRodney W. Grimes const DBT *key; 13658f0484fSRodney W. Grimes int *exactp; 13758f0484fSRodney W. Grimes { 13858f0484fSRodney W. Grimes register PAGE *h; 13958f0484fSRodney W. Grimes register EPG *e; 14058f0484fSRodney W. Grimes EPG save; 14158f0484fSRodney W. Grimes pgno_t cpgno, pg; 14258f0484fSRodney W. Grimes indx_t cindex; 14358f0484fSRodney W. Grimes int found; 14458f0484fSRodney W. Grimes 14558f0484fSRodney W. Grimes /* 14658f0484fSRodney W. Grimes * Find any matching record; __bt_search pins the page. Only exact 14758f0484fSRodney W. Grimes * matches are tricky, otherwise just return the location of the key 14858f0484fSRodney W. Grimes * if it were to be inserted into the tree. 14958f0484fSRodney W. Grimes */ 15058f0484fSRodney W. Grimes if ((e = __bt_search(t, key, exactp)) == NULL) 15158f0484fSRodney W. Grimes return (NULL); 15258f0484fSRodney W. Grimes if (!*exactp) 15358f0484fSRodney W. Grimes return (e); 15458f0484fSRodney W. Grimes 15558f0484fSRodney W. Grimes if (ISSET(t, B_DELCRSR)) { 15658f0484fSRodney W. Grimes cpgno = t->bt_bcursor.pgno; 15758f0484fSRodney W. Grimes cindex = t->bt_bcursor.index; 15858f0484fSRodney W. Grimes } else { 15958f0484fSRodney W. Grimes cpgno = P_INVALID; 16058f0484fSRodney W. Grimes cindex = 0; /* GCC thinks it's uninitialized. */ 16158f0484fSRodney W. Grimes } 16258f0484fSRodney W. Grimes 16358f0484fSRodney W. Grimes /* 16458f0484fSRodney W. Grimes * Walk backwards, skipping empty pages, as long as the entry matches 16558f0484fSRodney W. Grimes * and there are keys left in the tree. Save a copy of each match in 16658f0484fSRodney W. Grimes * case we go too far. A special case is that we don't return a match 16758f0484fSRodney W. Grimes * on records that the cursor references that have already been flagged 16858f0484fSRodney W. Grimes * for deletion. 16958f0484fSRodney W. Grimes */ 17058f0484fSRodney W. Grimes save = *e; 17158f0484fSRodney W. Grimes h = e->page; 17258f0484fSRodney W. Grimes found = 0; 17358f0484fSRodney W. Grimes do { 17458f0484fSRodney W. Grimes if (cpgno != h->pgno || cindex != e->index) { 17558f0484fSRodney W. Grimes if (save.page->pgno != e->page->pgno) { 17658f0484fSRodney W. Grimes mpool_put(t->bt_mp, save.page, 0); 17758f0484fSRodney W. Grimes save = *e; 17858f0484fSRodney W. Grimes } else 17958f0484fSRodney W. Grimes save.index = e->index; 18058f0484fSRodney W. Grimes found = 1; 18158f0484fSRodney W. Grimes } 18258f0484fSRodney W. Grimes /* 18358f0484fSRodney W. Grimes * Make a special effort not to unpin the page the last (or 18458f0484fSRodney W. Grimes * original) match was on, but also make sure it's unpinned 18558f0484fSRodney W. Grimes * if an error occurs. 18658f0484fSRodney W. Grimes */ 18758f0484fSRodney W. Grimes while (e->index == 0) { 18858f0484fSRodney W. Grimes if (h->prevpg == P_INVALID) 18958f0484fSRodney W. Grimes goto done1; 19058f0484fSRodney W. Grimes if (h->pgno != save.page->pgno) 19158f0484fSRodney W. Grimes mpool_put(t->bt_mp, h, 0); 19258f0484fSRodney W. Grimes if ((h = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL) { 19358f0484fSRodney W. Grimes if (h->pgno == save.page->pgno) 19458f0484fSRodney W. Grimes mpool_put(t->bt_mp, save.page, 0); 19558f0484fSRodney W. Grimes return (NULL); 19658f0484fSRodney W. Grimes } 19758f0484fSRodney W. Grimes e->page = h; 19858f0484fSRodney W. Grimes e->index = NEXTINDEX(h); 19958f0484fSRodney W. Grimes } 20058f0484fSRodney W. Grimes --e->index; 20158f0484fSRodney W. Grimes } while (__bt_cmp(t, key, e) == 0); 20258f0484fSRodney W. Grimes 20358f0484fSRodney W. Grimes /* 20458f0484fSRodney W. Grimes * Reach here with the last page that was looked at pinned, which may 20558f0484fSRodney W. Grimes * or may not be the same as the last (or original) match page. If 20658f0484fSRodney W. Grimes * it's not useful, release it. 20758f0484fSRodney W. Grimes */ 20858f0484fSRodney W. Grimes done1: if (h->pgno != save.page->pgno) 20958f0484fSRodney W. Grimes mpool_put(t->bt_mp, h, 0); 21058f0484fSRodney W. Grimes 21158f0484fSRodney W. Grimes /* 21258f0484fSRodney W. Grimes * If still haven't found a record, the only possibility left is the 21358f0484fSRodney W. Grimes * next one. Move forward one slot, skipping empty pages and check. 21458f0484fSRodney W. Grimes */ 21558f0484fSRodney W. Grimes if (!found) { 21658f0484fSRodney W. Grimes h = save.page; 21758f0484fSRodney W. Grimes if (++save.index == NEXTINDEX(h)) { 21858f0484fSRodney W. Grimes do { 21958f0484fSRodney W. Grimes pg = h->nextpg; 22058f0484fSRodney W. Grimes mpool_put(t->bt_mp, h, 0); 22158f0484fSRodney W. Grimes if (pg == P_INVALID) { 22258f0484fSRodney W. Grimes *exactp = 0; 22358f0484fSRodney W. Grimes return (e); 22458f0484fSRodney W. Grimes } 22558f0484fSRodney W. Grimes if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) 22658f0484fSRodney W. Grimes return (NULL); 22758f0484fSRodney W. Grimes } while ((save.index = NEXTINDEX(h)) == 0); 22858f0484fSRodney W. Grimes save.page = h; 22958f0484fSRodney W. Grimes } 23058f0484fSRodney W. Grimes if (__bt_cmp(t, key, &save) != 0) { 23158f0484fSRodney W. Grimes *exactp = 0; 23258f0484fSRodney W. Grimes return (e); 23358f0484fSRodney W. Grimes } 23458f0484fSRodney W. Grimes } 23558f0484fSRodney W. Grimes *e = save; 23658f0484fSRodney W. Grimes *exactp = 1; 23758f0484fSRodney W. Grimes return (e); 23858f0484fSRodney W. Grimes } 239