]>
git.saurik.com Git - apple/libc.git/blob - db/btree/bt_get.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1990, 1993
24 * The Regents of the University of California. All rights reserved.
26 * This code is derived from software contributed to Berkeley by
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
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.
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
59 #include <sys/types.h>
69 * __BT_GET -- Get a record from the btree.
72 * dbp: pointer to access method
74 * data: data to return
75 * flag: currently unused
78 * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
81 __bt_get(dbp
, key
, data
, flags
)
93 /* Toss any page pinned across calls. */
94 if (t
->bt_pinned
!= NULL
) {
95 mpool_put(t
->bt_mp
, t
->bt_pinned
, 0);
99 /* Get currently doesn't take any flags. */
105 if ((e
= __bt_search(t
, key
, &exact
)) == NULL
)
108 mpool_put(t
->bt_mp
, e
->page
, 0);
109 return (RET_SPECIAL
);
113 * A special case is if we found the record but it's flagged for
114 * deletion. In this case, we want to find another record with the
115 * same key, if it exists. Rather than look around the tree we call
116 * __bt_first and have it redo the search, as __bt_first will not
117 * return keys marked for deletion. Slow, but should never happen.
119 if (ISSET(t
, B_DELCRSR
) && e
->page
->pgno
== t
->bt_bcursor
.pgno
&&
120 e
->index
== t
->bt_bcursor
.index
) {
121 mpool_put(t
->bt_mp
, e
->page
, 0);
122 if ((e
= __bt_first(t
, key
, &exact
)) == NULL
)
125 return (RET_SPECIAL
);
128 status
= __bt_ret(t
, e
, NULL
, data
);
130 * If the user is doing concurrent access, we copied the
131 * key/data, toss the page.
133 if (ISSET(t
, B_DB_LOCK
))
134 mpool_put(t
->bt_mp
, e
->page
, 0);
136 t
->bt_pinned
= e
->page
;
141 * __BT_FIRST -- Find the first entry.
148 * The first entry in the tree greater than or equal to key.
151 __bt_first(t
, key
, exactp
)
164 * Find any matching record; __bt_search pins the page. Only exact
165 * matches are tricky, otherwise just return the location of the key
166 * if it were to be inserted into the tree.
168 if ((e
= __bt_search(t
, key
, exactp
)) == NULL
)
173 if (ISSET(t
, B_DELCRSR
)) {
174 cpgno
= t
->bt_bcursor
.pgno
;
175 cindex
= t
->bt_bcursor
.index
;
178 cindex
= 0; /* GCC thinks it's uninitialized. */
182 * Walk backwards, skipping empty pages, as long as the entry matches
183 * and there are keys left in the tree. Save a copy of each match in
184 * case we go too far. A special case is that we don't return a match
185 * on records that the cursor references that have already been flagged
192 if (cpgno
!= h
->pgno
|| cindex
!= e
->index
) {
193 if (save
.page
->pgno
!= e
->page
->pgno
) {
194 mpool_put(t
->bt_mp
, save
.page
, 0);
197 save
.index
= e
->index
;
201 * Make a special effort not to unpin the page the last (or
202 * original) match was on, but also make sure it's unpinned
203 * if an error occurs.
205 while (e
->index
== 0) {
206 if (h
->prevpg
== P_INVALID
)
208 if (h
->pgno
!= save
.page
->pgno
)
209 mpool_put(t
->bt_mp
, h
, 0);
210 if ((h
= mpool_get(t
->bt_mp
, h
->prevpg
, 0)) == NULL
) {
211 if (h
->pgno
== save
.page
->pgno
)
212 mpool_put(t
->bt_mp
, save
.page
, 0);
216 e
->index
= NEXTINDEX(h
);
219 } while (__bt_cmp(t
, key
, e
) == 0);
222 * Reach here with the last page that was looked at pinned, which may
223 * or may not be the same as the last (or original) match page. If
224 * it's not useful, release it.
226 done1
: if (h
->pgno
!= save
.page
->pgno
)
227 mpool_put(t
->bt_mp
, h
, 0);
230 * If still haven't found a record, the only possibility left is the
231 * next one. Move forward one slot, skipping empty pages and check.
235 if (++save
.index
== NEXTINDEX(h
)) {
238 mpool_put(t
->bt_mp
, h
, 0);
239 if (pg
== P_INVALID
) {
243 if ((h
= mpool_get(t
->bt_mp
, pg
, 0)) == NULL
)
245 } while ((save
.index
= NEXTINDEX(h
)) == 0);
248 if (__bt_cmp(t
, key
, &save
) != 0) {