summaryrefslogtreecommitdiff
path: root/src/db/crdel_rec.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/db/crdel_rec.c')
-rw-r--r--src/db/crdel_rec.c301
1 files changed, 301 insertions, 0 deletions
diff --git a/src/db/crdel_rec.c b/src/db/crdel_rec.c
new file mode 100644
index 00000000..08e7bae8
--- /dev/null
+++ b/src/db/crdel_rec.c
@@ -0,0 +1,301 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/fop.h"
+#include "dbinc/hash.h"
+#include "dbinc/mp.h"
+#include "dbinc/txn.h"
+
+/*
+ * __crdel_metasub_recover --
+ * Recovery function for metasub.
+ *
+ * PUBLIC: int __crdel_metasub_recover
+ * PUBLIC: __P((ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__crdel_metasub_recover(env, dbtp, lsnp, op, info)
+ ENV *env;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops op;
+ void *info;
+{
+ __crdel_metasub_args *argp;
+ DB_THREAD_INFO *ip;
+ DB *file_dbp;
+ DBC *dbc;
+ DB_MPOOLFILE *mpf;
+ PAGE *pagep;
+ int cmp_p, ret, t_ret;
+
+ ip = ((DB_TXNHEAD *)info)->thread_info;
+ pagep = NULL;
+ REC_PRINT(__crdel_metasub_print);
+ REC_INTRO(__crdel_metasub_read, ip, 0);
+
+ /*
+ * If we are undoing this operation, but the DB that we got back
+ * was never really opened, then this open was an in-memory open
+ * that did not finish. We can let the file creation take care
+ * of any necessary undo/cleanup.
+ */
+ if (DB_UNDO(op) && !F_ISSET(file_dbp, DB_AM_OPEN_CALLED))
+ goto done;
+
+ if ((ret = __memp_fget(mpf, &argp->pgno, ip, NULL, 0, &pagep)) != 0) {
+ /*
+ * If this is an in-memory file, this might be OK. Also, heap
+ * can get there through a truncate and we have to redo page 1
+ */
+ if ((file_dbp->type == DB_HEAP ||
+ F_ISSET(file_dbp, DB_AM_INMEM)) &&
+ (ret = __memp_fget(mpf, &argp->pgno, ip, NULL,
+ DB_MPOOL_CREATE | DB_MPOOL_DIRTY, &pagep)) == 0) {
+ if (F_ISSET(file_dbp, DB_AM_INMEM))
+ LSN_NOT_LOGGED(LSN(pagep));
+ } else {
+ *lsnp = argp->prev_lsn;
+ ret = 0;
+ goto out;
+ }
+ }
+
+ cmp_p = LOG_COMPARE(&LSN(pagep), &argp->lsn);
+ CHECK_LSN(env, op, cmp_p, &LSN(pagep), &argp->lsn);
+
+ if (cmp_p == 0 && DB_REDO(op)) {
+ REC_DIRTY(mpf, ip, file_dbp->priority, &pagep);
+ memcpy(pagep, argp->page.data, argp->page.size);
+ LSN(pagep) = *lsnp;
+
+ /*
+ * If this was an in-memory database and we are re-creating
+ * and this is the meta-data page, then we need to set up a
+ * bunch of fields in the dbo as well.
+ */
+ if (F_ISSET(file_dbp, DB_AM_INMEM) &&
+ argp->pgno == PGNO_BASE_MD &&
+ (ret = __db_meta_setup(file_dbp->env, file_dbp,
+ file_dbp->dname, (DBMETA *)pagep, 0, DB_CHK_META)) != 0)
+ goto out;
+ } else if (DB_UNDO(op)) {
+ /*
+ * We want to undo this page creation. The page creation
+ * happened in two parts. First, we called __db_pg_alloc which
+ * was logged separately. Then we wrote the meta-data onto
+ * the page. So long as we restore the LSN, then the recovery
+ * for __db_pg_alloc will do everything else.
+ *
+ * Don't bother checking the lsn on the page. If we are
+ * rolling back the next thing is that this page will get
+ * freed. Opening the subdb will have reinitialized the
+ * page, but not the lsn.
+ */
+ REC_DIRTY(mpf, ip, file_dbp->priority, &pagep);
+ LSN(pagep) = argp->lsn;
+ }
+
+done: *lsnp = argp->prev_lsn;
+ ret = 0;
+
+out: if (pagep != NULL && (t_ret = __memp_fput(mpf,
+ ip, pagep, file_dbp->priority)) != 0 &&
+ ret == 0)
+ ret = t_ret;
+
+ REC_CLOSE;
+}
+
+/*
+ * __crdel_inmem_create_recover --
+ * Recovery function for inmem_create.
+ *
+ * PUBLIC: int __crdel_inmem_create_recover
+ * PUBLIC: __P((ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__crdel_inmem_create_recover(env, dbtp, lsnp, op, info)
+ ENV *env;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops op;
+ void *info;
+{
+ __crdel_inmem_create_args *argp;
+ DB *dbp;
+ int do_close, ret, t_ret;
+
+ COMPQUIET(info, NULL);
+
+ dbp = NULL;
+ do_close = 0;
+ REC_PRINT(__crdel_inmem_create_print);
+ REC_NOOP_INTRO(__crdel_inmem_create_read);
+
+ /* First, see if the DB handle already exists. */
+ if (argp->fileid == DB_LOGFILEID_INVALID) {
+ if (DB_REDO(op))
+ ret = ENOENT;
+ else
+ ret = 0;
+ } else
+ ret = __dbreg_id_to_db(env, argp->txnp, &dbp, argp->fileid, 0);
+
+ if (DB_REDO(op)) {
+ /*
+ * If the dbreg failed, that means that we're creating a
+ * tmp file.
+ */
+ if (ret != 0) {
+ if ((ret = __db_create_internal(&dbp, env, 0)) != 0)
+ goto out;
+
+ F_SET(dbp, DB_AM_RECOVER | DB_AM_INMEM);
+ memcpy(dbp->fileid, argp->fid.data, DB_FILE_ID_LEN);
+ if (((ret = __os_strdup(env,
+ argp->name.data, &dbp->dname)) != 0))
+ goto out;
+
+ /*
+ * This DBP is never going to be entered into the
+ * dbentry table, so if we leave it open here,
+ * then we're going to lose it.
+ */
+ do_close = 1;
+ }
+
+ /* Now, set the fileid. */
+ memcpy(dbp->fileid, argp->fid.data, argp->fid.size);
+ if ((ret = __memp_set_fileid(dbp->mpf, dbp->fileid)) != 0)
+ goto out;
+ dbp->preserve_fid = 1;
+ MAKE_INMEM(dbp);
+ if ((ret = __env_setup(dbp,
+ NULL, NULL, argp->name.data, TXN_INVALID, 0)) != 0)
+ goto out;
+ ret = __env_mpool(dbp, argp->name.data, 0);
+
+ if (ret == ENOENT) {
+ dbp->pgsize = argp->pgsize;
+ if ((ret = __env_mpool(dbp,
+ argp->name.data, DB_CREATE)) != 0)
+ goto out;
+ } else if (ret != 0)
+ goto out;
+ }
+
+ if (DB_UNDO(op)) {
+ if (ret == 0)
+ ret = __memp_nameop(env, argp->fid.data, NULL,
+ (const char *)argp->name.data, NULL, 1);
+
+ if (ret == ENOENT || ret == DB_DELETED)
+ ret = 0;
+ else
+ goto out;
+ }
+
+ *lsnp = argp->prev_lsn;
+
+out: if (dbp != NULL) {
+ t_ret = 0;
+
+ if (do_close || ret != 0)
+ t_ret = __db_close(dbp, NULL, DB_NOSYNC);
+ if (t_ret != 0 && ret == 0)
+ ret = t_ret;
+ }
+ REC_NOOP_CLOSE;
+}
+
+/*
+ * __crdel_inmem_rename_recover --
+ * Recovery function for inmem_rename.
+ *
+ * PUBLIC: int __crdel_inmem_rename_recover
+ * PUBLIC: __P((ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__crdel_inmem_rename_recover(env, dbtp, lsnp, op, info)
+ ENV *env;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops op;
+ void *info;
+{
+ __crdel_inmem_rename_args *argp;
+ u_int8_t *fileid;
+ int ret;
+
+ COMPQUIET(info, NULL);
+
+ REC_PRINT(__crdel_inmem_rename_print);
+ REC_NOOP_INTRO(__crdel_inmem_rename_read);
+ fileid = argp->fid.data;
+
+ /* Void out errors because the files may or may not still exist. */
+ if (DB_REDO(op))
+ (void)__memp_nameop(env, fileid,
+ (const char *)argp->newname.data,
+ (const char *)argp->oldname.data,
+ (const char *)argp->newname.data, 1);
+
+ if (DB_UNDO(op))
+ (void)__memp_nameop(env, fileid,
+ (const char *)argp->oldname.data,
+ (const char *)argp->newname.data,
+ (const char *)argp->oldname.data, 1);
+
+ *lsnp = argp->prev_lsn;
+ ret = 0;
+
+ REC_NOOP_CLOSE;
+}
+
+/*
+ * __crdel_inmem_remove_recover --
+ * Recovery function for inmem_remove.
+ *
+ * PUBLIC: int __crdel_inmem_remove_recover
+ * PUBLIC: __P((ENV *, DBT *, DB_LSN *, db_recops, void *));
+ */
+int
+__crdel_inmem_remove_recover(env, dbtp, lsnp, op, info)
+ ENV *env;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops op;
+ void *info;
+{
+ __crdel_inmem_remove_args *argp;
+ int ret;
+
+ COMPQUIET(info, NULL);
+
+ REC_PRINT(__crdel_inmem_remove_print);
+ REC_NOOP_INTRO(__crdel_inmem_remove_read);
+
+ /*
+ * Since removes are delayed; there is no undo for a remove; only redo.
+ * The remove may fail, which is OK.
+ */
+ if (DB_REDO(op)) {
+ (void)__memp_nameop(env,
+ argp->fid.data, NULL, argp->name.data, NULL, 1);
+ }
+
+ *lsnp = argp->prev_lsn;
+ ret = 0;
+
+ REC_NOOP_CLOSE;
+}