diff options
author | Alison Felizzi <alison.felizzi@mongodb.com> | 2022-01-20 06:09:34 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-01-20 06:40:01 +0000 |
commit | 642bf716d84facac62a36fe247bf60c7821a8d6e (patch) | |
tree | cf7b2763c98b3cc54c5b912b7d5ccda21bd9bb12 | |
parent | 1a14fcf6f87827584ea5624b84a14247ef38dde9 (diff) | |
download | mongo-642bf716d84facac62a36fe247bf60c7821a8d6e.tar.gz |
Import wiredtiger: 85f16d6331a66fc6f5e2767dce40ccedce7f9f7d from branch mongodb-master
ref: c9247ed856..85f16d6331
for: 5.3.0
WT-8365 Improve performance for timestamp_transaction
-rw-r--r-- | src/third_party/wiredtiger/import.data | 2 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/txn/txn_timestamp.c | 72 | ||||
-rwxr-xr-x[-rw-r--r--] | src/third_party/wiredtiger/test/suite/test_debug_mode03.py | 68 |
3 files changed, 113 insertions, 29 deletions
diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data index 2d043350f8d..8db82ed1344 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-master", - "commit": "c9247ed856597fbc2fa4311a00b89ce97c916553" + "commit": "85f16d6331a66fc6f5e2767dce40ccedce7f9f7d" } diff --git a/src/third_party/wiredtiger/src/txn/txn_timestamp.c b/src/third_party/wiredtiger/src/txn/txn_timestamp.c index 75a9928ed0b..0d4fe46e412 100644 --- a/src/third_party/wiredtiger/src/txn/txn_timestamp.c +++ b/src/third_party/wiredtiger/src/txn/txn_timestamp.c @@ -854,50 +854,68 @@ __wt_txn_set_read_timestamp(WT_SESSION_IMPL *session, wt_timestamp_t read_ts) int __wt_txn_set_timestamp(WT_SESSION_IMPL *session, const char *cfg[]) { - WT_CONFIG_ITEM cval; + WT_CONFIG cparser; + WT_CONFIG_ITEM ckey, cval; WT_DECL_RET; - wt_timestamp_t ts; + wt_timestamp_t commit_ts, durable_ts, prepare_ts, read_ts; bool set_ts; set_ts = false; + commit_ts = durable_ts = prepare_ts = read_ts = 0; + WT_TRET(__wt_txn_context_check(session, true)); - /* Look for a commit timestamp. */ - ret = __wt_config_gets_def(session, cfg, "commit_timestamp", 0, &cval); - WT_RET_NOTFOUND_OK(ret); - if (ret == 0 && cval.len != 0) { - WT_RET(__wt_txn_parse_timestamp(session, "commit", &ts, &cval)); - WT_RET(__wt_txn_set_commit_timestamp(session, ts)); - set_ts = true; + /* + * If the API received no configuration string, or we just have the base configuration, there's + * nothing to do. + */ + if (cfg == NULL || cfg[0] == NULL || cfg[1] == NULL) + return (0); + + /* + * We take a shortcut in parsing that works because we're only given a base configuration and a + * user configuration. + */ + WT_ASSERT(session, cfg[0] != NULL && cfg[1] != NULL && cfg[2] == NULL); + __wt_config_init(session, &cparser, cfg[1]); + while ((ret = __wt_config_next(&cparser, &ckey, &cval)) == 0) { + WT_ASSERT(session, ckey.str != NULL); + if (WT_STRING_MATCH("commit_timestamp", ckey.str, ckey.len)) { + WT_RET(__wt_txn_parse_timestamp(session, "commit", &commit_ts, &cval)); + set_ts = true; + } else if (WT_STRING_MATCH("durable_timestamp", ckey.str, ckey.len)) { + WT_RET(__wt_txn_parse_timestamp(session, "durable", &durable_ts, &cval)); + set_ts = true; + } else if (WT_STRING_MATCH("prepare_timestamp", ckey.str, ckey.len)) { + WT_RET(__wt_txn_parse_timestamp(session, "prepare", &prepare_ts, &cval)); + set_ts = true; + } else if (WT_STRING_MATCH("read_timestamp", ckey.str, ckey.len)) { + WT_RET(__wt_txn_parse_timestamp(session, "durable", &read_ts, &cval)); + set_ts = true; + } } + WT_RET_NOTFOUND_OK(ret); + + /* Look for a commit timestamp. */ + if (commit_ts != 0) + WT_RET(__wt_txn_set_commit_timestamp(session, commit_ts)); /* * Look for a durable timestamp. Durable timestamp should be set only after setting the commit * timestamp. */ - ret = __wt_config_gets_def(session, cfg, "durable_timestamp", 0, &cval); - WT_RET_NOTFOUND_OK(ret); - if (ret == 0 && cval.len != 0) { - WT_RET(__wt_txn_parse_timestamp(session, "durable", &ts, &cval)); - WT_RET(__wt_txn_set_durable_timestamp(session, ts)); - } - + if (durable_ts != 0) + WT_RET(__wt_txn_set_durable_timestamp(session, durable_ts)); __wt_txn_publish_durable_timestamp(session); /* Look for a read timestamp. */ - WT_RET(__wt_config_gets_def(session, cfg, "read_timestamp", 0, &cval)); - if (ret == 0 && cval.len != 0) { - WT_RET(__wt_txn_parse_timestamp(session, "read", &ts, &cval)); - set_ts = true; - WT_RET(__wt_txn_set_read_timestamp(session, ts)); - } + if (read_ts != 0) + WT_RET(__wt_txn_set_read_timestamp(session, read_ts)); /* Look for a prepare timestamp. */ - WT_RET(__wt_config_gets_def(session, cfg, "prepare_timestamp", 0, &cval)); - if (ret == 0 && cval.len != 0) { - WT_RET(__wt_txn_parse_timestamp(session, "prepare", &ts, &cval)); - WT_RET(__wt_txn_set_prepare_timestamp(session, ts)); - } + if (prepare_ts != 0) + WT_RET(__wt_txn_set_prepare_timestamp(session, prepare_ts)); + if (set_ts) WT_RET(__wt_txn_ts_log(session)); diff --git a/src/third_party/wiredtiger/test/suite/test_debug_mode03.py b/src/third_party/wiredtiger/test/suite/test_debug_mode03.py index 34640d63712..3b0ad8ad694 100644..100755 --- a/src/third_party/wiredtiger/test/suite/test_debug_mode03.py +++ b/src/third_party/wiredtiger/test/suite/test_debug_mode03.py @@ -26,7 +26,10 @@ # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. -import wiredtiger, wttest +import struct, wiredtiger, wttest + +def timestamp(kind, ts): + return "{}_timestamp={:X}".format(kind, ts) # test_debug_mode03.py # Test the debug mode settings. Test table_logging use. @@ -44,6 +47,11 @@ class test_debug_mode03(wttest.WiredTigerTestCase): c[k] = self.value c.close() + def add_data_at_ts(self, ts): + self.session.begin_transaction() + self.add_data() + self.session.commit_transaction(timestamp("commit", ts)) + def find_log_recs(self): # Open a log cursor. We should find log records that have # the value we inserted. @@ -61,6 +69,39 @@ class test_debug_mode03(wttest.WiredTigerTestCase): c.close() return count + def pack_large_int(self, large): + # This line in intpacking.py tells us how to pack a large integer: + # + # First byte | Next bytes | Min Value | Max Value + # [11 10llll] | l | 2^13 + 2^6 | 2^64 - 1 + # + # An 8 byte integer is packed as byte 0xe8, followed by 8 bytes packed for big endian. + LARGE_INT = 2**13 + 2**6 + self.assertGreaterEqual(large, LARGE_INT) + packed_int = b'\xe8' + struct.pack('>Q', large - LARGE_INT) # >Q == 8 bytes big endian + return packed_int + + def find_ts_log_rec(self, ts): + # The timestamp we're looking for will be encoded as a 'packed integer' in the log file. We + # don't need a general purpose encoder here, we just need to know how to pack large integers. + packed_int = self.pack_large_int(ts) + + # Open a log cursor, and we look for the timestamp somewhere in the values. + c = self.session.open_cursor("log:", None) + count = 0 + while c.next() == 0: + # lsn.file, lsn.offset, opcount + keys = c.get_key() + # txnid, rectype, optype, fileid, logrec_key, logrec_value + values = c.get_value() + + #self.tty('LOG: keys={}, values={}\n val5={}\n packed={}'.format( + # str(keys), str(values), values[5].hex(), packed_int.hex())) + if packed_int in values[5]: # logrec_value + count += 1 + c.close() + return count + def test_table_logging(self): self.session.create(self.uri, 'key_format=i,value_format=u,log=(enabled=false)') self.add_data() @@ -75,5 +116,30 @@ class test_debug_mode03(wttest.WiredTigerTestCase): count = self.find_log_recs() self.assertEqual(count, 0) + # Debug table logging with operations from timestamp_transaction + def test_table_logging_ts(self): + # We pick a large timestamp because encoding a large integer is relatively easy + # and we won't get any false positives when searching the log file. + base_ts = 0x1020304050600000 + + self.session.create(self.uri, 'key_format=i,value_format=u,log=(enabled=false)') + self.add_data_at_ts(base_ts + 0x100) + + self.session.begin_transaction() + c = self.session.open_cursor(self.uri, None) + c[self.entries] = self.value + c.close() + self.session.timestamp_transaction(timestamp("read", base_ts + 0x200)) + self.session.prepare_transaction(timestamp("prepare", base_ts + 0x201)) + self.session.timestamp_transaction(timestamp("commit", base_ts + 0x202)) + self.session.timestamp_transaction(timestamp("durable", base_ts + 0x203)) + self.session.commit_transaction() + + self.assertGreater(self.find_ts_log_rec(base_ts + 0x100), 0) + self.assertGreater(self.find_ts_log_rec(base_ts + 0x200), 0) + self.assertGreater(self.find_ts_log_rec(base_ts + 0x201), 0) + self.assertGreater(self.find_ts_log_rec(base_ts + 0x202), 0) + self.assertGreater(self.find_ts_log_rec(base_ts + 0x203), 0) + if __name__ == '__main__': wttest.run() |