summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Noma <gregory.noma@gmail.com>2021-04-22 13:45:25 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-04-22 18:26:28 +0000
commitb67407b986ea715b0b9948c64a90369809ff6da0 (patch)
tree22bc6365d08d1ef54f0c5ef4a1de2c6c9b8aa084
parentabc2b21e0d47c527c00df30fcf322ff01699877d (diff)
downloadmongo-b67407b986ea715b0b9948c64a90369809ff6da0.tar.gz
SERVER-52833 Perform capped deletes during startup recovery on documents inserted earlier in startup recovery
-rw-r--r--jstests/noPassthrough/capped_deletes_within_rollback.js38
-rw-r--r--jstests/noPassthrough/capped_deletes_within_startup_recovery.js45
-rw-r--r--src/mongo/db/server_recovery.h3
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp9
4 files changed, 94 insertions, 1 deletions
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<std::string> _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;