summaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorAlex Gorrod <alexander.gorrod@mongodb.com>2015-07-01 17:58:06 +1000
committerMichael Cahill <michael.cahill@mongodb.com>2015-07-02 13:37:37 +1000
commit7a9e1bdade725fd59a0fd87ca77c7dd66aeba1ec (patch)
treecaa348cb25b880993b55a4e6efa599c173de4a11 /src/include
parent9f72da7968f828753276aaf92afbb0c82f75a3b4 (diff)
downloadmongo-7a9e1bdade725fd59a0fd87ca77c7dd66aeba1ec.tar.gz
WT-1982 Fix a window where reconciliation could go back in transaction time.
(cherry picked from commit cd1704d6c4d84c5db8ae6b471c658945ffa226f9)
Diffstat (limited to 'src/include')
-rw-r--r--src/include/btmem.h5
-rw-r--r--src/include/txn.h5
-rw-r--r--src/include/txn.i30
3 files changed, 22 insertions, 18 deletions
diff --git a/src/include/btmem.h b/src/include/btmem.h
index 77ad31fc3f6..23b17ef2cd3 100644
--- a/src/include/btmem.h
+++ b/src/include/btmem.h
@@ -194,6 +194,11 @@ struct __wt_page_modify {
/* The largest update transaction ID (approximate). */
uint64_t update_txn;
+#ifdef HAVE_DIAGNOSTIC
+ /* Check that transaction time moves forward. */
+ uint64_t last_oldest_id;
+#endif
+
/* Dirty bytes added to the cache. */
size_t bytes_dirty;
diff --git a/src/include/txn.h b/src/include/txn.h
index dbaa11309ab..d2b369a41c4 100644
--- a/src/include/txn.h
+++ b/src/include/txn.h
@@ -25,6 +25,9 @@
#define WT_SESSION_TXN_STATE(s) (&S2C(s)->txn_global.states[(s)->id])
+#define WT_SESSION_IS_CHECKPOINT(s) \
+ ((s)->id != 0 && (s)->id == S2C(s)->txn_global.checkpoint_id)
+
struct WT_COMPILER_TYPE_ALIGN(WT_CACHE_LINE_ALIGNMENT) __wt_txn_state {
volatile uint64_t id;
volatile uint64_t snap_min;
@@ -54,7 +57,7 @@ struct __wt_txn_global {
*/
volatile uint32_t checkpoint_id; /* Checkpoint's session ID */
volatile uint64_t checkpoint_gen;
- volatile uint64_t checkpoint_snap_min;
+ volatile uint64_t checkpoint_pinned;
WT_TXN_STATE *states; /* Per-session transaction states */
};
diff --git a/src/include/txn.i b/src/include/txn.i
index f0b0534ff4a..a9b19ca1ff5 100644
--- a/src/include/txn.i
+++ b/src/include/txn.i
@@ -98,8 +98,8 @@ __wt_txn_oldest_id(WT_SESSION_IMPL *session)
{
WT_BTREE *btree;
WT_TXN_GLOBAL *txn_global;
- uint64_t checkpoint_snap_min, oldest_id;
- uint32_t checkpoint_id;
+ uint64_t checkpoint_pinned, oldest_id;
+ uint32_t checkpoint_gen;
txn_global = &S2C(session)->txn_global;
btree = S2BT_SAFE(session);
@@ -108,9 +108,9 @@ __wt_txn_oldest_id(WT_SESSION_IMPL *session)
* Take a local copy of these IDs in case they are updated while we are
* checking visibility.
*/
- checkpoint_id = txn_global->checkpoint_id;
- checkpoint_snap_min = txn_global->checkpoint_snap_min;
- oldest_id = txn_global->oldest_id;
+ WT_ORDERED_READ(oldest_id, txn_global->oldest_id);
+ WT_ORDERED_READ(checkpoint_gen, txn_global->checkpoint_gen);
+ WT_ORDERED_READ(checkpoint_pinned, txn_global->checkpoint_pinned);
/*
* Checkpoint transactions often fall behind ordinary application
@@ -122,17 +122,13 @@ __wt_txn_oldest_id(WT_SESSION_IMPL *session)
* checkpoint, or this handle is up to date with the active checkpoint
* then it's safe to ignore the checkpoint ID in the visibility check.
*/
- if (checkpoint_snap_min != WT_TXN_NONE &&
- checkpoint_id != session->id && (btree == NULL ||
- btree->checkpoint_gen != txn_global->checkpoint_gen) &&
- TXNID_LT(checkpoint_snap_min, oldest_id))
- /*
- * Use the checkpoint ID for the visibility check if it is the
- * oldest ID in the system.
- */
- oldest_id = checkpoint_snap_min;
+ if (checkpoint_pinned == WT_TXN_NONE ||
+ TXNID_LT(oldest_id, checkpoint_pinned) ||
+ WT_SESSION_IS_CHECKPOINT(session) ||
+ (btree != NULL && btree->checkpoint_gen == checkpoint_gen))
+ return (oldest_id);
- return (oldest_id);
+ return (checkpoint_pinned);
}
/*
@@ -340,7 +336,7 @@ __wt_txn_id_check(WT_SESSION_IMPL *session)
if (!F_ISSET(txn, TXN_HAS_ID)) {
conn = S2C(session);
txn_global = &conn->txn_global;
- txn_state = &txn_global->states[session->id];
+ txn_state = WT_SESSION_TXN_STATE(session);
WT_ASSERT(session, txn_state->id == WT_TXN_NONE);
@@ -432,7 +428,7 @@ __wt_txn_cursor_op(WT_SESSION_IMPL *session)
txn = &session->txn;
txn_global = &S2C(session)->txn_global;
- txn_state = &txn_global->states[session->id];
+ txn_state = WT_SESSION_TXN_STATE(session);
/*
* If there is no transaction running (so we don't have an ID), and no