2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 1996, 1997, 1998
5 * Sleepycat Software. All rights reserved.
11 static const char sccsid
[] = "@(#)bt_rec.c 10.21 (Sleepycat) 4/28/98";
14 #ifndef NO_SYSTEM_INCLUDES
15 #include <sys/types.h>
27 #include "common_ext.h"
30 * __bam_pg_alloc_recover --
31 * Recovery function for pg_alloc.
33 * PUBLIC: int __bam_pg_alloc_recover
34 * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
37 __bam_pg_alloc_recover(logp
, dbtp
, lsnp
, redo
, info
)
44 __bam_pg_alloc_args
*argp
;
50 int cmp_n
, cmp_p
, modified
, ret
;
52 REC_PRINT(__bam_pg_alloc_print
);
53 REC_INTRO(__bam_pg_alloc_read
);
56 * Fix up the allocated page. If we're redoing the operation, we have
57 * to get the page (creating it if it doesn't exist), and update its
58 * LSN. If we're undoing the operation, we have to reset the page's
59 * LSN and put it on the free list.
61 * Fix up the metadata page. If we're redoing the operation, we have
62 * to get the metadata page and update its LSN and its free pointer.
63 * If we're undoing the operation and the page was ever created, we put
67 if ((ret
= memp_fget(mpf
, &pgno
, 0, &meta
)) != 0) {
68 /* The metadata page must always exist. */
69 (void)__db_pgerr(file_dbp
, pgno
);
72 if ((ret
= memp_fget(mpf
, &argp
->pgno
, DB_MPOOL_CREATE
, &pagep
)) != 0) {
74 * We specify creation and check for it later, because this
75 * operation was supposed to create the page, and even in
76 * the undo case it's going to get linked onto the freelist
77 * which we're also fixing up.
79 (void)__db_pgerr(file_dbp
, argp
->pgno
);
80 (void)memp_fput(mpf
, meta
, 0);
84 /* Fix up the allocated page. */
86 cmp_n
= log_compare(lsnp
, &LSN(pagep
));
87 cmp_p
= log_compare(&LSN(pagep
), &argp
->page_lsn
);
88 if (cmp_p
== 0 && redo
) {
89 /* Need to redo update described. */
90 P_INIT(pagep
, file_dbp
->pgsize
,
91 argp
->pgno
, PGNO_INVALID
, PGNO_INVALID
, 0, argp
->ptype
);
95 } else if (cmp_n
== 0 && !redo
) {
96 /* Need to undo update described. */
97 P_INIT(pagep
, file_dbp
->pgsize
,
98 argp
->pgno
, PGNO_INVALID
, meta
->free
, 0, P_INVALID
);
100 pagep
->lsn
= argp
->page_lsn
;
103 if ((ret
= memp_fput(mpf
, pagep
, modified
? DB_MPOOL_DIRTY
: 0)) != 0) {
104 (void)__db_panic(file_dbp
);
105 (void)memp_fput(mpf
, meta
, 0);
109 /* Fix up the metadata page. */
111 cmp_n
= log_compare(lsnp
, &LSN(meta
));
112 cmp_p
= log_compare(&LSN(meta
), &argp
->meta_lsn
);
113 if (cmp_p
== 0 && redo
) {
114 /* Need to redo update described. */
116 meta
->free
= argp
->next
;
118 } else if (cmp_n
== 0 && !redo
) {
119 /* Need to undo update described. */
120 meta
->lsn
= argp
->meta_lsn
;
121 meta
->free
= argp
->pgno
;
124 if ((ret
= memp_fput(mpf
, meta
, modified
? DB_MPOOL_DIRTY
: 0)) != 0) {
125 (void)__db_panic(file_dbp
);
129 *lsnp
= argp
->prev_lsn
;
136 * __bam_pg_free_recover --
137 * Recovery function for pg_free.
139 * PUBLIC: int __bam_pg_free_recover
140 * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
143 __bam_pg_free_recover(logp
, dbtp
, lsnp
, redo
, info
)
150 __bam_pg_free_args
*argp
;
156 int cmp_n
, cmp_p
, modified
, ret
;
158 REC_PRINT(__bam_pg_free_print
);
159 REC_INTRO(__bam_pg_free_read
);
162 * Fix up the freed page. If we're redoing the operation we get the
163 * page and explicitly discard its contents, then update its LSN. If
164 * we're undoing the operation, we get the page and restore its header.
166 if ((ret
= memp_fget(mpf
, &argp
->pgno
, 0, &pagep
)) != 0) {
168 * We don't automatically create the page. The only way the
169 * page might not exist is if the alloc never happened, and
170 * the only way the alloc might never have happened is if we
171 * are undoing, in which case there's no reason to create the
176 (void)__db_pgerr(file_dbp
, argp
->pgno
);
180 cmp_n
= log_compare(lsnp
, &LSN(pagep
));
181 cmp_p
= log_compare(&LSN(pagep
), &LSN(argp
->header
.data
));
182 if (cmp_p
== 0 && redo
) {
183 /* Need to redo update described. */
184 P_INIT(pagep
, file_dbp
->pgsize
,
185 pagep
->pgno
, PGNO_INVALID
, argp
->next
, 0, P_INVALID
);
189 } else if (cmp_n
== 0 && !redo
) {
190 /* Need to undo update described. */
191 memcpy(pagep
, argp
->header
.data
, argp
->header
.size
);
195 if ((ret
= memp_fput(mpf
, pagep
, modified
? DB_MPOOL_DIRTY
: 0)) != 0) {
196 (void)__db_panic(file_dbp
);
201 * Fix up the metadata page. If we're redoing or undoing the operation
202 * we get the page and update its LSN and free pointer.
204 pgno
= PGNO_METADATA
;
205 if ((ret
= memp_fget(mpf
, &pgno
, 0, &meta
)) != 0) {
206 /* The metadata page must always exist. */
207 (void)__db_pgerr(file_dbp
, pgno
);
212 cmp_n
= log_compare(lsnp
, &LSN(meta
));
213 cmp_p
= log_compare(&LSN(meta
), &argp
->meta_lsn
);
214 if (cmp_p
== 0 && redo
) {
215 /* Need to redo update described. */
216 meta
->free
= argp
->pgno
;
220 } else if (cmp_n
== 0 && !redo
) {
221 /* Need to undo update described. */
222 meta
->free
= argp
->next
;
224 meta
->lsn
= argp
->meta_lsn
;
227 if ((ret
= memp_fput(mpf
, meta
, modified
? DB_MPOOL_DIRTY
: 0)) != 0) {
228 (void)__db_panic(file_dbp
);
232 done
: *lsnp
= argp
->prev_lsn
;
239 * __bam_split_recover --
240 * Recovery function for split.
242 * PUBLIC: int __bam_split_recover
243 * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
246 __bam_split_recover(logp
, dbtp
, lsnp
, redo
, info
)
253 __bam_split_args
*argp
;
256 PAGE
*_lp
, *lp
, *np
, *pp
, *_rp
, *rp
, *sp
;
258 int l_update
, p_update
, r_update
, ret
, rootsplit
, t_ret
;
260 REC_PRINT(__bam_split_print
);
263 _lp
= lp
= np
= pp
= _rp
= rp
= NULL
;
265 REC_INTRO(__bam_split_read
);
268 * There are two kinds of splits that we have to recover from. The
269 * first is a root-page split, where the root page is split from a
270 * leaf page into an internal page and two new leaf pages are created.
271 * The second is where a page is split into two pages, and a new key
272 * is inserted into the parent page.
276 rootsplit
= pgno
== PGNO_ROOT
;
277 if (memp_fget(mpf
, &argp
->left
, 0, &lp
) != 0)
279 if (memp_fget(mpf
, &argp
->right
, 0, &rp
) != 0)
283 l_update
= r_update
= p_update
= 0;
285 * Decide if we need to resplit the page.
287 * If this is a root split, then the root has to exist, it's
288 * the page we're splitting and it gets modified. If this is
289 * not a root split, then the left page has to exist, for the
293 if ((ret
= memp_fget(mpf
, &pgno
, 0, &pp
)) != 0) {
294 (void)__db_pgerr(file_dbp
, pgno
);
299 log_compare(&LSN(pp
), &LSN(argp
->pg
.data
)) == 0;
302 (void)__db_pgerr(file_dbp
, argp
->left
);
305 if (lp
== NULL
|| log_compare(&LSN(lp
), &argp
->llsn
) == 0)
307 if (rp
== NULL
|| log_compare(&LSN(rp
), &argp
->rlsn
) == 0)
309 if (!p_update
&& !l_update
&& !r_update
)
312 /* Allocate and initialize new left/right child pages. */
313 if ((_lp
= (PAGE
*)__db_malloc(file_dbp
->pgsize
)) == NULL
||
314 (_rp
= (PAGE
*)__db_malloc(file_dbp
->pgsize
)) == NULL
) {
316 __db_err(file_dbp
->dbenv
, "%s", strerror(ret
));
320 P_INIT(_lp
, file_dbp
->pgsize
, argp
->left
,
322 ISINTERNAL(sp
) ? PGNO_INVALID
: argp
->right
,
323 LEVEL(sp
), TYPE(sp
));
324 P_INIT(_rp
, file_dbp
->pgsize
, argp
->right
,
325 ISINTERNAL(sp
) ? PGNO_INVALID
: argp
->left
,
326 PGNO_INVALID
, LEVEL(sp
), TYPE(sp
));
328 P_INIT(_lp
, file_dbp
->pgsize
, PGNO(sp
),
329 ISINTERNAL(sp
) ? PGNO_INVALID
: PREV_PGNO(sp
),
330 ISINTERNAL(sp
) ? PGNO_INVALID
: argp
->right
,
331 LEVEL(sp
), TYPE(sp
));
332 P_INIT(_rp
, file_dbp
->pgsize
, argp
->right
,
333 ISINTERNAL(sp
) ? PGNO_INVALID
: sp
->pgno
,
334 ISINTERNAL(sp
) ? PGNO_INVALID
: NEXT_PGNO(sp
),
335 LEVEL(sp
), TYPE(sp
));
338 /* Split the page. */
339 if ((ret
= __bam_copy(file_dbp
, sp
, _lp
, 0, argp
->indx
)) != 0 ||
340 (ret
= __bam_copy(file_dbp
, sp
, _rp
, argp
->indx
,
344 /* If the left child is wrong, update it. */
345 if (lp
== NULL
&& (ret
=
346 memp_fget(mpf
, &argp
->left
, DB_MPOOL_CREATE
, &lp
)) != 0) {
347 (void)__db_pgerr(file_dbp
, argp
->left
);
352 memcpy(lp
, _lp
, file_dbp
->pgsize
);
354 if ((ret
= memp_fput(mpf
, lp
, DB_MPOOL_DIRTY
)) != 0)
359 /* If the right child is wrong, update it. */
360 if (rp
== NULL
&& (ret
= memp_fget(mpf
,
361 &argp
->right
, DB_MPOOL_CREATE
, &rp
)) != 0) {
362 (void)__db_pgerr(file_dbp
, argp
->right
);
367 memcpy(rp
, _rp
, file_dbp
->pgsize
);
369 if ((ret
= memp_fput(mpf
, rp
, DB_MPOOL_DIRTY
)) != 0)
375 * If the parent page is wrong, update it. This is of interest
376 * only if it was a root split, since root splits create parent
377 * pages. All other splits modify a parent page, but those are
378 * separately logged and recovered.
380 if (rootsplit
&& p_update
) {
381 if (file_dbp
->type
== DB_BTREE
)
382 P_INIT(pp
, file_dbp
->pgsize
,
383 PGNO_ROOT
, PGNO_INVALID
, PGNO_INVALID
,
384 _lp
->level
+ 1, P_IBTREE
);
386 P_INIT(pp
, file_dbp
->pgsize
,
387 PGNO_ROOT
, PGNO_INVALID
, PGNO_INVALID
,
388 _lp
->level
+ 1, P_IRECNO
);
390 file_dbp
->type
== DB_RECNO
||
391 F_ISSET(file_dbp
, DB_BT_RECNUM
) ?
392 __bam_total(_lp
) + __bam_total(_rp
) : 0);
394 if ((ret
= memp_fput(mpf
, pp
, DB_MPOOL_DIRTY
)) != 0)
400 * Finally, redo the next-page link if necessary. This is of
401 * interest only if it wasn't a root split -- inserting a new
402 * page in the tree requires that any following page have its
403 * previous-page pointer updated to our new page. The next
404 * page must exist because we're redoing the operation.
406 if (!rootsplit
&& !IS_ZERO_LSN(argp
->nlsn
)) {
407 if ((ret
= memp_fget(mpf
, &argp
->npgno
, 0, &np
)) != 0) {
408 (void)__db_pgerr(file_dbp
, argp
->npgno
);
412 if (log_compare(&LSN(np
), &argp
->nlsn
) == 0) {
413 PREV_PGNO(np
) = argp
->right
;
415 if ((ret
= memp_fput(mpf
,
416 np
, DB_MPOOL_DIRTY
)) != 0)
423 * If the split page is wrong, replace its contents with the
424 * logged page contents. If the page doesn't exist, it means
425 * that the create of the page never happened, nor did any of
426 * the adds onto the page that caused the split, and there's
427 * really no undo-ing to be done.
429 if ((ret
= memp_fget(mpf
, &pgno
, 0, &pp
)) != 0) {
433 if (log_compare(lsnp
, &LSN(pp
)) == 0) {
434 memcpy(pp
, argp
->pg
.data
, argp
->pg
.size
);
435 if ((ret
= memp_fput(mpf
, pp
, DB_MPOOL_DIRTY
)) != 0)
441 * If it's a root split and the left child ever existed, update
442 * its LSN. (If it's not a root split, we've updated the left
443 * page already -- it's the same as the split page.) If the
444 * right child ever existed, root split or not, update its LSN.
445 * The undo of the page allocation(s) will restore them to the
448 lrundo
: if ((rootsplit
&& lp
!= NULL
) || rp
!= NULL
) {
449 if (rootsplit
&& lp
!= NULL
&&
450 log_compare(lsnp
, &LSN(lp
)) == 0) {
451 lp
->lsn
= argp
->llsn
;
453 memp_fput(mpf
, lp
, DB_MPOOL_DIRTY
)) != 0)
458 log_compare(lsnp
, &LSN(rp
)) == 0) {
459 rp
->lsn
= argp
->rlsn
;
461 memp_fput(mpf
, rp
, DB_MPOOL_DIRTY
)) != 0)
468 * Finally, undo the next-page link if necessary. This is of
469 * interest only if it wasn't a root split -- inserting a new
470 * page in the tree requires that any following page have its
471 * previous-page pointer updated to our new page. Since it's
472 * possible that the next-page never existed, we ignore it as
473 * if there's nothing to undo.
475 if (!rootsplit
&& !IS_ZERO_LSN(argp
->nlsn
)) {
476 if ((ret
= memp_fget(mpf
, &argp
->npgno
, 0, &np
)) != 0) {
480 if (log_compare(lsnp
, &LSN(np
)) == 0) {
481 PREV_PGNO(np
) = argp
->left
;
482 np
->lsn
= argp
->nlsn
;
483 if (memp_fput(mpf
, np
, DB_MPOOL_DIRTY
))
490 done
: *lsnp
= argp
->prev_lsn
;
494 fatal
: (void)__db_panic(file_dbp
);
496 out
: /* Free any pages that weren't dirtied. */
497 if (pp
!= NULL
&& (t_ret
= memp_fput(mpf
, pp
, 0)) != 0 && ret
== 0)
499 if (lp
!= NULL
&& (t_ret
= memp_fput(mpf
, lp
, 0)) != 0 && ret
== 0)
501 if (np
!= NULL
&& (t_ret
= memp_fput(mpf
, np
, 0)) != 0 && ret
== 0)
503 if (rp
!= NULL
&& (t_ret
= memp_fput(mpf
, rp
, 0)) != 0 && ret
== 0)
506 /* Free any allocated space. */
516 * __bam_rsplit_recover --
517 * Recovery function for a reverse split.
519 * PUBLIC: int __bam_rsplit_recover
520 * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
523 __bam_rsplit_recover(logp
, dbtp
, lsnp
, redo
, info
)
530 __bam_rsplit_args
*argp
;
535 int cmp_n
, cmp_p
, modified
, ret
;
537 REC_PRINT(__bam_rsplit_print
);
538 REC_INTRO(__bam_rsplit_read
);
540 /* Fix the root page. */
542 if ((ret
= memp_fget(mpf
, &pgno
, 0, &pagep
)) != 0) {
543 /* The root page must always exist. */
544 __db_pgerr(file_dbp
, pgno
);
548 cmp_n
= log_compare(lsnp
, &LSN(pagep
));
549 cmp_p
= log_compare(&LSN(pagep
), &argp
->rootlsn
);
550 if (cmp_p
== 0 && redo
) {
551 /* Need to redo update described. */
552 memcpy(pagep
, argp
->pgdbt
.data
, argp
->pgdbt
.size
);
553 pagep
->pgno
= PGNO_ROOT
;
556 } else if (cmp_n
== 0 && !redo
) {
557 /* Need to undo update described. */
558 P_INIT(pagep
, file_dbp
->pgsize
, PGNO_ROOT
,
559 argp
->nrec
, PGNO_INVALID
, pagep
->level
+ 1,
560 file_dbp
->type
== DB_BTREE
? P_IBTREE
: P_IRECNO
);
561 if ((ret
= __db_pitem(file_dbp
, pagep
, 0,
562 argp
->rootent
.size
, &argp
->rootent
, NULL
)) != 0)
564 pagep
->lsn
= argp
->rootlsn
;
567 if ((ret
= memp_fput(mpf
, pagep
, modified
? DB_MPOOL_DIRTY
: 0)) != 0) {
568 (void)__db_panic(file_dbp
);
573 * Fix the page copied over the root page. It's possible that the
574 * page never made it to disk, so if we're undo-ing and the page
575 * doesn't exist, it's okay and there's nothing further to do.
577 if ((ret
= memp_fget(mpf
, &argp
->pgno
, 0, &pagep
)) != 0) {
580 (void)__db_pgerr(file_dbp
, argp
->pgno
);
584 cmp_n
= log_compare(lsnp
, &LSN(pagep
));
585 cmp_p
= log_compare(&LSN(pagep
), &LSN(argp
->pgdbt
.data
));
586 if (cmp_p
== 0 && redo
) {
587 /* Need to redo update described. */
590 } else if (cmp_n
== 0 && !redo
) {
591 /* Need to undo update described. */
592 memcpy(pagep
, argp
->pgdbt
.data
, argp
->pgdbt
.size
);
595 if ((ret
= memp_fput(mpf
, pagep
, modified
? DB_MPOOL_DIRTY
: 0)) != 0) {
596 (void)__db_panic(file_dbp
);
600 done
: *lsnp
= argp
->prev_lsn
;
607 * __bam_adj_recover --
608 * Recovery function for adj.
610 * PUBLIC: int __bam_adj_recover
611 * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
614 __bam_adj_recover(logp
, dbtp
, lsnp
, redo
, info
)
621 __bam_adj_args
*argp
;
625 int cmp_n
, cmp_p
, modified
, ret
;
627 REC_PRINT(__bam_adj_print
);
628 REC_INTRO(__bam_adj_read
);
630 /* Get the page; if it never existed and we're undoing, we're done. */
631 if ((ret
= memp_fget(mpf
, &argp
->pgno
, 0, &pagep
)) != 0) {
634 (void)__db_pgerr(file_dbp
, argp
->pgno
);
639 cmp_n
= log_compare(lsnp
, &LSN(pagep
));
640 cmp_p
= log_compare(&LSN(pagep
), &argp
->lsn
);
641 if (cmp_p
== 0 && redo
) {
642 /* Need to redo update described. */
643 if ((ret
= __bam_adjindx(file_dbp
,
644 pagep
, argp
->indx
, argp
->indx_copy
, argp
->is_insert
)) != 0)
649 } else if (cmp_n
== 0 && !redo
) {
650 /* Need to undo update described. */
651 if ((ret
= __bam_adjindx(file_dbp
,
652 pagep
, argp
->indx
, argp
->indx_copy
, !argp
->is_insert
)) != 0)
655 LSN(pagep
) = argp
->lsn
;
658 if ((ret
= memp_fput(mpf
, pagep
, modified
? DB_MPOOL_DIRTY
: 0)) != 0)
661 done
: *lsnp
= argp
->prev_lsn
;
665 err
: (void)memp_fput(mpf
, pagep
, 0);
671 * __bam_cadjust_recover --
672 * Recovery function for the adjust of a count change in an internal
675 * PUBLIC: int __bam_cadjust_recover
676 * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
679 __bam_cadjust_recover(logp
, dbtp
, lsnp
, redo
, info
)
686 __bam_cadjust_args
*argp
;
690 int cmp_n
, cmp_p
, modified
, ret
;
692 REC_PRINT(__bam_cadjust_print
);
693 REC_INTRO(__bam_cadjust_read
);
695 /* Get the page; if it never existed and we're undoing, we're done. */
696 if ((ret
= memp_fget(mpf
, &argp
->pgno
, 0, &pagep
)) != 0) {
699 (void)__db_pgerr(file_dbp
, argp
->pgno
);
704 cmp_n
= log_compare(lsnp
, &LSN(pagep
));
705 cmp_p
= log_compare(&LSN(pagep
), &argp
->lsn
);
706 if (cmp_p
== 0 && redo
) {
707 /* Need to redo update described. */
708 if (file_dbp
->type
== DB_BTREE
&&
709 F_ISSET(file_dbp
, DB_BT_RECNUM
)) {
710 GET_BINTERNAL(pagep
, argp
->indx
)->nrecs
+= argp
->adjust
;
711 if (argp
->total
&& PGNO(pagep
) == PGNO_ROOT
)
712 RE_NREC_ADJ(pagep
, argp
->adjust
);
714 if (file_dbp
->type
== DB_RECNO
) {
715 GET_RINTERNAL(pagep
, argp
->indx
)->nrecs
+= argp
->adjust
;
716 if (argp
->total
&& PGNO(pagep
) == PGNO_ROOT
)
717 RE_NREC_ADJ(pagep
, argp
->adjust
);
722 } else if (cmp_n
== 0 && !redo
) {
723 /* Need to undo update described. */
724 if (file_dbp
->type
== DB_BTREE
&&
725 F_ISSET(file_dbp
, DB_BT_RECNUM
)) {
726 GET_BINTERNAL(pagep
, argp
->indx
)->nrecs
-= argp
->adjust
;
727 if (argp
->total
&& PGNO(pagep
) == PGNO_ROOT
)
728 RE_NREC_ADJ(pagep
, argp
->adjust
);
730 if (file_dbp
->type
== DB_RECNO
) {
731 GET_RINTERNAL(pagep
, argp
->indx
)->nrecs
-= argp
->adjust
;
732 if (argp
->total
&& PGNO(pagep
) == PGNO_ROOT
)
733 RE_NREC_ADJ(pagep
, -(argp
->adjust
));
735 LSN(pagep
) = argp
->lsn
;
738 if ((ret
= memp_fput(mpf
, pagep
, modified
? DB_MPOOL_DIRTY
: 0)) != 0)
741 done
: *lsnp
= argp
->prev_lsn
;
748 * __bam_cdel_recover --
749 * Recovery function for the intent-to-delete of a cursor record.
751 * PUBLIC: int __bam_cdel_recover
752 * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
755 __bam_cdel_recover(logp
, dbtp
, lsnp
, redo
, info
)
762 __bam_cdel_args
*argp
;
766 int cmp_n
, cmp_p
, modified
, ret
;
768 REC_PRINT(__bam_cdel_print
);
769 REC_INTRO(__bam_cdel_read
);
771 /* Get the page; if it never existed and we're undoing, we're done. */
772 if ((ret
= memp_fget(mpf
, &argp
->pgno
, 0, &pagep
)) != 0) {
775 (void)__db_pgerr(file_dbp
, argp
->pgno
);
780 cmp_n
= log_compare(lsnp
, &LSN(pagep
));
781 cmp_p
= log_compare(&LSN(pagep
), &argp
->lsn
);
782 if (cmp_p
== 0 && redo
) {
783 /* Need to redo update described. */
784 B_DSET(GET_BKEYDATA(pagep
, argp
->indx
+ O_INDX
)->type
);
788 } else if (cmp_n
== 0 && !redo
) {
789 /* Need to undo update described. */
790 B_DCLR(GET_BKEYDATA(pagep
, argp
->indx
+ O_INDX
)->type
);
792 LSN(pagep
) = argp
->lsn
;
795 if ((ret
= memp_fput(mpf
, pagep
, modified
? DB_MPOOL_DIRTY
: 0)) != 0)
798 done
: *lsnp
= argp
->prev_lsn
;
805 * __bam_repl_recover --
806 * Recovery function for page item replacement.
808 * PUBLIC: int __bam_repl_recover
809 * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
812 __bam_repl_recover(logp
, dbtp
, lsnp
, redo
, info
)
819 __bam_repl_args
*argp
;
825 int cmp_n
, cmp_p
, modified
, ret
;
828 REC_PRINT(__bam_repl_print
);
829 REC_INTRO(__bam_repl_read
);
831 /* Get the page; if it never existed and we're undoing, we're done. */
832 if ((ret
= memp_fget(mpf
, &argp
->pgno
, 0, &pagep
)) != 0) {
835 (void)__db_pgerr(file_dbp
, argp
->pgno
);
838 bk
= GET_BKEYDATA(pagep
, argp
->indx
);
841 cmp_n
= log_compare(lsnp
, &LSN(pagep
));
842 cmp_p
= log_compare(&LSN(pagep
), &argp
->lsn
);
843 if (cmp_p
== 0 && redo
) {
845 * Need to redo update described.
847 * Re-build the replacement item.
849 memset(&dbt
, 0, sizeof(dbt
));
850 dbt
.size
= argp
->prefix
+ argp
->suffix
+ argp
->repl
.size
;
851 if ((dbt
.data
= __db_malloc(dbt
.size
)) == NULL
) {
856 memcpy(p
, bk
->data
, argp
->prefix
);
858 memcpy(p
, argp
->repl
.data
, argp
->repl
.size
);
859 p
+= argp
->repl
.size
;
860 memcpy(p
, bk
->data
+ (bk
->len
- argp
->suffix
), argp
->suffix
);
862 ret
= __bam_ritem(file_dbp
, pagep
, argp
->indx
, &dbt
);
869 } else if (cmp_n
== 0 && !redo
) {
871 * Need to undo update described.
873 * Re-build the original item.
875 memset(&dbt
, 0, sizeof(dbt
));
876 dbt
.size
= argp
->prefix
+ argp
->suffix
+ argp
->orig
.size
;
877 if ((dbt
.data
= __db_malloc(dbt
.size
)) == NULL
) {
882 memcpy(p
, bk
->data
, argp
->prefix
);
884 memcpy(p
, argp
->orig
.data
, argp
->orig
.size
);
885 p
+= argp
->orig
.size
;
886 memcpy(p
, bk
->data
+ (bk
->len
- argp
->suffix
), argp
->suffix
);
888 ret
= __bam_ritem(file_dbp
, pagep
, argp
->indx
, &dbt
);
893 /* Reset the deleted flag, if necessary. */
895 B_DSET(GET_BKEYDATA(pagep
, argp
->indx
)->type
);
897 LSN(pagep
) = argp
->lsn
;
900 if ((ret
= memp_fput(mpf
, pagep
, modified
? DB_MPOOL_DIRTY
: 0)) != 0)
903 done
: *lsnp
= argp
->prev_lsn
;
907 err
: (void)memp_fput(mpf
, pagep
, 0);