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