summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlison Felizzi <alison.felizzi@mongodb.com>2022-01-20 06:09:34 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-01-20 06:40:01 +0000
commit642bf716d84facac62a36fe247bf60c7821a8d6e (patch)
treecf7b2763c98b3cc54c5b912b7d5ccda21bd9bb12
parent1a14fcf6f87827584ea5624b84a14247ef38dde9 (diff)
downloadmongo-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.data2
-rw-r--r--src/third_party/wiredtiger/src/txn/txn_timestamp.c72
-rwxr-xr-x[-rw-r--r--]src/third_party/wiredtiger/test/suite/test_debug_mode03.py68
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()