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

ex_apprec.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.c,v 12.1 2005/06/16 20:22:06 bostic Exp $
00008  */
00009 
00010 #include <sys/types.h>
00011 #include <sys/stat.h>
00012 
00013 #include <errno.h>
00014 #include <stddef.h>
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <string.h>
00018 #include <unistd.h>
00019 
00020 #include <db.h>
00021 
00022 #include "ex_apprec.h"
00023 
00024 int     apprec_dispatch __P((DB_ENV *, DBT *, DB_LSN *, db_recops));
00025 int     open_env __P((const char *, FILE *, const char *, DB_ENV **));
00026 int     verify_absence __P((DB_ENV *, const char *));
00027 int     verify_presence __P((DB_ENV *, const char *));
00028 
00029 int
00030 main(argc, argv)
00031         int argc;
00032         char *argv[];
00033 {
00034         extern char *optarg;
00035         DB_ENV *dbenv;
00036         DB_LSN lsn;
00037         DB_TXN *txn;
00038         DBT dirnamedbt;
00039         int ret;
00040         const char *home;
00041         char ch, dirname[256];
00042         const char *progname = "ex_apprec";             /* Program name. */
00043 
00044         /* Default home. */
00045         home = "TESTDIR";
00046 
00047         while ((ch = getopt(argc, argv, "h:")) != EOF)
00048                 switch (ch) {
00049                 case 'h':
00050                         home = optarg;
00051                         break;
00052                 default:
00053                         fprintf(stderr, "usage: %s [-h home]", progname);
00054                         exit(EXIT_FAILURE);
00055                 }
00056 
00057         printf("Set up environment.\n");
00058         if ((ret = open_env(home, stderr, progname, &dbenv)) != 0)
00059                 return (EXIT_FAILURE);
00060 
00061         printf("Create a directory in a transaction.\n");
00062         /*
00063          * This application's convention is to log the full directory name,
00064          * including trailing nul.
00065          */
00066         memset(&dirnamedbt, 0, sizeof(dirnamedbt));
00067         sprintf(dirname, "%s/MYDIRECTORY", home);
00068         dirnamedbt.data = dirname;
00069         dirnamedbt.size = strlen(dirname) + 1;
00070 
00071         if ((ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0) {
00072                 dbenv->err(dbenv, ret, "txn_begin");
00073                 return (EXIT_FAILURE);
00074         }
00075 
00076         /* Remember, always log actions before you execute them! */
00077         memset(&lsn, 0, sizeof(lsn));
00078         if ((ret =
00079             ex_apprec_mkdir_log(dbenv, txn, &lsn, 0, &dirnamedbt)) != 0) {
00080                 dbenv->err(dbenv, ret, "mkdir_log");
00081                 return (EXIT_FAILURE);
00082         }
00083         if (mkdir(dirname, 0755) != 0) {
00084                 dbenv->err(dbenv, errno, "mkdir");
00085                 return (EXIT_FAILURE);
00086         }
00087 
00088         printf("Verify the directory's presence: ");
00089         verify_presence(dbenv, dirname);
00090         printf("check.\n");
00091 
00092         /* Now abort the transaction and verify that the directory goes away. */
00093         printf("Abort the transaction.\n");
00094         if ((ret = txn->abort(txn)) != 0) {
00095                 dbenv->err(dbenv, ret, "txn_abort");
00096                 return (EXIT_FAILURE);
00097         }
00098 
00099         printf("Verify the directory's absence: ");
00100         verify_absence(dbenv, dirname);
00101         printf("check.\n");
00102 
00103         /* Now do the same thing over again, only with a commit this time. */
00104         printf("Create a directory in a transaction.\n");
00105         memset(&dirnamedbt, 0, sizeof(dirnamedbt));
00106         sprintf(dirname, "%s/MYDIRECTORY", home);
00107         dirnamedbt.data = dirname;
00108         dirnamedbt.size = strlen(dirname) + 1;
00109         if ((ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0) {
00110                 dbenv->err(dbenv, ret, "txn_begin");
00111                 return (EXIT_FAILURE);
00112         }
00113 
00114         memset(&lsn, 0, sizeof(lsn));
00115         if ((ret =
00116             ex_apprec_mkdir_log(dbenv, txn, &lsn, 0, &dirnamedbt)) != 0) {
00117                 dbenv->err(dbenv, ret, "mkdir_log");
00118                 return (EXIT_FAILURE);
00119         }
00120         if (mkdir(dirname, 0755) != 0) {
00121                 dbenv->err(dbenv, errno, "mkdir");
00122                 return (EXIT_FAILURE);
00123         }
00124 
00125         printf("Verify the directory's presence: ");
00126         verify_presence(dbenv, dirname);
00127         printf("check.\n");
00128 
00129         /* Now abort the transaction and verify that the directory goes away. */
00130         printf("Commit the transaction.\n");
00131         if ((ret = txn->commit(txn, 0)) != 0) {
00132                 dbenv->err(dbenv, ret, "txn_commit");
00133                 return (EXIT_FAILURE);
00134         }
00135 
00136         printf("Verify the directory's presence: ");
00137         verify_presence(dbenv, dirname);
00138         printf("check.\n");
00139 
00140         printf("Now remove the directory, then run recovery.\n");
00141         if ((ret = dbenv->close(dbenv, 0)) != 0) {
00142                 fprintf(stderr, "DB_ENV->close: %s\n", db_strerror(ret));
00143                 return (EXIT_FAILURE);
00144         }
00145         if (rmdir(dirname) != 0) {
00146                 fprintf(stderr,
00147                     "%s: rmdir failed with error %s", progname,
00148                     strerror(errno));
00149         }
00150         verify_absence(dbenv, dirname);
00151 
00152         /* Opening with DB_RECOVER runs recovery. */
00153         if ((ret = open_env(home, stderr, progname, &dbenv)) != 0)
00154                 return (EXIT_FAILURE);
00155 
00156         printf("Verify the directory's presence: ");
00157         verify_presence(dbenv, dirname);
00158         printf("check.\n");
00159 
00160         /* Close the handle. */
00161         if ((ret = dbenv->close(dbenv, 0)) != 0) {
00162                 fprintf(stderr, "DB_ENV->close: %s\n", db_strerror(ret));
00163                 return (EXIT_FAILURE);
00164         }
00165 
00166         return (EXIT_SUCCESS);
00167 }
00168 
00169 int
00170 open_env(home, errfp, progname, dbenvp)
00171         const char *home, *progname;
00172         FILE *errfp;
00173         DB_ENV **dbenvp;
00174 {
00175         DB_ENV *dbenv;
00176         int ret;
00177 
00178         /*
00179          * Create an environment object and initialize it for error
00180          * reporting.
00181          */
00182         if ((ret = db_env_create(&dbenv, 0)) != 0) {
00183                 fprintf(errfp, "%s: %s\n", progname, db_strerror(ret));
00184                 return (ret);
00185         }
00186         dbenv->set_errfile(dbenv, errfp);
00187         dbenv->set_errpfx(dbenv, progname);
00188 
00189         /* Set up our custom recovery dispatch function. */
00190         if ((ret = dbenv->set_app_dispatch(dbenv, apprec_dispatch)) != 0) {
00191                 dbenv->err(dbenv, ret, "set_app_dispatch");
00192                 return (ret);
00193         }
00194 
00195         /*
00196          * Open the environment with full transactional support, running
00197          * recovery.
00198          */
00199         if ((ret =
00200             dbenv->open(dbenv, home, DB_CREATE | DB_RECOVER | DB_INIT_LOCK |
00201             DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN, 0)) != 0) {
00202                 dbenv->err(dbenv, ret, "environment open: %s", home);
00203                 dbenv->close(dbenv, 0);
00204                 return (ret);
00205         }
00206 
00207         *dbenvp = dbenv;
00208         return (0);
00209 }
00210 
00211 /*
00212  * Sample application dispatch function to handle user-specified log record
00213  * types.
00214  */
00215 int
00216 apprec_dispatch(dbenv, dbt, lsn, op)
00217         DB_ENV *dbenv;
00218         DBT *dbt;
00219         DB_LSN *lsn;
00220         db_recops op;
00221 {
00222         u_int32_t rectype;
00223 
00224         /* Pull the record type out of the log record. */
00225         memcpy(&rectype, dbt->data, sizeof(rectype));
00226 
00227         switch (rectype) {
00228         case DB_ex_apprec_mkdir:
00229                 return (ex_apprec_mkdir_recover(dbenv, dbt, lsn, op, NULL));
00230         default:
00231                 /*
00232                  * We've hit an unexpected, allegedly user-defined record
00233                  * type.
00234                  */
00235                 dbenv->errx(dbenv, "Unexpected log record type encountered");
00236                 return (EINVAL);
00237         }
00238 }
00239 
00240 int
00241 verify_absence(dbenv, dirname)
00242         DB_ENV *dbenv;
00243         const char *dirname;
00244 {
00245 
00246         if (access(dirname, F_OK) == 0) {
00247                 dbenv->errx(dbenv, "Error--directory present!");
00248                 exit(EXIT_FAILURE);
00249         }
00250 
00251         return (0);
00252 }
00253 
00254 int
00255 verify_presence(dbenv, dirname)
00256         DB_ENV *dbenv;
00257         const char *dirname;
00258 {
00259 
00260         if (access(dirname, F_OK) != 0) {
00261                 dbenv->errx(dbenv, "Error--directory not present!");
00262                 exit(EXIT_FAILURE);
00263         }
00264 
00265         return (0);
00266 }

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