/*-1* SPDX-License-Identifier: BSD-3-Clause2*3* Copyright (c) 1990, 1993, 19944* The Regents of the University of California. All rights reserved.5*6* This code is derived from software contributed to Berkeley by7* Mike Olson.8*9* Redistribution and use in source and binary forms, with or without10* modification, are permitted provided that the following conditions11* are met:12* 1. Redistributions of source code must retain the above copyright13* notice, this list of conditions and the following disclaimer.14* 2. Redistributions in binary form must reproduce the above copyright15* notice, this list of conditions and the following disclaimer in the16* documentation and/or other materials provided with the distribution.17* 3. Neither the name of the University nor the names of its contributors18* may be used to endorse or promote products derived from this software19* without specific prior written permission.20*21* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND22* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE23* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE24* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE25* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL26* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS27* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)28* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT29* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY30* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF31* SUCH DAMAGE.32*/3334#include <sys/types.h>3536#include <stdio.h>3738#include <db.h>39#include "btree.h"4041static int __bt_snext(BTREE *, PAGE *, const DBT *, int *);42static int __bt_sprev(BTREE *, PAGE *, const DBT *, int *);4344/*45* __bt_search --46* Search a btree for a key.47*48* Parameters:49* t: tree to search50* key: key to find51* exactp: pointer to exact match flag52*53* Returns:54* The EPG for matching record, if any, or the EPG for the location55* of the key, if it were inserted into the tree, is entered into56* the bt_cur field of the tree. A pointer to the field is returned.57*/58EPG *59__bt_search(BTREE *t, const DBT *key, int *exactp)60{61PAGE *h;62indx_t base, idx, lim;63pgno_t pg;64int cmp;6566BT_CLR(t);67for (pg = P_ROOT;;) {68if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)69return (NULL);7071/* Do a binary search on the current page. */72t->bt_cur.page = h;73for (base = 0, lim = NEXTINDEX(h); lim; lim >>= 1) {74t->bt_cur.index = idx = base + (lim >> 1);75if ((cmp = __bt_cmp(t, key, &t->bt_cur)) == 0) {76if (h->flags & P_BLEAF) {77*exactp = 1;78return (&t->bt_cur);79}80goto next;81}82if (cmp > 0) {83base = idx + 1;84--lim;85}86}8788/*89* If it's a leaf page, we're almost done. If no duplicates90* are allowed, or we have an exact match, we're done. Else,91* it's possible that there were matching keys on this page,92* which later deleted, and we're on a page with no matches93* while there are matches on other pages. If at the start or94* end of a page, check the adjacent page.95*/96if (h->flags & P_BLEAF) {97if (!F_ISSET(t, B_NODUPS)) {98if (base == 0 &&99h->prevpg != P_INVALID &&100__bt_sprev(t, h, key, exactp))101return (&t->bt_cur);102if (base == NEXTINDEX(h) &&103h->nextpg != P_INVALID &&104__bt_snext(t, h, key, exactp))105return (&t->bt_cur);106}107*exactp = 0;108t->bt_cur.index = base;109return (&t->bt_cur);110}111112/*113* No match found. Base is the smallest index greater than114* key and may be zero or a last + 1 index. If it's non-zero,115* decrement by one, and record the internal page which should116* be a parent page for the key. If a split later occurs, the117* inserted page will be to the right of the saved page.118*/119idx = base ? base - 1 : base;120121next: BT_PUSH(t, h->pgno, idx);122pg = GETBINTERNAL(h, idx)->pgno;123mpool_put(t->bt_mp, h, 0);124}125}126127/*128* __bt_snext --129* Check for an exact match after the key.130*131* Parameters:132* t: tree133* h: current page134* key: key135* exactp: pointer to exact match flag136*137* Returns:138* If an exact match found.139*/140static int141__bt_snext(BTREE *t, PAGE *h, const DBT *key, int *exactp)142{143EPG e;144145/*146* Get the next page. The key is either an exact147* match, or not as good as the one we already have.148*/149if ((e.page = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)150return (0);151e.index = 0;152if (__bt_cmp(t, key, &e) == 0) {153mpool_put(t->bt_mp, h, 0);154t->bt_cur = e;155*exactp = 1;156return (1);157}158mpool_put(t->bt_mp, e.page, 0);159return (0);160}161162/*163* __bt_sprev --164* Check for an exact match before the key.165*166* Parameters:167* t: tree168* h: current page169* key: key170* exactp: pointer to exact match flag171*172* Returns:173* If an exact match found.174*/175static int176__bt_sprev(BTREE *t, PAGE *h, const DBT *key, int *exactp)177{178EPG e;179180/*181* Get the previous page. The key is either an exact182* match, or not as good as the one we already have.183*/184if ((e.page = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)185return (0);186e.index = NEXTINDEX(e.page) - 1;187if (__bt_cmp(t, key, &e) == 0) {188mpool_put(t->bt_mp, h, 0);189t->bt_cur = e;190*exactp = 1;191return (1);192}193mpool_put(t->bt_mp, e.page, 0);194return (0);195}196197198