summaryrefslogtreecommitdiff
path: root/db/txn
diff options
context:
space:
mode:
authorjbj <devnull@localhost>2004-10-16 01:31:54 +0000
committerjbj <devnull@localhost>2004-10-16 01:31:54 +0000
commitd03f220fde879509cab2ac1c73b71b7efb52b737 (patch)
tree1e34bfadac0a6618d0e9a7933bad90063a785acf /db/txn
parent2dc699bfe049b9319ea3719f604d25940ff52004 (diff)
downloadlibrpm-tizen-d03f220fde879509cab2ac1c73b71b7efb52b737.tar.gz
librpm-tizen-d03f220fde879509cab2ac1c73b71b7efb52b737.tar.bz2
librpm-tizen-d03f220fde879509cab2ac1c73b71b7efb52b737.zip
... and in with the New ...
CVS patchset: 7471 CVS date: 2004/10/16 01:31:54
Diffstat (limited to 'db/txn')
-rw-r--r--db/txn/txn.c230
-rw-r--r--db/txn/txn.src19
-rw-r--r--db/txn/txn_auto.c954
-rw-r--r--db/txn/txn_autop.c281
-rw-r--r--db/txn/txn_method.c25
-rw-r--r--db/txn/txn_rec.c158
-rw-r--r--db/txn/txn_recover.c162
-rw-r--r--db/txn/txn_region.c91
-rw-r--r--db/txn/txn_stat.c315
-rw-r--r--db/txn/txn_util.c16
10 files changed, 1259 insertions, 992 deletions
diff --git a/db/txn/txn.c b/db/txn/txn.c
index 937046fa8..94755318b 100644
--- a/db/txn/txn.c
+++ b/db/txn/txn.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996-2003
+ * Copyright (c) 1996-2004
* Sleepycat Software. All rights reserved.
*/
/*
@@ -34,14 +34,12 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
+ *
+ * $Id: txn.c,v 11.248 2004/09/23 15:02:32 bostic Exp $
*/
#include "db_config.h"
-#ifndef lint
-static const char revid[] = "$Id: txn.c,v 11.219 2003/12/03 14:33:06 bostic Exp $";
-#endif /* not lint */
-
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <stdlib.h>
@@ -106,6 +104,7 @@ static int __txn_isvalid __P((const DB_TXN *, TXN_DETAIL **, txnop_t));
static int __txn_undo __P((DB_TXN *));
static int __txn_dispatch_undo __P((DB_ENV *,
DB_TXN *, DBT *, DB_LSN *, void *));
+static void __txn_set_begin_lsnp __P((DB_TXN *txn, DB_LSN **));
/*
* __txn_begin_pp --
@@ -126,7 +125,7 @@ __txn_begin_pp(dbenv, parent, txnpp, flags)
if ((ret = __db_fchk(dbenv,
"txn_begin", flags,
- DB_DIRTY_READ | DB_TXN_NOWAIT |
+ DB_DEGREE_2 | DB_DIRTY_READ | DB_TXN_NOWAIT |
DB_TXN_NOSYNC | DB_TXN_SYNC)) != 0)
return (ret);
if ((ret = __db_fcchk(dbenv,
@@ -185,6 +184,8 @@ __txn_begin(dbenv, parent, txnpp, flags)
TAILQ_INIT(&txn->events);
STAILQ_INIT(&txn->logs);
txn->flags = TXN_MALLOC;
+ if (LF_ISSET(DB_DEGREE_2))
+ F_SET(txn, TXN_DEGREE_2);
if (LF_ISSET(DB_DIRTY_READ))
F_SET(txn, TXN_DIRTY_READ);
if (LF_ISSET(DB_TXN_NOSYNC))
@@ -246,9 +247,8 @@ __txn_xa_begin(dbenv, txn)
PANIC_CHECK(dbenv);
/*
- * We need to initialize the transaction structure, but we must
- * be careful not to smash the links. We manually intialize the
- * structure.
+ * We need to initialize the transaction structure, but must be careful
+ * not to smash the links. We manually initialize the structure.
*/
txn->mgrp = dbenv->tx_handle;
TAILQ_INIT(&txn->kids);
@@ -306,7 +306,7 @@ __txn_begin_int(txn, internal)
int internal;
{
DB_ENV *dbenv;
- DB_LSN begin_lsn, null_lsn;
+ DB_LSN null_lsn;
DB_TXNMGR *mgr;
DB_TXNREGION *region;
TXN_DETAIL *td;
@@ -318,21 +318,6 @@ __txn_begin_int(txn, internal)
dbenv = mgr->dbenv;
region = mgr->reginfo.primary;
- /*
- * We do not have to write begin records (and if we do not, then we
- * need never write records for read-only transactions). However,
- * we do need to find the current LSN so that we can store it in the
- * transaction structure, so we can know where to take checkpoints.
- *
- * XXX
- * We should set this value when we write the first log record, not
- * here.
- */
- if (DBENV_LOGGING(dbenv))
- __log_txn_lsn(dbenv, &begin_lsn, NULL, NULL);
- else
- ZERO_LSN(begin_lsn);
-
R_LOCK(dbenv, &mgr->reginfo);
if (!F_ISSET(txn, TXN_COMPENSATE) && F_ISSET(region, TXN_IN_RECOVERY)) {
__db_err(dbenv, "operation not permitted during recovery");
@@ -372,14 +357,14 @@ __txn_begin_int(txn, internal)
&region->last_txnid, &region->cur_maxid);
__os_free(dbenv, ids);
if (DBENV_LOGGING(dbenv) &&
- (ret = __txn_recycle_log(dbenv, NULL,
- &null_lsn, 0, region->last_txnid, region->cur_maxid)) != 0)
+ (ret = __txn_recycle_log(dbenv, NULL, &null_lsn,
+ 0, region->last_txnid + 1, region->cur_maxid)) != 0)
goto err;
}
/* Allocate a new transaction detail structure. */
if ((ret =
- __db_shalloc(mgr->reginfo.addr, sizeof(TXN_DETAIL), 0, &td)) != 0) {
+ __db_shalloc(&mgr->reginfo, sizeof(TXN_DETAIL), 0, &td)) != 0) {
__db_err(dbenv,
"Unable to allocate memory for transaction detail");
goto err;
@@ -395,7 +380,7 @@ __txn_begin_int(txn, internal)
td->txnid = id;
ZERO_LSN(td->last_lsn);
- td->begin_lsn = begin_lsn;
+ ZERO_LSN(td->begin_lsn);
if (txn->parent != NULL)
td->parent = txn->parent->off;
else
@@ -404,7 +389,7 @@ __txn_begin_int(txn, internal)
td->flags = 0;
td->xa_status = 0;
- off = R_OFFSET(&mgr->reginfo, td);
+ off = R_OFFSET(dbenv, &mgr->reginfo, td);
R_UNLOCK(dbenv, &mgr->reginfo);
ZERO_LSN(txn->last_lsn);
@@ -417,6 +402,7 @@ __txn_begin_int(txn, internal)
txn->id = __txn_id;
txn->prepare = __txn_prepare;
txn->set_timeout = __txn_set_timeout;
+ txn->set_begin_lsnp = __txn_set_begin_lsnp;
/*
* If this is a transaction family, we must link the child to the
@@ -586,19 +572,20 @@ __txn_commit(txnp, flags)
}
/*
- * Process any aborted pages from our children.
- * We delay putting pages on the free list that are newly
- * allocated and then aborted so that we can undo other
- * allocations, if necessary, without worrying about
- * these pages which were not on the free list before.
+ * Process any aborted pages from our children. We delay putting pages
+ * on the free list that are newly allocated and then aborted so we can
+ * undo other allocations, if necessary, without worrying about these
+ * pages which were not on the free list before.
*/
if (txnp->txn_list != NULL) {
+#ifndef HAVE_FTRUNCATE
t_ret = __db_do_the_limbo(dbenv,
NULL, txnp, txnp->txn_list, LIMBO_NORMAL);
- __db_txnlist_end(dbenv, txnp->txn_list);
- txnp->txn_list = NULL;
if (t_ret != 0 && ret == 0)
ret = t_ret;
+#endif
+ __db_txnlist_end(dbenv, txnp->txn_list);
+ txnp->txn_list = NULL;
}
if (ret != 0)
@@ -608,13 +595,12 @@ __txn_commit(txnp, flags)
return (__txn_end(txnp, 1));
err: /*
- * If we are prepared, then we "must" be able to commit. We
- * panic here because even though the coordinator might be
- * able to retry it is not clear it would know to do that.
- * Otherwise we'll try to abort. If that is successful,
- * then we return whatever was in ret (i.e., the reason we failed).
- * If the abort was unsuccessful, then abort probably returned
- * DB_RUNRECOVERY and we need to propagate that up.
+ * If we are prepared, then we "must" be able to commit. We panic here
+ * because even though the coordinator might be able to retry it is not
+ * clear it would know to do that. Otherwise we'll try to abort. If
+ * that is successful, then we return whatever was in ret (that is, the
+ * reason we failed). If the abort was unsuccessful, abort probably
+ * returned DB_RUNRECOVERY and we need to propagate that up.
*/
if (td->status == TXN_PREPARED)
return (__db_panic(dbenv, ret));
@@ -702,7 +688,7 @@ __txn_abort(txnp)
request.op = DB_LOCK_UPGRADE_WRITE;
request.obj = NULL;
if ((ret = __lock_vec(
- dbenv, txnp->txnid, 0, &request, 1, NULL)) != 0)
+ dbenv, txnp->txnid, DB_LOCK_ABORT, &request, 1, NULL)) != 0)
return (__db_panic(dbenv, ret));
}
if ((ret = __txn_undo(txnp)) != 0)
@@ -818,10 +804,12 @@ __txn_prepare(txnp, gid)
if ((ret = __txn_commit(kid, DB_TXN_NOSYNC)) != 0)
return (ret);
+#ifndef HAVE_FTRUNCATE
if (txnp->txn_list != NULL &&
(ret = __db_do_the_limbo(dbenv,
NULL, txnp, txnp->txn_list, LIMBO_PREPARE)) != 0)
return (ret);
+#endif
/*
* In XA, the global transaction ID in the txn_detail structure is
* already set; in a non-XA environment, we must set it here. XA
@@ -866,7 +854,7 @@ __txn_prepare(txnp, gid)
__os_free(dbenv, request.obj->data);
if (ret != 0)
return (ret);
-
+
}
MUTEX_THREAD_LOCK(dbenv, txnp->mgrp->mutexp);
@@ -917,29 +905,30 @@ __txn_isvalid(txnp, tdp, op)
TXN_DETAIL **tdp;
txnop_t op;
{
+ DB_ENV *dbenv;
DB_TXNMGR *mgrp;
DB_TXNREGION *region;
TXN_DETAIL *tp;
mgrp = txnp->mgrp;
+ dbenv = mgrp->dbenv;
region = mgrp->reginfo.primary;
/* Check for recovery. */
if (!F_ISSET(txnp, TXN_COMPENSATE) &&
F_ISSET(region, TXN_IN_RECOVERY)) {
- __db_err(mgrp->dbenv,
- "operation not permitted during recovery");
+ __db_err(dbenv, "operation not permitted during recovery");
goto err;
}
/* Check for live cursors. */
if (txnp->cursors != 0) {
- __db_err(mgrp->dbenv, "transaction has active cursors");
+ __db_err(dbenv, "transaction has active cursors");
goto err;
}
/* Check transaction's state. */
- tp = (TXN_DETAIL *)R_ADDR(&mgrp->reginfo, txnp->off);
+ tp = (TXN_DETAIL *)R_ADDR(dbenv, &mgrp->reginfo, txnp->off);
if (tdp != NULL)
*tdp = tp;
@@ -961,8 +950,8 @@ __txn_isvalid(txnp, tdp, op)
*/
if (tp->status != TXN_PREPARED &&
!F_ISSET(tp, TXN_DTL_RESTORED)) {
- __db_err(mgrp->dbenv, "not a restored transaction");
- return (__db_panic(mgrp->dbenv, EINVAL));
+ __db_err(dbenv, "not a restored transaction");
+ return (__db_panic(dbenv, EINVAL));
}
return (0);
@@ -975,7 +964,7 @@ __txn_isvalid(txnp, tdp, op)
* I'm not arguing this is good, but I could imagine
* someone doing it.
*/
- __db_err(mgrp->dbenv,
+ __db_err(dbenv,
"Prepare disallowed on child transactions");
return (EINVAL);
}
@@ -989,7 +978,7 @@ __txn_isvalid(txnp, tdp, op)
switch (tp->status) {
case TXN_PREPARED:
if (op == TXN_OP_PREPARE) {
- __db_err(mgrp->dbenv, "transaction already prepared");
+ __db_err(dbenv, "transaction already prepared");
/*
* Txn_prepare doesn't blow away the user handle, so
* in this case, give the user the opportunity to
@@ -1003,7 +992,7 @@ __txn_isvalid(txnp, tdp, op)
case TXN_ABORTED:
case TXN_COMMITTED:
default:
- __db_err(mgrp->dbenv, "transaction already %s",
+ __db_err(dbenv, "transaction already %s",
tp->status == TXN_COMMITTED ? "committed" : "aborted");
goto err;
}
@@ -1015,7 +1004,7 @@ err: /*
* handles are dead by definition when we return, and if you use
* a cursor you forgot to close, we have no idea what will happen.
*/
- return (__db_panic(mgrp->dbenv, EINVAL));
+ return (__db_panic(dbenv, EINVAL));
}
/*
@@ -1066,14 +1055,14 @@ __txn_end(txnp, is_commit)
/* End the transaction. */
R_LOCK(dbenv, &mgr->reginfo);
- tp = (TXN_DETAIL *)R_ADDR(&mgr->reginfo, txnp->off);
+ tp = (TXN_DETAIL *)R_ADDR(dbenv, &mgr->reginfo, txnp->off);
SH_TAILQ_REMOVE(&region->active_txn, tp, links, __txn_detail);
if (F_ISSET(tp, TXN_DTL_RESTORED)) {
region->stat.st_nrestores--;
do_closefiles = region->stat.st_nrestores == 0;
}
- __db_shalloc_free(mgr->reginfo.addr, tp);
+ __db_shalloc_free(&mgr->reginfo, tp);
if (is_commit)
region->stat.st_ncommits++;
@@ -1163,6 +1152,7 @@ __txn_undo(txnp)
dbenv = mgr->dbenv;
logc = NULL;
txnlist = NULL;
+ ret = 0;
if (!DBENV_LOGGING(dbenv))
return (0);
@@ -1178,7 +1168,7 @@ __txn_undo(txnp)
* Allocate a txnlist for children and aborted page allocs.
* We need to associate the list with the maximal parent
* so that aborted pages are recovered when that transaction
- * is commited or aborted.
+ * is committed or aborted.
*/
for (ptxn = txnp->parent; ptxn != NULL && ptxn->parent != NULL;)
ptxn = ptxn->parent;
@@ -1240,7 +1230,9 @@ __txn_undo(txnp)
}
}
+#ifndef HAVE_FTRUNCATE
ret = __db_do_the_limbo(dbenv, ptxn, txnp, txnlist, LIMBO_NORMAL);
+#endif
err: if (logc != NULL && (t_ret = __log_c_close(logc)) != 0 && ret == 0)
ret = t_ret;
@@ -1285,7 +1277,7 @@ __txn_checkpoint_pp(dbenv, kbytes, minutes, flags)
__env_rep_enter(dbenv);
ret = __txn_checkpoint(dbenv, kbytes, minutes, flags);
if (rep_check)
- __env_rep_exit(dbenv);
+ __env_db_rep_exit(dbenv);
return (ret);
}
@@ -1304,13 +1296,13 @@ __txn_checkpoint(dbenv, kbytes, minutes, flags)
DB_LSN ckp_lsn, last_ckp;
DB_TXNMGR *mgr;
DB_TXNREGION *region;
- TXN_DETAIL *txnp;
+ REGENV *renv;
+ REGINFO *infop;
time_t last_ckp_time, now;
- u_int32_t bytes, gen, mbytes;
+ u_int32_t bytes, gen, id, logflags, mbytes;
int ret;
ret = gen = 0;
-
/*
* A client will only call through here during recovery,
* so just sync the Mpool and go home.
@@ -1327,6 +1319,12 @@ __txn_checkpoint(dbenv, kbytes, minutes, flags)
mgr = dbenv->tx_handle;
region = mgr->reginfo.primary;
+ infop = dbenv->reginfo;
+ renv = infop->primary;
+ /*
+ * No mutex is needed as envid is read-only once it is set.
+ */
+ id = renv->envid;
/*
* The checkpoint LSN is an LSN such that all transactions begun before
@@ -1369,20 +1367,8 @@ __txn_checkpoint(dbenv, kbytes, minutes, flags)
return (0);
}
-do_ckp: /*
- * Find the oldest active transaction and figure out its "begin" LSN.
- * This is the lowest LSN we can checkpoint, since any record written
- * after it may be involved in a transaction and may therefore need
- * to be undone in the case of an abort.
- */
- R_LOCK(dbenv, &mgr->reginfo);
- for (txnp = SH_TAILQ_FIRST(&region->active_txn, __txn_detail);
- txnp != NULL;
- txnp = SH_TAILQ_NEXT(txnp, links, __txn_detail))
- if (!IS_ZERO_LSN(txnp->begin_lsn) &&
- log_compare(&txnp->begin_lsn, &ckp_lsn) < 0)
- ckp_lsn = txnp->begin_lsn;
- R_UNLOCK(dbenv, &mgr->reginfo);
+do_ckp:
+ __txn_getactive(dbenv, &ckp_lsn);
if (MPOOL_ON(dbenv) && (ret = __memp_sync(dbenv, NULL)) != 0) {
__db_err(dbenv,
@@ -1411,10 +1397,12 @@ do_ckp: /*
* recovery from the ckp_lsn contained in this
* checkpoint.
*/
- if ((ret = __dbreg_open_files(dbenv)) != 0 ||
- (ret = __txn_ckp_log(dbenv, NULL,
- &ckp_lsn, DB_FLUSH | DB_LOG_PERM | DB_LOG_CHKPNT, &ckp_lsn,
- &last_ckp, (int32_t)time(NULL), gen)) != 0) {
+ logflags = DB_LOG_PERM | DB_LOG_CHKPNT;
+ if (!IS_RECOVERING(dbenv))
+ logflags |= DB_FLUSH;
+ if ((ret = __dbreg_log_files(dbenv)) != 0 ||
+ (ret = __txn_ckp_log(dbenv, NULL, &ckp_lsn, logflags,
+ &ckp_lsn, &last_ckp, (int32_t)time(NULL), id, gen)) != 0) {
__db_err(dbenv,
"txn_checkpoint: log failed at LSN [%ld %ld] %s",
(long)ckp_lsn.file, (long)ckp_lsn.offset,
@@ -1428,6 +1416,43 @@ do_ckp: /*
}
/*
+ * __txn_getactive --
+ * Find the oldest active transaction and figure out its "begin" LSN.
+ * This is the lowest LSN we can checkpoint, since any record written
+ * after it may be involved in a transaction and may therefore need
+ * to be undone in the case of an abort.
+ *
+ * We check both the file and offset for 0 since the lsn may be in
+ * transition. If it is then we don't care about this txn becuase it
+ * must be starting after we set the initial value of lsnp in the caller.
+ * All txns must initalize their begin_lsn before writing to the log.
+ *
+ * PUBLIC: void __txn_getactive __P((DB_ENV *, DB_LSN *));
+ */
+void
+__txn_getactive(dbenv, lsnp)
+ DB_ENV *dbenv;
+ DB_LSN *lsnp;
+{
+ DB_TXNMGR *mgr;
+ DB_TXNREGION *region;
+ TXN_DETAIL *txnp;
+
+ mgr = dbenv->tx_handle;
+ region = mgr->reginfo.primary;
+
+ R_LOCK(dbenv, &mgr->reginfo);
+ for (txnp = SH_TAILQ_FIRST(&region->active_txn, __txn_detail);
+ txnp != NULL;
+ txnp = SH_TAILQ_NEXT(txnp, links, __txn_detail))
+ if (txnp->begin_lsn.file != 0 &&
+ txnp->begin_lsn.offset != 0 &&
+ log_compare(&txnp->begin_lsn, lsnp) < 0)
+ *lsnp = txnp->begin_lsn;
+ R_UNLOCK(dbenv, &mgr->reginfo);
+}
+
+/*
* __txn_getckp --
* Get the LSN of the last transaction checkpoint.
*
@@ -1470,7 +1495,7 @@ __txn_activekids(dbenv, rectype, txnp)
{
/*
* On a child commit, we know that there are children (i.e., the
- * commiting child at the least. In that case, skip this check.
+ * committing child at the least. In that case, skip this check.
*/
if (F_ISSET(txnp, TXN_COMPENSATE) || rectype == DB___txn_child)
return (0);
@@ -1496,9 +1521,9 @@ __txn_force_abort(dbenv, buffer)
{
DB_CIPHER *db_cipher;
HDR *hdr;
- u_int32_t hdrlen, offset, opcode, rec_len, sum_len;
+ u_int32_t hdrlen, offset, opcode, sum_len;
u_int8_t *bp, *key, chksum[DB_MAC_KEY];
- size_t hdrsize;
+ size_t hdrsize, rec_len;
int ret;
db_cipher = dbenv->crypto_handle;
@@ -1536,7 +1561,7 @@ __txn_force_abort(dbenv, buffer)
return (__db_panic(dbenv, ret));
__db_chksum(buffer + hdrsize, rec_len, key, chksum);
- memcpy(buffer + SSZ(HDR, chksum), &chksum, sum_len);
+ memcpy(buffer + SSZA(HDR, chksum), chksum, sum_len);
return (0);
}
@@ -1563,8 +1588,8 @@ __txn_preclose(dbenv)
R_LOCK(dbenv, &mgr->reginfo);
if (region != NULL &&
- region->stat.st_nrestores
- <= mgr->n_discards && mgr->n_discards != 0)
+ region->stat.st_nrestores <= mgr->n_discards &&
+ mgr->n_discards != 0)
do_closefiles = 1;
R_UNLOCK(dbenv, &mgr->reginfo);
@@ -1624,10 +1649,10 @@ __txn_updateckp(dbenv, lsnp)
region = mgr->reginfo.primary;
/*
- * We want to make sure last_ckp only moves forward; since
- * we drop locks above and in log_put, it's possible
- * for two calls to __txn_ckp_log to finish in a different
- * order from how they were called.
+ * We want to make sure last_ckp only moves forward; since we drop
+ * locks above and in log_put, it's possible for two calls to
+ * __txn_ckp_log to finish in a different order from how they were
+ * called.
*/
R_LOCK(dbenv, &mgr->reginfo);
if (log_compare(&region->last_ckp, lsnp) < 0) {
@@ -1636,3 +1661,26 @@ __txn_updateckp(dbenv, lsnp)
}
R_UNLOCK(dbenv, &mgr->reginfo);
}
+
+/*
+ * txn_set_begin_lsnp --
+ * Set the pointer to the begin_lsn field if that field is zero.
+ */
+static void
+__txn_set_begin_lsnp(txn, rlsnp)
+ DB_TXN *txn;
+ DB_LSN **rlsnp;
+{
+ DB_LSN *lsnp;
+ TXN_DETAIL *td;
+
+ td = (TXN_DETAIL *)R_ADDR(txn->mgrp->dbenv,
+ &txn->mgrp->reginfo, txn->off);
+ while (td->parent != INVALID_ROFF)
+ td = (TXN_DETAIL *)R_ADDR(txn->mgrp->dbenv,
+ &txn->mgrp->reginfo, td->parent);
+
+ lsnp = &td->begin_lsn;
+ if (IS_ZERO_LSN(*lsnp))
+ *rlsnp = lsnp;
+}
diff --git a/db/txn/txn.src b/db/txn/txn.src
index 11afb4004..34bd8bd0b 100644
--- a/db/txn/txn.src
+++ b/db/txn/txn.src
@@ -1,17 +1,15 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996-2003
+ * Copyright (c) 1996-2004
* Sleepycat Software. All rights reserved.
*
- * $Id: txn.src,v 11.24 2003/11/14 05:32:33 ubell Exp $
+ * $Id: txn.src,v 11.33 2004/07/27 12:35:19 bostic Exp $
*/
PREFIX __txn
DBPRIVATE
-INCLUDE #include "db_config.h"
-INCLUDE
INCLUDE #ifndef NO_SYSTEM_INCLUDES
INCLUDE #include <sys/types.h>
INCLUDE
@@ -35,6 +33,8 @@ INCLUDE #include "dbinc/crypto.h"
INCLUDE #include "dbinc/db_page.h"
INCLUDE #include "dbinc/db_dispatch.h"
INCLUDE #include "dbinc/db_am.h"
+INCLUDE #include "dbinc/db_shash.h"
+INCLUDE #include "dbinc/lock.h"
INCLUDE #include "dbinc/log.h"
INCLUDE #include "dbinc/txn.h"
INCLUDE
@@ -46,9 +46,9 @@ INCLUDE
* either changes the Epoch or has a 64-bit offset.
*/
BEGIN regop 10
-ARG opcode u_int32_t lu
+ARG opcode u_int32_t ld
TIME timestamp int32_t ld
-DBT locks DBT s
+LOCKS locks DBT s
END
/*
@@ -64,11 +64,16 @@ END
* The previous checkpoint.
* timestamp:
* See comment in commit about timestamps.
+ * envid:
+ * Environment ID of this checkpoint.
+ * rep_gen:
+ * Persistent replication generation number.
*/
BEGIN ckp 11
POINTER ckp_lsn DB_LSN * lu
POINTER last_ckp DB_LSN * lu
TIME timestamp int32_t ld
+ARG envid u_int32_t ld
ARG rep_gen u_int32_t ld
END
@@ -94,7 +99,7 @@ ARG formatID int32_t ld
ARG gtrid u_int32_t u
ARG bqual u_int32_t u
POINTER begin_lsn DB_LSN * lu
-DBT locks DBT s
+LOCKS locks DBT s
END
/*
diff --git a/db/txn/txn_auto.c b/db/txn/txn_auto.c
index a8bd386b4..c5afa0cdb 100644
--- a/db/txn/txn_auto.c
+++ b/db/txn/txn_auto.c
@@ -1,4 +1,5 @@
/* Do not edit: automatically built by gen_rec.awk. */
+
#include "db_config.h"
#ifndef NO_SYSTEM_INCLUDES
@@ -24,6 +25,8 @@
#include "dbinc/db_page.h"
#include "dbinc/db_dispatch.h"
#include "dbinc/db_am.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
#include "dbinc/log.h"
#include "dbinc/txn.h"
@@ -44,31 +47,42 @@ __txn_regop_log(dbenv, txnid, ret_lsnp, flags,
{
DBT logrec;
DB_TXNLOGREC *lr;
- DB_LSN *lsnp, null_lsn;
+ DB_LSN *lsnp, null_lsn, *rlsnp;
u_int32_t zero, uinttmp, rectype, txn_num;
u_int npad;
u_int8_t *bp;
int is_durable, ret;
+ COMPQUIET(lr, NULL);
+
rectype = DB___txn_regop;
npad = 0;
+ rlsnp = ret_lsnp;
- is_durable = 1;
- if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
- F_ISSET(dbenv, DB_ENV_TXN_NOT_DURABLE)) {
+ ret = 0;
+
+ if (LF_ISSET(DB_LOG_NOT_DURABLE)) {
if (txnid == NULL)
return (0);
is_durable = 0;
- }
+ } else
+ is_durable = 1;
+
if (txnid == NULL) {
txn_num = 0;
- null_lsn.file = 0;
- null_lsn.offset = 0;
lsnp = &null_lsn;
+ null_lsn.file = null_lsn.offset = 0;
} else {
if (TAILQ_FIRST(&txnid->kids) != NULL &&
(ret = __txn_activekids(dbenv, rectype, txnid)) != 0)
return (ret);
+ /*
+ * We need to assign begin_lsn while holding region mutex.
+ * That assignment is done inside the DbEnv->log_put call,
+ * so pass in the appropriate memory location to be filled
+ * in by the log_put code.
+ */
+ DB_SET_BEGIN_LSNP(txnid, &rlsnp);
txn_num = txnid->txnid;
lsnp = &txnid->last_lsn;
}
@@ -83,27 +97,23 @@ __txn_regop_log(dbenv, txnid, ret_lsnp, flags,
logrec.size += npad;
}
- if (!is_durable && txnid != NULL) {
+ if (is_durable || txnid == NULL) {
+ if ((ret =
+ __os_malloc(dbenv, logrec.size, &logrec.data)) != 0)
+ return (ret);
+ } else {
if ((ret = __os_malloc(dbenv,
logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
return (ret);
#ifdef DIAGNOSTIC
- goto do_malloc;
-#else
- logrec.data = &lr->data;
-#endif
- } else {
-#ifdef DIAGNOSTIC
-do_malloc:
-#endif
if ((ret =
__os_malloc(dbenv, logrec.size, &logrec.data)) != 0) {
-#ifdef DIAGNOSTIC
- if (!is_durable && txnid != NULL)
- (void)__os_free(dbenv, lr);
-#endif
+ __os_free(dbenv, lr);
return (ret);
}
+#else
+ logrec.data = lr->data;
+#endif
}
if (npad > 0)
memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
@@ -140,137 +150,47 @@ do_malloc:
DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
+ if (is_durable || txnid == NULL) {
+ if ((ret = __log_put(dbenv, rlsnp,(DBT *)&logrec,
+ flags | DB_LOG_NOCOPY)) == 0 && txnid != NULL) {
+ txnid->last_lsn = *rlsnp;
+ if (rlsnp != ret_lsnp)
+ *ret_lsnp = *rlsnp;
+ }
+ } else {
#ifdef DIAGNOSTIC
- if (!is_durable && txnid != NULL) {
- /*
- * We set the debug bit if we are going
- * to log non-durable transactions so
- * they will be ignored by recovery.
+ /*
+ * Set the debug bit if we are going to log non-durable
+ * transactions so they will be ignored by recovery.
*/
memcpy(lr->data, logrec.data, logrec.size);
rectype |= DB_debug_FLAG;
memcpy(logrec.data, &rectype, sizeof(rectype));
- }
-#endif
- if (!is_durable && txnid != NULL) {
+ ret = __log_put(dbenv,
+ rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
+#else
ret = 0;
- STAILQ_INSERT_HEAD(&txnid->logs, lr, links);
-#ifdef DIAGNOSTIC
- goto do_put;
#endif
- } else{
-#ifdef DIAGNOSTIC
-do_put:
-#endif
- ret = __log_put(dbenv,
- ret_lsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
- if (ret == 0 && txnid != NULL)
- txnid->last_lsn = *ret_lsnp;
+ STAILQ_INSERT_HEAD(&txnid->logs, lr, links);
+ LSN_NOT_LOGGED(*ret_lsnp);
}
- if (!is_durable)
- LSN_NOT_LOGGED(*ret_lsnp);
#ifdef LOG_DIAGNOSTIC
if (ret != 0)
(void)__txn_regop_print(dbenv,
(DBT *)&logrec, ret_lsnp, NULL, NULL);
#endif
-#ifndef DIAGNOSTIC
+
+#ifdef DIAGNOSTIC
+ __os_free(dbenv, logrec.data);
+#else
if (is_durable || txnid == NULL)
-#endif
__os_free(dbenv, logrec.data);
-
+#endif
return (ret);
}
-#ifdef HAVE_REPLICATION
-/*
- * PUBLIC: int __txn_regop_getpgnos __P((DB_ENV *, DBT *, DB_LSN *,
- * PUBLIC: db_recops, void *));
- */
-int
-__txn_regop_getpgnos(dbenv, rec, lsnp, notused1, summary)
- DB_ENV *dbenv;
- DBT *rec;
- DB_LSN *lsnp;
- db_recops notused1;
- void *summary;
-{
- TXN_RECS *t;
- int ret;
- COMPQUIET(rec, NULL);
- COMPQUIET(notused1, DB_TXN_ABORT);
-
- t = (TXN_RECS *)summary;
-
- if ((ret = __rep_check_alloc(dbenv, t, 1)) != 0)
- return (ret);
-
- t->array[t->npages].flags = LSN_PAGE_NOLOCK;
- t->array[t->npages].lsn = *lsnp;
- t->array[t->npages].fid = DB_LOGFILEID_INVALID;
- memset(&t->array[t->npages].pgdesc, 0,
- sizeof(t->array[t->npages].pgdesc));
-
- t->npages++;
-
- return (0);
-}
-#endif /* HAVE_REPLICATION */
-
-/*
- * PUBLIC: int __txn_regop_print __P((DB_ENV *, DBT *, DB_LSN *,
- * PUBLIC: db_recops, void *));
- */
-int
-__txn_regop_print(dbenv, dbtp, lsnp, notused2, notused3)
- DB_ENV *dbenv;
- DBT *dbtp;
- DB_LSN *lsnp;
- db_recops notused2;
- void *notused3;
-{
- __txn_regop_args *argp;
- struct tm *lt;
- u_int32_t i;
- int ch;
- int ret;
-
- notused2 = DB_TXN_ABORT;
- notused3 = NULL;
-
- if ((ret = __txn_regop_read(dbenv, dbtp->data, &argp)) != 0)
- return (ret);
- (void)printf(
- "[%lu][%lu]__txn_regop%s: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
- (u_long)lsnp->file,
- (u_long)lsnp->offset,
- (argp->type & DB_debug_FLAG) ? "_debug" : "",
- (u_long)argp->type,
- (u_long)argp->txnid->txnid,
- (u_long)argp->prev_lsn.file,
- (u_long)argp->prev_lsn.offset);
- (void)printf("\topcode: %lu\n", (u_long)argp->opcode);
- lt = localtime((time_t *)&argp->timestamp);
- (void)printf(
- "\ttimestamp: %ld (%.24s, 20%02lu%02lu%02lu%02lu%02lu.%02lu)\n",
- (long)argp->timestamp, ctime((time_t *)&argp->timestamp),
- (u_long)lt->tm_year - 100, (u_long)lt->tm_mon+1,
- (u_long)lt->tm_mday, (u_long)lt->tm_hour,
- (u_long)lt->tm_min, (u_long)lt->tm_sec);
- (void)printf("\tlocks: ");
- for (i = 0; i < argp->locks.size; i++) {
- ch = ((u_int8_t *)argp->locks.data)[i];
- printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch);
- }
- (void)printf("\n");
- (void)printf("\n");
- __os_free(dbenv, argp);
-
- return (0);
-}
-
/*
* PUBLIC: int __txn_regop_read __P((DB_ENV *, void *, __txn_regop_args **));
*/
@@ -288,9 +208,9 @@ __txn_regop_read(dbenv, recbuf, argpp)
if ((ret = __os_malloc(dbenv,
sizeof(__txn_regop_args) + sizeof(DB_TXN), &argp)) != 0)
return (ret);
+ bp = recbuf;
argp->txnid = (DB_TXN *)&argp[1];
- bp = recbuf;
memcpy(&argp->type, bp, sizeof(argp->type));
bp += sizeof(argp->type);
@@ -320,11 +240,11 @@ __txn_regop_read(dbenv, recbuf, argpp)
/*
* PUBLIC: int __txn_ckp_log __P((DB_ENV *, DB_TXN *, DB_LSN *,
- * PUBLIC: u_int32_t, DB_LSN *, DB_LSN *, int32_t, u_int32_t));
+ * PUBLIC: u_int32_t, DB_LSN *, DB_LSN *, int32_t, u_int32_t, u_int32_t));
*/
int
__txn_ckp_log(dbenv, txnid, ret_lsnp, flags,
- ckp_lsn, last_ckp, timestamp, rep_gen)
+ ckp_lsn, last_ckp, timestamp, envid, rep_gen)
DB_ENV *dbenv;
DB_TXN *txnid;
DB_LSN *ret_lsnp;
@@ -332,35 +252,47 @@ __txn_ckp_log(dbenv, txnid, ret_lsnp, flags,
DB_LSN * ckp_lsn;
DB_LSN * last_ckp;
int32_t timestamp;
+ u_int32_t envid;
u_int32_t rep_gen;
{
DBT logrec;
DB_TXNLOGREC *lr;
- DB_LSN *lsnp, null_lsn;
+ DB_LSN *lsnp, null_lsn, *rlsnp;
u_int32_t uinttmp, rectype, txn_num;
u_int npad;
u_int8_t *bp;
int is_durable, ret;
+ COMPQUIET(lr, NULL);
+
rectype = DB___txn_ckp;
npad = 0;
+ rlsnp = ret_lsnp;
+
+ ret = 0;
- is_durable = 1;
- if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
- F_ISSET(dbenv, DB_ENV_TXN_NOT_DURABLE)) {
+ if (LF_ISSET(DB_LOG_NOT_DURABLE)) {
if (txnid == NULL)
return (0);
is_durable = 0;
- }
+ } else
+ is_durable = 1;
+
if (txnid == NULL) {
txn_num = 0;
- null_lsn.file = 0;
- null_lsn.offset = 0;
lsnp = &null_lsn;
+ null_lsn.file = null_lsn.offset = 0;
} else {
if (TAILQ_FIRST(&txnid->kids) != NULL &&
(ret = __txn_activekids(dbenv, rectype, txnid)) != 0)
return (ret);
+ /*
+ * We need to assign begin_lsn while holding region mutex.
+ * That assignment is done inside the DbEnv->log_put call,
+ * so pass in the appropriate memory location to be filled
+ * in by the log_put code.
+ */
+ DB_SET_BEGIN_LSNP(txnid, &rlsnp);
txn_num = txnid->txnid;
lsnp = &txnid->last_lsn;
}
@@ -369,6 +301,7 @@ __txn_ckp_log(dbenv, txnid, ret_lsnp, flags,
+ sizeof(*ckp_lsn)
+ sizeof(*last_ckp)
+ sizeof(u_int32_t)
+ + sizeof(u_int32_t)
+ sizeof(u_int32_t);
if (CRYPTO_ON(dbenv)) {
npad =
@@ -376,27 +309,23 @@ __txn_ckp_log(dbenv, txnid, ret_lsnp, flags,
logrec.size += npad;
}
- if (!is_durable && txnid != NULL) {
+ if (is_durable || txnid == NULL) {
+ if ((ret =
+ __os_malloc(dbenv, logrec.size, &logrec.data)) != 0)
+ return (ret);
+ } else {
if ((ret = __os_malloc(dbenv,
logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
return (ret);
#ifdef DIAGNOSTIC
- goto do_malloc;
-#else
- logrec.data = &lr->data;
-#endif
- } else {
-#ifdef DIAGNOSTIC
-do_malloc:
-#endif
if ((ret =
__os_malloc(dbenv, logrec.size, &logrec.data)) != 0) {
-#ifdef DIAGNOSTIC
- if (!is_durable && txnid != NULL)
- (void)__os_free(dbenv, lr);
-#endif
+ __os_free(dbenv, lr);
return (ret);
}
+#else
+ logrec.data = lr->data;
+#endif
}
if (npad > 0)
memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
@@ -428,139 +357,57 @@ do_malloc:
memcpy(bp, &uinttmp, sizeof(uinttmp));
bp += sizeof(uinttmp);
+ uinttmp = (u_int32_t)envid;
+ memcpy(bp, &uinttmp, sizeof(uinttmp));
+ bp += sizeof(uinttmp);
+
uinttmp = (u_int32_t)rep_gen;
memcpy(bp, &uinttmp, sizeof(uinttmp));
bp += sizeof(uinttmp);
DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
+ if (is_durable || txnid == NULL) {
+ if ((ret = __log_put(dbenv, rlsnp,(DBT *)&logrec,
+ flags | DB_LOG_NOCOPY)) == 0 && txnid != NULL) {
+ txnid->last_lsn = *rlsnp;
+ if (rlsnp != ret_lsnp)
+ *ret_lsnp = *rlsnp;
+ }
+ } else {
#ifdef DIAGNOSTIC
- if (!is_durable && txnid != NULL) {
- /*
- * We set the debug bit if we are going
- * to log non-durable transactions so
- * they will be ignored by recovery.
+ /*
+ * Set the debug bit if we are going to log non-durable
+ * transactions so they will be ignored by recovery.
*/
memcpy(lr->data, logrec.data, logrec.size);
rectype |= DB_debug_FLAG;
memcpy(logrec.data, &rectype, sizeof(rectype));
- }
-#endif
- if (!is_durable && txnid != NULL) {
+ ret = __log_put(dbenv,
+ rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
+#else
ret = 0;
- STAILQ_INSERT_HEAD(&txnid->logs, lr, links);
-#ifdef DIAGNOSTIC
- goto do_put;
-#endif
- } else{
-#ifdef DIAGNOSTIC
-do_put:
#endif
- ret = __log_put(dbenv,
- ret_lsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
- if (ret == 0 && txnid != NULL)
- txnid->last_lsn = *ret_lsnp;
+ STAILQ_INSERT_HEAD(&txnid->logs, lr, links);
+ LSN_NOT_LOGGED(*ret_lsnp);
}
- if (!is_durable)
- LSN_NOT_LOGGED(*ret_lsnp);
#ifdef LOG_DIAGNOSTIC
if (ret != 0)
(void)__txn_ckp_print(dbenv,
(DBT *)&logrec, ret_lsnp, NULL, NULL);
#endif
-#ifndef DIAGNOSTIC
+
+#ifdef DIAGNOSTIC
+ __os_free(dbenv, logrec.data);
+#else
if (is_durable || txnid == NULL)
-#endif
__os_free(dbenv, logrec.data);
-
+#endif
return (ret);
}
-#ifdef HAVE_REPLICATION
-/*
- * PUBLIC: int __txn_ckp_getpgnos __P((DB_ENV *, DBT *, DB_LSN *,
- * PUBLIC: db_recops, void *));
- */
-int
-__txn_ckp_getpgnos(dbenv, rec, lsnp, notused1, summary)
- DB_ENV *dbenv;
- DBT *rec;
- DB_LSN *lsnp;
- db_recops notused1;
- void *summary;
-{
- TXN_RECS *t;
- int ret;
- COMPQUIET(rec, NULL);
- COMPQUIET(notused1, DB_TXN_ABORT);
-
- t = (TXN_RECS *)summary;
-
- if ((ret = __rep_check_alloc(dbenv, t, 1)) != 0)
- return (ret);
-
- t->array[t->npages].flags = LSN_PAGE_NOLOCK;
- t->array[t->npages].lsn = *lsnp;
- t->array[t->npages].fid = DB_LOGFILEID_INVALID;
- memset(&t->array[t->npages].pgdesc, 0,
- sizeof(t->array[t->npages].pgdesc));
-
- t->npages++;
-
- return (0);
-}
-#endif /* HAVE_REPLICATION */
-
-/*
- * PUBLIC: int __txn_ckp_print __P((DB_ENV *, DBT *, DB_LSN *,
- * PUBLIC: db_recops, void *));
- */
-int
-__txn_ckp_print(dbenv, dbtp, lsnp, notused2, notused3)
- DB_ENV *dbenv;
- DBT *dbtp;
- DB_LSN *lsnp;
- db_recops notused2;
- void *notused3;
-{
- __txn_ckp_args *argp;
- struct tm *lt;
- int ret;
-
- notused2 = DB_TXN_ABORT;
- notused3 = NULL;
-
- if ((ret = __txn_ckp_read(dbenv, dbtp->data, &argp)) != 0)
- return (ret);
- (void)printf(
- "[%lu][%lu]__txn_ckp%s: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
- (u_long)lsnp->file,
- (u_long)lsnp->offset,
- (argp->type & DB_debug_FLAG) ? "_debug" : "",
- (u_long)argp->type,
- (u_long)argp->txnid->txnid,
- (u_long)argp->prev_lsn.file,
- (u_long)argp->prev_lsn.offset);
- (void)printf("\tckp_lsn: [%lu][%lu]\n",
- (u_long)argp->ckp_lsn.file, (u_long)argp->ckp_lsn.offset);
- (void)printf("\tlast_ckp: [%lu][%lu]\n",
- (u_long)argp->last_ckp.file, (u_long)argp->last_ckp.offset);
- lt = localtime((time_t *)&argp->timestamp);
- (void)printf(
- "\ttimestamp: %ld (%.24s, 20%02lu%02lu%02lu%02lu%02lu.%02lu)\n",
- (long)argp->timestamp, ctime((time_t *)&argp->timestamp),
- (u_long)lt->tm_year - 100, (u_long)lt->tm_mon+1,
- (u_long)lt->tm_mday, (u_long)lt->tm_hour,
- (u_long)lt->tm_min, (u_long)lt->tm_sec);
- (void)printf("\trep_gen: %ld\n", (long)argp->rep_gen);
- (void)printf("\n");
- __os_free(dbenv, argp);
-
- return (0);
-}
-
/*
* PUBLIC: int __txn_ckp_read __P((DB_ENV *, void *, __txn_ckp_args **));
*/
@@ -578,9 +425,9 @@ __txn_ckp_read(dbenv, recbuf, argpp)
if ((ret = __os_malloc(dbenv,
sizeof(__txn_ckp_args) + sizeof(DB_TXN), &argp)) != 0)
return (ret);
+ bp = recbuf;
argp->txnid = (DB_TXN *)&argp[1];
- bp = recbuf;
memcpy(&argp->type, bp, sizeof(argp->type));
bp += sizeof(argp->type);
@@ -601,6 +448,10 @@ __txn_ckp_read(dbenv, recbuf, argpp)
bp += sizeof(uinttmp);
memcpy(&uinttmp, bp, sizeof(uinttmp));
+ argp->envid = (u_int32_t)uinttmp;
+ bp += sizeof(uinttmp);
+
+ memcpy(&uinttmp, bp, sizeof(uinttmp));
argp->rep_gen = (u_int32_t)uinttmp;
bp += sizeof(uinttmp);
@@ -624,31 +475,42 @@ __txn_child_log(dbenv, txnid, ret_lsnp, flags,
{
DBT logrec;
DB_TXNLOGREC *lr;
- DB_LSN *lsnp, null_lsn;
+ DB_LSN *lsnp, null_lsn, *rlsnp;
u_int32_t uinttmp, rectype, txn_num;
u_int npad;
u_int8_t *bp;
int is_durable, ret;
+ COMPQUIET(lr, NULL);
+
rectype = DB___txn_child;
npad = 0;
+ rlsnp = ret_lsnp;
- is_durable = 1;
- if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
- F_ISSET(dbenv, DB_ENV_TXN_NOT_DURABLE)) {
+ ret = 0;
+
+ if (LF_ISSET(DB_LOG_NOT_DURABLE)) {
if (txnid == NULL)
return (0);
is_durable = 0;
- }
+ } else
+ is_durable = 1;
+
if (txnid == NULL) {
txn_num = 0;
- null_lsn.file = 0;
- null_lsn.offset = 0;
lsnp = &null_lsn;
+ null_lsn.file = null_lsn.offset = 0;
} else {
if (TAILQ_FIRST(&txnid->kids) != NULL &&
(ret = __txn_activekids(dbenv, rectype, txnid)) != 0)
return (ret);
+ /*
+ * We need to assign begin_lsn while holding region mutex.
+ * That assignment is done inside the DbEnv->log_put call,
+ * so pass in the appropriate memory location to be filled
+ * in by the log_put code.
+ */
+ DB_SET_BEGIN_LSNP(txnid, &rlsnp);
txn_num = txnid->txnid;
lsnp = &txnid->last_lsn;
}
@@ -662,27 +524,23 @@ __txn_child_log(dbenv, txnid, ret_lsnp, flags,
logrec.size += npad;
}
- if (!is_durable && txnid != NULL) {
+ if (is_durable || txnid == NULL) {
+ if ((ret =
+ __os_malloc(dbenv, logrec.size, &logrec.data)) != 0)
+ return (ret);
+ } else {
if ((ret = __os_malloc(dbenv,
logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
return (ret);
#ifdef DIAGNOSTIC
- goto do_malloc;
-#else
- logrec.data = &lr->data;
-#endif
- } else {
-#ifdef DIAGNOSTIC
-do_malloc:
-#endif
if ((ret =
__os_malloc(dbenv, logrec.size, &logrec.data)) != 0) {
-#ifdef DIAGNOSTIC
- if (!is_durable && txnid != NULL)
- (void)__os_free(dbenv, lr);
-#endif
+ __os_free(dbenv, lr);
return (ret);
}
+#else
+ logrec.data = lr->data;
+#endif
}
if (npad > 0)
memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
@@ -710,123 +568,47 @@ do_malloc:
DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
+ if (is_durable || txnid == NULL) {
+ if ((ret = __log_put(dbenv, rlsnp,(DBT *)&logrec,
+ flags | DB_LOG_NOCOPY)) == 0 && txnid != NULL) {
+ txnid->last_lsn = *rlsnp;
+ if (rlsnp != ret_lsnp)
+ *ret_lsnp = *rlsnp;
+ }
+ } else {
#ifdef DIAGNOSTIC
- if (!is_durable && txnid != NULL) {
- /*
- * We set the debug bit if we are going
- * to log non-durable transactions so
- * they will be ignored by recovery.
+ /*
+ * Set the debug bit if we are going to log non-durable
+ * transactions so they will be ignored by recovery.
*/
memcpy(lr->data, logrec.data, logrec.size);
rectype |= DB_debug_FLAG;
memcpy(logrec.data, &rectype, sizeof(rectype));
- }
-#endif
- if (!is_durable && txnid != NULL) {
+ ret = __log_put(dbenv,
+ rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
+#else
ret = 0;
- STAILQ_INSERT_HEAD(&txnid->logs, lr, links);
-#ifdef DIAGNOSTIC
- goto do_put;
-#endif
- } else{
-#ifdef DIAGNOSTIC
-do_put:
#endif
- ret = __log_put(dbenv,
- ret_lsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
- if (ret == 0 && txnid != NULL)
- txnid->last_lsn = *ret_lsnp;
+ STAILQ_INSERT_HEAD(&txnid->logs, lr, links);
+ LSN_NOT_LOGGED(*ret_lsnp);
}
- if (!is_durable)
- LSN_NOT_LOGGED(*ret_lsnp);
#ifdef LOG_DIAGNOSTIC
if (ret != 0)
(void)__txn_child_print(dbenv,
(DBT *)&logrec, ret_lsnp, NULL, NULL);
#endif
-#ifndef DIAGNOSTIC
+
+#ifdef DIAGNOSTIC
+ __os_free(dbenv, logrec.data);
+#else
if (is_durable || txnid == NULL)
-#endif
__os_free(dbenv, logrec.data);
-
+#endif
return (ret);
}
-#ifdef HAVE_REPLICATION
-/*
- * PUBLIC: int __txn_child_getpgnos __P((DB_ENV *, DBT *, DB_LSN *,
- * PUBLIC: db_recops, void *));
- */
-int
-__txn_child_getpgnos(dbenv, rec, lsnp, notused1, summary)
- DB_ENV *dbenv;
- DBT *rec;
- DB_LSN *lsnp;
- db_recops notused1;
- void *summary;
-{
- TXN_RECS *t;
- int ret;
- COMPQUIET(rec, NULL);
- COMPQUIET(notused1, DB_TXN_ABORT);
-
- t = (TXN_RECS *)summary;
-
- if ((ret = __rep_check_alloc(dbenv, t, 1)) != 0)
- return (ret);
-
- t->array[t->npages].flags = LSN_PAGE_NOLOCK;
- t->array[t->npages].lsn = *lsnp;
- t->array[t->npages].fid = DB_LOGFILEID_INVALID;
- memset(&t->array[t->npages].pgdesc, 0,
- sizeof(t->array[t->npages].pgdesc));
-
- t->npages++;
-
- return (0);
-}
-#endif /* HAVE_REPLICATION */
-
-/*
- * PUBLIC: int __txn_child_print __P((DB_ENV *, DBT *, DB_LSN *,
- * PUBLIC: db_recops, void *));
- */
-int
-__txn_child_print(dbenv, dbtp, lsnp, notused2, notused3)
- DB_ENV *dbenv;
- DBT *dbtp;
- DB_LSN *lsnp;
- db_recops notused2;
- void *notused3;
-{
- __txn_child_args *argp;
- int ret;
-
- notused2 = DB_TXN_ABORT;
- notused3 = NULL;
-
- if ((ret = __txn_child_read(dbenv, dbtp->data, &argp)) != 0)
- return (ret);
- (void)printf(
- "[%lu][%lu]__txn_child%s: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
- (u_long)lsnp->file,
- (u_long)lsnp->offset,
- (argp->type & DB_debug_FLAG) ? "_debug" : "",
- (u_long)argp->type,
- (u_long)argp->txnid->txnid,
- (u_long)argp->prev_lsn.file,
- (u_long)argp->prev_lsn.offset);
- (void)printf("\tchild: 0x%lx\n", (u_long)argp->child);
- (void)printf("\tc_lsn: [%lu][%lu]\n",
- (u_long)argp->c_lsn.file, (u_long)argp->c_lsn.offset);
- (void)printf("\n");
- __os_free(dbenv, argp);
-
- return (0);
-}
-
/*
* PUBLIC: int __txn_child_read __P((DB_ENV *, void *, __txn_child_args **));
*/
@@ -844,9 +626,9 @@ __txn_child_read(dbenv, recbuf, argpp)
if ((ret = __os_malloc(dbenv,
sizeof(__txn_child_args) + sizeof(DB_TXN), &argp)) != 0)
return (ret);
+ bp = recbuf;
argp->txnid = (DB_TXN *)&argp[1];
- bp = recbuf;
memcpy(&argp->type, bp, sizeof(argp->type));
bp += sizeof(argp->type);
@@ -890,31 +672,42 @@ __txn_xa_regop_log(dbenv, txnid, ret_lsnp, flags,
{
DBT logrec;
DB_TXNLOGREC *lr;
- DB_LSN *lsnp, null_lsn;
+ DB_LSN *lsnp, null_lsn, *rlsnp;
u_int32_t zero, uinttmp, rectype, txn_num;
u_int npad;
u_int8_t *bp;
int is_durable, ret;
+ COMPQUIET(lr, NULL);
+
rectype = DB___txn_xa_regop;
npad = 0;
+ rlsnp = ret_lsnp;
+
+ ret = 0;
- is_durable = 1;
- if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
- F_ISSET(dbenv, DB_ENV_TXN_NOT_DURABLE)) {
+ if (LF_ISSET(DB_LOG_NOT_DURABLE)) {
if (txnid == NULL)
return (0);
is_durable = 0;
- }
+ } else
+ is_durable = 1;
+
if (txnid == NULL) {
txn_num = 0;
- null_lsn.file = 0;
- null_lsn.offset = 0;
lsnp = &null_lsn;
+ null_lsn.file = null_lsn.offset = 0;
} else {
if (TAILQ_FIRST(&txnid->kids) != NULL &&
(ret = __txn_activekids(dbenv, rectype, txnid)) != 0)
return (ret);
+ /*
+ * We need to assign begin_lsn while holding region mutex.
+ * That assignment is done inside the DbEnv->log_put call,
+ * so pass in the appropriate memory location to be filled
+ * in by the log_put code.
+ */
+ DB_SET_BEGIN_LSNP(txnid, &rlsnp);
txn_num = txnid->txnid;
lsnp = &txnid->last_lsn;
}
@@ -933,27 +726,23 @@ __txn_xa_regop_log(dbenv, txnid, ret_lsnp, flags,
logrec.size += npad;
}
- if (!is_durable && txnid != NULL) {
+ if (is_durable || txnid == NULL) {
+ if ((ret =
+ __os_malloc(dbenv, logrec.size, &logrec.data)) != 0)
+ return (ret);
+ } else {
if ((ret = __os_malloc(dbenv,
logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
return (ret);
#ifdef DIAGNOSTIC
- goto do_malloc;
-#else
- logrec.data = &lr->data;
-#endif
- } else {
-#ifdef DIAGNOSTIC
-do_malloc:
-#endif
if ((ret =
__os_malloc(dbenv, logrec.size, &logrec.data)) != 0) {
-#ifdef DIAGNOSTIC
- if (!is_durable && txnid != NULL)
- (void)__os_free(dbenv, lr);
-#endif
+ __os_free(dbenv, lr);
return (ret);
}
+#else
+ logrec.data = lr->data;
+#endif
}
if (npad > 0)
memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
@@ -1015,140 +804,47 @@ do_malloc:
DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
+ if (is_durable || txnid == NULL) {
+ if ((ret = __log_put(dbenv, rlsnp,(DBT *)&logrec,
+ flags | DB_LOG_NOCOPY)) == 0 && txnid != NULL) {
+ txnid->last_lsn = *rlsnp;
+ if (rlsnp != ret_lsnp)
+ *ret_lsnp = *rlsnp;
+ }
+ } else {
#ifdef DIAGNOSTIC
- if (!is_durable && txnid != NULL) {
- /*
- * We set the debug bit if we are going
- * to log non-durable transactions so
- * they will be ignored by recovery.
+ /*
+ * Set the debug bit if we are going to log non-durable
+ * transactions so they will be ignored by recovery.
*/
memcpy(lr->data, logrec.data, logrec.size);
rectype |= DB_debug_FLAG;
memcpy(logrec.data, &rectype, sizeof(rectype));
- }
-#endif
- if (!is_durable && txnid != NULL) {
+ ret = __log_put(dbenv,
+ rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
+#else
ret = 0;
- STAILQ_INSERT_HEAD(&txnid->logs, lr, links);
-#ifdef DIAGNOSTIC
- goto do_put;
-#endif
- } else{
-#ifdef DIAGNOSTIC
-do_put:
#endif
- ret = __log_put(dbenv,
- ret_lsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
- if (ret == 0 && txnid != NULL)
- txnid->last_lsn = *ret_lsnp;
+ STAILQ_INSERT_HEAD(&txnid->logs, lr, links);
+ LSN_NOT_LOGGED(*ret_lsnp);
}
- if (!is_durable)
- LSN_NOT_LOGGED(*ret_lsnp);
#ifdef LOG_DIAGNOSTIC
if (ret != 0)
(void)__txn_xa_regop_print(dbenv,
(DBT *)&logrec, ret_lsnp, NULL, NULL);
#endif
-#ifndef DIAGNOSTIC
+
+#ifdef DIAGNOSTIC
+ __os_free(dbenv, logrec.data);
+#else
if (is_durable || txnid == NULL)
-#endif
__os_free(dbenv, logrec.data);
-
+#endif
return (ret);
}
-#ifdef HAVE_REPLICATION
-/*
- * PUBLIC: int __txn_xa_regop_getpgnos __P((DB_ENV *, DBT *,
- * PUBLIC: DB_LSN *, db_recops, void *));
- */
-int
-__txn_xa_regop_getpgnos(dbenv, rec, lsnp, notused1, summary)
- DB_ENV *dbenv;
- DBT *rec;
- DB_LSN *lsnp;
- db_recops notused1;
- void *summary;
-{
- TXN_RECS *t;
- int ret;
- COMPQUIET(rec, NULL);
- COMPQUIET(notused1, DB_TXN_ABORT);
-
- t = (TXN_RECS *)summary;
-
- if ((ret = __rep_check_alloc(dbenv, t, 1)) != 0)
- return (ret);
-
- t->array[t->npages].flags = LSN_PAGE_NOLOCK;
- t->array[t->npages].lsn = *lsnp;
- t->array[t->npages].fid = DB_LOGFILEID_INVALID;
- memset(&t->array[t->npages].pgdesc, 0,
- sizeof(t->array[t->npages].pgdesc));
-
- t->npages++;
-
- return (0);
-}
-#endif /* HAVE_REPLICATION */
-
-/*
- * PUBLIC: int __txn_xa_regop_print __P((DB_ENV *, DBT *, DB_LSN *,
- * PUBLIC: db_recops, void *));
- */
-int
-__txn_xa_regop_print(dbenv, dbtp, lsnp, notused2, notused3)
- DB_ENV *dbenv;
- DBT *dbtp;
- DB_LSN *lsnp;
- db_recops notused2;
- void *notused3;
-{
- __txn_xa_regop_args *argp;
- u_int32_t i;
- int ch;
- int ret;
-
- notused2 = DB_TXN_ABORT;
- notused3 = NULL;
-
- if ((ret = __txn_xa_regop_read(dbenv, dbtp->data, &argp)) != 0)
- return (ret);
- (void)printf(
- "[%lu][%lu]__txn_xa_regop%s: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
- (u_long)lsnp->file,
- (u_long)lsnp->offset,
- (argp->type & DB_debug_FLAG) ? "_debug" : "",
- (u_long)argp->type,
- (u_long)argp->txnid->txnid,
- (u_long)argp->prev_lsn.file,
- (u_long)argp->prev_lsn.offset);
- (void)printf("\topcode: %lu\n", (u_long)argp->opcode);
- (void)printf("\txid: ");
- for (i = 0; i < argp->xid.size; i++) {
- ch = ((u_int8_t *)argp->xid.data)[i];
- printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch);
- }
- (void)printf("\n");
- (void)printf("\tformatID: %ld\n", (long)argp->formatID);
- (void)printf("\tgtrid: %u\n", argp->gtrid);
- (void)printf("\tbqual: %u\n", argp->bqual);
- (void)printf("\tbegin_lsn: [%lu][%lu]\n",
- (u_long)argp->begin_lsn.file, (u_long)argp->begin_lsn.offset);
- (void)printf("\tlocks: ");
- for (i = 0; i < argp->locks.size; i++) {
- ch = ((u_int8_t *)argp->locks.data)[i];
- printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch);
- }
- (void)printf("\n");
- (void)printf("\n");
- __os_free(dbenv, argp);
-
- return (0);
-}
-
/*
* PUBLIC: int __txn_xa_regop_read __P((DB_ENV *, void *,
* PUBLIC: __txn_xa_regop_args **));
@@ -1167,9 +863,9 @@ __txn_xa_regop_read(dbenv, recbuf, argpp)
if ((ret = __os_malloc(dbenv,
sizeof(__txn_xa_regop_args) + sizeof(DB_TXN), &argp)) != 0)
return (ret);
+ bp = recbuf;
argp->txnid = (DB_TXN *)&argp[1];
- bp = recbuf;
memcpy(&argp->type, bp, sizeof(argp->type));
bp += sizeof(argp->type);
@@ -1230,31 +926,42 @@ __txn_recycle_log(dbenv, txnid, ret_lsnp, flags,
{
DBT logrec;
DB_TXNLOGREC *lr;
- DB_LSN *lsnp, null_lsn;
+ DB_LSN *lsnp, null_lsn, *rlsnp;
u_int32_t uinttmp, rectype, txn_num;
u_int npad;
u_int8_t *bp;
int is_durable, ret;
+ COMPQUIET(lr, NULL);
+
rectype = DB___txn_recycle;
npad = 0;
+ rlsnp = ret_lsnp;
+
+ ret = 0;
- is_durable = 1;
- if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
- F_ISSET(dbenv, DB_ENV_TXN_NOT_DURABLE)) {
+ if (LF_ISSET(DB_LOG_NOT_DURABLE)) {
if (txnid == NULL)
return (0);
is_durable = 0;
- }
+ } else
+ is_durable = 1;
+
if (txnid == NULL) {
txn_num = 0;
- null_lsn.file = 0;
- null_lsn.offset = 0;
lsnp = &null_lsn;
+ null_lsn.file = null_lsn.offset = 0;
} else {
if (TAILQ_FIRST(&txnid->kids) != NULL &&
(ret = __txn_activekids(dbenv, rectype, txnid)) != 0)
return (ret);
+ /*
+ * We need to assign begin_lsn while holding region mutex.
+ * That assignment is done inside the DbEnv->log_put call,
+ * so pass in the appropriate memory location to be filled
+ * in by the log_put code.
+ */
+ DB_SET_BEGIN_LSNP(txnid, &rlsnp);
txn_num = txnid->txnid;
lsnp = &txnid->last_lsn;
}
@@ -1268,27 +975,23 @@ __txn_recycle_log(dbenv, txnid, ret_lsnp, flags,
logrec.size += npad;
}
- if (!is_durable && txnid != NULL) {
+ if (is_durable || txnid == NULL) {
+ if ((ret =
+ __os_malloc(dbenv, logrec.size, &logrec.data)) != 0)
+ return (ret);
+ } else {
if ((ret = __os_malloc(dbenv,
logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
return (ret);
#ifdef DIAGNOSTIC
- goto do_malloc;
-#else
- logrec.data = &lr->data;
-#endif
- } else {
-#ifdef DIAGNOSTIC
-do_malloc:
-#endif
if ((ret =
__os_malloc(dbenv, logrec.size, &logrec.data)) != 0) {
-#ifdef DIAGNOSTIC
- if (!is_durable && txnid != NULL)
- (void)__os_free(dbenv, lr);
-#endif
+ __os_free(dbenv, lr);
return (ret);
}
+#else
+ logrec.data = lr->data;
+#endif
}
if (npad > 0)
memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
@@ -1314,122 +1017,47 @@ do_malloc:
DB_ASSERT((u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
+ if (is_durable || txnid == NULL) {
+ if ((ret = __log_put(dbenv, rlsnp,(DBT *)&logrec,
+ flags | DB_LOG_NOCOPY)) == 0 && txnid != NULL) {
+ txnid->last_lsn = *rlsnp;
+ if (rlsnp != ret_lsnp)
+ *ret_lsnp = *rlsnp;
+ }
+ } else {
#ifdef DIAGNOSTIC
- if (!is_durable && txnid != NULL) {
- /*
- * We set the debug bit if we are going
- * to log non-durable transactions so
- * they will be ignored by recovery.
+ /*
+ * Set the debug bit if we are going to log non-durable
+ * transactions so they will be ignored by recovery.
*/
memcpy(lr->data, logrec.data, logrec.size);
rectype |= DB_debug_FLAG;
memcpy(logrec.data, &rectype, sizeof(rectype));
- }
-#endif
- if (!is_durable && txnid != NULL) {
+ ret = __log_put(dbenv,
+ rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
+#else
ret = 0;
- STAILQ_INSERT_HEAD(&txnid->logs, lr, links);
-#ifdef DIAGNOSTIC
- goto do_put;
-#endif
- } else{
-#ifdef DIAGNOSTIC
-do_put:
#endif
- ret = __log_put(dbenv,
- ret_lsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
- if (ret == 0 && txnid != NULL)
- txnid->last_lsn = *ret_lsnp;
+ STAILQ_INSERT_HEAD(&txnid->logs, lr, links);
+ LSN_NOT_LOGGED(*ret_lsnp);
}
- if (!is_durable)
- LSN_NOT_LOGGED(*ret_lsnp);
#ifdef LOG_DIAGNOSTIC
if (ret != 0)
(void)__txn_recycle_print(dbenv,
(DBT *)&logrec, ret_lsnp, NULL, NULL);
#endif
-#ifndef DIAGNOSTIC
+
+#ifdef DIAGNOSTIC
+ __os_free(dbenv, logrec.data);
+#else
if (is_durable || txnid == NULL)
-#endif
__os_free(dbenv, logrec.data);
-
+#endif
return (ret);
}
-#ifdef HAVE_REPLICATION
-/*
- * PUBLIC: int __txn_recycle_getpgnos __P((DB_ENV *, DBT *, DB_LSN *,
- * PUBLIC: db_recops, void *));
- */
-int
-__txn_recycle_getpgnos(dbenv, rec, lsnp, notused1, summary)
- DB_ENV *dbenv;
- DBT *rec;
- DB_LSN *lsnp;
- db_recops notused1;
- void *summary;
-{
- TXN_RECS *t;
- int ret;
- COMPQUIET(rec, NULL);
- COMPQUIET(notused1, DB_TXN_ABORT);
-
- t = (TXN_RECS *)summary;
-
- if ((ret = __rep_check_alloc(dbenv, t, 1)) != 0)
- return (ret);
-
- t->array[t->npages].flags = LSN_PAGE_NOLOCK;
- t->array[t->npages].lsn = *lsnp;
- t->array[t->npages].fid = DB_LOGFILEID_INVALID;
- memset(&t->array[t->npages].pgdesc, 0,
- sizeof(t->array[t->npages].pgdesc));
-
- t->npages++;
-
- return (0);
-}
-#endif /* HAVE_REPLICATION */
-
-/*
- * PUBLIC: int __txn_recycle_print __P((DB_ENV *, DBT *, DB_LSN *,
- * PUBLIC: db_recops, void *));
- */
-int
-__txn_recycle_print(dbenv, dbtp, lsnp, notused2, notused3)
- DB_ENV *dbenv;
- DBT *dbtp;
- DB_LSN *lsnp;
- db_recops notused2;
- void *notused3;
-{
- __txn_recycle_args *argp;
- int ret;
-
- notused2 = DB_TXN_ABORT;
- notused3 = NULL;
-
- if ((ret = __txn_recycle_read(dbenv, dbtp->data, &argp)) != 0)
- return (ret);
- (void)printf(
- "[%lu][%lu]__txn_recycle%s: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
- (u_long)lsnp->file,
- (u_long)lsnp->offset,
- (argp->type & DB_debug_FLAG) ? "_debug" : "",
- (u_long)argp->type,
- (u_long)argp->txnid->txnid,
- (u_long)argp->prev_lsn.file,
- (u_long)argp->prev_lsn.offset);
- (void)printf("\tmin: %u\n", argp->min);
- (void)printf("\tmax: %u\n", argp->max);
- (void)printf("\n");
- __os_free(dbenv, argp);
-
- return (0);
-}
-
/*
* PUBLIC: int __txn_recycle_read __P((DB_ENV *, void *,
* PUBLIC: __txn_recycle_args **));
@@ -1448,9 +1076,9 @@ __txn_recycle_read(dbenv, recbuf, argpp)
if ((ret = __os_malloc(dbenv,
sizeof(__txn_recycle_args) + sizeof(DB_TXN), &argp)) != 0)
return (ret);
+ bp = recbuf;
argp->txnid = (DB_TXN *)&argp[1];
- bp = recbuf;
memcpy(&argp->type, bp, sizeof(argp->type));
bp += sizeof(argp->type);
@@ -1473,68 +1101,6 @@ __txn_recycle_read(dbenv, recbuf, argpp)
}
/*
- * PUBLIC: int __txn_init_print __P((DB_ENV *, int (***)(DB_ENV *,
- * PUBLIC: DBT *, DB_LSN *, db_recops, void *), size_t *));
- */
-int
-__txn_init_print(dbenv, dtabp, dtabsizep)
- DB_ENV *dbenv;
- int (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
- size_t *dtabsizep;
-{
- int ret;
-
- if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
- __txn_regop_print, DB___txn_regop)) != 0)
- return (ret);
- if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
- __txn_ckp_print, DB___txn_ckp)) != 0)
- return (ret);
- if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
- __txn_child_print, DB___txn_child)) != 0)
- return (ret);
- if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
- __txn_xa_regop_print, DB___txn_xa_regop)) != 0)
- return (ret);
- if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
- __txn_recycle_print, DB___txn_recycle)) != 0)
- return (ret);
- return (0);
-}
-
-#ifdef HAVE_REPLICATION
-/*
- * PUBLIC: int __txn_init_getpgnos __P((DB_ENV *, int (***)(DB_ENV *,
- * PUBLIC: DBT *, DB_LSN *, db_recops, void *), size_t *));
- */
-int
-__txn_init_getpgnos(dbenv, dtabp, dtabsizep)
- DB_ENV *dbenv;
- int (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
- size_t *dtabsizep;
-{
- int ret;
-
- if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
- __txn_regop_getpgnos, DB___txn_regop)) != 0)
- return (ret);
- if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
- __txn_ckp_getpgnos, DB___txn_ckp)) != 0)
- return (ret);
- if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
- __txn_child_getpgnos, DB___txn_child)) != 0)
- return (ret);
- if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
- __txn_xa_regop_getpgnos, DB___txn_xa_regop)) != 0)
- return (ret);
- if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
- __txn_recycle_getpgnos, DB___txn_recycle)) != 0)
- return (ret);
- return (0);
-}
-#endif /* HAVE_REPLICATION */
-
-/*
* PUBLIC: int __txn_init_recover __P((DB_ENV *, int (***)(DB_ENV *,
* PUBLIC: DBT *, DB_LSN *, db_recops, void *), size_t *));
*/
diff --git a/db/txn/txn_autop.c b/db/txn/txn_autop.c
new file mode 100644
index 000000000..dbcf61b9d
--- /dev/null
+++ b/db/txn/txn_autop.c
@@ -0,0 +1,281 @@
+/* Do not edit: automatically built by gen_rec.awk. */
+
+#include "db_config.h"
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif /* HAVE_SYS_TIME_H */
+#endif /* TIME_WITH SYS_TIME */
+
+#include <ctype.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "dbinc/crypto.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_dispatch.h"
+#include "dbinc/db_am.h"
+#include "dbinc/db_shash.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/txn.h"
+
+/*
+ * PUBLIC: int __txn_regop_print __P((DB_ENV *, DBT *, DB_LSN *,
+ * PUBLIC: db_recops, void *));
+ */
+int
+__txn_regop_print(dbenv, dbtp, lsnp, notused2, notused3)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops notused2;
+ void *notused3;
+{
+ __txn_regop_args *argp;
+ struct tm *lt;
+ time_t timeval;
+ int ret;
+
+ notused2 = DB_TXN_ABORT;
+ notused3 = NULL;
+
+ if ((ret = __txn_regop_read(dbenv, dbtp->data, &argp)) != 0)
+ return (ret);
+ (void)printf(
+ "[%lu][%lu]__txn_regop%s: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
+ (u_long)lsnp->file,
+ (u_long)lsnp->offset,
+ (argp->type & DB_debug_FLAG) ? "_debug" : "",
+ (u_long)argp->type,
+ (u_long)argp->txnid->txnid,
+ (u_long)argp->prev_lsn.file,
+ (u_long)argp->prev_lsn.offset);
+ (void)printf("\topcode: %ld\n", (long)argp->opcode);
+ timeval = (time_t)argp->timestamp;
+ lt = localtime(&timeval);
+ (void)printf(
+ "\ttimestamp: %ld (%.24s, 20%02lu%02lu%02lu%02lu%02lu.%02lu)\n",
+ (long)argp->timestamp, ctime(&timeval),
+ (u_long)lt->tm_year - 100, (u_long)lt->tm_mon+1,
+ (u_long)lt->tm_mday, (u_long)lt->tm_hour,
+ (u_long)lt->tm_min, (u_long)lt->tm_sec);
+ (void)printf("\tlocks: \n");
+ __lock_list_print(dbenv, &argp->locks);
+ (void)printf("\n");
+ __os_free(dbenv, argp);
+ return (0);
+}
+
+/*
+ * PUBLIC: int __txn_ckp_print __P((DB_ENV *, DBT *, DB_LSN *,
+ * PUBLIC: db_recops, void *));
+ */
+int
+__txn_ckp_print(dbenv, dbtp, lsnp, notused2, notused3)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops notused2;
+ void *notused3;
+{
+ __txn_ckp_args *argp;
+ struct tm *lt;
+ time_t timeval;
+ int ret;
+
+ notused2 = DB_TXN_ABORT;
+ notused3 = NULL;
+
+ if ((ret = __txn_ckp_read(dbenv, dbtp->data, &argp)) != 0)
+ return (ret);
+ (void)printf(
+ "[%lu][%lu]__txn_ckp%s: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
+ (u_long)lsnp->file,
+ (u_long)lsnp->offset,
+ (argp->type & DB_debug_FLAG) ? "_debug" : "",
+ (u_long)argp->type,
+ (u_long)argp->txnid->txnid,
+ (u_long)argp->prev_lsn.file,
+ (u_long)argp->prev_lsn.offset);
+ (void)printf("\tckp_lsn: [%lu][%lu]\n",
+ (u_long)argp->ckp_lsn.file, (u_long)argp->ckp_lsn.offset);
+ (void)printf("\tlast_ckp: [%lu][%lu]\n",
+ (u_long)argp->last_ckp.file, (u_long)argp->last_ckp.offset);
+ timeval = (time_t)argp->timestamp;
+ lt = localtime(&timeval);
+ (void)printf(
+ "\ttimestamp: %ld (%.24s, 20%02lu%02lu%02lu%02lu%02lu.%02lu)\n",
+ (long)argp->timestamp, ctime(&timeval),
+ (u_long)lt->tm_year - 100, (u_long)lt->tm_mon+1,
+ (u_long)lt->tm_mday, (u_long)lt->tm_hour,
+ (u_long)lt->tm_min, (u_long)lt->tm_sec);
+ (void)printf("\tenvid: %ld\n", (long)argp->envid);
+ (void)printf("\trep_gen: %ld\n", (long)argp->rep_gen);
+ (void)printf("\n");
+ __os_free(dbenv, argp);
+ return (0);
+}
+
+/*
+ * PUBLIC: int __txn_child_print __P((DB_ENV *, DBT *, DB_LSN *,
+ * PUBLIC: db_recops, void *));
+ */
+int
+__txn_child_print(dbenv, dbtp, lsnp, notused2, notused3)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops notused2;
+ void *notused3;
+{
+ __txn_child_args *argp;
+ int ret;
+
+ notused2 = DB_TXN_ABORT;
+ notused3 = NULL;
+
+ if ((ret = __txn_child_read(dbenv, dbtp->data, &argp)) != 0)
+ return (ret);
+ (void)printf(
+ "[%lu][%lu]__txn_child%s: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
+ (u_long)lsnp->file,
+ (u_long)lsnp->offset,
+ (argp->type & DB_debug_FLAG) ? "_debug" : "",
+ (u_long)argp->type,
+ (u_long)argp->txnid->txnid,
+ (u_long)argp->prev_lsn.file,
+ (u_long)argp->prev_lsn.offset);
+ (void)printf("\tchild: 0x%lx\n", (u_long)argp->child);
+ (void)printf("\tc_lsn: [%lu][%lu]\n",
+ (u_long)argp->c_lsn.file, (u_long)argp->c_lsn.offset);
+ (void)printf("\n");
+ __os_free(dbenv, argp);
+ return (0);
+}
+
+/*
+ * PUBLIC: int __txn_xa_regop_print __P((DB_ENV *, DBT *, DB_LSN *,
+ * PUBLIC: db_recops, void *));
+ */
+int
+__txn_xa_regop_print(dbenv, dbtp, lsnp, notused2, notused3)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops notused2;
+ void *notused3;
+{
+ __txn_xa_regop_args *argp;
+ u_int32_t i;
+ int ch;
+ int ret;
+
+ notused2 = DB_TXN_ABORT;
+ notused3 = NULL;
+
+ if ((ret = __txn_xa_regop_read(dbenv, dbtp->data, &argp)) != 0)
+ return (ret);
+ (void)printf(
+ "[%lu][%lu]__txn_xa_regop%s: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
+ (u_long)lsnp->file,
+ (u_long)lsnp->offset,
+ (argp->type & DB_debug_FLAG) ? "_debug" : "",
+ (u_long)argp->type,
+ (u_long)argp->txnid->txnid,
+ (u_long)argp->prev_lsn.file,
+ (u_long)argp->prev_lsn.offset);
+ (void)printf("\topcode: %lu\n", (u_long)argp->opcode);
+ (void)printf("\txid: ");
+ for (i = 0; i < argp->xid.size; i++) {
+ ch = ((u_int8_t *)argp->xid.data)[i];
+ printf(isprint(ch) || ch == 0x0a ? "%c" : "%#x ", ch);
+ }
+ (void)printf("\n");
+ (void)printf("\tformatID: %ld\n", (long)argp->formatID);
+ (void)printf("\tgtrid: %u\n", argp->gtrid);
+ (void)printf("\tbqual: %u\n", argp->bqual);
+ (void)printf("\tbegin_lsn: [%lu][%lu]\n",
+ (u_long)argp->begin_lsn.file, (u_long)argp->begin_lsn.offset);
+ (void)printf("\tlocks: \n");
+ __lock_list_print(dbenv, &argp->locks);
+ (void)printf("\n");
+ __os_free(dbenv, argp);
+ return (0);
+}
+
+/*
+ * PUBLIC: int __txn_recycle_print __P((DB_ENV *, DBT *, DB_LSN *,
+ * PUBLIC: db_recops, void *));
+ */
+int
+__txn_recycle_print(dbenv, dbtp, lsnp, notused2, notused3)
+ DB_ENV *dbenv;
+ DBT *dbtp;
+ DB_LSN *lsnp;
+ db_recops notused2;
+ void *notused3;
+{
+ __txn_recycle_args *argp;
+ int ret;
+
+ notused2 = DB_TXN_ABORT;
+ notused3 = NULL;
+
+ if ((ret = __txn_recycle_read(dbenv, dbtp->data, &argp)) != 0)
+ return (ret);
+ (void)printf(
+ "[%lu][%lu]__txn_recycle%s: rec: %lu txnid %lx prevlsn [%lu][%lu]\n",
+ (u_long)lsnp->file,
+ (u_long)lsnp->offset,
+ (argp->type & DB_debug_FLAG) ? "_debug" : "",
+ (u_long)argp->type,
+ (u_long)argp->txnid->txnid,
+ (u_long)argp->prev_lsn.file,
+ (u_long)argp->prev_lsn.offset);
+ (void)printf("\tmin: %u\n", argp->min);
+ (void)printf("\tmax: %u\n", argp->max);
+ (void)printf("\n");
+ __os_free(dbenv, argp);
+ return (0);
+}
+
+/*
+ * PUBLIC: int __txn_init_print __P((DB_ENV *, int (***)(DB_ENV *,
+ * PUBLIC: DBT *, DB_LSN *, db_recops, void *), size_t *));
+ */
+int
+__txn_init_print(dbenv, dtabp, dtabsizep)
+ DB_ENV *dbenv;
+ int (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
+ size_t *dtabsizep;
+{
+ int ret;
+
+ if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
+ __txn_regop_print, DB___txn_regop)) != 0)
+ return (ret);
+ if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
+ __txn_ckp_print, DB___txn_ckp)) != 0)
+ return (ret);
+ if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
+ __txn_child_print, DB___txn_child)) != 0)
+ return (ret);
+ if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
+ __txn_xa_regop_print, DB___txn_xa_regop)) != 0)
+ return (ret);
+ if ((ret = __db_add_recovery(dbenv, dtabp, dtabsizep,
+ __txn_recycle_print, DB___txn_recycle)) != 0)
+ return (ret);
+ return (0);
+}
diff --git a/db/txn/txn_method.c b/db/txn/txn_method.c
index f9359f455..c13f86dee 100644
--- a/db/txn/txn_method.c
+++ b/db/txn/txn_method.c
@@ -1,16 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996-2003
+ * Copyright (c) 1996-2004
* Sleepycat Software. All rights reserved.
+ *
+ * $Id: txn_method.c,v 11.72 2004/03/23 17:24:18 bostic Exp $
*/
#include "db_config.h"
-#ifndef lint
-static const char revid[] = "$Id: txn_method.c,v 11.66 2003/06/30 17:20:30 bostic Exp $";
-#endif /* not lint */
-
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
@@ -21,11 +19,14 @@ static const char revid[] = "$Id: txn_method.c,v 11.66 2003/06/30 17:20:30 bosti
#include <string.h>
#endif
+#ifdef HAVE_RPC
+#include "db_server.h"
+#endif
+
#include "db_int.h"
#include "dbinc/txn.h"
#ifdef HAVE_RPC
-#include "dbinc_auto/db_server.h"
#include "dbinc_auto/rpc_client_ext.h"
#endif
@@ -62,6 +63,7 @@ __txn_dbenv_create(dbenv)
dbenv->txn_checkpoint = __dbcl_txn_checkpoint;
dbenv->txn_recover = __dbcl_txn_recover;
dbenv->txn_stat = __dbcl_txn_stat;
+ dbenv->txn_stat_print = NULL;
dbenv->txn_begin = __dbcl_txn_begin;
} else
#endif
@@ -74,6 +76,7 @@ __txn_dbenv_create(dbenv)
dbenv->txn_checkpoint = __txn_checkpoint_pp;
dbenv->txn_recover = __txn_recover_pp;
dbenv->txn_stat = __txn_stat_pp;
+ dbenv->txn_stat_print = __txn_stat_print_pp;
dbenv->txn_begin = __txn_begin_pp;
}
}
@@ -83,7 +86,15 @@ __txn_get_tx_max(dbenv, tx_maxp)
DB_ENV *dbenv;
u_int32_t *tx_maxp;
{
- *tx_maxp = dbenv->tx_max;
+ ENV_NOT_CONFIGURED(dbenv,
+ dbenv->tx_handle, "DB_ENV->get_tx_max", DB_INIT_TXN);
+
+ if (TXN_ON(dbenv)) {
+ /* Cannot be set after open, no lock required to read. */
+ *tx_maxp = ((DB_TXNREGION *)
+ ((DB_TXNMGR *)dbenv->tx_handle)->reginfo.primary)->maxtxns;
+ } else
+ *tx_maxp = dbenv->tx_max;
return (0);
}
diff --git a/db/txn/txn_rec.c b/db/txn/txn_rec.c
index be4b016b5..ea885528f 100644
--- a/db/txn/txn_rec.c
+++ b/db/txn/txn_rec.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996-2003
+ * Copyright (c) 1996-2004
* Sleepycat Software. All rights reserved.
*/
/*
@@ -31,14 +31,12 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
+ *
+ * $Id: txn_rec.c,v 11.64 2004/09/22 17:41:10 bostic Exp $
*/
#include "db_config.h"
-#ifndef lint
-static const char revid[] = "$Id: txn_rec.c,v 11.54 2003/10/31 23:26:11 ubell Exp $";
-#endif /* not lint */
-
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
@@ -50,15 +48,13 @@ static const char revid[] = "$Id: txn_rec.c,v 11.54 2003/10/31 23:26:11 ubell Ex
#include "dbinc/txn.h"
#include "dbinc/db_am.h"
-#define IS_XA_TXN(R) (R->xid.size != 0)
-
/*
* PUBLIC: int __txn_regop_recover
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
*
* These records are only ever written for commits. Normally, we redo any
* committed transaction, however if we are doing recovery to a timestamp, then
- * we may treat transactions that commited after the timestamp as aborted.
+ * we may treat transactions that committed after the timestamp as aborted.
*/
int
__txn_regop_recover(dbenv, dbtp, lsnp, op, info)
@@ -71,6 +67,7 @@ __txn_regop_recover(dbenv, dbtp, lsnp, op, info)
DB_TXNHEAD *headp;
__txn_regop_args *argp;
int ret;
+ u_int32_t status;
#ifdef DEBUG_RECOVER
(void)__txn_regop_print(dbenv, dbtp, lsnp, op, info);
@@ -86,14 +83,16 @@ __txn_regop_recover(dbenv, dbtp, lsnp, op, info)
* apply to the BACKWARD_ROLL case.
*/
- if (op == DB_TXN_FORWARD_ROLL)
+ if (op == DB_TXN_FORWARD_ROLL) {
/*
* If this was a 2-phase-commit transaction, then it
* might already have been removed from the list, and
* that's OK. Ignore the return code from remove.
*/
- (void)__db_txnlist_remove(dbenv, info, argp->txnid->txnid);
- else if ((dbenv->tx_timestamp != 0 &&
+ if ((ret = __db_txnlist_remove(dbenv,
+ info, argp->txnid->txnid)) != DB_NOTFOUND && ret != 0)
+ goto err;
+ } else if ((dbenv->tx_timestamp != 0 &&
argp->timestamp > (int32_t)dbenv->tx_timestamp) ||
(!IS_ZERO_LSN(headp->trunc_lsn) &&
log_compare(&headp->trunc_lsn, lsnp) < 0)) {
@@ -101,32 +100,24 @@ __txn_regop_recover(dbenv, dbtp, lsnp, op, info)
* We failed either the timestamp check or the trunc_lsn check,
* so we treat this as an abort even if it was a commit record.
*/
- ret = __db_txnlist_update(dbenv,
- info, argp->txnid->txnid, TXN_ABORT, NULL);
-
- if (ret == TXN_IGNORE)
- ret = TXN_OK;
- else if (ret == TXN_NOTFOUND)
- ret = __db_txnlist_add(dbenv,
- info, argp->txnid->txnid, TXN_IGNORE, NULL);
- else if (ret != TXN_OK)
+ if ((ret = __db_txnlist_update(dbenv, info,
+ argp->txnid->txnid, TXN_ABORT, NULL, &status, 1)) != 0)
+ goto err;
+ else if (status != TXN_IGNORE && status != TXN_OK)
goto err;
- /* else ret = 0; Not necessary because TXN_OK == 0 */
} else {
/* This is a normal commit; mark it appropriately. */
- ret = __db_txnlist_update(dbenv,
- info, argp->txnid->txnid, argp->opcode, lsnp);
-
- if (ret == TXN_IGNORE)
- ret = TXN_OK;
- else if (ret == TXN_NOTFOUND)
- ret = __db_txnlist_add(dbenv,
+ if ((ret = __db_txnlist_update(dbenv,
+ info, argp->txnid->txnid, argp->opcode, lsnp,
+ &status, 0)) == DB_NOTFOUND) {
+ if ((ret = __db_txnlist_add(dbenv,
info, argp->txnid->txnid,
argp->opcode == TXN_ABORT ?
- TXN_IGNORE : argp->opcode, lsnp);
- else if (ret != TXN_OK)
+ TXN_IGNORE : argp->opcode, lsnp)) != 0)
+ goto err;
+ } else if (ret != 0 ||
+ (status != TXN_IGNORE && status != TXN_OK))
goto err;
- /* else ret = 0; Not necessary because TXN_OK == 0 */
}
if (ret == 0)
@@ -159,6 +150,7 @@ __txn_xa_regop_recover(dbenv, dbtp, lsnp, op, info)
{
__txn_xa_regop_args *argp;
int ret;
+ u_int32_t status;
#ifdef DEBUG_RECOVER
(void)__txn_xa_regop_print(dbenv, dbtp, lsnp, op, info);
@@ -172,7 +164,14 @@ __txn_xa_regop_recover(dbenv, dbtp, lsnp, op, info)
goto err;
}
- ret = __db_txnlist_find(dbenv, info, argp->txnid->txnid);
+ /*
+ * The return value here is either a DB_NOTFOUND or it is
+ * the transaction status from the list. It is not a normal
+ * error return, so we must make sure that in each of the
+ * cases below, we overwrite the ret value so we return
+ * appropriately.
+ */
+ ret = __db_txnlist_find(dbenv, info, argp->txnid->txnid, &status);
/*
* If we are rolling forward, then an aborted prepare
@@ -183,9 +182,9 @@ __txn_xa_regop_recover(dbenv, dbtp, lsnp, op, info)
if (op == DB_TXN_FORWARD_ROLL) {
if ((ret = __db_txnlist_remove(dbenv,
- info, argp->txnid->txnid)) != TXN_OK)
+ info, argp->txnid->txnid)) != 0)
goto txn_err;
- } else if (op == DB_TXN_BACKWARD_ROLL && ret == TXN_PREPARE) {
+ } else if (op == DB_TXN_BACKWARD_ROLL && status == TXN_PREPARE) {
/*
* On the backward pass, we have four possibilities:
* 1. The transaction is already committed, no-op.
@@ -200,7 +199,8 @@ __txn_xa_regop_recover(dbenv, dbtp, lsnp, op, info)
if (argp->opcode == TXN_ABORT) {
if ((ret = __db_txnlist_update(dbenv,
info, argp->txnid->txnid,
- TXN_ABORT, NULL)) != TXN_PREPARE)
+ TXN_ABORT, NULL, &status, 0)) != 0 &&
+ status != TXN_PREPARE)
goto txn_err;
ret = 0;
}
@@ -212,7 +212,7 @@ __txn_xa_regop_recover(dbenv, dbtp, lsnp, op, info)
* after recovery (see txn_recover).
*/
else if ((ret = __db_txnlist_remove(dbenv,
- info, argp->txnid->txnid)) != TXN_OK) {
+ info, argp->txnid->txnid)) != 0) {
txn_err: __db_err(dbenv,
"Transaction not in list %x", argp->txnid->txnid);
ret = DB_NOTFOUND;
@@ -287,7 +287,8 @@ __txn_child_recover(dbenv, dbtp, lsnp, op, info)
void *info;
{
__txn_child_args *argp;
- int c_stat, p_stat, ret;
+ int ret, t_ret;
+ u_int32_t c_stat, p_stat, tmpstat;
#ifdef DEBUG_RECOVER
(void)__txn_child_print(dbenv, dbtp, lsnp, op, info);
@@ -297,9 +298,9 @@ __txn_child_recover(dbenv, dbtp, lsnp, op, info)
/*
* This is a record in a PARENT's log trail indicating that a
- * child commited. If we are aborting, we need to update the
+ * child committed. If we are aborting, we need to update the
* parent's LSN array. If we are in recovery, then if the
- * parent is commiting, we set ourselves up to commit, else
+ * parent is committing, we set ourselves up to commit, else
* we do nothing.
*/
if (op == DB_TXN_ABORT) {
@@ -310,10 +311,35 @@ __txn_child_recover(dbenv, dbtp, lsnp, op, info)
info, &argp->c_lsn, TXNLIST_NEW);
} else if (op == DB_TXN_BACKWARD_ROLL) {
/* Child might exist -- look for it. */
- c_stat = __db_txnlist_find(dbenv, info, argp->child);
- p_stat = __db_txnlist_find(dbenv, info, argp->txnid->txnid);
+ ret = __db_txnlist_find(dbenv, info, argp->child, &c_stat);
+ t_ret =
+ __db_txnlist_find(dbenv, info, argp->txnid->txnid, &p_stat);
+ if (ret != 0 && ret != DB_NOTFOUND)
+ goto out;
+ if (t_ret != 0 && t_ret != DB_NOTFOUND) {
+ ret = t_ret;
+ goto out;
+ }
+ /*
+ * If the parent is in state COMMIT or IGNORE, then we apply
+ * that to the child, else we need to abort the child.
+ */
- if (c_stat == TXN_EXPECTED) {
+ if (ret == DB_NOTFOUND ||
+ c_stat == TXN_OK || c_stat == TXN_COMMIT) {
+ if (t_ret == DB_NOTFOUND ||
+ (p_stat != TXN_COMMIT && p_stat != TXN_IGNORE))
+ c_stat = TXN_ABORT;
+ else
+ c_stat = p_stat;
+
+ if (ret == DB_NOTFOUND)
+ ret = __db_txnlist_add(dbenv,
+ info, argp->child, c_stat, NULL);
+ else
+ ret = __db_txnlist_update(dbenv, info,
+ argp->child, c_stat, NULL, &tmpstat, 0);
+ } else if (c_stat == TXN_EXPECTED) {
/*
* The open after this create succeeded. If the
* parent succeeded, we don't want to redo; if the
@@ -328,9 +354,7 @@ __txn_child_recover(dbenv, dbtp, lsnp, op, info)
c_stat = TXN_ABORT;
}
ret = __db_txnlist_update(dbenv,
- info, argp->child, c_stat, NULL);
- if (ret > 0)
- ret = 0;
+ info, argp->child, c_stat, NULL, &tmpstat, 0);
} else if (c_stat == TXN_UNEXPECTED) {
/*
* The open after this create failed. If the parent
@@ -341,54 +365,30 @@ __txn_child_recover(dbenv, dbtp, lsnp, op, info)
*/
ret = __db_txnlist_update(dbenv, info, argp->child,
p_stat == TXN_COMMIT ? TXN_COMMIT : TXN_IGNORE,
- NULL);
- if (ret > 0)
- ret = 0;
- } else if (c_stat != TXN_IGNORE) {
- switch (p_stat) {
- case TXN_COMMIT:
- c_stat = TXN_COMMIT;
- break;
- case TXN_IGNORE:
- c_stat = TXN_IGNORE;
- break;
- default:
- c_stat = TXN_ABORT;
- }
-
- ret = __db_txnlist_add(dbenv,
- info, argp->child, c_stat, NULL);
+ NULL, &tmpstat, 0);
}
} else if (op == DB_TXN_OPENFILES) {
/*
* If we have a partial subtransaction, then the whole
* transaction should be ignored.
*/
- c_stat = __db_txnlist_find(dbenv, info, argp->child);
- if (c_stat == TXN_NOTFOUND) {
- p_stat =
- __db_txnlist_find(dbenv, info, argp->txnid->txnid);
- if (p_stat == TXN_NOTFOUND)
- ret = __db_txnlist_add(dbenv, info,
- argp->txnid->txnid, TXN_IGNORE, NULL);
- else
- ret = __db_txnlist_update(dbenv, info,
- argp->txnid->txnid, TXN_IGNORE, NULL);
- }
+ if ((ret = __db_txnlist_find(dbenv,
+ info, argp->child, &c_stat)) == DB_NOTFOUND)
+ ret = __db_txnlist_update(dbenv, info,
+ argp->txnid->txnid, TXN_IGNORE,
+ NULL, &p_stat, 1);
} else if (DB_REDO(op)) {
/* Forward Roll */
if ((ret =
- __db_txnlist_remove(dbenv, info, argp->child)) != TXN_OK) {
+ __db_txnlist_remove(dbenv, info, argp->child)) != 0)
__db_err(dbenv,
"Transaction not in list %x", argp->child);
- ret = DB_NOTFOUND;
- }
}
if (ret == 0)
*lsnp = argp->prev_lsn;
- __os_free(dbenv, argp);
+out: __os_free(dbenv, argp);
return (ret);
}
@@ -401,7 +401,7 @@ __txn_child_recover(dbenv, dbtp, lsnp, op, info)
* or commit and we need to respond correctly.
*
* lsnp is the LSN of the returned LSN
- * argp is the perpare record (in an appropriate structure)
+ * argp is the prepare record (in an appropriate structure)
*
* PUBLIC: int __txn_restore_txn __P((DB_ENV *,
* PUBLIC: DB_LSN *, __txn_xa_regop_args *));
@@ -426,7 +426,7 @@ __txn_restore_txn(dbenv, lsnp, argp)
/* Allocate a new transaction detail structure. */
if ((ret =
- __db_shalloc(mgr->reginfo.addr, sizeof(TXN_DETAIL), 0, &td)) != 0) {
+ __db_shalloc(&mgr->reginfo, sizeof(TXN_DETAIL), 0, &td)) != 0) {
R_UNLOCK(dbenv, &mgr->reginfo);
return (ret);
}
diff --git a/db/txn/txn_recover.c b/db/txn/txn_recover.c
index 753a84dd3..0d15f57eb 100644
--- a/db/txn/txn_recover.c
+++ b/db/txn/txn_recover.c
@@ -1,16 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 2001-2003
+ * Copyright (c) 2001-2004
* Sleepycat Software. All rights reserved.
+ *
+ * $Id: txn_recover.c,v 1.53 2004/09/22 17:41:10 bostic Exp $
*/
#include "db_config.h"
-#ifndef lint
-static const char revid[] = "$Id: txn_recover.c,v 1.43 2003/09/16 20:50:17 sue Exp $";
-#endif /* not lint */
-
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
@@ -65,14 +63,14 @@ __txn_continue(env, txnp, td, off)
* Return the txn that corresponds to this global ID.
*
* PUBLIC: int __txn_map_gid __P((DB_ENV *,
- * PUBLIC: u_int8_t *, TXN_DETAIL **, size_t *));
+ * PUBLIC: u_int8_t *, TXN_DETAIL **, roff_t *));
*/
int
__txn_map_gid(dbenv, gid, tdp, offp)
DB_ENV *dbenv;
u_int8_t *gid;
TXN_DETAIL **tdp;
- size_t *offp;
+ roff_t *offp;
{
DB_TXNMGR *mgr;
DB_TXNREGION *tmr;
@@ -96,7 +94,7 @@ __txn_map_gid(dbenv, gid, tdp, offp)
if (*tdp == NULL)
return (EINVAL);
- *offp = R_OFFSET(&mgr->reginfo, *tdp);
+ *offp = R_OFFSET(dbenv, &mgr->reginfo, *tdp);
return (0);
}
@@ -132,7 +130,7 @@ __txn_recover_pp(dbenv, preplist, count, retp, flags)
__env_rep_enter(dbenv);
ret = __txn_recover(dbenv, preplist, count, retp, flags);
if (rep_check)
- __env_rep_exit(dbenv);
+ __env_db_rep_exit(dbenv);
return (ret);
}
@@ -180,22 +178,17 @@ __txn_get_prepared(dbenv, xids, txns, count, retp, flags)
long *retp;
u_int32_t flags;
{
- DBT data;
- DB_LOGC *logc;
- DB_LSN min, open_lsn;
+ DB_LSN min;
DB_PREPLIST *prepp;
DB_TXNMGR *mgr;
DB_TXNREGION *tmr;
TXN_DETAIL *td;
XID *xidp;
- __txn_ckp_args *ckp_args;
long i;
- int nrestores, open_files, ret, t_ret;
- void *txninfo;
+ int nrestores, open_files, ret;
*retp = 0;
- logc = NULL;
MAX_LSN(min);
prepp = txns;
xidp = xids;
@@ -245,8 +238,13 @@ __txn_get_prepared(dbenv, xids, txns, count, retp, flags)
if (xids != NULL) {
xidp->formatID = td->format;
- xidp->gtrid_length = td->gtrid;
- xidp->bqual_length = td->bqual;
+ /*
+ * XID structure uses longs; we use u_int32_t's as we
+ * log them to disk. Cast them to make the conversion
+ * explicit.
+ */
+ xidp->gtrid_length = (long)td->gtrid;
+ xidp->bqual_length = (long)td->bqual;
memcpy(xidp->data, td->xid, sizeof(td->xid));
xidp++;
}
@@ -258,13 +256,14 @@ __txn_get_prepared(dbenv, xids, txns, count, retp, flags)
goto err;
}
__txn_continue(dbenv,
- prepp->txn, td, R_OFFSET(&mgr->reginfo, td));
+ prepp->txn, td, R_OFFSET(dbenv, &mgr->reginfo, td));
F_SET(prepp->txn, TXN_MALLOC);
memcpy(prepp->gid, td->xid, sizeof(td->xid));
prepp++;
}
- if (log_compare(&td->begin_lsn, &min) < 0)
+ if (!IS_ZERO_LSN(td->begin_lsn) &&
+ log_compare(&td->begin_lsn, &min) < 0)
min = td->begin_lsn;
(*retp)++;
@@ -283,59 +282,96 @@ __txn_get_prepared(dbenv, xids, txns, count, retp, flags)
}
if (open_files && nrestores && *retp != 0 && !IS_MAX_LSN(min)) {
- /*
- * Figure out the last checkpoint before the smallest
- * start_lsn in the region.
- */
F_SET((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
+ ret = __txn_openfiles(dbenv, &min, 0);
+ F_CLR((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
+ }
+err:
+ return (ret);
+}
+
+/*
+ * __txn_openfiles --
+ * Call env_openfiles.
+ *
+ * PUBLIC: int __txn_openfiles __P((DB_ENV *, DB_LSN *, int));
+ */
+int
+__txn_openfiles(dbenv, min, force)
+ DB_ENV *dbenv;
+ DB_LSN *min;
+ int force;
+{
+ DBT data;
+ DB_LOGC *logc;
+ DB_LSN open_lsn;
+ __txn_ckp_args *ckp_args;
+ int ret, t_ret;
+ void *txninfo;
- if ((ret = __log_cursor(dbenv, &logc)) != 0)
- goto err;
-
- memset(&data, 0, sizeof(data));
- if ((ret = __txn_getckp(dbenv, &open_lsn)) == 0)
- while (!IS_ZERO_LSN(open_lsn) && (ret =
- __log_c_get(logc, &open_lsn, &data, DB_SET)) == 0 &&
- log_compare(&min, &open_lsn) < 0) {
- /* Format the log record. */
- if ((ret = __txn_ckp_read(dbenv,
- data.data, &ckp_args)) != 0) {
- __db_err(dbenv,
- "Invalid checkpoint record at [%lu][%lu]",
- (u_long)open_lsn.file,
- (u_long)open_lsn.offset);
+ /*
+ * Figure out the last checkpoint before the smallest
+ * start_lsn in the region.
+ */
+ logc = NULL;
+ if ((ret = __log_cursor(dbenv, &logc)) != 0)
+ goto err;
+
+ memset(&data, 0, sizeof(data));
+ if ((ret = __txn_getckp(dbenv, &open_lsn)) == 0)
+ while (!IS_ZERO_LSN(open_lsn) && (ret =
+ __log_c_get(logc, &open_lsn, &data, DB_SET)) == 0 &&
+ (force ||
+ (min != NULL && log_compare(min, &open_lsn) < 0))) {
+ /* Format the log record. */
+ if ((ret = __txn_ckp_read(dbenv,
+ data.data, &ckp_args)) != 0) {
+ __db_err(dbenv,
+ "Invalid checkpoint record at [%lu][%lu]",
+ (u_long)open_lsn.file,
+ (u_long)open_lsn.offset);
+ goto err;
+ }
+ /*
+ * If force is set, then we're forcing ourselves
+ * to go back far enough to open files.
+ * Use ckp_lsn and then break out of the loop.
+ */
+ open_lsn = force ? ckp_args->ckp_lsn :
+ ckp_args->last_ckp;
+ __os_free(dbenv, ckp_args);
+ if (force) {
+ if ((ret = __log_c_get(logc, &open_lsn,
+ &data, DB_SET)) != 0)
goto err;
- }
- open_lsn = ckp_args->last_ckp;
- __os_free(dbenv, ckp_args);
+ break;
}
-
- /*
- * There are three ways by which we may have gotten here.
- * - We got a DB_NOTFOUND -- we need to read the first
- * log record.
- * - We found a checkpoint before min. We're done.
- * - We found a checkpoint after min who's last_ckp is 0. We
- * need to start at the beginning of the log.
- */
- if ((ret == DB_NOTFOUND || IS_ZERO_LSN(open_lsn)) && (ret =
- __log_c_get(logc, &open_lsn, &data, DB_FIRST)) != 0) {
- __db_err(dbenv, "No log records");
- goto err;
}
- if ((ret = __db_txnlist_init(dbenv, 0, 0, NULL, &txninfo)) != 0)
- goto err;
- ret = __env_openfiles(dbenv, logc,
- txninfo, &data, &open_lsn, NULL, 0, 0);
- if (txninfo != NULL)
- __db_txnlist_end(dbenv, txninfo);
+ /*
+ * There are several ways by which we may have gotten here.
+ * - We got a DB_NOTFOUND -- we need to read the first
+ * log record.
+ * - We found a checkpoint before min. We're done.
+ * - We found a checkpoint after min who's last_ckp is 0. We
+ * need to start at the beginning of the log.
+ * - We are forcing an openfiles and we have our ckp_lsn.
+ */
+ if ((ret == DB_NOTFOUND || IS_ZERO_LSN(open_lsn)) && (ret =
+ __log_c_get(logc, &open_lsn, &data, DB_FIRST)) != 0) {
+ __db_err(dbenv, "No log records");
+ goto err;
}
-err: F_CLR((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);
+ if ((ret = __db_txnlist_init(dbenv, 0, 0, NULL, &txninfo)) != 0)
+ goto err;
+ ret = __env_openfiles(dbenv, logc,
+ txninfo, &data, &open_lsn, NULL, 0, 0);
+ if (txninfo != NULL)
+ __db_txnlist_end(dbenv, txninfo);
+err:
if (logc != NULL && (t_ret = __log_c_close(logc)) != 0 && ret == 0)
ret = t_ret;
-
return (ret);
}
diff --git a/db/txn/txn_region.c b/db/txn/txn_region.c
index 16b26a469..55a5310f9 100644
--- a/db/txn/txn_region.c
+++ b/db/txn/txn_region.c
@@ -1,16 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996-2003
+ * Copyright (c) 1996-2004
* Sleepycat Software. All rights reserved.
+ *
+ * $Id: txn_region.c,v 11.86 2004/09/22 17:41:10 bostic Exp $
*/
#include "db_config.h"
-#ifndef lint
-static const char revid[] = "$Id: txn_region.c,v 11.79 2003/07/23 13:13:12 mjc Exp $";
-#endif /* not lint */
-
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
@@ -32,7 +30,6 @@ static const char revid[] = "$Id: txn_region.c,v 11.79 2003/07/23 13:13:12 mjc E
#include "dbinc/log.h"
#include "dbinc/txn.h"
-static int __txn_findlastckp __P((DB_ENV *, DB_LSN *));
static int __txn_init __P((DB_ENV *, DB_TXNMGR *));
static size_t __txn_region_size __P((DB_ENV *));
@@ -56,9 +53,9 @@ __txn_open(dbenv)
tmgrp->dbenv = dbenv;
/* Join/create the txn region. */
+ tmgrp->reginfo.dbenv = dbenv;
tmgrp->reginfo.type = REGION_TYPE_TXN;
tmgrp->reginfo.id = INVALID_REGION_ID;
- tmgrp->reginfo.mode = dbenv->db_mode;
tmgrp->reginfo.flags = REGION_JOIN_OK;
if (F_ISSET(dbenv, DB_ENV_CREATE))
F_SET(&tmgrp->reginfo, REGION_CREATE_OK);
@@ -73,7 +70,7 @@ __txn_open(dbenv)
/* Set the local addresses. */
tmgrp->reginfo.primary =
- R_ADDR(&tmgrp->reginfo, tmgrp->reginfo.rp->primary);
+ R_ADDR(dbenv, &tmgrp->reginfo, tmgrp->reginfo.rp->primary);
/* Acquire a mutex to protect the active TXN list. */
if (F_ISSET(dbenv, DB_ENV_THREAD) &&
@@ -131,18 +128,18 @@ __txn_init(dbenv, tmgrp)
* the last log file until we find the last checkpoint.
*/
if (IS_ZERO_LSN(last_ckp) &&
- (ret = __txn_findlastckp(dbenv, &last_ckp)) != 0)
+ (ret = __txn_findlastckp(dbenv, &last_ckp, NULL)) != 0)
return (ret);
}
- if ((ret = __db_shalloc(tmgrp->reginfo.addr,
+ if ((ret = __db_shalloc(&tmgrp->reginfo,
sizeof(DB_TXNREGION), 0, &tmgrp->reginfo.primary)) != 0) {
__db_err(dbenv,
"Unable to allocate memory for the transaction region");
return (ret);
}
tmgrp->reginfo.rp->primary =
- R_OFFSET(&tmgrp->reginfo, tmgrp->reginfo.primary);
+ R_OFFSET(dbenv, &tmgrp->reginfo, tmgrp->reginfo.primary);
region = tmgrp->reginfo.primary;
memset(region, 0, sizeof(*region));
@@ -158,14 +155,14 @@ __txn_init(dbenv, tmgrp)
SH_TAILQ_INIT(&region->active_txn);
#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
/* Allocate room for the txn maintenance info and initialize it. */
- if ((ret = __db_shalloc(tmgrp->reginfo.addr,
+ if ((ret = __db_shalloc(&tmgrp->reginfo,
sizeof(REGMAINT) + TXN_MAINT_SIZE, 0, &addr)) != 0) {
__db_err(dbenv,
"Unable to allocate memory for mutex maintenance");
return (ret);
}
__db_maintinit(&tmgrp->reginfo, addr, TXN_MAINT_SIZE);
- region->maint_off = R_OFFSET(&tmgrp->reginfo, addr);
+ region->maint_off = R_OFFSET(dbenv, &tmgrp->reginfo, addr);
#endif
return (0);
}
@@ -173,13 +170,16 @@ __txn_init(dbenv, tmgrp)
/*
* __txn_findlastckp --
* Find the last checkpoint in the log, walking backwards from the
- * beginning of the last log file. (The log system looked through
- * the last log file when it started up.)
+ * max_lsn given or the beginning of the last log file. (The
+ * log system looked through the last log file when it started up.)
+ *
+ * PUBLIC: int __txn_findlastckp __P((DB_ENV *, DB_LSN *, DB_LSN *));
*/
-static int
-__txn_findlastckp(dbenv, lsnp)
+int
+__txn_findlastckp(dbenv, lsnp, max_lsn)
DB_ENV *dbenv;
DB_LSN *lsnp;
+ DB_LSN *max_lsn;
{
DB_LOGC *logc;
DB_LSN lsn;
@@ -192,15 +192,22 @@ __txn_findlastckp(dbenv, lsnp)
/* Get the last LSN. */
memset(&dbt, 0, sizeof(dbt));
- if ((ret = __log_c_get(logc, &lsn, &dbt, DB_LAST)) != 0)
- goto err;
-
- /*
- * Twiddle the last LSN so it points to the beginning of the last
- * file; we know there's no checkpoint after that, since the log
- * system already looked there.
- */
- lsn.offset = 0;
+ if (max_lsn != NULL) {
+ lsn = *max_lsn;
+ ZERO_LSN(*lsnp);
+ if ((ret = __log_c_get(logc, &lsn, &dbt, DB_SET)) != 0)
+ goto err;
+ } else {
+ if ((ret = __log_c_get(logc, &lsn, &dbt, DB_LAST)) != 0)
+ goto err;
+ /*
+ * Twiddle the last LSN so it points to the
+ * beginning of the last file; we know there's
+ * no checkpoint after that, since the log
+ * system already looked there.
+ */
+ lsn.offset = 0;
+ }
/* Read backwards, looking for checkpoints. */
while ((ret = __log_c_get(logc, &lsn, &dbt, DB_PREV)) == 0) {
@@ -225,7 +232,6 @@ err: if ((t_ret = __log_c_close(logc)) != 0 && ret == 0)
/*
* __txn_dbenv_refresh --
* Clean up after the transaction system on a close or failed open.
- * Called only from __dbenv_refresh. (Formerly called __txn_close.)
*
* PUBLIC: int __txn_dbenv_refresh __P((DB_ENV *));
*/
@@ -235,12 +241,14 @@ __txn_dbenv_refresh(dbenv)
{
DB_TXN *txnp;
DB_TXNMGR *tmgrp;
+ REGINFO *reginfo;
TXN_DETAIL *td;
u_int32_t txnid;
int aborted, ret, t_ret;
ret = 0;
tmgrp = dbenv->tx_handle;
+ reginfo = &tmgrp->reginfo;
/*
* This function can only be called once per process (i.e., not
@@ -257,7 +265,7 @@ __txn_dbenv_refresh(dbenv)
if (TAILQ_FIRST(&tmgrp->txn_chain) != NULL) {
while ((txnp = TAILQ_FIRST(&tmgrp->txn_chain)) != NULL) {
/* Prepared transactions are OK. */
- td = (TXN_DETAIL *)R_ADDR(&tmgrp->reginfo, txnp->off);
+ td = (TXN_DETAIL *)R_ADDR(dbenv, reginfo, txnp->off);
txnid = txnp->txnid;
if (td->status == TXN_PREPARED) {
if ((ret = __txn_discard(txnp, 0)) != 0) {
@@ -292,10 +300,10 @@ __txn_dbenv_refresh(dbenv)
/* Discard the per-thread lock. */
if (tmgrp->mutexp != NULL)
- __db_mutex_free(dbenv, &tmgrp->reginfo, tmgrp->mutexp);
+ __db_mutex_free(dbenv, reginfo, tmgrp->mutexp);
/* Detach from the region. */
- if ((t_ret = __db_r_detach(dbenv, &tmgrp->reginfo, 0)) != 0 && ret == 0)
+ if ((t_ret = __db_r_detach(dbenv, reginfo, 0)) != 0 && ret == 0)
ret = t_ret;
__os_free(dbenv, tmgrp);
@@ -338,11 +346,26 @@ __txn_region_destroy(dbenv, infop)
DB_ENV *dbenv;
REGINFO *infop;
{
- __db_shlocks_destroy(infop, (REGMAINT *)R_ADDR(infop,
- ((DB_TXNREGION *)R_ADDR(infop, infop->rp->primary))->maint_off));
+ /*
+ * This routine is called in two cases: when discarding the mutexes
+ * from a previous Berkeley DB run, during recovery, and two, when
+ * discarding the mutexes as we shut down the database environment.
+ * In the latter case, we also need to discard shared memory segments,
+ * this is the last time we use them, and the last region-specific
+ * call we make.
+ */
+#ifdef HAVE_MUTEX_SYSTEM_RESOURCES
+ DB_TXNREGION *region;
- COMPQUIET(dbenv, NULL);
- COMPQUIET(infop, NULL);
+ region = R_ADDR(dbenv, infop, infop->rp->primary);
+
+ __db_shlocks_destroy(infop, R_ADDR(dbenv, infop, region->maint_off));
+ if (infop->primary != NULL && F_ISSET(dbenv, DB_ENV_PRIVATE))
+ __db_shalloc_free(infop,
+ R_ADDR(dbenv, infop, region->maint_off));
+#endif
+ if (infop->primary != NULL && F_ISSET(dbenv, DB_ENV_PRIVATE))
+ __db_shalloc_free(infop, infop->primary);
}
/*
diff --git a/db/txn/txn_stat.c b/db/txn/txn_stat.c
index 905a2a5eb..e9536b67c 100644
--- a/db/txn/txn_stat.c
+++ b/db/txn/txn_stat.c
@@ -1,27 +1,44 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996-2003
+ * Copyright (c) 1996-2004
* Sleepycat Software. All rights reserved.
+ *
+ * $Id: txn_stat.c,v 11.36 2004/09/15 21:49:21 mjc Exp $
*/
#include "db_config.h"
-#ifndef lint
-static const char revid[] = "$Id: txn_stat.c,v 11.22 2003/09/13 19:20:43 bostic Exp $";
-#endif /* not lint */
-
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+#include <stdlib.h>
#include <string.h>
#endif
#include "db_int.h"
+#include "dbinc/db_page.h"
+#include "dbinc/db_am.h"
#include "dbinc/log.h"
#include "dbinc/txn.h"
-static int __txn_stat __P((DB_ENV *, DB_TXN_STAT **, u_int32_t));
+#ifdef HAVE_STATISTICS
+static int __txn_compare __P((const void *, const void *));
+static int __txn_print_all __P((DB_ENV *, u_int32_t));
+static int __txn_print_stats __P((DB_ENV *, u_int32_t));
+static int __txn_stat __P((DB_ENV *, DB_TXN_STAT **, u_int32_t));
+static void __txn_xid_stats __P((DB_ENV *, DB_MSGBUF *, DB_TXN_ACTIVE *));
/*
* __txn_stat_pp --
@@ -38,7 +55,8 @@ __txn_stat_pp(dbenv, statp, flags)
int rep_check, ret;
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "txn_stat", DB_INIT_TXN);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->tx_handle, "DB_ENV->txn_stat", DB_INIT_TXN);
if ((ret = __db_fchk(dbenv,
"DB_ENV->txn_stat", flags, DB_STAT_CLEAR)) != 0)
@@ -49,7 +67,7 @@ __txn_stat_pp(dbenv, statp, flags)
__env_rep_enter(dbenv);
ret = __txn_stat(dbenv, statp, flags);
if (rep_check)
- __env_rep_exit(dbenv);
+ __env_db_rep_exit(dbenv);
return (ret);
}
@@ -106,7 +124,7 @@ __txn_stat(dbenv, statp, flags)
stats->st_txnarray[ndx].parentid = TXN_INVALID;
else
stats->st_txnarray[ndx].parentid =
- ((TXN_DETAIL *)R_ADDR(&mgr->reginfo,
+ ((TXN_DETAIL *)R_ADDR(dbenv, &mgr->reginfo,
txnp->parent))->txnid;
stats->st_txnarray[ndx].lsn = txnp->begin_lsn;
if ((stats->st_txnarray[ndx].xa_status = txnp->xa_status) != 0)
@@ -131,3 +149,282 @@ __txn_stat(dbenv, statp, flags)
*statp = stats;
return (0);
}
+
+/*
+ * __txn_stat_print_pp --
+ * DB_ENV->txn_stat_print pre/post processing.
+ *
+ * PUBLIC: int __txn_stat_print_pp __P((DB_ENV *, u_int32_t));
+ */
+int
+__txn_stat_print_pp(dbenv, flags)
+ DB_ENV *dbenv;
+ u_int32_t flags;
+{
+ int rep_check, ret;
+
+ PANIC_CHECK(dbenv);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->tx_handle, "DB_ENV->txn_stat_print", DB_INIT_TXN);
+
+ if ((ret = __db_fchk(dbenv, "DB_ENV->txn_stat",
+ flags, DB_STAT_ALL | DB_STAT_CLEAR)) != 0)
+ return (ret);
+
+ rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;
+ if (rep_check)
+ __env_rep_enter(dbenv);
+ ret = __txn_stat_print(dbenv, flags);
+ if (rep_check)
+ __env_db_rep_exit(dbenv);
+ return (ret);
+}
+
+/*
+ * __txn_stat_print
+ * DB_ENV->txn_stat_print method.
+ *
+ * PUBLIC: int __txn_stat_print __P((DB_ENV *, u_int32_t));
+ */
+int
+__txn_stat_print(dbenv, flags)
+ DB_ENV *dbenv;
+ u_int32_t flags;
+{
+ u_int32_t orig_flags;
+ int ret;
+
+ orig_flags = flags;
+ LF_CLR(DB_STAT_CLEAR);
+ if (flags == 0 || LF_ISSET(DB_STAT_ALL)) {
+ ret = __txn_print_stats(dbenv, orig_flags);
+ if (flags == 0 || ret != 0)
+ return (ret);
+ }
+
+ if (LF_ISSET(DB_STAT_ALL) &&
+ (ret = __txn_print_all(dbenv, orig_flags)) != 0)
+ return (ret);
+
+ return (0);
+}
+
+/*
+ * __txn_print_stats --
+ * Display default transaction region statistics.
+ */
+static int
+__txn_print_stats(dbenv, flags)
+ DB_ENV *dbenv;
+ u_int32_t flags;
+{
+ DB_MSGBUF mb;
+ DB_TXN_STAT *sp;
+ u_int32_t i;
+ int ret;
+
+ if ((ret = __txn_stat(dbenv, &sp, flags)) != 0)
+ return (ret);
+
+ if (LF_ISSET(DB_STAT_ALL))
+ __db_msg(dbenv, "Default transaction region information:");
+ __db_msg(dbenv, "%lu/%lu\t%s",
+ (u_long)sp->st_last_ckp.file, (u_long)sp->st_last_ckp.offset,
+ sp->st_last_ckp.file == 0 ?
+ "No checkpoint LSN" : "File/offset for last checkpoint LSN");
+ if (sp->st_time_ckp == 0)
+ __db_msg(dbenv, "0\tNo checkpoint timestamp");
+ else
+ __db_msg(dbenv, "%.24s\tCheckpoint timestamp",
+ ctime(&sp->st_time_ckp));
+ __db_msg(dbenv, "%#lx\tLast transaction ID allocated",
+ (u_long)sp->st_last_txnid);
+ __db_dl(dbenv, "Maximum number of active transactions configured",
+ (u_long)sp->st_maxtxns);
+ __db_dl(dbenv, "Active transactions", (u_long)sp->st_nactive);
+ __db_dl(dbenv,
+ "Maximum active transactions", (u_long)sp->st_maxnactive);
+ __db_dl(dbenv,
+ "Number of transactions begun", (u_long)sp->st_nbegins);
+ __db_dl(dbenv,
+ "Number of transactions aborted", (u_long)sp->st_naborts);
+ __db_dl(dbenv,
+ "Number of transactions committed", (u_long)sp->st_ncommits);
+ __db_dl(dbenv,
+ "Number of transactions restored", (u_long)sp->st_nrestores);
+
+ __db_dlbytes(dbenv, "Transaction region size",
+ (u_long)0, (u_long)0, (u_long)sp->st_regsize);
+ __db_dl_pct(dbenv,
+ "The number of region locks that required waiting",
+ (u_long)sp->st_region_wait, DB_PCT(sp->st_region_wait,
+ sp->st_region_wait + sp->st_region_nowait), NULL);
+
+ qsort(sp->st_txnarray,
+ sp->st_nactive, sizeof(sp->st_txnarray[0]), __txn_compare);
+ __db_msg(dbenv, "List of active transactions:");
+ DB_MSGBUF_INIT(&mb);
+ for (i = 0; i < sp->st_nactive; ++i) {
+ __db_msgadd(dbenv,
+ &mb, "\tID: %lx; begin LSN: file/offset %lu/%lu",
+ (u_long)sp->st_txnarray[i].txnid,
+ (u_long)sp->st_txnarray[i].lsn.file,
+ (u_long)sp->st_txnarray[i].lsn.offset);
+ if (sp->st_txnarray[i].parentid != 0)
+ __db_msgadd(dbenv, &mb, "; parent: %lx",
+ (u_long)sp->st_txnarray[i].parentid);
+ if (sp->st_txnarray[i].xa_status != 0)
+ __txn_xid_stats(dbenv, &mb, &sp->st_txnarray[i]);
+ DB_MSGBUF_FLUSH(dbenv, &mb);
+ }
+
+ __os_ufree(dbenv, sp);
+
+ return (0);
+}
+
+/*
+ * __txn_print_all --
+ * Display debugging transaction region statistics.
+ */
+static int
+__txn_print_all(dbenv, flags)
+ DB_ENV *dbenv;
+ u_int32_t flags;
+{
+ static const FN fn[] = {
+ { TXN_IN_RECOVERY, "TXN_IN_RECOVERY" },
+ { 0, NULL }
+ };
+ DB_TXNMGR *mgr;
+ DB_TXNREGION *region;
+
+ mgr = dbenv->tx_handle;
+ region = mgr->reginfo.primary;
+
+ R_LOCK(dbenv, &mgr->reginfo);
+
+ __db_print_reginfo(dbenv, &mgr->reginfo, "Transaction");
+
+ __db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+ __db_msg(dbenv, "DB_TXNMGR handle information:");
+
+ __db_print_mutex(dbenv, NULL, mgr->mutexp, "DB_TXNMGR mutex", flags);
+ __db_dl(dbenv,
+ "Number of transactions discarded", (u_long)mgr->n_discards);
+
+ __db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+ __db_msg(dbenv, "DB_TXNREGION handle information:");
+ STAT_ULONG("Maximum number of active txns", region->maxtxns);
+ STAT_HEX("Last transaction ID allocated", region->last_txnid);
+ STAT_HEX("Current maximum unused ID", region->cur_maxid);
+
+ STAT_LSN("Last checkpoint LSN", &region->last_ckp);
+ __db_msg(dbenv,
+ "%.24s\tLast checkpoint timestamp",
+ region->time_ckp == 0 ? "0" : ctime(&region->time_ckp));
+
+ __db_prflags(dbenv, NULL, region->flags, fn, NULL, "\tFlags");
+
+ __db_msg(dbenv, "%s", DB_GLOBAL(db_line));
+ __db_msg(dbenv, "XA information:");
+ STAT_LONG("XA RMID", dbenv->xa_rmid);
+ /*
+ * XXX
+ * Display list of XA transactions in the DB_ENV handle.
+ */
+
+ R_UNLOCK(dbenv, &mgr->reginfo);
+
+ return (0);
+}
+
+static void
+__txn_xid_stats(dbenv, mbp, txnp)
+ DB_ENV *dbenv;
+ DB_MSGBUF *mbp;
+ DB_TXN_ACTIVE *txnp;
+{
+ u_int32_t v, *xp;
+ u_int i;
+ int cnt;
+ const char *s;
+
+ switch (txnp->xa_status) {
+ case TXN_XA_ABORTED:
+ s = "ABORTED";
+ break;
+ case TXN_XA_DEADLOCKED:
+ s = "DEADLOCKED";
+ break;
+ case TXN_XA_ENDED:
+ s = "ENDED";
+ break;
+ case TXN_XA_PREPARED:
+ s = "PREPARED";
+ break;
+ case TXN_XA_STARTED:
+ s = "STARTED";
+ break;
+ case TXN_XA_SUSPENDED:
+ s = "SUSPENDED";
+ break;
+ default:
+ s = "UNKNOWN STATE";
+ __db_err(dbenv,
+ "XA: unknown state: %lu", (u_long)txnp->xa_status);
+ break;
+ }
+ __db_msgadd(dbenv, mbp, "\tXA: %s; XID:\n\t\t", s == NULL ? "" : s);
+ for (cnt = 0, xp = (u_int32_t *)txnp->xid,
+ i = 0; i < DB_XIDDATASIZE; i += sizeof(u_int32_t)) {
+ memcpy(&v, xp++, sizeof(u_int32_t));
+ __db_msgadd(dbenv, mbp, "%#x ", v);
+ if (++cnt == 4) {
+ DB_MSGBUF_FLUSH(dbenv, mbp);
+ __db_msgadd(dbenv, mbp, "\t\t");
+ cnt = 0;
+ }
+ }
+}
+
+static int
+__txn_compare(a1, b1)
+ const void *a1, *b1;
+{
+ const DB_TXN_ACTIVE *a, *b;
+
+ a = a1;
+ b = b1;
+
+ if (a->txnid > b->txnid)
+ return (1);
+ if (a->txnid < b->txnid)
+ return (-1);
+ return (0);
+}
+
+#else /* !HAVE_STATISTICS */
+
+int
+__txn_stat_pp(dbenv, statp, flags)
+ DB_ENV *dbenv;
+ DB_TXN_STAT **statp;
+ u_int32_t flags;
+{
+ COMPQUIET(statp, NULL);
+ COMPQUIET(flags, 0);
+
+ return (__db_stat_not_built(dbenv));
+}
+
+int
+__txn_stat_print_pp(dbenv, flags)
+ DB_ENV *dbenv;
+ u_int32_t flags;
+{
+ COMPQUIET(flags, 0);
+
+ return (__db_stat_not_built(dbenv));
+}
+#endif
diff --git a/db/txn/txn_util.c b/db/txn/txn_util.c
index 1a9e901f5..ff94cd7db 100644
--- a/db/txn/txn_util.c
+++ b/db/txn/txn_util.c
@@ -1,16 +1,14 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 2001-2003
+ * Copyright (c) 2001-2004
* Sleepycat Software. All rights reserved.
+ *
+ * $Id: txn_util.c,v 11.28 2004/09/16 17:55:19 margo Exp $
*/
#include "db_config.h"
-#ifndef lint
-static const char revid[] = "$Id: txn_util.c,v 11.25 2003/12/03 14:33:07 bostic Exp $";
-#endif /* not lint */
-
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <string.h>
@@ -280,8 +278,8 @@ __txn_doevents(dbenv, txn, opcode, preprocess)
case TXN_CLOSE:
/* If we didn't abort this txn, we screwed up badly. */
DB_ASSERT(opcode == TXN_ABORT);
- if ((t_ret =
- __db_close(e->u.c.dbp, NULL, 0)) != 0 && ret == 0)
+ if ((t_ret = __db_close(e->u.c.dbp,
+ NULL, DB_NOSYNC)) != 0 && ret == 0)
ret = t_ret;
break;
case TXN_REMOVE:
@@ -315,7 +313,9 @@ dofree:
__os_free(dbenv, e->u.r.fileid);
__os_free(dbenv, e->u.r.name);
break;
-
+ case TXN_CLOSE:
+ case TXN_TRADE:
+ case TXN_TRADED:
default:
break;
}