summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Milkie <milkie@10gen.com>2012-05-07 12:47:56 -0400
committerEric Milkie <milkie@10gen.com>2012-05-10 11:56:44 -0400
commit1aaac5eb0dc31c80f82080c9b3e75b49409b74cd (patch)
tree23ee34f64e8edc5425ef882a22a4123edec7a9fd
parentdd21525b0210951619935e0c8964158c12cfe70f (diff)
downloadmongo-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.cpp33
-rw-r--r--jstests/replsets/slavedelay3.js38
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