summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@wiredtiger.com>2012-06-18 13:53:44 +1000
committerMichael Cahill <michael.cahill@wiredtiger.com>2012-06-20 15:32:47 +1000
commitf3ab36014fe49487fdb791d468811e33ec8b354b (patch)
treefac4a6cb582a35e9398535d98061e9beba4573da
parenta7dc715a834b3d1d2c5eb3e521ccd10b9ba0ed3a (diff)
downloadmongo-f3ab36014fe49487fdb791d468811e33ec8b354b.tar.gz
Fix __wt_conn_btree_apply to acquire handles correctly,
pass WT_BTREE_SNAPSHOT_OP from checkpoint code.
-rw-r--r--src/btree/bt_handle.c4
-rw-r--r--src/conn/conn_btree.c9
-rw-r--r--src/include/txn.i2
-rw-r--r--src/txn/txn.c35
-rw-r--r--test/format/wts_ops.c8
-rw-r--r--test/thread/t.c4
6 files changed, 40 insertions, 22 deletions
diff --git a/src/btree/bt_handle.c b/src/btree/bt_handle.c
index 3cc126b1c89..5b9a1fef052 100644
--- a/src/btree/bt_handle.c
+++ b/src/btree/bt_handle.c
@@ -133,8 +133,10 @@ __wt_btree_close(WT_SESSION_IMPL *session)
__wt_btree_huffman_close(session);
/* Snapshot lock. */
- if (btree->snaplock != NULL)
+ if (btree->snaplock != NULL) {
(void)__wt_rwlock_destroy(session, btree->snaplock);
+ btree->snaplock = NULL;
+ }
/* Free allocated memory. */
__wt_free(session, btree->key_format);
diff --git a/src/conn/conn_btree.c b/src/conn/conn_btree.c
index 90331c2adca..b68448be4f6 100644
--- a/src/conn/conn_btree.c
+++ b/src/conn/conn_btree.c
@@ -300,8 +300,15 @@ __wt_conn_btree_apply(WT_SESSION_IMPL *session,
__wt_spin_lock(session, &conn->spinlock);
TAILQ_FOREACH(btree, &conn->btqh, q)
- if (btree->snapshot == NULL &&
+ if (F_ISSET(btree, WT_BTREE_OPEN) &&
+ btree->snapshot == NULL &&
strcmp(btree->name, WT_METADATA_URI) != 0) {
+ /*
+ * We have the connection spinlock, which prevents
+ * handles being opened or closed, so there is no need
+ * for additional handle locking here, or pulling every
+ * tree into this session's handle cache.
+ */
session->btree = btree;
WT_ERR(func(session, cfg));
}
diff --git a/src/include/txn.i b/src/include/txn.i
index 37395341750..da9f5af9716 100644
--- a/src/include/txn.i
+++ b/src/include/txn.i
@@ -125,7 +125,7 @@ __wt_txn_update_check(WT_SESSION_IMPL *session, WT_UPDATE *upd)
WT_TXN *txn;
txn = &session->txn;
- if (txn->isolation == TXN_ISO_SNAPSHOT)
+ if (F_ISSET(txn, TXN_RUNNING) && txn->isolation == TXN_ISO_SNAPSHOT)
while (upd != NULL && !__wt_txn_visible(session, upd->txnid)) {
if (upd->txnid != WT_TXN_ABORTED)
return (WT_DEADLOCK);
diff --git a/src/txn/txn.c b/src/txn/txn.c
index 36149170239..8244a093cf0 100644
--- a/src/txn/txn.c
+++ b/src/txn/txn.c
@@ -193,15 +193,11 @@ int
__wt_txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[])
{
WT_CONFIG_ITEM cval;
- WT_CURSOR *cursor;
WT_DECL_RET;
WT_TXN_GLOBAL *txn_global;
const char *snapshot;
const char *txn_cfg[] = { "isolation=snapshot", NULL };
- cursor = NULL;
- txn_global = &S2C(session)->txn_global;
-
if ((ret = __wt_config_gets(
session, cfg, "snapshot", &cval)) != 0 && ret != WT_NOTFOUND)
WT_RET(ret);
@@ -212,12 +208,14 @@ __wt_txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[])
/* Only one checkpoint can be active at a time. */
__wt_writelock(session, S2C(session)->ckpt_rwlock);
-
WT_ERR(__wt_txn_begin(session, txn_cfg));
/* Prevent eviction from evicting anything newer than this. */
+ txn_global = &S2C(session)->txn_global;
txn_global->ckpt_txnid = session->txn.snap_min;
+ WT_ERR(__wt_meta_track_on(session));
+
/*
* If we're doing an ordinary unnamed checkpoint, we only need to flush
* open files. If we're creating a named snapshot, we need to walk the
@@ -225,16 +223,27 @@ __wt_txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[])
*/
WT_TRET((snapshot == NULL) ?
__wt_conn_btree_apply(session, __wt_snapshot, cfg) :
- __wt_meta_btree_apply(session, __wt_snapshot, cfg, 0));
+ __wt_meta_btree_apply(session,
+ __wt_snapshot, cfg, WT_BTREE_SNAPSHOT_OP));
- if (cursor != NULL)
- WT_TRET(cursor->close(cursor));
-
- txn_global->ckpt_txnid = WT_TXN_NONE;
-
- WT_TRET(__txn_release(session));
+ /*
+ * XXX Rolling back the changes here is problematic.
+ *
+ * If we unroll here, we need a way to roll back changes to the avail
+ * list for each tree that was successfully synced before the error
+ * occurred. Otherwise, the next time we try this operation, we will
+ * try to free an old snapshot again.
+ *
+ * OTOH, if we commit the changes after a failure, we have partially
+ * overwritten the checkpoint, so what ends up on disk is not
+ * consistent.
+ */
+ WT_TRET(__wt_meta_track_off(session, ret != 0));
-err: __wt_rwunlock(session, S2C(session)->ckpt_rwlock);
+err: txn_global->ckpt_txnid = WT_TXN_NONE;
+ if (F_ISSET(&session->txn, TXN_RUNNING))
+ WT_TRET(__txn_release(session));
+ __wt_rwunlock(session, S2C(session)->ckpt_rwlock);
__wt_free(session, snapshot);
return (ret);
}
diff --git a/test/format/wts_ops.c b/test/format/wts_ops.c
index 0ec003d186a..7e28f029ab7 100644
--- a/test/format/wts_ops.c
+++ b/test/format/wts_ops.c
@@ -171,10 +171,10 @@ ops(void *arg)
WT_TABLENAME, sync_name);
sync_drop = 0;
} else {
- if ((ret = session->sync(
- session, WT_TABLENAME, sync_name)) != 0)
- die(ret, "session.sync: %s: %s",
- WT_TABLENAME, sync_name);
+ if ((ret = session->checkpoint(
+ session, sync_name)) != 0)
+ die(ret, "session.checkpoint: %s",
+ sync_name);
sync_drop = 1;
}
diff --git a/test/thread/t.c b/test/thread/t.c
index 554c624073b..0f40e0424e4 100644
--- a/test/thread/t.c
+++ b/test/thread/t.c
@@ -163,8 +163,8 @@ wt_shutdown(void)
if ((ret = session->verify(session, FNAME, NULL)) != 0)
die("session.verify", ret);
- if ((ret = session->sync(session, FNAME, NULL)) != 0)
- die("session.sync", ret);
+ if ((ret = session->checkpoint(session, NULL)) != 0)
+ die("session.checkpoint", ret);
if ((ret = conn->close(conn, NULL)) != 0)
die("conn.close", ret);