]> git.saurik.com Git - apple/libc.git/blob - db/btree/bt_search.c
Libc-320.1.3.tar.gz
[apple/libc.git] / db / btree / bt_search.c
1 /*
2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /*-
24 * Copyright (c) 1990, 1993, 1994
25 * The Regents of the University of California. All rights reserved.
26 *
27 * This code is derived from software contributed to Berkeley by
28 * Mike Olson.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the University of
41 * California, Berkeley and its contributors.
42 * 4. Neither the name of the University nor the names of its contributors
43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE.
57 */
58
59 #if defined(LIBC_SCCS) && !defined(lint)
60 static char sccsid[] = "@(#)bt_search.c 8.8 (Berkeley) 7/31/94";
61 #endif /* LIBC_SCCS and not lint */
62 #include <sys/cdefs.h>
63
64 #include <sys/types.h>
65
66 #include <stdio.h>
67
68 #include <db.h>
69 #include "btree.h"
70
71 static int __bt_snext(BTREE *, PAGE *, const DBT *, int *);
72 static int __bt_sprev(BTREE *, PAGE *, const DBT *, int *);
73
74 /*
75 * __bt_search --
76 * Search a btree for a key.
77 *
78 * Parameters:
79 * t: tree to search
80 * key: key to find
81 * exactp: pointer to exact match flag
82 *
83 * Returns:
84 * The EPG for matching record, if any, or the EPG for the location
85 * of the key, if it were inserted into the tree, is entered into
86 * the bt_cur field of the tree. A pointer to the field is returned.
87 */
88 EPG *
89 __bt_search(t, key, exactp)
90 BTREE *t;
91 const DBT *key;
92 int *exactp;
93 {
94 PAGE *h;
95 indx_t base, index, lim;
96 pgno_t pg;
97 int cmp;
98
99 BT_CLR(t);
100 for (pg = P_ROOT;;) {
101 if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
102 return (NULL);
103
104 /* Do a binary search on the current page. */
105 t->bt_cur.page = h;
106 for (base = 0, lim = NEXTINDEX(h); lim; lim >>= 1) {
107 t->bt_cur.index = index = base + (lim >> 1);
108 if ((cmp = __bt_cmp(t, key, &t->bt_cur)) == 0) {
109 if (h->flags & P_BLEAF) {
110 *exactp = 1;
111 return (&t->bt_cur);
112 }
113 goto next;
114 }
115 if (cmp > 0) {
116 base = index + 1;
117 --lim;
118 }
119 }
120
121 /*
122 * If it's a leaf page, we're almost done. If no duplicates
123 * are allowed, or we have an exact match, we're done. Else,
124 * it's possible that there were matching keys on this page,
125 * which later deleted, and we're on a page with no matches
126 * while there are matches on other pages. If at the start or
127 * end of a page, check the adjacent page.
128 */
129 if (h->flags & P_BLEAF) {
130 if (!F_ISSET(t, B_NODUPS)) {
131 if (base == 0 &&
132 h->prevpg != P_INVALID &&
133 __bt_sprev(t, h, key, exactp))
134 return (&t->bt_cur);
135 if (base == NEXTINDEX(h) &&
136 h->nextpg != P_INVALID &&
137 __bt_snext(t, h, key, exactp))
138 return (&t->bt_cur);
139 }
140 *exactp = 0;
141 t->bt_cur.index = base;
142 return (&t->bt_cur);
143 }
144
145 /*
146 * No match found. Base is the smallest index greater than
147 * key and may be zero or a last + 1 index. If it's non-zero,
148 * decrement by one, and record the internal page which should
149 * be a parent page for the key. If a split later occurs, the
150 * inserted page will be to the right of the saved page.
151 */
152 index = base ? base - 1 : base;
153
154 next: BT_PUSH(t, h->pgno, index);
155 pg = GETBINTERNAL(h, index)->pgno;
156 mpool_put(t->bt_mp, h, 0);
157 }
158 }
159
160 /*
161 * __bt_snext --
162 * Check for an exact match after the key.
163 *
164 * Parameters:
165 * t: tree
166 * h: current page
167 * key: key
168 * exactp: pointer to exact match flag
169 *
170 * Returns:
171 * If an exact match found.
172 */
173 static int
174 __bt_snext(t, h, key, exactp)
175 BTREE *t;
176 PAGE *h;
177 const DBT *key;
178 int *exactp;
179 {
180 EPG e;
181
182 /*
183 * Get the next page. The key is either an exact
184 * match, or not as good as the one we already have.
185 */
186 if ((e.page = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
187 return (0);
188 e.index = 0;
189 if (__bt_cmp(t, key, &e) == 0) {
190 mpool_put(t->bt_mp, h, 0);
191 t->bt_cur = e;
192 *exactp = 1;
193 return (1);
194 }
195 mpool_put(t->bt_mp, e.page, 0);
196 return (0);
197 }
198
199 /*
200 * __bt_sprev --
201 * Check for an exact match before the key.
202 *
203 * Parameters:
204 * t: tree
205 * h: current page
206 * key: key
207 * exactp: pointer to exact match flag
208 *
209 * Returns:
210 * If an exact match found.
211 */
212 static int
213 __bt_sprev(t, h, key, exactp)
214 BTREE *t;
215 PAGE *h;
216 const DBT *key;
217 int *exactp;
218 {
219 EPG e;
220
221 /*
222 * Get the previous page. The key is either an exact
223 * match, or not as good as the one we already have.
224 */
225 if ((e.page = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
226 return (0);
227 e.index = NEXTINDEX(e.page) - 1;
228 if (__bt_cmp(t, key, &e) == 0) {
229 mpool_put(t->bt_mp, h, 0);
230 t->bt_cur = e;
231 *exactp = 1;
232 return (1);
233 }
234 mpool_put(t->bt_mp, e.page, 0);
235 return (0);
236 }