summaryrefslogtreecommitdiff
path: root/jstests/disk/wt_repair_orphaned_idents.js
blob: 83d3bfee424730934f75ea1248e291cb62884510 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/**
 * Tests that --repair on WiredTiger creates new entries for orphaned idents in the catalog.
 *
 * @tags: [requires_wiredtiger]
 */

(function() {

load('jstests/disk/libs/wt_file_helper.js');

const baseName = "wt_repair_orphaned_idents";
const dbpath = MongoRunner.dataPath + baseName + "/";

resetDbpath(dbpath);

// Create a collection and insert a doc.
let mongod = MongoRunner.runMongod({dbpath: dbpath});
const importantCollName = "importantColl";
const importantDocId = "importantDoc";
const importantColl = mongod.getDB("test")[importantCollName];
assert.commandWorked(importantColl.insert({_id: importantDocId}));
const importantCollIdent = getUriForColl(importantColl);
MongoRunner.stopMongod(mongod);

// Delete the _mdb_catalog.
let mdbCatalogFile = dbpath + "_mdb_catalog.wt";
jsTestLog("deleting catalog file: " + mdbCatalogFile);
removeFile(mdbCatalogFile);

// Repair crates the _mdb_catalog and catalog entries for all the orphaned idents.
jsTestLog("running mongod with --repair");
assert.eq(0, runMongoProgram("mongod", "--repair", "--port", mongod.port, "--dbpath", dbpath));

jsTestLog("restarting mongod");
mongod = MongoRunner.runMongod({dbpath: dbpath, noCleanData: true});

let localDb = mongod.getDB("local");
let res = localDb.runCommand({listCollections: 1});
assert.commandWorked(res, tojson(res));

// This is the function that 'show collections' uses.
let collNames = localDb.getCollectionNames();

const orphanPrefix = "orphan.";
let recoveredCount = 0;
const orphanedImportantCollName = "orphan." + importantCollIdent.replace(/-/g, "_");
for (let collName of collNames) {
    if (collName.startsWith(orphanPrefix)) {
        // Manually create the _id index.
        assert.commandWorked(localDb[collName].createIndex({_id: 1}));

        if (collName == orphanedImportantCollName) {
            assert.commandWorked(localDb.adminCommand(
                {renameCollection: "local." + collName, to: "test." + importantCollName}));
        } else {
            assert.commandWorked(localDb.adminCommand(
                {renameCollection: "local." + collName, to: "test.recovered" + recoveredCount}));
        }
        recoveredCount++;
    }
}
assert.gt(recoveredCount, 0);

let testDb = mongod.getDB("test");

// Assert the recovered collection still has the original document.
assert.eq(testDb[importantCollName].find({_id: importantDocId}).count(), 1);

res = testDb.runCommand({listCollections: 1});
assert.commandWorked(res);
assert.eq(res.cursor.firstBatch.length, recoveredCount);
for (let entry of res.cursor.firstBatch) {
    let collName = entry.name;
    assert(collName.startsWith("recovered") || collName == importantCollName);

    // Assert _id index has been successfully created.
    assert("idIndex" in entry);

    // Make sure we can interact with the recovered collections.
    assert.commandWorked(testDb.runCommand({find: collName}));
    assert.commandWorked(testDb[collName].insert({x: 1}));
    assert(testDb[collName].drop());
}

MongoRunner.stopMongod(mongod);
})();