diff options
author | Eric Milkie <milkie@10gen.com> | 2012-05-07 12:47:56 -0400 |
---|---|---|
committer | Eric Milkie <milkie@10gen.com> | 2012-05-10 11:56:44 -0400 |
commit | 1aaac5eb0dc31c80f82080c9b3e75b49409b74cd (patch) | |
tree | 23ee34f64e8edc5425ef882a22a4123edec7a9fd | |
parent | dd21525b0210951619935e0c8964158c12cfe70f (diff) | |
download | mongo-1aaac5eb0dc31c80f82080c9b3e75b49409b74cd.tar.gz |
SERVER-5706 if only slaveDelay'd nodes are available, use them
SERVER-4750 prevent syncing to secondaries with a slavedelay greater than yourself
Conflicts:
db/repl/rs_initialsync.cpp
jstests/replsets/slavedelay3.js
-rw-r--r-- | db/repl/rs_initialsync.cpp | 33 | ||||
-rw-r--r-- | jstests/replsets/slavedelay3.js | 38 |
2 files changed, 62 insertions, 9 deletions
diff --git a/db/repl/rs_initialsync.cpp b/db/repl/rs_initialsync.cpp index 112d7396bc5..1677bfc38c6 100644 --- a/db/repl/rs_initialsync.cpp +++ b/db/repl/rs_initialsync.cpp @@ -80,7 +80,7 @@ namespace mongo { } const Member* ReplSetImpl::getMemberToSyncTo() { - Member *closest = 0; + bool buildIndexes = true; // wait for 2N pings before choosing a sync target @@ -95,16 +95,31 @@ namespace mongo { buildIndexes = myConfig().buildIndexes; } + Member *closest = 0; + // find the member with the lowest ping time that has more data than me - for (Member *m = _members.head(); m; m = m->next()) { - if (m->hbinfo().up() && - // make sure members with buildIndexes sync from other members w/indexes - (!buildIndexes || (buildIndexes && m->config().buildIndexes)) && - (m->state() == MemberState::RS_PRIMARY || - (m->state() == MemberState::RS_SECONDARY && m->hbinfo().opTime > lastOpTimeWritten)) && - (!closest || m->hbinfo().ping < closest->hbinfo().ping)) { - closest = m; + + // Make two attempts. The first attempt, we ignore those nodes with + // slave delay higher than our own. The second attempt includes such + // nodes, in case those are the only ones we can reach. + for (int attempts = 0; attempts < 2; ++attempts) { + for (Member *m = _members.head(); m; m = m->next()) { + if (m->hbinfo().up() && + // make sure members with buildIndexes sync from other members w/indexes + (!buildIndexes || (buildIndexes && m->config().buildIndexes)) && + (m->state() == MemberState::RS_PRIMARY || + (m->state() == MemberState::RS_SECONDARY && + m->hbinfo().opTime > lastOpTimeWritten)) && + (!closest || m->hbinfo().ping < closest->hbinfo().ping)) { + + if ( attempts == 0 && + myConfig().slaveDelay < m->config().slaveDelay ) { + break; // skip this one in the first attempt + } + closest = m; + } } + if (closest) break; // no need for second attempt } { diff --git a/jstests/replsets/slavedelay3.js b/jstests/replsets/slavedelay3.js new file mode 100644 index 00000000000..e89fe965f46 --- /dev/null +++ b/jstests/replsets/slavedelay3.js @@ -0,0 +1,38 @@ +load("jstests/replsets/rslib.js"); + +var name = 'slavedelay3'; +var replTest = new ReplSetTest({ name: name, nodes: 3 }); +var nodes = replTest.startSet(); +var config = replTest.getReplSetConfig(); +// ensure member 0 is primary +config.members[0].priority = 2; +config.members[1].priority = 0; +config.members[1].slaveDelay = 5; + +replTest.initiate(config); +replTest.awaitReplication(); +replTest.bridge(); + + +var master = replTest.getMaster().getDB(name); + var slaveConns = replTest.liveNodes.slaves; + var slave = []; + for (var i in slaveConns) { + var d = slaveConns[i].getDB(name); + d.getMongo().setSlaveOk(); + slave.push(d); + } + +waitForAllMembers(master); + + + +replTest.partition(0,2); +replTest.awaitReplication(); + +master.foo.insert({x:1}); + +// make sure the record still appears in the remote slave +assert.soon( function() { return slave[1].foo.findOne() != null; } ); + +replTest.stopSet();
\ No newline at end of file |