summaryrefslogtreecommitdiff
path: root/jstests/disk/repair_clustered_collection.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/disk/repair_clustered_collection.js')
-rw-r--r--jstests/disk/repair_clustered_collection.js87
1 files changed, 87 insertions, 0 deletions
diff --git a/jstests/disk/repair_clustered_collection.js b/jstests/disk/repair_clustered_collection.js
new file mode 100644
index 00000000000..001ac2dbeb2
--- /dev/null
+++ b/jstests/disk/repair_clustered_collection.js
@@ -0,0 +1,87 @@
+/**
+ * Tests that --repair on WiredTiger correctly and gracefully handles a missing _mdb_catalog when
+ * a clustered collection exists on the server instance.
+ *
+ * @tags: [requires_wiredtiger]
+ */
+(function() {
+
+load('jstests/disk/libs/wt_file_helper.js');
+load("jstests/libs/collection_drop_recreate.js");
+
+const dbName = jsTestName();
+const collName = "test";
+const dbpath = MongoRunner.dataPath + dbName + "/";
+
+const runRepairTest = function runRepairTestOnMongoDInstance(
+ collectionOptions, docToInsert, isTimeseries) {
+ let mongod = startMongodOnExistingPath(dbpath);
+ let db = mongod.getDB(dbName);
+
+ assertDropCollection(db, collName);
+ assertCreateCollection(db, collName, collectionOptions);
+
+ let testColl = db[collName];
+ let testCollUri = getUriForColl(testColl);
+ let testCollFile = dbpath + testCollUri + ".wt";
+
+ assert.commandWorked(testColl.insert(docToInsert));
+
+ // A document repaired from a timeseries collection will be in a different format than the
+ // original document. This is because the timeseries's system.views collection will be not be
+ // associated with the orphaned clustered collection. Thus, the data will show up as it would
+ // have in the raw system.buckets collection for the timeseries collection.
+ const expectedOrphanDoc =
+ isTimeseries ? db["system.buckets." + collName].findOne() : testColl.findOne();
+
+ MongoRunner.stopMongod(mongod);
+
+ // Delete the _mdb_catalog.
+ let mdbCatalogFile = dbpath + "_mdb_catalog.wt";
+ jsTestLog("deleting catalog file: " + mdbCatalogFile);
+ removeFile(mdbCatalogFile);
+
+ assertRepairSucceeds(dbpath, mongod.port);
+
+ // Verify that repair succeeds in creating an empty catalog and MongoDB starts up normally with
+ // no data.
+ mongod = startMongodOnExistingPath(dbpath);
+ db = mongod.getDB(dbName);
+ testColl = db[collName];
+ assert.isnull(testColl.exists());
+ assert.eq(testColl.find(docToInsert).itcount(), 0);
+ assert.eq(testColl.count(), 0);
+
+ // Ensure the orphaned collection is valid and the document is preserved.
+ const orphanedImportantCollName = "orphan." + testCollUri.replace(/-/g, "_");
+ const localDb = mongod.getDB("local");
+ orphanedCollection = localDb[orphanedImportantCollName];
+ assert(orphanedCollection.exists());
+ assert.eq(orphanedCollection.count(expectedOrphanDoc),
+ 1,
+ `Expected to find document ${tojson(expectedOrphanDoc)} but collection has contents ${
+ tojson(orphanedCollection.find().toArray())}`);
+
+ const validateResult = orphanedCollection.validate();
+ assert(validateResult.valid);
+ MongoRunner.stopMongod(mongod);
+};
+
+// Standard clustered collection test.
+let isTimeseries = false;
+let clusteredCollOptions = {clusteredIndex: {key: {_id: 1}, unique: true}};
+let docToInsert = {_id: 1};
+runRepairTest(clusteredCollOptions, docToInsert, isTimeseries);
+
+// Timeseries test since all timeseries collections are implicitly clustered.
+isTimeseries = true;
+clusteredCollOptions = {
+ timeseries: {timeField: "timestamp", metaField: "metadata", granularity: "hours"}
+};
+docToInsert = {
+ "metadata": {"sensorId": 5578, "type": "temperature"},
+ "timestamp": ISODate("2021-05-18T00:00:00.000Z"),
+ "temp": 12
+};
+runRepairTest(clusteredCollOptions, docToInsert, isTimeseries);
+})();