summaryrefslogtreecommitdiff
path: root/db2/common/db_apprec.c
diff options
context:
space:
mode:
Diffstat (limited to 'db2/common/db_apprec.c')
-rw-r--r--db2/common/db_apprec.c143
1 files changed, 143 insertions, 0 deletions
diff --git a/db2/common/db_apprec.c b/db2/common/db_apprec.c
new file mode 100644
index 0000000000..b22b0c5e9a
--- /dev/null
+++ b/db2/common/db_apprec.c
@@ -0,0 +1,143 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996, 1997
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1997\n\
+ Sleepycat Software Inc. All rights reserved.\n";
+static const char sccsid[] = "@(#)db_apprec.c 10.15 (Sleepycat) 7/27/97";
+#endif
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <time.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "shqueue.h"
+#include "db_page.h"
+#include "db_dispatch.h"
+#include "db_am.h"
+#include "log.h"
+#include "txn.h"
+#include "common_ext.h"
+
+/*
+ * __db_apprec --
+ * Perform recovery.
+ *
+ * PUBLIC: int __db_apprec __P((DB_ENV *, int));
+ */
+int
+__db_apprec(dbenv, flags)
+ DB_ENV *dbenv;
+ int flags;
+{
+ DBT data;
+ DB_LOG *lp;
+ DB_LSN ckp_lsn, first_lsn, lsn, tmp_lsn;
+ time_t now;
+ int first_flag, ret, tret;
+ void *txninfo;
+
+ ZERO_LSN(ckp_lsn);
+
+ /* Initialize the transaction list. */
+ if ((ret = __db_txnlist_init(&txninfo)) != 0)
+ return (ret);
+
+ /*
+ * Read forward through the log opening the appropriate files
+ * so that we can call recovery routines. In general, we start
+ * at the last checkpoint prior to the last checkpointed LSN.
+ * For catastrophic recovery, we begin at the first LSN that
+ * appears in any log file (log figures this out for us when
+ * we pass it the DB_FIRST flag).
+ */
+ lp = dbenv->lg_info;
+ if (LF_ISSET(DB_RECOVER_FATAL))
+ first_flag = DB_FIRST;
+ else
+ first_flag = __log_findckp(lp, &lsn) != 0 ? DB_FIRST : DB_SET;
+
+ memset(&data, 0, sizeof(data));
+ if ((ret = log_get(lp, &lsn, &data, first_flag)) != 0) {
+ __db_err(dbenv, "Failure: unable to get log record");
+ if (first_flag == DB_SET)
+ __db_err(dbenv, "Retrieving LSN %lu %lu",
+ (u_long)lsn.file, (u_long)lsn.offset);
+ else
+ __db_err(dbenv, "Retrieving first LSN");
+ goto err;
+ }
+
+ first_lsn = lsn;
+ for (; ret == 0;
+ ret = log_get(dbenv->lg_info, &lsn, &data, DB_NEXT))
+ if ((tret = __db_dispatch(lp,
+ &data, &lsn, TXN_OPENFILES, txninfo)) < 0) {
+ ret = tret;
+ goto msgerr;
+ }
+
+ for (ret = log_get(lp, &lsn, &data, DB_LAST);
+ ret == 0 && log_compare(&lsn, &first_lsn) > 0;
+ ret = log_get(lp,&lsn, &data, DB_PREV)) {
+ tmp_lsn = lsn;
+ tret =
+ __db_dispatch(lp, &data, &lsn, TXN_BACKWARD_ROLL, txninfo);
+ if (IS_ZERO_LSN(ckp_lsn) && tret > 0)
+ ckp_lsn = tmp_lsn;
+ if (tret < 0) {
+ ret = tret;
+ goto msgerr;
+ }
+ }
+
+ for (ret = log_get(lp, &lsn, &data, DB_NEXT);
+ ret == 0; ret = log_get(lp, &lsn, &data, DB_NEXT))
+ if ((tret = __db_dispatch(lp,
+ &data, &lsn, TXN_FORWARD_ROLL, txninfo)) < 0) {
+ ret = tret;
+ goto msgerr;
+ }
+
+ /* Now close all the db files that are open. */
+ __log_close_files(lp);
+
+ /*
+ * Now set the maximum transaction id, set the last checkpoint lsn,
+ * and the current time. Then take a checkpoint.
+ */
+ (void)time(&now);
+
+ dbenv->tx_info->region->last_txnid = ((__db_txnhead *)txninfo)->maxid;
+ dbenv->tx_info->region->last_ckp = ckp_lsn;
+ dbenv->tx_info->region->time_ckp = (u_int32_t) now;
+ txn_checkpoint(dbenv->tx_info, 0, 0);
+
+ if (dbenv->db_verbose) {
+ __db_err(lp->dbenv, "Recovery complete at %s", ctime(&now));
+ __db_err(lp->dbenv, "%s %lu %s [%lu][%lu]",
+ "Maximum transaction id",
+ (u_long)dbenv->tx_info->region->last_txnid,
+ "Recovery checkpoint",
+ (u_long)dbenv->tx_info->region->last_ckp.file,
+ (u_long)dbenv->tx_info->region->last_ckp.offset);
+ }
+
+ return (0);
+
+msgerr: __db_err(dbenv, "Recovery function for LSN %lu %lu failed",
+ (u_long)lsn.file, (u_long)lsn.offset);
+
+err: return (ret);
+}