summaryrefslogtreecommitdiff
path: root/jstests/disk/repair_unfinished_indexes.js
blob: 0f2a84fc68ab24c4c39884412a84f1a3f9495a30 (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
87
88
89
90
91
92
93
94
95
/**
 * This test shuts down a replica set during a two-phase index build. The test corrupts a WiredTiger
 * collection file and expects that --repair salvages the data and drops the unfinished index.
 *
 * @tags: [requires_wiredtiger, requires_replication]
 */

(function() {

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

const dbName = "repair_unfinished_indexes";
const collName = "test";

const replSet = new ReplSetTest({nodes: 2});
replSet.startSet();
replSet.initiate();

const primary = replSet.getPrimary();
const primaryDB = primary.getDB(dbName);

const secondary = replSet.getSecondary();
const secondaryDB = secondary.getDB(dbName);
const secondaryPort = secondary.port;
const secondaryDbpath = secondary.dbpath;

const primaryColl = primaryDB.getCollection(collName);

assert.commandWorked(primaryColl.insert({_id: 0, a: 1}));

jsTestLog("Starting index build on primary and pausing before completion");
IndexBuildTest.pauseIndexBuilds(primary);
const createIdx = IndexBuildTest.startIndexBuild(primary, primaryColl.getFullName(), {a: 1});

jsTestLog("Waiting for secondary to start the index build");
IndexBuildTest.waitForIndexBuildToStart(secondaryDB);

const secondaryCollUri = getUriForColl(secondaryDB[collName]);
replSet.stop(secondary);

// Confirm that the secondary node leaves the index as unfinished.
(function startAsStandalone() {
    jsTestLog("Starting secondary as standalone");
    const mongod = startMongodOnExistingPath(
        secondaryDbpath,
        // This parameter ensures that when the standalone starts up, it applies all unapplied oplog
        // entries since the last shutdown. This "smooths out" a race condition in this test where
        // the secondary can shut down without fully applying the 'startIndexBuild' oplog entry, and
        // not advancing the stable timestamp to the top of the oplog.
        {setParameter: 'recoverFromOplogAsStandalone=true'});
    IndexBuildTest.assertIndexes(mongod.getDB(dbName).getCollection(collName),
                                 2,
                                 ["_id_"],
                                 ["a_1"],
                                 {includeBuildUUIDs: true});
    MongoRunner.stopMongod(mongod);
})();

const exitCode = createIdx({checkExitSuccess: false});
assert.neq(0, exitCode, 'expected shell to exit abnormally due to shutdown');

const secondaryCollFile = secondaryDbpath + "/" + secondaryCollUri + ".wt";
jsTestLog("Corrupting secondary collection file: " + secondaryCollFile);
corruptFile(secondaryCollFile);
assertRepairSucceeds(secondaryDbpath, secondaryPort);

// Importantly, confirm that the secondary node dropped the unfinished index.
(function startAsStandaloneAfterRepair() {
    jsTestLog("Starting secondary as standalone after repair");
    const mongod = startMongodOnExistingPath(secondaryDbpath);
    IndexBuildTest.assertIndexes(
        mongod.getDB(dbName).getCollection(collName), 1, ["_id_"], [], {includeBuildUUIDs: true});
    MongoRunner.stopMongod(mongod);
})();

// The secondary may not be reintroduced because data was modified.
assertErrorOnStartupWhenStartingAsReplSet(
    secondaryDbpath, secondaryPort, replSet.getReplSetConfig()._id);

(function reSyncSecondary() {
    jsTestLog("Wiping dbpath and re-syncing secondary");
    const newSecondary = assertStartInReplSet(
        replSet, secondary, true /* cleanData */, true /* expectResync */, function(node) {});

    IndexBuildTest.resumeIndexBuilds(primary);
    IndexBuildTest.waitForIndexBuildToStop(primaryDB);
    replSet.awaitReplication();
    IndexBuildTest.assertIndexes(primaryColl, 2, ["_id_", "a_1"]);
    IndexBuildTest.assertIndexes(
        newSecondary.getDB(dbName).getCollection(collName), 2, ["_id_", "a_1"]);
})();

replSet.stopSet();
})();