Skip to content

Commit

Permalink
SERVER-26599 Master-slave initial sync should use the exact _id index…
Browse files Browse the repository at this point in the history
… spec from master
  • Loading branch information
Tess Avitabile committed Oct 18, 2016
1 parent 7862cc3 commit 5053052
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 7 deletions.
31 changes: 28 additions & 3 deletions jstests/noPassthrough/index_version_autoupgrade.js
Expand Up @@ -42,9 +42,18 @@
testDB.dropDatabase();
var coll = testDB.index_version_autoupgrade;

assert.commandWorked(coll.createIndex({withoutAnyOptions: 1}));
// Create a v=1 _id index. This requires setting featureCompatibilityVersion to 3.2.
assert.commandWorked(conn.adminCommand({setFeatureCompatibilityVersion: "3.2"}));
assert.commandWorked(testDB.createCollection("index_version_autoupgrade"));
assert.commandWorked(conn.adminCommand({setFeatureCompatibilityVersion: "3.4"}));
var allIndexes = coll.getIndexes();
var spec = GetIndexHelpers.findByKeyPattern(allIndexes, {withoutAnyOptions: 1});
var spec = GetIndexHelpers.findByKeyPattern(allIndexes, {_id: 1});
assert.neq(null, spec, "Index with key pattern {_id: 1} not found: " + tojson(allIndexes));
assert.eq(1, spec.v, "Expected a v=1 index to be built: " + tojson(spec));

assert.commandWorked(coll.createIndex({withoutAnyOptions: 1}));
allIndexes = coll.getIndexes();
spec = GetIndexHelpers.findByKeyPattern(allIndexes, {withoutAnyOptions: 1});
assert.neq(
null,
spec,
Expand Down Expand Up @@ -72,21 +81,23 @@

if (doesAutoUpgrade) {
expectedResults = [
{keyPattern: {_id: 1}, version: defaultIndexVersion},
{keyPattern: {withoutAnyOptions: 1}, version: defaultIndexVersion},
{keyPattern: {withV1: 1}, version: defaultIndexVersion},
{keyPattern: {withV2: 1}, version: defaultIndexVersion},
];

} else {
expectedResults = [
{keyPattern: {_id: 1}, version: 1},
{keyPattern: {withoutAnyOptions: 1}, version: defaultIndexVersion},
{keyPattern: {withV1: 1}, version: 1},
{keyPattern: {withV2: 1}, version: 2},
];
}

expectedResults.forEach(function(expected) {
var allIndexes = coll.getIndexes();
var allIndexes = collToVerify.getIndexes();
var spec = GetIndexHelpers.findByKeyPattern(allIndexes, expected.keyPattern);
assert.neq(null,
spec,
Expand Down Expand Up @@ -151,5 +162,19 @@
}, false);
MongoRunner.stopMongod(cloneConn);

// Test that the "clone" command doesn't upgrade existing indexes to the latest version.
cloneConn = MongoRunner.runMongod({});
assert.neq(null, cloneConn, "mongod was unable to start up");
assert.eq("3.4", getFeatureCompatibilityVersion(cloneConn));
testIndexVersionAutoUpgrades(function(coll) {
var cloneDB = cloneConn.getDB(coll.getDB().getName());
assert.commandWorked(cloneDB.runCommand({
clone: conn.host,
fromDB: coll.getDB().getName(),
}));
return cloneDB[coll.getName()];
}, false);
MongoRunner.stopMongod(cloneConn);

MongoRunner.stopMongod(conn);
})();
46 changes: 46 additions & 0 deletions jstests/repl/initial_sync_id_index.js
@@ -0,0 +1,46 @@
// Tests that the _id index spec is copied exactly during initial sync.
(function() {
"use strict";

load("jstests/libs/get_index_helpers.js");

const rt = new ReplTest();
const master = rt.start(true);
const masterDB = master.getDB("test");

// Initially, featureCompatibilityVersion is 3.4, so we will create v=2 indexes.
let res = master.adminCommand({getParameter: 1, featureCompatibilityVersion: 1});
assert.commandWorked(res);
assert.eq(res.featureCompatibilityVersion, "3.4");
assert.commandWorked(masterDB.createCollection("collV2"));
let spec = GetIndexHelpers.findByName(masterDB.collV2.getIndexes(), "_id_");
assert.neq(spec, null);
assert.eq(spec.v, 2);

// Set featureCompatibilityVersion to 3.2, so we create v=1 indexes.
assert.commandWorked(master.adminCommand({setFeatureCompatibilityVersion: "3.2"}));
res = master.adminCommand({getParameter: 1, featureCompatibilityVersion: 1});
assert.commandWorked(res);
assert.eq(res.featureCompatibilityVersion, "3.2");
assert.commandWorked(masterDB.createCollection("collV1"));
spec = GetIndexHelpers.findByName(masterDB.collV1.getIndexes(), "_id_");
assert.neq(spec, null);
assert.eq(spec.v, 1);

// Initial sync a slave.
const slave = rt.start(false);
const slaveDB = slave.getDB("test");

// Perform a w=2 write to ensure that slave can be read from, and initial sync is complete.
assert.writeOK(masterDB.coll.insert({}, {writeConcern: {w: 2}}));

// Check _id index versions on slave.
spec = GetIndexHelpers.findByName(slaveDB.collV2.getIndexes(), "_id_");
assert.neq(spec, null);
assert.eq(spec.v, 2);
spec = GetIndexHelpers.findByName(slaveDB.collV1.getIndexes(), "_id_");
assert.neq(spec, null);
assert.eq(spec.v, 1);

rt.stop();
})();
34 changes: 30 additions & 4 deletions src/mongo/db/cloner.cpp
Expand Up @@ -674,10 +674,36 @@ Status Cloner::copyDb(OperationContext* txn,
MultiIndexBlock indexer(txn, c);
indexer.allowInterruption();

const auto featureCompatibilityVersion =
serverGlobalParams.featureCompatibility.version.load();
auto indexInfoObjs = uassertStatusOK(indexer.init(
c->getIndexCatalog()->getDefaultIdIndexSpec(featureCompatibilityVersion)));
BSONObj idIndexSpec;
{
Lock::TempRelease tempRelease(txn->lockState());
auto sourceIndexes = _conn->getIndexSpecs(
from_name.ns(), opts.slaveOk ? QueryOption_SlaveOk : 0);
for (auto&& indexSpec : sourceIndexes) {
if ("_id_"_sd == indexSpec["name"].String()) {
idIndexSpec = indexSpec;
break;
}
}
}

uassert(ErrorCodes::NotMaster,
str::stream() << "Not primary while cloning database " << opts.fromDB
<< " (after getting _id index spec for collection "
<< from_name.ns()
<< ")",
!txn->writesAreReplicated() ||
repl::getGlobalReplicationCoordinator()->canAcceptWritesForDatabase(
toDBName));

uassert(40332,
str::stream() << "_id index spec not found for collection "
<< from_name.ns()
<< " during clone",
!idIndexSpec.isEmpty());

auto indexInfoObjs = uassertStatusOK(
indexer.init(fixIndexSpec(to_name.db().toString(), idIndexSpec)));
invariant(indexInfoObjs.size() == 1);
uassertStatusOK(indexer.insertAllDocumentsInCollection(&dups));

Expand Down

0 comments on commit 5053052

Please sign in to comment.