diff options
Diffstat (limited to 'jstests/disk/repair_clustered_collection.js')
| -rw-r--r-- | jstests/disk/repair_clustered_collection.js | 87 |
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); +})(); |
