summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCheahuychou Mao <mao.cheahuychou@gmail.com>2022-04-13 20:59:51 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-04-18 16:12:56 +0000
commit0b8c3267a6a61454010848f3b969f62b7525892d (patch)
tree2793b94ab7d571e8966f0a058670311195a8c94e
parent845602af9c2f05f33fe03ec4f0b49f843bb81740 (diff)
downloadmongo-0b8c3267a6a61454010848f3b969f62b7525892d.tar.gz
SERVER-65505 Make the gdb pretty printers for Session/TransactionParticipant work with the latest version of the SessionCatalog
(cherry picked from commit 53eaaa11e4e19029a714c2db6d243af3b5fbbd68)
-rw-r--r--buildscripts/gdb/mongo.py211
1 files changed, 124 insertions, 87 deletions
diff --git a/buildscripts/gdb/mongo.py b/buildscripts/gdb/mongo.py
index b39d08a77c1..6ad24bf9a85 100644
--- a/buildscripts/gdb/mongo.py
+++ b/buildscripts/gdb/mongo.py
@@ -318,75 +318,100 @@ class DumpMongoDSessionCatalog(gdb.Command):
else:
lsids_to_print = [str(s['first']['_id']) for s in session_kv_pairs]
- for sess_kv in session_kv_pairs:
- # The Session is stored inside the SessionRuntimeInfo object.
- session_runtime_info = get_unique_ptr(sess_kv['second']).dereference() # pylint: disable=undefined-variable
- session = session_runtime_info['session']
- # TODO: Add a custom pretty printer for LogicalSessionId.
- lsid_str = str(session['_sessionId']['_id'])
+ for session_kv in session_kv_pairs:
+ # The Session objects are stored inside the SessionRuntimeInfo object.
+ session_runtime_info = get_unique_ptr(session_kv['second']).dereference() # pylint: disable=undefined-variable
+ parent_session = session_runtime_info['parentSession']
+ child_sessions = absl_get_nodes(session_runtime_info['childSessions']) # pylint: disable=undefined-variable
+ lsid = str(parent_session['_sessionId']['_id'])
# If we are only interested in a specific session, then we print out the entire Session
- # object, to aid more detailed debugging.
- if lsid_str == lsid_to_find:
- print("SessionId", "=", lsid_str)
- print(session)
+ # objects, to aid more detailed debugging.
+ if lsid == lsid_to_find:
+ self.dump_session_runtime_info(session_runtime_info)
+ print(parent_session)
+ for child_session_kv in child_sessions:
+ child_session = child_session_kv['second']
+ print(child_session)
# Terminate if this is the only session we care about.
break
# Only print info for the necessary sessions.
- if lsid_str not in lsids_to_print:
+ if lsid not in lsids_to_print:
continue
- # If we are printing multiple sessions, we only print the most interesting fields from
- # the Session object for the sake of efficiency. We print the session id string first so
- # the session is easily identifiable.
- print("Session (" + str(session.address) + "):")
- print("SessionId", "=", lsid_str)
- session_fields_to_print = ['_checkoutOpCtx', '_killsRequested']
- for field in session_fields_to_print:
+ # If we are printing multiple sessions, we only print the most interesting fields for
+ # each Session object for the sake of efficiency.
+ self.dump_session_runtime_info(session_runtime_info)
+ self.dump_session(parent_session)
+ for child_session_kv in child_sessions:
+ child_session = child_session_kv['second']
+ self.dump_session(child_session)
+
+ @staticmethod
+ def dump_session_runtime_info(session_runtime_info):
+ """Dump the session runtime info."""
+
+ parent_session = session_runtime_info['parentSession']
+ # TODO: Add a custom pretty printer for LogicalSessionId.
+ lsid = str(parent_session['_sessionId']['_id'])[1:-1]
+ print("SessionId =", lsid)
+ fields_to_print = ['checkoutOpCtx', 'killsRequested']
+ for field in fields_to_print:
+ # Skip fields that aren't found on the object.
+ if field in get_field_names(session_runtime_info):
+ print(field, "=", session_runtime_info[field])
+ else:
+ print("Could not find field '%s' on the SessionRuntimeInfo object." % field)
+ print("")
+
+ @staticmethod
+ def dump_session(session):
+ """Dump the session."""
+
+ print("Session (" + str(session.address) + "):")
+ fields_to_print = ['_sessionId', '_numWaitingToCheckOut']
+ for field in fields_to_print:
+ # Skip fields that aren't found on the object.
+ if field in get_field_names(session):
+ print(field, "=", session[field])
+ else:
+ print("Could not find field '%s' on the SessionRuntimeInfo object." % field)
+
+ # Print the information from a TransactionParticipant if a session has one.
+ txn_part_dec = get_decoration(session, "TransactionParticipant")
+ if txn_part_dec:
+ # Only print the most interesting fields for debugging transactions issues. The
+ # TransactionParticipant class encapsulates internal state in two distinct
+ # structures: a 'PrivateState' type (stored in private field '_p') and an
+ # 'ObservableState' type (stored in private field '_o'). The information we care
+ # about here is all contained inside the 'ObservableState', so we extract fields
+ # from that object. If, in the future, we want to print fields from the
+ # 'PrivateState' object, we can inspect the TransactionParticipant's '_p' field.
+ txn_part = txn_part_dec[1]
+ txn_part_observable_state = txn_part['_o']
+ fields_to_print = ['txnState', 'activeTxnNumberAndRetryCounter']
+ print("TransactionParticipant (" + str(txn_part.address) + "):")
+ for field in fields_to_print:
# Skip fields that aren't found on the object.
- if field in get_field_names(session):
- print(field, "=", session[field])
- else:
- print("Could not find field '%s' on the Session object." % field)
-
- # Print the information from a TransactionParticipant if a session has one. Otherwise
- # we just print the session's id and nothing else.
- txn_part_dec = get_decoration(session, "TransactionParticipant")
- if txn_part_dec:
- # Only print the most interesting fields for debugging transactions issues. The
- # TransactionParticipant class encapsulates internal state in two distinct
- # structures: a 'PrivateState' type (stored in private field '_p') and an
- # 'ObservableState' type (stored in private field '_o'). The information we care
- # about here is all contained inside the 'ObservableState', so we extract fields
- # from that object. If, in the future, we want to print fields from the
- # 'PrivateState' object, we can inspect the TransactionParticipant's '_p' field.
- txn_part = txn_part_dec[1]
- txn_part_observable_state = txn_part['_o']
- fields_to_print = ['txnState', 'activeTxnNumber']
- print("TransactionParticipant (" + str(txn_part.address) + "):")
- for field in fields_to_print:
- # Skip fields that aren't found on the object.
- if field in get_field_names(txn_part_observable_state):
- print(field, "=", txn_part_observable_state[field])
- else:
- print("Could not find field '%s' on the TransactionParticipant" % field)
-
- # The 'txnResourceStash' field is a boost::optional so we unpack it manually if it
- # is non-empty. We are only interested in its Locker object for now. TODO: Load the
- # boost pretty printers so the object will be printed clearly by default, without
- # the need for special unpacking.
- val = get_boost_optional(txn_part_observable_state['txnResourceStash'])
- if val:
- locker_addr = get_unique_ptr(val["_locker"]) # pylint: disable=undefined-variable
- locker_obj = locker_addr.dereference().cast(
- gdb.lookup_type("mongo::LockerImpl"))
- print('txnResourceStash._locker', "@", locker_addr)
- print("txnResourceStash._locker._id", "=", locker_obj["_id"])
+ if field in get_field_names(txn_part_observable_state):
+ print(field, "=", txn_part_observable_state[field])
else:
- print('txnResourceStash', "=", None)
- # Separate sessions by a newline.
- print("")
+ print("Could not find field '%s' on the TransactionParticipant" % field)
+
+ # The 'txnResourceStash' field is a boost::optional so we unpack it manually if it
+ # is non-empty. We are only interested in its Locker object for now. TODO: Load the
+ # boost pretty printers so the object will be printed clearly by default, without
+ # the need for special unpacking.
+ val = get_boost_optional(txn_part_observable_state['txnResourceStash'])
+ if val:
+ locker_addr = get_unique_ptr(val["_locker"]) # pylint: disable=undefined-variable
+ locker_obj = locker_addr.dereference().cast(gdb.lookup_type("mongo::LockerImpl"))
+ print('txnResourceStash._locker', "@", locker_addr)
+ print("txnResourceStash._locker._id", "=", locker_obj["_id"])
+ else:
+ print('txnResourceStash', "=", None)
+ print("")
# Register command
@@ -536,39 +561,51 @@ class MongoDBDumpRecoveryUnits(gdb.Command):
# Dump stashed recovery unit info for each session in a mongod process
for session_kv in get_session_kv_pairs():
- session_runtime_info = get_unique_ptr(session_kv["second"]).dereference() # pylint: disable=undefined-variable
- session = session_runtime_info["session"]
+ # The Session objects are stored inside the SessionRuntimeInfo object.
+ session_runtime_info = get_unique_ptr(session_kv['second']).dereference() # pylint: disable=undefined-variable
+ parent_session = session_runtime_info['parentSession']
+ child_sessions = absl_get_nodes(session_runtime_info['childSessions']) # pylint: disable=undefined-variable
- # Prepare structured output doc
- session_lsid = str(session["_sessionId"]["_id"])[1:-1]
- txn_participant_dec = get_decoration(session, "TransactionParticipant")
- output_doc = {"session": session_lsid, "txnResourceStash": "0x0"}
-
- recovery_unit_handle = None
- recovery_unit = None
- if txn_participant_dec:
- txn_participant_observable_state = txn_participant_dec[1]["_o"]
- txn_resource_stash = get_boost_optional(
- txn_participant_observable_state["txnResourceStash"])
-
- if txn_resource_stash:
- output_doc["txnResourceStash"] = str(txn_resource_stash.address)
- recovery_unit_handle = get_unique_ptr(txn_resource_stash["_recoveryUnit"]) # pylint: disable=undefined-variable
- # By default, cast the recovery unit as "mongo::WiredTigerRecoveryUnit"
- recovery_unit = recovery_unit_handle.dereference().cast(
- gdb.lookup_type(recovery_unit_impl_type))
-
- output_doc["recoveryUnit"] = hex(recovery_unit_handle) if recovery_unit else "0x0"
- wt_session = get_wt_session(recovery_unit, recovery_unit_impl_type)
- if wt_session:
- output_doc["WT_SESSION"] = hex(wt_session)
- print(json.dumps(output_doc))
- if recovery_unit:
- print(recovery_unit)
+ MongoDBDumpRecoveryUnits.dump_session(parent_session, recovery_unit_impl_type)
+ for child_session_kv in child_sessions:
+ child_session = child_session_kv['second']
+ MongoDBDumpRecoveryUnits.dump_session(child_session, recovery_unit_impl_type)
if enabled_at_start:
gdb.execute("set print static-members on")
+ @staticmethod
+ def dump_session(session, recovery_unit_impl_type):
+ """Dump the session."""
+
+ # Prepare structured output doc
+ lsid = session["_sessionId"]
+ output_doc = {"session": str(lsid["_id"])[1:-1], "txnResourceStash": "0x0"}
+ txn_participant_dec = get_decoration(session, "TransactionParticipant")
+ recovery_unit_handle = None
+ recovery_unit = None
+
+ if txn_participant_dec:
+ txn_participant_observable_state = txn_participant_dec[1]["_o"]
+ txn_resource_stash = get_boost_optional(
+ txn_participant_observable_state["txnResourceStash"])
+ if txn_resource_stash:
+ output_doc["txnResourceStash"] = str(txn_resource_stash.address)
+ recovery_unit_handle = get_unique_ptr(txn_resource_stash["_recoveryUnit"]) # pylint: disable=undefined-variable
+ # By default, cast the recovery unit as "mongo::WiredTigerRecoveryUnit"
+ recovery_unit = recovery_unit_handle.dereference().cast(
+ gdb.lookup_type(recovery_unit_impl_type))
+
+ output_doc["recoveryUnit"] = hex(recovery_unit_handle) if recovery_unit else "0x0"
+ wt_session = get_wt_session(recovery_unit, recovery_unit_impl_type)
+ if wt_session:
+ output_doc["WT_SESSION"] = hex(wt_session)
+
+ print(json.dumps(output_doc))
+ print(lsid)
+ if recovery_unit:
+ print(recovery_unit)
+
# Register command
MongoDBDumpRecoveryUnits()