00001 /*- 00002 * See the file LICENSE for redistribution information. 00003 * 00004 * Copyright (c) 1996, 1997, 1998, 1999, 2000 00005 * Sleepycat Software. All rights reserved. 00006 */ 00007 /* 00008 * Copyright (c) 1996 00009 * The President and Fellows of Harvard University. All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without 00012 * modification, are permitted provided that the following conditions 00013 * are met: 00014 * 1. Redistributions of source code must retain the above copyright 00015 * notice, this list of conditions and the following disclaimer. 00016 * 2. Redistributions in binary form must reproduce the above copyright 00017 * notice, this list of conditions and the following disclaimer in the 00018 * documentation and/or other materials provided with the distribution. 00019 * 3. Neither the name of the University nor the names of its contributors 00020 * may be used to endorse or promote products derived from this software 00021 * without specific prior written permission. 00022 * 00023 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 00024 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00025 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00026 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 00027 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00028 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00029 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00032 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00033 * SUCH DAMAGE. 00034 */ 00035 00036 #include "config.h" 00037 00038 #ifndef lint 00039 static const char revid[] = "$Id: txn__rec_8c-source.html,v 1.1 2008年06月08日 10:24:57 sebdiaz Exp $"; 00040 #endif /* not lint */ 00041 00042 #ifndef NO_SYSTEM_INCLUDES 00043 #include <sys/types.h> 00044 00045 #include <errno.h> 00046 #endif 00047 00048 #include "db_int.h" 00049 #include "db_page.h" 00050 #include "txn.h" 00051 #include "db_am.h" 00052 00053 /* 00054 * PUBLIC: int CDB___txn_regop_recover 00055 * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); 00056 * 00057 * These records are only ever written for commits. Normally, we redo any 00058 * committed transaction, however if we are doing recovery to a timestamp, then 00059 * we may treat transactions that commited after the timestamp as aborted. 00060 */ 00061 int 00062 CDB___txn_regop_recover(dbenv, dbtp, lsnp, op, info) 00063 DB_ENV *dbenv; 00064 DBT *dbtp; 00065 DB_LSN *lsnp; 00066 db_recops op; 00067 void *info; 00068 { 00069 __txn_regop_args *argp; 00070 int ret; 00071 00072 #ifdef DEBUG_RECOVER 00073 (void)CDB___txn_regop_print(dbenv, dbtp, lsnp, op, info); 00074 #endif 00075 COMPQUIET(op, 0); 00076 00077 if ((ret = CDB___txn_regop_read(dbenv, dbtp->data, &argp)) != 0) 00078 return (ret); 00079 00080 if (argp->opcode != TXN_COMMIT) 00081 ret = EINVAL; 00082 else if (dbenv->tx_timestamp == 0 || 00083 argp->timestamp <= (int32_t)dbenv->tx_timestamp) 00084 if (CDB___db_txnlist_find(info, argp->txnid->txnid) == DB_NOTFOUND) 00085 ret = CDB___db_txnlist_add(dbenv, info, argp->txnid->txnid); 00086 00087 if (ret == 0) 00088 *lsnp = argp->prev_lsn; 00089 CDB___os_free(argp, 0); 00090 00091 return (ret); 00092 } 00093 00094 /* 00095 * PUBLIC: int CDB___txn_xa_regop_recover 00096 * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); 00097 * 00098 * These records are only ever written for prepares. 00099 */ 00100 int 00101 CDB___txn_xa_regop_recover(dbenv, dbtp, lsnp, op, info) 00102 DB_ENV *dbenv; 00103 DBT *dbtp; 00104 DB_LSN *lsnp; 00105 db_recops op; 00106 void *info; 00107 { 00108 __txn_xa_regop_args *argp; 00109 int ret; 00110 00111 #ifdef DEBUG_RECOVER 00112 (void)CDB___txn_xa_regop_print(dbenv, dbtp, lsnp, op, info); 00113 #endif 00114 COMPQUIET(op, 0); 00115 COMPQUIET(dbenv, NULL); 00116 00117 if ((ret = CDB___txn_xa_regop_read(dbenv, dbtp->data, &argp)) != 0) 00118 return (ret); 00119 00120 if (argp->opcode != TXN_PREPARE) 00121 ret = EINVAL; 00122 else 00123 /* Call CDB___db_txnlist_find so that we update the maxid. */ 00124 (void)CDB___db_txnlist_find(info, argp->txnid->txnid); 00125 00126 if (ret == 0) 00127 *lsnp = argp->prev_lsn; 00128 CDB___os_free(argp, 0); 00129 00130 return (ret); 00131 } 00132 00133 /* 00134 * PUBLIC: int CDB___txn_ckp_recover 00135 * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); 00136 */ 00137 int 00138 CDB___txn_ckp_recover(dbenv, dbtp, lsnp, op, info) 00139 DB_ENV *dbenv; 00140 DBT *dbtp; 00141 DB_LSN *lsnp; 00142 db_recops op; 00143 void *info; 00144 { 00145 __txn_ckp_args *argp; 00146 int ret; 00147 00148 #ifdef DEBUG_RECOVER 00149 CDB___txn_ckp_print(dbenv, dbtp, lsnp, op, info); 00150 #endif 00151 COMPQUIET(dbenv, NULL); 00152 00153 if ((ret = CDB___txn_ckp_read(dbenv, dbtp->data, &argp)) != 0) 00154 return (ret); 00155 00156 /* 00157 * Check for 'restart' checkpoint record. This occurs when the 00158 * checkpoint lsn is equal to the lsn of the checkpoint record 00159 * and means that we could set the transaction ID back to 1, so 00160 * that we don't exhaust the transaction ID name space. 00161 */ 00162 if (argp->ckp_lsn.file == lsnp->file && 00163 argp->ckp_lsn.offset == lsnp->offset) 00164 CDB___db_txnlist_gen(info, DB_REDO(op) ? -1 : 1); 00165 00166 *lsnp = argp->last_ckp; 00167 CDB___os_free(argp, 0); 00168 return (DB_TXN_CKP); 00169 } 00170 00171 /* 00172 * CDB___txn_child_recover 00173 * Recover a commit record for a child transaction. 00174 * 00175 * PUBLIC: int CDB___txn_child_recover 00176 * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); 00177 */ 00178 int 00179 CDB___txn_child_recover(dbenv, dbtp, lsnp, op, info) 00180 DB_ENV *dbenv; 00181 DBT *dbtp; 00182 DB_LSN *lsnp; 00183 db_recops op; 00184 void *info; 00185 { 00186 __txn_child_args *argp; 00187 int ret; 00188 00189 #ifdef DEBUG_RECOVER 00190 (void)CDB___txn_child_print(dbenv, dbtp, lsnp, op, info); 00191 #endif 00192 COMPQUIET(op, 0); 00193 COMPQUIET(dbenv, NULL); 00194 00195 if ((ret = CDB___txn_child_read(dbenv, dbtp->data, &argp)) != 0) 00196 return (ret); 00197 00198 /* 00199 * We count the child as committed only if its parent committed. 00200 * So, if we are not yet in the transaction list, but our parent 00201 * is, then we should go ahead and commit. 00202 */ 00203 if (argp->opcode != TXN_COMMIT) 00204 ret = EINVAL; 00205 else 00206 if (CDB___db_txnlist_find(info, argp->parent) == 0 && 00207 CDB___db_txnlist_find(info, argp->txnid->txnid) == DB_NOTFOUND) 00208 ret = CDB___db_txnlist_add(dbenv, info, argp->txnid->txnid); 00209 00210 if (ret == 0) 00211 *lsnp = argp->prev_lsn; 00212 CDB___os_free(argp, 0); 00213 00214 return (ret); 00215 }