diff options
Diffstat (limited to 'jstests/noPassthrough/libs/missing_index_ident.js')
| -rw-r--r-- | jstests/noPassthrough/libs/missing_index_ident.js | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/jstests/noPassthrough/libs/missing_index_ident.js b/jstests/noPassthrough/libs/missing_index_ident.js new file mode 100644 index 00000000000..1c7e7dc2782 --- /dev/null +++ b/jstests/noPassthrough/libs/missing_index_ident.js @@ -0,0 +1,93 @@ +load('jstests/libs/fail_point_util.js'); +load('jstests/noPassthrough/libs/index_build.js'); + +const MissingIndexIdent = class { + /** + * Starts a one-node replica set and gets it into a state where the catalog entry for index + * 'a_1' references an ident which is missing. Returns with the node stopped. + */ + static run() { + 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()[jsTestName()]; + }; + + assert.commandWorked(coll().insert({a: 0})); + + const fp = configureFailPoint(primary(), 'hangIndexBuildBeforeCommit'); + const awaitCreateIndex = + IndexBuildTest.startIndexBuild(primary(), coll().getFullName(), {a: 1}); + fp.wait(); + + // Get a timestamp before the commit timestamp of the index build. + const ts = + assert + .commandWorked(testDB().runCommand({insert: coll().getName(), documents: [{a: 1}]})) + .operationTime; + + configureFailPoint(primary(), 'holdStableTimestampAtSpecificTimestamp', {timestamp: ts}); + fp.off(); + awaitCreateIndex(); + + const ident = assert.commandWorked(testDB().runCommand({collStats: coll().getName()})) + .indexDetails.a_1.uri.substring('statistics:table:'.length); + + replTest.restart(primary(), { + setParameter: { + // Set minSnapshotHistoryWindowInSeconds to 0 so that the the oldest timestamp can + // move forward, despite the stable timestamp being held steady. + minSnapshotHistoryWindowInSeconds: 0, + 'failpoint.holdStableTimestampAtSpecificTimestamp': + tojson({mode: 'alwaysOn', data: {timestamp: ts}}) + } + }); + + MissingIndexIdent.checkRecoveryLogs(primary(), coll(), ts, ident); + + const dbpath = primary().dbpath; + + // Shut down uncleanly so that a checkpoint is not taken. This will cause the index catalog + // entry referencing the now-dropped ident to still be present. + replTest.stop(0, 9, {allowedExitCode: MongoRunner.EXIT_SIGKILL}, {forRestart: true}); + + return {replTest, dbpath, ts, ident}; + } + + /** + * Checks that the index was recovered. + */ + static checkRecoveryLogs(conn, coll, ts, ident) { + // On startup, the node will recover from before the index commit timestamp. + checkLog.containsJson(conn, 23987, { + recoveryTimestamp: (recoveryTs) => { + return timestampCmp( + Timestamp(recoveryTs['$timestamp']['t'], recoveryTs['$timestamp']['i']), + ts) <= 0; + } + }); + + // Since the index build was not yet completed at the recovery timestamp, its ident will + // be dropped. + checkLog.containsJson(conn, 22206, { + index: 'a_1', + namespace: coll.getFullName(), + ident: ident, + commitTimestamp: {$timestamp: {t: 0, i: 0}}, + }); + + // The oldest timestamp moving forward will cause the ident reaper to drop the ident. + checkLog.containsJson(conn, 22237, { + ident: ident, + dropTimestamp: {$timestamp: {t: 0, i: 0}}, + }); + } +}; |
