bt_delete.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. /*-
  2. * Copyright (c) 1990, 1993, 1994
  3. * The Regents of the University of California. All rights reserved.
  4. *
  5. * This code is derived from software contributed to Berkeley by
  6. * Mike Olson.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. All advertising materials mentioning features or use of this software
  17. * must display the following acknowledgement:
  18. * This product includes software developed by the University of
  19. * California, Berkeley and its contributors.
  20. * 4. Neither the name of the University nor the names of its contributors
  21. * may be used to endorse or promote products derived from this software
  22. * without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34. * SUCH DAMAGE.
  35. */
  36. #if defined(LIBC_SCCS) && !defined(lint)
  37. static char sccsid[] = "@(#)bt_delete.c 8.13 (Berkeley) 7/28/94";
  38. #endif /* LIBC_SCCS and not lint */
  39. #include <sys/types.h>
  40. #include <errno.h>
  41. #include <stdio.h>
  42. #include <string.h>
  43. #include "../include/db.h"
  44. #include "btree.h"
  45. static int __bt_bdelete __P((BTREE *, const DBT *));
  46. static int __bt_curdel __P((BTREE *, const DBT *, PAGE *, u_int));
  47. static int __bt_pdelete __P((BTREE *, PAGE *));
  48. static int __bt_relink __P((BTREE *, PAGE *));
  49. static int __bt_stkacq __P((BTREE *, PAGE **, CURSOR *));
  50. /*
  51. * __bt_delete
  52. * Delete the item(s) referenced by a key.
  53. *
  54. * Return RET_SPECIAL if the key is not found.
  55. */
  56. int
  57. __bt_delete(dbp, key, flags)
  58. const DB *dbp;
  59. const DBT *key;
  60. u_int flags;
  61. {
  62. BTREE *t;
  63. CURSOR *c;
  64. PAGE *h;
  65. int status;
  66. t = dbp->internal;
  67. /* Toss any page pinned across calls. */
  68. if (t->bt_pinned != NULL) {
  69. mpool_put(t->bt_mp, t->bt_pinned, 0);
  70. t->bt_pinned = NULL;
  71. }
  72. /* Check for change to a read-only tree. */
  73. if (F_ISSET(t, B_RDONLY)) {
  74. errno = EPERM;
  75. return (RET_ERROR);
  76. }
  77. switch (flags) {
  78. case 0:
  79. status = __bt_bdelete(t, key);
  80. break;
  81. case R_CURSOR:
  82. /*
  83. * If flags is R_CURSOR, delete the cursor. Must already
  84. * have started a scan and not have already deleted it.
  85. */
  86. c = &t->bt_cursor;
  87. if (F_ISSET(c, CURS_INIT)) {
  88. if (F_ISSET(c, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE))
  89. return (RET_SPECIAL);
  90. if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL)
  91. return (RET_ERROR);
  92. /*
  93. * If the page is about to be emptied, we'll need to
  94. * delete it, which means we have to acquire a stack.
  95. */
  96. if (NEXTINDEX(h) == 1)
  97. if (__bt_stkacq(t, &h, &t->bt_cursor))
  98. return (RET_ERROR);
  99. status = __bt_dleaf(t, NULL, h, c->pg.index);
  100. if (NEXTINDEX(h) == 0 && status == RET_SUCCESS) {
  101. if (__bt_pdelete(t, h))
  102. return (RET_ERROR);
  103. } else
  104. mpool_put(t->bt_mp,
  105. h, status == RET_SUCCESS ? MPOOL_DIRTY : 0);
  106. break;
  107. }
  108. /* FALLTHROUGH */
  109. default:
  110. errno = EINVAL;
  111. return (RET_ERROR);
  112. }
  113. if (status == RET_SUCCESS)
  114. F_SET(t, B_MODIFIED);
  115. return (status);
  116. }
  117. /*
  118. * __bt_stkacq --
  119. * Acquire a stack so we can delete a cursor entry.
  120. *
  121. * Parameters:
  122. * t: tree
  123. * hp: pointer to current, pinned PAGE pointer
  124. * c: pointer to the cursor
  125. *
  126. * Returns:
  127. * 0 on success, 1 on failure
  128. */
  129. static int
  130. __bt_stkacq(t, hp, c)
  131. BTREE *t;
  132. PAGE **hp;
  133. CURSOR *c;
  134. {
  135. BINTERNAL *bi;
  136. EPG *e;
  137. EPGNO *parent;
  138. PAGE *h;
  139. indx_t idx = 0;
  140. pgno_t pgno;
  141. recno_t nextpg, prevpg;
  142. int exact, level;
  143. /*
  144. * Find the first occurrence of the key in the tree. Toss the
  145. * currently locked page so we don't hit an already-locked page.
  146. */
  147. h = *hp;
  148. mpool_put(t->bt_mp, h, 0);
  149. if ((e = __bt_search(t, &c->key, &exact)) == NULL)
  150. return (1);
  151. h = e->page;
  152. /* See if we got it in one shot. */
  153. if (h->pgno == c->pg.pgno)
  154. goto ret;
  155. /*
  156. * Move right, looking for the page. At each move we have to move
  157. * up the stack until we don't have to move to the next page. If
  158. * we have to change pages at an internal level, we have to fix the
  159. * stack back up.
  160. */
  161. while (h->pgno != c->pg.pgno) {
  162. if ((nextpg = h->nextpg) == P_INVALID)
  163. break;
  164. mpool_put(t->bt_mp, h, 0);
  165. /* Move up the stack. */
  166. for (level = 0; (parent = BT_POP(t)) != NULL; ++level) {
  167. /* Get the parent page. */
  168. if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
  169. return (1);
  170. /* Move to the next index. */
  171. if (parent->index != NEXTINDEX(h) - 1) {
  172. idx = parent->index + 1;
  173. BT_PUSH(t, h->pgno, idx);
  174. break;
  175. }
  176. mpool_put(t->bt_mp, h, 0);
  177. }
  178. /* Restore the stack. */
  179. while (level--) {
  180. /* Push the next level down onto the stack. */
  181. bi = GETBINTERNAL(h, idx);
  182. pgno = bi->pgno;
  183. BT_PUSH(t, pgno, 0);
  184. /* Lose the currently pinned page. */
  185. mpool_put(t->bt_mp, h, 0);
  186. /* Get the next level down. */
  187. if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
  188. return (1);
  189. idx = 0;
  190. }
  191. mpool_put(t->bt_mp, h, 0);
  192. if ((h = mpool_get(t->bt_mp, nextpg, 0)) == NULL)
  193. return (1);
  194. }
  195. if (h->pgno == c->pg.pgno)
  196. goto ret;
  197. /* Reacquire the original stack. */
  198. mpool_put(t->bt_mp, h, 0);
  199. if ((e = __bt_search(t, &c->key, &exact)) == NULL)
  200. return (1);
  201. h = e->page;
  202. /*
  203. * Move left, looking for the page. At each move we have to move
  204. * up the stack until we don't have to change pages to move to the
  205. * next page. If we have to change pages at an internal level, we
  206. * have to fix the stack back up.
  207. */
  208. while (h->pgno != c->pg.pgno) {
  209. if ((prevpg = h->prevpg) == P_INVALID)
  210. break;
  211. mpool_put(t->bt_mp, h, 0);
  212. /* Move up the stack. */
  213. for (level = 0; (parent = BT_POP(t)) != NULL; ++level) {
  214. /* Get the parent page. */
  215. if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
  216. return (1);
  217. /* Move to the next index. */
  218. if (parent->index != 0) {
  219. idx = parent->index - 1;
  220. BT_PUSH(t, h->pgno, idx);
  221. break;
  222. }
  223. mpool_put(t->bt_mp, h, 0);
  224. }
  225. /* Restore the stack. */
  226. while (level--) {
  227. /* Push the next level down onto the stack. */
  228. bi = GETBINTERNAL(h, idx);
  229. pgno = bi->pgno;
  230. /* Lose the currently pinned page. */
  231. mpool_put(t->bt_mp, h, 0);
  232. /* Get the next level down. */
  233. if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
  234. return (1);
  235. idx = NEXTINDEX(h) - 1;
  236. BT_PUSH(t, pgno, idx);
  237. }
  238. mpool_put(t->bt_mp, h, 0);
  239. if ((h = mpool_get(t->bt_mp, prevpg, 0)) == NULL)
  240. return (1);
  241. }
  242. ret: mpool_put(t->bt_mp, h, 0);
  243. return ((*hp = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL);
  244. }
  245. /*
  246. * __bt_bdelete --
  247. * Delete all key/data pairs matching the specified key.
  248. *
  249. * Parameters:
  250. * t: tree
  251. * key: key to delete
  252. *
  253. * Returns:
  254. * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
  255. */
  256. static int
  257. __bt_bdelete(t, key)
  258. BTREE *t;
  259. const DBT *key;
  260. {
  261. EPG *e;
  262. PAGE *h;
  263. int deleted, exact, redo;
  264. deleted = 0;
  265. /* Find any matching record; __bt_search pins the page. */
  266. loop: if ((e = __bt_search(t, key, &exact)) == NULL)
  267. return (deleted ? RET_SUCCESS : RET_ERROR);
  268. if (!exact) {
  269. mpool_put(t->bt_mp, e->page, 0);
  270. return (deleted ? RET_SUCCESS : RET_SPECIAL);
  271. }
  272. /*
  273. * Delete forward, then delete backward, from the found key. If
  274. * there are duplicates and we reach either side of the page, do
  275. * the key search again, so that we get them all.
  276. */
  277. redo = 0;
  278. h = e->page;
  279. do {
  280. if (__bt_dleaf(t, key, h, e->index)) {
  281. mpool_put(t->bt_mp, h, 0);
  282. return (RET_ERROR);
  283. }
  284. if (F_ISSET(t, B_NODUPS)) {
  285. if (NEXTINDEX(h) == 0) {
  286. if (__bt_pdelete(t, h))
  287. return (RET_ERROR);
  288. } else
  289. mpool_put(t->bt_mp, h, MPOOL_DIRTY);
  290. return (RET_SUCCESS);
  291. }
  292. deleted = 1;
  293. } while (e->index < NEXTINDEX(h) && __bt_cmp(t, key, e) == 0);
  294. /* Check for right-hand edge of the page. */
  295. if (e->index == NEXTINDEX(h))
  296. redo = 1;
  297. /* Delete from the key to the beginning of the page. */
  298. while (e->index-- > 0) {
  299. if (__bt_cmp(t, key, e) != 0)
  300. break;
  301. if (__bt_dleaf(t, key, h, e->index) == RET_ERROR) {
  302. mpool_put(t->bt_mp, h, 0);
  303. return (RET_ERROR);
  304. }
  305. if (e->index == 0)
  306. redo = 1;
  307. }
  308. /* Check for an empty page. */
  309. if (NEXTINDEX(h) == 0) {
  310. if (__bt_pdelete(t, h))
  311. return (RET_ERROR);
  312. goto loop;
  313. }
  314. /* Put the page. */
  315. mpool_put(t->bt_mp, h, MPOOL_DIRTY);
  316. if (redo)
  317. goto loop;
  318. return (RET_SUCCESS);
  319. }
  320. /*
  321. * __bt_pdelete --
  322. * Delete a single page from the tree.
  323. *
  324. * Parameters:
  325. * t: tree
  326. * h: leaf page
  327. *
  328. * Returns:
  329. * RET_SUCCESS, RET_ERROR.
  330. *
  331. * Side-effects:
  332. * mpool_put's the page
  333. */
  334. static int
  335. __bt_pdelete(t, h)
  336. BTREE *t;
  337. PAGE *h;
  338. {
  339. BINTERNAL *bi;
  340. PAGE *pg;
  341. EPGNO *parent;
  342. indx_t cnt, idx, *ip, offset;
  343. u_int32_t nksize;
  344. char *from;
  345. /*
  346. * Walk the parent page stack -- a LIFO stack of the pages that were
  347. * traversed when we searched for the page where the delete occurred.
  348. * Each stack entry is a page number and a page index offset. The
  349. * offset is for the page traversed on the search. We've just deleted
  350. * a page, so we have to delete the key from the parent page.
  351. *
  352. * If the delete from the parent page makes it empty, this process may
  353. * continue all the way up the tree. We stop if we reach the root page
  354. * (which is never deleted, it's just not worth the effort) or if the
  355. * delete does not empty the page.
  356. */
  357. while ((parent = BT_POP(t)) != NULL) {
  358. /* Get the parent page. */
  359. if ((pg = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
  360. return (RET_ERROR);
  361. idx = parent->index;
  362. bi = GETBINTERNAL(pg, idx);
  363. /* Free any overflow pages. */
  364. if (bi->flags & P_BIGKEY &&
  365. __ovfl_delete(t, bi->bytes) == RET_ERROR) {
  366. mpool_put(t->bt_mp, pg, 0);
  367. return (RET_ERROR);
  368. }
  369. /*
  370. * Free the parent if it has only the one key and it's not the
  371. * root page. If it's the rootpage, turn it back into an empty
  372. * leaf page.
  373. */
  374. if (NEXTINDEX(pg) == 1) {
  375. if (pg->pgno == P_ROOT) {
  376. pg->lower = BTDATAOFF;
  377. pg->upper = t->bt_psize;
  378. pg->flags = P_BLEAF;
  379. } else {
  380. if (__bt_relink(t, pg) || __bt_free(t, pg))
  381. return (RET_ERROR);
  382. continue;
  383. }
  384. } else {
  385. /* Pack remaining key items at the end of the page. */
  386. nksize = NBINTERNAL(bi->ksize);
  387. from = (char *)pg + pg->upper;
  388. memmove(from + nksize, from, (char *)bi - from);
  389. pg->upper += nksize;
  390. /* Adjust indices' offsets, shift the indices down. */
  391. offset = pg->linp[idx];
  392. for (cnt = idx, ip = &pg->linp[0]; cnt--; ++ip)
  393. if (ip[0] < offset)
  394. ip[0] += nksize;
  395. for (cnt = NEXTINDEX(pg) - idx; --cnt; ++ip)
  396. ip[0] = ip[1] < offset ? ip[1] + nksize : ip[1];
  397. pg->lower -= sizeof(indx_t);
  398. }
  399. mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
  400. break;
  401. }
  402. /* Free the leaf page, as long as it wasn't the root. */
  403. if (h->pgno == P_ROOT) {
  404. mpool_put(t->bt_mp, h, MPOOL_DIRTY);
  405. return (RET_SUCCESS);
  406. }
  407. return (__bt_relink(t, h) || __bt_free(t, h));
  408. }
  409. /*
  410. * __bt_dleaf --
  411. * Delete a single record from a leaf page.
  412. *
  413. * Parameters:
  414. * t: tree
  415. * key: referenced key
  416. * h: page
  417. * index: index on page to delete
  418. *
  419. * Returns:
  420. * RET_SUCCESS, RET_ERROR.
  421. */
  422. int
  423. __bt_dleaf(t, key, h, idx)
  424. BTREE *t;
  425. const DBT *key;
  426. PAGE *h;
  427. u_int idx;
  428. {
  429. BLEAF *bl;
  430. indx_t cnt, *ip, offset;
  431. u_int32_t nbytes;
  432. void *to;
  433. char *from;
  434. /* If this record is referenced by the cursor, delete the cursor. */
  435. if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
  436. !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
  437. t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index == idx &&
  438. __bt_curdel(t, key, h, idx))
  439. return (RET_ERROR);
  440. /* If the entry uses overflow pages, make them available for reuse. */
  441. to = bl = GETBLEAF(h, idx);
  442. if (bl->flags & P_BIGKEY && __ovfl_delete(t, bl->bytes) == RET_ERROR)
  443. return (RET_ERROR);
  444. if (bl->flags & P_BIGDATA &&
  445. __ovfl_delete(t, bl->bytes + bl->ksize) == RET_ERROR)
  446. return (RET_ERROR);
  447. /* Pack the remaining key/data items at the end of the page. */
  448. nbytes = NBLEAF(bl);
  449. from = (char *)h + h->upper;
  450. memmove(from + nbytes, from, (char *)to - from);
  451. h->upper += nbytes;
  452. /* Adjust the indices' offsets, shift the indices down. */
  453. offset = h->linp[idx];
  454. for (cnt = idx, ip = &h->linp[0]; cnt--; ++ip)
  455. if (ip[0] < offset)
  456. ip[0] += nbytes;
  457. for (cnt = NEXTINDEX(h) - idx; --cnt; ++ip)
  458. ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
  459. h->lower -= sizeof(indx_t);
  460. /* If the cursor is on this page, adjust it as necessary. */
  461. if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
  462. !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
  463. t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index > idx)
  464. --t->bt_cursor.pg.index;
  465. return (RET_SUCCESS);
  466. }
  467. /*
  468. * __bt_curdel --
  469. * Delete the cursor.
  470. *
  471. * Parameters:
  472. * t: tree
  473. * key: referenced key (or NULL)
  474. * h: page
  475. * index: index on page to delete
  476. *
  477. * Returns:
  478. * RET_SUCCESS, RET_ERROR.
  479. */
  480. static int
  481. __bt_curdel(t, key, h, idx)
  482. BTREE *t;
  483. const DBT *key;
  484. PAGE *h;
  485. u_int idx;
  486. {
  487. CURSOR *c;
  488. EPG e;
  489. PAGE *pg;
  490. int curcopy, status;
  491. /*
  492. * If there are duplicates, move forward or backward to one.
  493. * Otherwise, copy the key into the cursor area.
  494. */
  495. c = &t->bt_cursor;
  496. F_CLR(c, CURS_AFTER | CURS_BEFORE | CURS_ACQUIRE);
  497. curcopy = 0;
  498. if (!F_ISSET(t, B_NODUPS)) {
  499. /*
  500. * We're going to have to do comparisons. If we weren't
  501. * provided a copy of the key, i.e. the user is deleting
  502. * the current cursor position, get one.
  503. */
  504. if (key == NULL) {
  505. e.page = h;
  506. e.index = idx;
  507. if ((status = __bt_ret(t, &e,
  508. &c->key, &c->key, NULL, NULL, 1)) != RET_SUCCESS)
  509. return (status);
  510. curcopy = 1;
  511. key = &c->key;
  512. }
  513. /* Check previous key, if not at the beginning of the page. */
  514. if (idx > 0) {
  515. e.page = h;
  516. e.index = idx - 1;
  517. if (__bt_cmp(t, key, &e) == 0) {
  518. F_SET(c, CURS_BEFORE);
  519. goto dup2;
  520. }
  521. }
  522. /* Check next key, if not at the end of the page. */
  523. if (idx < NEXTINDEX(h) - 1) {
  524. e.page = h;
  525. e.index = idx + 1;
  526. if (__bt_cmp(t, key, &e) == 0) {
  527. F_SET(c, CURS_AFTER);
  528. goto dup2;
  529. }
  530. }
  531. /* Check previous key if at the beginning of the page. */
  532. if (idx == 0 && h->prevpg != P_INVALID) {
  533. if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
  534. return (RET_ERROR);
  535. e.page = pg;
  536. e.index = NEXTINDEX(pg) - 1;
  537. if (__bt_cmp(t, key, &e) == 0) {
  538. F_SET(c, CURS_BEFORE);
  539. goto dup1;
  540. }
  541. mpool_put(t->bt_mp, pg, 0);
  542. }
  543. /* Check next key if at the end of the page. */
  544. if (idx == NEXTINDEX(h) - 1 && h->nextpg != P_INVALID) {
  545. if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
  546. return (RET_ERROR);
  547. e.page = pg;
  548. e.index = 0;
  549. if (__bt_cmp(t, key, &e) == 0) {
  550. F_SET(c, CURS_AFTER);
  551. dup1: mpool_put(t->bt_mp, pg, 0);
  552. dup2: c->pg.pgno = e.page->pgno;
  553. c->pg.index = e.index;
  554. return (RET_SUCCESS);
  555. }
  556. mpool_put(t->bt_mp, pg, 0);
  557. }
  558. }
  559. e.page = h;
  560. e.index = idx;
  561. if (curcopy || (status =
  562. __bt_ret(t, &e, &c->key, &c->key, NULL, NULL, 1)) == RET_SUCCESS) {
  563. F_SET(c, CURS_ACQUIRE);
  564. return (RET_SUCCESS);
  565. }
  566. return (status);
  567. }
  568. /*
  569. * __bt_relink --
  570. * Link around a deleted page.
  571. *
  572. * Parameters:
  573. * t: tree
  574. * h: page to be deleted
  575. */
  576. static int
  577. __bt_relink(t, h)
  578. BTREE *t;
  579. PAGE *h;
  580. {
  581. PAGE *pg;
  582. if (h->nextpg != P_INVALID) {
  583. if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
  584. return (RET_ERROR);
  585. pg->prevpg = h->prevpg;
  586. mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
  587. }
  588. if (h->prevpg != P_INVALID) {
  589. if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
  590. return (RET_ERROR);
  591. pg->nextpg = h->nextpg;
  592. mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
  593. }
  594. return (0);
  595. }