]>
git.saurik.com Git - apple/libc.git/blob - db/btree/bt_put.c
41d43c5fc7bfa2666591eefa628f7a167bca7e36
2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1990, 1993, 1994
27 * The Regents of the University of California. All rights reserved.
29 * This code is derived from software contributed to Berkeley by
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 #if defined(LIBC_SCCS) && !defined(lint)
62 static char sccsid
[] = "@(#)bt_put.c 8.8 (Berkeley) 7/26/94";
63 #endif /* LIBC_SCCS and not lint */
64 #include <sys/cdefs.h>
66 #include <sys/types.h>
76 static EPG
*bt_fast(BTREE
*, const DBT
*, const DBT
*, int *);
79 * __BT_PUT -- Add a btree item to the tree.
82 * dbp: pointer to access method
88 * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is already in the
89 * tree and R_NOOVERWRITE specified.
92 __bt_put(dbp
, key
, data
, flags
)
102 indx_t index
, nxtindex
;
105 int dflags
, exact
, status
;
106 char *dest
, db
[NOVFLSIZE
], kb
[NOVFLSIZE
];
110 /* Toss any page pinned across calls. */
111 if (t
->bt_pinned
!= NULL
) {
112 mpool_put(t
->bt_mp
, t
->bt_pinned
, 0);
116 /* Check for change to a read-only tree. */
117 if (F_ISSET(t
, B_RDONLY
)) {
128 * If flags is R_CURSOR, put the cursor. Must already
129 * have started a scan and not have already deleted it.
131 if (F_ISSET(&t
->bt_cursor
, CURS_INIT
) &&
132 !F_ISSET(&t
->bt_cursor
,
133 CURS_ACQUIRE
| CURS_AFTER
| CURS_BEFORE
))
142 * If the key/data pair won't fit on a page, store it on overflow
143 * pages. Only put the key on the overflow page if the pair are
144 * still too big after moving the data to an overflow page.
147 * If the insert fails later on, the overflow pages aren't recovered.
150 if (key
->size
+ data
->size
> t
->bt_ovflsize
) {
151 if (key
->size
> t
->bt_ovflsize
) {
152 storekey
: if (__ovfl_put(t
, key
, &pg
) == RET_ERROR
)
155 tkey
.size
= NOVFLSIZE
;
156 memmove(kb
, &pg
, sizeof(pgno_t
));
157 memmove(kb
+ sizeof(pgno_t
),
158 &key
->size
, sizeof(u_int32_t
));
162 if (key
->size
+ data
->size
> t
->bt_ovflsize
) {
163 if (__ovfl_put(t
, data
, &pg
) == RET_ERROR
)
166 tdata
.size
= NOVFLSIZE
;
167 memmove(db
, &pg
, sizeof(pgno_t
));
168 memmove(db
+ sizeof(pgno_t
),
169 &data
->size
, sizeof(u_int32_t
));
173 if (key
->size
+ data
->size
> t
->bt_ovflsize
)
177 /* Replace the cursor. */
178 if (flags
== R_CURSOR
) {
179 if ((h
= mpool_get(t
->bt_mp
, t
->bt_cursor
.pg
.pgno
, 0)) == NULL
)
181 index
= t
->bt_cursor
.pg
.index
;
186 * Find the key to delete, or, the location at which to insert.
187 * Bt_fast and __bt_search both pin the returned page.
189 if (t
->bt_order
== NOT
|| (e
= bt_fast(t
, key
, data
, &exact
)) == NULL
)
190 if ((e
= __bt_search(t
, key
, &exact
)) == NULL
)
196 * Add the key/data pair to the tree. If an identical key is already
197 * in the tree, and R_NOOVERWRITE is set, an error is returned. If
198 * R_NOOVERWRITE is not set, the key is either added (if duplicates are
199 * permitted) or an error is returned.
205 mpool_put(t
->bt_mp
, h
, 0);
206 return (RET_SPECIAL
);
208 if (!exact
|| !F_ISSET(t
, B_NODUPS
))
212 * Note, the delete may empty the page, so we need to put a
213 * new entry into the page immediately.
215 delete: if (__bt_dleaf(t
, key
, h
, index
) == RET_ERROR
) {
216 mpool_put(t
->bt_mp
, h
, 0);
223 * If not enough room, or the user has put a ceiling on the number of
224 * keys permitted in the page, split the page. The split code will
225 * insert the key and data and unpin the current page. If inserting
226 * into the offset array, shift the pointers up.
228 nbytes
= NBLEAFDBT(key
->size
, data
->size
);
229 if (h
->upper
- h
->lower
< nbytes
+ sizeof(indx_t
)) {
230 if ((status
= __bt_split(t
, h
, key
,
231 data
, dflags
, nbytes
, index
)) != RET_SUCCESS
)
236 if (index
< (nxtindex
= NEXTINDEX(h
)))
237 memmove(h
->linp
+ index
+ 1, h
->linp
+ index
,
238 (nxtindex
- index
) * sizeof(indx_t
));
239 h
->lower
+= sizeof(indx_t
);
241 h
->linp
[index
] = h
->upper
-= nbytes
;
242 dest
= (char *)h
+ h
->upper
;
243 WR_BLEAF(dest
, key
, data
, dflags
);
245 /* If the cursor is on this page, adjust it as necessary. */
246 if (F_ISSET(&t
->bt_cursor
, CURS_INIT
) &&
247 !F_ISSET(&t
->bt_cursor
, CURS_ACQUIRE
) &&
248 t
->bt_cursor
.pg
.pgno
== h
->pgno
&& t
->bt_cursor
.pg
.index
>= index
)
249 ++t
->bt_cursor
.pg
.index
;
251 if (t
->bt_order
== NOT
) {
252 if (h
->nextpg
== P_INVALID
) {
253 if (index
== NEXTINDEX(h
) - 1) {
254 t
->bt_order
= FORWARD
;
255 t
->bt_last
.index
= index
;
256 t
->bt_last
.pgno
= h
->pgno
;
258 } else if (h
->prevpg
== P_INVALID
) {
261 t
->bt_last
.index
= 0;
262 t
->bt_last
.pgno
= h
->pgno
;
267 mpool_put(t
->bt_mp
, h
, MPOOL_DIRTY
);
270 if (flags
== R_SETCURSOR
)
271 __bt_setcur(t
, e
->page
->pgno
, e
->index
);
273 F_SET(t
, B_MODIFIED
);
274 return (RET_SUCCESS
);
278 u_long bt_cache_hit
, bt_cache_miss
;
282 * BT_FAST -- Do a quick check for sorted data.
289 * EPG for new record or NULL if not found.
292 bt_fast(t
, key
, data
, exactp
)
294 const DBT
*key
, *data
;
301 if ((h
= mpool_get(t
->bt_mp
, t
->bt_last
.pgno
, 0)) == NULL
) {
306 t
->bt_cur
.index
= t
->bt_last
.index
;
309 * If won't fit in this page or have too many keys in this page,
310 * have to search to get split stack.
312 nbytes
= NBLEAFDBT(key
->size
, data
->size
);
313 if (h
->upper
- h
->lower
< nbytes
+ sizeof(indx_t
))
316 if (t
->bt_order
== FORWARD
) {
317 if (t
->bt_cur
.page
->nextpg
!= P_INVALID
)
319 if (t
->bt_cur
.index
!= NEXTINDEX(h
) - 1)
321 if ((cmp
= __bt_cmp(t
, key
, &t
->bt_cur
)) < 0)
323 t
->bt_last
.index
= cmp
? ++t
->bt_cur
.index
: t
->bt_cur
.index
;
325 if (t
->bt_cur
.page
->prevpg
!= P_INVALID
)
327 if (t
->bt_cur
.index
!= 0)
329 if ((cmp
= __bt_cmp(t
, key
, &t
->bt_cur
)) > 0)
331 t
->bt_last
.index
= 0;
344 mpool_put(t
->bt_mp
, h
, 0);