00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "db_config.h"
00011
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014
00015 #include <string.h>
00016 #endif
00017
00018 #include "db_int.h"
00019 #include "dbinc/txn.h"
00020 #include "dbinc/db_page.h"
00021 #include "dbinc/db_dispatch.h"
00022 #include "dbinc/log.h"
00023 #include "dbinc_auto/db_auto.h"
00024 #include "dbinc_auto/crdel_auto.h"
00025 #include "dbinc_auto/db_ext.h"
00026
00027
00028
00029
00030
00031
00032
00033
00034 int
00035 __txn_map_gid(dbenv, gid, tdp, offp)
00036 DB_ENV *dbenv;
00037 u_int8_t *gid;
00038 TXN_DETAIL **tdp;
00039 roff_t *offp;
00040 {
00041 DB_TXNMGR *mgr;
00042 DB_TXNREGION *region;
00043
00044 mgr = dbenv->tx_handle;
00045 region = mgr->reginfo.primary;
00046
00047
00048
00049
00050
00051
00052 TXN_SYSTEM_LOCK(dbenv);
00053 for (*tdp = SH_TAILQ_FIRST(®ion->active_txn, __txn_detail);
00054 *tdp != NULL;
00055 *tdp = SH_TAILQ_NEXT(*tdp, links, __txn_detail))
00056 if (memcmp(gid, (*tdp)->xid, sizeof((*tdp)->xid)) == 0)
00057 break;
00058 TXN_SYSTEM_UNLOCK(dbenv);
00059
00060 if (*tdp == NULL)
00061 return (EINVAL);
00062
00063 *offp = R_OFFSET(&mgr->reginfo, *tdp);
00064 return (0);
00065 }
00066
00067
00068
00069
00070
00071
00072
00073
00074 int
00075 __txn_recover_pp(dbenv, preplist, count, retp, flags)
00076 DB_ENV *dbenv;
00077 DB_PREPLIST *preplist;
00078 long count, *retp;
00079 u_int32_t flags;
00080 {
00081 DB_THREAD_INFO *ip;
00082 int ret;
00083
00084 PANIC_CHECK(dbenv);
00085 ENV_REQUIRES_CONFIG(
00086 dbenv, dbenv->tx_handle, "txn_recover", DB_INIT_TXN);
00087
00088 if (F_ISSET((DB_TXNREGION *)
00089 ((DB_TXNMGR *)dbenv->tx_handle)->reginfo.primary,
00090 TXN_IN_RECOVERY)) {
00091 __db_err(dbenv, "operation not permitted while in recovery");
00092 return (EINVAL);
00093 }
00094
00095 ENV_ENTER(dbenv, ip);
00096 REPLICATION_WRAP(dbenv,
00097 (__txn_recover(dbenv, preplist, count, retp, flags)), ret);
00098 ENV_LEAVE(dbenv, ip);
00099 return (ret);
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109 int
00110 __txn_recover(dbenv, preplist, count, retp, flags)
00111 DB_ENV *dbenv;
00112 DB_PREPLIST *preplist;
00113 long count, *retp;
00114 u_int32_t flags;
00115 {
00116
00117
00118
00119
00120
00121 return (__txn_get_prepared(dbenv, NULL, preplist, count, retp, flags));
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 int
00138 __txn_get_prepared(dbenv, xids, txns, count, retp, flags)
00139 DB_ENV *dbenv;
00140 XID *xids;
00141 DB_PREPLIST *txns;
00142 long count;
00143 long *retp;
00144 u_int32_t flags;
00145 {
00146 DB_LSN min;
00147 DB_PREPLIST *prepp;
00148 DB_TXNMGR *mgr;
00149 DB_TXNREGION *region;
00150 TXN_DETAIL *td;
00151 XID *xidp;
00152 long i;
00153 int nrestores, open_files, ret;
00154
00155 *retp = 0;
00156
00157 MAX_LSN(min);
00158 prepp = txns;
00159 xidp = xids;
00160 nrestores = ret = 0;
00161 open_files = 1;
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 mgr = dbenv->tx_handle;
00172 region = mgr->reginfo.primary;
00173
00174
00175
00176
00177
00178
00179
00180
00181 TXN_SYSTEM_LOCK(dbenv);
00182 if (flags == DB_FIRST) {
00183 for (td = SH_TAILQ_FIRST(®ion->active_txn, __txn_detail);
00184 td != NULL;
00185 td = SH_TAILQ_NEXT(td, links, __txn_detail)) {
00186 if (F_ISSET(td, TXN_DTL_RESTORED))
00187 nrestores++;
00188 if (F_ISSET(td, TXN_DTL_COLLECTED))
00189 open_files = 0;
00190 F_CLR(td, TXN_DTL_COLLECTED);
00191 }
00192 mgr->n_discards = 0;
00193 } else
00194 open_files = 0;
00195
00196
00197 for (td = SH_TAILQ_FIRST(®ion->active_txn, __txn_detail);
00198 td != NULL && *retp < count;
00199 td = SH_TAILQ_NEXT(td, links, __txn_detail)) {
00200 if (td->status != TXN_PREPARED ||
00201 F_ISSET(td, TXN_DTL_COLLECTED))
00202 continue;
00203
00204 if (xids != NULL) {
00205 xidp->formatID = td->format;
00206
00207
00208
00209
00210
00211 xidp->gtrid_length = (long)td->gtrid;
00212 xidp->bqual_length = (long)td->bqual;
00213 memcpy(xidp->data, td->xid, sizeof(td->xid));
00214 xidp++;
00215 }
00216
00217 if (txns != NULL) {
00218 if ((ret = __os_calloc(dbenv,
00219 1, sizeof(DB_TXN), &prepp->txn)) != 0) {
00220 TXN_SYSTEM_UNLOCK(dbenv);
00221 goto err;
00222 }
00223 __txn_continue(dbenv, prepp->txn, td);
00224 F_SET(prepp->txn, TXN_MALLOC);
00225 memcpy(prepp->gid, td->xid, sizeof(td->xid));
00226 prepp++;
00227 }
00228
00229 if (!IS_ZERO_LSN(td->begin_lsn) &&
00230 log_compare(&td->begin_lsn, &min) < 0)
00231 min = td->begin_lsn;
00232
00233 (*retp)++;
00234 F_SET(td, TXN_DTL_COLLECTED);
00235 if (IS_ENV_REPLICATED(dbenv) &&
00236 (ret = __op_rep_enter(dbenv)) != 0)
00237 goto err;
00238 }
00239 TXN_SYSTEM_UNLOCK(dbenv);
00240
00241
00242
00243
00244 if (txns != NULL) {
00245 MUTEX_LOCK(dbenv, mgr->mutex);
00246 for (i = 0; i < *retp; i++)
00247 TAILQ_INSERT_TAIL(&mgr->txn_chain, txns[i].txn, links);
00248 MUTEX_UNLOCK(dbenv, mgr->mutex);
00249 }
00250
00251 if (open_files && nrestores && *retp != 0 && !IS_MAX_LSN(min)) {
00252 F_SET((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
00253 ret = __txn_openfiles(dbenv, &min, 0);
00254 F_CLR((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
00255 }
00256 return (0);
00257
00258 err: TXN_SYSTEM_UNLOCK(dbenv);
00259 return (ret);
00260 }
00261
00262
00263
00264
00265
00266
00267
00268 int
00269 __txn_openfiles(dbenv, min, force)
00270 DB_ENV *dbenv;
00271 DB_LSN *min;
00272 int force;
00273 {
00274 DBT data;
00275 DB_LOGC *logc;
00276 DB_LSN open_lsn;
00277 DB_TXNHEAD *txninfo;
00278 __txn_ckp_args *ckp_args;
00279 int ret, t_ret;
00280
00281
00282
00283
00284
00285 logc = NULL;
00286 if ((ret = __log_cursor(dbenv, &logc)) != 0)
00287 goto err;
00288
00289 memset(&data, 0, sizeof(data));
00290 if ((ret = __txn_getckp(dbenv, &open_lsn)) == 0)
00291 while (!IS_ZERO_LSN(open_lsn) && (ret =
00292 __log_c_get(logc, &open_lsn, &data, DB_SET)) == 0 &&
00293 (force ||
00294 (min != NULL && log_compare(min, &open_lsn) < 0))) {
00295
00296 if ((ret = __txn_ckp_read(dbenv,
00297 data.data, &ckp_args)) != 0) {
00298 __db_err(dbenv,
00299 "Invalid checkpoint record at [%lu][%lu]",
00300 (u_long)open_lsn.file,
00301 (u_long)open_lsn.offset);
00302 goto err;
00303 }
00304
00305
00306
00307
00308
00309 open_lsn = force ? ckp_args->ckp_lsn :
00310 ckp_args->last_ckp;
00311 __os_free(dbenv, ckp_args);
00312 if (force) {
00313 if ((ret = __log_c_get(logc, &open_lsn,
00314 &data, DB_SET)) != 0)
00315 goto err;
00316 break;
00317 }
00318 }
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329 if ((ret == DB_NOTFOUND || IS_ZERO_LSN(open_lsn)) && (ret =
00330 __log_c_get(logc, &open_lsn, &data, DB_FIRST)) != 0) {
00331 __db_err(dbenv, "No log records");
00332 goto err;
00333 }
00334
00335 if ((ret = __db_txnlist_init(dbenv, 0, 0, NULL, &txninfo)) != 0)
00336 goto err;
00337 ret = __env_openfiles(dbenv, logc,
00338 txninfo, &data, &open_lsn, NULL, 0, 0);
00339 if (txninfo != NULL)
00340 __db_txnlist_end(dbenv, txninfo);
00341
00342 err:
00343 if (logc != NULL && (t_ret = __log_c_close(logc)) != 0 && ret == 0)
00344 ret = t_ret;
00345 return (ret);
00346 }