bt_rec.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:31k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1996, 1997, 1998, 1999, 2000
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: bt_rec.c,v 11.35 2001/01/10 16:24:47 ubell Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <string.h>
  14. #endif
  15. #include "db_int.h"
  16. #include "db_page.h"
  17. #include "hash.h"
  18. #include "btree.h"
  19. #include "log.h"
  20. #define IS_BTREE_PAGE(pagep)
  21. (TYPE(pagep) == P_IBTREE ||
  22.  TYPE(pagep) == P_LBTREE || TYPE(pagep) == P_LDUP)
  23. /*
  24.  * __bam_pg_alloc_recover --
  25.  * Recovery function for pg_alloc.
  26.  *
  27.  * PUBLIC: int __bam_pg_alloc_recover
  28.  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  29.  */
  30. int
  31. __bam_pg_alloc_recover(dbenv, dbtp, lsnp, op, info)
  32. DB_ENV *dbenv;
  33. DBT *dbtp;
  34. DB_LSN *lsnp;
  35. db_recops op;
  36. void *info;
  37. {
  38. __bam_pg_alloc_args *argp;
  39. DB *file_dbp;
  40. DBC *dbc;
  41. DBMETA *meta;
  42. DB_MPOOLFILE *mpf;
  43. PAGE *pagep;
  44. db_pgno_t pgno;
  45. int cmp_n, cmp_p, level, modified, ret;
  46. REC_PRINT(__bam_pg_alloc_print);
  47. REC_INTRO(__bam_pg_alloc_read, 0);
  48. /*
  49.  * Fix up the allocated page.  If we're redoing the operation, we have
  50.  * to get the page (creating it if it doesn't exist), and update its
  51.  * LSN.  If we're undoing the operation, we have to reset the page's
  52.  * LSN and put it on the free list.
  53.  *
  54.  * Fix up the metadata page.  If we're redoing the operation, we have
  55.  * to get the metadata page and update its LSN and its free pointer.
  56.  * If we're undoing the operation and the page was ever created, we put
  57.  * it on the freelist.
  58.  */
  59. pgno = PGNO_BASE_MD;
  60. meta = NULL;
  61. if ((ret = memp_fget(mpf, &pgno, 0, &meta)) != 0) {
  62. /* The metadata page must always exist on redo. */
  63. if (DB_REDO(op)) {
  64. (void)__db_pgerr(file_dbp, pgno);
  65. goto out;
  66. } else
  67. goto done;
  68. }
  69. if ((ret = memp_fget(mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) {
  70. /*
  71.  * We specify creation and check for it later, because this
  72.  * operation was supposed to create the page, and even in
  73.  * the undo case it's going to get linked onto the freelist
  74.  * which we're also fixing up.
  75.  */
  76. (void)__db_pgerr(file_dbp, argp->pgno);
  77. goto err;
  78. }
  79. /* Fix up the allocated page. */
  80. modified = 0;
  81. cmp_n = log_compare(lsnp, &LSN(pagep));
  82. cmp_p = log_compare(&LSN(pagep), &argp->page_lsn);
  83. /*
  84.  * If an inital allocation is aborted and then reallocated
  85.  * during an archival restore the log record will have
  86.  * an LSN for the page but the page will be empty.
  87.  */
  88. if (IS_ZERO_LSN(LSN(pagep)))
  89. cmp_p = 0;
  90. CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->page_lsn);
  91. /*
  92.  * If we we rolled back this allocation previously during an
  93.  * archive restore, the page may have the LSN of the meta page
  94.  * at the point of the roll back.  This will be no more
  95.  * than the LSN of the metadata page at the time of this allocation.
  96.  */
  97. if (DB_REDO(op) &&
  98.     (cmp_p == 0 ||
  99.     (IS_ZERO_LSN(argp->page_lsn) &&
  100.     log_compare(&LSN(pagep), &argp->meta_lsn) <= 0))) {
  101. /* Need to redo update described. */
  102. switch (argp->ptype) {
  103. case P_LBTREE:
  104. case P_LRECNO:
  105. case P_LDUP:
  106. level = LEAFLEVEL;
  107. break;
  108. default:
  109. level = 0;
  110. break;
  111. }
  112. P_INIT(pagep, file_dbp->pgsize,
  113.     argp->pgno, PGNO_INVALID, PGNO_INVALID, level, argp->ptype);
  114. pagep->lsn = *lsnp;
  115. modified = 1;
  116. } else if (cmp_n == 0 && DB_UNDO(op)) {
  117. /*
  118.  * Undo the allocation, reinitialize the page and
  119.  * link its next pointer to the free list.
  120.  */
  121. P_INIT(pagep, file_dbp->pgsize,
  122.     argp->pgno, PGNO_INVALID, argp->next, 0, P_INVALID);
  123. pagep->lsn = argp->page_lsn;
  124. modified = 1;
  125. }
  126. if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) {
  127. goto err;
  128. }
  129. /*
  130.  * If the page was newly created, put it on the limbo list.
  131.  */
  132. if (IS_ZERO_LSN(LSN(pagep)) &&
  133.      IS_ZERO_LSN(argp->page_lsn) && DB_UNDO(op)) {
  134. /* Put the page in limbo.*/
  135. if ((ret = __db_add_limbo(dbenv,
  136.     info, argp->fileid, argp->pgno, 1)) != 0)
  137. goto err;
  138. }
  139. /* Fix up the metadata page. */
  140. modified = 0;
  141. cmp_n = log_compare(lsnp, &LSN(meta));
  142. cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
  143. CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn);
  144. if (cmp_p == 0 && DB_REDO(op)) {
  145. /* Need to redo update described. */
  146. LSN(meta) = *lsnp;
  147. meta->free = argp->next;
  148. modified = 1;
  149. } else if (cmp_n == 0 && DB_UNDO(op)) {
  150. /* Need to undo update described. */
  151. LSN(meta) = argp->meta_lsn;
  152. /*
  153.  * If the page has a zero LSN then its newly created
  154.  * and will go into limbo rather than directly on the
  155.  * free list.
  156.  */
  157. if (!IS_ZERO_LSN(argp->page_lsn))
  158. meta->free = argp->pgno;
  159. modified = 1;
  160. }
  161. if ((ret = memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  162. goto out;
  163. /*
  164.  * This could be the metapage from a subdb which is read from disk
  165.  * to recover its creation.
  166.  */
  167. if (F_ISSET(file_dbp, DB_AM_SUBDB))
  168. switch (argp->type) {
  169. case P_BTREEMETA:
  170. case P_HASHMETA:
  171. case P_QAMMETA:
  172. file_dbp->sync(file_dbp, 0);
  173. break;
  174. }
  175. done: *lsnp = argp->prev_lsn;
  176. ret = 0;
  177. if (0) {
  178. err:
  179. if (meta != NULL)
  180. (void)memp_fput(mpf, meta, 0);
  181. }
  182. out: REC_CLOSE;
  183. }
  184. /*
  185.  * __bam_pg_free_recover --
  186.  * Recovery function for pg_free.
  187.  *
  188.  * PUBLIC: int __bam_pg_free_recover
  189.  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  190.  */
  191. int
  192. __bam_pg_free_recover(dbenv, dbtp, lsnp, op, info)
  193. DB_ENV *dbenv;
  194. DBT *dbtp;
  195. DB_LSN *lsnp;
  196. db_recops op;
  197. void *info;
  198. {
  199. __bam_pg_free_args *argp;
  200. DB *file_dbp;
  201. DBC *dbc;
  202. DBMETA *meta;
  203. DB_LSN copy_lsn;
  204. DB_MPOOLFILE *mpf;
  205. PAGE *pagep;
  206. db_pgno_t pgno;
  207. int cmp_n, cmp_p, modified, ret;
  208. COMPQUIET(info, NULL);
  209. REC_PRINT(__bam_pg_free_print);
  210. REC_INTRO(__bam_pg_free_read, 1);
  211. /*
  212.  * Fix up the freed page.  If we're redoing the operation we get the
  213.  * page and explicitly discard its contents, then update its LSN.  If
  214.  * we're undoing the operation, we get the page and restore its header.
  215.  * Create the page if necessary, we may be freeing an aborted
  216.  * create.
  217.  */
  218. if ((ret = memp_fget(mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
  219. goto out;
  220. modified = 0;
  221. __ua_memcpy(&copy_lsn, &LSN(argp->header.data), sizeof(DB_LSN));
  222. cmp_n = log_compare(lsnp, &LSN(pagep));
  223. cmp_p = log_compare(&LSN(pagep), &copy_lsn);
  224. CHECK_LSN(op, cmp_p, &LSN(pagep), &copy_lsn);
  225. if (DB_REDO(op) &&
  226.     (cmp_p == 0 ||
  227.     (IS_ZERO_LSN(copy_lsn) &&
  228.     log_compare(&LSN(pagep), &argp->meta_lsn) <= 0))) {
  229. /* Need to redo update described. */
  230. P_INIT(pagep, file_dbp->pgsize,
  231.     argp->pgno, PGNO_INVALID, argp->next, 0, P_INVALID);
  232. pagep->lsn = *lsnp;
  233. modified = 1;
  234. } else if (cmp_n == 0 && DB_UNDO(op)) {
  235. /* Need to undo update described. */
  236. memcpy(pagep, argp->header.data, argp->header.size);
  237. modified = 1;
  238. }
  239. if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  240. goto out;
  241. /*
  242.  * Fix up the metadata page.  If we're redoing or undoing the operation
  243.  * we get the page and update its LSN and free pointer.
  244.  */
  245. pgno = PGNO_BASE_MD;
  246. if ((ret = memp_fget(mpf, &pgno, 0, &meta)) != 0) {
  247. /* The metadata page must always exist. */
  248. (void)__db_pgerr(file_dbp, pgno);
  249. goto out;
  250. }
  251. modified = 0;
  252. cmp_n = log_compare(lsnp, &LSN(meta));
  253. cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
  254. CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn);
  255. if (cmp_p == 0 && DB_REDO(op)) {
  256. /* Need to redo the deallocation. */
  257. meta->free = argp->pgno;
  258. LSN(meta) = *lsnp;
  259. modified = 1;
  260. } else if (cmp_n == 0 && DB_UNDO(op)) {
  261. /* Need to undo the deallocation. */
  262. meta->free = argp->next;
  263. LSN(meta) = argp->meta_lsn;
  264. modified = 1;
  265. }
  266. if ((ret = memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  267. goto out;
  268. done: *lsnp = argp->prev_lsn;
  269. ret = 0;
  270. out: REC_CLOSE;
  271. }
  272. /*
  273.  * __bam_split_recover --
  274.  * Recovery function for split.
  275.  *
  276.  * PUBLIC: int __bam_split_recover
  277.  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  278.  */
  279. int
  280. __bam_split_recover(dbenv, dbtp, lsnp, op, info)
  281. DB_ENV *dbenv;
  282. DBT *dbtp;
  283. DB_LSN *lsnp;
  284. db_recops op;
  285. void *info;
  286. {
  287. __bam_split_args *argp;
  288. DB *file_dbp;
  289. DBC *dbc;
  290. DB_MPOOLFILE *mpf;
  291. PAGE *_lp, *lp, *np, *pp, *_rp, *rp, *sp;
  292. db_pgno_t pgno, root_pgno;
  293. u_int32_t ptype;
  294. int cmp, l_update, p_update, r_update, rc, ret, rootsplit, t_ret;
  295. COMPQUIET(info, NULL);
  296. REC_PRINT(__bam_split_print);
  297. mpf = NULL;
  298. _lp = lp = np = pp = _rp = rp = NULL;
  299. sp = NULL;
  300. REC_INTRO(__bam_split_read, 1);
  301. /*
  302.  * There are two kinds of splits that we have to recover from.  The
  303.  * first is a root-page split, where the root page is split from a
  304.  * leaf page into an internal page and two new leaf pages are created.
  305.  * The second is where a page is split into two pages, and a new key
  306.  * is inserted into the parent page.
  307.  *
  308.  * DBTs are not aligned in log records, so we need to copy the page
  309.  * so that we can access fields within it throughout this routine.
  310.  * Although we could hardcode the unaligned copies in this routine,
  311.  * we will be calling into regular btree functions with this page,
  312.  * so it's got to be aligned.  Copying it into allocated memory is
  313.  * the only way to guarantee this.
  314.  */
  315. if ((ret = __os_malloc(dbenv, argp->pg.size, NULL, &sp)) != 0)
  316. goto out;
  317. memcpy(sp, argp->pg.data, argp->pg.size);
  318. pgno = PGNO(sp);
  319. root_pgno = argp->root_pgno;
  320. rootsplit = pgno == root_pgno;
  321. if (memp_fget(mpf, &argp->left, 0, &lp) != 0)
  322. lp = NULL;
  323. if (memp_fget(mpf, &argp->right, 0, &rp) != 0)
  324. rp = NULL;
  325. if (DB_REDO(op)) {
  326. l_update = r_update = p_update = 0;
  327. /*
  328.  * Decide if we need to resplit the page.
  329.  *
  330.  * If this is a root split, then the root has to exist, it's
  331.  * the page we're splitting and it gets modified.  If this is
  332.  * not a root split, then the left page has to exist, for the
  333.  * same reason.
  334.  */
  335. if (rootsplit) {
  336. if ((ret = memp_fget(mpf, &pgno, 0, &pp)) != 0) {
  337. (void)__db_pgerr(file_dbp, pgno);
  338. pp = NULL;
  339. goto out;
  340. }
  341. cmp = log_compare(&LSN(pp), &LSN(argp->pg.data));
  342. CHECK_LSN(op, cmp, &LSN(pp), &LSN(argp->pg.data));
  343. p_update = cmp  == 0;
  344. } else if (lp == NULL) {
  345. (void)__db_pgerr(file_dbp, argp->left);
  346. goto out;
  347. }
  348. if (lp != NULL) {
  349. cmp = log_compare(&LSN(lp), &argp->llsn);
  350. CHECK_LSN(op, cmp, &LSN(lp), &argp->llsn);
  351. if (cmp == 0)
  352. l_update = 1;
  353. } else
  354. l_update = 1;
  355. if (rp != NULL) {
  356. cmp = log_compare(&LSN(rp), &argp->rlsn);
  357. CHECK_LSN(op, cmp, &LSN(rp), &argp->rlsn);
  358. if (cmp == 0)
  359. r_update = 1;
  360. } else
  361. r_update = 1;
  362. if (!p_update && !l_update && !r_update)
  363. goto check_next;
  364. /* Allocate and initialize new left/right child pages. */
  365. if ((ret =
  366.     __os_malloc(dbenv, file_dbp->pgsize, NULL, &_lp)) != 0
  367.     || (ret =
  368.     __os_malloc(dbenv, file_dbp->pgsize, NULL, &_rp)) != 0)
  369. goto out;
  370. if (rootsplit) {
  371. P_INIT(_lp, file_dbp->pgsize, argp->left,
  372.     PGNO_INVALID,
  373.     ISINTERNAL(sp) ? PGNO_INVALID : argp->right,
  374.     LEVEL(sp), TYPE(sp));
  375. P_INIT(_rp, file_dbp->pgsize, argp->right,
  376.     ISINTERNAL(sp) ?  PGNO_INVALID : argp->left,
  377.     PGNO_INVALID, LEVEL(sp), TYPE(sp));
  378. } else {
  379. P_INIT(_lp, file_dbp->pgsize, PGNO(sp),
  380.     ISINTERNAL(sp) ? PGNO_INVALID : PREV_PGNO(sp),
  381.     ISINTERNAL(sp) ? PGNO_INVALID : argp->right,
  382.     LEVEL(sp), TYPE(sp));
  383. P_INIT(_rp, file_dbp->pgsize, argp->right,
  384.     ISINTERNAL(sp) ? PGNO_INVALID : sp->pgno,
  385.     ISINTERNAL(sp) ? PGNO_INVALID : NEXT_PGNO(sp),
  386.     LEVEL(sp), TYPE(sp));
  387. }
  388. /* Split the page. */
  389. if ((ret = __bam_copy(file_dbp, sp, _lp, 0, argp->indx)) != 0 ||
  390.     (ret = __bam_copy(file_dbp, sp, _rp, argp->indx,
  391.     NUM_ENT(sp))) != 0)
  392. goto out;
  393. /* If the left child is wrong, update it. */
  394. if (lp == NULL && (ret =
  395.     memp_fget(mpf, &argp->left, DB_MPOOL_CREATE, &lp)) != 0) {
  396. (void)__db_pgerr(file_dbp, argp->left);
  397. lp = NULL;
  398. goto out;
  399. }
  400. if (l_update) {
  401. memcpy(lp, _lp, file_dbp->pgsize);
  402. lp->lsn = *lsnp;
  403. if ((ret = memp_fput(mpf, lp, DB_MPOOL_DIRTY)) != 0)
  404. goto out;
  405. lp = NULL;
  406. }
  407. /* If the right child is wrong, update it. */
  408. if (rp == NULL && (ret = memp_fget(mpf,
  409.     &argp->right, DB_MPOOL_CREATE, &rp)) != 0) {
  410. (void)__db_pgerr(file_dbp, argp->right);
  411. rp = NULL;
  412. goto out;
  413. }
  414. if (r_update) {
  415. memcpy(rp, _rp, file_dbp->pgsize);
  416. rp->lsn = *lsnp;
  417. if ((ret = memp_fput(mpf, rp, DB_MPOOL_DIRTY)) != 0)
  418. goto out;
  419. rp = NULL;
  420. }
  421. /*
  422.  * If the parent page is wrong, update it.  This is of interest
  423.  * only if it was a root split, since root splits create parent
  424.  * pages.  All other splits modify a parent page, but those are
  425.  * separately logged and recovered.
  426.  */
  427. if (rootsplit && p_update) {
  428. if (IS_BTREE_PAGE(sp)) {
  429. ptype = P_IBTREE;
  430. rc = argp->opflags & SPL_NRECS ? 1 : 0;
  431. } else {
  432. ptype = P_IRECNO;
  433. rc = 1;
  434. }
  435. P_INIT(pp, file_dbp->pgsize, root_pgno,
  436.     PGNO_INVALID, PGNO_INVALID, _lp->level + 1, ptype);
  437. RE_NREC_SET(pp,
  438.     rc ? __bam_total(_lp) + __bam_total(_rp) : 0);
  439. pp->lsn = *lsnp;
  440. if ((ret = memp_fput(mpf, pp, DB_MPOOL_DIRTY)) != 0)
  441. goto out;
  442. pp = NULL;
  443. }
  444. check_next: /*
  445.  * Finally, redo the next-page link if necessary.  This is of
  446.  * interest only if it wasn't a root split -- inserting a new
  447.  * page in the tree requires that any following page have its
  448.  * previous-page pointer updated to our new page.  The next
  449.  * page must exist because we're redoing the operation.
  450.  */
  451. if (!rootsplit && !IS_ZERO_LSN(argp->nlsn)) {
  452. if ((ret = memp_fget(mpf, &argp->npgno, 0, &np)) != 0) {
  453. (void)__db_pgerr(file_dbp, argp->npgno);
  454. np = NULL;
  455. goto out;
  456. }
  457. cmp = log_compare(&LSN(np), &argp->nlsn);
  458. CHECK_LSN(op, cmp, &LSN(np), &argp->nlsn);
  459. if (cmp == 0) {
  460. PREV_PGNO(np) = argp->right;
  461. np->lsn = *lsnp;
  462. if ((ret =
  463.     memp_fput(mpf, np, DB_MPOOL_DIRTY)) != 0)
  464. goto out;
  465. np = NULL;
  466. }
  467. }
  468. } else {
  469. /*
  470.  * If the split page is wrong, replace its contents with the
  471.  * logged page contents.  If the page doesn't exist, it means
  472.  * that the create of the page never happened, nor did any of
  473.  * the adds onto the page that caused the split, and there's
  474.  * really no undo-ing to be done.
  475.  */
  476. if ((ret = memp_fget(mpf, &pgno, 0, &pp)) != 0) {
  477. pp = NULL;
  478. goto lrundo;
  479. }
  480. if (log_compare(lsnp, &LSN(pp)) == 0) {
  481. memcpy(pp, argp->pg.data, argp->pg.size);
  482. if ((ret = memp_fput(mpf, pp, DB_MPOOL_DIRTY)) != 0)
  483. goto out;
  484. pp = NULL;
  485. }
  486. /*
  487.  * If it's a root split and the left child ever existed, update
  488.  * its LSN.  (If it's not a root split, we've updated the left
  489.  * page already -- it's the same as the split page.) If the
  490.  * right child ever existed, root split or not, update its LSN.
  491.  * The undo of the page allocation(s) will restore them to the
  492.  * free list.
  493.  */
  494. lrundo: if ((rootsplit && lp != NULL) || rp != NULL) {
  495. if (rootsplit && lp != NULL &&
  496.     log_compare(lsnp, &LSN(lp)) == 0) {
  497. lp->lsn = argp->llsn;
  498. if ((ret =
  499.     memp_fput(mpf, lp, DB_MPOOL_DIRTY)) != 0)
  500. goto out;
  501. lp = NULL;
  502. }
  503. if (rp != NULL &&
  504.     log_compare(lsnp, &LSN(rp)) == 0) {
  505. rp->lsn = argp->rlsn;
  506. if ((ret =
  507.     memp_fput(mpf, rp, DB_MPOOL_DIRTY)) != 0)
  508. goto out;
  509. rp = NULL;
  510. }
  511. }
  512. /*
  513.  * Finally, undo the next-page link if necessary.  This is of
  514.  * interest only if it wasn't a root split -- inserting a new
  515.  * page in the tree requires that any following page have its
  516.  * previous-page pointer updated to our new page.  Since it's
  517.  * possible that the next-page never existed, we ignore it as
  518.  * if there's nothing to undo.
  519.  */
  520. if (!rootsplit && !IS_ZERO_LSN(argp->nlsn)) {
  521. if ((ret = memp_fget(mpf, &argp->npgno, 0, &np)) != 0) {
  522. np = NULL;
  523. goto done;
  524. }
  525. if (log_compare(lsnp, &LSN(np)) == 0) {
  526. PREV_PGNO(np) = argp->left;
  527. np->lsn = argp->nlsn;
  528. if (memp_fput(mpf, np, DB_MPOOL_DIRTY))
  529. goto out;
  530. np = NULL;
  531. }
  532. }
  533. }
  534. done: *lsnp = argp->prev_lsn;
  535. ret = 0;
  536. out: /* Free any pages that weren't dirtied. */
  537. if (pp != NULL && (t_ret = memp_fput(mpf, pp, 0)) != 0 && ret == 0)
  538. ret = t_ret;
  539. if (lp != NULL && (t_ret = memp_fput(mpf, lp, 0)) != 0 && ret == 0)
  540. ret = t_ret;
  541. if (np != NULL && (t_ret = memp_fput(mpf, np, 0)) != 0 && ret == 0)
  542. ret = t_ret;
  543. if (rp != NULL && (t_ret = memp_fput(mpf, rp, 0)) != 0 && ret == 0)
  544. ret = t_ret;
  545. /* Free any allocated space. */
  546. if (_lp != NULL)
  547. __os_free(_lp, file_dbp->pgsize);
  548. if (_rp != NULL)
  549. __os_free(_rp, file_dbp->pgsize);
  550. if (sp != NULL)
  551. __os_free(sp, argp->pg.size);
  552. REC_CLOSE;
  553. }
  554. /*
  555.  * __bam_rsplit_recover --
  556.  * Recovery function for a reverse split.
  557.  *
  558.  * PUBLIC: int __bam_rsplit_recover
  559.  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  560.  */
  561. int
  562. __bam_rsplit_recover(dbenv, dbtp, lsnp, op, info)
  563. DB_ENV *dbenv;
  564. DBT *dbtp;
  565. DB_LSN *lsnp;
  566. db_recops op;
  567. void *info;
  568. {
  569. __bam_rsplit_args *argp;
  570. DB *file_dbp;
  571. DBC *dbc;
  572. DB_LSN copy_lsn;
  573. DB_MPOOLFILE *mpf;
  574. PAGE *pagep;
  575. db_pgno_t pgno, root_pgno;
  576. int cmp_n, cmp_p, modified, ret;
  577. COMPQUIET(info, NULL);
  578. REC_PRINT(__bam_rsplit_print);
  579. REC_INTRO(__bam_rsplit_read, 1);
  580. /* Fix the root page. */
  581. pgno = root_pgno = argp->root_pgno;
  582. if ((ret = memp_fget(mpf, &pgno, 0, &pagep)) != 0) {
  583. /* The root page must always exist if we are going forward. */
  584. if (DB_REDO(op)) {
  585. __db_pgerr(file_dbp, pgno);
  586. goto out;
  587. }
  588. /* This must be the root of an OPD tree. */
  589. DB_ASSERT(root_pgno !=
  590.     ((BTREE *)file_dbp->bt_internal)->bt_root);
  591. ret = 0;
  592. goto done;
  593. }
  594. modified = 0;
  595. cmp_n = log_compare(lsnp, &LSN(pagep));
  596. cmp_p = log_compare(&LSN(pagep), &argp->rootlsn);
  597. CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->rootlsn);
  598. if (cmp_p == 0 && DB_REDO(op)) {
  599. /* Need to redo update described. */
  600. memcpy(pagep, argp->pgdbt.data, argp->pgdbt.size);
  601. pagep->pgno = root_pgno;
  602. pagep->lsn = *lsnp;
  603. modified = 1;
  604. } else if (cmp_n == 0 && DB_UNDO(op)) {
  605. /* Need to undo update described. */
  606. P_INIT(pagep, file_dbp->pgsize, root_pgno,
  607.     argp->nrec, PGNO_INVALID, pagep->level + 1,
  608.     IS_BTREE_PAGE(pagep) ? P_IBTREE : P_IRECNO);
  609. if ((ret = __db_pitem(dbc, pagep, 0,
  610.     argp->rootent.size, &argp->rootent, NULL)) != 0)
  611. goto out;
  612. pagep->lsn = argp->rootlsn;
  613. modified = 1;
  614. }
  615. if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  616. goto out;
  617. /*
  618.  * Fix the page copied over the root page.  It's possible that the
  619.  * page never made it to disk, so if we're undo-ing and the page
  620.  * doesn't exist, it's okay and there's nothing further to do.
  621.  */
  622. if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
  623. if (DB_UNDO(op))
  624. goto done;
  625. (void)__db_pgerr(file_dbp, argp->pgno);
  626. goto out;
  627. }
  628. modified = 0;
  629. __ua_memcpy(&copy_lsn, &LSN(argp->pgdbt.data), sizeof(DB_LSN));
  630. cmp_n = log_compare(lsnp, &LSN(pagep));
  631. cmp_p = log_compare(&LSN(pagep), &copy_lsn);
  632. CHECK_LSN(op, cmp_p, &LSN(pagep), &copy_lsn);
  633. if (cmp_p == 0 && DB_REDO(op)) {
  634. /* Need to redo update described. */
  635. pagep->lsn = *lsnp;
  636. modified = 1;
  637. } else if (cmp_n == 0 && DB_UNDO(op)) {
  638. /* Need to undo update described. */
  639. memcpy(pagep, argp->pgdbt.data, argp->pgdbt.size);
  640. modified = 1;
  641. }
  642. if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  643. goto out;
  644. done: *lsnp = argp->prev_lsn;
  645. ret = 0;
  646. out: REC_CLOSE;
  647. }
  648. /*
  649.  * __bam_adj_recover --
  650.  * Recovery function for adj.
  651.  *
  652.  * PUBLIC: int __bam_adj_recover
  653.  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  654.  */
  655. int
  656. __bam_adj_recover(dbenv, dbtp, lsnp, op, info)
  657. DB_ENV *dbenv;
  658. DBT *dbtp;
  659. DB_LSN *lsnp;
  660. db_recops op;
  661. void *info;
  662. {
  663. __bam_adj_args *argp;
  664. DB *file_dbp;
  665. DBC *dbc;
  666. DB_MPOOLFILE *mpf;
  667. PAGE *pagep;
  668. int cmp_n, cmp_p, modified, ret;
  669. COMPQUIET(info, NULL);
  670. REC_PRINT(__bam_adj_print);
  671. REC_INTRO(__bam_adj_read, 1);
  672. /* Get the page; if it never existed and we're undoing, we're done. */
  673. if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
  674. if (DB_UNDO(op))
  675. goto done;
  676. (void)__db_pgerr(file_dbp, argp->pgno);
  677. goto out;
  678. }
  679. modified = 0;
  680. cmp_n = log_compare(lsnp, &LSN(pagep));
  681. cmp_p = log_compare(&LSN(pagep), &argp->lsn);
  682. CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
  683. if (cmp_p == 0 && DB_REDO(op)) {
  684. /* Need to redo update described. */
  685. if ((ret = __bam_adjindx(dbc,
  686.     pagep, argp->indx, argp->indx_copy, argp->is_insert)) != 0)
  687. goto err;
  688. LSN(pagep) = *lsnp;
  689. modified = 1;
  690. } else if (cmp_n == 0 && DB_UNDO(op)) {
  691. /* Need to undo update described. */
  692. if ((ret = __bam_adjindx(dbc,
  693.     pagep, argp->indx, argp->indx_copy, !argp->is_insert)) != 0)
  694. goto err;
  695. LSN(pagep) = argp->lsn;
  696. modified = 1;
  697. }
  698. if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  699. goto out;
  700. done: *lsnp = argp->prev_lsn;
  701. ret = 0;
  702. if (0) {
  703. err: (void)memp_fput(mpf, pagep, 0);
  704. }
  705. out: REC_CLOSE;
  706. }
  707. /*
  708.  * __bam_cadjust_recover --
  709.  * Recovery function for the adjust of a count change in an internal
  710.  * page.
  711.  *
  712.  * PUBLIC: int __bam_cadjust_recover
  713.  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  714.  */
  715. int
  716. __bam_cadjust_recover(dbenv, dbtp, lsnp, op, info)
  717. DB_ENV *dbenv;
  718. DBT *dbtp;
  719. DB_LSN *lsnp;
  720. db_recops op;
  721. void *info;
  722. {
  723. __bam_cadjust_args *argp;
  724. DB *file_dbp;
  725. DBC *dbc;
  726. DB_MPOOLFILE *mpf;
  727. PAGE *pagep;
  728. int cmp_n, cmp_p, modified, ret;
  729. COMPQUIET(info, NULL);
  730. REC_PRINT(__bam_cadjust_print);
  731. REC_INTRO(__bam_cadjust_read, 1);
  732. /* Get the page; if it never existed and we're undoing, we're done. */
  733. if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
  734. if (DB_UNDO(op))
  735. goto done;
  736. (void)__db_pgerr(file_dbp, argp->pgno);
  737. goto out;
  738. }
  739. modified = 0;
  740. cmp_n = log_compare(lsnp, &LSN(pagep));
  741. cmp_p = log_compare(&LSN(pagep), &argp->lsn);
  742. CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
  743. if (cmp_p == 0 && DB_REDO(op)) {
  744. /* Need to redo update described. */
  745. if (IS_BTREE_PAGE(pagep)) {
  746. GET_BINTERNAL(pagep, argp->indx)->nrecs += argp->adjust;
  747. if (argp->opflags & CAD_UPDATEROOT)
  748. RE_NREC_ADJ(pagep, argp->adjust);
  749. } else {
  750. GET_RINTERNAL(pagep, argp->indx)->nrecs += argp->adjust;
  751. if (argp->opflags & CAD_UPDATEROOT)
  752. RE_NREC_ADJ(pagep, argp->adjust);
  753. }
  754. LSN(pagep) = *lsnp;
  755. modified = 1;
  756. } else if (cmp_n == 0 && DB_UNDO(op)) {
  757. /* Need to undo update described. */
  758. if (IS_BTREE_PAGE(pagep)) {
  759. GET_BINTERNAL(pagep, argp->indx)->nrecs -= argp->adjust;
  760. if (argp->opflags & CAD_UPDATEROOT)
  761. RE_NREC_ADJ(pagep, -(argp->adjust));
  762. } else {
  763. GET_RINTERNAL(pagep, argp->indx)->nrecs -= argp->adjust;
  764. if (argp->opflags & CAD_UPDATEROOT)
  765. RE_NREC_ADJ(pagep, -(argp->adjust));
  766. }
  767. LSN(pagep) = argp->lsn;
  768. modified = 1;
  769. }
  770. if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  771. goto out;
  772. done: *lsnp = argp->prev_lsn;
  773. ret = 0;
  774. out: REC_CLOSE;
  775. }
  776. /*
  777.  * __bam_cdel_recover --
  778.  * Recovery function for the intent-to-delete of a cursor record.
  779.  *
  780.  * PUBLIC: int __bam_cdel_recover
  781.  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  782.  */
  783. int
  784. __bam_cdel_recover(dbenv, dbtp, lsnp, op, info)
  785. DB_ENV *dbenv;
  786. DBT *dbtp;
  787. DB_LSN *lsnp;
  788. db_recops op;
  789. void *info;
  790. {
  791. __bam_cdel_args *argp;
  792. DB *file_dbp;
  793. DBC *dbc;
  794. DB_MPOOLFILE *mpf;
  795. PAGE *pagep;
  796. u_int32_t indx;
  797. int cmp_n, cmp_p, modified, ret;
  798. COMPQUIET(info, NULL);
  799. REC_PRINT(__bam_cdel_print);
  800. REC_INTRO(__bam_cdel_read, 1);
  801. /* Get the page; if it never existed and we're undoing, we're done. */
  802. if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
  803. if (DB_UNDO(op))
  804. goto done;
  805. (void)__db_pgerr(file_dbp, argp->pgno);
  806. goto out;
  807. }
  808. modified = 0;
  809. cmp_n = log_compare(lsnp, &LSN(pagep));
  810. cmp_p = log_compare(&LSN(pagep), &argp->lsn);
  811. CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
  812. if (cmp_p == 0 && DB_REDO(op)) {
  813. /* Need to redo update described. */
  814. indx = argp->indx + (TYPE(pagep) == P_LBTREE ? O_INDX : 0);
  815. B_DSET(GET_BKEYDATA(pagep, indx)->type);
  816. LSN(pagep) = *lsnp;
  817. modified = 1;
  818. } else if (cmp_n == 0 && DB_UNDO(op)) {
  819. /* Need to undo update described. */
  820. indx = argp->indx + (TYPE(pagep) == P_LBTREE ? O_INDX : 0);
  821. B_DCLR(GET_BKEYDATA(pagep, indx)->type);
  822. (void)__bam_ca_delete(file_dbp, argp->pgno, argp->indx, 0);
  823. LSN(pagep) = argp->lsn;
  824. modified = 1;
  825. }
  826. if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  827. goto out;
  828. done: *lsnp = argp->prev_lsn;
  829. ret = 0;
  830. out: REC_CLOSE;
  831. }
  832. /*
  833.  * __bam_repl_recover --
  834.  * Recovery function for page item replacement.
  835.  *
  836.  * PUBLIC: int __bam_repl_recover
  837.  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  838.  */
  839. int
  840. __bam_repl_recover(dbenv, dbtp, lsnp, op, info)
  841. DB_ENV *dbenv;
  842. DBT *dbtp;
  843. DB_LSN *lsnp;
  844. db_recops op;
  845. void *info;
  846. {
  847. __bam_repl_args *argp;
  848. BKEYDATA *bk;
  849. DB *file_dbp;
  850. DBC *dbc;
  851. DBT dbt;
  852. DB_MPOOLFILE *mpf;
  853. PAGE *pagep;
  854. int cmp_n, cmp_p, modified, ret;
  855. u_int8_t *p;
  856. COMPQUIET(info, NULL);
  857. REC_PRINT(__bam_repl_print);
  858. REC_INTRO(__bam_repl_read, 1);
  859. /* Get the page; if it never existed and we're undoing, we're done. */
  860. if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
  861. if (DB_UNDO(op))
  862. goto done;
  863. (void)__db_pgerr(file_dbp, argp->pgno);
  864. goto out;
  865. }
  866. bk = GET_BKEYDATA(pagep, argp->indx);
  867. modified = 0;
  868. cmp_n = log_compare(lsnp, &LSN(pagep));
  869. cmp_p = log_compare(&LSN(pagep), &argp->lsn);
  870. CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
  871. if (cmp_p == 0 && DB_REDO(op)) {
  872. /*
  873.  * Need to redo update described.
  874.  *
  875.  * Re-build the replacement item.
  876.  */
  877. memset(&dbt, 0, sizeof(dbt));
  878. dbt.size = argp->prefix + argp->suffix + argp->repl.size;
  879. if ((ret = __os_malloc(dbenv, dbt.size, NULL, &dbt.data)) != 0)
  880. goto err;
  881. p = dbt.data;
  882. memcpy(p, bk->data, argp->prefix);
  883. p += argp->prefix;
  884. memcpy(p, argp->repl.data, argp->repl.size);
  885. p += argp->repl.size;
  886. memcpy(p, bk->data + (bk->len - argp->suffix), argp->suffix);
  887. ret = __bam_ritem(dbc, pagep, argp->indx, &dbt);
  888. __os_free(dbt.data, dbt.size);
  889. if (ret != 0)
  890. goto err;
  891. LSN(pagep) = *lsnp;
  892. modified = 1;
  893. } else if (cmp_n == 0 && DB_UNDO(op)) {
  894. /*
  895.  * Need to undo update described.
  896.  *
  897.  * Re-build the original item.
  898.  */
  899. memset(&dbt, 0, sizeof(dbt));
  900. dbt.size = argp->prefix + argp->suffix + argp->orig.size;
  901. if ((ret = __os_malloc(dbenv, dbt.size, NULL, &dbt.data)) != 0)
  902. goto err;
  903. p = dbt.data;
  904. memcpy(p, bk->data, argp->prefix);
  905. p += argp->prefix;
  906. memcpy(p, argp->orig.data, argp->orig.size);
  907. p += argp->orig.size;
  908. memcpy(p, bk->data + (bk->len - argp->suffix), argp->suffix);
  909. ret = __bam_ritem(dbc, pagep, argp->indx, &dbt);
  910. __os_free(dbt.data, dbt.size);
  911. if (ret != 0)
  912. goto err;
  913. /* Reset the deleted flag, if necessary. */
  914. if (argp->isdeleted)
  915. B_DSET(GET_BKEYDATA(pagep, argp->indx)->type);
  916. LSN(pagep) = argp->lsn;
  917. modified = 1;
  918. }
  919. if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  920. goto out;
  921. done: *lsnp = argp->prev_lsn;
  922. ret = 0;
  923. if (0) {
  924. err: (void)memp_fput(mpf, pagep, 0);
  925. }
  926. out: REC_CLOSE;
  927. }
  928. /*
  929.  * __bam_root_recover --
  930.  * Recovery function for setting the root page on the meta-data page.
  931.  *
  932.  * PUBLIC: int __bam_root_recover
  933.  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  934.  */
  935. int
  936. __bam_root_recover(dbenv, dbtp, lsnp, op, info)
  937. DB_ENV *dbenv;
  938. DBT *dbtp;
  939. DB_LSN *lsnp;
  940. db_recops op;
  941. void *info;
  942. {
  943. __bam_root_args *argp;
  944. BTMETA *meta;
  945. DB *file_dbp;
  946. DBC *dbc;
  947. DB_MPOOLFILE *mpf;
  948. int cmp_n, cmp_p, modified, ret;
  949. COMPQUIET(info, NULL);
  950. REC_PRINT(__bam_root_print);
  951. REC_INTRO(__bam_root_read, 0);
  952. if ((ret = memp_fget(mpf, &argp->meta_pgno, 0, &meta)) != 0) {
  953. /* The metadata page must always exist on redo. */
  954. if (DB_REDO(op)) {
  955. (void)__db_pgerr(file_dbp, argp->meta_pgno);
  956. goto out;
  957. } else
  958. goto done;
  959. }
  960. modified = 0;
  961. cmp_n = log_compare(lsnp, &LSN(meta));
  962. cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
  963. CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn);
  964. if (cmp_p == 0 && DB_REDO(op)) {
  965. /* Need to redo update described. */
  966. meta->root = argp->root_pgno;
  967. meta->dbmeta.lsn = *lsnp;
  968. ((BTREE *)file_dbp->bt_internal)->bt_root = meta->root;
  969. modified = 1;
  970. } else if (cmp_n == 0 && DB_UNDO(op)) {
  971. /* Nothing to undo except lsn. */
  972. meta->dbmeta.lsn = argp->meta_lsn;
  973. modified = 1;
  974. }
  975. if ((ret = memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
  976. goto out;
  977. done: *lsnp = argp->prev_lsn;
  978. ret = 0;
  979. out: REC_CLOSE;
  980. }
  981. /*
  982.  * __bam_curadj_recover --
  983.  * Transaction abort function to undo cursor adjustments.
  984.  * This should only be triggered by subtransaction aborts.
  985.  *
  986.  * PUBLIC: int __bam_curadj_recover
  987.  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  988.  */
  989. int
  990. __bam_curadj_recover(dbenv, dbtp, lsnp, op, info)
  991. DB_ENV *dbenv;
  992. DBT *dbtp;
  993. DB_LSN *lsnp;
  994. db_recops op;
  995. void *info;
  996. {
  997. __bam_curadj_args *argp;
  998. DB *file_dbp;
  999. DBC *dbc;
  1000. DB_MPOOLFILE *mpf;
  1001. int ret;
  1002. COMPQUIET(info, NULL);
  1003. REC_PRINT(__bam_curadj_print);
  1004. REC_INTRO(__bam_curadj_read, 0);
  1005. ret = 0;
  1006. if (op != DB_TXN_ABORT)
  1007. goto done;
  1008. switch(argp->mode) {
  1009. case DB_CA_DI:
  1010. if ((ret = __bam_ca_di(dbc, argp->from_pgno,
  1011.     argp->from_indx, -(int)argp->first_indx)) != 0)
  1012. goto out;
  1013. break;
  1014. case DB_CA_DUP:
  1015. if ((ret = __bam_ca_undodup(file_dbp, argp->first_indx,
  1016.      argp->from_pgno, argp->from_indx, argp->to_indx)) != 0)
  1017. goto out;
  1018. break;
  1019. case DB_CA_RSPLIT:
  1020. if ((ret =
  1021.     __bam_ca_rsplit(dbc, argp->to_pgno, argp->from_pgno)) != 0)
  1022. goto out;
  1023. break;
  1024. case DB_CA_SPLIT:
  1025. __bam_ca_undosplit(file_dbp, argp->from_pgno,
  1026.     argp->to_pgno, argp->left_pgno, argp->from_indx);
  1027. break;
  1028. }
  1029. done: *lsnp = argp->prev_lsn;
  1030. out: REC_CLOSE;
  1031. }
  1032. /*
  1033.  * __bam_rcuradj_recover --
  1034.  * Transaction abort function to undo cursor adjustments in rrecno.
  1035.  * This should only be triggered by subtransaction aborts.
  1036.  *
  1037.  * PUBLIC: int __bam_rcuradj_recover
  1038.  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
  1039.  */
  1040. int
  1041. __bam_rcuradj_recover(dbenv, dbtp, lsnp, op, info)
  1042. DB_ENV *dbenv;
  1043. DBT *dbtp;
  1044. DB_LSN *lsnp;
  1045. db_recops op;
  1046. void *info;
  1047. {
  1048. __bam_rcuradj_args *argp;
  1049. BTREE_CURSOR *cp;
  1050. DB *file_dbp;
  1051. DBC *dbc, *rdbc;
  1052. DB_MPOOLFILE *mpf;
  1053. int ret, t_ret;
  1054. COMPQUIET(info, NULL);
  1055. rdbc = NULL;
  1056. REC_PRINT(__bam_rcuradj_print);
  1057. REC_INTRO(__bam_rcuradj_read, 0);
  1058. ret = t_ret = 0;
  1059. if (op != DB_TXN_ABORT)
  1060. goto done;
  1061. /*
  1062.  * We don't know whether we're in an offpage dup set, and
  1063.  * thus don't know whether the dbc REC_INTRO has handed us is
  1064.  * of a reasonable type.  It's certainly unset, so if this is
  1065.  * an offpage dup set, we don't have an OPD cursor.  The
  1066.  * simplest solution is just to allocate a whole new cursor
  1067.  * for our use;  we're only really using it to hold pass some
  1068.  * state into __ram_ca, and this way we don't need to make
  1069.  * this function know anything about how offpage dups work.
  1070.  */
  1071. if ((ret =
  1072.     __db_icursor(file_dbp, NULL, DB_RECNO, argp->root, 0, &rdbc)) != 0)
  1073. goto out;
  1074. cp = (BTREE_CURSOR *)rdbc->internal;
  1075. F_SET(cp, C_RENUMBER);
  1076. cp->recno = argp->recno;
  1077. switch(argp->mode) {
  1078. case CA_DELETE:
  1079. /*
  1080.  * The way to undo a delete is with an insert.  Since
  1081.  * we're undoing it, the delete flag must be set.
  1082.  */
  1083. F_SET(cp, C_DELETED);
  1084. F_SET(cp, C_RENUMBER); /* Just in case. */
  1085. cp->order = argp->order;
  1086. __ram_ca(rdbc, CA_ICURRENT);
  1087. break;
  1088. case CA_IAFTER:
  1089. case CA_IBEFORE:
  1090. case CA_ICURRENT:
  1091. /*
  1092.  * The way to undo an insert is with a delete.  The delete
  1093.  * flag is unset to start with.
  1094.  */
  1095. F_CLR(cp, C_DELETED);
  1096. cp->order = INVALID_ORDER;
  1097. __ram_ca(rdbc, CA_DELETE);
  1098. break;
  1099. }
  1100. done: *lsnp = argp->prev_lsn;
  1101. out: if (rdbc != NULL && (t_ret = rdbc->c_close(rdbc)) != 0 && ret == 0)
  1102. ret = t_ret;
  1103. REC_CLOSE;
  1104. }