2
* See the file LICENSE for redistribution information.
4
* Copyright (c) 1996-2002
5
* Sleepycat Software. All rights reserved.
11
static const char revid[] = "$Id$";
14
#ifndef NO_SYSTEM_INCLUDES
15
#include <sys/types.h>
21
#include "dbinc/db_page.h"
22
#include "dbinc/log.h"
23
#include "dbinc/hash.h"
26
* PUBLIC: int __db_addrem_recover
27
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
29
* This log message is generated whenever we add or remove a duplicate
30
* to/from a duplicate page. On recover, we just do the opposite.
33
__db_addrem_recover(dbenv, dbtp, lsnp, op, info)
40
__db_addrem_args *argp;
46
int cmp_n, cmp_p, ret;
49
COMPQUIET(info, NULL);
50
REC_PRINT(__db_addrem_print);
51
REC_INTRO(__db_addrem_read, 1);
53
if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
56
* We are undoing and the page doesn't exist. That
57
* is equivalent to having a pagelsn of 0, so we
58
* would not have to undo anything. In this case,
59
* don't bother creating a page.
63
if ((ret = mpf->get(mpf,
64
&argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
68
cmp_n = log_compare(lsnp, &LSN(pagep));
69
cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
70
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->pagelsn);
72
if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_DUP) ||
73
(cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_REM_DUP)) {
75
/* Need to redo an add, or undo a delete. */
76
if ((ret = __db_pitem(dbc, pagep, argp->indx, argp->nbytes,
77
argp->hdr.size == 0 ? NULL : &argp->hdr,
78
argp->dbt.size == 0 ? NULL : &argp->dbt)) != 0)
81
change = DB_MPOOL_DIRTY;
83
} else if ((cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_ADD_DUP) ||
84
(cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_REM_DUP)) {
85
/* Need to undo an add, or redo a delete. */
86
if ((ret = __db_ditem(dbc,
87
pagep, argp->indx, argp->nbytes)) != 0)
89
change = DB_MPOOL_DIRTY;
96
LSN(pagep) = argp->pagelsn;
99
if ((ret = mpf->put(mpf, pagep, change)) != 0)
103
done: *lsnp = argp->prev_lsn;
106
out: if (pagep != NULL)
107
(void)mpf->put(mpf, pagep, 0);
112
* PUBLIC: int __db_big_recover
113
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
116
__db_big_recover(dbenv, dbtp, lsnp, op, info)
129
int cmp_n, cmp_p, ret;
132
COMPQUIET(info, NULL);
133
REC_PRINT(__db_big_print);
134
REC_INTRO(__db_big_read, 1);
136
if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
139
* We are undoing and the page doesn't exist. That
140
* is equivalent to having a pagelsn of 0, so we
141
* would not have to undo anything. In this case,
142
* don't bother creating a page.
147
if ((ret = mpf->get(mpf,
148
&argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
153
* There are three pages we need to check. The one on which we are
154
* adding data, the previous one whose next_pointer may have
155
* been updated, and the next one whose prev_pointer may have
158
cmp_n = log_compare(lsnp, &LSN(pagep));
159
cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
160
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->pagelsn);
162
if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_BIG) ||
163
(cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_REM_BIG)) {
164
/* We are either redo-ing an add, or undoing a delete. */
165
P_INIT(pagep, file_dbp->pgsize, argp->pgno, argp->prev_pgno,
166
argp->next_pgno, 0, P_OVERFLOW);
167
OV_LEN(pagep) = argp->dbt.size;
169
memcpy((u_int8_t *)pagep + P_OVERHEAD(file_dbp), argp->dbt.data,
171
PREV_PGNO(pagep) = argp->prev_pgno;
172
change = DB_MPOOL_DIRTY;
173
} else if ((cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_ADD_BIG) ||
174
(cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_REM_BIG)) {
176
* We are either undo-ing an add or redo-ing a delete.
177
* The page is about to be reclaimed in either case, so
178
* there really isn't anything to do here.
180
change = DB_MPOOL_DIRTY;
183
LSN(pagep) = DB_REDO(op) ? *lsnp : argp->pagelsn;
185
if ((ret = mpf->put(mpf, pagep, change)) != 0)
190
* We only delete a whole chain of overflow.
191
* Each page is handled individually
193
if (argp->opcode == DB_REM_BIG)
196
/* Now check the previous page. */
197
ppage: if (argp->prev_pgno != PGNO_INVALID) {
199
if ((ret = mpf->get(mpf, &argp->prev_pgno, 0, &pagep)) != 0) {
202
* We are undoing and the page doesn't exist.
203
* That is equivalent to having a pagelsn of 0,
204
* so we would not have to undo anything. In
205
* this case, don't bother creating a page.
207
*lsnp = argp->prev_lsn;
211
if ((ret = mpf->get(mpf, &argp->prev_pgno,
212
DB_MPOOL_CREATE, &pagep)) != 0)
216
cmp_n = log_compare(lsnp, &LSN(pagep));
217
cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);
218
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->prevlsn);
220
if (cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_BIG) {
221
/* Redo add, undo delete. */
222
NEXT_PGNO(pagep) = argp->pgno;
223
change = DB_MPOOL_DIRTY;
224
} else if (cmp_n == 0 &&
225
DB_UNDO(op) && argp->opcode == DB_ADD_BIG) {
226
/* Redo delete, undo add. */
227
NEXT_PGNO(pagep) = argp->next_pgno;
228
change = DB_MPOOL_DIRTY;
231
LSN(pagep) = DB_REDO(op) ? *lsnp : argp->prevlsn;
232
if ((ret = mpf->put(mpf, pagep, change)) != 0)
237
/* Now check the next page. Can only be set on a delete. */
238
npage: if (argp->next_pgno != PGNO_INVALID) {
240
if ((ret = mpf->get(mpf, &argp->next_pgno, 0, &pagep)) != 0) {
243
* We are undoing and the page doesn't exist.
244
* That is equivalent to having a pagelsn of 0,
245
* so we would not have to undo anything. In
246
* this case, don't bother creating a page.
250
if ((ret = mpf->get(mpf, &argp->next_pgno,
251
DB_MPOOL_CREATE, &pagep)) != 0)
255
cmp_n = log_compare(lsnp, &LSN(pagep));
256
cmp_p = log_compare(&LSN(pagep), &argp->nextlsn);
257
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->nextlsn);
258
if (cmp_p == 0 && DB_REDO(op)) {
259
PREV_PGNO(pagep) = PGNO_INVALID;
260
change = DB_MPOOL_DIRTY;
261
} else if (cmp_n == 0 && DB_UNDO(op)) {
262
PREV_PGNO(pagep) = argp->pgno;
263
change = DB_MPOOL_DIRTY;
266
LSN(pagep) = DB_REDO(op) ? *lsnp : argp->nextlsn;
267
if ((ret = mpf->put(mpf, pagep, change)) != 0)
272
done: *lsnp = argp->prev_lsn;
275
out: if (pagep != NULL)
276
(void)mpf->put(mpf, pagep, 0);
281
* __db_ovref_recover --
282
* Recovery function for __db_ovref().
284
* PUBLIC: int __db_ovref_recover
285
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
288
__db_ovref_recover(dbenv, dbtp, lsnp, op, info)
295
__db_ovref_args *argp;
300
int cmp, modified, ret;
303
COMPQUIET(info, NULL);
304
REC_PRINT(__db_ovref_print);
305
REC_INTRO(__db_ovref_read, 1);
307
if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
310
__db_pgerr(file_dbp, argp->pgno, ret);
315
cmp = log_compare(&LSN(pagep), &argp->lsn);
316
CHECK_LSN(op, cmp, &LSN(pagep), &argp->lsn);
317
if (cmp == 0 && DB_REDO(op)) {
318
/* Need to redo update described. */
319
OV_REF(pagep) += argp->adjust;
323
} else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
324
/* Need to undo update described. */
325
OV_REF(pagep) -= argp->adjust;
327
pagep->lsn = argp->lsn;
330
if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
334
done: *lsnp = argp->prev_lsn;
337
out: if (pagep != NULL)
338
(void)mpf->put(mpf, pagep, 0);
343
* __db_relink_recover --
344
* Recovery function for relink.
346
* PUBLIC: int __db_relink_recover
347
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
350
__db_relink_recover(dbenv, dbtp, lsnp, op, info)
357
__db_relink_args *argp;
362
int cmp_n, cmp_p, modified, ret;
365
COMPQUIET(info, NULL);
366
REC_PRINT(__db_relink_print);
367
REC_INTRO(__db_relink_read, 1);
370
* There are up to three pages we need to check -- the page, and the
371
* previous and next pages, if they existed. For a page add operation,
372
* the current page is the result of a split and is being recovered
373
* elsewhere, so all we need do is recover the next page.
375
if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
377
__db_pgerr(file_dbp, argp->pgno, ret);
383
if (argp->opcode == DB_ADD_PAGE)
386
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
387
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
388
if (cmp_p == 0 && DB_REDO(op)) {
389
/* Redo the relink. */
392
} else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
393
/* Undo the relink. */
394
pagep->next_pgno = argp->next;
395
pagep->prev_pgno = argp->prev;
397
pagep->lsn = argp->lsn;
400
next1: if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
404
next2: if ((ret = mpf->get(mpf, &argp->next, 0, &pagep)) != 0) {
406
__db_pgerr(file_dbp, argp->next, ret);
412
cmp_n = log_compare(lsnp, &LSN(pagep));
413
cmp_p = log_compare(&LSN(pagep), &argp->lsn_next);
414
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn_next);
415
if ((argp->opcode == DB_REM_PAGE && cmp_p == 0 && DB_REDO(op)) ||
416
(argp->opcode == DB_ADD_PAGE && cmp_n == 0 && DB_UNDO(op))) {
417
/* Redo the remove or undo the add. */
418
pagep->prev_pgno = argp->prev;
421
} else if ((argp->opcode == DB_REM_PAGE && cmp_n == 0 && DB_UNDO(op)) ||
422
(argp->opcode == DB_ADD_PAGE && cmp_p == 0 && DB_REDO(op))) {
423
/* Undo the remove or redo the add. */
424
pagep->prev_pgno = argp->pgno;
430
pagep->lsn = argp->lsn_next;
434
if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
437
if (argp->opcode == DB_ADD_PAGE)
440
prev: if ((ret = mpf->get(mpf, &argp->prev, 0, &pagep)) != 0) {
442
__db_pgerr(file_dbp, argp->prev, ret);
448
cmp_p = log_compare(&LSN(pagep), &argp->lsn_prev);
449
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn_prev);
450
if (cmp_p == 0 && DB_REDO(op)) {
451
/* Redo the relink. */
452
pagep->next_pgno = argp->next;
455
} else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
456
/* Undo the relink. */
457
pagep->next_pgno = argp->pgno;
463
pagep->lsn = argp->lsn_prev;
467
if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
471
done: *lsnp = argp->prev_lsn;
474
out: if (pagep != NULL)
475
(void)mpf->put(mpf, pagep, 0);
480
* __db_debug_recover --
481
* Recovery function for debug.
483
* PUBLIC: int __db_debug_recover __P((DB_ENV *,
484
* PUBLIC: DBT *, DB_LSN *, db_recops, void *));
487
__db_debug_recover(dbenv, dbtp, lsnp, op, info)
494
__db_debug_args *argp;
497
COMPQUIET(dbenv, NULL);
498
COMPQUIET(op, DB_TXN_ABORT);
499
COMPQUIET(info, NULL);
501
REC_PRINT(__db_debug_print);
502
REC_NOOP_INTRO(__db_debug_read);
504
*lsnp = argp->prev_lsn;
511
* __db_noop_recover --
512
* Recovery function for noop.
514
* PUBLIC: int __db_noop_recover __P((DB_ENV *,
515
* PUBLIC: DBT *, DB_LSN *, db_recops, void *));
518
__db_noop_recover(dbenv, dbtp, lsnp, op, info)
525
__db_noop_args *argp;
531
int cmp_n, cmp_p, ret;
534
COMPQUIET(info, NULL);
535
REC_PRINT(__db_noop_print);
536
REC_INTRO(__db_noop_read, 0);
538
if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0)
541
cmp_n = log_compare(lsnp, &LSN(pagep));
542
cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);
543
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->prevlsn);
545
if (cmp_p == 0 && DB_REDO(op)) {
547
change = DB_MPOOL_DIRTY;
548
} else if (cmp_n == 0 && DB_UNDO(op)) {
549
LSN(pagep) = argp->prevlsn;
550
change = DB_MPOOL_DIRTY;
552
ret = mpf->put(mpf, pagep, change);
555
done: *lsnp = argp->prev_lsn;
556
out: if (pagep != NULL)
557
(void)mpf->put(mpf, pagep, 0);
562
* __db_pg_alloc_recover --
563
* Recovery function for pg_alloc.
565
* PUBLIC: int __db_pg_alloc_recover
566
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
569
__db_pg_alloc_recover(dbenv, dbtp, lsnp, op, info)
576
__db_pg_alloc_args *argp;
583
int cmp_n, cmp_p, created, level, modified, ret;
587
REC_PRINT(__db_pg_alloc_print);
588
REC_INTRO(__db_pg_alloc_read, 0);
591
* Fix up the allocated page. If we're redoing the operation, we have
592
* to get the page (creating it if it doesn't exist), and update its
593
* LSN. If we're undoing the operation, we have to reset the page's
594
* LSN and put it on the free list.
596
* Fix up the metadata page. If we're redoing the operation, we have
597
* to get the metadata page and update its LSN and its free pointer.
598
* If we're undoing the operation and the page was ever created, we put
599
* it on the freelist.
602
if ((ret = mpf->get(mpf, &pgno, 0, &meta)) != 0) {
603
/* The metadata page must always exist on redo. */
605
__db_pgerr(file_dbp, pgno, ret);
610
created = modified = 0;
611
if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) {
613
* We have to be able to identify if a page was newly
614
* created so we can recover it properly. We cannot simply
615
* look for an empty header, because hash uses a pgin
616
* function that will set the header. Instead, we explicitly
617
* try for the page without CREATE and if that fails, then
621
mpf->get(mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) {
622
__db_pgerr(file_dbp, argp->pgno, ret);
625
created = modified = 1;
628
/* Fix up the allocated page. */
629
cmp_n = log_compare(lsnp, &LSN(pagep));
630
cmp_p = log_compare(&LSN(pagep), &argp->page_lsn);
633
* If an inital allocation is aborted and then reallocated
634
* during an archival restore the log record will have
635
* an LSN for the page but the page will be empty.
637
if (IS_ZERO_LSN(LSN(pagep)))
639
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->page_lsn);
641
* If we we rolled back this allocation previously during an
642
* archive restore, the page may have the LSN of the meta page
643
* at the point of the roll back. This will be no more
644
* than the LSN of the metadata page at the time of this allocation.
645
* Another special case we have to handle is if we ended up with a
646
* page of all 0's which can happen if we abort between allocating a
647
* page in mpool and initializing it. In that case, even if we're
648
* undoing, we need to re-initialize the page.
652
(IS_ZERO_LSN(argp->page_lsn) &&
653
log_compare(&LSN(pagep), &argp->meta_lsn) <= 0))) {
654
/* Need to redo update described. */
655
switch (argp->ptype) {
665
P_INIT(pagep, file_dbp->pgsize,
666
argp->pgno, PGNO_INVALID, PGNO_INVALID, level, argp->ptype);
670
} else if (DB_UNDO(op) && (cmp_n == 0 || created)) {
672
* This is where we handle the case of a 0'd page (pagep->pgno
673
* is equal to PGNO_INVALID).
674
* Undo the allocation, reinitialize the page and
675
* link its next pointer to the free list.
677
P_INIT(pagep, file_dbp->pgsize,
678
argp->pgno, PGNO_INVALID, argp->next, 0, P_INVALID);
680
pagep->lsn = argp->page_lsn;
685
* If the page was newly created, put it on the limbo list.
687
if (IS_ZERO_LSN(LSN(pagep)) &&
688
IS_ZERO_LSN(argp->page_lsn) && DB_UNDO(op)) {
689
/* Put the page in limbo.*/
690
if ((ret = __db_add_limbo(dbenv,
691
info, argp->fileid, argp->pgno, 1)) != 0)
695
if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
699
/* Fix up the metadata page. */
701
cmp_n = log_compare(lsnp, &LSN(meta));
702
cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
703
CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn);
704
if (cmp_p == 0 && DB_REDO(op)) {
705
/* Need to redo update described. */
707
meta->free = argp->next;
709
} else if (cmp_n == 0 && DB_UNDO(op)) {
710
/* Need to undo update described. */
711
LSN(meta) = argp->meta_lsn;
714
* If the page has a zero LSN then its newly created
715
* and will go into limbo rather than directly on the
718
if (!IS_ZERO_LSN(argp->page_lsn))
719
meta->free = argp->pgno;
722
if ((ret = mpf->put(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
726
* This could be the metapage from a subdb which is read from disk
727
* to recover its creation.
729
if (F_ISSET(file_dbp, DB_AM_SUBDB))
730
switch (argp->type) {
734
file_dbp->sync(file_dbp, 0);
738
done: *lsnp = argp->prev_lsn;
741
out: if (pagep != NULL)
742
(void)mpf->put(mpf, pagep, 0);
744
(void)mpf->put(mpf, meta, 0);
745
if (ret == ENOENT && op == DB_TXN_BACKWARD_ALLOC)
751
* __db_pg_free_recover --
752
* Recovery function for pg_free.
754
* PUBLIC: int __db_pg_free_recover
755
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
758
__db_pg_free_recover(dbenv, dbtp, lsnp, op, info)
765
__db_pg_free_args *argp;
773
int cmp_n, cmp_p, modified, ret;
775
COMPQUIET(info, NULL);
778
REC_PRINT(__db_pg_free_print);
779
REC_INTRO(__db_pg_free_read, 1);
782
* Fix up the freed page. If we're redoing the operation we get the
783
* page and explicitly discard its contents, then update its LSN. If
784
* we're undoing the operation, we get the page and restore its header.
785
* Create the page if necessary, we may be freeing an aborted
788
if ((ret = mpf->get(mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
791
(void)__ua_memcpy(©_lsn, &LSN(argp->header.data), sizeof(DB_LSN));
792
cmp_n = log_compare(lsnp, &LSN(pagep));
793
cmp_p = log_compare(&LSN(pagep), ©_lsn);
794
CHECK_LSN(op, cmp_p, &LSN(pagep), ©_lsn);
797
(IS_ZERO_LSN(copy_lsn) &&
798
log_compare(&LSN(pagep), &argp->meta_lsn) <= 0))) {
799
/* Need to redo update described. */
800
P_INIT(pagep, file_dbp->pgsize,
801
argp->pgno, PGNO_INVALID, argp->next, 0, P_INVALID);
805
} else if (cmp_n == 0 && DB_UNDO(op)) {
806
/* Need to undo update described. */
807
memcpy(pagep, argp->header.data, argp->header.size);
811
if ((ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
816
* Fix up the metadata page. If we're redoing or undoing the operation
817
* we get the page and update its LSN and free pointer.
820
if ((ret = mpf->get(mpf, &pgno, 0, &meta)) != 0) {
821
/* The metadata page must always exist. */
822
__db_pgerr(file_dbp, pgno, ret);
827
cmp_n = log_compare(lsnp, &LSN(meta));
828
cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
829
CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn);
830
if (cmp_p == 0 && DB_REDO(op)) {
831
/* Need to redo the deallocation. */
832
meta->free = argp->pgno;
835
} else if (cmp_n == 0 && DB_UNDO(op)) {
836
/* Need to undo the deallocation. */
837
meta->free = argp->next;
838
LSN(meta) = argp->meta_lsn;
841
if ((ret = mpf->put(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
845
done: *lsnp = argp->prev_lsn;
848
out: if (pagep != NULL)
849
(void)mpf->put(mpf, pagep, 0);
851
(void)mpf->put(mpf, meta, 0);
856
* __db_cksum_recover --
857
* Recovery function for checksum failure log record.
859
* PUBLIC: int __db_cksum_recover __P((DB_ENV *,
860
* PUBLIC: DBT *, DB_LSN *, db_recops, void *));
863
__db_cksum_recover(dbenv, dbtp, lsnp, op, info)
870
__db_cksum_args *argp;
874
COMPQUIET(info, NULL);
875
COMPQUIET(lsnp, NULL);
876
COMPQUIET(op, DB_TXN_ABORT);
878
REC_PRINT(__db_cksum_print);
880
if ((ret = __db_cksum_read(dbenv, dbtp->data, &argp)) != 0)
884
* We had a checksum failure -- the only option is to run catastrophic
887
if (F_ISSET(dbenv, DB_ENV_FATAL))
891
"Checksum failure requires catastrophic recovery");
892
ret = __db_panic(dbenv, DB_RUNRECOVERY);
895
__os_free(dbenv, argp);