1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1996,2008 Oracle. All rights reserved. 5 * 6 * $Id: ex_apprec_rec.c,v 12.7 2008/01/08 20:58:24 bostic Exp $ 7 */ 8 9/* 10 * This file is based on the template file ex_apprec_template. Note that 11 * because ex_apprec_mkdir, like most application-specific recovery functions, 12 * does not make use of DB-private structures, it has actually been simplified 13 * significantly. 14 */ 15 16#include <sys/stat.h> 17#include <sys/types.h> 18#include <errno.h> 19#include <stdlib.h> 20 21#include <db.h> 22 23#include "ex_apprec.h" 24 25/* 26 * ex_apprec_mkdir_recover -- 27 * Recovery function for mkdir. 28 * 29 * PUBLIC: int ex_apprec_mkdir_recover 30 * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops)); 31 */ 32int 33ex_apprec_mkdir_recover(dbenv, dbtp, lsnp, op) 34 DB_ENV *dbenv; 35 DBT *dbtp; 36 DB_LSN *lsnp; 37 db_recops op; 38{ 39 ex_apprec_mkdir_args *argp; 40 int ret; 41 42 argp = NULL; 43 44#ifdef DEBUG_RECOVER 45 ex_apprec_mkdir_print(dbenv, dbtp, lsnp, op); 46#endif 47 if ((ret = ex_apprec_mkdir_read(dbenv, dbtp->data, &argp)) != 0) 48 goto out; 49 50 switch (op) { 51 case DB_TXN_ABORT: 52 case DB_TXN_BACKWARD_ROLL: 53 /* 54 * If we're aborting, we need to remove the directory if it 55 * exists. We log the trailing zero in pathnames, so we can 56 * simply pass the data part of the DBT into rmdir as a string. 57 * (Note that we don't have any alignment guarantees, but for 58 * a char * this doesn't matter.) 59 * 60 * Ignore all errors other than ENOENT; DB may attempt to undo 61 * or redo operations without knowing whether they have already 62 * been done or undone, so we should never assume in a recovery 63 * function that the task definitely needs doing or undoing. 64 */ 65 ret = rmdir(argp->dirname.data); 66 if (ret != 0 && errno != ENOENT) 67 dbenv->err(dbenv, ret, "Error in abort of mkdir"); 68 else 69 ret = 0; 70 break; 71 case DB_TXN_FORWARD_ROLL: 72 /* 73 * The forward direction is just the opposite; here, we ignore 74 * EEXIST, because the directory may already exist. 75 */ 76 ret = mkdir(argp->dirname.data, 0755); 77 if (ret != 0 && errno != EEXIST) 78 dbenv->err(dbenv, 79 ret, "Error in roll-forward of mkdir"); 80 else 81 ret = 0; 82 break; 83 default: 84 /* 85 * We might want to handle DB_TXN_PRINT or DB_TXN_APPLY here, 86 * too, but we don't try to print the log records and aren't 87 * using replication, so there's no need to in this example. 88 */ 89 dbenv->errx(dbenv, "Unexpected operation type\n"); 90 return (EINVAL); 91 } 92 93 /* 94 * The recovery function is responsible for returning the LSN of the 95 * previous log record in this transaction, so that transaction aborts 96 * can follow the chain backwards. 97 * 98 * (If we'd wanted the LSN of this record earlier, we could have 99 * read it from lsnp, as well--but because we weren't working with 100 * pages or other objects that store their LSN and base recovery 101 * decisions on it, we didn't need to.) 102 */ 103 *lsnp = argp->prev_lsn; 104 105out: if (argp != NULL) 106 free(argp); 107 return (ret); 108} 109