Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

ex_apprec_rec.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: ex_apprec_rec.c,v 12.1 2005/06/16 20:22:06 bostic Exp $
00008  */
00009 
00010 /*
00011  * This file is based on the template file ex_apprec_template.  Note that
00012  * because ex_apprec_mkdir, like most application-specific recovery functions,
00013  * does not make use of DB-private structures, it has actually been simplified
00014  * significantly.
00015  */
00016 
00017 #include <sys/types.h>
00018 #include <sys/stat.h>
00019 #include <errno.h>
00020 #include <stdlib.h>
00021 #include <unistd.h>
00022 
00023 #include <db.h>
00024 
00025 #include "ex_apprec.h"
00026 
00027 /*
00028  * ex_apprec_mkdir_recover --
00029  *      Recovery function for mkdir.
00030  *
00031  * PUBLIC: int ex_apprec_mkdir_recover
00032  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
00033  */
00034 int
00035 ex_apprec_mkdir_recover(dbenv, dbtp, lsnp, op, info)
00036         DB_ENV *dbenv;
00037         DBT *dbtp;
00038         DB_LSN *lsnp;
00039         db_recops op;
00040         void *info;
00041 {
00042         ex_apprec_mkdir_args *argp;
00043         int ret;
00044 
00045         argp = NULL;
00046 
00047         /*
00048          * Shut up the compiler--"info" is used for the recovery functions
00049          * belonging to transaction meta-operations such as txn_create, and
00050          * need not concern us here either.
00051          */
00052         info = NULL;
00053 
00054         if ((ret = ex_apprec_mkdir_read(dbenv, dbtp->data, &argp)) != 0)
00055                 goto out;
00056 
00057         switch (op) {
00058         case DB_TXN_ABORT:
00059         case DB_TXN_BACKWARD_ROLL:
00060                 /*
00061                  * If we're aborting, we need to remove the directory if it
00062                  * exists.  We log the trailing zero in pathnames, so we can
00063                  * simply pass the data part of the DBT into rmdir as a string.
00064                  * (Note that we don't have any alignment guarantees, but for
00065                  * a char * this doesn't matter.)
00066                  *
00067                  * Ignore all errors other than ENOENT;  DB may attempt to undo
00068                  * or redo operations without knowing whether they have already
00069                  * been done or undone, so we should never assume in a recovery
00070                  * function that the task definitely needs doing or undoing.
00071                  */
00072                 ret = rmdir(argp->dirname.data);
00073                 if (ret != 0 && errno != ENOENT)
00074                         dbenv->err(dbenv, ret, "Error in abort of mkdir");
00075                 else
00076                         ret = 0;
00077                 break;
00078         case DB_TXN_FORWARD_ROLL:
00079                 /*
00080                  * The forward direction is just the opposite;  here, we ignore
00081                  * EEXIST, because the directory may already exist.
00082                  */
00083                 ret = mkdir(argp->dirname.data, 0755);
00084                 if (ret != 0 && errno != EEXIST)
00085                         dbenv->err(dbenv,
00086                             ret, "Error in roll-forward of mkdir");
00087                 else
00088                         ret = 0;
00089                 break;
00090         default:
00091                 /*
00092                  * We might want to handle DB_TXN_PRINT or DB_TXN_APPLY here,
00093                  * too, but we don't try to print the log records and aren't
00094                  * using replication, so there's no need to in this example.
00095                  */
00096                 dbenv->errx(dbenv, "Unexpected operation type\n");
00097                 return (EINVAL);
00098         }
00099 
00100         /*
00101          * The recovery function is responsible for returning the LSN of the
00102          * previous log record in this transaction, so that transaction aborts
00103          * can follow the chain backwards.
00104          *
00105          * (If we'd wanted the LSN of this record earlier, we could have
00106          * read it from lsnp, as well--but because we weren't working with
00107          * pages or other objects that store their LSN and base recovery
00108          * decisions on it, we didn't need to.)
00109          */
00110         *lsnp = argp->prev_lsn;
00111 
00112 out:    if (argp != NULL)
00113                 free(argp);
00114         return (ret);
00115 }

Generated on Sun Dec 25 12:14:25 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2