summaryrefslogtreecommitdiff
path: root/jstests/replsets
diff options
context:
space:
mode:
authorAntonin Kral <a.kral@bobek.cz>2011-09-14 17:08:06 +0200
committerAntonin Kral <a.kral@bobek.cz>2011-09-14 17:08:06 +0200
commit5d342a758c6095b4d30aba0750b54f13b8916f51 (patch)
tree762e9aa84781f5e3b96db2c02d356c29cf0217c0 /jstests/replsets
parentcbe2d992e9cd1ea66af9fa91df006106775d3073 (diff)
downloadmongodb-5d342a758c6095b4d30aba0750b54f13b8916f51.tar.gz
Imported Upstream version 2.0.0
Diffstat (limited to 'jstests/replsets')
-rw-r--r--jstests/replsets/auth1.js35
-rw-r--r--jstests/replsets/cloneDb.js18
-rw-r--r--jstests/replsets/config1.js21
-rwxr-xr-xjstests/replsets/downstream.js36
-rw-r--r--jstests/replsets/fastsync.js151
-rw-r--r--jstests/replsets/initial_sync1.js5
-rw-r--r--jstests/replsets/initial_sync3.js37
-rw-r--r--jstests/replsets/key11
-rw-r--r--jstests/replsets/key21
-rw-r--r--jstests/replsets/maintenance.js32
-rw-r--r--jstests/replsets/majority.js60
-rw-r--r--jstests/replsets/randomcommands1.js29
-rw-r--r--jstests/replsets/reconfig.js69
-rw-r--r--jstests/replsets/remove1.js130
-rw-r--r--jstests/replsets/replset1.js22
-rw-r--r--jstests/replsets/replset3.js2
-rw-r--r--jstests/replsets/replset5.js88
-rw-r--r--jstests/replsets/replsetadd.js34
-rw-r--r--jstests/replsets/replsetarb1.js33
-rw-r--r--jstests/replsets/replsetarb2.js13
-rw-r--r--jstests/replsets/replsetarb3.js144
-rw-r--r--jstests/replsets/replsetfreeze.js4
-rw-r--r--jstests/replsets/replsetrestart1.js14
-rw-r--r--jstests/replsets/replsetrestart2.js8
-rw-r--r--jstests/replsets/rollback2.js19
-rw-r--r--jstests/replsets/rollback4.js117
-rw-r--r--jstests/replsets/rslib.js44
-rw-r--r--jstests/replsets/slavedelay1.js104
-rw-r--r--jstests/replsets/stale_clustered.js101
-rw-r--r--jstests/replsets/stepdown.js142
-rwxr-xr-xjstests/replsets/stepdown2.js139
-rw-r--r--jstests/replsets/sync1.js396
-rw-r--r--jstests/replsets/sync2.js48
-rw-r--r--jstests/replsets/tags.js154
-rw-r--r--jstests/replsets/tags2.js44
-rw-r--r--jstests/replsets/toostale.js34
-rw-r--r--jstests/replsets/twosets.js35
37 files changed, 1660 insertions, 704 deletions
diff --git a/jstests/replsets/auth1.js b/jstests/replsets/auth1.js
index 60e4b95..71ab2d9 100644
--- a/jstests/replsets/auth1.js
+++ b/jstests/replsets/auth1.js
@@ -3,17 +3,27 @@
load("jstests/replsets/rslib.js");
var name = "rs_auth1";
-var port = allocatePorts(4);
-var path = "jstests/replsets/";
+var port = allocatePorts(5);
+var path = "jstests/libs/";
+
+
+print("try starting mongod with auth");
+var m = runMongoProgram( "mongod", "--auth", "--port", port[4], "--dbpath", "/data/db/wrong-auth");
+
+assert.throws(function() {
+ m.getDB("local").auth("__system", "");
+});
+
+stopMongod(port[4]);
+
-
print("reset permissions");
run("chmod", "644", path+"key1");
run("chmod", "644", path+"key2");
print("try starting mongod");
-var m = runMongoProgram( "mongod", "--keyFile", path+"key1", "--port", port[0], "--dbpath", "/data/db/" + name);
+m = runMongoProgram( "mongod", "--keyFile", path+"key1", "--port", port[0], "--dbpath", "/data/db/" + name);
print("should fail with wrong permissions");
@@ -81,6 +91,10 @@ function doQueryOn(p) {
doQueryOn(slave);
master.adminCommand({logout:1});
+
+print("unauthorized:");
+printjson(master.adminCommand({replSetGetStatus : 1}));
+
doQueryOn(master);
@@ -125,11 +139,12 @@ master.auth("bar", "baz");
for (var i=0; i<1000; i++) {
master.foo.insert({x:i, foo : "bar"});
}
-master.runCommand({getlasterror:1, w:3, wtimeout:60000});
+var result = master.runCommand({getlasterror:1, w:2, wtimeout:60000});
+printjson(result);
print("resync");
-rs.restart(0);
+rs.restart(0, {"keyFile" : path+"key1"});
print("add some more data 2");
@@ -159,7 +174,7 @@ master.getSisterDB("admin").auth("foo", "bar");
print("shouldn't ever sync");
-for (var i = 0; i<30; i++) {
+for (var i = 0; i<10; i++) {
print("iteration: " +i);
var results = master.adminCommand({replSetGetStatus:1});
printjson(results);
@@ -177,9 +192,15 @@ conn = new MongodRunner(port[3], "/data/db/"+name+"-3", null, null, ["--replSet"
conn.start();
wait(function() {
+ try {
var results = master.adminCommand({replSetGetStatus:1});
printjson(results);
return results.members[3].state == 2;
+ }
+ catch (e) {
+ print(e);
+ }
+ return false;
});
print("make sure it has the config, too");
diff --git a/jstests/replsets/cloneDb.js b/jstests/replsets/cloneDb.js
index 6d2d0f3..2519c09 100644
--- a/jstests/replsets/cloneDb.js
+++ b/jstests/replsets/cloneDb.js
@@ -6,34 +6,36 @@ doTest = function( signal ) {
var N = 2000
- // ~1KB string
+ print("~1KB string");
var Text = ''
for (var i = 0; i < 40; i++)
Text += 'abcdefghijklmnopqrstuvwxyz'
- // Create replica set
+ print("Create replica set");
var repset = new ReplicaSet ('testSet', 3) .begin()
var master = repset.getMaster()
var db1 = master.getDB('test')
- // Insert data
+ print("Insert data");
for (var i = 0; i < N; i++) {
db1['foo'].insert({x: i, text: Text})
db1.getLastError(2) // wait to be copied to at least one secondary
}
- // Create single server
+ print("Create single server");
var solo = new Server ('singleTarget')
var soloConn = solo.begin()
+ soloConn.getDB("admin").runCommand({setParameter:1,logLevel:5});
+
var db2 = soloConn.getDB('test')
- // Clone db from replica set to single server
+ print("Clone db from replica set to single server");
db2.cloneDatabase (repset.getURL())
- // Confirm clone worked
+ print("Confirm clone worked");
assert.eq (Text, db2['foo'] .findOne({x: N-1}) ['text'], 'cloneDatabase failed (test1)')
- // Now test the reverse direction
+ print("Now test the reverse direction");
db1 = master.getDB('test2')
db2 = soloConn.getDB('test2')
for (var i = 0; i < N; i++) {
@@ -43,7 +45,7 @@ doTest = function( signal ) {
db1.cloneDatabase (solo.host())
assert.eq (Text, db2['foo'] .findOne({x: N-1}) ['text'], 'cloneDatabase failed (test2)')
- // Shut down replica set and single server
+ print("Shut down replica set and single server");
solo.end()
repset.stopSet( signal )
}
diff --git a/jstests/replsets/config1.js b/jstests/replsets/config1.js
deleted file mode 100644
index 748ce8f..0000000
--- a/jstests/replsets/config1.js
+++ /dev/null
@@ -1,21 +0,0 @@
-doTest = function( signal ) {
- var name = 'config1';
-
- var replTest = new ReplSetTest( {name: name, nodes: 3} );
- var nodes = replTest.startSet();
-
- var config = replTest.getReplSetConfig();
- config.settings = {"heartbeatSleep" : .5, heartbeatTimeout : .8};
-
- replTest.initiate(config);
-
- // Call getMaster to return a reference to the node that's been
- // elected master.
- var master = replTest.getMaster();
-
- config = master.getDB("local").system.replset.findOne();
- assert.eq(config.settings.heartbeatSleep, .5);
- assert.eq(config.settings.heartbeatTimeout, .8);
-};
-
-doTest(15);
diff --git a/jstests/replsets/downstream.js b/jstests/replsets/downstream.js
new file mode 100755
index 0000000..795e667
--- /dev/null
+++ b/jstests/replsets/downstream.js
@@ -0,0 +1,36 @@
+// BUG: [SERVER-1768] replica set getlasterror {w: 2} after 2000
+// inserts hangs while secondary servers log "replSet error RS102 too stale to catch up" every once in a while
+
+function newReplicaSet (name, numServers) {
+ var rs = new ReplSetTest({name: name, nodes: numServers})
+ rs.startSet()
+ rs.initiate()
+ rs.awaitReplication()
+ return rs
+}
+
+function go() {
+var N = 2000
+
+// ~1KB string
+var Text = ''
+for (var i = 0; i < 40; i++)
+ Text += 'abcdefghijklmnopqrstuvwxyz'
+
+// Create replica set of 3 servers
+var repset = newReplicaSet('repset', 3)
+var conn = repset.getMaster()
+var db = conn.getDB('test')
+
+// Add data to it
+for (var i = 0; i < N; i++)
+ db['foo'].insert({x: i, text: Text})
+
+// wait to be copied to at least one secondary (BUG hangs here)
+db.getLastError(2)
+
+print('getlasterror_w2.js SUCCESS')
+}
+
+// turn off until fixed
+//go();
diff --git a/jstests/replsets/fastsync.js b/jstests/replsets/fastsync.js
index d7c3905..1c9c215 100644
--- a/jstests/replsets/fastsync.js
+++ b/jstests/replsets/fastsync.js
@@ -22,7 +22,7 @@ var wait = function(f) {
}
var reconnect = function(a) {
- wait(function() {
+ wait(function() {
try {
a.getDB("foo").bar.stats();
return true;
@@ -33,7 +33,7 @@ var reconnect = function(a) {
});
};
-ports = allocatePorts( 3 );
+ports = allocatePorts( 4 );
var basename = "jstests_fastsync";
var basePath = "/data/db/" + basename;
@@ -48,7 +48,7 @@ var admin = p.getDB("admin");
var foo = p.getDB("foo");
var local = p.getDB("local");
-var config = {_id : basename, members : [{_id : 0, host : hostname+":"+ports[0]}]};
+var config = {_id : basename, members : [{_id : 0, host : hostname+":"+ports[0], priority:2}]};
printjson(config);
var result = admin.runCommand({replSetInitiate : config});
print("result:");
@@ -59,10 +59,19 @@ while (count < 10 && result.ok != 1) {
count++;
sleep(2000);
result = admin.runCommand({replSetInitiate : config});
-}
+}
assert(result.ok, tojson(result));
-assert.soon(function() { return admin.runCommand({isMaster:1}).ismaster; });
+assert.soon(function() { result = false;
+ try {
+ result = admin.runCommand({isMaster:1}).ismaster;
+ }
+ catch(e) {
+ print(e);
+ return false;
+ }
+ return result;
+ });
print("1");
for (var i=0; i<100000; i++) {
@@ -73,45 +82,113 @@ print("total in foo: "+foo.bar.count());
print("2");
admin.runCommand( {fsync:1,lock:1} );
-copyDbpath( basePath + "-p", basePath + "-s" );
+copyDbpath( basePath + "-p", basePath + "-s"+1 );
admin.$cmd.sys.unlock.findOne();
-
print("3");
-var sargs = new MongodRunner( ports[ 1 ], basePath + "-s", false, false,
+var startSlave = function(n) {
+ var sargs = new MongodRunner( ports[ n ], basePath + "-s"+n, false, false,
["--replSet", basename, "--fastsync",
"--oplogSize", 2], {no_bind : true} );
-var reuseData = true;
-sargs.start(reuseData);
+ var reuseData = true;
+ var conn = sargs.start(reuseData);
+
+ config = local.system.replset.findOne();
+ config.version++;
+ config.members.push({_id:n, host:hostname+":"+ports[n]});
+
+ result = admin.runCommand({replSetReconfig : config});
+ printjson(result);
+ assert(result.ok, "reconfig worked");
+ reconnect(p);
+
+ print("4");
+ var status = admin.runCommand({replSetGetStatus : 1});
+ var count = 0;
+ while (status.members[n].state != 2 && count < 200) {
+ print("not a secondary yet");
+ if (count % 10 == 0) {
+ printjson(status);
+ }
+ assert(!status.members[n].errmsg || !status.members[n].errmsg.match("^initial sync cloning db"));
-config = local.system.replset.findOne();
-config.version++;
-config.members.push({_id:1, host:hostname+":"+ports[1]});
+ sleep(1000);
-result = admin.runCommand({replSetReconfig : config});
-assert(result.ok, "reconfig worked");
-reconnect(p);
+ // disconnection could happen here
+ try {
+ status = admin.runCommand({replSetGetStatus : 1});
+ }
+ catch (e) {
+ print(e);
+ }
+ count++;
+ }
-print("4");
-var status = admin.runCommand({replSetGetStatus : 1});
-var count = 0;
-while (status.members[1].state != 2 && count < 200) {
- print("not a secondary yet");
- if (count % 10 == 0) {
- printjson(status);
- }
- assert(!status.members[1].errmsg || !status.members[1].errmsg.match("^initial sync cloning db"));
-
- sleep(1000);
-
- // disconnection could happen here
- try {
- status = admin.runCommand({replSetGetStatus : 1});
- }
- catch (e) {
- print(e);
- }
- count++;
+ assert.eq(status.members[n].state, 2);
+
+ assert.soon(function() {
+ return admin.runCommand({isMaster : 1}).ismaster;
+ });
+
+ admin.foo.insert({x:1});
+ assert.soon(function() {
+ var last = local.oplog.rs.find().sort({$natural:-1}).limit(1).next();
+ var cur = conn.getDB("local").oplog.rs.find().sort({$natural:-1}).limit(1).next();
+ print("last: "+tojson(last)+" cur: "+tojson(cur));
+ return cur != null && last != null && cur.ts.t == last.ts.t && cur.ts.i == last.ts.i;
+ });
+
+ return conn;
+};
+
+var s1 = startSlave(1);
+
+var me1 = s1.getDB("local").me.findOne();
+
+print("me: " +me1._id);
+assert(me1._id != null);
+
+print("5");
+s1.getDB("admin").runCommand( {fsync:1,lock:1} );
+copyDbpath( basePath + "-s1", basePath + "-s2" );
+s1.getDB("admin").$cmd.sys.unlock.findOne();
+
+var s2 = startSlave(2);
+
+var me2 = s2.getDB("local").me.findOne();
+
+print("me: " +me2._id);
+assert(me1._id != me2._id);
+
+print("restart member with a different port and make it a new set");
+try {
+ p.getDB("admin").runCommand({shutdown:1});
+}
+catch(e) {
+ print("good, shutting down: " +e);
}
+sleep(10000);
+
+pargs = new MongodRunner( ports[ 3 ], basePath + "-p", false, false,
+ ["--replSet", basename, "--oplogSize", 2],
+ {no_bind : true} );
+p = pargs.start(true);
+
+printjson(p.getDB("admin").runCommand({replSetGetStatus:1}));
+
+p.getDB("admin").runCommand({replSetReconfig : {
+ _id : basename,
+ members : [{_id:0, host : hostname+":"+ports[3]}]
+ }, force : true});
+
+print("start waiting for primary...");
+assert.soon(function() {
+ try {
+ return p.getDB("admin").runCommand({isMaster : 1}).ismaster;
+ }
+ catch(e) {
+ print(e);
+ }
+ return false;
+ }, "waiting for master", 60000);
-assert.eq(status.members[1].state, 2);
diff --git a/jstests/replsets/initial_sync1.js b/jstests/replsets/initial_sync1.js
index df978c4..4cfd606 100644
--- a/jstests/replsets/initial_sync1.js
+++ b/jstests/replsets/initial_sync1.js
@@ -95,12 +95,11 @@ replTest.stop(1);
print("8. Eventually it should become a secondary");
print("if initial sync has started, this will cause it to fail and sleep for 5 minutes");
-sleep(5*60*1000);
wait(function() {
var status = admin_s2.runCommand({replSetGetStatus:1});
occasionally(function() { printjson(status); });
return status.members[2].state == 2;
- });
+ }, 350);
print("9. Bring #2 back up");
@@ -122,5 +121,5 @@ for (var i=0; i<10000; i++) {
print("11. Everyone happy eventually");
-replTest.awaitReplication();
+replTest.awaitReplication(300000);
diff --git a/jstests/replsets/initial_sync3.js b/jstests/replsets/initial_sync3.js
index 471aa16..7f2af94 100644
--- a/jstests/replsets/initial_sync3.js
+++ b/jstests/replsets/initial_sync3.js
@@ -43,14 +43,14 @@ wait(function() {
if (!status.members) {
return false;
}
-
+
for (i=0; i<7; i++) {
if (status.members[i].state != 1 && status.members[i].state != 2) {
return false;
}
}
return true;
-
+
});
replTest.awaitReplication();
@@ -66,6 +66,7 @@ rs2.initiate();
master = rs2.getMaster();
var config = master.getDB("local").system.replset.findOne();
config.version++;
+config.members[0].priority = 2;
config.members[0].initialSync = {state : 2};
config.members[1].initialSync = {state : 1};
try {
@@ -75,12 +76,34 @@ catch(e) {
print("trying to reconfigure: "+e);
}
-master = rs2.getMaster();
-config = master.getDB("local").system.replset.findOne();
+// wait for a heartbeat, too, just in case sync happens before hb
+assert.soon(function() {
+ try {
+ for (var n in rs2.nodes) {
+ if (rs2.nodes[n].getDB("local").system.replset.findOne().version != 2) {
+ return false;
+ }
+ }
+ }
+ catch (e) {
+ return false;
+ }
+ return true;
+});
+
+rs2.awaitReplication();
+
+// test partitioning
+master = rs2.bridge();
+rs2.partition(0, 2);
+
+master.getDB("foo").bar.baz.insert({x:1});
+rs2.awaitReplication();
-assert(typeof(config.members[0].initialSync) == "object");
-assert.eq(config.members[0].initialSync.state, 2);
-assert.eq(config.members[1].initialSync.state, 1);
+master.getDB("foo").bar.baz.insert({x:2});
+var x = master.getDB("foo").runCommand({getLastError : 1, w : 3, wtimeout : 5000});
+printjson(x);
+assert.eq(null, x.err);
rs2.stopSet();
diff --git a/jstests/replsets/key1 b/jstests/replsets/key1
deleted file mode 100644
index b5c19e4..0000000
--- a/jstests/replsets/key1
+++ /dev/null
@@ -1 +0,0 @@
-foop de doop
diff --git a/jstests/replsets/key2 b/jstests/replsets/key2
deleted file mode 100644
index cbde821..0000000
--- a/jstests/replsets/key2
+++ /dev/null
@@ -1 +0,0 @@
-other key
diff --git a/jstests/replsets/maintenance.js b/jstests/replsets/maintenance.js
new file mode 100644
index 0000000..5b068cd
--- /dev/null
+++ b/jstests/replsets/maintenance.js
@@ -0,0 +1,32 @@
+
+
+var replTest = new ReplSetTest( {name: 'unicomplex', nodes: 3} );
+var conns = replTest.startSet();
+replTest.initiate();
+
+// Make sure we have a master
+var master = replTest.getMaster();
+
+for (i=0;i<10000; i++) { master.getDB("bar").foo.insert({x:1,y:i,abc:123,str:"foo bar baz"}); }
+for (i=0;i<1000; i++) { master.getDB("bar").foo.update({y:i},{$push :{foo : "barrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr"}}); }
+
+replTest.awaitReplication();
+
+assert.soon(function() { return conns[2].getDB("admin").isMaster().secondary; });
+
+join = startParallelShell( "db.getSisterDB('bar').runCommand({compact : 'foo'});", replTest.ports[2] );
+
+print("check secondary goes to recovering");
+assert.soon(function() { return !conns[2].getDB("admin").isMaster().secondary; });
+
+print("joining");
+join();
+
+print("check secondary becomes a secondary again");
+var x = 0;
+assert.soon(function() {
+ var im = conns[2].getDB("admin").isMaster();
+ if (x++ % 5 == 0) printjson(im);
+ return im.secondary;
+});
+
diff --git a/jstests/replsets/majority.js b/jstests/replsets/majority.js
new file mode 100644
index 0000000..6df1a41
--- /dev/null
+++ b/jstests/replsets/majority.js
@@ -0,0 +1,60 @@
+var num = 5;
+var host = getHostName();
+var name = "tags";
+var timeout = 10000;
+
+var replTest = new ReplSetTest( {name: name, nodes: num, startPort:31000} );
+var nodes = replTest.startSet();
+var port = replTest.ports;
+replTest.initiate({_id : name, members :
+ [
+ {_id:0, host : host+":"+port[0], priority : 2},
+ {_id:1, host : host+":"+port[1]},
+ {_id:2, host : host+":"+port[2]},
+ {_id:3, host : host+":"+port[3], arbiterOnly : true},
+ {_id:4, host : host+":"+port[4], arbiterOnly : true},
+ ],
+ });
+
+replTest.awaitReplication();
+replTest.bridge();
+
+var testInsert = function() {
+ master.getDB("foo").bar.insert({x:1});
+ var result = master.getDB("foo").runCommand({getLastError:1, w:"majority", wtimeout:timeout});
+ printjson(result);
+ return result;
+};
+
+var master = replTest.getMaster();
+
+print("get back in the groove");
+testInsert();
+replTest.awaitReplication();
+
+print("makes sure majority works");
+assert.eq(testInsert().err, null);
+
+print("setup: 0,1 | 2,3,4");
+replTest.partition(0,2);
+replTest.partition(0,3);
+replTest.partition(0,4);
+replTest.partition(1,2);
+replTest.partition(1,3);
+replTest.partition(1,4);
+
+print("make sure majority doesn't work");
+// primary should now be 2
+master = replTest.getMaster();
+assert.eq(testInsert().err, "timeout");
+
+print("bring set back together");
+replTest.unPartition(0,2);
+replTest.unPartition(0,3);
+replTest.unPartition(1,4);
+
+master = replTest.getMaster();
+
+print("make sure majority works");
+assert.eq(testInsert().err, null);
+
diff --git a/jstests/replsets/randomcommands1.js b/jstests/replsets/randomcommands1.js
deleted file mode 100644
index c451e74..0000000
--- a/jstests/replsets/randomcommands1.js
+++ /dev/null
@@ -1,29 +0,0 @@
-
-replTest = new ReplSetTest( {name: 'randomcommands1', nodes: 3} );
-
-nodes = replTest.startSet();
-replTest.initiate();
-
-master = replTest.getMaster();
-slaves = replTest.liveNodes.slaves;
-printjson(replTest.liveNodes);
-
-db = master.getDB("foo")
-t = db.foo
-
-ts = slaves.map( function(z){ z.setSlaveOk(); return z.getDB( "foo" ).foo; } )
-
-t.save({a: 1000});
-t.ensureIndex( { a : 1 } )
-
-db.getLastError( 3 , 30000 )
-
-ts.forEach( function(z){ assert.eq( 2 , z.getIndexKeys().length , "A " + z.getMongo() ); } )
-
-t.reIndex()
-
-db.getLastError( 3 , 30000 )
-ts.forEach( function(z){ assert.eq( 2 , z.getIndexKeys().length , "A " + z.getMongo() ); } )
-
-replTest.stopSet( 15 )
-
diff --git a/jstests/replsets/reconfig.js b/jstests/replsets/reconfig.js
new file mode 100644
index 0000000..b7dca03
--- /dev/null
+++ b/jstests/replsets/reconfig.js
@@ -0,0 +1,69 @@
+
+// try reconfiguring with servers down
+
+var replTest = new ReplSetTest({ name: 'testSet', nodes: 5 });
+var nodes = replTest.startSet();
+replTest.initiate();
+
+var master = replTest.getMaster();
+
+print("initial sync");
+master.getDB("foo").bar.insert({X:1});
+replTest.awaitReplication();
+
+print("stopping 3 & 4");
+replTest.stop(3);
+replTest.stop(4);
+
+print("reconfiguring");
+master = replTest.getMaster();
+var config = master.getDB("local").system.replset.findOne();
+var oldVersion = config.version++;
+config.members[0].votes = 2;
+config.members[3].votes = 2;
+try {
+ master.getDB("admin").runCommand({replSetReconfig : config});
+}
+catch(e) {
+ print(e);
+}
+
+var config = master.getDB("local").system.replset.findOne();
+assert.eq(oldVersion+1, config.version);
+
+
+print("0 & 3 up; 1, 2, 4 down");
+replTest.restart(3);
+
+// in case 0 isn't master
+replTest.awaitReplication();
+
+replTest.stop(1);
+replTest.stop(2);
+
+print("try to reconfigure with a 'majority' down");
+oldVersion = config.version;
+config.version++;
+master = replTest.getMaster();
+try {
+ master.getDB("admin").runCommand({replSetReconfig : config});
+}
+catch (e) {
+ print(e);
+}
+
+var config = master.getDB("local").system.replset.findOne();
+assert.eq(oldVersion+1, config.version);
+
+replTest.stopSet();
+
+replTest2 = new ReplSetTest({name : 'testSet2', nodes : 1});
+nodes = replTest2.startSet();
+
+result = nodes[0].getDB("admin").runCommand({replSetInitiate : {_id : "testSet2", members : [
+ {_id : 0, tags : ["member0"]}
+ ]}});
+
+assert(result.errmsg.match(/bad or missing host field/));
+
+replTest2.stopSet();
diff --git a/jstests/replsets/remove1.js b/jstests/replsets/remove1.js
index ebd17d6..f93fe9e 100644
--- a/jstests/replsets/remove1.js
+++ b/jstests/replsets/remove1.js
@@ -16,7 +16,7 @@ var host = getHostName();
print("Start set with three nodes");
-var replTest = new ReplSetTest( {name: name, nodes: 3} );
+var replTest = new ReplSetTest( {name: name, nodes: 2} );
var nodes = replTest.startSet();
replTest.initiate();
var master = replTest.getMaster();
@@ -28,85 +28,44 @@ master.getDB("foo").bar.baz.insert({x:1});
replTest.awaitReplication();
-print("Remove slave2");
+print("Remove slaves");
var config = replTest.getReplSetConfig();
config.members.pop();
config.version = 2;
-try {
- master.getDB("admin").runCommand({replSetReconfig:config});
-}
-catch(e) {
- print(e);
-}
-reconnect(master);
-
-
-print("Remove slave1");
-config.members.pop();
-config.version = 3;
-try {
- master.getDB("admin").runCommand({replSetReconfig:config});
-}
-catch(e) {
- print(e);
-}
-reconnect(master);
-
-print("sleeping 1");
-sleep(10000);
-// these are already down, but this clears their ports from memory so that they
-// can be restarted later
-stopMongod(replTest.getPort(1));
-stopMongod(replTest.getPort(2));
-
-
-print("Bring slave1 back up");
-var paths = [ replTest.getPath(1), replTest.getPath(2) ];
-var ports = allocatePorts(2, replTest.getPort(2)+1);
-var args = ["mongod", "--port", ports[0], "--dbpath", paths[0], "--noprealloc", "--smallfiles", "--rest"];
-var conn = startMongoProgram.apply( null, args );
-conn.getDB("local").system.replset.remove();
-printjson(conn.getDB("local").runCommand({getlasterror:1}));
-print(conn);
-print("sleeping 2");
-sleep(10000);
-stopMongod(ports[0]);
-
-replTest.restart(1);
-
-
-print("Bring slave2 back up");
-args[2] = ports[1];
-args[4] = paths[1];
-conn = startMongoProgram.apply( null, args );
-conn.getDB("local").system.replset.remove();
-print("path: "+paths[1]);
-print("sleeping 3");
-sleep(10000);
-stopMongod(ports[1]);
-
-replTest.restart(2);
-sleep(10000);
-
-
-print("Add them back as slaves");
+assert.soon(function() {
+ try {
+ master.getDB("admin").runCommand({replSetReconfig:config});
+ }
+ catch(e) {
+ print(e);
+ }
+
+ reconnect(master);
+ reconnect(replTest.nodes[1]);
+ var c = master.getDB("local").system.replset.findOne();
+ return c.version == 2;
+ });
+
+print("Add it back as a slave");
config.members.push({_id:1, host : host+":"+replTest.getPort(1)});
-config.members.push({_id:2, host : host+":"+replTest.getPort(2)});
-config.version = 4;
+config.version = 3;
+printjson(config);
wait(function() {
try {
- master.getDB("admin").runCommand({replSetReconfig:config});
+ master.getDB("admin").runCommand({replSetReconfig:config});
}
catch(e) {
- print(e);
+ print(e);
}
reconnect(master);
+ printjson(master.getDB("admin").runCommand({replSetGetStatus:1}));
master.setSlaveOk();
var newConfig = master.getDB("local").system.replset.findOne();
- return newConfig.version == 4;
- });
+ print( "newConfig: " + tojson(newConfig) );
+ return newConfig.version == 3;
+} , "wait1" );
print("Make sure everyone's secondary");
@@ -115,18 +74,49 @@ wait(function() {
occasionally(function() {
printjson(status);
});
-
- if (!status.members || status.members.length != 3) {
+
+ if (!status.members || status.members.length != 2) {
return false;
}
- for (var i = 0; i<3; i++) {
+ for (var i = 0; i<2; i++) {
if (status.members[i].state != 1 && status.members[i].state != 2) {
return false;
}
}
return true;
- });
+} , "wait2" );
+
+
+print("reconfig with minority");
+replTest.stop(1);
+
+assert.soon(function() {
+ try {
+ return master.getDB("admin").runCommand({isMaster : 1}).secondary;
+ }
+ catch(e) {
+ print("trying to get master: "+e);
+ }
+});
+
+config.version = 4;
+config.members.pop();
+try {
+ master.getDB("admin").runCommand({replSetReconfig : config, force : true});
+}
+catch(e) {
+ print(e);
+}
+
+reconnect(master);
+assert.soon(function() {
+ return master.getDB("admin").runCommand({isMaster : 1}).ismaster;
+});
+
+config = master.getDB("local").system.replset.findOne();
+printjson(config);
+assert(config.version > 4);
replTest.stopSet();
diff --git a/jstests/replsets/replset1.js b/jstests/replsets/replset1.js
index 5ac94e7..6387c5d 100644
--- a/jstests/replsets/replset1.js
+++ b/jstests/replsets/replset1.js
@@ -108,6 +108,28 @@ doTest = function( signal ) {
assert.eq( 1000 , count.n , "slave count wrong: " + slave );
});
+ // last error
+ master = replTest.getMaster();
+ slaves = replTest.liveNodes.slaves;
+ printjson(replTest.liveNodes);
+
+ db = master.getDB("foo")
+ t = db.foo
+
+ ts = slaves.map( function(z){ z.setSlaveOk(); return z.getDB( "foo" ).foo; } )
+
+ t.save({a: 1000});
+ t.ensureIndex( { a : 1 } )
+
+ db.getLastError( 3 , 30000 )
+
+ ts.forEach( function(z){ assert.eq( 2 , z.getIndexKeys().length , "A " + z.getMongo() ); } )
+
+ t.reIndex()
+
+ db.getLastError( 3 , 30000 )
+ ts.forEach( function(z){ assert.eq( 2 , z.getIndexKeys().length , "A " + z.getMongo() ); } )
+
// Shut down the set and finish the test.
replTest.stopSet( signal );
}
diff --git a/jstests/replsets/replset3.js b/jstests/replsets/replset3.js
index faa0627..ba08eac 100644
--- a/jstests/replsets/replset3.js
+++ b/jstests/replsets/replset3.js
@@ -29,7 +29,7 @@ doTest = function (signal) {
// Step down master. Note: this may close our connection!
try {
- master.getDB("admin").runCommand({ replSetStepDown: true });
+ master.getDB("admin").runCommand({ replSetStepDown: true, force: 1 });
} catch (err) {
print("caught: " + err + " on stepdown");
}
diff --git a/jstests/replsets/replset5.js b/jstests/replsets/replset5.js
index 6a7d8a5..67ce2d7 100644
--- a/jstests/replsets/replset5.js
+++ b/jstests/replsets/replset5.js
@@ -23,51 +23,63 @@ doTest = function (signal) {
master.getDB("barDB").bar.save({ a: 1 });
replTest.awaitReplication();
- // These writes should be replicated immediately
- var docNum = 5000;
- for(var n=0; n<docNum; n++) {
- master.getDB(testDB).foo.insert({ n: n });
- }
+ // These writes should be replicated immediately
+ var docNum = 5000;
+ for (var n = 0; n < docNum; n++) {
+ master.getDB(testDB).foo.insert({ n: n });
+ }
- // If you want to test failure, just add values for w and wtimeout
- // to the following command. This will override the default set above and
- // prevent replication from happening in time for the count tests below.
- master.getDB("admin").runCommand({getlasterror: 1});
+ // should use the configured last error defaults from above, that's what we're testing.
+ //
+ // If you want to test failure, just add values for w and wtimeout (e.g. w=1)
+ // to the following command. This will override the default set above and
+ // prevent replication from happening in time for the count tests below.
+ //
+ var result = master.getDB("admin").runCommand({ getlasterror: 1 });
+ print("replset5.js getlasterror result:");
+ printjson(result);
+
+ if (result.err == "timeout") {
+ print("\WARNING getLastError timed out and should not have.\nThis machine seems extremely slow. Stopping test without failing it\n")
+ replTest.stopSet(signal);
+ print("\WARNING getLastError timed out and should not have.\nThis machine seems extremely slow. Stopping test without failing it\n")
+ return;
+ }
var slaves = replTest.liveNodes.slaves;
slaves[0].setSlaveOk();
slaves[1].setSlaveOk();
- print("Testing slave counts");
+ print("replset5.js Testing slave counts");
+
+ var slave0count = slaves[0].getDB(testDB).foo.count();
+ assert(slave0count == docNum, "Slave 0 has " + slave0count + " of " + docNum + " documents!");
+
+ var slave1count = slaves[1].getDB(testDB).foo.count();
+ assert(slave1count == docNum, "Slave 1 has " + slave1count + " of " + docNum + " documents!");
+
+ var master1count = master.getDB(testDB).foo.count();
+ assert(master1count == docNum, "Master has " + master1count + " of " + docNum + " documents!");
+
+ print("replset5.js reconfigure with hidden=1");
+ config = master.getDB("local").system.replset.findOne();
+ config.version++;
+ config.members[2].priority = 0;
+ config.members[2].hidden = 1;
+
+ try {
+ master.adminCommand({ replSetReconfig: config });
+ }
+ catch (e) {
+ print(e);
+ }
+
+ config = master.getDB("local").system.replset.findOne();
+ printjson(config);
+ assert.eq(config.members[2].hidden, true);
- var slave0count = slaves[0].getDB(testDB).foo.count();
- assert( slave0count == docNum, "Slave 0 has " + slave0count + " of " + docNum + " documents!");
-
- var slave1count = slaves[1].getDB(testDB).foo.count();
- assert( slave1count == docNum, "Slave 1 has " + slave1count + " of " + docNum + " documents!");
-
- var master1count = master.getDB(testDB).foo.count();
- assert( master1count == docNum, "Master has " + master1count + " of " + docNum + " documents!");
-
- print("reconfigure with hidden=1");
- config = master.getDB("local").system.replset.findOne();
- config.version++;
- config.members[2].priority = 0;
- config.members[2].hidden = 1;
-
- try {
- master.adminCommand({replSetReconfig : config});
- }
- catch(e) {
- print(e);
- }
-
- config = master.getDB("local").system.replset.findOne();
- printjson(config);
- assert.eq(config.members[2].hidden, true);
-
replTest.stopSet(signal);
}
-doTest( 15 );
-print("replset5.js success");
+doTest( 15 );
+print("replset5.js success");
diff --git a/jstests/replsets/replsetadd.js b/jstests/replsets/replsetadd.js
index 673e1d7..44ef7c6 100644
--- a/jstests/replsets/replsetadd.js
+++ b/jstests/replsets/replsetadd.js
@@ -2,13 +2,17 @@
doTest = function( signal ) {
// Test add node
- var replTest = new ReplSetTest( {name: 'testSet', nodes: 0} );
+ var replTest = new ReplSetTest( {name: 'testSet', nodes: 0, host:"localhost"} );
var first = replTest.add();
// Initiate replica set
assert.soon(function() {
- var res = first.getDB("admin").runCommand({replSetInitiate: null});
+ var res = first.getDB("admin").runCommand({replSetInitiate: {
+ _id : 'testSet',
+ members : [{_id : 0, host : "localhost:"+replTest.ports[0]}]
+ }
+ });
return res['ok'] == 1;
});
@@ -18,12 +22,36 @@ doTest = function( signal ) {
return result['ok'] == 1;
});
+ replTest.getMaster();
+
// Start a second node
var second = replTest.add();
// Add the second node.
// This runs the equivalent of rs.add(newNode);
- replTest.reInitiate();
+ print("calling add again");
+ try {
+ replTest.reInitiate();
+ }
+ catch(e) {
+ print(e);
+ }
+
+ print("try to change to localhost to "+getHostName());
+ var master = replTest.getMaster();
+
+ var config = master.getDB("local").system.replset.findOne();
+ config.version++;
+ config.members.forEach(function(m) {
+ m.host = m.host.replace("localhost", getHostName());
+ print(m.host);
+ });
+ printjson(config);
+
+ print("trying reconfig that shouldn't work");
+ var result = master.getDB("admin").runCommand({replSetReconfig: config});
+ assert.eq(result.ok, 0);
+ assert.eq(result.assertionCode, 13645);
replTest.stopSet( signal );
}
diff --git a/jstests/replsets/replsetarb1.js b/jstests/replsets/replsetarb1.js
deleted file mode 100644
index a323290..0000000
--- a/jstests/replsets/replsetarb1.js
+++ /dev/null
@@ -1,33 +0,0 @@
-// FAILING TEST
-// no primary is ever elected if the first server is an arbiter
-
-doTest = function( signal ) {
-
- var replTest = new ReplSetTest( {name: 'unicomplex', nodes: 3} );
- var nodes = replTest.nodeList();
-
- print(tojson(nodes));
-
- var conns = replTest.startSet();
- var r = replTest.initiate({"_id" : "unicomplex",
- "members" : [
- {"_id" : 0, "host" : nodes[0], "arbiterOnly" : true},
- {"_id" : 1, "host" : nodes[1]},
- {"_id" : 2, "host" : nodes[2]}]});
-
- // Make sure we have a master
- // Neither this
- var master = replTest.getMaster();
-
- // Make sure we have an arbiter
- // Nor this will succeed
- assert.soon(function() {
- res = conns[0].getDB("admin").runCommand({replSetGetStatus: 1});
- printjson(res);
- return res.myState == 7;
- }, "Aribiter failed to initialize.");
-
- replTest.stopSet( signal );
-}
-
-// doTest( 15 );
diff --git a/jstests/replsets/replsetarb2.js b/jstests/replsets/replsetarb2.js
index 0e4c791..6f712cb 100644
--- a/jstests/replsets/replsetarb2.js
+++ b/jstests/replsets/replsetarb2.js
@@ -1,5 +1,4 @@
// Election when master fails and remaining nodes are an arbiter and a slave.
-// Note that in this scenario, the arbiter needs two votes.
doTest = function( signal ) {
@@ -9,11 +8,11 @@ doTest = function( signal ) {
print(tojson(nodes));
var conns = replTest.startSet();
- var r = replTest.initiate({"_id" : "unicomplex",
+ var r = replTest.initiate({"_id" : "unicomplex",
"members" : [
- {"_id" : 0, "host" : nodes[0] },
- {"_id" : 1, "host" : nodes[1], "arbiterOnly" : true, "votes": 2},
- {"_id" : 2, "host" : nodes[2] }]});
+ {"_id" : 0, "host" : nodes[0] },
+ {"_id" : 1, "host" : nodes[1], "arbiterOnly" : true, "votes": 1, "priority" : 0},
+ {"_id" : 2, "host" : nodes[2] }]});
// Make sure we have a master
var master = replTest.getMaster();
@@ -25,6 +24,10 @@ doTest = function( signal ) {
return res.myState == 7;
}, "Aribiter failed to initialize.");
+ var result = conns[1].getDB("admin").runCommand({isMaster : 1});
+ assert(result.arbiterOnly);
+ assert(!result.passive);
+
// Wait for initial replication
master.getDB("foo").foo.insert({a: "foo"});
replTest.awaitReplication();
diff --git a/jstests/replsets/replsetarb3.js b/jstests/replsets/replsetarb3.js
deleted file mode 100644
index 1193cf2..0000000
--- a/jstests/replsets/replsetarb3.js
+++ /dev/null
@@ -1,144 +0,0 @@
-// @file replsetarb3.js
-// try turning arbiters into non-arbiters and vice versa
-
-/*
- * 1: initialize set
- * 2: check m3.state == 7
- * 3: reconfig
- * 4: check m3.state == 2
- * 5: reconfig
- * 6: check m3.state == 7
- * 7: reconfig
- * 8: check m3.state == 2
- * 9: insert 10000
- * 10: reconfig
- * 11: check m3.state == 7
- */
-
-var debug = false;
-
-var statusSoon = function(s) {
- assert.soon(function() {
- var status = master.getDB("admin").runCommand({ replSetGetStatus: 1 });
- if (debug)
- printjson(status);
- return status.members[2].state == s;
- });
-};
-
-var w = 0;
-var wait = function(f) {
- w++;
- var n = 0;
- while (!f()) {
- if( n % 4 == 0 )
- print("toostale.js waiting " + w);
- if (++n == 4) {
- print("" + f);
- }
- assert(n < 200, 'tried 200 times, giving up');
- sleep(1000);
- }
-}
-
-var reconnect = function(a) {
- wait(function() {
- try {
- a.getDB("foo").bar.stats();
- return true;
- } catch(e) {
- print(e);
- return false;
- }
- });
-};
-
-var reconfig = function() {
- config.version++;
- try {
- var result = master.getDB("admin").runCommand({replSetReconfig : config});
- }
- catch(e) {
- print(e);
- }
- reconnect(master);
- reconnect(replTest.liveNodes.slaves[1]);
- sleep(20000);
-};
-
-var replTest = new ReplSetTest( {name: 'unicomplex', nodes: 3} );
-var nodes = replTest.nodeList();
-
-print(tojson(nodes));
-
-
-var conns = replTest.startSet();
-
-print("1");
-var config = {"_id" : "unicomplex", "members" : [
- {"_id" : 0, "host" : nodes[0] },
- {"_id" : 1, "host" : nodes[1] },
- {"_id" : 2, "host" : nodes[2], "arbiterOnly" : true}]};
-var r = replTest.initiate(config);
-config.version = 1;
-
-var master = replTest.getMaster();
-
-// Wait for initial replication
-master.getDB("foo").foo.insert({a: "foo"});
-replTest.awaitReplication();
-
-
-print("2");
-statusSoon(7);
-assert.eq(replTest.liveNodes.slaves[1].getDB("local").oplog.rs.count(), 0);
-
-/*
-print("3");
-delete config.members[2].arbiterOnly;
-reconfig();
-
-
-print("4");
-statusSoon(2);
-assert(replTest.liveNodes.slaves[1].getDB("local").oplog.rs.count() > 0);
-
-
-print("5");
-config.members[2].arbiterOnly = true;
-reconfig();
-
-
-print("6");
-statusSoon(7);
-assert.eq(replTest.liveNodes.slaves[1].getDB("local").oplog.rs.count(), 0);
-
-
-print("7");
-delete config.members[2].arbiterOnly;
-reconfig();
-
-
-print("8");
-statusSoon(2);
-assert(replTest.liveNodes.slaves[1].getDB("local").oplog.rs.count() > 0);
-
-
-print("9");
-for (var i = 0; i < 10000; i++) {
- master.getDB("foo").bar.insert({increment : i, c : 0, foo : "kasdlfjaklsdfalksdfakldfmalksdfmaklmfalkfmkafmdsaklfma", date : new Date(), d : Date()});
-}
-
-
-print("10");
-config.members[2].arbiterOnly = true;
-reconfig();
-
-
-print("11");
-statusSoon(7);
-assert.eq(replTest.liveNodes.slaves[1].getDB("local").oplog.rs.count(), 0);
-*/
-
-replTest.stopSet( 15 );
-
diff --git a/jstests/replsets/replsetfreeze.js b/jstests/replsets/replsetfreeze.js
index 3721ba5..7096349 100644
--- a/jstests/replsets/replsetfreeze.js
+++ b/jstests/replsets/replsetfreeze.js
@@ -53,7 +53,7 @@ var master = replTest.getMaster();
print("2: step down m1");
try {
- master.getDB("admin").runCommand({replSetStepDown : 1});
+ master.getDB("admin").runCommand({replSetStepDown : 1, force : 1});
}
catch(e) {
print(e);
@@ -80,7 +80,7 @@ master = replTest.getMaster();
print("6: step down new master");
try {
- master.getDB("admin").runCommand({replSetStepDown : 1});
+ master.getDB("admin").runCommand({replSetStepDown : 1, force : 1});
}
catch(e) {
print(e);
diff --git a/jstests/replsets/replsetrestart1.js b/jstests/replsets/replsetrestart1.js
index 65adaf4..d9f5093 100644
--- a/jstests/replsets/replsetrestart1.js
+++ b/jstests/replsets/replsetrestart1.js
@@ -22,9 +22,16 @@ doTest = function( signal ) {
s1Id = replTest.getNodeId( replTest.liveNodes.slaves[0] );
s2Id = replTest.getNodeId( replTest.liveNodes.slaves[1] );
- replTest.stop( mId );
replTest.stop( s1Id );
replTest.stop( s2Id );
+
+ assert.soon(function() {
+ var status = master.getDB("admin").runCommand({replSetGetStatus: 1});
+ return status.members[1].state == 8 && status.members[2].state == 8;
+ });
+
+
+ replTest.stop( mId );
// Now let's restart these nodes
replTest.restart( mId );
@@ -35,6 +42,11 @@ doTest = function( signal ) {
master = replTest.getMaster();
slaves = replTest.liveNodes.slaves;
+ assert.soon(function() {
+ var status = master.getDB("admin").runCommand({replSetGetStatus: 1});
+ return status.members[1].state != 8 && status.members[2].state != 8;
+ });
+
// Do a status check on each node
// Master should be set to 1 (primary)
assert.soon(function() {
diff --git a/jstests/replsets/replsetrestart2.js b/jstests/replsets/replsetrestart2.js
index 324bd37..6d96697 100644
--- a/jstests/replsets/replsetrestart2.js
+++ b/jstests/replsets/replsetrestart2.js
@@ -1,16 +1,16 @@
// config saved on shutdown
var compare_configs = function(c1, c2) {
- assert(c1.version == c2.version, 'version same');
- assert(c1._id == c2._id, '_id same');
+ assert.eq(c1.version, c2.version, 'version same');
+ assert.eq(c1._id, c2._id, '_id same');
printjson(c1);
printjson(c2);
for (var i in c1.members) {
assert(c2.members[i] !== undefined, 'field '+i+' exists in both configs');
- assert(c1.members[i]._id == c2.members[i]._id, 'id is equal in both configs');
- assert(c1.members[i].host == c2.members[i].host, 'id is equal in both configs');
+ assert.eq(c1.members[i]._id, c2.members[i]._id, 'id is equal in both configs');
+ assert.eq(c1.members[i].host, c2.members[i].host, 'id is equal in both configs');
}
}
diff --git a/jstests/replsets/rollback2.js b/jstests/replsets/rollback2.js
index 46fb548..7ab3c6b 100644
--- a/jstests/replsets/rollback2.js
+++ b/jstests/replsets/rollback2.js
@@ -202,9 +202,24 @@ doTest = function (signal) {
wait(function () { return B.isMaster().ismaster || B.isMaster().secondary; });
// everyone is up here...
- assert(A.isMaster().ismaster || A.isMaster().secondary, "A up");
- assert(B.isMaster().ismaster || B.isMaster().secondary, "B up");
replTest.awaitReplication();
+
+ // theoretically, a read could slip in between StateBox::change() printing
+ // replSet SECONDARY
+ // and the replset actually becoming secondary
+ // so we're trying to wait for that here
+ print("waiting for secondary");
+ assert.soon(function() {
+ try {
+ var aim = A.isMaster();
+ var bim = B.isMaster();
+ return (aim.ismaster || aim.secondary) &&
+ (bim.ismaster || bim.secondary);
+ }
+ catch(e) {
+ print("checking A and B: "+e);
+ }
+ });
verify(a);
diff --git a/jstests/replsets/rollback4.js b/jstests/replsets/rollback4.js
new file mode 100644
index 0000000..5d3299b
--- /dev/null
+++ b/jstests/replsets/rollback4.js
@@ -0,0 +1,117 @@
+//Test for SERVER-3650 (rollback from slave)
+if (0) { // enable for SERVER-3772
+
+var num = 7;
+var host = getHostName();
+var name = "rollback4";
+
+var replTest = new ReplSetTest( {name: name, nodes: num} );
+var config = replTest.getReplSetConfig();
+
+// set preferred masters
+config.members[0].priority = 3
+config.members[6].priority = 2
+// all other are 1
+
+var nodes = replTest.startSet();
+replTest.initiate(config);
+replTest.awaitReplication()
+replTest.bridge();
+
+replTest.waitForMaster();
+var master = replTest.getMaster();
+printjson(master.adminCommand("replSetGetStatus"));
+
+var mColl = master.getCollection('test.foo');
+
+mColl.insert({});
+printjson(master.adminCommand("replSetGetStatus"));
+printjson(master.adminCommand({getLastError:1, w:7, wtimeout:30*1000}));
+
+// partition 012 | 3456 with 0 and 6 the old and new master
+
+
+printjson({startPartition: new Date()});
+replTest.partition(0,3)
+replTest.partition(0,4)
+replTest.partition(0,5)
+replTest.partition(0,6)
+replTest.partition(1,3)
+replTest.partition(1,4)
+replTest.partition(1,5)
+replTest.partition(1,6)
+replTest.partition(2,3)
+replTest.partition(2,4)
+replTest.partition(2,5)
+replTest.partition(2,6)
+printjson({endPartition: new Date()});
+
+var gotThrough = 0
+try {
+ while (true){
+ mColl.insert({})
+ out = master.adminCommand({getLastError:1, w:3});
+ if (out.err)
+ break;
+
+ gotThrough++;
+ }
+}
+catch (e) {
+ print("caught exception");
+}
+
+printjson({gotThrough: gotThrough});
+printjson({cantWriteOldPrimary: new Date()});
+printjson(master.adminCommand("replSetGetStatus"));
+
+assert(gotThrough > 0, "gotOneThrough");
+
+sleep(5*1000); // make sure new seconds field in opTime
+
+replTest.waitForMaster();
+var master2 = replTest.getMaster();
+printjson(master2.adminCommand("replSetGetStatus"));
+
+var m2Coll = master2.getCollection('test.foo');
+
+var sentinel = {_id: 'sentinel'} // used to detect which master's data is used
+m2Coll.insert(sentinel);
+printjson(master2.adminCommand({getLastError:1, w:4, wtimeout:30*1000}));
+printjson(master2.adminCommand("replSetGetStatus"));
+
+m2Coll.insert({}); // this shouldn't be necessary but the next GLE doesn't work without it
+
+printjson({startUnPartition: new Date()});
+replTest.unPartition(0,3)
+replTest.unPartition(0,4)
+replTest.unPartition(0,5)
+replTest.unPartition(0,6)
+replTest.unPartition(1,3)
+replTest.unPartition(1,4)
+replTest.unPartition(1,5)
+replTest.unPartition(1,6)
+replTest.unPartition(2,3)
+replTest.unPartition(2,4)
+replTest.unPartition(2,5)
+replTest.unPartition(2,6)
+printjson({endUnPartition: new Date()});
+
+printjson(master2.adminCommand({getLastError:1, w:7, wtimeout:30*1000}));
+printjson(master2.adminCommand("replSetGetStatus"));
+
+assert.soon(function() {return master.adminCommand('isMaster').ismaster},
+ "Node 0 back to primary",
+ 60*1000/*needs to be longer than LeaseTime*/);
+printjson(master.adminCommand("replSetGetStatus"));
+
+// make sure old master rolled back to new master
+assert.eq(m2Coll.count(sentinel), 1, "check sentinal on node 6");
+assert.eq(mColl.count(sentinel), 1, "check sentinal on node 0");
+
+replTest.stopSet();
+
+}
+
+
+
diff --git a/jstests/replsets/rslib.js b/jstests/replsets/rslib.js
index c072829..19271c9 100644
--- a/jstests/replsets/rslib.js
+++ b/jstests/replsets/rslib.js
@@ -2,7 +2,7 @@
var count = 0;
var w = 0;
-var wait = function(f) {
+var wait = function(f,msg) {
w++;
var n = 0;
while (!f()) {
@@ -11,7 +11,7 @@ var wait = function(f) {
if (++n == 4) {
print("" + f);
}
- assert(n < 200, 'tried 200 times, giving up');
+ assert(n < 200, 'tried 200 times, giving up on ' + msg );
sleep(1000);
}
};
@@ -61,3 +61,43 @@ var getLatestOp = function(server) {
}
return null;
};
+
+
+var waitForAllMembers = function(master) {
+ var ready = false;
+ var count = 0;
+
+ outer:
+ while (count < 60) {
+ count++;
+ var state = master.getSisterDB("admin").runCommand({replSetGetStatus:1});
+ occasionally(function() { printjson(state); }, 10);
+
+ for (var m in state.members) {
+ if (state.members[m].state != 2 && state.members[m].state != 1) {
+ sleep(1000);
+ continue outer;
+ }
+ }
+ return;
+ }
+
+ assert(false, "all members not ready");
+};
+
+var reconfig = function(rs, config) {
+ var admin = rs.getMaster().getDB("admin");
+
+ try {
+ var ok = admin.runCommand({replSetReconfig : config});
+ assert.eq(ok.ok,1);
+ }
+ catch(e) {
+ print(e);
+ }
+
+ master = rs.getMaster().getDB("admin");
+ waitForAllMembers(master);
+
+ return master;
+};
diff --git a/jstests/replsets/slavedelay1.js b/jstests/replsets/slavedelay1.js
index e549822..9301c8e 100644
--- a/jstests/replsets/slavedelay1.js
+++ b/jstests/replsets/slavedelay1.js
@@ -1,22 +1,4 @@
-
-var waitForAllMembers = function(master) {
- var ready = false;
-
- outer:
- while (true) {
- var state = master.getSisterDB("admin").runCommand({replSetGetStatus:1});
- printjson(state);
-
- for (var m in state.members) {
- if (state.members[m].state != 2 && state.members[m].state != 1) {
- sleep(10000);
- continue outer;
- }
- }
- return;
- }
-};
-
+load("jstests/replsets/rslib.js");
doTest = function( signal ) {
@@ -30,7 +12,7 @@ doTest = function( signal ) {
/* set slaveDelay to 30 seconds */
var config = replTest.getReplSetConfig();
config.members[2].priority = 0;
- config.members[2].slaveDelay = 30;
+ config.members[2].slaveDelay = 10;
replTest.initiate(config);
@@ -59,11 +41,16 @@ doTest = function( signal ) {
// make sure delayed slave doesn't have it
assert.eq(slave[1].foo.findOne(), null);
- // wait 35 seconds
- sleep(35000);
-
+ for (var i=0; i<8; i++) {
+ assert.eq(slave[1].foo.findOne(), null);
+ sleep(1000);
+ }
+
// now delayed slave should have it
- assert.eq(slave[1].foo.findOne().x, 1);
+ assert.soon(function() {
+ var z = slave[1].foo.findOne();
+ return z && z.x == 1;
+ });
/************* Part 2 *******************/
@@ -79,9 +66,15 @@ doTest = function( signal ) {
assert.eq(slave[0].foo.findOne({_id : 99}).foo, "bar");
assert.eq(slave[1].foo.findOne({_id : 99}), null);
- sleep(35000);
-
- assert.eq(slave[1].foo.findOne({_id : 99}).foo, "bar");
+ for (var i=0; i<8; i++) {
+ assert.eq(slave[1].foo.findOne({_id:99}), null);
+ sleep(1000);
+ }
+
+ assert.soon(function() {
+ var z = slave[1].foo.findOne({_id : 99});
+ return z && z.foo == "bar";
+ });
/************* Part 3 *******************/
@@ -94,34 +87,53 @@ doTest = function( signal ) {
config.version++;
config.members.push({_id : 3, host : host+":31007",priority:0, slaveDelay:10});
- var admin = master.getSisterDB("admin");
- try {
- var ok = admin.runCommand({replSetReconfig : config});
- assert.eq(ok.ok,1);
- }
- catch(e) {
- print(e);
- }
-
- master = replTest.getMaster().getDB(name);
-
- waitForAllMembers(master);
-
- sleep(15000);
-
+ master = reconfig(replTest, config);
+ master = master.getSisterDB(name);
+
// it should be all caught up now
master.foo.insert({_id : 123, "x" : "foo"});
master.runCommand({getlasterror:1,w:2});
conn.setSlaveOk();
- assert.eq(conn.getDB(name).foo.findOne({_id:123}), null);
+
+ for (var i=0; i<8; i++) {
+ assert.eq(conn.getDB(name).foo.findOne({_id:123}), null);
+ sleep(1000);
+ }
+
+ assert.soon(function() {
+ var z = conn.getDB(name).foo.findOne({_id:123});
+ return z != null && z.x == "foo"
+ });
+
+ /************* Part 4 ******************/
- sleep(15000);
+ print("reconfigure slavedelay");
+
+ config.version++;
+ config.members[3].slaveDelay = 15;
- assert.eq(conn.getDB(name).foo.findOne({_id:123}).x, "foo");
+ master = reconfig(replTest, config);
+ master = master.getSisterDB(name);
+ assert.soon(function() {
+ return conn.getDB("local").system.replset.findOne().version == config.version;
+ });
+
+ master.foo.insert({_id : 124, "x" : "foo"});
+
+ for (var i=0; i<13; i++) {
+ assert.eq(conn.getDB(name).foo.findOne({_id:124}), null);
+ sleep(1000);
+ }
+
+ assert.soon(function() {
+ var z = conn.getDB(name).foo.findOne({_id:124});
+ return z != null && z.x == "foo"
+ });
+
- replTest.stopSet();
+ replTest.stopSet();
}
doTest(15);
diff --git a/jstests/replsets/stale_clustered.js b/jstests/replsets/stale_clustered.js
new file mode 100644
index 0000000..457231e
--- /dev/null
+++ b/jstests/replsets/stale_clustered.js
@@ -0,0 +1,101 @@
+// this tests that slaveOk'd queries in sharded setups get correctly routed when
+// a slave goes into RECOVERING state, and don't break
+
+function prt(s) {
+ print("\nstale_clustered.js " + s);
+ print();
+}
+
+var shardTest = new ShardingTest( name = "clusteredstale" ,
+ numShards = 2 ,
+ verboseLevel = 0 ,
+ numMongos = 2 ,
+ otherParams = { rs : true } )//,
+ //rs0 : { logpath : "$path/mongod.log" },
+ //rs1 : { logpath : "$path/mongod.log" } } );
+
+shardTest.setBalancer( false )
+
+var mongos = shardTest.s0
+var mongosSOK = shardTest.s1
+mongosSOK.setSlaveOk()
+
+var admin = mongos.getDB("admin")
+var config = mongos.getDB("config")
+
+var dbase = mongos.getDB("test")
+var coll = dbase.getCollection("foo")
+var dbaseSOk = mongosSOK.getDB( "" + dbase )
+var collSOk = mongosSOK.getCollection( "" + coll )
+
+
+var rsA = shardTest._rs[0].test
+var rsB = shardTest._rs[1].test
+
+rsA.getMaster().getDB( "test_a" ).dummy.insert( { x : 1 } )
+rsB.getMaster().getDB( "test_b" ).dummy.insert( { x : 1 } )
+
+rsA.awaitReplication()
+rsB.awaitReplication()
+
+prt("1: initial insert")
+
+coll.save({ _id : -1, a : "a", date : new Date() })
+coll.save({ _id : 1, b : "b", date : new Date() })
+
+prt("2: shard collection")
+
+shardTest.shardGo( coll, /* shardBy */ { _id : 1 }, /* splitAt */ { _id : 0 } )
+
+prt("3: test normal and slaveOk queries")
+
+// Make shardA and rsA the same
+var shardA = shardTest.getShard( coll, { _id : -1 } )
+var shardAColl = shardA.getCollection( "" + coll )
+var shardB = shardTest.getShard( coll, { _id : 1 } )
+
+if( shardA.name == rsB.getURL() ){
+ var swap = rsB
+ rsB = rsA
+ rsA = swap
+}
+
+rsA.awaitReplication()
+rsB.awaitReplication()
+
+assert.eq( coll.find().itcount(), collSOk.find().itcount() )
+assert.eq( shardAColl.find().itcount(), 1 )
+assert.eq( shardAColl.findOne()._id, -1 )
+
+prt("5: overflow oplog");
+
+var secs = rsA.getSecondaries()
+var goodSec = secs[0]
+var badSec = secs[1]
+
+rsA.overflow( badSec )
+
+prt("6: stop non-overflowed secondary")
+
+rsA.stop( goodSec, undefined, true )
+
+prt("7: check our regular and slaveok query")
+
+assert.eq( coll.find().itcount(), collSOk.find().itcount() )
+
+prt("8: restart both our secondaries clean")
+
+rsA.restart( rsA.getSecondaries(), { remember : true, startClean : true }, undefined, 5 * 60 * 1000 )
+
+prt("9: wait for recovery")
+
+rsA.waitForState( rsA.getSecondaries(), rsA.SECONDARY, 5 * 60 * 1000 )
+
+prt("10: check our regular and slaveok query")
+
+assert.eq( coll.find().itcount(), collSOk.find().itcount() )
+
+prt("DONE\n\n\n");
+
+//shardTest.stop()
+
diff --git a/jstests/replsets/stepdown.js b/jstests/replsets/stepdown.js
new file mode 100644
index 0000000..3a17b0e
--- /dev/null
+++ b/jstests/replsets/stepdown.js
@@ -0,0 +1,142 @@
+/* check that on a loss of primary, another node doesn't assume primary if it is stale
+ we force a stepDown to test this
+ we use lock+fsync to force secondary to be stale
+*/
+
+var replTest = new ReplSetTest({ name: 'testSet', nodes: 2 });
+var nodes = replTest.startSet();
+replTest.initiate();
+var master = replTest.getMaster();
+
+// do a write
+print("\ndo a write");
+master.getDB("foo").bar.insert({x:1});
+replTest.awaitReplication();
+
+// lock secondary
+print("\nlock secondary");
+var locked = replTest.liveNodes.slaves[0];
+printjson( locked.getDB("admin").runCommand({fsync : 1, lock : 1}) );
+
+print("\nwaiting 11ish seconds");
+
+sleep(2000);
+
+for (var i = 0; i < 11; i++) {
+ // do another write
+ master.getDB("foo").bar.insert({x:i});
+ sleep(1000);
+}
+
+print("\n do stepdown that should not work");
+
+// this should fail, so we don't need to try/catch
+var result = master.getDB("admin").runCommand({replSetStepDown: 10});
+printjson(result);
+assert.eq(result.ok, 0);
+
+print("\n do stepdown that should work");
+try {
+ master.getDB("admin").runCommand({replSetStepDown: 50, force : true});
+}
+catch (e) {
+ print(e);
+}
+
+var r2 = master.getDB("admin").runCommand({ismaster : 1});
+assert.eq(r2.ismaster, false);
+assert.eq(r2.secondary, true);
+
+print("\nunlock");
+printjson(locked.getDB("admin").$cmd.sys.unlock.findOne());
+
+print("\nreset stepped down time");
+master.getDB("admin").runCommand({replSetFreeze:0});
+master = replTest.getMaster();
+
+print("\nmake 1 config with priorities");
+var config = master.getDB("local").system.replset.findOne();
+print("\nmake 2");
+config.version++;
+config.members[0].priority = 2;
+config.members[1].priority = 1;
+// make sure 1 can stay master once 0 is down
+config.members[0].votes = 0;
+try {
+ master.getDB("admin").runCommand({replSetReconfig : config});
+}
+catch (e) {
+ print(e);
+}
+
+print("\nawait");
+replTest.awaitReplication();
+
+master = replTest.getMaster();
+var firstMaster = master;
+print("\nmaster is now "+firstMaster);
+
+try {
+ printjson(master.getDB("admin").runCommand({replSetStepDown : 100, force : true}));
+}
+catch (e) {
+ print(e);
+}
+
+print("\nget a master");
+replTest.getMaster();
+
+assert.soon(function() {
+ var secondMaster = replTest.getMaster();
+ return firstMaster+"" != secondMaster+"";
+ }, 'making sure '+firstMaster+' isn\'t still master', 60000);
+
+
+print("\ncheck shutdown command");
+
+master = replTest.liveNodes.master;
+var slave = replTest.liveNodes.slaves[0];
+var slaveId = replTest.getNodeId(slave);
+
+try {
+ slave.adminCommand({shutdown :1})
+}
+catch (e) {
+ print(e);
+}
+
+print("\nsleeping");
+
+sleep(2000);
+
+print("\nrunning shutdown without force on master: "+master);
+
+result = replTest.getMaster().getDB("admin").runCommand({shutdown : 1, timeoutSecs : 3});
+assert.eq(result.ok, 0);
+
+print("\nsend shutdown command");
+
+var currentMaster = replTest.getMaster();
+try {
+ printjson(currentMaster.getDB("admin").runCommand({shutdown : 1, force : true}));
+}
+catch (e) {
+ print(e);
+}
+
+print("checking "+currentMaster+" is actually shutting down");
+assert.soon(function() {
+ try {
+ currentMaster.findOne();
+ }
+ catch(e) {
+ return true;
+ }
+ return false;
+});
+
+print("\nOK 1");
+
+replTest.stopSet();
+
+print("OK 2");
diff --git a/jstests/replsets/stepdown2.js b/jstests/replsets/stepdown2.js
new file mode 100755
index 0000000..591fea2
--- /dev/null
+++ b/jstests/replsets/stepdown2.js
@@ -0,0 +1,139 @@
+print("\nstepdown2.js");
+
+var replTest = new ReplSetTest({ name: 'testSet', nodes: 2 });
+var nodes = replTest.startSet();
+replTest.initiate();
+var master = replTest.getMaster();
+
+// do a write
+print("\ndo a write");
+master.getDB("foo").bar.insert({x:1});
+replTest.awaitReplication();
+
+// lock secondary
+print("\nlock secondary");
+var locked = replTest.liveNodes.slaves[0];
+printjson( locked.getDB("admin").runCommand({fsync : 1, lock : 1}) );
+
+print("\nwaiting 11ish seconds");
+
+sleep(3003);
+
+for (var i = 0; i < 11; i++) {
+ // do another write
+ master.getDB("foo").bar.insert({x:i});
+ sleep(1008);
+}
+
+print("\n do stepdown that should not work");
+
+// this should fail, so we don't need to try/catch
+var result = master.getDB("admin").runCommand({replSetStepDown: 10});
+printjson(result);
+assert.eq(result.ok, 0);
+
+print("\n do stepdown that should work");
+try {
+ master.getDB("admin").runCommand({replSetStepDown: 50, force : true});
+}
+catch (e) {
+ print(e);
+}
+
+var r2 = master.getDB("admin").runCommand({ismaster : 1});
+assert.eq(r2.ismaster, false);
+assert.eq(r2.secondary, true);
+
+print("\nunlock");
+printjson(locked.getDB("admin").$cmd.sys.unlock.findOne());
+
+print("\nreset stepped down time");
+master.getDB("admin").runCommand({replSetFreeze:0});
+master = replTest.getMaster();
+
+print("\nmake 1 config with priorities");
+var config = master.getDB("local").system.replset.findOne();
+print("\nmake 2");
+config.version++;
+config.members[0].priority = 2;
+config.members[1].priority = 1;
+// make sure 1 can stay master once 0 is down
+config.members[0].votes = 0;
+try {
+ master.getDB("admin").runCommand({replSetReconfig : config});
+}
+catch (e) {
+ print(e);
+}
+
+print("\nawait");
+replTest.awaitReplication();
+
+master = replTest.getMaster();
+var firstMaster = master;
+print("\nmaster is now "+firstMaster);
+
+try {
+ printjson(master.getDB("admin").runCommand({replSetStepDown : 100, force : true}));
+}
+catch (e) {
+ print(e);
+}
+
+print("\nget a master");
+replTest.getMaster();
+
+assert.soon(function() {
+ var secondMaster = replTest.getMaster();
+ return firstMaster+"" != secondMaster+"";
+ }, 'making sure '+firstMaster+' isn\'t still master', 60000);
+
+
+print("\ncheck shutdown command");
+
+master = replTest.liveNodes.master;
+var slave = replTest.liveNodes.slaves[0];
+var slaveId = replTest.getNodeId(slave);
+
+try {
+ slave.adminCommand({shutdown :1})
+}
+catch (e) {
+ print(e);
+}
+
+print("\nsleeping");
+
+sleep(2000);
+
+print("\nrunning shutdown without force on master: "+master);
+
+result = replTest.getMaster().getDB("admin").runCommand({shutdown : 1, timeoutSecs : 3});
+assert.eq(result.ok, 0);
+
+print("\nsend shutdown command");
+
+var currentMaster = replTest.getMaster();
+try {
+ printjson(currentMaster.getDB("admin").runCommand({shutdown : 1, force : true}));
+}
+catch (e) {
+ print(e);
+}
+
+print("checking "+currentMaster+" is actually shutting down");
+assert.soon(function() {
+ try {
+ currentMaster.findOne();
+ }
+ catch(e) {
+ return true;
+ }
+ return false;
+});
+
+print("\nOK 1 stepdown2.js");
+
+replTest.stopSet();
+
+print("\nOK 2 stepdown2.js");
diff --git a/jstests/replsets/sync1.js b/jstests/replsets/sync1.js
index af16044..a090c1c 100644
--- a/jstests/replsets/sync1.js
+++ b/jstests/replsets/sync1.js
@@ -15,156 +15,172 @@ function pause(s) {
sleep(4000);
}
}
-}
-
-doTest = function (signal) {
-
- var replTest = new ReplSetTest({ name: 'testSet', nodes: 3 });
- var nodes = replTest.startSet({ oplogSize: "40" });
-
- sleep(5000);
-
- print("\nsync1.js ********************************************************************** part 0");
- replTest.initiate();
-
- // get master
- print("\nsync1.js ********************************************************************** part 1");
- var master = replTest.getMaster();
- print("\nsync1.js ********************************************************************** part 2");
- var dbs = [master.getDB("foo")];
-
- for (var i in nodes) {
- if (nodes[i] + "" == master + "") {
- continue;
- }
- dbs.push(nodes[i].getDB("foo"));
- nodes[i].setSlaveOk();
- }
-
- print("\nsync1.js ********************************************************************** part 3");
- dbs[0].bar.drop();
-
- print("\nsync1.js ********************************************************************** part 4");
- // slow things down a bit
- dbs[0].bar.ensureIndex({ x: 1 });
- dbs[0].bar.ensureIndex({ y: 1 });
- dbs[0].bar.ensureIndex({ z: 1 });
- dbs[0].bar.ensureIndex({ w: 1 });
-
- var ok = false;
- var inserts = 10000;
-
- print("\nsync1.js ********************************************************************** part 5");
-
- for (var i = 0; i < inserts; i++) {
- dbs[0].bar.insert({ x: "foo" + i, y: "bar" + i, z: i, w: "biz baz bar boo" });
- }
-
- var status;
- do {
- sleep(1000);
- status = dbs[0].getSisterDB("admin").runCommand({ replSetGetStatus: 1 });
- } while (status.members[1].state != 2 || status.members[2].state != 2);
-
- print("\nsync1.js ********************************************************************** part 6");
- dbs[0].getSisterDB("admin").runCommand({ replSetTest: 1, blind: true });
-
- print("\nsync1.js ********************************************************************** part 7");
-
- sleep(5000);
-
- var max1;
- var max2;
- var count = 0;
- while (1) {
- try {
- max1 = dbs[1].bar.find().sort({ z: -1 }).limit(1).next();
- max2 = dbs[2].bar.find().sort({ z: -1 }).limit(1).next();
- }
- catch (e) {
- print("\nsync1.js couldn't get max1/max2; retrying " + e);
- sleep(2000);
- count++;
- if (count == 50) {
- assert(false, "errored out 50 times");
- }
- continue;
- }
- break;
- }
-
- // wait for a new master to be elected
- sleep(5000);
- var newMaster;
-
- print("\nsync1.js ********************************************************************** part 9");
-
- for (var q = 0; q < 10; q++) {
- // figure out who is master now
- newMaster = replTest.getMaster();
- if (newMaster + "" != master + "")
- break;
- sleep(2000);
- if (q > 6) print("sync1.js zzz....");
- }
-
- assert(newMaster + "" != master + "", "new master is " + newMaster + ", old master was " + master);
-
- print("\nsync1.js new master is " + newMaster + ", old master was " + master);
-
- print("\nsync1.js ********************************************************************** part 9.1");
-
- count = 0;
- countExceptions = 0;
- do {
- try {
- max1 = dbs[1].bar.find().sort({ z: -1 }).limit(1).next();
- max2 = dbs[2].bar.find().sort({ z: -1 }).limit(1).next();
- }
- catch (e) {
- if (countExceptions++ > 300) {
- print("dbs[1]:");
- try {
- printjson(dbs[1].isMaster());
- printjson(dbs[1].bar.count());
+}
+
+doTest = function (signal) {
+
+ var replTest = new ReplSetTest({ name: 'testSet', nodes: 3 });
+ var nodes = replTest.startSet({ oplogSize: "40" });
+ print("\nsync1.js ********************************************************************** part 0");
+ replTest.initiate();
+
+ // get master
+ print("\nsync1.js ********************************************************************** part 1");
+ var master = replTest.getMaster();
+ print("\nsync1.js ********************************************************************** part 2");
+ var dbs = [master.getDB("foo")];
+
+ for (var i in nodes) {
+ if (nodes[i] + "" == master + "") {
+ continue;
+ }
+ dbs.push(nodes[i].getDB("foo"));
+ nodes[i].setSlaveOk();
+ }
+
+ print("\nsync1.js ********************************************************************** part 3");
+ dbs[0].bar.drop();
+
+ print("\nsync1.js ********************************************************************** part 4");
+ // slow things down a bit
+ dbs[0].bar.ensureIndex({ x: 1 });
+ dbs[0].bar.ensureIndex({ y: 1 });
+ dbs[0].bar.ensureIndex({ z: 1 });
+ dbs[0].bar.ensureIndex({ w: 1 });
+
+ var ok = false;
+ var inserts = 10000;
+
+ print("\nsync1.js ********************************************************************** part 5");
+
+ for (var i = 0; i < inserts; i++) {
+ dbs[0].bar.insert({ x: "foo" + i, y: "bar" + i, z: i, w: "biz baz bar boo" });
+ }
+
+ var status;
+ var secondaries = 0;
+ var count = 0;
+ do {
+ sleep(1000);
+ status = dbs[0].getSisterDB("admin").runCommand({ replSetGetStatus: 1 });
+
+ occasionally(function() {
+ printjson(status);
+ }, 30);
+
+ secondaries = 0;
+ secondaries += status.members[0].state == 2 ? 1 : 0;
+ secondaries += status.members[1].state == 2 ? 1 : 0;
+ secondaries += status.members[2].state == 2 ? 1 : 0;
+ count++;
+ } while (secondaries < 2 && count < 300);
+
+ assert(count < 300);
+
+ // Need to be careful here, allocating datafiles for the slaves can take a *long* time on slow systems
+ sleep(7000);
+
+ print("\nsync1.js ********************************************************************** part 6");
+ dbs[0].getSisterDB("admin").runCommand({ replSetTest: 1, blind: true });
+
+ print("\nsync1.js ********************************************************************** part 7");
+
+ sleep(5000);
+ // If we start getting error hasNext: false with done alloc datafile msgs - may need to up the sleep again in part 5
+
+
+ var max1;
+ var max2;
+ var count = 0;
+ while (1) {
+ try {
+ max1 = dbs[1].bar.find().sort({ z: -1 }).limit(1).next();
+ max2 = dbs[2].bar.find().sort({ z: -1 }).limit(1).next();
+ }
+ catch (e) {
+ print("\nsync1.js couldn't get max1/max2; retrying " + e);
+ sleep(2000);
+ count++;
+ if (count == 50) {
+ assert(false, "errored out 50 times");
+ }
+ continue;
+ }
+ break;
+ }
+
+ // wait for a new master to be elected
+ sleep(5000);
+ var newMaster;
+
+ print("\nsync1.js ********************************************************************** part 9");
+
+ for (var q = 0; q < 10; q++) {
+ // figure out who is master now
+ newMaster = replTest.getMaster();
+ if (newMaster + "" != master + "")
+ break;
+ sleep(2000);
+ if (q > 6) print("sync1.js zzz....");
+ }
+
+ assert(newMaster + "" != master + "", "new master is " + newMaster + ", old master was " + master);
+
+ print("\nsync1.js new master is " + newMaster + ", old master was " + master);
+
+ print("\nsync1.js ********************************************************************** part 9.1");
+
+ count = 0;
+ countExceptions = 0;
+ do {
+ try {
+ max1 = dbs[1].bar.find().sort({ z: -1 }).limit(1).next();
+ max2 = dbs[2].bar.find().sort({ z: -1 }).limit(1).next();
+ }
+ catch (e) {
+ if (countExceptions++ > 300) {
+ print("dbs[1]:");
+ try {
+ printjson(dbs[1].isMaster());
+ printjson(dbs[1].bar.count());
printjson(dbs[1].adminCommand({replSetGetStatus : 1}));
- }
- catch (e) { print(e); }
- print("dbs[2]:");
- try {
- printjson(dbs[2].isMaster());
- printjson(dbs[2].bar.count());
+ }
+ catch (e) { print(e); }
+ print("dbs[2]:");
+ try {
+ printjson(dbs[2].isMaster());
+ printjson(dbs[2].bar.count());
printjson(dbs[2].adminCommand({replSetGetStatus : 1}));
- }
- catch (e) { print(e); }
- assert(false, "sync1.js too many exceptions, failing");
- }
- print("\nsync1.js: exception querying; will sleep and try again " + e);
- sleep(3000);
- continue;
- }
-
- print("\nsync1.js waiting for match " + count + " " + Date() + " z[1]:" + max1.z + " z[2]:" + max2.z);
-
- // printjson(max1);
- // printjson(max2);
-
- sleep(2000);
-
- count++;
- if (count == 100) {
- pause("fail phase 1");
- assert(false, "replsets/\nsync1.js fails timing out");
- replTest.stopSet(signal);
- return;
- }
- } while (max1.z != max2.z);
-
- // okay, now they're caught up. We have a max: max1.z
-
- print("\nsync1.js ********************************************************************** part 10");
-
- // now, let's see if rollback works
+ }
+ catch (e) { print(e); }
+ assert(false, "sync1.js too many exceptions, failing");
+ }
+ print("\nsync1.js: exception querying; will sleep and try again " + e);
+ sleep(3000);
+ continue;
+ }
+
+ print("\nsync1.js waiting for match " + count + " " + Date() + " z[1]:" + max1.z + " z[2]:" + max2.z);
+
+ // printjson(max1);
+ // printjson(max2);
+
+ sleep(2000);
+
+ count++;
+ if (count == 100) {
+ pause("fail phase 1");
+ assert(false, "replsets/\nsync1.js fails timing out");
+ replTest.stopSet(signal);
+ return;
+ }
+ } while (max1.z != max2.z);
+
+ // okay, now they're caught up. We have a max: max1.z
+
+ print("\nsync1.js ********************************************************************** part 10");
+
+ // now, let's see if rollback works
wait(function() {
try {
dbs[0].adminCommand({ replSetTest: 1, blind: false });
@@ -180,50 +196,50 @@ doTest = function (signal) {
});
- dbs[0].getMongo().setSlaveOk();
- sleep(5000);
-
- // now this should resync
- print("\nsync1.js ********************************************************************** part 11");
- var max0 = null;
- count = 0;
- do {
- try {
- max0 = dbs[0].bar.find().sort({ z: -1 }).limit(1).next();
- max1 = dbs[1].bar.find().sort({ z: -1 }).limit(1).next();
- }
- catch (e) {
- print("\nsync1.js part 11 exception on bar.find() will sleep and try again " + e);
- sleep(2000);
- continue;
- }
-
- print("part 11");
- if (max0) {
- print("max0.z:" + max0.z);
- print("max1.z:" + max1.z);
- }
-
- sleep(2000);
-
- count++;
- if (count == 100) {
- printjson(dbs[0].isMaster());
+ dbs[0].getMongo().setSlaveOk();
+ sleep(5000);
+
+ // now this should resync
+ print("\nsync1.js ********************************************************************** part 11");
+ var max0 = null;
+ count = 0;
+ do {
+ try {
+ max0 = dbs[0].bar.find().sort({ z: -1 }).limit(1).next();
+ max1 = dbs[1].bar.find().sort({ z: -1 }).limit(1).next();
+ }
+ catch (e) {
+ print("\nsync1.js part 11 exception on bar.find() will sleep and try again " + e);
+ sleep(2000);
+ continue;
+ }
+
+ print("part 11");
+ if (max0) {
+ print("max0.z:" + max0.z);
+ print("max1.z:" + max1.z);
+ }
+
+ sleep(2000);
+
+ count++;
+ if (count == 100) {
+ printjson(dbs[0].isMaster());
printjson(dbs[0].adminCommand({replSetGetStatus:1}));
- printjson(dbs[1].isMaster());
+ printjson(dbs[1].isMaster());
printjson(dbs[1].adminCommand({replSetGetStatus:1}));
- pause("FAIL part 11");
- assert(false, "replsets/\nsync1.js fails timing out");
- replTest.stopSet(signal);
- return;
- }
- //print("||||| count:" + count);
- //printjson(max0);
- } while (!max0 || max0.z != max1.z);
-
- print("\nsync1.js ********************************************************************** part 12");
- pause("\nsync1.js success");
- replTest.stopSet(signal);
+ pause("FAIL part 11");
+ assert(false, "replsets/\nsync1.js fails timing out");
+ replTest.stopSet(signal);
+ return;
+ }
+ //print("||||| count:" + count);
+ //printjson(max0);
+ } while (!max0 || max0.z != max1.z);
+
+ print("\nsync1.js ********************************************************************** part 12");
+ pause("\nsync1.js success");
+ replTest.stopSet(signal);
}
if( 1 || debugging ) {
diff --git a/jstests/replsets/sync2.js b/jstests/replsets/sync2.js
new file mode 100644
index 0000000..9f6c205
--- /dev/null
+++ b/jstests/replsets/sync2.js
@@ -0,0 +1,48 @@
+
+var replTest = new ReplSetTest({ name: 'testSet', nodes: 5 });
+var nodes = replTest.startSet({ oplogSize: "2" });
+replTest.initiate();
+
+var master = replTest.getMaster();
+var config = master.getDB("local").system.replset.findOne();
+config.version++;
+config.members[0].priority = 2;
+
+try {
+ master.getDB("admin").runCommand({replSetReconfig : config});
+}
+catch(e) {
+ print(e);
+}
+
+// initial sync
+master.getDB("foo").bar.insert({x:1});
+replTest.awaitReplication();
+
+master = replTest.bridge();
+
+replTest.partition(0,4);
+replTest.partition(1,2);
+replTest.partition(2,3);
+replTest.partition(3,1);
+
+// 4 is connected to 2
+replTest.partition(4,1);
+replTest.partition(4,3);
+
+master.getDB("foo").bar.insert({x:1});
+replTest.awaitReplication();
+
+var result = master.getDB("admin").runCommand({getLastError:1,w:5,wtimeout:1000});
+assert.eq(null, result.err, tojson(result));
+
+// 4 is connected to 3
+replTest.partition(4,2);
+replTest.unPartition(4,3);
+
+master.getDB("foo").bar.insert({x:1});
+replTest.awaitReplication();
+
+result = master.getDB("admin").runCommand({getLastError:1,w:5,wtimeout:1000});
+assert.eq(null, result.err, tojson(result));
+
diff --git a/jstests/replsets/tags.js b/jstests/replsets/tags.js
new file mode 100644
index 0000000..4e73886
--- /dev/null
+++ b/jstests/replsets/tags.js
@@ -0,0 +1,154 @@
+
+var num = 5;
+var host = getHostName();
+var name = "tags";
+
+var replTest = new ReplSetTest( {name: name, nodes: num, startPort:31000} );
+var nodes = replTest.startSet();
+var port = replTest.ports;
+replTest.initiate({_id : name, members :
+ [
+ {_id:0, host : host+":"+port[0], tags : {"server" : "0", "dc" : "ny", "ny" : "1", "rack" : "ny.rk1"}},
+ {_id:1, host : host+":"+port[1], tags : {"server" : "1", "dc" : "ny", "ny" : "2", "rack" : "ny.rk1"}},
+ {_id:2, host : host+":"+port[2], tags : {"server" : "2", "dc" : "ny", "ny" : "3", "rack" : "ny.rk2", "2" : "this"}},
+ {_id:3, host : host+":"+port[3], tags : {"server" : "3", "dc" : "sf", "sf" : "1", "rack" : "sf.rk1"}},
+ {_id:4, host : host+":"+port[4], tags : {"server" : "4", "dc" : "sf", "sf" : "2", "rack" : "sf.rk2"}},
+ ],
+ settings : {
+ getLastErrorModes : {
+ "important" : {"dc" : 2, "server" : 3},
+ "a machine" : {"server" : 1}
+ }
+ }});
+
+var master = replTest.getMaster();
+
+var config = master.getDB("local").system.replset.findOne();
+
+printjson(config);
+var modes = config.settings.getLastErrorModes;
+assert.eq(typeof modes, "object");
+assert.eq(modes.important.dc, 2);
+assert.eq(modes.important.server, 3);
+assert.eq(modes["a machine"]["server"], 1);
+
+config.version++;
+config.members[1].priority = 1.5;
+config.members[2].priority = 2;
+modes.rack = {"sf" : 1};
+modes.niceRack = {"sf" : 2};
+modes["a machine"]["2"] = 1;
+modes.on2 = {"2" : 1}
+
+try {
+ master.getDB("admin").runCommand({replSetReconfig : config});
+}
+catch(e) {
+ print(e);
+}
+
+replTest.awaitReplication();
+
+print("primary should now be 2");
+master = replTest.getMaster();
+config = master.getDB("local").system.replset.findOne();
+printjson(config);
+
+modes = config.settings.getLastErrorModes;
+assert.eq(typeof modes, "object");
+assert.eq(modes.important.dc, 2);
+assert.eq(modes.important.server, 3);
+assert.eq(modes["a machine"]["server"], 1);
+assert.eq(modes.rack["sf"], 1);
+assert.eq(modes.niceRack["sf"], 2);
+
+print("bridging");
+replTest.bridge();
+
+replTest.partition(0, 3);
+replTest.partition(0, 4);
+replTest.partition(1, 3);
+replTest.partition(1, 4);
+replTest.partition(2, 3);
+replTest.partition(2, 4);
+replTest.partition(3, 4);
+print("done bridging");
+
+print("test1");
+print("2 should be primary");
+master = replTest.getMaster();
+
+printjson(master.getDB("admin").runCommand({replSetGetStatus:1}));
+
+var timeout = 20000;
+
+master.getDB("foo").bar.insert({x:1});
+var result = master.getDB("foo").runCommand({getLastError:1,w:"rack",wtimeout:timeout});
+printjson(result);
+assert.eq(result.err, "timeout");
+
+replTest.unPartition(1,4);
+
+print("test2");
+master.getDB("foo").bar.insert({x:1});
+result = master.getDB("foo").runCommand({getLastError:1,w:"rack",wtimeout:timeout});
+printjson(result);
+assert.eq(result.err, null);
+
+print("test3");
+result = master.getDB("foo").runCommand({getLastError:1,w:"niceRack",wtimeout:timeout});
+printjson(result);
+assert.eq(result.err, "timeout");
+
+replTest.unPartition(3,4);
+
+print("test4");
+result = master.getDB("foo").runCommand({getLastError:1,w:"niceRack",wtimeout:timeout});
+printjson(result);
+assert.eq(result.err, null);
+
+print("non-existent w");
+result = master.getDB("foo").runCommand({getLastError:1,w:"blahblah",wtimeout:timeout});
+printjson(result);
+assert.eq(result.assertionCode, 14830);
+assert.eq(result.ok, 0);
+
+print("test on2");
+master.getDB("foo").bar.insert({x:1});
+result = master.getDB("foo").runCommand({getLastError:1,w:"on2",wtimeout:0});
+printjson(result);
+assert.eq(result.err, null);
+
+print("test two on the primary");
+master.getDB("foo").bar.insert({x:1});
+result = master.getDB("foo").runCommand({getLastError:1,w:"a machine",wtimeout:0});
+printjson(result);
+assert.eq(result.err, null);
+
+print("test5");
+master.getDB("foo").bar.insert({x:1});
+result = master.getDB("foo").runCommand({getLastError:1,w:"important",wtimeout:timeout});
+printjson(result);
+assert.eq(result.err, null);
+
+replTest.unPartition(1,3);
+
+replTest.partition(2, 0);
+replTest.partition(2, 1);
+replTest.stop(2);
+
+print("1 must become primary here because otherwise the other members will take too long timing out their old sync threads");
+master = replTest.getMaster();
+
+print("test6");
+master.getDB("foo").bar.insert({x:1});
+result = master.getDB("foo").runCommand({getLastError:1,w:"niceRack",wtimeout:timeout});
+printjson(result);
+assert.eq(result.err, null);
+
+print("test on2");
+master.getDB("foo").bar.insert({x:1});
+result = master.getDB("foo").runCommand({getLastError:1,w:"on2",wtimeout:timeout});
+printjson(result);
+assert.eq(result.err, "timeout");
+
diff --git a/jstests/replsets/tags2.js b/jstests/replsets/tags2.js
new file mode 100644
index 0000000..16dfcdf
--- /dev/null
+++ b/jstests/replsets/tags2.js
@@ -0,0 +1,44 @@
+// Change a getLastErrorMode from 2 to 3 servers
+
+var host = getHostName();
+var replTest = new ReplSetTest( {name: "rstag", nodes: 3, startPort: 31000} );
+var nodes = replTest.startSet();
+var ports = replTest.ports;
+var conf = {_id : "rstag", version: 1, members : [
+ {_id : 0, host : host+":"+ports[0], tags : {"backup" : "A"}},
+ {_id : 1, host : host+":"+ports[1], tags : {"backup" : "B"}},
+ {_id : 2, host : host+":"+ports[2], tags : {"backup" : "C"}} ],
+ settings : {getLastErrorModes : {
+ backedUp : {backup : 2} }} };
+replTest.initiate( conf );
+replTest.awaitReplication();
+
+master = replTest.getMaster();
+var db = master.getDB("test");
+db.foo.insert( {x:1} );
+var result = db.runCommand( {getLastError:1, w:"backedUp", wtimeout:20000} );
+assert.eq (result.err, null);
+
+conf.version = 2;
+conf.settings.getLastErrorModes.backedUp.backup = 3;
+master.getDB("admin").runCommand( {replSetReconfig: conf} );
+replTest.awaitReplication();
+
+master = replTest.getMaster();
+var db = master.getDB("test");
+db.foo.insert( {x:2} );
+var result = db.runCommand( {getLastError:1, w:"backedUp", wtimeout:20000} );
+assert.eq (result.err, null);
+
+conf.version = 3;
+conf.members[0].priorty = 3;
+conf.members[2].priorty = 0;
+master.getDB("admin").runCommand( {replSetReconfig: conf} );
+
+master = replTest.getMaster();
+var db = master.getDB("test");
+db.foo.insert( {x:3} );
+var result = db.runCommand( {getLastError:1, w:"backedUp", wtimeout:20000} );
+assert.eq (result.err, null);
+
+replTest.stopSet();
diff --git a/jstests/replsets/toostale.js b/jstests/replsets/toostale.js
index 0b8da0d..08b1a9c 100644
--- a/jstests/replsets/toostale.js
+++ b/jstests/replsets/toostale.js
@@ -32,7 +32,7 @@ var wait = function(f) {
}
var reconnect = function(a) {
- wait(function() {
+ wait(function() {
try {
a.bar.stats();
return true;
@@ -46,9 +46,14 @@ var reconnect = function(a) {
var name = "toostale"
var replTest = new ReplSetTest( {name: name, nodes: 3});
+var host = getHostName();
var nodes = replTest.startSet();
-replTest.initiate();
+replTest.initiate({_id : name, members : [
+ {_id : 0, host : host+":"+replTest.ports[0]},
+ {_id : 1, host : host+":"+replTest.ports[1], arbiterOnly : true},
+ {_id : 2, host : host+":"+replTest.ports[2]}
+]});
var master = replTest.getMaster();
var mdb = master.getDB("foo");
@@ -60,7 +65,7 @@ mdb.foo.save({a: 1000});
print("2: initial sync");
replTest.awaitReplication();
-print("3: blind s2");
+print("3: stop s2");
replTest.stop(2);
print("waiting until the master knows the slave is blind");
assert.soon(function() { return master.getDB("admin").runCommand({replSetGetStatus:1}).members[2].health == 0 });
@@ -82,7 +87,7 @@ while (count != prevCount) {
}
-print("5: unblind s2");
+print("5: restart s2");
replTest.restart(2);
print("waiting until the master knows the slave is not blind");
assert.soon(function() { return master.getDB("admin").runCommand({replSetGetStatus:1}).members[2].health != 0 });
@@ -106,16 +111,17 @@ replTest.restart(2);
print("8: check s2.state == 3");
-status = master.getDB("admin").runCommand({replSetGetStatus:1});
-while (status.state == 0) {
- print("state is 0: ");
- printjson(status);
- sleep(1000);
- status = master.getDB("admin").runCommand({replSetGetStatus:1});
-}
+assert.soon(function() {
+ var status = master.getDB("admin").runCommand({replSetGetStatus:1});
+ printjson(status);
+ return status.members && status.members[2].state == 3;
+});
-printjson(status);
-assert.eq(status.members[2].state, 3, 'recovering');
+print("make sure s2 doesn't become primary");
+replTest.stop(0);
+sleep(20000);
+printjson(replTest.nodes[2].getDB("admin").runCommand({isMaster : 1}));
+printjson(replTest.nodes[2].getDB("admin").runCommand({replSetGetStatus : 1}));
-replTest.stopSet(15);
+//replTest.stopSet(15);
diff --git a/jstests/replsets/twosets.js b/jstests/replsets/twosets.js
deleted file mode 100644
index aae1113..0000000
--- a/jstests/replsets/twosets.js
+++ /dev/null
@@ -1,35 +0,0 @@
-// add a node from a different set to the current set
-// I don't know what should happen here.
-
-doTest = function( signal ) {
-
- var orig = new ReplSetTest( {name: 'testSet', nodes: 3} );
- orig.startSet();
- orig.initiate();
- var master = orig.getMaster();
-
- var interloper = new ReplSetTest( {name: 'testSet', nodes: 3, startPort : 31003} );
- interloper.startSet();
- interloper.initiate();
-
- var conf = master.getDB("local").system.replset.findOne();
-
- var nodes = interloper.nodeList();
- var host = nodes[0];
- var id = conf.members.length;
- conf.members.push({_id : id, host : host});
- conf.version++;
-
- try {
- var result = master.getDB("admin").runCommand({replSetReconfig : conf});
- }
- catch(e) {
- print(e);
- }
-
- // now... stuff should blow up?
-
- sleep(10);
-}
-
-doTest(15); \ No newline at end of file