summaryrefslogtreecommitdiff
path: root/src/txn
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2015-02-17 17:25:57 +0000
committer <>2015-03-17 16:26:24 +0000
commit780b92ada9afcf1d58085a83a0b9e6bc982203d1 (patch)
tree598f8b9fa431b228d29897e798de4ac0c1d3d970 /src/txn
parent7a2660ba9cc2dc03a69ddfcfd95369395cc87444 (diff)
downloadberkeleydb-780b92ada9afcf1d58085a83a0b9e6bc982203d1.tar.gz
Imported from /home/lorry/working-area/delta_berkeleydb/db-6.1.23.tar.gz.HEADdb-6.1.23master
Diffstat (limited to 'src/txn')
-rw-r--r--src/txn/txn.c42
-rw-r--r--src/txn/txn.src2
-rw-r--r--src/txn/txn_chkpt.c4
-rw-r--r--src/txn/txn_failchk.c4
-rw-r--r--src/txn/txn_method.c2
-rw-r--r--src/txn/txn_rec.c7
-rw-r--r--src/txn/txn_recover.c6
-rw-r--r--src/txn/txn_region.c121
-rw-r--r--src/txn/txn_stat.c2
-rw-r--r--src/txn/txn_util.c43
10 files changed, 168 insertions, 65 deletions
diff --git a/src/txn/txn.c b/src/txn/txn.c
index 81225e5c..91652cb7 100644
--- a/src/txn/txn.c
+++ b/src/txn/txn.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015 Oracle and/or its affiliates. All rights reserved.
*/
/*
* Copyright (c) 1995, 1996
@@ -227,8 +227,15 @@ __txn_begin(env, ip, parent, txnpp, flags)
if (LF_ISSET(DB_TXN_FAMILY))
F_SET(txn, TXN_FAMILY | TXN_INFAMILY | TXN_READONLY);
if (LF_ISSET(DB_TXN_SNAPSHOT) || F_ISSET(dbenv, DB_ENV_TXN_SNAPSHOT) ||
- (parent != NULL && F_ISSET(parent, TXN_SNAPSHOT)))
- F_SET(txn, TXN_SNAPSHOT);
+ (parent != NULL && F_ISSET(parent, TXN_SNAPSHOT))) {
+ if (IS_REP_CLIENT(env)) {
+ __db_errx(env, DB_STR("4572",
+ "DB_TXN_SNAPSHOT may not be used on a replication client"));
+ ret = (EINVAL);
+ goto err;
+ } else
+ F_SET(txn, TXN_SNAPSHOT);
+ }
if (LF_ISSET(DB_IGNORE_LEASE))
F_SET(txn, TXN_IGNORE_LEASE);
@@ -581,8 +588,7 @@ __txn_continue(env, txn, td, ip, add_to_list)
txn->set_timeout = __txn_set_timeout;
txn->set_txn_lsnp = __txn_set_txn_lsnp;
- /* XXX Do we need to explicitly set a SYNC flag here? */
- txn->flags = TXN_MALLOC |
+ txn->flags = TXN_MALLOC | TXN_SYNC |
(F_ISSET(td, TXN_DTL_NOWAIT) ? TXN_NOWAIT : 0);
txn->xa_thr_status = TXN_XA_THREAD_NOTA;
@@ -795,8 +801,9 @@ __txn_commit(txn, flags)
if (ret == 0) {
DB_LSN s_lsn;
- DB_ASSERT(env, __log_current_lsn_int(
- env, &s_lsn, NULL, NULL) == 0);
+ if ((ret = __log_current_lsn_int(
+ env, &s_lsn, NULL, NULL)) != 0)
+ goto err;
DB_ASSERT(env, LOG_COMPARE(
&td->visible_lsn, &s_lsn) <= 0);
COMPQUIET(s_lsn.file, 0);
@@ -890,17 +897,16 @@ static int
__txn_close_cursors(txn)
DB_TXN *txn;
{
- int ret, tret;
+ int ret, t_ret;
DBC *dbc;
- ret = tret = 0;
+ ret = t_ret = 0;
dbc = NULL;
if (txn == NULL)
return (0);
while ((dbc = TAILQ_FIRST(&txn->my_cursors)) != NULL) {
-
DB_ASSERT(dbc->env, txn == dbc->txn);
/*
@@ -913,21 +919,21 @@ __txn_close_cursors(txn)
/* Removed from the active queue here. */
if (F_ISSET(dbc, DBC_ACTIVE))
- ret = __dbc_close(dbc);
+ t_ret = __dbc_close(dbc);
dbc->txn = NULL;
/* We have to close all cursors anyway, so continue on error. */
- if (ret != 0) {
- __db_err(dbc->env, ret, "__dbc_close");
- if (tret == 0)
- tret = ret;
+ if (t_ret != 0) {
+ __db_err(dbc->env, t_ret, "__dbc_close");
+ if (ret == 0)
+ ret = t_ret;
}
}
txn->my_cursors.tqh_first = NULL;
txn->my_cursors.tqh_last = NULL;
- return (tret);/* Return the first error if any. */
+ return (ret); /* Return the first error, if any. */
}
/*
@@ -1050,7 +1056,7 @@ __txn_abort(txn)
* it, however make sure that it is aborted when the last process
* tries to abort it.
*/
- if (txn->xa_thr_status != TXN_XA_THREAD_NOTA && td->xa_ref > 1) {
+ if (txn->xa_thr_status != TXN_XA_THREAD_NOTA && td->xa_ref > 1) {
td->status = TXN_NEED_ABORT;
return (0);
}
@@ -2165,5 +2171,5 @@ __txn_applied(env, ip, commit_info, timeout)
if (renv->envid == commit_info->envid &&
LOG_COMPARE(&commit_info->lsn, &lsn) <= 0)
return (0);
- return (DB_NOTFOUND);
+ return (USR_ERR(env, DB_NOTFOUND));
}
diff --git a/src/txn/txn.src b/src/txn/txn.src
index 7e82dc82..d9af5318 100644
--- a/src/txn/txn.src
+++ b/src/txn/txn.src
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015 Oracle and/or its affiliates. All rights reserved.
*
* $Id$
*/
diff --git a/src/txn/txn_chkpt.c b/src/txn/txn_chkpt.c
index 73715b10..a909767f 100644
--- a/src/txn/txn_chkpt.c
+++ b/src/txn/txn_chkpt.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015 Oracle and/or its affiliates. All rights reserved.
*/
/*
* Copyright (c) 1995, 1996
@@ -377,7 +377,7 @@ __txn_getckp(env, lsnp)
TXN_SYSTEM_UNLOCK(env);
if (IS_ZERO_LSN(lsn))
- return (DB_NOTFOUND);
+ return (USR_ERR(env, DB_NOTFOUND));
*lsnp = lsn;
return (0);
diff --git a/src/txn/txn_failchk.c b/src/txn/txn_failchk.c
index b2007ad6..94f22ec2 100644
--- a/src/txn/txn_failchk.c
+++ b/src/txn/txn_failchk.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 2005, 2012 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015 Oracle and/or its affiliates. All rights reserved.
*
* $Id$
*/
@@ -57,7 +57,7 @@ retry: TXN_SYSTEM_LOCK(env);
if (F_ISSET(td, TXN_DTL_INMEMORY)) {
TXN_SYSTEM_UNLOCK(env);
- return (__db_failed(env, DB_STR("4501",
+ return (__db_failed(env, DB_STR("4573",
"Transaction has in memory logs"),
td->pid, td->tid));
}
diff --git a/src/txn/txn_method.c b/src/txn/txn_method.c
index 629eac04..357e78c6 100644
--- a/src/txn/txn_method.c
+++ b/src/txn/txn_method.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015 Oracle and/or its affiliates. All rights reserved.
*
* $Id$
*/
diff --git a/src/txn/txn_rec.c b/src/txn/txn_rec.c
index b39d56d1..708af98a 100644
--- a/src/txn/txn_rec.c
+++ b/src/txn/txn_rec.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015 Oracle and/or its affiliates. All rights reserved.
*/
/*
* Copyright (c) 1996
@@ -210,11 +210,12 @@ __txn_prepare_recover(env, dbtp, lsnp, op, info)
*/
else if ((ret = __db_txnlist_remove(env,
info, argp->txnp->txnid)) != 0) {
-txn_err: __db_errx(env,
+txn_err:
+ ret = USR_ERR(env, DB_NOTFOUND);
+ __db_errx(env,
DB_STR_A("4515",
"transaction not in list %lx", "%lx"),
(u_long)argp->txnp->txnid);
- ret = DB_NOTFOUND;
} else if (IS_ZERO_LSN(headp->trunc_lsn) ||
LOG_COMPARE(&headp->trunc_lsn, lsnp) >= 0) {
if ((ret = __db_txnlist_add(env,
diff --git a/src/txn/txn_recover.c b/src/txn/txn_recover.c
index 67f24439..915a289f 100644
--- a/src/txn/txn_recover.c
+++ b/src/txn/txn_recover.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015 Oracle and/or its affiliates. All rights reserved.
*
* $Id$
*/
@@ -305,8 +305,8 @@ __txn_openfiles(env, ip, min, force)
if ((ret = __db_txnlist_init(env, ip, 0, 0, NULL, &txninfo)) != 0)
goto err;
- ret = __env_openfiles(
- env, logc, txninfo, &data, &open_lsn, NULL, (double)0, 0);
+ ret = __env_openfiles(env,
+ logc, txninfo, &data, &open_lsn, NULL, (double)0, 0);
if (txninfo != NULL)
__db_txnlist_end(env, txninfo);
diff --git a/src/txn/txn_region.c b/src/txn/txn_region.c
index 6f43d45f..7fef66e6 100644
--- a/src/txn/txn_region.c
+++ b/src/txn/txn_region.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015 Oracle and/or its affiliates. All rights reserved.
*
* $Id$
*/
@@ -13,6 +13,7 @@
#include "dbinc/txn.h"
static int __txn_init __P((ENV *, DB_TXNMGR *));
+static int lsn_hi_to_low __P((const void *, const void *));
/*
* __txn_open --
@@ -57,12 +58,30 @@ __txn_open(env)
env->tx_handle = mgr;
return (0);
-err: env->tx_handle = NULL;
- if (mgr->reginfo.addr != NULL)
- (void)__env_region_detach(env, &mgr->reginfo, 0);
+err: (void)__mutex_free(env, &mgr->mutex);
+ (void)__txn_region_detach(env, mgr);
- (void)__mutex_free(env, &mgr->mutex);
- __os_free(env, mgr);
+ return (ret);
+}
+
+/*
+ * __txn_region_detach --
+ *
+ * PUBLIC: int __txn_region_detach __P((ENV *, DB_TXNMGR *));
+ */
+int
+__txn_region_detach(env, mgr)
+ ENV *env;
+ DB_TXNMGR *mgr;
+{
+ int ret;
+
+ ret = 0;
+ if (mgr != NULL) {
+ ret = __env_region_detach(env, &mgr->reginfo, 0);
+ __os_free(env, mgr);
+ env->tx_handle = NULL;
+ }
return (ret);
}
@@ -409,39 +428,101 @@ __txn_id_set(env, cur_txnid, max_txnid)
}
/*
- * __txn_oldest_reader --
- * Find the oldest "read LSN" of any active transaction'
- * MVCC changes older than this can safely be discarded from the cache.
+ * lsn_hi_to_low --
+ * Compare lsns, sorting them from high to low. This is the opposite of
+ * __rep_lsn_cmp.
+ */
+static int
+lsn_hi_to_low(lsn1, lsn2)
+ const void *lsn1, *lsn2;
+{
+ return (LOG_COMPARE((DB_LSN *)lsn2, (DB_LSN *)lsn1));
+}
+
+/*
+ * __txn_get_readers --
+ * Find the read LSN of all active transactions.
+ * MVCC versions older than the oldest active transaction can safely be
+ * discarded from the cache. MVCC versions not quite so old can be
+ * discarded if they are not visible to any active transaction.
*
- * PUBLIC: int __txn_oldest_reader __P((ENV *, DB_LSN *));
+ * Returns:
+ * An error code, or 0.
+ * If 0 was returned, *readers has been filled in with an __os_malloc()'d
+ * array of active transactions with read_lsns, sorted from newest
+ * (largest) to oldest (smallest). *ntxnsp indicates how many are there.
+ * The last lsn is that of the oldest active mvcc-supporting transaction.
+ * The caller must __os_free() *readers whenever it is non-NULL.
+ *
+ * PUBLIC: int __txn_get_readers __P((ENV *, DB_LSN **, int *));
*/
+#define TXN_READERS_SIZE 64 /* Initial number of LSNs to allocate. */
int
-__txn_oldest_reader(env, lsnp)
+__txn_get_readers(env, readers, ntxnsp)
ENV *env;
- DB_LSN *lsnp;
+ DB_LSN **readers;
+ int *ntxnsp;
{
- DB_LSN old_lsn;
+ DB_LSN current, *lsns;
DB_TXNMGR *mgr;
DB_TXNREGION *region;
TXN_DETAIL *td;
- int ret;
+ int cmp, is_sorted, ret;
+ unsigned count, txnmax;
+
+ *ntxnsp = 0;
+ *readers = NULL;
if ((mgr = env->tx_handle) == NULL)
return (0);
region = mgr->reginfo.primary;
+ lsns = NULL;
+
+ if ((ret = __log_current_lsn_int(env, &current, NULL, NULL)) != 0)
+ return (ret);
- if ((ret = __log_current_lsn_int(env, &old_lsn, NULL, NULL)) != 0)
+ txnmax = TXN_READERS_SIZE;
+ if ((ret = __os_malloc(env, txnmax * sizeof(lsns[0]), &lsns)) != 0)
return (ret);
TXN_SYSTEM_LOCK(env);
- SH_TAILQ_FOREACH(td, &region->active_txn, links, __txn_detail)
- if (LOG_COMPARE(&td->read_lsn, &old_lsn) < 0)
- old_lsn = td->read_lsn;
+ /* The array always has at least the current lsn. */
+ lsns[0] = current;
+ count = 1;
+ is_sorted = TRUE;
- *lsnp = old_lsn;
+ /*
+ * Build up our array in most-recent (largest) to first-started (oldest)
+ * order. Delete adjacent dups. Detect when the txns need to be sorted.
+ */
+ SH_TAILQ_FOREACH(td, &region->active_txn, links, __txn_detail) {
+ if (IS_MAX_LSN(td->read_lsn) ||
+ (cmp = LOG_COMPARE(&td->read_lsn, &lsns[count - 1])) == 0)
+ continue;
+ if (cmp > 0)
+ is_sorted = FALSE;
+ if (count >= txnmax) {
+ txnmax += txnmax;
+ if ((ret = __os_realloc(env,
+ txnmax * sizeof(lsns[0]), &lsns)) != 0)
+ goto err;
+ }
+ lsns[count] = td->read_lsn;
+ count++;
+ }
+
+err:
TXN_SYSTEM_UNLOCK(env);
- return (0);
+ if (ret != 0)
+ __os_free(env, lsns);
+ else {
+ if (!is_sorted)
+ qsort(lsns, count, sizeof(lsns[0]), lsn_hi_to_low);
+ *ntxnsp = (int)count;
+ *readers = lsns;
+ }
+ return (ret);
}
/*
diff --git a/src/txn/txn_stat.c b/src/txn/txn_stat.c
index 62fe622d..231ac3c5 100644
--- a/src/txn/txn_stat.c
+++ b/src/txn/txn_stat.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015 Oracle and/or its affiliates. All rights reserved.
*
* $Id$
*/
diff --git a/src/txn/txn_util.c b/src/txn/txn_util.c
index 0ecd7f6c..9f3b8cf6 100644
--- a/src/txn/txn_util.c
+++ b/src/txn/txn_util.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015 Oracle and/or its affiliates. All rights reserved.
*
* $Id$
*/
@@ -9,6 +9,7 @@
#include "db_config.h"
#include "db_int.h"
+#include "dbinc/blob.h"
#include "dbinc/db_page.h"
#include "dbinc/lock.h"
#include "dbinc/mp.h"
@@ -209,7 +210,7 @@ __txn_remlock(env, txn, lock, locker)
for (e = TAILQ_FIRST(&txn->events); e != NULL; e = next_e) {
next_e = TAILQ_NEXT(e, links);
- if ((e->op != TXN_TRADE && e->op != TXN_TRADED &&
+ if ((e->op != TXN_TRADE && e->op != TXN_TRADED &&
e->op != TXN_XTRADE) ||
(e->u.t.lock.off != lock->off && e->u.t.locker != locker))
continue;
@@ -280,13 +281,21 @@ __txn_doevents(env, txn, opcode, preprocess)
e != NULL; e = enext) {
enext = TAILQ_NEXT(e, links);
/*
- * Move all exclusive handle locks and
+ * Move all exclusive handle locks and
* read handle locks to the handle locker.
*/
if (!(opcode == TXN_COMMIT && e->op == TXN_XTRADE) &&
- (e->op != TXN_TRADE ||
- IS_WRITELOCK(e->u.t.lock.mode)))
+ (e->op != TXN_TRADE ||
+ IS_WRITELOCK(e->u.t.lock.mode))) {
+ if (opcode == TXN_PREPARE &&
+ e->op == TXN_REMOVE) {
+ __db_errx(env, DB_STR_A("4501",
+"TXN->prepare is not allowed because this transaction removes \"%s\"", "%s"),
+ e->u.r.name);
+ return (EINVAL);
+ }
continue;
+ }
DO_TRADE;
if (txn->parent != NULL) {
TAILQ_REMOVE(&txn->events, e, links);
@@ -321,17 +330,26 @@ __txn_doevents(env, txn, opcode, preprocess)
ret = t_ret;
break;
case TXN_REMOVE:
- if (txn->parent != NULL)
+ if (txn->parent != NULL) {
TAILQ_INSERT_TAIL(
&txn->parent->events, e, links);
- else if (e->u.r.fileid != NULL) {
+ continue;
+ } else if (e->u.r.fileid != NULL) {
if ((t_ret = __memp_nameop(env,
e->u.r.fileid, NULL, e->u.r.name,
NULL, e->u.r.inmem)) != 0 && ret == 0)
ret = t_ret;
- } else if ((t_ret =
- __os_unlink(env, e->u.r.name, 0)) != 0 && ret == 0)
- ret = t_ret;
+ } else if ((t_ret = __os_unlink(
+ env, e->u.r.name, 0)) != 0 && ret == 0) {
+ /*
+ * It is possible for blob files to be deleted
+ * multiple times when truncating a database,
+ * so ignore ENOENT errors with blob files.
+ */
+ if (t_ret != ENOENT || strstr(
+ e->u.r.name, BLOB_FILE_PREFIX) == NULL)
+ ret = t_ret;
+ }
break;
case TXN_TRADE:
case TXN_XTRADE:
@@ -371,8 +389,6 @@ dofree:
/* Free resources here. */
switch (e->op) {
case TXN_REMOVE:
- if (txn->parent != NULL)
- continue;
if (e->u.r.fileid != NULL)
__os_free(env, e->u.r.fileid);
__os_free(env, e->u.r.name);
@@ -548,9 +564,8 @@ __txn_reset_fe_watermarks(txn)
{
DB *db;
- if (txn->parent) {
+ if (txn->parent)
DB_ASSERT(txn->mgrp->env, TAILQ_FIRST(&txn->femfs) == NULL);
- }
while ((db = TAILQ_FIRST(&txn->femfs)))
__clear_fe_watermark(txn, db);