diff options
Diffstat (limited to 'storage/bdb/fileops/fop_rec.c')
-rw-r--r-- | storage/bdb/fileops/fop_rec.c | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/storage/bdb/fileops/fop_rec.c b/storage/bdb/fileops/fop_rec.c new file mode 100644 index 00000000000..67720e01d13 --- /dev/null +++ b/storage/bdb/fileops/fop_rec.c @@ -0,0 +1,308 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001-2002 + * Sleepycat Software. All rights reserved. + */ + +#include "db_config.h" + +#ifndef lint +static const char revid[] = "$Id: fop_rec.c,v 1.18 2002/08/14 20:27:01 bostic Exp $"; +#endif /* not lint */ + +#ifndef NO_SYSTEM_INCLUDES +#include <sys/types.h> + +#include <string.h> +#endif + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/fop.h" +#include "dbinc/db_am.h" +#include "dbinc/txn.h" + +/* + * __fop_create_recover -- + * Recovery function for create. + * + * PUBLIC: int __fop_create_recover + * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + */ +int +__fop_create_recover(dbenv, dbtp, lsnp, op, info) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + DB_FH fh; + __fop_create_args *argp; + char *real_name; + int ret; + + real_name = NULL; + COMPQUIET(info, NULL); + REC_PRINT(__fop_create_print); + REC_NOOP_INTRO(__fop_create_read); + + if ((ret = __db_appname(dbenv, (APPNAME)argp->appname, + (const char *)argp->name.data, 0, NULL, &real_name)) != 0) + goto out; + + if (DB_UNDO(op)) + (void)__os_unlink(dbenv, real_name); + else if (DB_REDO(op)) + if ((ret = __os_open(dbenv, real_name, + DB_OSO_CREATE | DB_OSO_EXCL, argp->mode, &fh)) == 0) + __os_closehandle(dbenv, &fh); + + *lsnp = argp->prev_lsn; + +out: if (real_name != NULL) + __os_free(dbenv, real_name); + + REC_NOOP_CLOSE; +} + +/* + * __fop_remove_recover -- + * Recovery function for remove. + * + * PUBLIC: int __fop_remove_recover + * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + */ +int +__fop_remove_recover(dbenv, dbtp, lsnp, op, info) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + __fop_remove_args *argp; + char *real_name; + int ret; + + real_name = NULL; + COMPQUIET(info, NULL); + REC_PRINT(__fop_remove_print); + REC_NOOP_INTRO(__fop_remove_read); + + if ((ret = __db_appname(dbenv, (APPNAME)argp->appname, + (const char *)argp->name.data, 0, NULL, &real_name)) != 0) + goto out; + + if (DB_REDO(op) && (ret = dbenv->memp_nameop(dbenv, + (u_int8_t *)argp->fid.data, NULL, real_name, NULL)) != 0) + goto out; + + *lsnp = argp->prev_lsn; +out: if (real_name != NULL) + __os_free(dbenv, real_name); + REC_NOOP_CLOSE; +} + +/* + * __fop_write_recover -- + * Recovery function for writechunk. + * + * PUBLIC: int __fop_write_recover + * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + */ +int +__fop_write_recover(dbenv, dbtp, lsnp, op, info) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + __fop_write_args *argp; + int ret; + + COMPQUIET(info, NULL); + REC_PRINT(__fop_write_print); + REC_NOOP_INTRO(__fop_write_read); + + if (DB_UNDO(op)) + DB_ASSERT(argp->flag != 0); + else if (DB_REDO(op)) + ret = __fop_write(dbenv, + argp->txnid, argp->name.data, argp->appname, NULL, + argp->offset, argp->page.data, argp->page.size, argp->flag); + + *lsnp = argp->prev_lsn; + REC_NOOP_CLOSE; +} + +/* + * __fop_rename_recover -- + * Recovery function for rename. + * + * PUBLIC: int __fop_rename_recover + * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + */ +int +__fop_rename_recover(dbenv, dbtp, lsnp, op, info) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + __fop_rename_args *argp; + DBMETA *meta; + char *real_new, *real_old, *src; + int ret; + u_int8_t *fileid, mbuf[DBMETASIZE]; + + real_new = NULL; + real_old = NULL; + ret = 0; + meta = (DBMETA *)&mbuf[0]; + + COMPQUIET(info, NULL); + REC_PRINT(__fop_rename_print); + REC_NOOP_INTRO(__fop_rename_read); + fileid = argp->fileid.data; + + if ((ret = __db_appname(dbenv, (APPNAME)argp->appname, + (const char *)argp->newname.data, 0, NULL, &real_new)) != 0) + goto out; + if ((ret = __db_appname(dbenv, (APPNAME)argp->appname, + (const char *)argp->oldname.data, 0, NULL, &real_old)) != 0) + goto out; + + /* + * Verify that we are manipulating the correct file. We should always + * be OK on an ABORT or an APPLY, but during recovery, we have to + * check. + */ + if (op != DB_TXN_ABORT && op != DB_TXN_APPLY) { + src = DB_UNDO(op) ? real_new : real_old; + /* + * Interpret any error as meaning that the file either doesn't + * exist, doesn't have a meta-data page, or is in some other + * way, shape or form, incorrect, so that we should not restore + * it. + */ + if (__fop_read_meta( + dbenv, src, mbuf, DBMETASIZE, NULL, 1, 0) != 0) + goto done; + if (__db_chk_meta(dbenv, NULL, meta, 1) != 0) + goto done; + if (memcmp(argp->fileid.data, meta->uid, DB_FILE_ID_LEN) != 0) + goto done; + } + + if (DB_UNDO(op)) + (void)dbenv->memp_nameop(dbenv, fileid, + (const char *)argp->oldname.data, real_new, real_old); + if (DB_REDO(op)) + (void)dbenv->memp_nameop(dbenv, fileid, + (const char *)argp->newname.data, real_old, real_new); + +done: *lsnp = argp->prev_lsn; +out: if (real_new != NULL) + __os_free(dbenv, real_new); + if (real_old != NULL) + __os_free(dbenv, real_old); + + REC_NOOP_CLOSE; +} + +/* + * __fop_file_remove_recover -- + * Recovery function for file_remove. On the REDO pass, we need to + * make sure no one recreated the file while we weren't looking. On an + * undo pass must check if the file we are interested in is the one that + * exists and then set the status of the child transaction depending on + * what we find out. + * + * PUBLIC: int __fop_file_remove_recover + * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + */ +int +__fop_file_remove_recover(dbenv, dbtp, lsnp, op, info) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + __fop_file_remove_args *argp; + DBMETA *meta; + char *real_name; + int is_real, is_tmp, ret; + u_int8_t mbuf[DBMETASIZE]; + u_int32_t cstat; + + real_name = NULL; + is_real = is_tmp = 0; + meta = (DBMETA *)&mbuf[0]; + REC_PRINT(__fop_file_remove_print); + REC_NOOP_INTRO(__fop_file_remove_read); + + /* + * This record is only interesting on the backward, forward, and + * apply phases. + */ + if (op != DB_TXN_BACKWARD_ROLL && + op != DB_TXN_FORWARD_ROLL && op != DB_TXN_APPLY) + goto done; + + if ((ret = __db_appname(dbenv, + (APPNAME)argp->appname, argp->name.data, 0, NULL, &real_name)) != 0) + goto out; + + /* Verify that we are manipulating the correct file. */ + if ((ret = __fop_read_meta(dbenv, + real_name, mbuf, DBMETASIZE, NULL, 1, 0)) != 0) { + /* File does not exist. */ + cstat = TXN_EXPECTED; + } else { + /* + * We can ignore errors here since we'll simply fail the + * checks below and assume this is the wrong file. + */ + (void)__db_chk_meta(dbenv, NULL, meta, 1); + is_real = + memcmp(argp->real_fid.data, meta->uid, DB_FILE_ID_LEN) == 0; + is_tmp = + memcmp(argp->tmp_fid.data, meta->uid, DB_FILE_ID_LEN) == 0; + + if (!is_real && !is_tmp) + /* File exists, but isn't what we were removing. */ + cstat = TXN_IGNORE; + else + /* File exists and is the one that we were removing. */ + cstat = TXN_COMMIT; + } + + if (DB_UNDO(op)) { + /* On the backward pass, we leave a note for the child txn. */ + if ((ret = __db_txnlist_update(dbenv, + info, argp->child, cstat, NULL)) == DB_NOTFOUND) + ret = __db_txnlist_add(dbenv, + info, argp->child, cstat, NULL); + } else if (DB_REDO(op)) { + /* + * On the forward pass, check if someone recreated the + * file while we weren't looking. + */ + if (cstat == TXN_COMMIT) + (void)dbenv->memp_nameop(dbenv, + is_real ? argp->real_fid.data : argp->tmp_fid.data, + NULL, real_name, NULL); + } + +done: *lsnp = argp->prev_lsn; + ret = 0; + +out: if (real_name != NULL) + __os_free(dbenv, real_name); + REC_NOOP_CLOSE; +} |