summaryrefslogtreecommitdiff
path: root/src/txn
diff options
context:
space:
mode:
Diffstat (limited to 'src/txn')
-rw-r--r--src/txn/txn.c1
-rw-r--r--src/txn/txn_ckpt.c61
-rw-r--r--src/txn/txn_log.c1
-rw-r--r--src/txn/txn_nsnap.c37
4 files changed, 77 insertions, 23 deletions
diff --git a/src/txn/txn.c b/src/txn/txn.c
index a70551cdeb2..26a0ed679e2 100644
--- a/src/txn/txn.c
+++ b/src/txn/txn.c
@@ -777,7 +777,6 @@ __wt_txn_global_init(WT_SESSION_IMPL *session, const char *cfg[])
WT_RET(__wt_calloc_def(
session, conn->session_size, &txn_global->states));
- WT_CACHE_LINE_ALIGNMENT_VERIFY(session, txn_global->states);
for (i = 0, s = txn_global->states; i < conn->session_size; i++, s++)
s->id = s->metadata_pinned = s->pinned_id = WT_TXN_NONE;
diff --git a/src/txn/txn_ckpt.c b/src/txn/txn_ckpt.c
index 802ccd84915..399d9187d82 100644
--- a/src/txn/txn_ckpt.c
+++ b/src/txn/txn_ckpt.c
@@ -555,9 +555,6 @@ __txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[])
saved_isolation = session->isolation;
full = idle = logging = tracking = false;
- /* Ensure the metadata table is open before taking any locks. */
- WT_RET(__wt_metadata_cursor(session, NULL));
-
/*
* Do a pass over the configuration arguments and figure out what kind
* of checkpoint this is.
@@ -641,8 +638,8 @@ __txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[])
* then release any clean handles.
*/
WT_ASSERT(session, session->ckpt_handle_next == 0);
- WT_WITH_SCHEMA_LOCK(session, ret,
- WT_WITH_TABLE_LOCK(session, ret,
+ WT_WITH_SCHEMA_LOCK(session,
+ WT_WITH_TABLE_LOCK(session,
WT_WITH_HANDLE_LIST_LOCK(session,
ret = __checkpoint_apply_all(
session, cfg, __wt_checkpoint_get_handles, NULL))));
@@ -784,7 +781,7 @@ __txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[])
/* Disable metadata tracking during the metadata checkpoint. */
saved_meta_next = session->meta_track_next;
session->meta_track_next = NULL;
- WT_WITH_METADATA_LOCK(session, ret,
+ WT_WITH_METADATA_LOCK(session,
WT_WITH_DHANDLE(session,
WT_SESSION_META_DHANDLE(session),
ret = __wt_checkpoint(session, cfg)));
@@ -878,13 +875,39 @@ err: /*
}
/*
+ * __txn_checkpoint_wrapper --
+ * Checkpoint wrapper.
+ */
+static int
+__txn_checkpoint_wrapper(WT_SESSION_IMPL *session, const char *cfg[])
+{
+ WT_DECL_RET;
+ WT_TXN_GLOBAL *txn_global;
+
+ txn_global = &S2C(session)->txn_global;
+
+ WT_STAT_CONN_SET(session, txn_checkpoint_running, 1);
+ txn_global->checkpoint_running = true;
+ WT_FULL_BARRIER();
+
+ ret = __txn_checkpoint(session, cfg);
+
+ WT_STAT_CONN_SET(session, txn_checkpoint_running, 0);
+ txn_global->checkpoint_running = false;
+ WT_FULL_BARRIER();
+
+ return (ret);
+}
+
+/*
* __wt_txn_checkpoint --
* Checkpoint a database or a list of objects in the database.
*/
int
-__wt_txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[])
+__wt_txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[], bool waiting)
{
WT_DECL_RET;
+ uint32_t mask;
/*
* Reset open cursors. Do this explicitly, even though it will happen
@@ -894,13 +917,22 @@ __wt_txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[])
*/
WT_RET(__wt_session_reset_cursors(session, false));
+ /* Ensure the metadata table is open before taking any locks. */
+ WT_RET(__wt_metadata_cursor(session, NULL));
+
/*
* Don't highjack the session checkpoint thread for eviction.
*
* Application threads are not generally available for potentially slow
* operations, but checkpoint does enough I/O it may be called upon to
* perform slow operations for the block manager.
+ *
+ * Application checkpoints wait until the checkpoint lock is available,
+ * compaction checkpoints don't.
*/
+#define WT_TXN_SESSION_MASK \
+ (WT_SESSION_CAN_WAIT | WT_SESSION_NO_EVICTION)
+ mask = F_MASK(session, WT_TXN_SESSION_MASK);
F_SET(session, WT_SESSION_CAN_WAIT | WT_SESSION_NO_EVICTION);
/*
@@ -910,14 +942,15 @@ __wt_txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[])
* calls checkpoint directly, it can be tough to avoid. Serialize here
* to ensure we don't get into trouble.
*/
- WT_STAT_CONN_SET(session, txn_checkpoint_running, 1);
-
- WT_WITH_CHECKPOINT_LOCK(session, ret,
- ret = __txn_checkpoint(session, cfg));
-
- WT_STAT_CONN_SET(session, txn_checkpoint_running, 0);
+ if (waiting)
+ WT_WITH_CHECKPOINT_LOCK(session,
+ ret = __txn_checkpoint_wrapper(session, cfg));
+ else
+ WT_WITH_CHECKPOINT_LOCK_NOWAIT(session, ret,
+ ret = __txn_checkpoint_wrapper(session, cfg));
- F_CLR(session, WT_SESSION_CAN_WAIT | WT_SESSION_NO_EVICTION);
+ F_CLR(session, WT_TXN_SESSION_MASK);
+ F_SET(session, mask);
return (ret);
}
diff --git a/src/txn/txn_log.c b/src/txn/txn_log.c
index f1b78879d76..5f4704b40c4 100644
--- a/src/txn/txn_log.c
+++ b/src/txn/txn_log.c
@@ -551,6 +551,7 @@ __txn_printlog(WT_SESSION_IMPL *session,
*/
int
__wt_txn_printlog(WT_SESSION *wt_session, uint32_t flags)
+ WT_GCC_FUNC_ATTRIBUTE((visibility("default")))
{
WT_SESSION_IMPL *session;
WT_TXN_PRINTLOG_ARGS args;
diff --git a/src/txn/txn_nsnap.c b/src/txn/txn_nsnap.c
index 7ba0cc8700e..65ec1a6662f 100644
--- a/src/txn/txn_nsnap.c
+++ b/src/txn/txn_nsnap.c
@@ -28,7 +28,6 @@ __nsnap_destroy(WT_SESSION_IMPL *session, WT_NAMED_SNAPSHOT *nsnap)
static int
__nsnap_drop_one(WT_SESSION_IMPL *session, WT_CONFIG_ITEM *name)
{
- WT_DECL_RET;
WT_NAMED_SNAPSHOT *found;
WT_TXN_GLOBAL *txn_global;
@@ -56,7 +55,7 @@ __nsnap_drop_one(WT_SESSION_IMPL *session, WT_CONFIG_ITEM *name)
__nsnap_destroy(session, found);
WT_STAT_CONN_INCR(session, txn_snapshots_dropped);
- return (ret);
+ return (0);
}
/*
@@ -67,7 +66,6 @@ __nsnap_drop_one(WT_SESSION_IMPL *session, WT_CONFIG_ITEM *name)
static int
__nsnap_drop_to(WT_SESSION_IMPL *session, WT_CONFIG_ITEM *name, bool inclusive)
{
- WT_DECL_RET;
WT_NAMED_SNAPSHOT *last, *nsnap, *prev;
WT_TXN_GLOBAL *txn_global;
uint64_t new_nsnap_oldest;
@@ -134,7 +132,7 @@ __nsnap_drop_to(WT_SESSION_IMPL *session, WT_CONFIG_ITEM *name, bool inclusive)
new_nsnap_oldest == WT_TXN_NONE ||
!__wt_txn_visible_all(session, new_nsnap_oldest));
- return (ret);
+ return (0);
}
/*
@@ -152,26 +150,45 @@ __wt_txn_named_snapshot_begin(WT_SESSION_IMPL *session, const char *cfg[])
const char *txn_cfg[] =
{ WT_CONFIG_BASE(session, WT_SESSION_begin_transaction),
"isolation=snapshot", NULL };
- bool started_txn;
+ bool include_updates, started_txn;
started_txn = false;
nsnap_new = NULL;
txn_global = &S2C(session)->txn_global;
txn = &session->txn;
+ WT_RET(__wt_config_gets_def(session, cfg, "include_updates", 0, &cval));
+ include_updates = cval.val != 0;
+
WT_RET(__wt_config_gets_def(session, cfg, "name", 0, &cval));
WT_ASSERT(session, cval.len != 0);
if (!F_ISSET(txn, WT_TXN_RUNNING)) {
+ if (include_updates)
+ WT_RET_MSG(session, EINVAL, "A transaction must be "
+ "running to include updates in a named snapshot");
+
WT_RET(__wt_txn_begin(session, txn_cfg));
started_txn = true;
}
- F_SET(txn, WT_TXN_READONLY);
+ if (!include_updates)
+ F_SET(txn, WT_TXN_READONLY);
/* Save a copy of the transaction's snapshot. */
WT_ERR(__wt_calloc_one(session, &nsnap_new));
nsnap = nsnap_new;
WT_ERR(__wt_strndup(session, cval.str, cval.len, &nsnap->name));
+
+ /*
+ * To include updates from a writing transaction, make sure a
+ * transaction ID has been allocated.
+ */
+ if (include_updates) {
+ WT_ERR(__wt_txn_id_check(session));
+ WT_ASSERT(session, txn->id != WT_TXN_NONE);
+ nsnap->id = txn->id;
+ } else
+ nsnap->id = WT_TXN_NONE;
nsnap->pinned_id = WT_SESSION_TXN_STATE(session)->pinned_id;
nsnap->snap_min = txn->snap_min;
nsnap->snap_max = txn->snap_max;
@@ -209,8 +226,7 @@ err: if (started_txn) {
WT_TRET(__wt_txn_rollback(session, NULL));
WT_DIAGNOSTIC_YIELD;
WT_ASSERT(session, !__wt_txn_visible_all(session, pinned_id));
- } else if (ret == 0)
- F_SET(txn, WT_TXN_NAMED_SNAPSHOT);
+ }
if (nsnap_new != NULL)
__nsnap_destroy(session, nsnap_new);
@@ -303,6 +319,11 @@ __wt_txn_named_snapshot_get(WT_SESSION_IMPL *session, WT_CONFIG_ITEM *nameval)
memcpy(txn->snapshot, nsnap->snapshot,
nsnap->snapshot_count *
sizeof(*nsnap->snapshot));
+ if (nsnap->id != WT_TXN_NONE) {
+ WT_ASSERT(session, txn->id == WT_TXN_NONE);
+ txn->id = nsnap->id;
+ F_SET(txn, WT_TXN_READONLY);
+ }
F_SET(txn, WT_TXN_HAS_SNAPSHOT);
break;
}