diff options
5 files changed, 81 insertions, 3 deletions
diff --git a/src/mongo/db/storage/devnull/devnull_kv_engine.cpp b/src/mongo/db/storage/devnull/devnull_kv_engine.cpp index 311b77896fa..7d2b0e1f9ae 100644 --- a/src/mongo/db/storage/devnull/devnull_kv_engine.cpp +++ b/src/mongo/db/storage/devnull/devnull_kv_engine.cpp @@ -237,6 +237,9 @@ public: return true; } + virtual void printIndexEntryMetadata(OperationContext* opCtx, + const KeyString::Value& keyString) const {} + virtual std::unique_ptr<SortedDataInterface::Cursor> newCursor(OperationContext* opCtx, bool isForward) const { return {}; diff --git a/src/mongo/db/storage/sorted_data_interface.h b/src/mongo/db/storage/sorted_data_interface.h index 514c8be2f56..088d0ae4424 100644 --- a/src/mongo/db/storage/sorted_data_interface.h +++ b/src/mongo/db/storage/sorted_data_interface.h @@ -168,6 +168,12 @@ public: virtual bool isEmpty(OperationContext* opCtx) = 0; /** + * Prints any storage engine provided metadata for the index entry with key 'keyString'. + */ + virtual void printIndexEntryMetadata(OperationContext* opCtx, + const KeyString::Value& keyString) const = 0; + + /** * Return the number of entries in 'this' index. * * The default implementation should be overridden with a more diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp index d077bbe7984..5ef6d9ef85d 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp @@ -438,6 +438,74 @@ bool WiredTigerIndex::isEmpty(OperationContext* opCtx) { return false; } +void WiredTigerIndex::printIndexEntryMetadata(OperationContext* opCtx, + const KeyString::Value& keyString) const { + // Printing the index entry metadata requires a new session. We cannot open other cursors when + // there are open history store cursors in the session. We also need to make sure that the + // existing session has not written data to avoid potential deadlocks. + invariant(!opCtx->lockState()->inAWriteUnitOfWork()); + WiredTigerSession session(WiredTigerRecoveryUnit::get(opCtx)->getSessionCache()->conn()); + + // Per the version cursor API: + // - A version cursor can only be called with the read timestamp as the oldest timestamp. + // - If there is no oldest timestamp, the version cursor can only be called with a read + // timestamp of 1. + // - If there is an oldest timestamp, reading at timestamp 1 will get rounded up. + const std::string config = "read_timestamp=1,roundup_timestamps=(read=true)"; + WiredTigerBeginTxnBlock beginTxn(session.getSession(), config.c_str()); + + // Open a version cursor. This is a debug cursor that enables iteration through the history of + // values for a given index entry. + WT_CURSOR* cursor = session.getNewCursor(_uri, "debug=(dump_version=true)"); + + const WiredTigerItem searchKey(keyString.getBuffer(), keyString.getSize()); + cursor->set_key(cursor, searchKey.Get()); + + int ret = cursor->search(cursor); + while (ret != WT_NOTFOUND) { + invariantWTOK(ret, cursor->session); + + uint64_t startTs = 0, startDurableTs = 0, stopTs = 0, stopDurableTs = 0; + uint64_t startTxnId = 0, stopTxnId = 0; + uint8_t flags = 0, location = 0, prepare = 0, type = 0; + WT_ITEM value; + + invariantWTOK(cursor->get_value(cursor, + &startTxnId, + &startTs, + &startDurableTs, + &stopTxnId, + &stopTs, + &stopDurableTs, + &type, + &prepare, + &flags, + &location, + &value), + cursor->session); + + auto indexKey = KeyString::toBson( + keyString.getBuffer(), keyString.getSize(), _ordering, keyString.getTypeBits()); + + LOGV2(6601200, + "WiredTiger index entry metadata", + "keyString"_attr = keyString, + "indexKey"_attr = indexKey, + "startTxnId"_attr = startTxnId, + "startTs"_attr = Timestamp(startTs), + "startDurableTs"_attr = Timestamp(startDurableTs), + "stopTxnId"_attr = stopTxnId, + "stopTs"_attr = Timestamp(stopTs), + "stopDurableTs"_attr = Timestamp(stopDurableTs), + "type"_attr = type, + "prepare"_attr = prepare, + "flags"_attr = flags, + "location"_attr = location); + + ret = cursor->next(cursor); + } +} + long long WiredTigerIndex::getSpaceUsedBytes(OperationContext* opCtx) const { dassert(opCtx->lockState()->isReadLocked()); auto ru = WiredTigerRecoveryUnit::get(opCtx); diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_index.h b/src/mongo/db/storage/wiredtiger/wiredtiger_index.h index daf234f9ff7..9586c9fd6e0 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_index.h +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_index.h @@ -155,6 +155,9 @@ public: virtual Status initAsEmpty(OperationContext* opCtx); + virtual void printIndexEntryMetadata(OperationContext* opCtx, + const KeyString::Value& keyString) const; + Status compact(OperationContext* opCtx) override; const std::string& uri() const { diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp index 5414cdf6381..a0f6dad7597 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp @@ -1638,8 +1638,6 @@ StatusWith<RecordData> WiredTigerRecordStore::doUpdateWithDamages( void WiredTigerRecordStore::printRecordMetadata(OperationContext* opCtx, const RecordId& recordId) const { - LOGV2(6120300, "Printing record metadata", "recordId"_attr = recordId); - // Printing the record metadata requires a new session. We cannot open other cursors when there // are open history store cursors in the session. WiredTigerSession session(_kvEngine->getConnection()); @@ -1684,7 +1682,7 @@ void WiredTigerRecordStore::printRecordMetadata(OperationContext* opCtx, cursor->session); RecordData recordData(static_cast<const char*>(value.data), value.size); - LOGV2(6120301, + LOGV2(6120300, "WiredTiger record metadata", "recordId"_attr = recordId, "startTxnId"_attr = startTxnId, |