diff options
author | jbj <devnull@localhost> | 2002-08-14 16:31:49 +0000 |
---|---|---|
committer | jbj <devnull@localhost> | 2002-08-14 16:31:49 +0000 |
commit | d481ba55c02407124c499c7800ea556786137bc5 (patch) | |
tree | e0d3fdb7906ae3290f019999e0661cfc5b1b3f58 /db/examples_c | |
parent | 9114d6ffea4ee330874ebc8febe225ce0e891eac (diff) | |
download | librpm-tizen-d481ba55c02407124c499c7800ea556786137bc5.tar.gz librpm-tizen-d481ba55c02407124c499c7800ea556786137bc5.tar.bz2 librpm-tizen-d481ba55c02407124c499c7800ea556786137bc5.zip |
Initial revision
CVS patchset: 5630
CVS date: 2002/08/14 16:31:49
Diffstat (limited to 'db/examples_c')
-rw-r--r-- | db/examples_c/ex_apprec/auto_rebuild | 9 | ||||
-rw-r--r-- | db/examples_c/ex_apprec/ex_apprec.c | 267 | ||||
-rw-r--r-- | db/examples_c/ex_apprec/ex_apprec.h | 24 | ||||
-rw-r--r-- | db/examples_c/ex_apprec/ex_apprec.src | 41 | ||||
-rw-r--r-- | db/examples_c/ex_apprec/ex_apprec_auto.c | 188 | ||||
-rw-r--r-- | db/examples_c/ex_apprec/ex_apprec_auto.h | 13 | ||||
-rw-r--r-- | db/examples_c/ex_apprec/ex_apprec_rec.c | 115 | ||||
-rw-r--r-- | db/examples_c/ex_apprec/ex_apprec_template | 75 |
8 files changed, 732 insertions, 0 deletions
diff --git a/db/examples_c/ex_apprec/auto_rebuild b/db/examples_c/ex_apprec/auto_rebuild new file mode 100644 index 000000000..342519848 --- /dev/null +++ b/db/examples_c/ex_apprec/auto_rebuild @@ -0,0 +1,9 @@ +# Script to rebuild automatically generated files for ex_apprec. + +E=../examples_c/ex_apprec + +cd ../../dist +awk -f gen_rec.awk \ + -v source_file=$E/ex_apprec_auto.c \ + -v header_file=$E/ex_apprec_auto.h \ + -v template_file=$E/ex_apprec_template < $E/ex_apprec.src diff --git a/db/examples_c/ex_apprec/ex_apprec.c b/db/examples_c/ex_apprec/ex_apprec.c new file mode 100644 index 000000000..571388d4b --- /dev/null +++ b/db/examples_c/ex_apprec/ex_apprec.c @@ -0,0 +1,267 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996-2002 + * Sleepycat Software. All rights reserved. + * + * Id: ex_apprec.c,v 1.2 2002/08/06 05:39:01 bostic Exp + */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <errno.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <db.h> + +#include "ex_apprec.h" + +int apprec_dispatch __P((DB_ENV *, DBT *, DB_LSN *, db_recops)); +int open_env __P((const char *, FILE *, const char *, DB_ENV **)); +int verify_absence __P((DB_ENV *, const char *)); +int verify_presence __P((DB_ENV *, const char *)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern char *optarg; + extern int optind; + DB_ENV *dbenv; + DB_LSN lsn; + DB_TXN *txn; + DBT dirnamedbt; + int ret; + const char *home; + char ch, dirname[256]; + const char *progname = "ex_apprec"; /* Program name. */ + + /* Default home. */ + home = "TESTDIR"; + + while ((ch = getopt(argc, argv, "h:")) != EOF) + switch (ch) { + case 'h': + home = optarg; + break; + default: + fprintf(stderr, "usage: %s [-h home]", progname); + exit(EXIT_FAILURE); + } + + printf("Set up environment.\n"); + if ((ret = open_env(home, stderr, progname, &dbenv)) != 0) + return (EXIT_FAILURE); + + printf("Create a directory in a transaction.\n"); + /* + * This application's convention is to log the full directory name, + * including trailing nul. + */ + memset(&dirnamedbt, 0, sizeof(dirnamedbt)); + sprintf(dirname, "%s/MYDIRECTORY", home); + dirnamedbt.data = dirname; + dirnamedbt.size = strlen(dirname) + 1; + + if ((ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0) { + dbenv->err(dbenv, ret, "txn_begin"); + return (EXIT_FAILURE); + } + + /* Remember, always log actions before you execute them! */ + memset(&lsn, 0, sizeof(lsn)); + if ((ret = + ex_apprec_mkdir_log(dbenv, txn, &lsn, 0, &dirnamedbt)) != 0) { + dbenv->err(dbenv, ret, "mkdir_log"); + return (EXIT_FAILURE); + } + if (mkdir(dirname, 0755) != 0) { + dbenv->err(dbenv, errno, "mkdir"); + return (EXIT_FAILURE); + } + + printf("Verify the directory's presence: "); + verify_presence(dbenv, dirname); + printf("check.\n"); + + /* Now abort the transaction and verify that the directory goes away. */ + printf("Abort the transaction.\n"); + if ((ret = txn->abort(txn)) != 0) { + dbenv->err(dbenv, ret, "txn_abort"); + return (EXIT_FAILURE); + } + + printf("Verify the directory's absence: "); + verify_absence(dbenv, dirname); + printf("check.\n"); + + /* Now do the same thing over again, only with a commit this time. */ + printf("Create a directory in a transaction.\n"); + memset(&dirnamedbt, 0, sizeof(dirnamedbt)); + sprintf(dirname, "%s/MYDIRECTORY", home); + dirnamedbt.data = dirname; + dirnamedbt.size = strlen(dirname) + 1; + if ((ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0) { + dbenv->err(dbenv, ret, "txn_begin"); + return (EXIT_FAILURE); + } + + memset(&lsn, 0, sizeof(lsn)); + if ((ret = + ex_apprec_mkdir_log(dbenv, txn, &lsn, 0, &dirnamedbt)) != 0) { + dbenv->err(dbenv, ret, "mkdir_log"); + return (EXIT_FAILURE); + } + if (mkdir(dirname, 0755) != 0) { + dbenv->err(dbenv, errno, "mkdir"); + return (EXIT_FAILURE); + } + + printf("Verify the directory's presence: "); + verify_presence(dbenv, dirname); + printf("check.\n"); + + /* Now abort the transaction and verify that the directory goes away. */ + printf("Commit the transaction.\n"); + if ((ret = txn->commit(txn, 0)) != 0) { + dbenv->err(dbenv, ret, "txn_commit"); + return (EXIT_FAILURE); + } + + printf("Verify the directory's presence: "); + verify_presence(dbenv, dirname); + printf("check.\n"); + + printf("Now remove the directory, then run recovery.\n"); + if ((ret = dbenv->close(dbenv, 0)) != 0) { + fprintf(stderr, "DB_ENV->close: %s\n", db_strerror(ret)); + return (EXIT_FAILURE); + } + if (rmdir(dirname) != 0) { + fprintf(stderr, + "%s: rmdir failed with error %s", progname, + strerror(errno)); + } + verify_absence(dbenv, dirname); + + /* Opening with DB_RECOVER runs recovery. */ + if ((ret = open_env(home, stderr, progname, &dbenv)) != 0) + return (EXIT_FAILURE); + + printf("Verify the directory's presence: "); + verify_presence(dbenv, dirname); + printf("check.\n"); + + /* Close the handle. */ + if ((ret = dbenv->close(dbenv, 0)) != 0) { + fprintf(stderr, "DB_ENV->close: %s\n", db_strerror(ret)); + return (EXIT_FAILURE); + } + + return (EXIT_SUCCESS); +} + +int +open_env(home, errfp, progname, dbenvp) + const char *home, *progname; + FILE *errfp; + DB_ENV **dbenvp; +{ + DB_ENV *dbenv; + int ret; + + /* + * Create an environment object and initialize it for error + * reporting. + */ + if ((ret = db_env_create(&dbenv, 0)) != 0) { + fprintf(errfp, "%s: %s\n", progname, db_strerror(ret)); + return (ret); + } + dbenv->set_errfile(dbenv, errfp); + dbenv->set_errpfx(dbenv, progname); + + /* Set up our custom recovery dispatch function. */ + if ((ret = dbenv->set_app_dispatch(dbenv, apprec_dispatch)) != 0) { + dbenv->err(dbenv, ret, "set_app_dispatch"); + return (ret); + } + + /* + * Open the environment with full transactional support, running + * recovery. + */ + if ((ret = + dbenv->open(dbenv, home, DB_CREATE | DB_RECOVER | DB_INIT_LOCK | + DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN, 0)) != 0) { + dbenv->err(dbenv, ret, "environment open: %s", home); + dbenv->close(dbenv, 0); + return (ret); + } + + *dbenvp = dbenv; + return (0); +} + +/* + * Sample application dispatch function to handle user-specified log record + * types. + */ +int +apprec_dispatch(dbenv, dbt, lsn, op) + DB_ENV *dbenv; + DBT *dbt; + DB_LSN *lsn; + db_recops op; +{ + u_int32_t rectype; + + /* Pull the record type out of the log record. */ + memcpy(&rectype, dbt->data, sizeof(rectype)); + + switch (rectype) { + case DB_ex_apprec_mkdir: + return (ex_apprec_mkdir_recover(dbenv, dbt, lsn, op, NULL)); + default: + /* + * We've hit an unexpected, allegedly user-defined record + * type. + */ + dbenv->errx(dbenv, "Unexpected log record type encountered"); + return (EINVAL); + } +} + +int +verify_absence(dbenv, dirname) + DB_ENV *dbenv; + const char *dirname; +{ + + if (access(dirname, F_OK) == 0) { + dbenv->errx(dbenv, "Error--directory present!"); + exit(EXIT_FAILURE); + } + + return (0); +} + +int +verify_presence(dbenv, dirname) + DB_ENV *dbenv; + const char *dirname; +{ + + if (access(dirname, F_OK) != 0) { + dbenv->errx(dbenv, "Error--directory not present!"); + exit(EXIT_FAILURE); + } + + return (0); +} diff --git a/db/examples_c/ex_apprec/ex_apprec.h b/db/examples_c/ex_apprec/ex_apprec.h new file mode 100644 index 000000000..f4899de29 --- /dev/null +++ b/db/examples_c/ex_apprec/ex_apprec.h @@ -0,0 +1,24 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2002 + * Sleepycat Software. All rights reserved. + * + * Id: ex_apprec.h,v 1.2 2002/08/08 15:47:00 bostic Exp + */ + +#ifndef _EX_APPREC_H_ +#define _EX_APPREC_H_ + +#include "ex_apprec_auto.h" + +int ex_apprec_mkdir_log + __P((DB_ENV *, DB_TXN *, DB_LSN *, u_int32_t, const DBT *)); +int ex_apprec_mkdir_print + __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); +int ex_apprec_mkdir_read + __P((DB_ENV *, void *, ex_apprec_mkdir_args **)); +int ex_apprec_mkdir_recover + __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + +#endif /* !_EX_APPREC_H_ */ diff --git a/db/examples_c/ex_apprec/ex_apprec.src b/db/examples_c/ex_apprec/ex_apprec.src new file mode 100644 index 000000000..986b57b68 --- /dev/null +++ b/db/examples_c/ex_apprec/ex_apprec.src @@ -0,0 +1,41 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2002 + * Sleepycat Software. All rights reserved. + * + * Id: ex_apprec.src,v 1.3 2002/08/08 15:47:00 bostic Exp + */ + +PREFIX ex_apprec + +/* + * This is the source file used to generate the application-specific recovery + * functions used by the ex_apprec example. It should be turned into usable + * source code (including a template for the recovery function itself) by + * invoking changing to the dist directory of the DB distribution and + * running the gen_rec.awk script there as follows: + * + * awk -f ./gen_rec.awk \ + * -v source_file=../examples_c/ex_apprec/ex_apprec_auto.c \ + * -v header_file=../examples_c/ex_apprec/ex_apprec_auto.h \ + * -v template_file=../examples_c/ex_apprec/ex_apprec_template \ + * < ../examples_c/ex_apprec/ex_apprec.src + +INCLUDE #include <ctype.h> +INCLUDE #include <errno.h> +INCLUDE #include <stdlib.h> +INCLUDE #include <string.h> +INCLUDE +INCLUDE #include <db.h> +INCLUDE +INCLUDE #include "ex_apprec.h" + +/* + * mkdir: used to create a directory + * + * dirname: relative or absolute pathname of the directory to be created + */ +BEGIN mkdir 10000 +DBT dirname DBT s +END diff --git a/db/examples_c/ex_apprec/ex_apprec_auto.c b/db/examples_c/ex_apprec/ex_apprec_auto.c new file mode 100644 index 000000000..d8c27e762 --- /dev/null +++ b/db/examples_c/ex_apprec/ex_apprec_auto.c @@ -0,0 +1,188 @@ +/* Do not edit: automatically built by gen_rec.awk. */ +#include <ctype.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include <db.h> + +#include "ex_apprec.h" +/* + * PUBLIC: int ex_apprec_mkdir_log __P((DB_ENV *, DB_TXN *, DB_LSN *, + * PUBLIC: u_int32_t, const DBT *)); + */ +int +ex_apprec_mkdir_log(dbenv, txnid, ret_lsnp, flags, + dirname) + DB_ENV *dbenv; + DB_TXN *txnid; + DB_LSN *ret_lsnp; + u_int32_t flags; + const DBT *dirname; +{ + DBT logrec; + DB_LSN *lsnp, null_lsn; + u_int32_t zero; + u_int32_t npad, rectype, txn_num; + int ret; + u_int8_t *bp; + + rectype = DB_ex_apprec_mkdir; + npad = 0; + + if (txnid == NULL) { + txn_num = 0; + null_lsn.file = 0; + null_lsn.offset = 0; + lsnp = &null_lsn; + } else { + txn_num = txnid->txnid; + lsnp = &txnid->last_lsn; + } + + logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN) + + sizeof(u_int32_t) + (dirname == NULL ? 0 : dirname->size); + if ((logrec.data = malloc(logrec.size)) == NULL) + return (ENOMEM); + + if (npad > 0) + memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad); + + bp = logrec.data; + + memcpy(bp, &rectype, sizeof(rectype)); + bp += sizeof(rectype); + + memcpy(bp, &txn_num, sizeof(txn_num)); + bp += sizeof(txn_num); + + memcpy(bp, lsnp, sizeof(DB_LSN)); + bp += sizeof(DB_LSN); + + if (dirname == NULL) { + zero = 0; + memcpy(bp, &zero, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + } else { + memcpy(bp, &dirname->size, sizeof(dirname->size)); + bp += sizeof(dirname->size); + memcpy(bp, dirname->data, dirname->size); + bp += dirname->size; + } + + ret = dbenv->log_put(dbenv, + ret_lsnp, (DBT *)&logrec, flags); + if (txnid != NULL && ret == 0) + txnid->last_lsn = *ret_lsnp; +#ifdef LOG_DIAGNOSTIC + if (ret != 0) + (void)ex_apprec_mkdir_print(dbenv, + (DBT *)&logrec, ret_lsnp, NULL, NULL); +#endif + free(logrec.data); + return (ret); +} + +/* + * PUBLIC: int ex_apprec_mkdir_print __P((DB_ENV *, DBT *, DB_LSN *, + * PUBLIC: db_recops, void *)); + */ +int +ex_apprec_mkdir_print(dbenv, dbtp, lsnp, notused2, notused3) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops notused2; + void *notused3; +{ + ex_apprec_mkdir_args *argp; + u_int32_t i; + int ch; + int ret; + + notused2 = DB_TXN_ABORT; + notused3 = NULL; + + if ((ret = ex_apprec_mkdir_read(dbenv, dbtp->data, &argp)) != 0) + return (ret); + (void)printf( + "[%lu][%lu]ex_apprec_mkdir: rec: %lu txnid %lx prevlsn [%lu][%lu]\n", + (u_long)lsnp->file, + (u_long)lsnp->offset, + (u_long)argp->type, + (u_long)argp->txnid->txnid, + (u_long)argp->prev_lsn.file, + (u_long)argp->prev_lsn.offset); + (void)printf("\tdirname: "); + for (i = 0; i < argp->dirname.size; i++) { + ch = ((u_int8_t *)argp->dirname.data)[i]; + printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch); + } + (void)printf("\n"); + (void)printf("\n"); + free(argp); + return (0); +} + +/* + * PUBLIC: int ex_apprec_mkdir_read __P((DB_ENV *, void *, + * PUBLIC: ex_apprec_mkdir_args **)); + */ +int +ex_apprec_mkdir_read(dbenv, recbuf, argpp) + DB_ENV *dbenv; + void *recbuf; + ex_apprec_mkdir_args **argpp; +{ + ex_apprec_mkdir_args *argp; + u_int8_t *bp; + /* Keep the compiler quiet. */ + + dbenv = NULL; + if ((argp = malloc(sizeof(ex_apprec_mkdir_args) + sizeof(DB_TXN))) == NULL) + return (ENOMEM); + + argp->txnid = (DB_TXN *)&argp[1]; + + bp = recbuf; + memcpy(&argp->type, bp, sizeof(argp->type)); + bp += sizeof(argp->type); + + memcpy(&argp->txnid->txnid, bp, sizeof(argp->txnid->txnid)); + bp += sizeof(argp->txnid->txnid); + + memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN)); + bp += sizeof(DB_LSN); + + memset(&argp->dirname, 0, sizeof(argp->dirname)); + memcpy(&argp->dirname.size, bp, sizeof(u_int32_t)); + bp += sizeof(u_int32_t); + argp->dirname.data = bp; + bp += argp->dirname.size; + + *argpp = argp; + return (0); +} + +/* + * PUBLIC: int ex_apprec_init_print __P((DB_ENV *, int (***)(DB_ENV *, + * PUBLIC: DBT *, DB_LSN *, db_recops, void *), size_t *)); + */ +int +ex_apprec_init_print(dbenv, dtabp, dtabsizep) + DB_ENV *dbenv; + int (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + size_t *dtabsizep; +{ + int __db_add_recovery __P((DB_ENV *, + int (***)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *), + size_t *, + int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *), u_int32_t)); + int ret; + + if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep, + ex_apprec_mkdir_print, DB_ex_apprec_mkdir)) != 0) + return (ret); + return (0); +} + diff --git a/db/examples_c/ex_apprec/ex_apprec_auto.h b/db/examples_c/ex_apprec/ex_apprec_auto.h new file mode 100644 index 000000000..358b1a9f0 --- /dev/null +++ b/db/examples_c/ex_apprec/ex_apprec_auto.h @@ -0,0 +1,13 @@ +/* Do not edit: automatically built by gen_rec.awk. */ + +#ifndef ex_apprec_AUTO_H +#define ex_apprec_AUTO_H +#define DB_ex_apprec_mkdir 10000 +typedef struct _ex_apprec_mkdir_args { + u_int32_t type; + DB_TXN *txnid; + DB_LSN prev_lsn; + DBT dirname; +} ex_apprec_mkdir_args; + +#endif diff --git a/db/examples_c/ex_apprec/ex_apprec_rec.c b/db/examples_c/ex_apprec/ex_apprec_rec.c new file mode 100644 index 000000000..ea732c3e1 --- /dev/null +++ b/db/examples_c/ex_apprec/ex_apprec_rec.c @@ -0,0 +1,115 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996-2002 + * Sleepycat Software. All rights reserved. + * + * Id: ex_apprec_rec.c,v 1.2 2002/08/06 05:39:02 bostic Exp + */ + +/* + * This file is based on the template file ex_apprec_template. Note that + * because ex_apprec_mkdir, like most application-specific recovery functions, + * does not make use of DB-private structures, it has actually been simplified + * significantly. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> + +#include <db.h> + +#include "ex_apprec.h" + +/* + * ex_apprec_mkdir_recover -- + * Recovery function for mkdir. + * + * PUBLIC: int ex_apprec_mkdir_recover + * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + */ +int +ex_apprec_mkdir_recover(dbenv, dbtp, lsnp, op, info) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + ex_apprec_mkdir_args *argp; + int ret; + + argp = NULL; + + /* + * Shut up the compiler--"info" is used for the recovery functions + * belonging to transaction meta-operations such as txn_create, and + * need not concern us here either. + */ + info = NULL; + + if ((ret = ex_apprec_mkdir_read(dbenv, dbtp->data, &argp)) != 0) + goto out; + + switch (op) { + case DB_TXN_ABORT: + case DB_TXN_BACKWARD_ROLL: + /* + * If we're aborting, we need to remove the directory if it + * exists. We log the trailing zero in pathnames, so we can + * simply pass the data part of the DBT into rmdir as a string. + * (Note that we don't have any alignment guarantees, but for + * a char * this doesn't matter.) + * + * Ignore all errors other than ENOENT; DB may attempt to undo + * or redo operations without knowing whether they have already + * been done or undone, so we should never assume in a recovery + * function that the task definitely needs doing or undoing. + */ + ret = rmdir(argp->dirname.data); + if (ret != 0 && errno != ENOENT) + dbenv->err(dbenv, ret, "Error in abort of mkdir"); + else + ret = 0; + break; + case DB_TXN_FORWARD_ROLL: + /* + * The forward direction is just the opposite; here, we ignore + * EEXIST, because the directory may already exist. + */ + ret = mkdir(argp->dirname.data, 0755); + if (ret != 0 && errno != EEXIST) + dbenv->err(dbenv, + ret, "Error in roll-forward of mkdir"); + else + ret = 0; + break; + default: + /* + * We might want to handle DB_TXN_PRINT or DB_TXN_APPLY here, + * too, but we don't try to print the log records and aren't + * using replication, so there's no need to in this example. + */ + dbenv->errx(dbenv, "Unexpected operation type\n"); + return (EINVAL); + } + + /* + * The recovery function is responsible for returning the LSN of the + * previous log record in this transaction, so that transaction aborts + * can follow the chain backwards. + * + * (If we'd wanted the LSN of this record earlier, we could have + * read it from lsnp, as well--but because we weren't working with + * pages or other objects that store their LSN and base recovery + * decisions on it, we didn't need to.) + */ + *lsnp = argp->prev_lsn; + +out: if (argp != NULL) + free(argp); + return (ret); +} diff --git a/db/examples_c/ex_apprec/ex_apprec_template b/db/examples_c/ex_apprec/ex_apprec_template new file mode 100644 index 000000000..e67ccb6d8 --- /dev/null +++ b/db/examples_c/ex_apprec/ex_apprec_template @@ -0,0 +1,75 @@ +#include "db_config.h" + +#ifndef NO_SYSTEM_INCLUDES +#include <sys/types.h> + +#include <string.h> +#endif + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/ex_apprec.h" +#include "dbinc/log.h" + +/* + * ex_apprec_mkdir_recover -- + * Recovery function for mkdir. + * + * PUBLIC: int ex_apprec_mkdir_recover + * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + */ +int +ex_apprec_mkdir_recover(dbenv, dbtp, lsnp, op, info) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + ex_apprec_mkdir_args *argp; + DB *file_dbp; + DBC *dbc; + DB_MPOOLFILE *mpf; + PAGE *pagep; + int cmp_n, cmp_p, modified, ret; + + REC_PRINT(ex_apprec_mkdir_print); + REC_INTRO(ex_apprec_mkdir_read, 1); + + if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) + if (DB_REDO(op)) { + if ((ret = mpf->get(mpf, + &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) + goto out; + } else { + *lsnp = argp->prev_lsn; + ret = 0; + goto out; + } + + modified = 0; + cmp_n = log_compare(lsnp, &LSN(pagep)); + + /* + * Use this when there is something like "pagelsn" in the argp + * structure. Sometimes, you might need to compare meta-data + * lsn's instead. + * + * cmp_p = log_compare(&LSN(pagep), argp->pagelsn); + */ + if (cmp_p == 0 && DB_REDO(op)) { + /* Need to redo update described. */ + modified = 1; + } else if (cmp_n == 0 && !DB_REDO(op)) { + /* Need to undo update described. */ + modified = 1; + } + if (ret = mpf->put(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) + goto out; + + *lsnp = argp->prev_lsn; + ret = 0; + +out: REC_CLOSE; +} + |