From b67407b986ea715b0b9948c64a90369809ff6da0 Mon Sep 17 00:00:00 2001 From: Gregory Noma Date: Thu, 22 Apr 2021 13:45:25 -0400 Subject: SERVER-52833 Perform capped deletes during startup recovery on documents inserted earlier in startup recovery --- .../capped_deletes_within_rollback.js | 38 ++++++++++++++++++ .../capped_deletes_within_startup_recovery.js | 45 ++++++++++++++++++++++ src/mongo/db/server_recovery.h | 3 +- .../storage/wiredtiger/wiredtiger_record_store.cpp | 9 +++++ 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 jstests/noPassthrough/capped_deletes_within_rollback.js create mode 100644 jstests/noPassthrough/capped_deletes_within_startup_recovery.js diff --git a/jstests/noPassthrough/capped_deletes_within_rollback.js b/jstests/noPassthrough/capped_deletes_within_rollback.js new file mode 100644 index 00000000000..8ba6a13e1f7 --- /dev/null +++ b/jstests/noPassthrough/capped_deletes_within_rollback.js @@ -0,0 +1,38 @@ +/** + * Tests that capped deletes occur during rollback on documents inserted earlier in rollback. + * + * @tags: [ + * requires_replication, + * ] + */ +(function() { +'use strict'; + +load('jstests/replsets/libs/rollback_test.js'); + +const rollbackTest = new RollbackTest(jsTestName()); + +const testDB = function() { + return rollbackTest.getPrimary().getDB('test'); +}; + +const coll = function() { + return testDB().getCollection(jsTestName()); +}; + +assert.commandWorked( + testDB().createCollection(coll().getName(), {capped: true, size: 100, max: 1})); +assert.commandWorked(coll().insert({a: 1})); + +rollbackTest.transitionToRollbackOperations(); +rollbackTest.transitionToSyncSourceOperationsBeforeRollback(); + +assert.commandWorked(coll().insert([{b: 1}, {b: 2}])); + +rollbackTest.transitionToSyncSourceOperationsDuringRollback(); +rollbackTest.transitionToSteadyStateOperations(); + +assert.eq(coll().find().itcount(), 1); + +rollbackTest.stop(); +})(); \ No newline at end of file diff --git a/jstests/noPassthrough/capped_deletes_within_startup_recovery.js b/jstests/noPassthrough/capped_deletes_within_startup_recovery.js new file mode 100644 index 00000000000..527d9bb0d76 --- /dev/null +++ b/jstests/noPassthrough/capped_deletes_within_startup_recovery.js @@ -0,0 +1,45 @@ +/** + * Tests that capped deletes occur during statup recovery on documents inserted earlier in startup + * recovery. + * + * @tags: [ + * requires_persistence, + * requires_replication, + * ] + */ +(function() { +'use strict'; + +load('jstests/libs/fail_point_util.js'); + +const replTest = new ReplSetTest({nodes: 1}); +replTest.startSet(); +replTest.initiate(); + +const primary = function() { + return replTest.getPrimary(); +}; + +const testDB = function() { + return primary().getDB('test'); +}; + +const coll = function() { + return testDB().getCollection(jsTestName()); +}; + +assert.commandWorked( + testDB().createCollection(coll().getName(), {capped: true, size: 100, max: 1})); + +const ts = + assert.commandWorked(testDB().runCommand({insert: coll().getName(), documents: [{a: 1}]})) + .operationTime; +configureFailPoint(primary(), 'holdStableTimestampAtSpecificTimestamp', {timestamp: ts}); + +assert.commandWorked(coll().insert([{b: 1}, {b: 2}])); +replTest.restart(primary()); + +assert.eq(coll().find().itcount(), 1); + +replTest.stopSet(); +})(); \ No newline at end of file diff --git a/src/mongo/db/server_recovery.h b/src/mongo/db/server_recovery.h index 3b9d87a8065..e78653d768a 100644 --- a/src/mongo/db/server_recovery.h +++ b/src/mongo/db/server_recovery.h @@ -34,6 +34,7 @@ #include "mongo/db/service_context.h" #include "mongo/platform/mutex.h" +#include "mongo/util/string_map.h" namespace mongo { /** @@ -82,7 +83,7 @@ public: private: mutable Mutex _mutex = MONGO_MAKE_LATCH("SizeRecoveryState::_mutex"); - std::set _collectionsAlwaysNeedingSizeAdjustment; + StringSet _collectionsAlwaysNeedingSizeAdjustment; }; /** diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp index f5873ff5249..eed04767a6e 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp @@ -1731,6 +1731,15 @@ void WiredTigerRecordStore::_initNextIdIfNeeded(OperationContext* opCtx) { return; } + // During startup recovery, the collectionAlwaysNeedsSizeAdjustment flag is not set by default + // for the sake of efficiency. However, if we reach this point, we may need to set it in order + // to ensure that capped deletes can occur on documents inserted earlier in startup recovery. + if (inReplicationRecovery(getGlobalServiceContext()) && + !sizeRecoveryState(getGlobalServiceContext()) + .collectionAlwaysNeedsSizeAdjustment(getIdent())) { + checkSize(opCtx); + } + // Need to start at 1 so we are always higher than RecordId::min() int64_t nextId = 1; -- cgit v1.2.1