]> git.saurik.com Git - apple/libc.git/blame - db/btree/bt_delete.c
Libc-320.1.3.tar.gz
[apple/libc.git] / db / btree / bt_delete.c
CommitLineData
e9ce8d39 1/*
9385eb3d 2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
e9ce8d39
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
734aad71
A
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
e9ce8d39
A
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
734aad71
A
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.
e9ce8d39
A
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
9385eb3d
A
23/*-
24 * Copyright (c) 1990, 1993, 1994
e9ce8d39
A
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
9385eb3d
A
59#if defined(LIBC_SCCS) && !defined(lint)
60static char sccsid[] = "@(#)bt_delete.c 8.13 (Berkeley) 7/28/94";
61#endif /* LIBC_SCCS and not lint */
62#include <sys/cdefs.h>
e9ce8d39
A
63
64#include <sys/types.h>
65
66#include <errno.h>
67#include <stdio.h>
68#include <string.h>
69
70#include <db.h>
71#include "btree.h"
72
9385eb3d
A
73static int __bt_bdelete(BTREE *, const DBT *);
74static int __bt_curdel(BTREE *, const DBT *, PAGE *, u_int);
75static int __bt_pdelete(BTREE *, PAGE *);
76static int __bt_relink(BTREE *, PAGE *);
77static int __bt_stkacq(BTREE *, PAGE **, CURSOR *);
e9ce8d39
A
78
79/*
9385eb3d
A
80 * __bt_delete
81 * Delete the item(s) referenced by a key.
e9ce8d39 82 *
9385eb3d 83 * Return RET_SPECIAL if the key is not found.
e9ce8d39
A
84 */
85int
86__bt_delete(dbp, key, flags)
87 const DB *dbp;
88 const DBT *key;
89 u_int flags;
90{
91 BTREE *t;
9385eb3d
A
92 CURSOR *c;
93 PAGE *h;
e9ce8d39
A
94 int status;
95
96 t = dbp->internal;
97
98 /* Toss any page pinned across calls. */
99 if (t->bt_pinned != NULL) {
100 mpool_put(t->bt_mp, t->bt_pinned, 0);
101 t->bt_pinned = NULL;
102 }
103
9385eb3d
A
104 /* Check for change to a read-only tree. */
105 if (F_ISSET(t, B_RDONLY)) {
e9ce8d39
A
106 errno = EPERM;
107 return (RET_ERROR);
108 }
109
9385eb3d 110 switch (flags) {
e9ce8d39 111 case 0:
9385eb3d 112 status = __bt_bdelete(t, key);
e9ce8d39
A
113 break;
114 case R_CURSOR:
115 /*
9385eb3d
A
116 * If flags is R_CURSOR, delete the cursor. Must already
117 * have started a scan and not have already deleted it.
e9ce8d39 118 */
9385eb3d
A
119 c = &t->bt_cursor;
120 if (F_ISSET(c, CURS_INIT)) {
121 if (F_ISSET(c, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE))
122 return (RET_SPECIAL);
123 if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL)
124 return (RET_ERROR);
125
126 /*
127 * If the page is about to be emptied, we'll need to
128 * delete it, which means we have to acquire a stack.
129 */
130 if (NEXTINDEX(h) == 1)
131 if (__bt_stkacq(t, &h, &t->bt_cursor))
132 return (RET_ERROR);
133
134 status = __bt_dleaf(t, NULL, h, c->pg.index);
135
136 if (NEXTINDEX(h) == 0 && status == RET_SUCCESS) {
137 if (__bt_pdelete(t, h))
138 return (RET_ERROR);
139 } else
140 mpool_put(t->bt_mp,
141 h, status == RET_SUCCESS ? MPOOL_DIRTY : 0);
142 break;
143 }
144 /* FALLTHROUGH */
e9ce8d39 145 default:
9385eb3d 146 errno = EINVAL;
e9ce8d39
A
147 return (RET_ERROR);
148 }
149 if (status == RET_SUCCESS)
9385eb3d 150 F_SET(t, B_MODIFIED);
e9ce8d39
A
151 return (status);
152}
153
154/*
9385eb3d
A
155 * __bt_stkacq --
156 * Acquire a stack so we can delete a cursor entry.
e9ce8d39
A
157 *
158 * Parameters:
9385eb3d
A
159 * t: tree
160 * hp: pointer to current, pinned PAGE pointer
161 * c: pointer to the cursor
162 *
163 * Returns:
164 * 0 on success, 1 on failure
165 */
166static int
167__bt_stkacq(t, hp, c)
168 BTREE *t;
169 PAGE **hp;
170 CURSOR *c;
171{
172 BINTERNAL *bi;
173 EPG *e;
174 EPGNO *parent;
175 PAGE *h;
176 indx_t index;
177 pgno_t pgno;
178 recno_t nextpg, prevpg;
179 int exact, level;
180
181 /*
182 * Find the first occurrence of the key in the tree. Toss the
183 * currently locked page so we don't hit an already-locked page.
184 */
185 h = *hp;
186 mpool_put(t->bt_mp, h, 0);
187 if ((e = __bt_search(t, &c->key, &exact)) == NULL)
188 return (1);
189 h = e->page;
190
191 /* See if we got it in one shot. */
192 if (h->pgno == c->pg.pgno)
193 goto ret;
194
195 /*
196 * Move right, looking for the page. At each move we have to move
197 * up the stack until we don't have to move to the next page. If
198 * we have to change pages at an internal level, we have to fix the
199 * stack back up.
200 */
201 while (h->pgno != c->pg.pgno) {
202 if ((nextpg = h->nextpg) == P_INVALID)
203 break;
204 mpool_put(t->bt_mp, h, 0);
205
206 /* Move up the stack. */
207 for (level = 0; (parent = BT_POP(t)) != NULL; ++level) {
208 /* Get the parent page. */
209 if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
210 return (1);
211
212 /* Move to the next index. */
213 if (parent->index != NEXTINDEX(h) - 1) {
214 index = parent->index + 1;
215 BT_PUSH(t, h->pgno, index);
216 break;
217 }
218 mpool_put(t->bt_mp, h, 0);
219 }
220
221 /* Restore the stack. */
222 while (level--) {
223 /* Push the next level down onto the stack. */
224 bi = GETBINTERNAL(h, index);
225 pgno = bi->pgno;
226 BT_PUSH(t, pgno, 0);
227
228 /* Lose the currently pinned page. */
229 mpool_put(t->bt_mp, h, 0);
230
231 /* Get the next level down. */
232 if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
233 return (1);
234 index = 0;
235 }
236 mpool_put(t->bt_mp, h, 0);
237 if ((h = mpool_get(t->bt_mp, nextpg, 0)) == NULL)
238 return (1);
239 }
240
241 if (h->pgno == c->pg.pgno)
242 goto ret;
243
244 /* Reacquire the original stack. */
245 mpool_put(t->bt_mp, h, 0);
246 if ((e = __bt_search(t, &c->key, &exact)) == NULL)
247 return (1);
248 h = e->page;
249
250 /*
251 * Move left, looking for the page. At each move we have to move
252 * up the stack until we don't have to change pages to move to the
253 * next page. If we have to change pages at an internal level, we
254 * have to fix the stack back up.
255 */
256 while (h->pgno != c->pg.pgno) {
257 if ((prevpg = h->prevpg) == P_INVALID)
258 break;
259 mpool_put(t->bt_mp, h, 0);
260
261 /* Move up the stack. */
262 for (level = 0; (parent = BT_POP(t)) != NULL; ++level) {
263 /* Get the parent page. */
264 if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
265 return (1);
266
267 /* Move to the next index. */
268 if (parent->index != 0) {
269 index = parent->index - 1;
270 BT_PUSH(t, h->pgno, index);
271 break;
272 }
273 mpool_put(t->bt_mp, h, 0);
274 }
275
276 /* Restore the stack. */
277 while (level--) {
278 /* Push the next level down onto the stack. */
279 bi = GETBINTERNAL(h, index);
280 pgno = bi->pgno;
281
282 /* Lose the currently pinned page. */
283 mpool_put(t->bt_mp, h, 0);
284
285 /* Get the next level down. */
286 if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
287 return (1);
288
289 index = NEXTINDEX(h) - 1;
290 BT_PUSH(t, pgno, index);
291 }
292 mpool_put(t->bt_mp, h, 0);
293 if ((h = mpool_get(t->bt_mp, prevpg, 0)) == NULL)
294 return (1);
295 }
296
297
298ret: mpool_put(t->bt_mp, h, 0);
299 return ((*hp = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL);
300}
301
302/*
303 * __bt_bdelete --
304 * Delete all key/data pairs matching the specified key.
305 *
306 * Parameters:
307 * t: tree
e9ce8d39
A
308 * key: key to delete
309 *
310 * Returns:
311 * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
312 */
313static int
9385eb3d 314__bt_bdelete(t, key)
e9ce8d39
A
315 BTREE *t;
316 const DBT *key;
317{
9385eb3d 318 EPG *e;
e9ce8d39 319 PAGE *h;
9385eb3d
A
320 int deleted, exact, redo;
321
322 deleted = 0;
e9ce8d39
A
323
324 /* Find any matching record; __bt_search pins the page. */
9385eb3d
A
325loop: if ((e = __bt_search(t, key, &exact)) == NULL)
326 return (deleted ? RET_SUCCESS : RET_ERROR);
e9ce8d39
A
327 if (!exact) {
328 mpool_put(t->bt_mp, e->page, 0);
9385eb3d 329 return (deleted ? RET_SUCCESS : RET_SPECIAL);
e9ce8d39
A
330 }
331
332 /*
9385eb3d
A
333 * Delete forward, then delete backward, from the found key. If
334 * there are duplicates and we reach either side of the page, do
335 * the key search again, so that we get them all.
e9ce8d39 336 */
9385eb3d
A
337 redo = 0;
338 h = e->page;
339 do {
340 if (__bt_dleaf(t, key, h, e->index)) {
341 mpool_put(t->bt_mp, h, 0);
342 return (RET_ERROR);
343 }
344 if (F_ISSET(t, B_NODUPS)) {
345 if (NEXTINDEX(h) == 0) {
346 if (__bt_pdelete(t, h))
e9ce8d39 347 return (RET_ERROR);
9385eb3d
A
348 } else
349 mpool_put(t->bt_mp, h, MPOOL_DIRTY);
350 return (RET_SUCCESS);
e9ce8d39 351 }
9385eb3d
A
352 deleted = 1;
353 } while (e->index < NEXTINDEX(h) && __bt_cmp(t, key, e) == 0);
354
355 /* Check for right-hand edge of the page. */
356 if (e->index == NEXTINDEX(h))
357 redo = 1;
e9ce8d39 358
9385eb3d
A
359 /* Delete from the key to the beginning of the page. */
360 while (e->index-- > 0) {
e9ce8d39
A
361 if (__bt_cmp(t, key, e) != 0)
362 break;
9385eb3d
A
363 if (__bt_dleaf(t, key, h, e->index) == RET_ERROR) {
364 mpool_put(t->bt_mp, h, 0);
365 return (RET_ERROR);
366 }
367 if (e->index == 0)
368 redo = 1;
e9ce8d39
A
369 }
370
9385eb3d
A
371 /* Check for an empty page. */
372 if (NEXTINDEX(h) == 0) {
373 if (__bt_pdelete(t, h))
374 return (RET_ERROR);
375 goto loop;
376 }
377
378 /* Put the page. */
379 mpool_put(t->bt_mp, h, MPOOL_DIRTY);
380
381 if (redo)
382 goto loop;
383 return (RET_SUCCESS);
384}
385
386/*
387 * __bt_pdelete --
388 * Delete a single page from the tree.
389 *
390 * Parameters:
391 * t: tree
392 * h: leaf page
393 *
394 * Returns:
395 * RET_SUCCESS, RET_ERROR.
396 *
397 * Side-effects:
398 * mpool_put's the page
399 */
400static int
401__bt_pdelete(t, h)
402 BTREE *t;
403 PAGE *h;
404{
405 BINTERNAL *bi;
406 PAGE *pg;
407 EPGNO *parent;
408 indx_t cnt, index, *ip, offset;
409 u_int32_t nksize;
410 char *from;
e9ce8d39
A
411
412 /*
9385eb3d
A
413 * Walk the parent page stack -- a LIFO stack of the pages that were
414 * traversed when we searched for the page where the delete occurred.
415 * Each stack entry is a page number and a page index offset. The
416 * offset is for the page traversed on the search. We've just deleted
417 * a page, so we have to delete the key from the parent page.
418 *
419 * If the delete from the parent page makes it empty, this process may
420 * continue all the way up the tree. We stop if we reach the root page
421 * (which is never deleted, it's just not worth the effort) or if the
422 * delete does not empty the page.
e9ce8d39 423 */
9385eb3d
A
424 while ((parent = BT_POP(t)) != NULL) {
425 /* Get the parent page. */
426 if ((pg = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
427 return (RET_ERROR);
428
429 index = parent->index;
430 bi = GETBINTERNAL(pg, index);
431
432 /* Free any overflow pages. */
433 if (bi->flags & P_BIGKEY &&
434 __ovfl_delete(t, bi->bytes) == RET_ERROR) {
435 mpool_put(t->bt_mp, pg, 0);
436 return (RET_ERROR);
437 }
438
439 /*
440 * Free the parent if it has only the one key and it's not the
441 * root page. If it's the rootpage, turn it back into an empty
442 * leaf page.
443 */
444 if (NEXTINDEX(pg) == 1)
445 if (pg->pgno == P_ROOT) {
446 pg->lower = BTDATAOFF;
447 pg->upper = t->bt_psize;
448 pg->flags = P_BLEAF;
e9ce8d39 449 } else {
9385eb3d 450 if (__bt_relink(t, pg) || __bt_free(t, pg))
e9ce8d39 451 return (RET_ERROR);
9385eb3d 452 continue;
e9ce8d39 453 }
9385eb3d
A
454 else {
455 /* Pack remaining key items at the end of the page. */
456 nksize = NBINTERNAL(bi->ksize);
457 from = (char *)pg + pg->upper;
458 memmove(from + nksize, from, (char *)bi - from);
459 pg->upper += nksize;
460
461 /* Adjust indices' offsets, shift the indices down. */
462 offset = pg->linp[index];
463 for (cnt = index, ip = &pg->linp[0]; cnt--; ++ip)
464 if (ip[0] < offset)
465 ip[0] += nksize;
466 for (cnt = NEXTINDEX(pg) - index; --cnt; ++ip)
467 ip[0] = ip[1] < offset ? ip[1] + nksize : ip[1];
468 pg->lower -= sizeof(indx_t);
e9ce8d39
A
469 }
470
9385eb3d
A
471 mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
472 break;
e9ce8d39
A
473 }
474
9385eb3d
A
475 /* Free the leaf page, as long as it wasn't the root. */
476 if (h->pgno == P_ROOT) {
477 mpool_put(t->bt_mp, h, MPOOL_DIRTY);
478 return (RET_SUCCESS);
479 }
480 return (__bt_relink(t, h) || __bt_free(t, h));
e9ce8d39
A
481}
482
483/*
9385eb3d
A
484 * __bt_dleaf --
485 * Delete a single record from a leaf page.
e9ce8d39
A
486 *
487 * Parameters:
488 * t: tree
9385eb3d
A
489 * key: referenced key
490 * h: page
491 * index: index on page to delete
e9ce8d39
A
492 *
493 * Returns:
494 * RET_SUCCESS, RET_ERROR.
495 */
496int
9385eb3d 497__bt_dleaf(t, key, h, index)
e9ce8d39 498 BTREE *t;
9385eb3d 499 const DBT *key;
e9ce8d39 500 PAGE *h;
9385eb3d 501 u_int index;
e9ce8d39 502{
9385eb3d
A
503 BLEAF *bl;
504 indx_t cnt, *ip, offset;
505 u_int32_t nbytes;
e9ce8d39 506 void *to;
9385eb3d 507 char *from;
e9ce8d39 508
9385eb3d
A
509 /* If this record is referenced by the cursor, delete the cursor. */
510 if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
511 !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
512 t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index == index &&
513 __bt_curdel(t, key, h, index))
514 return (RET_ERROR);
515
516 /* If the entry uses overflow pages, make them available for reuse. */
e9ce8d39
A
517 to = bl = GETBLEAF(h, index);
518 if (bl->flags & P_BIGKEY && __ovfl_delete(t, bl->bytes) == RET_ERROR)
519 return (RET_ERROR);
520 if (bl->flags & P_BIGDATA &&
521 __ovfl_delete(t, bl->bytes + bl->ksize) == RET_ERROR)
522 return (RET_ERROR);
e9ce8d39 523
9385eb3d
A
524 /* Pack the remaining key/data items at the end of the page. */
525 nbytes = NBLEAF(bl);
e9ce8d39
A
526 from = (char *)h + h->upper;
527 memmove(from + nbytes, from, (char *)to - from);
528 h->upper += nbytes;
529
9385eb3d 530 /* Adjust the indices' offsets, shift the indices down. */
e9ce8d39
A
531 offset = h->linp[index];
532 for (cnt = index, ip = &h->linp[0]; cnt--; ++ip)
533 if (ip[0] < offset)
534 ip[0] += nbytes;
535 for (cnt = NEXTINDEX(h) - index; --cnt; ++ip)
536 ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
537 h->lower -= sizeof(indx_t);
9385eb3d
A
538
539 /* If the cursor is on this page, adjust it as necessary. */
540 if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
541 !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
542 t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index > index)
543 --t->bt_cursor.pg.index;
544
e9ce8d39
A
545 return (RET_SUCCESS);
546}
9385eb3d
A
547
548/*
549 * __bt_curdel --
550 * Delete the cursor.
551 *
552 * Parameters:
553 * t: tree
554 * key: referenced key (or NULL)
555 * h: page
556 * index: index on page to delete
557 *
558 * Returns:
559 * RET_SUCCESS, RET_ERROR.
560 */
561static int
562__bt_curdel(t, key, h, index)
563 BTREE *t;
564 const DBT *key;
565 PAGE *h;
566 u_int index;
567{
568 CURSOR *c;
569 EPG e;
570 PAGE *pg;
571 int curcopy, status;
572
573 /*
574 * If there are duplicates, move forward or backward to one.
575 * Otherwise, copy the key into the cursor area.
576 */
577 c = &t->bt_cursor;
578 F_CLR(c, CURS_AFTER | CURS_BEFORE | CURS_ACQUIRE);
579
580 curcopy = 0;
581 if (!F_ISSET(t, B_NODUPS)) {
582 /*
583 * We're going to have to do comparisons. If we weren't
584 * provided a copy of the key, i.e. the user is deleting
585 * the current cursor position, get one.
586 */
587 if (key == NULL) {
588 e.page = h;
589 e.index = index;
590 if ((status = __bt_ret(t, &e,
591 &c->key, &c->key, NULL, NULL, 1)) != RET_SUCCESS)
592 return (status);
593 curcopy = 1;
594 key = &c->key;
595 }
596 /* Check previous key, if not at the beginning of the page. */
597 if (index > 0) {
598 e.page = h;
599 e.index = index - 1;
600 if (__bt_cmp(t, key, &e) == 0) {
601 F_SET(c, CURS_BEFORE);
602 goto dup2;
603 }
604 }
605 /* Check next key, if not at the end of the page. */
606 if (index < NEXTINDEX(h) - 1) {
607 e.page = h;
608 e.index = index + 1;
609 if (__bt_cmp(t, key, &e) == 0) {
610 F_SET(c, CURS_AFTER);
611 goto dup2;
612 }
613 }
614 /* Check previous key if at the beginning of the page. */
615 if (index == 0 && h->prevpg != P_INVALID) {
616 if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
617 return (RET_ERROR);
618 e.page = pg;
619 e.index = NEXTINDEX(pg) - 1;
620 if (__bt_cmp(t, key, &e) == 0) {
621 F_SET(c, CURS_BEFORE);
622 goto dup1;
623 }
624 mpool_put(t->bt_mp, pg, 0);
625 }
626 /* Check next key if at the end of the page. */
627 if (index == NEXTINDEX(h) - 1 && h->nextpg != P_INVALID) {
628 if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
629 return (RET_ERROR);
630 e.page = pg;
631 e.index = 0;
632 if (__bt_cmp(t, key, &e) == 0) {
633 F_SET(c, CURS_AFTER);
634dup1: mpool_put(t->bt_mp, pg, 0);
635dup2: c->pg.pgno = e.page->pgno;
636 c->pg.index = e.index;
637 return (RET_SUCCESS);
638 }
639 mpool_put(t->bt_mp, pg, 0);
640 }
641 }
642 e.page = h;
643 e.index = index;
644 if (curcopy || (status =
645 __bt_ret(t, &e, &c->key, &c->key, NULL, NULL, 1)) == RET_SUCCESS) {
646 F_SET(c, CURS_ACQUIRE);
647 return (RET_SUCCESS);
648 }
649 return (status);
650}
651
652/*
653 * __bt_relink --
654 * Link around a deleted page.
655 *
656 * Parameters:
657 * t: tree
658 * h: page to be deleted
659 */
660static int
661__bt_relink(t, h)
662 BTREE *t;
663 PAGE *h;
664{
665 PAGE *pg;
666
667 if (h->nextpg != P_INVALID) {
668 if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
669 return (RET_ERROR);
670 pg->prevpg = h->prevpg;
671 mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
672 }
673 if (h->prevpg != P_INVALID) {
674 if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
675 return (RET_ERROR);
676 pg->nextpg = h->nextpg;
677 mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
678 }
679 return (0);
680}