diff options
Diffstat (limited to 'src/third_party/wiredtiger/src/txn/txn_nsnap.c')
-rw-r--r-- | src/third_party/wiredtiger/src/txn/txn_nsnap.c | 55 |
1 files changed, 47 insertions, 8 deletions
diff --git a/src/third_party/wiredtiger/src/txn/txn_nsnap.c b/src/third_party/wiredtiger/src/txn/txn_nsnap.c index 8f7e93238de..7ba0cc8700e 100644 --- a/src/third_party/wiredtiger/src/txn/txn_nsnap.c +++ b/src/third_party/wiredtiger/src/txn/txn_nsnap.c @@ -42,9 +42,16 @@ __nsnap_drop_one(WT_SESSION_IMPL *session, WT_CONFIG_ITEM *name) return (WT_NOTFOUND); /* Bump the global ID if we are removing the first entry */ - if (found == TAILQ_FIRST(&txn_global->nsnaph)) + if (found == TAILQ_FIRST(&txn_global->nsnaph)) { + WT_ASSERT(session, !__wt_txn_visible_all( + session, txn_global->nsnap_oldest_id)); txn_global->nsnap_oldest_id = (TAILQ_NEXT(found, q) != NULL) ? - TAILQ_NEXT(found, q)->snap_min : WT_TXN_NONE; + TAILQ_NEXT(found, q)->pinned_id : WT_TXN_NONE; + WT_DIAGNOSTIC_YIELD; + WT_ASSERT(session, txn_global->nsnap_oldest_id == WT_TXN_NONE || + !__wt_txn_visible_all( + session, txn_global->nsnap_oldest_id)); + } TAILQ_REMOVE(&txn_global->nsnaph, found, q); __nsnap_destroy(session, found); WT_STAT_CONN_INCR(session, txn_snapshots_dropped); @@ -104,7 +111,7 @@ __nsnap_drop_to(WT_SESSION_IMPL *session, WT_CONFIG_ITEM *name, bool inclusive) } if (TAILQ_NEXT(last, q) != NULL) - new_nsnap_oldest = TAILQ_NEXT(last, q)->snap_min; + new_nsnap_oldest = TAILQ_NEXT(last, q)->pinned_id; } do { @@ -117,7 +124,15 @@ __nsnap_drop_to(WT_SESSION_IMPL *session, WT_CONFIG_ITEM *name, bool inclusive) } while (nsnap != last && !TAILQ_EMPTY(&txn_global->nsnaph)); /* Now that the queue of named snapshots is updated, update the ID */ + WT_ASSERT(session, !__wt_txn_visible_all( + session, txn_global->nsnap_oldest_id) && + (new_nsnap_oldest == WT_TXN_NONE || + WT_TXNID_LE(txn_global->nsnap_oldest_id, new_nsnap_oldest))); txn_global->nsnap_oldest_id = new_nsnap_oldest; + WT_DIAGNOSTIC_YIELD; + WT_ASSERT(session, + new_nsnap_oldest == WT_TXN_NONE || + !__wt_txn_visible_all(session, new_nsnap_oldest)); return (ret); } @@ -157,6 +172,7 @@ __wt_txn_named_snapshot_begin(WT_SESSION_IMPL *session, const char *cfg[]) WT_ERR(__wt_calloc_one(session, &nsnap_new)); nsnap = nsnap_new; WT_ERR(__wt_strndup(session, cval.str, cval.len, &nsnap->name)); + nsnap->pinned_id = WT_SESSION_TXN_STATE(session)->pinned_id; nsnap->snap_min = txn->snap_min; nsnap->snap_max = txn->snap_max; if (txn->snapshot_count > 0) { @@ -175,15 +191,25 @@ __wt_txn_named_snapshot_begin(WT_SESSION_IMPL *session, const char *cfg[]) */ WT_ERR_NOTFOUND_OK(__nsnap_drop_one(session, &cval)); - if (TAILQ_EMPTY(&txn_global->nsnaph)) - txn_global->nsnap_oldest_id = nsnap_new->snap_min; + if (TAILQ_EMPTY(&txn_global->nsnaph)) { + WT_ASSERT(session, txn_global->nsnap_oldest_id == WT_TXN_NONE && + !__wt_txn_visible_all(session, nsnap_new->pinned_id)); + __wt_readlock(session, txn_global->scan_rwlock); + txn_global->nsnap_oldest_id = nsnap_new->pinned_id; + __wt_readunlock(session, txn_global->scan_rwlock); + } TAILQ_INSERT_TAIL(&txn_global->nsnaph, nsnap_new, q); WT_STAT_CONN_INCR(session, txn_snapshots_created); nsnap_new = NULL; -err: if (started_txn) +err: if (started_txn) { +#ifdef HAVE_DIAGNOSTIC + uint64_t pinned_id = WT_SESSION_TXN_STATE(session)->pinned_id; +#endif WT_TRET(__wt_txn_rollback(session, NULL)); - else if (ret == 0) + 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) @@ -258,7 +284,20 @@ __wt_txn_named_snapshot_get(WT_SESSION_IMPL *session, WT_CONFIG_ITEM *nameval) __wt_readlock(session, txn_global->nsnap_rwlock); TAILQ_FOREACH(nsnap, &txn_global->nsnaph, q) if (WT_STRING_MATCH(nsnap->name, nameval->str, nameval->len)) { - txn->snap_min = txn_state->snap_min = nsnap->snap_min; + /* + * Acquire the scan lock so the oldest ID can't move + * forward without seeing our pinned ID. + */ + __wt_readlock(session, txn_global->scan_rwlock); + txn_state->pinned_id = nsnap->pinned_id; + __wt_readunlock(session, txn_global->scan_rwlock); + + WT_ASSERT(session, !__wt_txn_visible_all( + session, txn_state->pinned_id) && + txn_global->nsnap_oldest_id != WT_TXN_NONE && + WT_TXNID_LE(txn_global->nsnap_oldest_id, + txn_state->pinned_id)); + txn->snap_min = nsnap->snap_min; txn->snap_max = nsnap->snap_max; if ((txn->snapshot_count = nsnap->snapshot_count) != 0) memcpy(txn->snapshot, nsnap->snapshot, |