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
96
97
98
|
/**
* Test that initial sync does not fail if an identical index spec is created, dropped and
* recreated.
*/
(function() {
"use strict";
load("jstests/libs/fail_point_util.js"); // for kDefaultWaitForFailPointTimeout
const testName = "initial_sync_same_index_spec";
const dbName = testName;
const collName = "testcoll";
// Set up a stable two node replica set.
let replTest = new ReplSetTest({
name: testName,
nodes: [{}, {rsConfig: {priority: 0, votes: 0}}],
});
replTest.startSet();
replTest.initiateWithHighElectionTimeout();
let primary = replTest.getPrimary();
let secondary = replTest.getSecondary();
let primaryDB = primary.getDB(dbName);
let secondaryDB = secondary.getDB(dbName);
let primaryColl = primaryDB[collName];
let secondaryColl = secondaryDB[collName];
// Insert data into the collection for initial sync to copy.
assert.commandWorked(primaryColl.insert([{_id: 1, a: 1}, {_id: 2, a: 2}]));
// Set WC to 1. The default WC is majority and the replica set will not be able to satisfy majority
// index create/drop later.
assert.commandWorked(primary.adminCommand(
{setDefaultRWConcern: 1, defaultWriteConcern: {w: 1}, writeConcern: {w: "majority"}}));
/**
* Restart the the secondary with no data in order to provoke an initial sync from the primary.
* Use startup setParameter to set failpoints to pause the initial sync before indexes are fetched.
*/
const fp = 'hangBeforeClonerStage';
let secondaryStartupParams = {};
secondaryStartupParams['failpoint.' + fp] = tojson({
mode: 'alwaysOn',
data: {cloner: "CollectionCloner", stage: "listIndexes", nss: primaryColl.getFullName()}
});
// Only try initial sync once, so any failure syncing indexes will be surfaced.
secondaryStartupParams['numInitialSyncAttempts'] = 1;
const startupOptions = {
startClean: true,
setParameter: secondaryStartupParams
};
jsTestLog(
"Restarting the the secondary with no data in order to provoke an initial sync from the " +
"primary. Using startup options: " + tojson(startupOptions));
secondary = replTest.restart(secondary, startupOptions);
secondaryDB = secondary.getDB(dbName);
secondaryColl = secondaryDB[collName];
jsTestLog("Waiting for secondary to reach failPoint '" + fp + "'");
assert.commandWorked(secondary.adminCommand(
{waitForFailPoint: fp, timesEntered: 1, maxTimeMS: kDefaultWaitForFailPointTimeout}));
// Restarting the secondary may have resulted in an election. Wait until the system stabilizes and
// reaches RS_STARTUP2 state.
replTest.getPrimary();
replTest.waitForState(secondary, ReplSetTest.State.STARTUP_2);
/**
* Now that the secondary is hanging in initial sync, create, drop and recreate identical indexes to
* ensure it is correctly handled by initial sync (when the failpoint is removed).
*/
jsTestLog("Creating index on the primary.");
assert.commandWorked(primaryColl.createIndex({a: 1}, {name: "a1"}));
jsTestLog("Dropping index on the primary.");
assert.commandWorked(primaryColl.dropIndex("a1"));
jsTestLog("Recreating index with same spec on the primary.");
assert.commandWorked(primaryColl.createIndex({a: 1}, {name: "a2"}));
jsTestLog("Allowing secondary initial sync to resume.");
assert.commandWorked(
secondary.adminCommand({configureFailPoint: "hangBeforeClonerStage", mode: 'off'}));
jsTestLog("Waiting for initial sync to complete successfully.");
replTest.waitForState(secondary, ReplSetTest.State.SECONDARY);
replTest.stopSet();
})();
|