#include "db_config.h"
#ifndef lint
static const char revid[] = "$Id: db_rec.c,v 1.2 2004/03/30 01:21:24 jtownsen Exp $";
#endif
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <string.h>
#endif
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/db_shash.h"
#include "dbinc/log.h"
#include "dbinc/mp.h"
#include "dbinc/hash.h"
static int __db_pg_free_recover_int __P((DB_ENV *,
__db_pg_freedata_args *, DB *, DB_LSN *, DB_MPOOLFILE *, db_recops, int));
int
__db_addrem_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
__db_addrem_args *argp;
DB *file_dbp;
DBC *dbc;
DB_MPOOLFILE *mpf;
PAGE *pagep;
u_int32_t change;
int cmp_n, cmp_p, ret;
pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__db_addrem_print);
REC_INTRO(__db_addrem_read, 1);
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op)) {
goto done;
} else
if ((ret = __memp_fget(mpf,
&argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->pagelsn);
change = 0;
if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_DUP) ||
(cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_REM_DUP)) {
if ((ret = __db_pitem(dbc, pagep, argp->indx, argp->nbytes,
argp->hdr.size == 0 ? NULL : &argp->hdr,
argp->dbt.size == 0 ? NULL : &argp->dbt)) != 0)
goto out;
change = DB_MPOOL_DIRTY;
} else if ((cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_ADD_DUP) ||
(cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_REM_DUP)) {
if ((ret = __db_ditem(dbc,
pagep, argp->indx, argp->nbytes)) != 0)
goto out;
change = DB_MPOOL_DIRTY;
}
if (change) {
if (DB_REDO(op))
LSN(pagep) = *lsnp;
else
LSN(pagep) = argp->pagelsn;
}
if ((ret = __memp_fput(mpf, pagep, change)) != 0)
goto out;
pagep = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
out: if (pagep != NULL)
(void)__memp_fput(mpf, pagep, 0);
REC_CLOSE;
}
int
__db_big_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
__db_big_args *argp;
DB *file_dbp;
DBC *dbc;
DB_MPOOLFILE *mpf;
PAGE *pagep;
u_int32_t change;
int cmp_n, cmp_p, ret;
pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__db_big_print);
REC_INTRO(__db_big_read, 1);
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op)) {
ret = 0;
goto ppage;
} else
if ((ret = __memp_fget(mpf,
&argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->pagelsn);
change = 0;
if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_BIG) ||
(cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_REM_BIG)) {
P_INIT(pagep, file_dbp->pgsize, argp->pgno, argp->prev_pgno,
argp->next_pgno, 0, P_OVERFLOW);
OV_LEN(pagep) = argp->dbt.size;
OV_REF(pagep) = 1;
memcpy((u_int8_t *)pagep + P_OVERHEAD(file_dbp), argp->dbt.data,
argp->dbt.size);
PREV_PGNO(pagep) = argp->prev_pgno;
change = DB_MPOOL_DIRTY;
} else if ((cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_ADD_BIG) ||
(cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_REM_BIG)) {
change = DB_MPOOL_DIRTY;
}
if (change)
LSN(pagep) = DB_REDO(op) ? *lsnp : argp->pagelsn;
if ((ret = __memp_fput(mpf, pagep, change)) != 0)
goto out;
pagep = NULL;
if (argp->opcode == DB_REM_BIG)
goto done;
ppage: if (argp->prev_pgno != PGNO_INVALID) {
change = 0;
if ((ret =
__memp_fget(mpf, &argp->prev_pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op)) {
*lsnp = argp->prev_lsn;
ret = 0;
goto npage;
} else
if ((ret = __memp_fget(mpf, &argp->prev_pgno,
DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->prevlsn);
if (cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_BIG) {
NEXT_PGNO(pagep) = argp->pgno;
change = DB_MPOOL_DIRTY;
} else if (cmp_n == 0 &&
DB_UNDO(op) && argp->opcode == DB_ADD_BIG) {
NEXT_PGNO(pagep) = argp->next_pgno;
change = DB_MPOOL_DIRTY;
}
if (change)
LSN(pagep) = DB_REDO(op) ? *lsnp : argp->prevlsn;
if ((ret = __memp_fput(mpf, pagep, change)) != 0)
goto out;
}
pagep = NULL;
npage: if (argp->next_pgno != PGNO_INVALID) {
change = 0;
if ((ret =
__memp_fget(mpf, &argp->next_pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op)) {
goto done;
} else
if ((ret = __memp_fget(mpf, &argp->next_pgno,
DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
}
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->nextlsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->nextlsn);
if (cmp_p == 0 && DB_REDO(op)) {
PREV_PGNO(pagep) = PGNO_INVALID;
change = DB_MPOOL_DIRTY;
} else if (cmp_n == 0 && DB_UNDO(op)) {
PREV_PGNO(pagep) = argp->pgno;
change = DB_MPOOL_DIRTY;
}
if (change)
LSN(pagep) = DB_REDO(op) ? *lsnp : argp->nextlsn;
if ((ret = __memp_fput(mpf, pagep, change)) != 0)
goto out;
}
pagep = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
out: if (pagep != NULL)
(void)__memp_fput(mpf, pagep, 0);
REC_CLOSE;
}
int
__db_ovref_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
__db_ovref_args *argp;
DB *file_dbp;
DBC *dbc;
DB_MPOOLFILE *mpf;
PAGE *pagep;
int cmp, modified, ret;
pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__db_ovref_print);
REC_INTRO(__db_ovref_read, 1);
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (DB_UNDO(op))
goto done;
ret = __db_pgerr(file_dbp, argp->pgno, ret);
goto out;
}
modified = 0;
cmp = log_compare(&LSN(pagep), &argp->lsn);
CHECK_LSN(op, cmp, &LSN(pagep), &argp->lsn);
if (cmp == 0 && DB_REDO(op)) {
OV_REF(pagep) += argp->adjust;
pagep->lsn = *lsnp;
modified = 1;
} else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
OV_REF(pagep) -= argp->adjust;
pagep->lsn = argp->lsn;
modified = 1;
}
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
pagep = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
out: if (pagep != NULL)
(void)__memp_fput(mpf, pagep, 0);
REC_CLOSE;
}
int
__db_relink_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
__db_relink_args *argp;
DB *file_dbp;
DBC *dbc;
DB_MPOOLFILE *mpf;
PAGE *pagep;
int cmp_n, cmp_p, modified, ret;
pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__db_relink_print);
REC_INTRO(__db_relink_read, 1);
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (DB_REDO(op)) {
ret = __db_pgerr(file_dbp, argp->pgno, ret);
goto out;
}
goto next2;
}
modified = 0;
if (argp->opcode == DB_ADD_PAGE)
goto next1;
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
if (cmp_p == 0 && DB_REDO(op)) {
pagep->lsn = *lsnp;
modified = 1;
} else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
pagep->next_pgno = argp->next;
pagep->prev_pgno = argp->prev;
pagep->lsn = argp->lsn;
modified = 1;
}
next1: if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
pagep = NULL;
next2: if ((ret = __memp_fget(mpf, &argp->next, 0, &pagep)) != 0) {
if (DB_REDO(op)) {
ret = __db_pgerr(file_dbp, argp->next, ret);
goto out;
}
goto prev;
}
modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->lsn_next);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn_next);
if ((argp->opcode == DB_REM_PAGE && cmp_p == 0 && DB_REDO(op)) ||
(argp->opcode == DB_ADD_PAGE && cmp_n == 0 && DB_UNDO(op))) {
pagep->prev_pgno = argp->prev;
modified = 1;
} else if ((argp->opcode == DB_REM_PAGE && cmp_n == 0 && DB_UNDO(op)) ||
(argp->opcode == DB_ADD_PAGE && cmp_p == 0 && DB_REDO(op))) {
pagep->prev_pgno = argp->pgno;
modified = 1;
}
if (modified == 1) {
if (DB_UNDO(op))
pagep->lsn = argp->lsn_next;
else
pagep->lsn = *lsnp;
}
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
pagep = NULL;
if (argp->opcode == DB_ADD_PAGE)
goto done;
prev: if ((ret = __memp_fget(mpf, &argp->prev, 0, &pagep)) != 0) {
if (DB_REDO(op)) {
ret = __db_pgerr(file_dbp, argp->prev, ret);
goto out;
}
goto done;
}
modified = 0;
cmp_p = log_compare(&LSN(pagep), &argp->lsn_prev);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn_prev);
if (cmp_p == 0 && DB_REDO(op)) {
pagep->next_pgno = argp->next;
modified = 1;
} else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
pagep->next_pgno = argp->pgno;
modified = 1;
}
if (modified == 1) {
if (DB_UNDO(op))
pagep->lsn = argp->lsn_prev;
else
pagep->lsn = *lsnp;
}
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
pagep = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
out: if (pagep != NULL)
(void)__memp_fput(mpf, pagep, 0);
REC_CLOSE;
}
int
__db_debug_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
__db_debug_args *argp;
int ret;
COMPQUIET(dbenv, NULL);
COMPQUIET(op, DB_TXN_ABORT);
COMPQUIET(info, NULL);
REC_PRINT(__db_debug_print);
REC_NOOP_INTRO(__db_debug_read);
*lsnp = argp->prev_lsn;
ret = 0;
REC_NOOP_CLOSE;
}
int
__db_noop_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
__db_noop_args *argp;
DB *file_dbp;
DBC *dbc;
DB_MPOOLFILE *mpf;
PAGE *pagep;
u_int32_t change;
int cmp_n, cmp_p, ret;
pagep = NULL;
COMPQUIET(info, NULL);
REC_PRINT(__db_noop_print);
REC_INTRO(__db_noop_read, 0);
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0)
goto out;
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->prevlsn);
change = 0;
if (cmp_p == 0 && DB_REDO(op)) {
LSN(pagep) = *lsnp;
change = DB_MPOOL_DIRTY;
} else if (cmp_n == 0 && DB_UNDO(op)) {
LSN(pagep) = argp->prevlsn;
change = DB_MPOOL_DIRTY;
}
ret = __memp_fput(mpf, pagep, change);
pagep = NULL;
done: *lsnp = argp->prev_lsn;
out: if (pagep != NULL)
(void)__memp_fput(mpf, pagep, 0);
REC_CLOSE;
}
int
__db_pg_alloc_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
__db_pg_alloc_args *argp;
DB *file_dbp;
DBC *dbc;
DBMETA *meta;
DB_MPOOLFILE *mpf;
PAGE *pagep;
db_pgno_t pgno;
int cmp_n, cmp_p, created, level, modified, ret;
meta = NULL;
pagep = NULL;
REC_PRINT(__db_pg_alloc_print);
REC_INTRO(__db_pg_alloc_read, 0);
pgno = PGNO_BASE_MD;
if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0) {
if (DB_REDO(op)) {
ret = __db_pgerr(file_dbp, pgno, ret);
goto out;
} else
goto done;
}
created = modified = 0;
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
if ((ret = __memp_fget(
mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) {
if (ret == ENOSPC)
goto do_meta;
ret = __db_pgerr(file_dbp, argp->pgno, ret);
goto out;
}
created = modified = 1;
}
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->page_lsn);
if (IS_ZERO_LSN(LSN(pagep)))
cmp_p = 0;
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->page_lsn);
if (DB_REDO(op) &&
(cmp_p == 0 ||
(IS_ZERO_LSN(argp->page_lsn) && IS_INIT_LSN(LSN(pagep))))) {
switch (argp->ptype) {
case P_LBTREE:
case P_LRECNO:
case P_LDUP:
level = LEAFLEVEL;
break;
default:
level = 0;
break;
}
P_INIT(pagep, file_dbp->pgsize,
argp->pgno, PGNO_INVALID, PGNO_INVALID, level, argp->ptype);
pagep->lsn = *lsnp;
modified = 1;
} else if (DB_UNDO(op) && (cmp_n == 0 || created)) {
P_INIT(pagep, file_dbp->pgsize,
argp->pgno, PGNO_INVALID, argp->next, 0, P_INVALID);
pagep->lsn = argp->page_lsn;
modified = 1;
}
if (IS_ZERO_LSN(LSN(pagep)) &&
IS_ZERO_LSN(argp->page_lsn) && DB_UNDO(op)) {
if ((ret = __db_add_limbo(dbenv,
info, argp->fileid, argp->pgno, 1)) != 0)
goto out;
}
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
pagep = NULL;
do_meta:
modified = 0;
cmp_n = log_compare(lsnp, &LSN(meta));
cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn);
if (cmp_p == 0 && DB_REDO(op)) {
LSN(meta) = *lsnp;
meta->free = argp->next;
modified = 1;
} else if (cmp_n == 0 && DB_UNDO(op)) {
LSN(meta) = argp->meta_lsn;
if (!IS_ZERO_LSN(argp->page_lsn))
meta->free = argp->pgno;
modified = 1;
}
if (argp->pgno > meta->last_pgno) {
meta->last_pgno = argp->pgno;
modified = 1;
}
if ((ret = __memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
meta = NULL;
done: *lsnp = argp->prev_lsn;
ret = 0;
out: if (pagep != NULL)
(void)__memp_fput(mpf, pagep, 0);
if (meta != NULL)
(void)__memp_fput(mpf, meta, 0);
if (ret == ENOENT && op == DB_TXN_BACKWARD_ALLOC)
ret = 0;
REC_CLOSE;
}
static int
__db_pg_free_recover_int(dbenv, argp, file_dbp, lsnp, mpf, op, data)
DB_ENV *dbenv;
__db_pg_freedata_args *argp;
DB *file_dbp;
DB_LSN *lsnp;
DB_MPOOLFILE *mpf;
db_recops op;
int data;
{
DBMETA *meta;
DB_LSN copy_lsn;
PAGE *pagep;
db_pgno_t pgno;
int cmp_n, cmp_p, modified, ret;
meta = NULL;
pagep = NULL;
if ((ret = __memp_fget(mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
modified = 0;
(void)__ua_memcpy(©_lsn, &LSN(argp->header.data), sizeof(DB_LSN));
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), ©_lsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), ©_lsn);
if (DB_REDO(op) &&
(cmp_p == 0 ||
(IS_ZERO_LSN(copy_lsn) &&
log_compare(&LSN(pagep), &argp->meta_lsn) <= 0))) {
P_INIT(pagep, file_dbp->pgsize,
argp->pgno, PGNO_INVALID, argp->next, 0, P_INVALID);
pagep->lsn = *lsnp;
modified = 1;
} else if (cmp_n == 0 && DB_UNDO(op)) {
memcpy(pagep, argp->header.data, argp->header.size);
if (data)
memcpy((u_int8_t*)pagep + pagep->hf_offset,
argp->data.data, argp->data.size);
modified = 1;
}
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
pagep = NULL;
pgno = PGNO_BASE_MD;
if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0) {
ret = __db_pgerr(file_dbp, pgno, ret);
goto out;
}
modified = 0;
cmp_n = log_compare(lsnp, &LSN(meta));
cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn);
if (cmp_p == 0 && DB_REDO(op)) {
meta->free = argp->pgno;
if (meta->last_pgno < meta->free)
meta->last_pgno = meta->free;
LSN(meta) = *lsnp;
modified = 1;
} else if (cmp_n == 0 && DB_UNDO(op)) {
meta->free = argp->next;
LSN(meta) = argp->meta_lsn;
modified = 1;
}
if ((ret = __memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
meta = NULL;
*lsnp = argp->prev_lsn;
ret = 0;
out: if (pagep != NULL)
(void)__memp_fput(mpf, pagep, 0);
if (meta != NULL)
(void)__memp_fput(mpf, meta, 0);
return (ret);
}
int
__db_pg_free_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
DB *file_dbp;
DBC *dbc;
DB_MPOOLFILE *mpf;
__db_pg_free_args *argp;
int ret;
COMPQUIET(info, NULL);
REC_PRINT(__db_pg_free_print);
REC_INTRO(__db_pg_free_read, 1);
ret = __db_pg_free_recover_int(dbenv,
(__db_pg_freedata_args *)argp, file_dbp, lsnp, mpf, op, 0);
done:
out:
REC_CLOSE;
}
int
__db_pg_new_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
DB *file_dbp;
DBC *dbc;
DB_MPOOLFILE *mpf;
__db_pg_free_args *argp;
int ret;
REC_PRINT(__db_pg_free_print);
REC_INTRO(__db_pg_free_read, 1);
COMPQUIET(op, 0);
if ((ret =
__db_add_limbo(dbenv, info, argp->fileid, argp->pgno, 1)) == 0)
*lsnp = argp->prev_lsn;
done:
out:
REC_CLOSE;
}
int
__db_pg_freedata_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
DB *file_dbp;
DBC *dbc;
DB_MPOOLFILE *mpf;
__db_pg_freedata_args *argp;
int ret;
COMPQUIET(info, NULL);
REC_PRINT(__db_pg_freedata_print);
REC_INTRO(__db_pg_freedata_read, 1);
ret = __db_pg_free_recover_int(dbenv, argp, file_dbp, lsnp, mpf, op, 1);
done:
out:
REC_CLOSE;
}
int
__db_cksum_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
__db_cksum_args *argp;
int ret;
COMPQUIET(info, NULL);
COMPQUIET(lsnp, NULL);
COMPQUIET(op, DB_TXN_ABORT);
REC_PRINT(__db_cksum_print);
if ((ret = __db_cksum_read(dbenv, dbtp->data, &argp)) != 0)
return (ret);
if (F_ISSET(dbenv, DB_ENV_FATAL))
ret = 0;
else {
__db_err(dbenv,
"Checksum failure requires catastrophic recovery");
ret = __db_panic(dbenv, DB_RUNRECOVERY);
}
__os_free(dbenv, argp);
return (ret);
}
int
__db_pg_prepare_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
__db_pg_prepare_args *argp;
DB *file_dbp;
DBC *dbc;
DB_MPOOLFILE *mpf;
PAGE *pagep;
int ret, t_ret;
REC_PRINT(__db_pg_prepare_print);
REC_INTRO(__db_pg_prepare_read, 1);
mpf = file_dbp->mpf;
if (op == DB_TXN_ABORT) {
if ((ret = __memp_fget(
mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
goto out;
P_INIT(pagep, file_dbp->pgsize,
argp->pgno, PGNO_INVALID, PGNO_INVALID, 0, P_INVALID);
ZERO_LSN(pagep->lsn);
ret = __db_add_limbo(dbenv, info, argp->fileid, argp->pgno, 1);
if ((t_ret =
__memp_fput(mpf, pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
ret = t_ret;
}
done: if (ret == 0)
*lsnp = argp->prev_lsn;
out: REC_CLOSE;
}