From 1607e9204c3be422adcb293cfdc64a567c5c9987 Mon Sep 17 00:00:00 2001 From: Michael Cahill Date: Tue, 2 Aug 2016 16:42:36 +1000 Subject: WT-2804 Don't read values in a tree without a snapshot. (#2924) * Improve an assertion from WT-2802 that checks that we don't try to copy values from a cursor without a transaction pinned. * Copy cursor values before rollback in autocommit. If an autocommit operation such as WT_CURSOR::update touches multiple trees (e.g., multiple column groups in a table, or index updates, or multiple chunks in an LSM tree), then some cursors may have consumed the application's key/value pair when the operation has to roll back. Take a copy of any such values before attempting to retry the operation. (cherry picked from commit 41eb2dcaac1ff25654d1503f5e29714576ff8d81) --- src/include/api.h | 2 ++ src/session/session_api.c | 12 ++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/include/api.h b/src/include/api.h index 4514f5a42fa..86e560ced78 100644 --- a/src/include/api.h +++ b/src/include/api.h @@ -66,6 +66,8 @@ else if (ret == 0 && !F_ISSET(&(s)->txn, WT_TXN_ERROR)) \ ret = __wt_txn_commit((s), NULL); \ else { \ + if (retry) \ + WT_TRET(__wt_session_copy_values(s)); \ WT_TRET(__wt_txn_rollback((s), NULL)); \ if ((ret == 0 || ret == WT_ROLLBACK) && \ (retry)) { \ diff --git a/src/session/session_api.c b/src/session/session_api.c index cfd4c13ab2d..dffd832672e 100644 --- a/src/session/session_api.c +++ b/src/session/session_api.c @@ -43,10 +43,14 @@ __wt_session_copy_values(WT_SESSION_IMPL *session) TAILQ_FOREACH(cursor, &session->cursors, q) if (F_ISSET(cursor, WT_CURSTD_VALUE_INT)) { - /* We have to do this with a transaction ID pinned. */ - WT_ASSERT(session, - WT_SESSION_TXN_STATE(session)->snap_min != - WT_TXN_NONE); +#ifdef HAVE_DIAGNOSTIC + /* + * We have to do this with a transaction ID pinned + * unless the cursor is reading from a checkpoint. + */ + WT_TXN_STATE *txn_state = WT_SESSION_TXN_STATE(session); + WT_ASSERT(session, txn_state->snap_min != WT_TXN_NONE); +#endif F_CLR(cursor, WT_CURSTD_VALUE_INT); WT_RET(__wt_buf_set(session, &cursor->value, -- cgit v1.2.1