summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Chen <luke.chen@mongodb.com>2022-05-09 15:45:27 +1000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-05-09 06:19:32 +0000
commit20c06486b1efec6cf6dbd3b69890b07cedbe449f (patch)
tree446aa484068f935ca6cbb5e84e552845be5c25f8
parenta9a4d9997802371464c865e62ccd209a35d3903d (diff)
downloadmongo-20c06486b1efec6cf6dbd3b69890b07cedbe449f.tar.gz
Import wiredtiger: 96e1178c2cfb2adc2e53d2fbc7e512025ddf6cc2 from branch mongodb-master
ref: b9c5631ea0..96e1178c2c for: 6.1.0-rc0 WT-8158 Add gdb helper scripts to WiredTiger repository
-rw-r--r--src/third_party/wiredtiger/import.data2
-rw-r--r--src/third_party/wiredtiger/tools/gdb/dump_row_int.gdb66
-rw-r--r--src/third_party/wiredtiger/tools/gdb/wt.gdb11
-rw-r--r--src/third_party/wiredtiger/tools/gdb/wt_debug_script_update.py150
4 files changed, 228 insertions, 1 deletions
diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data
index d87ef49654a..92864186e3c 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": "b9c5631ea09739586d6b76c2d4e11903bb2bccec"
+ "commit": "96e1178c2cfb2adc2e53d2fbc7e512025ddf6cc2"
}
diff --git a/src/third_party/wiredtiger/tools/gdb/dump_row_int.gdb b/src/third_party/wiredtiger/tools/gdb/dump_row_int.gdb
new file mode 100644
index 00000000000..d83e54b0ed8
--- /dev/null
+++ b/src/third_party/wiredtiger/tools/gdb/dump_row_int.gdb
@@ -0,0 +1,66 @@
+# A helper script to dump row store internal page keys.
+# Usage: dump_row_int_keys <page>
+
+# Dump keys from a row store internal page.
+# Has one argument which is the page.
+define dump_row_int_keys
+ set pagination off
+ set $i = 0
+ set $page = $arg0
+ while $i < $page->u->intl->__index.entries
+ set $ikey = $page->u->intl->__index->index[$i].key.ikey
+ set $v = (uintptr_t)$ikey
+
+ set $keyp = 0
+ set $size = 0
+ set $key_location = ""
+
+ if $v & 0x1
+ set $key_location = "DSK:"
+# Relevant code snippets from WiredTiger we are trying to simulate.
+# #define WT_IK_FLAG 0x01
+# #define WT_IK_DECODE_KEY_LEN(v) ((v) >> 32)
+# #define WT_IK_DECODE_KEY_OFFSET(v) (((v)&0xFFFFFFFF) >> 1)
+# #define WT_PAGE_REF_OFFSET(page, o) ((void *)((uint8_t *)((page)->dsk) + (o)))
+# if (v & WT_IK_FLAG) {
+# *(void **)keyp = WT_PAGE_REF_OFFSET(page, WT_IK_DECODE_KEY_OFFSET(v));
+# *sizep = WT_IK_DECODE_KEY_LEN(v);
+ set $key_offset = (($v) & 0xFFFFFFFF) >> 1
+ set $keyp = ((void *)((uint8_t *)($page->dsk) + $key_offset))
+ set $size = ($v) >> 32
+ else
+ set $key_location = "MEM:"
+ set $keyp = ((void *)((uint8_t *)($ikey) + 8))
+ set $size = ((WT_IKEY*)$ikey)->size
+ end
+ set $sz_pad = ""
+ if $size < 10
+ set $sz_pad = " "
+ else
+ if $size < 100
+ set $sz_pad = " "
+ end
+ end
+ set $off_pad = ""
+ if $i < 10
+ set $off_pad = " "
+ else
+ if $i < 100
+ set $off_pad = " "
+ else
+ if $i < 1000
+ set $off_pad = " "
+ end
+ end
+ end
+ printf "%s%u:%s%s%u: ", $off_pad, $i, $key_location, $sz_pad, $size
+ set $j = 0
+ while $j < $size
+ printf "%c", ((char*)$keyp)[$j]
+ set $j = $j + 1
+ end
+ printf "\n"
+
+ set $i = $i + 1
+ end
+end
diff --git a/src/third_party/wiredtiger/tools/gdb/wt.gdb b/src/third_party/wiredtiger/tools/gdb/wt.gdb
new file mode 100644
index 00000000000..cd446e4f1ca
--- /dev/null
+++ b/src/third_party/wiredtiger/tools/gdb/wt.gdb
@@ -0,0 +1,11 @@
+# Usage: source <path_to>/wt.gdb
+# This is a thin wrapper around the other files that hold actual helper functions.
+
+# Assume GDB is run from a build directory one level deep in the tree.
+# TODO: Find a better solution
+directory ../tools/gdb_commands
+
+# Source the known gdb helpers
+source dump_row_int.gdb
+source wt_debug_script_update.py
+
diff --git a/src/third_party/wiredtiger/tools/gdb/wt_debug_script_update.py b/src/third_party/wiredtiger/tools/gdb/wt_debug_script_update.py
new file mode 100644
index 00000000000..13a04c18ef9
--- /dev/null
+++ b/src/third_party/wiredtiger/tools/gdb/wt_debug_script_update.py
@@ -0,0 +1,150 @@
+import gdb
+import bson
+from pprint import pprint
+
+# Usage examples:
+# coll_dh = get_data_handle(conn, 'file:collection-5550--7194480883124807592.wt')
+# dump_handle(coll_dh)
+# index_dh = get_data_handle(conn, 'file:index-5558--7194480883124807592.wt')
+# dump_handle(index_dh)
+
+def dbg(ident, var):
+ print('----------')
+ if type(var) == gdb.Value:
+ print('{}: ({}*){}'.format(ident, var.type, var.address))
+ else:
+ print(ident)
+ print(' ' + str(type(var)))
+ methods = dir(var)
+ out = [name for name in methods if not name.startswith("__")]
+ for item in out:
+ print(' ' + item)
+
+ if type(var) == gdb.Value:
+ print('\n Fields:')
+ print('\t' + '\n\t'.join(str(var).split('\n')))
+
+conn_impl_ptr = gdb.lookup_type("WT_CONNECTION_IMPL").pointer()
+dbg('impl', conn_impl_ptr)
+
+conn = gdb.parse_and_eval("session->iface->connection").reinterpret_cast(conn_impl_ptr).dereference()
+dbg('conn', conn)
+
+def walk_wt_list(lst):
+ ret = []
+ node = conn['dhqh']['tqh_first']
+ #dbg('node', node)
+ while True:
+ if not node:
+ break
+ ret.append(node.dereference())
+ node = node['q']['tqe_next']
+
+ return ret
+
+def get_data_handle(conn, handle_name):
+ #dbg('datahandles', conn['dhqh'])
+ ret = None
+ for handle in walk_wt_list(conn['dhqh']):
+ #print("Handle: " + str(handle['name']))
+ if handle['name'].string() == handle_name:
+ ret = handle
+
+ return ret
+
+def get_btree_handle(dhandle):
+ btree = gdb.lookup_type('WT_BTREE').pointer()
+ return dhandle['handle'].reinterpret_cast(btree).dereference()
+
+def dump_update_chain(update_chain):
+ while True:
+ if not update_chain:
+ print(' λ')
+ break
+ #dbg('update', update_chain)
+ wt_val = update_chain.dereference()
+ obj = None
+ #dbg('wt_val', wt_val)
+ val_bytes = gdb.selected_inferior().read_memory(wt_val['data'], wt_val['size'])
+ can_bson = wt_val['type'] == 3
+ if can_bson:
+ try:
+ obj = bson.decode_all(val_bytes)[0]
+ except:
+ pass
+ print(' ' + '\n '.join(str(wt_val).split('\n')) + " " + str(obj) + " =>")
+
+ update_chain = update_chain['next']
+
+def dump_insert_list(wt_insert):
+ key_struct = wt_insert['u']['key']
+ key = gdb.selected_inferior().read_memory(int(wt_insert.address) + key_struct['offset'], key_struct['size']).tobytes()
+ print('Key: ' + str(key))
+ print('Value:')
+ update_chain = wt_insert['upd']
+ dump_update_chain(update_chain)
+
+def dump_skip_list(wt_insert_head):
+ wt_insert = wt_insert_head['head'][0]
+ idx = 0
+ while True:
+ if not wt_insert:
+ break
+ dump_insert_list(wt_insert.dereference())
+ #dbg('insert' + str(idx), wt_insert.dereference())
+ idx+=1
+ wt_insert = wt_insert['next'][0]
+
+def dump_modified(leaf_page):
+ print("Modify:")
+ if not leaf_page['modify']:
+ print("No modifies")
+ return
+
+ leaf_modify = leaf_page['modify'].dereference()
+ #dbg('modify', leaf_modify)
+ row_leaf_insert = leaf_modify['u2']['row_leaf']['insert']
+ #dbg('row store', row_leaf_modify)
+ if not row_leaf_insert:
+ print("No insert list")
+ else:
+ print("Insert list:")
+ dump_skip_list(row_leaf_insert.dereference().dereference())
+
+ row_leaf_update = leaf_modify['u2']['row_leaf']['update']
+ if not row_leaf_update:
+ print("No update list")
+ else:
+ print("Update list:")
+ leaf_num_entries = int(leaf_page['entries'])
+ for i in range(0, leaf_num_entries):
+ dump_update_chain(row_leaf_update[i])
+
+def dump_disk(leaf_page):
+ leaf_num_entries = int(leaf_page['entries'])
+ dbg('in-memory page:', leaf_page)
+ dsk = leaf_page['dsk'].dereference()
+ if int(dsk.address) == 0:
+ print("No page loaded from disk.")
+ return
+ dbg('on-disk page:', dsk)
+ wt_page_header_size = 28
+ wt_block_header_size = 12
+ page_bytes = gdb.selected_inferior().read_memory(int(dsk.address) + wt_page_header_size + wt_block_header_size, int(dsk['mem_size'])).tobytes()
+ print("Dsk:\n" + str(page_bytes))
+
+def dump_handle(dhandle):
+ print("Dumping: " + dhandle['name'].string())
+ btree = get_btree_handle(dhandle)
+ root = btree['root']
+ root_page = root['page'].dereference()
+ dbg('btree', get_btree_handle(user))
+ dbg('root', btree['root'])
+ dbg('root page', root_page)
+ rpindex = root_page['u']['intl']['__index'].dereference()
+ dbg('rpindex', rpindex)
+ dbg('rp-pre-index', rpindex['index'].dereference().dereference())
+ leaf_page = rpindex['index'].dereference().dereference()['page'].dereference()
+ dbg('leaf', leaf_page)
+ dump_disk(leaf_page)
+ dump_modified(leaf_page)