From 9c9b46ba750801fec3f98d323fc99c83a3a0700b Mon Sep 17 00:00:00 2001 From: Luke Chen Date: Mon, 18 Oct 2021 14:00:30 +1100 Subject: Import wiredtiger: 51a5c5ff5b0ceea341f70a386fff5a9f68d2edac from branch mongodb-5.1 ref: e930e8d0cd..51a5c5ff5b for: 5.1.0-rc1 WT-8226 fix largest_key failed to consider prepared update --- src/third_party/wiredtiger/import.data | 2 +- src/third_party/wiredtiger/src/cursor/cur_std.c | 15 ++++---- src/third_party/wiredtiger/src/docs/cursor-ops.dox | 6 ++-- .../wiredtiger/src/include/txn_inline.h | 21 +++++++---- .../wiredtiger/src/include/wiredtiger.in | 1 + .../wiredtiger/test/suite/test_cursor17.py | 41 +++++++++++++++------- 6 files changed, 56 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data index c338f0f81f0..abf371b6693 100644 --- a/src/third_party/wiredtiger/import.data +++ b/src/third_party/wiredtiger/import.data @@ -2,5 +2,5 @@ "vendor": "wiredtiger", "github": "wiredtiger/wiredtiger.git", "branch": "mongodb-5.1", - "commit": "e930e8d0cd4c3330783e711253eae2923b1e2e3f" + "commit": "51a5c5ff5b0ceea341f70a386fff5a9f68d2edac" } diff --git a/src/third_party/wiredtiger/src/cursor/cur_std.c b/src/third_party/wiredtiger/src/cursor/cur_std.c index de5115845c7..1bf28de3f11 100644 --- a/src/third_party/wiredtiger/src/cursor/cur_std.c +++ b/src/third_party/wiredtiger/src/cursor/cur_std.c @@ -1124,23 +1124,24 @@ __wt_cursor_largest_key(WT_CURSOR *cursor) WT_DECL_RET; WT_SESSION_IMPL *session; bool ignore_tombstone; + bool visible_all; ignore_tombstone = F_ISSET(cursor, WT_CURSTD_IGNORE_TOMBSTONE); + visible_all = F_ISSET(cursor, WT_CURSTD_VISIBLE_ALL); CURSOR_API_CALL(cursor, session, largest_key, NULL); - if (F_ISSET(session->txn, WT_TXN_SHARED_TS_READ)) - WT_ERR_MSG(session, EINVAL, "largest key cannot be called with a read timestamp"); - WT_ERR(__wt_scr_alloc(session, 0, &key)); /* Reset the cursor to give up the cursor position. */ WT_ERR(cursor->reset(cursor)); - /* Ignore deletion */ + /* Ignore deletion. */ F_SET(cursor, WT_CURSTD_IGNORE_TOMBSTONE); + /* Ignore visibility. */ + F_SET(cursor, WT_CURSTD_VISIBLE_ALL); - /* Call cursor prev with read uncommitted isolation level. */ - WT_WITH_TXN_ISOLATION(session, WT_ISO_READ_UNCOMMITTED, ret = cursor->prev(cursor)); + /* Call cursor prev to get the largest key. */ + WT_ERR(cursor->prev(cursor)); WT_ERR(ret); /* Copy the key as we will reset the cursor after that. */ @@ -1153,6 +1154,8 @@ __wt_cursor_largest_key(WT_CURSOR *cursor) err: if (!ignore_tombstone) F_CLR(cursor, WT_CURSTD_IGNORE_TOMBSTONE); + if (!visible_all) + F_CLR(cursor, WT_CURSTD_VISIBLE_ALL); __wt_scr_free(session, &key); if (ret != 0) WT_TRET(cursor->reset(cursor)); diff --git a/src/third_party/wiredtiger/src/docs/cursor-ops.dox b/src/third_party/wiredtiger/src/docs/cursor-ops.dox index 82b763b563f..9618396a77c 100644 --- a/src/third_party/wiredtiger/src/docs/cursor-ops.dox +++ b/src/third_party/wiredtiger/src/docs/cursor-ops.dox @@ -108,10 +108,8 @@ record does not previously exist. The WT_SESSION::largest_key \c gets the largest key in a table regardless of visibility. -It can only be called without a read timestamp, otherwise it returns an invalid -argument error. Any following prev or next calls will behave as if they were -invoked on an unpositioned cursor no matter the largest key call is successful -or not. +Any following prev or next calls will behave as if they were invoked on an +unpositioned cursor no matter the largest key call is successful or not. @section cursor_error Cursor position after error diff --git a/src/third_party/wiredtiger/src/include/txn_inline.h b/src/third_party/wiredtiger/src/include/txn_inline.h index 908fe1d38dd..a6b13708057 100644 --- a/src/third_party/wiredtiger/src/include/txn_inline.h +++ b/src/third_party/wiredtiger/src/include/txn_inline.h @@ -766,9 +766,9 @@ __wt_txn_upd_visible_type(WT_SESSION_IMPL *session, WT_UPDATE *upd) if (prepare_state == WT_PREPARE_LOCKED) continue; - if (WT_IS_HS(session->dhandle) && upd->txnid != WT_TXN_ABORTED && - upd->type == WT_UPDATE_STANDARD) - /* Entries in the history store are always visible. */ + /* Entries in the history store are always visible. */ + if ((WT_IS_HS(session->dhandle) && upd->txnid != WT_TXN_ABORTED && + upd->type == WT_UPDATE_STANDARD)) return (WT_VISIBLE_TRUE); upd_visible = __wt_txn_visible(session, upd->txnid, upd->start_ts); @@ -901,7 +901,10 @@ __wt_txn_read_upd_list_internal(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, continue; } - upd_visible = __wt_txn_upd_visible_type(session, upd); + if (F_ISSET(&cbt->iface, WT_CURSTD_VISIBLE_ALL)) + upd_visible = WT_VISIBLE_TRUE; + else + upd_visible = __wt_txn_upd_visible_type(session, upd); if (upd_visible == WT_VISIBLE_TRUE) break; @@ -1038,8 +1041,14 @@ retry: cbt->upd_value->tw.prepare = tw.prepare; } - /* If the start time point is visible then we need to return the ondisk value. */ - if (WT_IS_HS(session->dhandle) || __wt_txn_tw_start_visible(session, &tw)) { + /* + * We return the onpage value in the following cases: + * 1. The record is from the history store. + * 2. It has the WT_CURSTD_VISIBLE_ALL flag set. + * 3. It is visible to the reader. + */ + if (WT_IS_HS(session->dhandle) || F_ISSET(&cbt->iface, WT_CURSTD_VISIBLE_ALL) || + __wt_txn_tw_start_visible(session, &tw)) { if (cbt->upd_value->skip_buf) { cbt->upd_value->buf.data = NULL; cbt->upd_value->buf.size = 0; diff --git a/src/third_party/wiredtiger/src/include/wiredtiger.in b/src/third_party/wiredtiger/src/include/wiredtiger.in index 3517c3523d2..ec50d871f90 100644 --- a/src/third_party/wiredtiger/src/include/wiredtiger.in +++ b/src/third_party/wiredtiger/src/include/wiredtiger.in @@ -735,6 +735,7 @@ struct __wt_cursor { #define WT_CURSTD_RAW_SEARCH 0x0800000u #define WT_CURSTD_VALUE_EXT 0x1000000u /* Value points out of tree. */ #define WT_CURSTD_VALUE_INT 0x2000000u /* Value points into tree. */ +#define WT_CURSTD_VISIBLE_ALL 0x4000000u /* AUTOMATIC FLAG VALUE GENERATION STOP 32 */ #define WT_CURSTD_KEY_SET (WT_CURSTD_KEY_EXT | WT_CURSTD_KEY_INT) #define WT_CURSTD_VALUE_SET (WT_CURSTD_VALUE_EXT | WT_CURSTD_VALUE_INT) diff --git a/src/third_party/wiredtiger/test/suite/test_cursor17.py b/src/third_party/wiredtiger/test/suite/test_cursor17.py index 322b82a65f8..becb6fcd5d3 100644 --- a/src/third_party/wiredtiger/test/suite/test_cursor17.py +++ b/src/third_party/wiredtiger/test/suite/test_cursor17.py @@ -118,32 +118,47 @@ class test_cursor17(wttest.WiredTigerTestCase): session2 = self.setUpSessionOpen(self.conn) cursor2 = session2.open_cursor(self.type + self.tablename, None) session2.begin_transaction() - cursor2[101] = self.ds.value(101) + cursor2[200] = self.ds.value(200) cursor = self.session.open_cursor(self.type + self.tablename, None) # Verify the largest key. self.session.begin_transaction() self.assertEqual(cursor.largest_key(), 0) - self.assertEqual(cursor.get_key(), 101) + self.assertEqual(cursor.get_key(), 200) self.session.rollback_transaction() session2.rollback_transaction() + + def test_invisible_timestamp(self): + self.populate(100) - def test_read_timestamp(self): + cursor = self.session.open_cursor(self.type + self.tablename, None) + self.session.begin_transaction() + cursor[200] = self.ds.value(200) + self.session.commit_transaction("commit_timestamp=" + self.timestamp_str(10)) + + # Verify the largest key. + self.session.begin_transaction("read_timestamp=" + self.timestamp_str(5)) + self.assertEqual(cursor.largest_key(), 0) + self.assertEqual(cursor.get_key(), 200) + self.session.rollback_transaction() + + def test_prepared_update(self): self.populate(100) + session2 = self.setUpSessionOpen(self.conn) + cursor2 = session2.open_cursor(self.type + self.tablename, None) + session2.begin_transaction() + cursor2[200] = self.ds.value(200) + session2.prepare_transaction("prepare_timestamp=" + self.timestamp_str(10)) + cursor = self.session.open_cursor(self.type + self.tablename, None) - self.session.begin_transaction('read_timestamp=' + self.timestamp_str(5)) - # Expect the largest key to throw. - with self.expectedStderrPattern("largest key cannot be called with a read timestamp"): - try: - cursor.largest_key() - except wiredtiger.WiredTigerError as e: - gotException = True - self.pr('got expected exception: ' + str(e)) - self.assertTrue(str(e).find('nvalid argument') >= 0) - self.assertTrue(gotException, msg = 'expected exception') + + # Verify the largest key. + self.session.begin_transaction("read_timestamp=" + self.timestamp_str(20)) + self.assertEqual(cursor.largest_key(), 0) + self.assertEqual(cursor.get_key(), 200) self.session.rollback_transaction() def test_not_positioned(self): -- cgit v1.2.1