summaryrefslogtreecommitdiffstats
path: root/debian/htdig/htdig-3.2.0b6/db/crdel_rec.c
diff options
context:
space:
mode:
Diffstat (limited to 'debian/htdig/htdig-3.2.0b6/db/crdel_rec.c')
-rw-r--r--debian/htdig/htdig-3.2.0b6/db/crdel_rec.c443
1 files changed, 443 insertions, 0 deletions
diff --git a/debian/htdig/htdig-3.2.0b6/db/crdel_rec.c b/debian/htdig/htdig-3.2.0b6/db/crdel_rec.c
new file mode 100644
index 00000000..7a420d46
--- /dev/null
+++ b/debian/htdig/htdig-3.2.0b6/db/crdel_rec.c
@@ -0,0 +1,443 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996, 1997, 1998, 1999
+ * Sleepycat Software. All rights reserved.
+ */
+
+#include "db_config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)crdel_rec.c 11.17 (Sleepycat) 11/15/99";
+#endif /* not lint */
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <errno.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "db_page.h"
+#include "log.h"
+#include "hash.h"
+#include "mp.h"
+#include "db_dispatch.h"
+
+/*
+ * CDB___crdel_fileopen_recover --
+ * Recovery function for fileopen.
+ *
+ * PUBLIC: int CDB___crdel_fileopen_recover
+ * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, int, void *));
+ */
+int
+CDB___crdel_fileopen_recover(dbenv, dbtp, lsnp, redo, info)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ int redo;
+ void *info;
+{
+ __crdel_fileopen_args *argp;
+ DBMETA ondisk;
+ DB_FH fh;
+ ssize_t nr;
+ int do_unlink, ret;
+ u_int32_t b, mb, io;
+ char *real_name;
+
+ COMPQUIET(info, NULL);
+
+ real_name = NULL;
+ REC_PRINT(CDB___crdel_fileopen_print);
+
+ if ((ret = CDB___crdel_fileopen_read(dbtp->data, &argp)) != 0)
+ goto out;
+ /*
+ * If this is an in-memory database, then the name is going to
+ * be NULL, which looks like a 0-length name in recovery.
+ */
+ if (argp->name.size == 0)
+ goto done;
+
+ if ((ret = CDB___db_appname(dbenv, DB_APP_DATA,
+ NULL, argp->name.data, 0, NULL, &real_name)) != 0)
+ goto out;
+ if (redo) {
+ /*
+ * The create commited, so we need to make sure that the file
+ * exists. A simple open should suffice.
+ */
+ if ((ret = CDB___os_open(real_name,
+ DB_OSO_CREATE, argp->mode, &fh)) != 0)
+ goto out;
+ if ((ret = CDB___os_closehandle(&fh)) != 0)
+ goto out;
+ } else if (!redo) {
+ /*
+ * If the file is 0-length then it was in the process of being
+ * created, so we should unlink it. If it is non-0 length, then
+ * either someone else created it and we need to leave it
+ * untouched or we were in the process of creating it, allocated
+ * the first page on a system that requires you to actually
+ * write pages as you allocate them, but never got any data
+ * on it.
+ * If the file doesn't exist, we never got around to creating
+ * it, so that's fine.
+ */
+ if (CDB___os_exists(real_name, NULL) != 0)
+ goto done;
+
+ if ((ret = CDB___os_open(real_name, 0, 0, &fh)) != 0)
+ goto out;
+ if ((ret = CDB___os_ioinfo(real_name, &fh, &mb, &b, &io)) != 0)
+ goto out;
+ do_unlink = 0;
+ if (mb != 0 || b != 0) {
+ /*
+ * We need to read the first page to see if its got
+ * valid data on it.
+ */
+ if ((ret = CDB___os_read(&fh,
+ &ondisk, sizeof(ondisk), &nr)) != 0 ||
+ nr != sizeof(ondisk))
+ goto out;
+ if (ondisk.magic == 0)
+ do_unlink = 1;
+ }
+ if ((ret = CDB___os_closehandle(&fh)) != 0)
+ goto out;
+ /* Check for 0-length and if it is, delete it. */
+ if (do_unlink || (mb == 0 && b == 0))
+ if ((ret = CDB___os_unlink(real_name)) != 0)
+ goto out;
+ }
+
+done: *lsnp = argp->prev_lsn;
+ ret = 0;
+
+out: if (argp != NULL)
+ CDB___os_free(argp, sizeof(*argp));
+ if (real_name != NULL)
+ CDB___os_freestr(real_name);
+ return (ret);
+}
+
+/*
+ * CDB___crdel_metasub_recover --
+ * Recovery function for metasub.
+ *
+ * PUBLIC: int CDB___crdel_metasub_recover
+ * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, int, void *));
+ */
+int
+CDB___crdel_metasub_recover(dbenv, dbtp, lsnp, redo, info)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ int redo;
+ void *info;
+{
+ __crdel_metasub_args *argp;
+ DB *file_dbp;
+ DBC *dbc;
+ DB_MPOOLFILE *mpf;
+ PAGE *pagep;
+ int cmp_n, cmp_p, modified, ret;
+
+ COMPQUIET(info, NULL);
+ REC_PRINT(CDB___crdel_metasub_print);
+ REC_INTRO(CDB___crdel_metasub_read, 0);
+
+ if ((ret = CDB_memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
+ if (redo) {
+ if ((ret = CDB_memp_fget(mpf,
+ &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
+ goto out;
+ } else {
+ *lsnp = argp->prev_lsn;
+ ret = 0;
+ goto out;
+ }
+ }
+
+ modified = 0;
+ cmp_n = CDB_log_compare(lsnp, &LSN(pagep));
+ cmp_p = CDB_log_compare(&LSN(pagep), &argp->lsn);
+
+ if (cmp_p == 0 && redo) {
+ memcpy(pagep, argp->page.data, argp->page.size);
+ LSN(pagep) = *lsnp;
+ modified = 1;
+ } else if (cmp_n == 0 && !redo) {
+ /*
+ * We want to undo this page creation. The page creation
+ * happened in two parts. First, we called __bam_new which
+ * was logged separately. Then we wrote the meta-data onto
+ * the page. So long as we restore the LSN, then the recovery
+ * for __bam_new will do everything else.
+ */
+ LSN(pagep) = argp->lsn;
+ modified = 1;
+ }
+ if ((ret = CDB_memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
+ goto out;
+
+done: *lsnp = argp->prev_lsn;
+ ret = 0;
+
+out: REC_CLOSE;
+}
+
+/*
+ * CDB___crdel_metapage_recover --
+ * Recovery function for metapage.
+ *
+ * PUBLIC: int CDB___crdel_metapage_recover
+ * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, int, void *));
+ */
+int
+CDB___crdel_metapage_recover(dbenv, dbtp, lsnp, redo, info)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ int redo;
+ void *info;
+{
+ __crdel_metapage_args *argp;
+ DB *dbp;
+ DBMETA *meta, ondisk;
+ DB_FH fh;
+ ssize_t nr;
+ u_int32_t b, io, mb, pagesize;
+ int is_done, ret;
+ char *real_name;
+
+ COMPQUIET(info, NULL);
+
+ real_name = NULL;
+ memset(&fh, 0, sizeof(fh));
+ REC_PRINT(CDB___crdel_metapage_print);
+
+ if ((ret = CDB___crdel_metapage_read(dbtp->data, &argp)) != 0)
+ goto out;
+
+ /*
+ * If this is an in-memory database, then the name is going to
+ * be NULL, which looks like a 0-length name in recovery.
+ */
+ if (argp->name.size == 0)
+ goto done;
+
+ meta = (DBMETA *)argp->page.data;
+ CDB___ua_memcpy(&pagesize, &meta->pagesize, sizeof(pagesize));
+
+ if ((ret = CDB___db_appname(dbenv, DB_APP_DATA,
+ NULL, argp->name.data, 0, NULL, &real_name)) != 0)
+ goto out;
+ if (redo) {
+ /*
+ * We simply read the first page and if the LSN is 0, we
+ * write the meta-data page.
+ */
+ if ((ret = CDB___os_open(real_name, 0, 0, &fh)) != 0)
+ goto out;
+ if ((ret = CDB___os_seek(&fh,
+ pagesize, argp->pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
+ goto out;
+ /*
+ * If the read succeeds then the page exists, then we need
+ * to vrify that the page has actually been written, because
+ * on some systems (e.g., Windows) we preallocate pages because
+ * files aren't allowed to have holes in them. If the page
+ * looks good then we're done.
+ */
+ if ((ret = CDB___os_read(&fh, &ondisk, sizeof(ondisk), &nr)) == 0 &&
+ nr == sizeof(ondisk)) {
+ if (ondisk.magic != 0)
+ goto done;
+ if ((ret = CDB___os_seek(&fh,
+ pagesize, argp->pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
+ goto out;
+ }
+
+ /*
+ * Page didn't exist, update the LSN and write a new one.
+ * (seek pointer shouldn't have moved)
+ */
+ CDB___ua_memcpy(&meta->lsn, lsnp, sizeof(DB_LSN));
+ if ((ret = CDB___os_write(&fh,
+ argp->page.data, argp->page.size, &nr)) != 0)
+ goto out;
+ if (nr != (ssize_t)argp->page.size) {
+ CDB___db_err(dbenv, "Write failed during recovery");
+ ret = EIO;
+ goto out;
+ }
+ /* Handle will be closed on exit. */
+ } else if (!redo) {
+ is_done = 0;
+
+ /* If file does not exist, there is nothing to undo. */
+ if (CDB___os_exists(real_name, NULL) != 0)
+ goto done;
+
+ /*
+ * Before we can look at anything on disk, we have to check
+ * if there is a valid dbp for this, and if there is, we'd
+ * better flush it.
+ */
+ if ((ret =
+ CDB___db_fileid_to_db(dbenv, &dbp, argp->fileid, 0)) == 0)
+ (void)dbp->sync(dbp, 0);
+
+ /*
+ * We need to make sure that we do not remove a file that
+ * someone else created. If the file is 0-length, then we
+ * can assume that we created it and remove it. If it is
+ * not 0-length, then we need to check the LSN and make
+ * sure that it's the file we created.
+ */
+ if ((ret = CDB___os_open(real_name, 0, 0, &fh)) != 0)
+ goto out;
+ if ((ret = CDB___os_ioinfo(real_name, &fh, &mb, &b, &io)) != 0)
+ goto out;
+ if (mb != 0 || b != 0) {
+ /* The file has something in it. */
+ if ((ret = CDB___os_seek(&fh,
+ pagesize, argp->pgno, 0, 0, DB_OS_SEEK_SET)) != 0)
+ goto out;
+ if ((ret = CDB___os_read(&fh,
+ &ondisk, sizeof(ondisk), &nr)) != 0)
+ goto out;
+ if (CDB_log_compare(&ondisk.lsn, lsnp) != 0)
+ is_done = 1;
+ }
+
+ /*
+ * Must close here, because unlink with the file open fails
+ * on some systems.
+ */
+ if ((ret = CDB___os_closehandle(&fh)) != 0)
+ goto out;
+
+ if (!is_done) {
+ /*
+ * On some systems, you cannot unlink an open file so
+ * we close the fd in the dbp here and make sure we
+ * don't try to close it again. First, check for a
+ * saved_open_fhp, then close down the mpool.
+ */
+ if (dbp->saved_open_fhp != NULL &&
+ F_ISSET(dbp->saved_open_fhp, DB_FH_VALID) &&
+ (ret = CDB___os_closehandle(dbp->saved_open_fhp)) != 0)
+ goto out;
+ if (dbp->mpf != NULL) {
+ (void)CDB___memp_fremove(dbp->mpf);
+ if ((ret = CDB_memp_fclose(dbp->mpf)) != 0)
+ goto out;
+ F_SET(dbp, DB_AM_DISCARD);
+ dbp->mpf = NULL;
+ }
+ if ((ret = CDB___os_unlink(real_name)) != 0)
+ goto out;
+ }
+ }
+
+done: *lsnp = argp->prev_lsn;
+ ret = 0;
+
+out: if (argp != NULL)
+ CDB___os_free(argp, sizeof(*argp));
+ if (real_name != NULL)
+ CDB___os_freestr(real_name);
+ if (F_ISSET(&fh, DB_FH_VALID))
+ (void)CDB___os_closehandle(&fh);
+ return (ret);
+}
+
+/*
+ * CDB___crdel_delete_recover --
+ * Recovery function for delete.
+ *
+ * PUBLIC: int CDB___crdel_delete_recover
+ * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, int, void *));
+ */
+int
+CDB___crdel_delete_recover(dbenv, dbtp, lsnp, redo, info)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ int redo;
+ void *info;
+{
+ __crdel_delete_args *argp;
+ int ret;
+ char *backup, *real_back, *real_name;
+
+ REC_PRINT(CDB___crdel_delete_print);
+
+ backup = real_back = real_name = NULL;
+ if ((ret = CDB___crdel_delete_read(dbtp->data, &argp)) != 0)
+ goto out;
+
+ if (redo) {
+ /*
+ * On a recovery, as we recreate what was going on, we
+ * recreate the creation of the file. And so, even though
+ * it committed, we need to delete it. Try to delete it,
+ * but it is not an error if that delete fails.
+ */
+ if ((ret = CDB___db_appname(dbenv, DB_APP_DATA,
+ NULL, argp->name.data, 0, NULL, &real_name)) != 0)
+ goto out;
+ (void)CDB___os_unlink(real_name);
+ /*
+ * The transaction committed, so the only thing that might
+ * be true is that the backup file is still around. Try
+ * to delete it, but it's not an error if that delete fails.
+ */
+ if ((ret = CDB___db_backup_name(argp->name.data,
+ &backup, lsnp)) != 0)
+ goto out;
+ if ((ret = CDB___db_appname(dbenv,
+ DB_APP_DATA, NULL, backup, 0, NULL, &real_back)) != 0)
+ goto out;
+ (void)CDB___os_unlink(real_back);
+ if ((ret = CDB___db_txnlist_delete(info,
+ argp->name.data, TXNLIST_INVALID_ID, 1)) != 0)
+ goto out;
+ } else if (!redo) {
+ /*
+ * Trying to undo. File may or may not have been deleted.
+ * Try to move the backup to the original. If the backup
+ * exists, then this is right. If it doesn't exist, then
+ * nothing will happen and that's OK.
+ */
+ if ((ret = CDB___db_backup_name(argp->name.data,
+ &backup, lsnp)) != 0)
+ goto out;
+ if ((ret = CDB___db_appname(dbenv,
+ DB_APP_DATA, NULL, backup, 0, NULL, &real_back)) != 0)
+ goto out;
+ if ((ret = CDB___db_appname(dbenv, DB_APP_DATA,
+ NULL, argp->name.data, 0, NULL, &real_name)) != 0)
+ goto out;
+ (void)CDB___os_rename(real_back, real_name);
+ }
+
+ *lsnp = argp->prev_lsn;
+ ret = 0;
+
+out: if (argp != NULL)
+ CDB___os_free(argp, sizeof(*argp));
+ if (backup != NULL)
+ CDB___os_freestr(backup);
+ if (real_back != NULL)
+ CDB___os_freestr(real_back);
+ if (real_name != NULL)
+ CDB___os_freestr(real_name);
+ return (ret);
+}