summaryrefslogtreecommitdiff
path: root/jstests/replsets
diff options
context:
space:
mode:
authorAntonin Kral <a.kral@bobek.cz>2011-03-17 00:07:52 +0100
committerAntonin Kral <a.kral@bobek.cz>2011-03-17 00:07:52 +0100
commit98b8b639326ab4c89eed73739d9903993c4c8959 (patch)
tree0462df078bf740093774d033b75f0ea24a31fa97 /jstests/replsets
parentf5d6e97ca8d2f3e7c4cdd5c9afbf8e756ef65bc2 (diff)
parent582fc32574a3b158c81e49cb00e6ae59205e66ba (diff)
downloadmongodb-98b8b639326ab4c89eed73739d9903993c4c8959.tar.gz
Merge commit 'upstream/1.8.0
Diffstat (limited to 'jstests/replsets')
-rw-r--r--jstests/replsets/auth1.js184
-rw-r--r--jstests/replsets/buildindexes.js86
-rw-r--r--jstests/replsets/cloneDb.js52
-rw-r--r--jstests/replsets/config1.js21
-rw-r--r--jstests/replsets/fastsync.js117
-rw-r--r--jstests/replsets/getlasterror_w2.js36
-rw-r--r--jstests/replsets/groupAndMapReduce.js105
-rw-r--r--jstests/replsets/initial_sync1.js129
-rw-r--r--jstests/replsets/initial_sync2.js179
-rw-r--r--jstests/replsets/initial_sync3.js87
-rw-r--r--jstests/replsets/ismaster1.js36
-rw-r--r--jstests/replsets/key11
-rw-r--r--jstests/replsets/key21
-rw-r--r--jstests/replsets/remove1.js132
-rw-r--r--jstests/replsets/replset2.js252
-rw-r--r--jstests/replsets/replset3.js130
-rw-r--r--jstests/replsets/replset5.js42
-rw-r--r--jstests/replsets/replset_remove_node.js9
-rw-r--r--jstests/replsets/replsetarb2.js2
-rw-r--r--jstests/replsets/replsetarb3.js144
-rw-r--r--jstests/replsets/replsetfreeze.js105
-rw-r--r--jstests/replsets/rollback.js333
-rw-r--r--jstests/replsets/rollback2.js423
-rwxr-xr-xjstests/replsets/rollback3.js39
-rw-r--r--jstests/replsets/rslib.js63
-rw-r--r--jstests/replsets/slaveDelay2.js104
-rw-r--r--jstests/replsets/slavedelay1.js127
-rw-r--r--jstests/replsets/sync1.js30
-rw-r--r--jstests/replsets/sync_passive.js89
-rw-r--r--jstests/replsets/sync_passive2.js120
-rw-r--r--jstests/replsets/toostale.js121
-rwxr-xr-xjstests/replsets/two_initsync.js1
-rw-r--r--jstests/replsets/twosets.js19
33 files changed, 2739 insertions, 580 deletions
diff --git a/jstests/replsets/auth1.js b/jstests/replsets/auth1.js
new file mode 100644
index 0000000..4945869
--- /dev/null
+++ b/jstests/replsets/auth1.js
@@ -0,0 +1,184 @@
+// check replica set authentication
+
+load("jstests/replsets/rslib.js");
+
+var name = "rs_auth1";
+var port = allocatePorts(4);
+var path = "jstests/replsets/";
+
+
+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);
+
+
+print("should fail with wrong permissions");
+assert.eq(m, 2, "mongod should exit w/ 2: permissions too open");
+stopMongod(port[0]);
+
+
+print("change permissions on #1 & #2");
+run("chmod", "600", path+"key1");
+run("chmod", "600", path+"key2");
+
+
+print("add a user to server0: foo");
+m = startMongodTest( port[0], name+"-0", 0 );
+m.getDB("admin").addUser("foo", "bar");
+m.getDB("test").addUser("bar", "baz");
+print("make sure user is written before shutting down");
+m.getDB("test").getLastError();
+stopMongod(port[0]);
+
+
+print("start up rs");
+var rs = new ReplSetTest({"name" : name, "nodes" : 3, "startPort" : port[0]});
+m = rs.restart(0, {"keyFile" : path+"key1"});
+var s = rs.start(1, {"keyFile" : path+"key1"});
+var s2 = rs.start(2, {"keyFile" : path+"key1"});
+
+var result = m.getDB("admin").auth("foo", "bar");
+assert.eq(result, 1, "login failed");
+result = m.getDB("admin").runCommand({replSetInitiate : rs.getReplSetConfig()});
+assert.eq(result.ok, 1, "couldn't initiate: "+tojson(result));
+
+var master = rs.getMaster().getDB("test");
+wait(function() {
+ var status = master.adminCommand({replSetGetStatus:1});
+ return status.members && status.members[1].state == 2 && status.members[2].state == 2;
+ });
+
+master.foo.insert({x:1});
+master.runCommand({getlasterror:1, w:3, wtimeout:60000});
+
+
+print("try some legal and illegal reads");
+var r = master.foo.findOne();
+assert.eq(r.x, 1);
+
+s.setSlaveOk();
+slave = s.getDB("test");
+
+function doQueryOn(p) {
+ var err = {};
+ try {
+ r = p.foo.findOne();
+ }
+ catch(e) {
+ if (typeof(JSON) != "undefined") {
+ err = JSON.parse(e.substring(6));
+ }
+ else if (e.indexOf("10057") > 0) {
+ err.code = 10057;
+ }
+ }
+ assert.eq(err.code, 10057);
+};
+
+doQueryOn(slave);
+master.adminCommand({logout:1});
+doQueryOn(master);
+
+
+result = slave.auth("bar", "baz");
+assert.eq(result, 1);
+
+r = slave.foo.findOne();
+assert.eq(r.x, 1);
+
+
+print("add some data");
+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});
+
+
+print("fail over");
+rs.stop(0);
+
+wait(function() {
+ function getMaster(s) {
+ var result = s.getDB("admin").runCommand({isMaster: 1});
+ printjson(result);
+ if (result.ismaster) {
+ master = s.getDB("test");
+ return true;
+ }
+ return false;
+ }
+
+ if (getMaster(s) || getMaster(s2)) {
+ return true;
+ }
+ return false;
+ });
+
+
+print("add some more data 1");
+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});
+
+
+print("resync");
+rs.restart(0);
+
+
+print("add some more data 2");
+for (var i=0; i<1000; i++) {
+ master.foo.insert({x:i, foo : "bar"});
+}
+master.runCommand({getlasterror:1, w:3, wtimeout:60000});
+
+
+print("add member with wrong key");
+var conn = new MongodRunner(port[3], "/data/db/"+name+"-3", null, null, ["--replSet","rs_auth1","--rest","--oplogSize","2", "--keyFile", path+"key2"], {no_bind : true});
+conn.start();
+
+
+master.getSisterDB("admin").auth("foo", "bar");
+var config = master.getSisterDB("local").system.replset.findOne();
+config.members.push({_id : 3, host : getHostName()+":"+port[3]});
+config.version++;
+try {
+ master.adminCommand({replSetReconfig:config});
+}
+catch (e) {
+ print("error: "+e);
+}
+reconnect(master);
+master.getSisterDB("admin").auth("foo", "bar");
+
+
+print("shouldn't ever sync");
+for (var i = 0; i<30; i++) {
+ print("iteration: " +i);
+ var results = master.adminCommand({replSetGetStatus:1});
+ printjson(results);
+ assert(results.members[3].state != 2);
+ sleep(1000);
+}
+
+
+print("stop member");
+stopMongod(port[3]);
+
+
+print("start back up with correct key");
+conn = new MongodRunner(port[3], "/data/db/"+name+"-3", null, null, ["--replSet","rs_auth1","--rest","--oplogSize","2", "--keyFile", path+"key1"], {no_bind : true});
+conn.start();
+
+wait(function() {
+ var results = master.adminCommand({replSetGetStatus:1});
+ printjson(results);
+ return results.members[3].state == 2;
+ });
+
diff --git a/jstests/replsets/buildindexes.js b/jstests/replsets/buildindexes.js
new file mode 100644
index 0000000..76de797
--- /dev/null
+++ b/jstests/replsets/buildindexes.js
@@ -0,0 +1,86 @@
+doTest = function( signal ) {
+
+ var name = "buildIndexes";
+ var host = getHostName();
+
+ var replTest = new ReplSetTest( {name: name, nodes: 3} );
+
+ var nodes = replTest.startSet();
+
+ var config = replTest.getReplSetConfig();
+ config.members[2].priority = 0;
+ config.members[2].buildIndexes = false;
+
+ replTest.initiate(config);
+
+ var master = replTest.getMaster().getDB(name);
+ var slaveConns = replTest.liveNodes.slaves;
+ var slave = [];
+ for (var i in slaveConns) {
+ slaveConns[i].setSlaveOk();
+ slave.push(slaveConns[i].getDB(name));
+ }
+ replTest.awaitReplication();
+
+ print("creating an index on x");
+ master.x.ensureIndex({y : 1});
+ printjson(master.x.stats());
+
+ for (var i=0; i<100; i++) {
+ master.x.insert({x:1,y:"abc",c:1});
+ }
+
+ replTest.awaitReplication();
+
+ printjson(slave[0].runCommand({count: "x"}));
+ var ns = master.x+"";
+ print("namespace: "+ns);
+
+ // can't query system.indexes from slave, so we'll look at coll.stats()
+ printjson(slave[0].adminCommand({replSetGetStatus:1}));
+ printjson(slave[0].getSisterDB("local").system.replset.findOne());
+ printjson(master.stats());
+ printjson(slave[0].stats());
+ printjson(slave[1].stats());
+ printjson(master.x.stats());
+ printjson(slave[0].x.stats());
+ printjson(slave[1].x.stats());
+ print("sleeping");
+ sleep(20000);
+ var indexes = slave[0].stats().indexes;
+ assert.eq(indexes, 2, 'number of indexes');
+
+ indexes = slave[1].stats().indexes;
+ assert.eq(indexes, 1);
+
+
+ indexes = slave[0].x.stats().indexSizes;
+ printjson(indexes);
+
+ var count = 0;
+ for (var i in indexes) {
+ count++;
+ if (i == "_id_") {
+ continue;
+ }
+ print(i);
+ print(i.match(/y_/));
+ assert(i.match(/y_/));
+ }
+
+ assert.eq(count, 2);
+
+ indexes = slave[1].x.stats().indexSizes;
+ printjson(indexes);
+
+ count = 0;
+ for (var i in indexes) {
+ count++;
+ }
+
+ assert.eq(count, 1);
+
+ replTest.stopSet(15);
+}
+
+doTest(15);
diff --git a/jstests/replsets/cloneDb.js b/jstests/replsets/cloneDb.js
new file mode 100644
index 0000000..6d2d0f3
--- /dev/null
+++ b/jstests/replsets/cloneDb.js
@@ -0,0 +1,52 @@
+// Test for cloning a db from a replica set [SERVER-1643] -Tony
+
+load('jstests/libs/grid.js')
+
+doTest = function( signal ) {
+
+ var N = 2000
+
+ // ~1KB string
+ var Text = ''
+ for (var i = 0; i < 40; i++)
+ Text += 'abcdefghijklmnopqrstuvwxyz'
+
+ // Create replica set
+ var repset = new ReplicaSet ('testSet', 3) .begin()
+ var master = repset.getMaster()
+ var db1 = master.getDB('test')
+
+ // 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
+ var solo = new Server ('singleTarget')
+ var soloConn = solo.begin()
+ var db2 = soloConn.getDB('test')
+
+ // Clone db from replica set to single server
+ db2.cloneDatabase (repset.getURL())
+
+ // Confirm clone worked
+ assert.eq (Text, db2['foo'] .findOne({x: N-1}) ['text'], 'cloneDatabase failed (test1)')
+
+ // Now test the reverse direction
+ db1 = master.getDB('test2')
+ db2 = soloConn.getDB('test2')
+ for (var i = 0; i < N; i++) {
+ db2['foo'].insert({x: i, text: Text})
+ db2.getLastError()
+ }
+ db1.cloneDatabase (solo.host())
+ assert.eq (Text, db2['foo'] .findOne({x: N-1}) ['text'], 'cloneDatabase failed (test2)')
+
+ // Shut down replica set and single server
+ solo.end()
+ repset.stopSet( signal )
+}
+
+doTest( 15 );
+print("replsets/cloneDb.js SUCCESS");
diff --git a/jstests/replsets/config1.js b/jstests/replsets/config1.js
new file mode 100644
index 0000000..748ce8f
--- /dev/null
+++ b/jstests/replsets/config1.js
@@ -0,0 +1,21 @@
+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/fastsync.js b/jstests/replsets/fastsync.js
new file mode 100644
index 0000000..d7c3905
--- /dev/null
+++ b/jstests/replsets/fastsync.js
@@ -0,0 +1,117 @@
+/*
+ * 1. insert 100000 objects
+ * 2. export to two dbpaths
+ * 3. add one node w/fastsync
+ * 4. check that we never get "errmsg" : "initial sync cloning db: whatever"
+ * 5. check writes are replicated
+ */
+
+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;
+ }
+ });
+};
+
+ports = allocatePorts( 3 );
+
+var basename = "jstests_fastsync";
+var basePath = "/data/db/" + basename;
+var hostname = getHostName();
+
+var pargs = new MongodRunner( ports[ 0 ], basePath + "-p", false, false,
+ ["--replSet", basename, "--oplogSize", 2],
+ {no_bind : true} );
+p = pargs.start();
+
+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]}]};
+printjson(config);
+var result = admin.runCommand({replSetInitiate : config});
+print("result:");
+printjson(result);
+
+var count = 0;
+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; });
+
+print("1");
+for (var i=0; i<100000; i++) {
+ foo.bar.insert({date : new Date(), x : i, str : "all the talk on the market"});
+}
+print("total in foo: "+foo.bar.count());
+
+
+print("2");
+admin.runCommand( {fsync:1,lock:1} );
+copyDbpath( basePath + "-p", basePath + "-s" );
+admin.$cmd.sys.unlock.findOne();
+
+
+print("3");
+var sargs = new MongodRunner( ports[ 1 ], basePath + "-s", false, false,
+ ["--replSet", basename, "--fastsync",
+ "--oplogSize", 2], {no_bind : true} );
+var reuseData = true;
+sargs.start(reuseData);
+
+config = local.system.replset.findOne();
+config.version++;
+config.members.push({_id:1, host:hostname+":"+ports[1]});
+
+result = admin.runCommand({replSetReconfig : config});
+assert(result.ok, "reconfig worked");
+reconnect(p);
+
+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[1].state, 2);
diff --git a/jstests/replsets/getlasterror_w2.js b/jstests/replsets/getlasterror_w2.js
new file mode 100644
index 0000000..795e667
--- /dev/null
+++ b/jstests/replsets/getlasterror_w2.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/groupAndMapReduce.js b/jstests/replsets/groupAndMapReduce.js
new file mode 100644
index 0000000..539fe44
--- /dev/null
+++ b/jstests/replsets/groupAndMapReduce.js
@@ -0,0 +1,105 @@
+doTest = function( signal ) {
+
+ // Test basic replica set functionality.
+ // -- Replication
+ // -- Failover
+
+ // Replica set testing API
+ // Create a new replica set test. Specify set name and the number of nodes you want.
+ var replTest = new ReplSetTest( {name: 'testSet', nodes: 3} );
+
+ // call startSet() to start each mongod in the replica set
+ // this returns a list of nodes
+ var nodes = replTest.startSet();
+
+ // Call initiate() to send the replSetInitiate command
+ // This will wait for initiation
+ replTest.initiate();
+
+ // Call getMaster to return a reference to the node that's been
+ // elected master.
+ var master = replTest.getMaster();
+
+ // save some records
+ var len = 100
+ for (var i = 0; i < len; ++i) {
+ master.getDB("foo").foo.save({a: i});
+ }
+
+ // This method will check the oplogs of the master
+ // and slaves in the set and wait until the change has replicated.
+ replTest.awaitReplication();
+ print("Sleeping 10s for slaves to go to secondary state");
+ sleep(10000);
+
+ slaves = replTest.liveNodes.slaves;
+ assert( slaves.length == 2, "Expected 2 slaves but length was " + slaves.length );
+ slaves.forEach(function(slave) {
+ // try to read from slave
+ slave.slaveOk = true;
+ var count = slave.getDB("foo").foo.count();
+ printjson( count );
+ assert.eq( len , count , "slave count wrong: " + slave );
+
+ print("Doing a findOne to verify we can get a row");
+ var one = slave.getDB("foo").foo.findOne();
+ printjson(one);
+
+// stats = slave.getDB("foo").adminCommand({replSetGetStatus:1});
+// printjson(stats);
+
+ print("Calling group() with slaveOk=true, must succeed");
+ slave.slaveOk = true;
+ count = slave.getDB("foo").foo.group({initial: {n:0}, reduce: function(obj,out){out.n++;}});
+ printjson( count );
+ assert.eq( len , count[0].n , "slave group count wrong: " + slave );
+
+ print("Calling group() with slaveOk=false, must fail");
+ slave.slaveOk = false;
+ try {
+ count = slave.getDB("foo").foo.group({initial: {n:0}, reduce: function(obj,out){out.n++;}});
+ assert(false, "group() succeeded with slaveOk=false");
+ } catch (e) {
+ print("Received exception: " + e);
+ }
+
+ print("Calling inline mr() with slaveOk=true, must succeed");
+ slave.slaveOk = true;
+ map = function() { emit(this.a, 1); };
+ reduce = function(key, vals) { var sum = 0; for (var i = 0; i < vals.length; ++i) { sum += vals[i]; } return sum; };
+ slave.getDB("foo").foo.mapReduce(map, reduce, {out: { "inline" : 1}});
+
+ print("Calling mr() to collection with slaveOk=true, must fail");
+ try {
+ slave.getDB("foo").foo.mapReduce(map, reduce, "output");
+ assert(false, "mapReduce() to collection succeeded on slave");
+ } catch (e) {
+ print("Received exception: " + e);
+ }
+
+ print("Calling inline mr() with slaveOk=false, must fail");
+ slave.slaveOk = false;
+ try {
+ slave.getDB("foo").foo.mapReduce(map, reduce, {out: { "inline" : 1}});
+ assert(false, "mapReduce() succeeded on slave with slaveOk=false");
+ } catch (e) {
+ print("Received exception: " + e);
+ }
+ print("Calling mr() to collection with slaveOk=false, must fail");
+ try {
+ slave.getDB("foo").foo.mapReduce(map, reduce, "output");
+ assert(false, "mapReduce() to collection succeeded on slave with slaveOk=false");
+ } catch (e) {
+ print("Received exception: " + e);
+ }
+
+ });
+
+
+
+ // Shut down the set and finish the test.
+ replTest.stopSet( signal );
+}
+
+doTest( 15 );
+print("SUCCESS");
diff --git a/jstests/replsets/initial_sync1.js b/jstests/replsets/initial_sync1.js
new file mode 100644
index 0000000..ee30b4e
--- /dev/null
+++ b/jstests/replsets/initial_sync1.js
@@ -0,0 +1,129 @@
+/**
+ * Test killing the secondary during initially sync
+ *
+ * 1. Bring up set
+ * 2. Insert some data
+ * 4. Make sure synced
+ * 5. Freeze #2
+ * 6. Bring up #3
+ * 7. Kill #2 in the middle of syncing
+ * 8. Eventually it should become a secondary
+ * 9. Bring #2 back up
+ * 10. Insert some stuff
+ * 11. Everyone happy eventually
+ */
+
+load("jstests/replsets/rslib.js");
+var basename = "jstests_initsync1";
+
+
+print("1. Bring up set");
+var replTest = new ReplSetTest( {name: basename, nodes: 2} );
+var conns = replTest.startSet();
+replTest.initiate();
+
+var master = replTest.getMaster();
+var foo = master.getDB("foo");
+var admin = master.getDB("admin");
+
+var slave1 = replTest.liveNodes.slaves[0];
+var admin_s1 = slave1.getDB("admin");
+var local_s1 = slave1.getDB("local");
+
+print("2. Insert some data");
+for (var i=0; i<10000; i++) {
+ foo.bar.insert({date : new Date(), x : i, str : "all the talk on the market"});
+}
+print("total in foo: "+foo.bar.count());
+
+
+print("4. Make sure synced");
+replTest.awaitReplication();
+
+
+print("5. Freeze #2");
+admin_s1.runCommand({replSetFreeze:999999});
+
+
+print("6. Bring up #3");
+var ports = allocatePorts( 3 );
+var basePath = "/data/db/" + basename;
+var hostname = getHostName();
+
+var sargs = new MongodRunner( ports[ 2 ], basePath, false, false,
+ ["--replSet", basename, "--oplogSize", 2],
+ {no_bind : true} );
+var slave2 = sargs.start();
+var local_s2 = slave2.getDB("local");
+var admin_s2 = slave2.getDB("admin");
+
+var config = replTest.getReplSetConfig();
+config.version = 2;
+config.members.push({_id:2, host:hostname+":"+ports[2]});
+
+try {
+ admin.runCommand({replSetReconfig:config});
+}
+catch(e) {
+ print(e);
+}
+reconnect(slave1);
+reconnect(slave2);
+
+wait(function() {
+ var config2 = local_s1.system.replset.findOne();
+ var config3 = local_s2.system.replset.findOne();
+
+ printjson(config2);
+ printjson(config3);
+
+ return config2.version == config.version &&
+ (config3 && config3.version == config.version);
+ });
+
+wait(function() {
+ var status = admin_s2.runCommand({replSetGetStatus:1});
+ printjson(status);
+ return status.members &&
+ (status.members[2].state == 3 || status.members[2].state == 2);
+ });
+
+
+print("7. Kill #2 in the middle of syncing");
+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;
+ });
+
+
+print("9. Bring #2 back up");
+replTest.start(1, {}, true);
+reconnect(slave1);
+wait(function() {
+ var status = admin_s1.runCommand({replSetGetStatus:1});
+ printjson(status);
+ return status.ok == 1 && status.members &&
+ status.members[1].state == 2 || status.members[1].state == 1;
+ });
+
+
+/**
+ * TODO: this fails on buildbot
+ * see SERVER-2550
+print("10. Insert some stuff");
+master = replTest.getMaster();
+for (var i=0; i<10000; i++) {
+ foo.bar.insert({date : new Date(), x : i, str : "all the talk on the market"});
+}
+
+
+print("11. Everyone happy eventually");
+replTest.awaitReplication();
+*/
diff --git a/jstests/replsets/initial_sync2.js b/jstests/replsets/initial_sync2.js
new file mode 100644
index 0000000..3ad3972
--- /dev/null
+++ b/jstests/replsets/initial_sync2.js
@@ -0,0 +1,179 @@
+/**
+ * Test killing the primary during initial sync
+ * and don't allow the other secondary to become primary
+ *
+ * 1. Bring up set
+ * 2. Insert some data
+ * 4. Make sure synced
+ * 5. Freeze #2
+ * 6. Bring up #3
+ * 7. Kill #1 in the middle of syncing
+ * 8. Check that #3 makes it into secondary state
+ * 9. Bring #1 back up
+ * 10. Initial sync should succeed
+ * 11. Insert some stuff
+ * 12. Everyone happy eventually
+ */
+
+load("jstests/replsets/rslib.js");
+var basename = "jstests_initsync2";
+
+var doTest = function() {
+
+print("1. Bring up set");
+var replTest = new ReplSetTest( {name: basename, nodes: 2} );
+var conns = replTest.startSet();
+replTest.initiate();
+
+var master = replTest.getMaster();
+var origMaster = master;
+var foo = master.getDB("foo");
+var admin = master.getDB("admin");
+
+var slave1 = replTest.liveNodes.slaves[0];
+var admin_s1 = slave1.getDB("admin");
+var local_s1 = slave1.getDB("local");
+
+print("2. Insert some data");
+for (var i=0; i<10000; i++) {
+ foo.bar.insert({date : new Date(), x : i, str : "all the talk on the market"});
+}
+print("total in foo: "+foo.bar.count());
+
+
+print("4. Make sure synced");
+replTest.awaitReplication();
+
+
+print("5. Freeze #2");
+admin_s1.runCommand({replSetFreeze:999999});
+
+
+print("6. Bring up #3");
+var ports = allocatePorts( 3 );
+var basePath = "/data/db/" + basename;
+var hostname = getHostName();
+
+var sargs = new MongodRunner( ports[ 2 ], basePath, false, false,
+ ["--replSet", basename, "--oplogSize", 2],
+ {no_bind : true} );
+var slave2 = sargs.start();
+var local_s2 = slave2.getDB("local");
+var admin_s2 = slave2.getDB("admin");
+
+var config = replTest.getReplSetConfig();
+config.version = 2;
+config.members.push({_id:2, host:hostname+":"+ports[2]});
+
+try {
+ admin.runCommand({replSetReconfig:config});
+}
+catch(e) {
+ print(e);
+}
+reconnect(slave1);
+reconnect(slave2);
+
+wait(function() {
+ var config2 = local_s1.system.replset.findOne();
+ var config3 = local_s2.system.replset.findOne();
+
+ printjson(config2);
+ printjson(config3);
+
+ return config2.version == config.version &&
+ (config3 && config3.version == config.version);
+ });
+admin_s2.runCommand({replSetFreeze:999999});
+
+
+wait(function() {
+ var status = admin_s2.runCommand({replSetGetStatus:1});
+ printjson(status);
+ return status.members &&
+ (status.members[2].state == 3 || status.members[2].state == 2);
+ });
+
+
+print("7. Kill #1 in the middle of syncing");
+replTest.stop(0);
+
+
+print("8. Check that #3 makes it into secondary state");
+wait(function() {
+ var status = admin_s2.runCommand({replSetGetStatus:1});
+ occasionally(function() { printjson(status);}, 10);
+ if (status.members[2].state == 2 || status.members[2].state == 1) {
+ return true;
+ }
+ return false;
+ });
+
+
+print("9. Bring #1 back up");
+replTest.start(0, {}, true);
+reconnect(master);
+wait(function() {
+ var status = admin.runCommand({replSetGetStatus:1});
+ printjson(status);
+ return status.members &&
+ (status.members[0].state == 1 || status.members[0].state == 2);
+ });
+
+
+print("10. Initial sync should succeed");
+wait(function() {
+ var status = admin_s2.runCommand({replSetGetStatus:1});
+ printjson(status);
+ return status.members &&
+ status.members[2].state == 2 || status.members[2].state == 1;
+ });
+
+
+print("11. Insert some stuff");
+// ReplSetTest doesn't find master correctly unless all nodes are defined by
+// ReplSetTest
+for (var i = 0; i<30; i++) {
+ var result = admin.runCommand({isMaster : 1});
+ if (result.ismaster) {
+ break;
+ }
+ else if (result.primary) {
+ master = connect(result.primary+"/admin").getMongo();
+ break;
+ }
+ sleep(1000);
+}
+
+for (var i=0; i<10000; i++) {
+ foo.bar.insert({date : new Date(), x : i, str : "all the talk on the market"});
+}
+
+
+print("12. Everyone happy eventually");
+// if 3 is master...
+if (master+"" != origMaster+"") {
+ print("3 is master");
+ slave2 = origMaster;
+}
+
+wait(function() {
+ var op1 = getLatestOp(master);
+ var op2 = getLatestOp(slave1);
+ var op3 = getLatestOp(slave2);
+
+ occasionally(function() {
+ print("latest ops:");
+ printjson(op1);
+ printjson(op2);
+ printjson(op3);
+ });
+
+ return friendlyEqual(getLatestOp(master), getLatestOp(slave1)) &&
+ friendlyEqual(getLatestOp(master), getLatestOp(slave2));
+ });
+
+replTest.stopSet();
+};
+
+doTest();
diff --git a/jstests/replsets/initial_sync3.js b/jstests/replsets/initial_sync3.js
new file mode 100644
index 0000000..471aa16
--- /dev/null
+++ b/jstests/replsets/initial_sync3.js
@@ -0,0 +1,87 @@
+/* test initial sync options
+ *
+ * {state : 1}
+ * {state : 2}
+ * {name : host+":"+port}
+ * {_id : 2}
+ * {optime : now}
+ * {optime : 1970}
+ */
+
+load("jstests/replsets/rslib.js");
+var name = "initialsync3";
+var host = getHostName();
+var port = allocatePorts(7);
+
+print("Start set with three nodes");
+var replTest = new ReplSetTest( {name: name, nodes: 7} );
+var nodes = replTest.startSet();
+replTest.initiate({
+ _id : name,
+ members : [
+ {_id:0, host : host+":"+port[0]},
+ {_id:1, host : host+":"+port[1], initialSync : {state : 1}},
+ {_id:2, host : host+":"+port[2], initialSync : {state : 2}},
+ {_id:3, host : host+":"+port[3], initialSync : {name : host+":"+port[2]}},
+ {_id:4, host : host+":"+port[4], initialSync : {_id : 2}},
+ {_id:5, host : host+":"+port[5], initialSync : {optime : new Date()}},
+ {_id:6, host : host+":"+port[6], initialSync : {optime : new Date(0)}}
+ ]});
+
+var master = replTest.getMaster();
+
+print("Initial sync");
+master.getDB("foo").bar.baz.insert({x:1});
+
+print("Make sure everyone's secondary");
+wait(function() {
+ var status = master.getDB("admin").runCommand({replSetGetStatus:1});
+ occasionally(function() {
+ printjson(status);
+ });
+
+ 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();
+
+replTest.stopSet();
+
+print("reconfig");
+
+var rs2 = new ReplSetTest( {name: 'reconfig-isync3', nodes: 3} );
+rs2.startSet();
+rs2.initiate();
+
+master = rs2.getMaster();
+var config = master.getDB("local").system.replset.findOne();
+config.version++;
+config.members[0].initialSync = {state : 2};
+config.members[1].initialSync = {state : 1};
+try {
+ master.getDB("admin").runCommand({replSetReconfig : config});
+}
+catch(e) {
+ print("trying to reconfigure: "+e);
+}
+
+master = rs2.getMaster();
+config = master.getDB("local").system.replset.findOne();
+
+assert(typeof(config.members[0].initialSync) == "object");
+assert.eq(config.members[0].initialSync.state, 2);
+assert.eq(config.members[1].initialSync.state, 1);
+
+rs2.stopSet();
+
+print("initialSync3 success!");
diff --git a/jstests/replsets/ismaster1.js b/jstests/replsets/ismaster1.js
new file mode 100644
index 0000000..22865e5
--- /dev/null
+++ b/jstests/replsets/ismaster1.js
@@ -0,0 +1,36 @@
+/**
+ * 1. Check passive field in isMaster
+ */
+
+load("jstests/replsets/rslib.js");
+
+var name = "ismaster";
+var host = getHostName();
+
+var replTest = new ReplSetTest( {name: name, nodes: 3} );
+
+var nodes = replTest.startSet();
+
+var config = replTest.getReplSetConfig();
+config.members[1].priority = 0;
+config.members[2].priority = 0;
+
+replTest.initiate(config);
+
+var master = replTest.getMaster();
+wait(function() {
+ var result = master.getDB("admin").runCommand({replSetGetStatus:1});
+ return result.members && result.members[0].state == 1 &&
+ result.members[1].state == 2 && result.members[2].state == 2;
+ });
+
+var result = master.getDB("admin").runCommand({isMaster:1});
+assert(!('passive' in result), tojson(result));
+
+result = replTest.liveNodes.slaves[0].getDB("admin").runCommand({isMaster:1});
+assert('passive' in result, tojson(result));
+
+result = replTest.liveNodes.slaves[1].getDB("admin").runCommand({isMaster:1});
+assert('passive' in result, tojson(result));
+
+replTest.stopSet();
diff --git a/jstests/replsets/key1 b/jstests/replsets/key1
new file mode 100644
index 0000000..b5c19e4
--- /dev/null
+++ b/jstests/replsets/key1
@@ -0,0 +1 @@
+foop de doop
diff --git a/jstests/replsets/key2 b/jstests/replsets/key2
new file mode 100644
index 0000000..cbde821
--- /dev/null
+++ b/jstests/replsets/key2
@@ -0,0 +1 @@
+other key
diff --git a/jstests/replsets/remove1.js b/jstests/replsets/remove1.js
new file mode 100644
index 0000000..ebd17d6
--- /dev/null
+++ b/jstests/replsets/remove1.js
@@ -0,0 +1,132 @@
+/* test removing a node from a replica set
+ *
+ * Start set with three nodes
+ * Initial sync
+ * Remove slave1
+ * Remove slave2
+ * Bring slave1 back up
+ * Bring slave2 back up
+ * Add them back as slave
+ * Make sure everyone's secondary
+ */
+
+load("jstests/replsets/rslib.js");
+var name = "removeNodes";
+var host = getHostName();
+
+
+print("Start set with three nodes");
+var replTest = new ReplSetTest( {name: name, nodes: 3} );
+var nodes = replTest.startSet();
+replTest.initiate();
+var master = replTest.getMaster();
+
+
+print("Initial sync");
+master.getDB("foo").bar.baz.insert({x:1});
+
+replTest.awaitReplication();
+
+
+print("Remove slave2");
+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");
+config.members.push({_id:1, host : host+":"+replTest.getPort(1)});
+config.members.push({_id:2, host : host+":"+replTest.getPort(2)});
+config.version = 4;
+wait(function() {
+ try {
+ master.getDB("admin").runCommand({replSetReconfig:config});
+ }
+ catch(e) {
+ print(e);
+ }
+ reconnect(master);
+
+ master.setSlaveOk();
+ var newConfig = master.getDB("local").system.replset.findOne();
+ return newConfig.version == 4;
+ });
+
+
+print("Make sure everyone's secondary");
+wait(function() {
+ var status = master.getDB("admin").runCommand({replSetGetStatus:1});
+ occasionally(function() {
+ printjson(status);
+ });
+
+ if (!status.members || status.members.length != 3) {
+ return false;
+ }
+
+ for (var i = 0; i<3; i++) {
+ if (status.members[i].state != 1 && status.members[i].state != 2) {
+ return false;
+ }
+ }
+ return true;
+ });
+
+replTest.stopSet();
+
diff --git a/jstests/replsets/replset2.js b/jstests/replsets/replset2.js
index f18b467..4849620 100644
--- a/jstests/replsets/replset2.js
+++ b/jstests/replsets/replset2.js
@@ -1,126 +1,126 @@
-print("\n\nreplset2.js BEGIN");
-
-doTest = function (signal) {
-
- // FAILING TEST
- // See below:
-
- // Test replication with getLastError
-
- // Replica set testing API
- // Create a new replica set test. Specify set name and the number of nodes you want.
- var replTest = new ReplSetTest({ name: 'testSet', nodes: 3, oplogSize: 5 });
-
- // call startSet() to start each mongod in the replica set
- // this returns a list of nodes
- var nodes = replTest.startSet();
-
- // Call initiate() to send the replSetInitiate command
- // This will wait for initiation
- replTest.initiate();
-
- var testDB = "repl-test";
-
- // Call getMaster to return a reference to the node that's been
- // elected master.
- var master = replTest.getMaster();
-
- // Wait for replication to a single node
- master.getDB(testDB).bar.insert({ n: 1 });
-
- // Wait for initial sync
- replTest.awaitReplication();
-
- var slaves = replTest.liveNodes.slaves;
- slaves.forEach(function (slave) { slave.setSlaveOk(); });
-
- var failed = false;
- var callGetLastError = function (w, timeout, db) {
- try {
- var result = master.getDB(db).getLastErrorObj(w, timeout);
- print("replset2.js getLastError result: " + tojson(result));
- if (result['ok'] != 1) {
- print("replset2.js FAILURE getlasterror not ok");
- failed = true;
- }
- }
- catch (e) {
- print("\nreplset2.js exception in getLastError: " + e + '\n');
- throw e;
- }
- }
-
- // Test getlasterror with multiple inserts
- // TEST FAILS HEREg
- print("\n\nreplset2.js **** Try inserting a multiple records -- first insert ****")
-
- printjson(master.getDB("admin").runCommand("replSetGetStatus"));
-
- master.getDB(testDB).foo.insert({ n: 1 });
- master.getDB(testDB).foo.insert({ n: 2 });
- master.getDB(testDB).foo.insert({ n: 3 });
-
- print("\nreplset2.js **** TEMP 1 ****")
-
- printjson(master.getDB("admin").runCommand("replSetGetStatus"));
-
- callGetLastError(3, 25000, testDB);
-
- print("replset2.js **** TEMP 1a ****")
-
- m1 = master.getDB(testDB).foo.findOne({ n: 1 });
- printjson(m1);
- assert(m1['n'] == 1, "replset2.js Failed to save to master on multiple inserts");
-
- print("replset2.js **** TEMP 1b ****")
-
- var s0 = slaves[0].getDB(testDB).foo.findOne({ n: 1 });
- assert(s0['n'] == 1, "replset2.js Failed to replicate to slave 0 on multiple inserts");
-
- var s1 = slaves[1].getDB(testDB).foo.findOne({ n: 1 });
- assert(s1['n'] == 1, "replset2.js Failed to replicate to slave 1 on multiple inserts");
-
- // Test getlasterror with a simple insert
- print("replset2.js **** Try inserting a single record ****")
- master.getDB(testDB).dropDatabase();
- master.getDB(testDB).foo.insert({ n: 1 });
- callGetLastError(3, 10000, testDB);
-
- m1 = master.getDB(testDB).foo.findOne({ n: 1 });
- printjson(m1);
- assert(m1['n'] == 1, "replset2.js Failed to save to master");
-
- s0 = slaves[0].getDB(testDB).foo.findOne({ n: 1 });
- assert(s0['n'] == 1, "replset2.js Failed to replicate to slave 0");
-
- s1 = slaves[1].getDB(testDB).foo.findOne({ n: 1 });
- assert(s1['n'] == 1, "replset2.js Failed to replicate to slave 1");
-
- // Test getlasterror with large insert
- print("replset2.js **** Try inserting many records ****")
+print("\n\nreplset2.js BEGIN");
+
+doTest = function (signal) {
+
+ // FAILING TEST
+ // See below:
+
+ // Test replication with getLastError
+
+ // Replica set testing API
+ // Create a new replica set test. Specify set name and the number of nodes you want.
+ var replTest = new ReplSetTest({ name: 'testSet', nodes: 3, oplogSize: 5 });
+
+ // call startSet() to start each mongod in the replica set
+ // this returns a list of nodes
+ var nodes = replTest.startSet();
+
+ // Call initiate() to send the replSetInitiate command
+ // This will wait for initiation
+ replTest.initiate();
+
+ var testDB = "repl-test";
+
+ // Call getMaster to return a reference to the node that's been
+ // elected master.
+ var master = replTest.getMaster();
+
+ // Wait for replication to a single node
+ master.getDB(testDB).bar.insert({ n: 1 });
+
+ // Wait for initial sync
+ replTest.awaitReplication();
+
+ var slaves = replTest.liveNodes.slaves;
+ slaves.forEach(function (slave) { slave.setSlaveOk(); });
+
+ var failed = false;
+ var callGetLastError = function (w, timeout, db) {
+ try {
+ var result = master.getDB(db).getLastErrorObj(w, timeout);
+ print("replset2.js getLastError result: " + tojson(result));
+ if (result['ok'] != 1) {
+ print("replset2.js FAILURE getlasterror not ok");
+ failed = true;
+ }
+ }
+ catch (e) {
+ print("\nreplset2.js exception in getLastError: " + e + '\n');
+ throw e;
+ }
+ }
+
+ // Test getlasterror with multiple inserts
+ // TEST FAILS HEREg
+ print("\n\nreplset2.js **** Try inserting a multiple records -- first insert ****")
+
+ printjson(master.getDB("admin").runCommand("replSetGetStatus"));
+
+ master.getDB(testDB).foo.insert({ n: 1 });
+ master.getDB(testDB).foo.insert({ n: 2 });
+ master.getDB(testDB).foo.insert({ n: 3 });
+
+ print("\nreplset2.js **** TEMP 1 ****")
+
+ printjson(master.getDB("admin").runCommand("replSetGetStatus"));
+
+ callGetLastError(3, 25000, testDB);
+
+ print("replset2.js **** TEMP 1a ****")
+
+ m1 = master.getDB(testDB).foo.findOne({ n: 1 });
+ printjson(m1);
+ assert(m1['n'] == 1, "replset2.js Failed to save to master on multiple inserts");
+
+ print("replset2.js **** TEMP 1b ****")
+
+ var s0 = slaves[0].getDB(testDB).foo.findOne({ n: 1 });
+ assert(s0['n'] == 1, "replset2.js Failed to replicate to slave 0 on multiple inserts");
+
+ var s1 = slaves[1].getDB(testDB).foo.findOne({ n: 1 });
+ assert(s1['n'] == 1, "replset2.js Failed to replicate to slave 1 on multiple inserts");
+
+ // Test getlasterror with a simple insert
+ print("replset2.js **** Try inserting a single record ****")
+ master.getDB(testDB).dropDatabase();
+ master.getDB(testDB).foo.insert({ n: 1 });
+ callGetLastError(3, 10000, testDB);
+
+ m1 = master.getDB(testDB).foo.findOne({ n: 1 });
+ printjson(m1);
+ assert(m1['n'] == 1, "replset2.js Failed to save to master");
+
+ s0 = slaves[0].getDB(testDB).foo.findOne({ n: 1 });
+ assert(s0['n'] == 1, "replset2.js Failed to replicate to slave 0");
+
+ s1 = slaves[1].getDB(testDB).foo.findOne({ n: 1 });
+ assert(s1['n'] == 1, "replset2.js Failed to replicate to slave 1");
+
+ // Test getlasterror with large insert
+ print("replset2.js **** Try inserting many records ****")
try {
- bigData = new Array(2000).toString()
- for (var n = 0; n < 1000; n++) {
- master.getDB(testDB).baz.insert({ n: n, data: bigData });
- }
- callGetLastError(3, 60000, testDB);
-
- print("replset2.js **** V1 ")
-
- var verifyReplication = function (nodeName, collection) {
- data = collection.findOne({ n: 1 });
- assert(data['n'] == 1, "replset2.js Failed to save to " + nodeName);
- data = collection.findOne({ n: 999 });
- assert(data['n'] == 999, "replset2.js Failed to save to " + nodeName);
- }
-
- print("replset2.js **** V2 ")
-
- verifyReplication("master", master.getDB(testDB).baz);
- verifyReplication("slave 0", slaves[0].getDB(testDB).baz);
- verifyReplication("slave 1", slaves[1].getDB(testDB).baz);
-
- assert(failed == false, "replset2.js Replication with getLastError failed. See errors.");
+ bigData = new Array(2000).toString()
+ for (var n = 0; n < 1000; n++) {
+ master.getDB(testDB).baz.insert({ n: n, data: bigData });
+ }
+ callGetLastError(3, 60000, testDB);
+
+ print("replset2.js **** V1 ")
+
+ var verifyReplication = function (nodeName, collection) {
+ data = collection.findOne({ n: 1 });
+ assert(data['n'] == 1, "replset2.js Failed to save to " + nodeName);
+ data = collection.findOne({ n: 999 });
+ assert(data['n'] == 999, "replset2.js Failed to save to " + nodeName);
+ }
+
+ print("replset2.js **** V2 ")
+
+ verifyReplication("master", master.getDB(testDB).baz);
+ verifyReplication("slave 0", slaves[0].getDB(testDB).baz);
+ verifyReplication("slave 1", slaves[1].getDB(testDB).baz);
+
+ assert(failed == false, "replset2.js Replication with getLastError failed. See errors.");
}
catch(e) {
print("ERROR: " + e);
@@ -132,10 +132,10 @@ doTest = function (signal) {
printjson(slaves[1].getDB("local").oplog.rs.find().sort({"$natural": -1}).limit(1).next());
}
-
- replTest.stopSet(signal);
+
+ replTest.stopSet(signal);
}
-doTest( 15 );
-
+doTest( 15 );
+
print("\nreplset2.js SUCCESS\n");
diff --git a/jstests/replsets/replset3.js b/jstests/replsets/replset3.js
index 8126b9d..faa0627 100644
--- a/jstests/replsets/replset3.js
+++ b/jstests/replsets/replset3.js
@@ -1,56 +1,80 @@
-
-doTest = function( signal ) {
-
- // Test replica set step down
-
- // Replica set testing API
- // Create a new replica set test. Specify set name and the number of nodes you want.
- var replTest = new ReplSetTest( {name: 'testSet', nodes: 3} );
-
- // call startSet() to start each mongod in the replica set
- // this returns a list of nodes
- var nodes = replTest.startSet();
-
- // Call initiate() to send the replSetInitiate command
- // This will wait for initiation
- replTest.initiate();
-
- // Get master node
- var master = replTest.getMaster();
-
- // Write some data to master
- // NOTE: this test fails unless we write some data.
- master.getDB("foo").foo.save({a: 1});
- master.getDB("foo").runCommand({getlasterror: 1, w:3, wtimeout: 20000});
-
- // Step down master
- master.getDB("admin").runCommand({replSetStepDown: true});
-
- try {
- var new_master = replTest.getMaster();
- }
- catch( err ) {
- throw( "Could not elect new master before timeout." );
- }
-
- assert( master != new_master, "Old master shouldn't be equal to new master." );
-
- // Make sure that slaves are still up
- var result = new_master.getDB("admin").runCommand({replSetGetStatus: 1});
- assert( result['ok'] == 1, "Could not verify that slaves were still up:" + result );
-
- slaves = replTest.liveNodes.slaves;
- assert.soon(function() {
- res = slaves[0].getDB("admin").runCommand({replSetGetStatus: 1})
- return res.myState == 2;
- }, "Slave 0 state not ready.");
-
- assert.soon(function() {
- res = slaves[1].getDB("admin").runCommand({replSetGetStatus: 1})
- return res.myState == 2;
- }, "Slave 1 state not ready.");
-
- replTest.stopSet( 15 );
+
+doTest = function (signal) {
+
+ // Test replica set step down
+
+ // Replica set testing API
+ // Create a new replica set test. Specify set name and the number of nodes you want.
+ var replTest = new ReplSetTest({ name: 'testSet', nodes: 3 });
+
+ // call startSet() to start each mongod in the replica set
+ // this returns a list of nodes
+ var nodes = replTest.startSet();
+
+ // Call initiate() to send the replSetInitiate command
+ // This will wait for initiation
+ replTest.initiate();
+
+ // Get master node
+ var master = replTest.getMaster();
+
+ // Write some data to master
+ // NOTE: this test fails unless we write some data.
+ master.getDB("foo").foo.save({ a: 1 });
+ master.getDB("foo").runCommand({ getlasterror: 1, w: 3, wtimeout: 20000 });
+
+ var phase = 1;
+
+ print(phase++);
+
+ // Step down master. Note: this may close our connection!
+ try {
+ master.getDB("admin").runCommand({ replSetStepDown: true });
+ } catch (err) {
+ print("caught: " + err + " on stepdown");
+ }
+
+ print(phase++);
+
+ try {
+ var new_master = replTest.getMaster();
+ }
+ catch (err) {
+ throw ("Could not elect new master before timeout.");
+ }
+
+ print(phase++);
+
+ assert(master != new_master, "Old master shouldn't be equal to new master.");
+
+ print(phase++);
+
+ // Make sure that slaves are still up
+ var result = new_master.getDB("admin").runCommand({ replSetGetStatus: 1 });
+ assert(result['ok'] == 1, "Could not verify that slaves were still up:" + result);
+
+ print(phase++);
+
+ slaves = replTest.liveNodes.slaves;
+ assert.soon(function () {
+ try {
+ res = slaves[0].getDB("admin").runCommand({ replSetGetStatus: 1 })
+ } catch (err) { }
+ return res.myState == 2;
+ }, "Slave 0 state not ready.");
+
+ print(phase++);
+
+ assert.soon(function () {
+ try {
+ res = slaves[1].getDB("admin").runCommand({ replSetGetStatus: 1 })
+ } catch (err) { }
+ return res.myState == 2;
+ }, "Slave 1 state not ready.");
+
+ print("replset3.js SUCCESS");
+
+ replTest.stopSet(15);
}
doTest( 15 );
diff --git a/jstests/replsets/replset5.js b/jstests/replsets/replset5.js
index fe1761e..13ee5c9 100644
--- a/jstests/replsets/replset5.js
+++ b/jstests/replsets/replset5.js
@@ -23,15 +23,15 @@ doTest = function (signal) {
master.getDB("barDB").bar.save({ a: 1 });
replTest.awaitReplication();
- // These writes should be replicated immediately
- master.getDB(testDB).foo.insert({ n: 1 });
- master.getDB(testDB).foo.insert({ n: 2 });
- master.getDB(testDB).foo.insert({ n: 3 });
-
- // *** NOTE ***: The default doesn't seem to be propogating.
- // When I run getlasterror with no defaults, the slaves don't have the data:
- // These getlasterror commands can be run individually to verify this.
- //master.getDB("admin").runCommand({ getlasterror: 1, w: 3, wtimeout: 20000 });
+ // 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});
var slaves = replTest.liveNodes.slaves;
@@ -40,31 +40,15 @@ doTest = function (signal) {
print("Testing slave counts");
- // These should all have 3 documents, but they don't always.
- var master1count = master.getDB(testDB).foo.count();
- assert( master1count == 3, "Master has " + master1count + " of 3 documents!");
-
var slave0count = slaves[0].getDB(testDB).foo.count();
- assert( slave0count == 3, "Slave 0 has " + slave0count + " of 3 documents!");
+ assert( slave0count == docNum, "Slave 0 has " + slave0count + " of " + docNum + " documents!");
var slave1count = slaves[1].getDB(testDB).foo.count();
- assert( slave1count == 3, "Slave 1 has " + slave1count + " of 3 documents!");
+ assert( slave1count == docNum, "Slave 1 has " + slave1count + " of " + docNum + " documents!");
- print("Testing slave 0");
+ var master1count = master.getDB(testDB).foo.count();
+ assert( master1count == docNum, "Master has " + master1count + " of " + docNum + " documents!");
- var s0 = slaves[0].getDB(testDB).foo.find();
- assert(s0.next()['n']);
- assert(s0.next()['n']);
- assert(s0.next()['n']);
-
- print("Testing slave 1");
-
- var s1 = slaves[1].getDB(testDB).foo.find();
- assert(s1.next()['n']);
- assert(s1.next()['n']);
- assert(s1.next()['n']);
-
- // End test
replTest.stopSet(signal);
}
diff --git a/jstests/replsets/replset_remove_node.js b/jstests/replsets/replset_remove_node.js
index fcb754c..9fef721 100644
--- a/jstests/replsets/replset_remove_node.js
+++ b/jstests/replsets/replset_remove_node.js
@@ -33,8 +33,15 @@ doTest = function( signal ) {
config.version = c.version + 1;
config.members = [ { "_id" : 0, "host" : replTest.host + ":31000" },
{ "_id" : 2, "host" : replTest.host + ":31002" } ]
- replTest.initiate( config , 'replSetReconfig' );
+ try {
+ replTest.initiate( config , 'replSetReconfig' );
+ }
+ catch(e) {
+ print(e);
+ }
+
+
// Make sure that a new master comes up
master = replTest.getMaster();
slaves = replTest.liveNodes.slaves;
diff --git a/jstests/replsets/replsetarb2.js b/jstests/replsets/replsetarb2.js
index 0dd8a3d..0e4c791 100644
--- a/jstests/replsets/replsetarb2.js
+++ b/jstests/replsets/replsetarb2.js
@@ -29,6 +29,8 @@ doTest = function( signal ) {
master.getDB("foo").foo.insert({a: "foo"});
replTest.awaitReplication();
+ assert( ! conns[1].getDB( "admin" ).runCommand( "ismaster" ).secondary , "arbiter shouldn't be secondary" )
+
// Now kill the original master
mId = replTest.getNodeId( master );
replTest.stop( mId );
diff --git a/jstests/replsets/replsetarb3.js b/jstests/replsets/replsetarb3.js
new file mode 100644
index 0000000..1193cf2
--- /dev/null
+++ b/jstests/replsets/replsetarb3.js
@@ -0,0 +1,144 @@
+// @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
new file mode 100644
index 0000000..3721ba5
--- /dev/null
+++ b/jstests/replsets/replsetfreeze.js
@@ -0,0 +1,105 @@
+/*
+ * 1: initialize set
+ * 2: step down m1
+ * 3: freeze set for 30 seconds
+ * 4: check no one is master for 30 seconds
+ * 5: check for new master
+ * 6: step down new master
+ * 7: freeze for 30 seconds
+ * 8: unfreeze
+ * 9: check we get a new master within 30 seconds
+ */
+
+
+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;
+ }
+ });
+};
+
+
+print("1: initialize set");
+var replTest = new ReplSetTest( {name: 'unicomplex', nodes: 3} );
+var nodes = replTest.nodeList();
+var conns = replTest.startSet();
+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);
+var master = replTest.getMaster();
+
+
+print("2: step down m1");
+try {
+ master.getDB("admin").runCommand({replSetStepDown : 1});
+}
+catch(e) {
+ print(e);
+}
+reconnect(master);
+
+print("3: freeze set for 30 seconds");
+master.getDB("admin").runCommand({replSetFreeze : 30});
+
+
+print("4: check no one is master for 30 seconds");
+var start = (new Date()).getTime();
+while ((new Date()).getTime() - start < 30000) {
+ var result = master.getDB("admin").runCommand({isMaster:1});
+ assert.eq(result.ismaster, false);
+ assert.eq(result.primary, undefined);
+ sleep(1000);
+}
+
+
+print("5: check for new master");
+master = replTest.getMaster();
+
+
+print("6: step down new master");
+try {
+ master.getDB("admin").runCommand({replSetStepDown : 1});
+}
+catch(e) {
+ print(e);
+}
+reconnect(master);
+
+
+print("7: freeze for 30 seconds");
+master.getDB("admin").runCommand({replSetFreeze : 30});
+sleep(1000);
+
+
+print("8: unfreeze");
+master.getDB("admin").runCommand({replSetFreeze : 0});
+
+
+print("9: check we get a new master within 30 seconds");
+master = replTest.getMaster();
+
+
+replTest.stopSet( 15 );
+
diff --git a/jstests/replsets/rollback.js b/jstests/replsets/rollback.js
index 8840371..6370e41 100644
--- a/jstests/replsets/rollback.js
+++ b/jstests/replsets/rollback.js
@@ -1,155 +1,186 @@
-// test rollback in replica sets
-
-// try running as :
-//
-// mongo --nodb rollback.js | tee out | grep -v ^m31
-//
-
-var debugging = 0;
-
-function pause(s) {
- print(s);
- while (debugging) {
- sleep(3000);
- print(s);
- }
-}
-
-function deb(obj) {
- if( debugging ) {
- print("\n\n\n" + obj + "\n\n");
- }
-}
-
-w = 0;
-
-function wait(f) {
- w++;
- var n = 0;
- while (!f()) {
- if( n % 4 == 0 )
- print("rollback.js waiting " + w);
- if (++n == 4) {
- print("" + f);
- }
- sleep(1000);
- }
-}
-
-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] },
- { "_id": 1, "host": nodes[1] },
- { "_id": 2, "host": nodes[2], arbiterOnly: true}]
- });
-
- // Make sure we have a master
- var master = replTest.getMaster();
- a_conn = conns[0];
- A = a_conn.getDB("admin");
- b_conn = conns[1];
- a_conn.setSlaveOk();
- b_conn.setSlaveOk();
- B = b_conn.getDB("admin");
- assert(master == conns[0], "conns[0] assumed to be master");
- assert(a_conn == master);
-
- //deb(master);
-
- // Make sure we have an arbiter
- assert.soon(function () {
- res = conns[2].getDB("admin").runCommand({ replSetGetStatus: 1 });
- return res.myState == 7;
- }, "Arbiter failed to initialize.");
-
- // Wait for initial replication
- var a = a_conn.getDB("foo");
- var b = b_conn.getDB("foo");
-
- /* force the oplog to roll */
- if (new Date() % 2 == 0) {
- print("ROLLING OPLOG AS PART OF TEST (we only do this sometimes)");
- var pass = 1;
- var first = a.getSisterDB("local").oplog.rs.find().sort({ $natural: 1 }).limit(1)[0];
- a.roll.insert({ x: 1 });
- while (1) {
- for (var i = 0; i < 10000; i++)
- a.roll.update({}, { $inc: { x: 1} });
- var op = a.getSisterDB("local").oplog.rs.find().sort({ $natural: 1 }).limit(1)[0];
- if (tojson(op.h) != tojson(first.h)) {
- printjson(op);
- printjson(first);
- break;
- }
- pass++;
- a.getLastError(2); // unlikely secondary isn't keeping up, but let's avoid possible intermittent issues with that.
- }
- print("PASSES FOR OPLOG ROLL: " + pass);
- }
- else {
- print("NO ROLL");
- }
-
- a.bar.insert({ q: 1, a: "foo" });
- a.bar.insert({ q: 2, a: "foo", x: 1 });
- a.bar.insert({ q: 3, bb: 9, a: "foo" });
-
- assert(a.bar.count() == 3, "t.count");
-
- // wait for secondary to get this data
- wait(function () { return b.bar.count() == 3; });
-
- A.runCommand({ replSetTest: 1, blind: true });
- wait(function () { return B.isMaster().ismaster; });
-
- b.bar.insert({ q: 4 });
- b.bar.insert({ q: 5 });
- b.bar.insert({ q: 6 });
- assert(b.bar.count() == 6, "u.count");
-
- // a should not have the new data as it was in blind state.
- B.runCommand({ replSetTest: 1, blind: true });
- A.runCommand({ replSetTest: 1, blind: false });
- wait(function () { return !B.isMaster().ismaster; });
- wait(function () { return A.isMaster().ismaster; });
-
- assert(a.bar.count() == 3, "t is 3");
- a.bar.insert({ q: 7 });
- a.bar.insert({ q: 8 });
- {
- assert(a.bar.count() == 5);
- var x = a.bar.find().toArray();
- assert(x[0].q == 1, '1');
- assert(x[1].q == 2, '2');
- assert(x[2].q == 3, '3');
- assert(x[3].q == 7, '7');
- assert(x[4].q == 8, '8');
- }
-
- // A is 1 2 3 7 8
- // B is 1 2 3 4 5 6
-
- // bring B back online
- B.runCommand({ replSetTest: 1, blind: false });
-
- 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");
-
- friendlyEqual(a.bar.find().sort({ _id: 1 }).toArray(), b.bar.find().sort({ _id: 1 }).toArray(), "server data sets do not match");
-
- pause("rollback.js SUCCESS");
- replTest.stopSet(signal);
+// test rollback in replica sets
+
+// try running as :
+//
+// mongo --nodb rollback.js | tee out | grep -v ^m31
+//
+
+var debugging = 0;
+
+function pause(s) {
+ print(s);
+ while (debugging) {
+ sleep(3000);
+ print(s);
+ }
+}
+
+function deb(obj) {
+ if( debugging ) {
+ print("\n\n\n" + obj + "\n\n");
+ }
+}
+
+w = 0;
+
+function wait(f) {
+ w++;
+ var n = 0;
+ while (!f()) {
+ if( n % 4 == 0 )
+ print("rollback.js waiting " + w);
+ if (++n == 4) {
+ print("" + f);
+ }
+ assert(n < 200, 'tried 200 times, giving up');
+ sleep(1000);
+ }
}
+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] },
+ { "_id": 1, "host": nodes[1] },
+ { "_id": 2, "host": nodes[2], arbiterOnly: true}]
+ });
+
+ // Make sure we have a master
+ var master = replTest.getMaster();
+ a_conn = conns[0];
+ A = a_conn.getDB("admin");
+ b_conn = conns[1];
+ a_conn.setSlaveOk();
+ b_conn.setSlaveOk();
+ B = b_conn.getDB("admin");
+ assert(master == conns[0], "conns[0] assumed to be master");
+ assert(a_conn == master);
+
+ //deb(master);
+
+ // Make sure we have an arbiter
+ assert.soon(function () {
+ res = conns[2].getDB("admin").runCommand({ replSetGetStatus: 1 });
+ return res.myState == 7;
+ }, "Arbiter failed to initialize.");
+
+ // Wait for initial replication
+ var a = a_conn.getDB("foo");
+ var b = b_conn.getDB("foo");
+
+ /* force the oplog to roll */
+ if (new Date() % 2 == 0) {
+ print("ROLLING OPLOG AS PART OF TEST (we only do this sometimes)");
+ var pass = 1;
+ var first = a.getSisterDB("local").oplog.rs.find().sort({ $natural: 1 }).limit(1)[0];
+ a.roll.insert({ x: 1 });
+ while (1) {
+ for (var i = 0; i < 10000; i++)
+ a.roll.update({}, { $inc: { x: 1} });
+ var op = a.getSisterDB("local").oplog.rs.find().sort({ $natural: 1 }).limit(1)[0];
+ if (tojson(op.h) != tojson(first.h)) {
+ printjson(op);
+ printjson(first);
+ break;
+ }
+ pass++;
+ a.getLastError(2); // unlikely secondary isn't keeping up, but let's avoid possible intermittent issues with that.
+ }
+ print("PASSES FOR OPLOG ROLL: " + pass);
+ }
+ else {
+ print("NO ROLL");
+ }
+
+ a.bar.insert({ q: 1, a: "foo" });
+ a.bar.insert({ q: 2, a: "foo", x: 1 });
+ a.bar.insert({ q: 3, bb: 9, a: "foo" });
+
+ assert(a.bar.count() == 3, "t.count");
+
+ // wait for secondary to get this data
+ wait(function () { return b.bar.count() == 3; });
+
+ A.runCommand({ replSetTest: 1, blind: true });
+ reconnect(a,b);
+ wait(function () { return B.isMaster().ismaster; });
+
+ b.bar.insert({ q: 4 });
+ b.bar.insert({ q: 5 });
+ b.bar.insert({ q: 6 });
+ assert(b.bar.count() == 6, "u.count");
+
+ // a should not have the new data as it was in blind state.
+ B.runCommand({ replSetTest: 1, blind: true });
+ print("*************** wait for server to reconnect ****************");
+ reconnect(a,b);
+ A.runCommand({ replSetTest: 1, blind: false });
+ reconnect(a,b);
+
+ print("*************** B ****************");
+ wait(function () { try { return !B.isMaster().ismaster; } catch(e) { return false; } });
+ print("*************** A ****************");
+ reconnect(a,b);
+ wait(function () {
+ try {
+ return A.isMaster().ismaster;
+ } catch(e) {
+ return false;
+ }
+ });
+
+ assert(a.bar.count() == 3, "t is 3");
+ a.bar.insert({ q: 7 });
+ a.bar.insert({ q: 8 });
+ {
+ assert(a.bar.count() == 5);
+ var x = a.bar.find().toArray();
+ assert(x[0].q == 1, '1');
+ assert(x[1].q == 2, '2');
+ assert(x[2].q == 3, '3');
+ assert(x[3].q == 7, '7');
+ assert(x[4].q == 8, '8');
+ }
+
+ // A is 1 2 3 7 8
+ // B is 1 2 3 4 5 6
+
+ // bring B back online
+ B.runCommand({ replSetTest: 1, blind: false });
+ reconnect(a,b);
+
+ 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();
+
+ friendlyEqual(a.bar.find().sort({ _id: 1 }).toArray(), b.bar.find().sort({ _id: 1 }).toArray(), "server data sets do not match");
+
+ pause("rollback.js SUCCESS");
+ replTest.stopSet(signal);
+};
+
+
+var reconnect = function(a,b) {
+ wait(function() {
+ try {
+ a.bar.stats();
+ b.bar.stats();
+ return true;
+ } catch(e) {
+ print(e);
+ return false;
+ }
+ });
+};
+
print("rollback.js");
doTest( 15 );
diff --git a/jstests/replsets/rollback2.js b/jstests/replsets/rollback2.js
index 483d221..46fb548 100644
--- a/jstests/replsets/rollback2.js
+++ b/jstests/replsets/rollback2.js
@@ -1,201 +1,232 @@
-// test rollback in replica sets
-
-// try running as :
-//
-// mongo --nodb rollback.js | tee out | grep -v ^m31
-//
-
-var debugging = 0;
-
-function pause(s) {
- print(s);
- while (debugging) {
- sleep(3000);
- print(s);
- }
-}
-
-function deb(obj) {
- if( debugging ) {
- print("\n\n\n" + obj + "\n\n");
- }
-}
-
-w = 0;
-
-function wait(f) {
- w++;
- var n = 0;
- while (!f()) {
- if (n % 4 == 0)
- print("rollback2.js waiting " + w);
- if (++n == 4) {
- print("" + f);
- }
- sleep(1000);
- }
-}
-
-function dbs_match(a, b) {
- print("dbs_match");
-
- var ac = a.system.namespaces.find().sort({name:1}).toArray();
- var bc = b.system.namespaces.find().sort({name:1}).toArray();
- if (!friendlyEqual(ac, bc)) {
- print("dbs_match: namespaces don't match");
- print("\n\n");
- printjson(ac);
- print("\n\n");
- printjson(bc);
- print("\n\n");
- return false;
- }
-
- var c = a.getCollectionNames();
- for( var i in c ) {
- print("checking " + c[i]);
- if( !friendlyEqual( a[c[i]].find().sort({_id:1}).toArray(), b[c[i]].find().sort({_id:1}).toArray() ) ) {
- print("dbs_match: collections don't match " + c[i]);
- return false;
- }
- }
- return true;
-}
-
-/* these writes will be initial data and replicate everywhere. */
-function doInitialWrites(db) {
- t = db.bar;
- t.insert({ q:0});
- t.insert({ q: 1, a: "foo" });
- t.insert({ q: 2, a: "foo", x: 1 });
- t.insert({ q: 3, bb: 9, a: "foo" });
- t.insert({ q: 40, a: 1 });
- t.insert({ q: 40, a: 2 });
- t.insert({ q: 70, txt: 'willremove' });
-
- db.createCollection("kap", { capped: true, size: 5000 });
- db.kap.insert({ foo: 1 })
-
- // going back to empty on capped is a special case and must be tested
- db.createCollection("kap2", { capped: true, size: 5501 });
-}
-
-/* these writes on one primary only and will be rolled back. */
-function doItemsToRollBack(db) {
- t = db.bar;
- t.insert({ q: 4 });
- t.update({ q: 3 }, { q: 3, rb: true });
-
- t.remove({ q: 40 }); // multi remove test
-
- t.update({ q: 2 }, { q: 39, rb: true });
-
- // rolling back a delete will involve reinserting the item(s)
- t.remove({ q: 1 });
-
- t.update({ q: 0 }, { $inc: { y: 1} });
-
- db.kap.insert({ foo: 2 })
- db.kap2.insert({ foo: 2 })
-
- // create a collection (need to roll back the whole thing)
- db.newcoll.insert({ a: true });
-
- // create a new empty collection (need to roll back the whole thing)
- db.createCollection("abc");
-}
-
-function doWritesToKeep2(db) {
- t = db.bar;
- t.insert({ txt: 'foo' });
- t.remove({ q: 70 });
- t.update({ q: 0 }, { $inc: { y: 33} });
-}
-
-function verify(db) {
- print("verify");
- t = db.bar;
- assert(t.find({ q: 1 }).count() == 1);
- assert(t.find({ txt: 'foo' }).count() == 1);
- assert(t.find({ q: 4 }).count() == 0);
-}
-
-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] },
- { "_id": 1, "host": nodes[1] },
- { "_id": 2, "host": nodes[2], arbiterOnly: true}]
- });
-
- // Make sure we have a master
- var master = replTest.getMaster();
- a_conn = conns[0];
- A = a_conn.getDB("admin");
- b_conn = conns[1];
- a_conn.setSlaveOk();
- b_conn.setSlaveOk();
- B = b_conn.getDB("admin");
- assert(master == conns[0], "conns[0] assumed to be master");
- assert(a_conn == master);
-
- //deb(master);
-
- // Make sure we have an arbiter
- assert.soon(function () {
- res = conns[2].getDB("admin").runCommand({ replSetGetStatus: 1 });
- return res.myState == 7;
- }, "Arbiter failed to initialize.");
-
- // Wait for initial replication
- var a = a_conn.getDB("foo");
- var b = b_conn.getDB("foo");
- doInitialWrites(a);
-
- // wait for secondary to get this data
- wait(function () { return b.bar.count() == a.bar.count(); });
-
- A.runCommand({ replSetTest: 1, blind: true });
- wait(function () { return B.isMaster().ismaster; });
-
- doItemsToRollBack(b);
-
- // a should not have the new data as it was in blind state.
- B.runCommand({ replSetTest: 1, blind: true });
- A.runCommand({ replSetTest: 1, blind: false });
- wait(function () { return !B.isMaster().ismaster; });
- wait(function () { return A.isMaster().ismaster; });
-
- assert(a.bar.count() >= 1, "count check");
- doWritesToKeep2(a);
-
- // A is 1 2 3 7 8
- // B is 1 2 3 4 5 6
-
- // bring B back online
- // as A is primary, B will roll back and then catch up
- B.runCommand({ replSetTest: 1, blind: false });
-
- 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");
-
- verify(a);
-
- assert( dbs_match(a,b), "server data sets do not match after rollback, something is wrong");
-
- pause("rollback2.js SUCCESS");
- replTest.stopSet(signal);
+// a test of rollback in replica sets
+//
+// try running as :
+//
+// mongo --nodb rollback2.js | tee out | grep -v ^m31
+//
+
+var debugging = 0;
+
+function pause(s) {
+ print(s);
+ while (debugging) {
+ sleep(3000);
+ print(s);
+ }
+}
+
+function deb(obj) {
+ if( debugging ) {
+ print("\n\n\n" + obj + "\n\n");
+ }
+}
+
+w = 0;
+
+function wait(f) {
+ w++;
+ var n = 0;
+ while (!f()) {
+ if (n % 4 == 0)
+ print("rollback2.js waiting " + w);
+ if (++n == 4) {
+ print("" + f);
+ }
+ assert(n < 200, 'tried 200 times, giving up');
+ sleep(1000);
+ }
+}
+
+function dbs_match(a, b) {
+ print("dbs_match");
+
+ var ac = a.system.namespaces.find().sort({name:1}).toArray();
+ var bc = b.system.namespaces.find().sort({name:1}).toArray();
+ if (!friendlyEqual(ac, bc)) {
+ print("dbs_match: namespaces don't match");
+ print("\n\n");
+ printjson(ac);
+ print("\n\n");
+ printjson(bc);
+ print("\n\n");
+ return false;
+ }
+
+ var c = a.getCollectionNames();
+ for( var i in c ) {
+ print("checking " + c[i]);
+ if( !friendlyEqual( a[c[i]].find().sort({_id:1}).toArray(), b[c[i]].find().sort({_id:1}).toArray() ) ) {
+ print("dbs_match: collections don't match " + c[i]);
+ return false;
+ }
+ }
+ return true;
+}
+
+/* these writes will be initial data and replicate everywhere. */
+function doInitialWrites(db) {
+ t = db.bar;
+ t.insert({ q:0});
+ t.insert({ q: 1, a: "foo" });
+ t.insert({ q: 2, a: "foo", x: 1 });
+ t.insert({ q: 3, bb: 9, a: "foo" });
+ t.insert({ q: 40, a: 1 });
+ t.insert({ q: 40, a: 2 });
+ t.insert({ q: 70, txt: 'willremove' });
+
+ db.createCollection("kap", { capped: true, size: 5000 });
+ db.kap.insert({ foo: 1 })
+
+ // going back to empty on capped is a special case and must be tested
+ db.createCollection("kap2", { capped: true, size: 5501 });
+}
+
+/* these writes on one primary only and will be rolled back. */
+function doItemsToRollBack(db) {
+ t = db.bar;
+ t.insert({ q: 4 });
+ t.update({ q: 3 }, { q: 3, rb: true });
+
+ t.remove({ q: 40 }); // multi remove test
+
+ t.update({ q: 2 }, { q: 39, rb: true });
+
+ // rolling back a delete will involve reinserting the item(s)
+ t.remove({ q: 1 });
+
+ t.update({ q: 0 }, { $inc: { y: 1} });
+
+ db.kap.insert({ foo: 2 })
+ db.kap2.insert({ foo: 2 })
+
+ // create a collection (need to roll back the whole thing)
+ db.newcoll.insert({ a: true });
+
+ // create a new empty collection (need to roll back the whole thing)
+ db.createCollection("abc");
}
+function doWritesToKeep2(db) {
+ t = db.bar;
+ t.insert({ txt: 'foo' });
+ t.remove({ q: 70 });
+ t.update({ q: 0 }, { $inc: { y: 33} });
+}
+
+function verify(db) {
+ print("verify");
+ t = db.bar;
+ assert(t.find({ q: 1 }).count() == 1);
+ assert(t.find({ txt: 'foo' }).count() == 1);
+ assert(t.find({ q: 4 }).count() == 0);
+}
+
+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] },
+ { "_id": 1, "host": nodes[1] },
+ { "_id": 2, "host": nodes[2], arbiterOnly: true}]
+ });
+
+ // Make sure we have a master
+ var master = replTest.getMaster();
+ a_conn = conns[0];
+ A = a_conn.getDB("admin");
+ b_conn = conns[1];
+ a_conn.setSlaveOk();
+ b_conn.setSlaveOk();
+ B = b_conn.getDB("admin");
+ assert(master == conns[0], "conns[0] assumed to be master");
+ assert(a_conn == master);
+
+ //deb(master);
+
+ // Make sure we have an arbiter
+ assert.soon(function () {
+ res = conns[2].getDB("admin").runCommand({ replSetGetStatus: 1 });
+ return res.myState == 7;
+ }, "Arbiter failed to initialize.");
+
+ // Wait for initial replication
+ var a = a_conn.getDB("foo");
+ var b = b_conn.getDB("foo");
+ wait(function () {
+ var status = A.runCommand({replSetGetStatus : 1});
+ return status.members[1].state == 2;
+ });
+
+ doInitialWrites(a);
+
+ // wait for secondary to get this data
+ wait(function () { return b.bar.count() == a.bar.count(); });
+ wait(function () {
+ var status = A.runCommand({replSetGetStatus : 1});
+ return status.members[1].state == 2;
+ });
+
+
+ A.runCommand({ replSetTest: 1, blind: true });
+ reconnect(a, b);
+
+ wait(function () { return B.isMaster().ismaster; });
+
+ doItemsToRollBack(b);
+
+ // a should not have the new data as it was in blind state.
+ B.runCommand({ replSetTest: 1, blind: true });
+ reconnect(a, b);
+ A.runCommand({ replSetTest: 1, blind: false });
+ reconnect(a,b);
+
+ wait(function () { try { return !B.isMaster().ismaster; } catch(e) { return false; } });
+ wait(function () { try { return A.isMaster().ismaster; } catch(e) { return false; } });
+
+ assert(a.bar.count() >= 1, "count check");
+ doWritesToKeep2(a);
+
+ // A is 1 2 3 7 8
+ // B is 1 2 3 4 5 6
+
+ // bring B back online
+ // as A is primary, B will roll back and then catch up
+ B.runCommand({ replSetTest: 1, blind: false });
+ reconnect(a,b);
+
+ 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();
+
+ verify(a);
+
+ assert( dbs_match(a,b), "server data sets do not match after rollback, something is wrong");
+
+ pause("rollback2.js SUCCESS");
+ replTest.stopSet(signal);
+};
+
+var reconnect = function(a,b) {
+ wait(function() {
+ try {
+ a.bar.stats();
+ b.bar.stats();
+ return true;
+ } catch(e) {
+ print(e);
+ return false;
+ }
+ });
+};
+
print("rollback2.js");
doTest( 15 );
diff --git a/jstests/replsets/rollback3.js b/jstests/replsets/rollback3.js
index 5c2f2f1..fa923d8 100755
--- a/jstests/replsets/rollback3.js
+++ b/jstests/replsets/rollback3.js
@@ -30,10 +30,10 @@ function wait(f) {
if (n % 4 == 0)
print("rollback3.js waiting " + w);
if (++n == 4) {
- print("" + f);
- }
- if (n == 200) {
- print("rollback3.js failing waited too long");
+ print("" + f);
+ }
+ if (n == 200) {
+ print("rollback3.js failing waited too long");
throw "wait error";
}
sleep(1000);
@@ -188,15 +188,20 @@ doTest = function (signal) {
wait(function () { return b.bar.count() == a.bar.count(); });
A.runCommand({ replSetTest: 1, blind: true });
- wait(function () { return B.isMaster().ismaster; });
+ reconnect(a,b);
+ wait(function () { try { return B.isMaster().ismaster; } catch(e) { return false; } });
doItemsToRollBack(b);
// a should not have the new data as it was in blind state.
B.runCommand({ replSetTest: 1, blind: true });
+ reconnect(a,b);
+
A.runCommand({ replSetTest: 1, blind: false });
- wait(function () { return !B.isMaster().ismaster; });
- wait(function () { return A.isMaster().ismaster; });
+ reconnect(a,b);
+
+ wait(function () { try { return !B.isMaster().ismaster; } catch(e) { return false; } });
+ wait(function () { try { return A.isMaster().ismaster; } catch(e) { return false; } });
assert(a.bar.count() >= 1, "count check");
doWritesToKeep2(a);
@@ -207,18 +212,34 @@ doTest = function (signal) {
// bring B back online
// as A is primary, B will roll back and then catch up
B.runCommand({ replSetTest: 1, blind: false });
+ reconnect(a,b);
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();
+
assert( dbs_match(a,b), "server data sets do not match after rollback, something is wrong");
pause("rollback3.js SUCCESS");
replTest.stopSet(signal);
-}
+};
+
+
+var reconnect = function(a,b) {
+ wait(function() {
+ try {
+ a.bar.stats();
+ b.bar.stats();
+ return true;
+ } catch(e) {
+ print(e);
+ return false;
+ }
+ });
+};
print("rollback3.js");
doTest( 15 );
diff --git a/jstests/replsets/rslib.js b/jstests/replsets/rslib.js
new file mode 100644
index 0000000..c072829
--- /dev/null
+++ b/jstests/replsets/rslib.js
@@ -0,0 +1,63 @@
+
+var count = 0;
+var w = 0;
+
+var wait = function(f) {
+ w++;
+ var n = 0;
+ while (!f()) {
+ if( n % 4 == 0 )
+ print("waiting " + w);
+ if (++n == 4) {
+ print("" + f);
+ }
+ assert(n < 200, 'tried 200 times, giving up');
+ sleep(1000);
+ }
+};
+
+/**
+ * Use this to do something once every 4 iterations.
+ *
+ * <pre>
+ * for (i=0; i<1000; i++) {
+ * occasionally(function() { print("4 more iterations"); });
+ * }
+ * </pre>
+ */
+var occasionally = function(f, n) {
+ var interval = n || 4;
+ if (count % interval == 0) {
+ f();
+ }
+ count++;
+};
+
+var reconnect = function(a) {
+ wait(function() {
+ try {
+ // make this work with either dbs or connections
+ if (typeof(a.getDB) == "function") {
+ a.getDB("foo").bar.stats();
+ }
+ else {
+ a.bar.stats();
+ }
+ return true;
+ } catch(e) {
+ print(e);
+ return false;
+ }
+ });
+};
+
+
+var getLatestOp = function(server) {
+ server.getDB("admin").getMongo().setSlaveOk();
+ var log = server.getDB("local")['oplog.rs'];
+ var cursor = log.find({}).sort({'$natural': -1}).limit(1);
+ if (cursor.hasNext()) {
+ return cursor.next();
+ }
+ return null;
+};
diff --git a/jstests/replsets/slaveDelay2.js b/jstests/replsets/slaveDelay2.js
new file mode 100644
index 0000000..2d9dd1f
--- /dev/null
+++ b/jstests/replsets/slaveDelay2.js
@@ -0,0 +1,104 @@
+
+var name = "slaveDelay2";
+var host = getHostName();
+
+var waitForAllMembers = function(master) {
+ var ready = false;
+
+ outer:
+ while (true) {
+ var state = master.getSisterDB("admin").runCommand({replSetGetStatus:1});
+
+ for (var m in state.members) {
+ if (state.members[m].state != 2 && state.members[m].state != 1) {
+ sleep(10000);
+ continue outer;
+ }
+ }
+
+ printjson(state);
+ print("okay, everyone is primary or secondary");
+ return;
+ }
+};
+
+
+var initialize = function() {
+ var replTest = new ReplSetTest( {name: name, nodes: 1} );
+
+ var nodes = replTest.startSet();
+
+ replTest.initiate();
+
+ var master = replTest.getMaster().getDB(name);
+
+ waitForAllMembers(master);
+
+ return replTest;
+};
+
+var populate = function(master) {
+ // insert records
+ for (var i =0; i<1000; i++) {
+ master.foo.insert({_id:1});
+ }
+
+ master.runCommand({getlasterror:1});
+}
+
+doTest = function( signal ) {
+ var replTest = initialize();
+ var master = replTest.getMaster().getDB(name);
+ populate(master);
+ var admin = master.getSisterDB("admin");
+
+ /**
+ * start a slave with a long delay (1 hour) and do some writes while it is
+ * initializing. Make sure it syncs all of these writes before going into
+ * syncDelay.
+ */
+ var conn = startMongodTest(31008, name + "-sd", 0, { useHostname: true, replSet: name });
+ conn.setSlaveOk();
+
+ config = master.getSisterDB("local").system.replset.findOne();
+ config.version++;
+ config.members.push({_id : 1, host : host+":31008",priority:0, slaveDelay:3600});
+ var ok = admin.runCommand({replSetReconfig : config});
+ assert.eq(ok.ok,1);
+
+ // do inserts during initial sync
+ count = 0;
+ while (count < 10) {
+ for (var i = 100*count; i<100*(count+1); i++) {
+ master.foo.insert({x:i});
+ }
+
+ //check if initial sync is done
+ var state = master.getSisterDB("admin").runCommand({replSetGetStatus:1});
+ printjson(state);
+ if (state.members[1].state == 2) {
+ break;
+ }
+
+ count++;
+ }
+
+ // throw out last 100 inserts, but make sure the others were applied
+ if (count == 0) {
+ print("NOTHING TO CHECK");
+ replTest.stopSet();
+ return;
+ }
+
+ // wait a bit for the syncs to be applied
+ waitForAllMembers(master);
+
+ for (var i=0; i<(100*count); i++) {
+ var obj = conn.getDB(name).foo.findOne({x : i});
+ assert(obj);
+ }
+
+ replTest.stopSet();
+}
+
+doTest(15);
diff --git a/jstests/replsets/slavedelay1.js b/jstests/replsets/slavedelay1.js
new file mode 100644
index 0000000..e549822
--- /dev/null
+++ b/jstests/replsets/slavedelay1.js
@@ -0,0 +1,127 @@
+
+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;
+ }
+};
+
+
+doTest = function( signal ) {
+
+ var name = "slaveDelay";
+ var host = getHostName();
+
+ var replTest = new ReplSetTest( {name: name, nodes: 3} );
+
+ var nodes = replTest.startSet();
+
+ /* set slaveDelay to 30 seconds */
+ var config = replTest.getReplSetConfig();
+ config.members[2].priority = 0;
+ config.members[2].slaveDelay = 30;
+
+ replTest.initiate(config);
+
+ 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);
+
+ // insert a record
+ master.foo.insert({x:1});
+ master.runCommand({getlasterror:1, w:2});
+
+ var doc = master.foo.findOne();
+ assert.eq(doc.x, 1);
+
+ // make sure slave has it
+ var doc = slave[0].foo.findOne();
+ assert.eq(doc.x, 1);
+
+ // make sure delayed slave doesn't have it
+ assert.eq(slave[1].foo.findOne(), null);
+
+ // wait 35 seconds
+ sleep(35000);
+
+ // now delayed slave should have it
+ assert.eq(slave[1].foo.findOne().x, 1);
+
+
+ /************* Part 2 *******************/
+
+ // how about non-initial sync?
+
+ for (var i=0; i<100; i++) {
+ master.foo.insert({_id : i, "foo" : "bar"});
+ }
+ master.runCommand({getlasterror:1,w:2});
+
+ assert.eq(master.foo.findOne({_id : 99}).foo, "bar");
+ 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");
+
+ /************* Part 3 *******************/
+
+ // how about if we add a new server? will it sync correctly?
+
+ var conn = startMongodTest( 31007 , name+"-part3" , 0 , {useHostname : true, replSet : name} );
+
+ config = master.getSisterDB("local").system.replset.findOne();
+ printjson(config);
+ 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);
+
+ // 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);
+
+ sleep(15000);
+
+ assert.eq(conn.getDB(name).foo.findOne({_id:123}).x, "foo");
+
+ replTest.stopSet();
+}
+
+doTest(15);
diff --git a/jstests/replsets/sync1.js b/jstests/replsets/sync1.js
index e60d128..af16044 100644
--- a/jstests/replsets/sync1.js
+++ b/jstests/replsets/sync1.js
@@ -1,5 +1,7 @@
// test rollback of replica sets
+load("jstests/replsets/rslib.js");
+
var debugging=0;
w = 0;
@@ -50,7 +52,7 @@ doTest = function (signal) {
dbs[0].bar.ensureIndex({ w: 1 });
var ok = false;
- var inserts = 100000;
+ var inserts = 10000;
print("\nsync1.js ********************************************************************** part 5");
@@ -62,7 +64,7 @@ doTest = function (signal) {
do {
sleep(1000);
status = dbs[0].getSisterDB("admin").runCommand({ replSetGetStatus: 1 });
- } while (status.members[1].state != 2 && status.members[2].state != 2);
+ } 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 });
@@ -125,12 +127,14 @@ doTest = function (signal) {
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());
+ printjson(dbs[2].adminCommand({replSetGetStatus : 1}));
}
catch (e) { print(e); }
assert(false, "sync1.js too many exceptions, failing");
@@ -161,10 +165,22 @@ doTest = function (signal) {
print("\nsync1.js ********************************************************************** part 10");
// now, let's see if rollback works
- var result = dbs[0].getSisterDB("admin").runCommand({ replSetTest: 1, blind: false });
+ wait(function() {
+ try {
+ dbs[0].adminCommand({ replSetTest: 1, blind: false });
+ }
+ catch(e) {
+ print(e);
+ }
+ reconnect(dbs[0]);
+ reconnect(dbs[1]);
+
+ var status = dbs[1].adminCommand({replSetGetStatus:1});
+ return status.members[0].health == 1;
+ });
+
+
dbs[0].getMongo().setSlaveOk();
-
- printjson(result);
sleep(5000);
// now this should resync
@@ -192,6 +208,10 @@ doTest = function (signal) {
count++;
if (count == 100) {
+ printjson(dbs[0].isMaster());
+ printjson(dbs[0].adminCommand({replSetGetStatus:1}));
+ 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);
diff --git a/jstests/replsets/sync_passive.js b/jstests/replsets/sync_passive.js
new file mode 100644
index 0000000..d3e8ef4
--- /dev/null
+++ b/jstests/replsets/sync_passive.js
@@ -0,0 +1,89 @@
+/**
+ * Test syncing from non-primaries.
+ *
+ * Start a set.
+ * Inital sync.
+ * Kill member 1.
+ * Add some data.
+ * Kill member 0.
+ * Restart member 1.
+ * Check that it syncs.
+ * Add some data.
+ * Kill member 1.
+ * Restart member 0.
+ * Check that it syncs.
+ */
+
+load("jstests/replsets/rslib.js");
+
+var name = "sync_passive";
+var host = getHostName();
+
+var replTest = new ReplSetTest( {name: name, nodes: 3} );
+
+var nodes = replTest.startSet();
+
+/* set slaveDelay to 30 seconds */
+var config = replTest.getReplSetConfig();
+config.members[2].priority = 0;
+
+replTest.initiate(config);
+
+var master = replTest.getMaster().getDB("test");
+var server0 = master;
+var server1 = replTest.liveNodes.slaves[0];
+
+print("Initial sync");
+for (var i=0;i<100;i++) {
+ master.foo.insert({x:i});
+}
+replTest.awaitReplication();
+
+
+print("stop #1");
+replTest.stop(1);
+
+
+print("add some data");
+for (var i=0;i<1000;i++) {
+ master.bar.insert({x:i});
+}
+replTest.awaitReplication();
+
+
+print("stop #0");
+replTest.stop(0);
+
+
+print("restart #1");
+replTest.restart(1);
+
+
+print("check sync");
+replTest.awaitReplication();
+
+
+print("add data");
+reconnect(server1);
+master = replTest.getMaster().getDB("test");
+for (var i=0;i<1000;i++) {
+ master.bar.insert({x:i});
+}
+replTest.awaitReplication();
+
+
+print("kill #1");
+replTest.stop(1);
+
+
+print("restart #0");
+replTest.restart(0);
+reconnect(server0);
+
+
+print("wait for sync");
+replTest.awaitReplication();
+
+
+print("bring #1 back up, make sure everything's okay");
+replTest.restart(1);
diff --git a/jstests/replsets/sync_passive2.js b/jstests/replsets/sync_passive2.js
new file mode 100644
index 0000000..230d71c
--- /dev/null
+++ b/jstests/replsets/sync_passive2.js
@@ -0,0 +1,120 @@
+/**
+ * Test syncing from non-primaries.
+ */
+
+load("jstests/replsets/rslib.js");
+
+var name = "sync_passive2";
+var host = getHostName();
+
+var replTest = new ReplSetTest( {name: name, nodes: 5} );
+var nodes = replTest.startSet();
+
+// 0: master
+// 1: arbiter
+// 2: slave a
+// 3: slave b
+// 4: slave c
+var config = replTest.getReplSetConfig();
+config.members[1].arbiterOnly = true;
+for (i=2; i<config.members.length; i++) {
+ config.members[i].priority = 0;
+}
+replTest.initiate(config);
+
+var master = replTest.getMaster().getDB("test");
+
+print("Initial sync");
+for (var i=0;i<10000;i++) {
+ master.foo.insert({x:i, foo:"bar", msg : "all the talk on the market", date : [new Date(), new Date(), new Date()]});
+}
+replTest.awaitReplication();
+
+
+print("stop c");
+replTest.stop(4);
+
+
+print("add data");
+for (var i=0;i<10000;i++) {
+ master.foo.insert({x:i, foo:"bar", msg : "all the talk on the market", date : [new Date(), new Date(), new Date()]});
+}
+replTest.awaitReplication();
+
+
+print("stop b");
+replTest.stop(3);
+
+
+print("add data");
+for (var i=0;i<10000;i++) {
+ master.foo.insert({x:i, foo:"bar", msg : "all the talk on the market", date : [new Date(), new Date(), new Date()]});
+}
+replTest.awaitReplication();
+
+
+print("kill master");
+replTest.stop(0);
+replTest.stop(2);
+
+
+// now we have just the arbiter up
+
+print("restart c");
+replTest.restart(4);
+print("restart b");
+replTest.restart(3);
+
+
+print("wait for sync");
+wait(function() {
+ var status = replTest.liveNodes.slaves[0].getDB("admin").runCommand({replSetGetStatus:1});
+ occasionally(function() {
+ printjson(status);
+ print("1: " + status.members +" 2: "+(status.members[3].state == 2)+" 3: "+ (status.members[4].state == 2)
+ + " 4: "+friendlyEqual(status.members[3].optime, status.members[4].optime));
+ });
+
+ return status.members &&
+ status.members[3].state == 2 &&
+ status.members[4].state == 2 &&
+ friendlyEqual(status.members[3].optime, status.members[4].optime);
+ });
+
+
+print("restart a");
+replTest.restart(2);
+print("wait for sync2");
+wait(function() {
+ var status = replTest.liveNodes.slaves[0].getDB("admin").runCommand({replSetGetStatus:1});
+ occasionally(function() {
+ printjson(status);
+ print("1: " + status.members +" 2a: "+(status.members[3].state == 2)+" 2: "+
+ (status.members[3].state == 2)+" 3: "+ (status.members[4].state == 2)
+ + " 4: "+friendlyEqual(status.members[3].optime, status.members[4].optime));
+ });
+
+ return status.members &&
+ status.members[2].state == 2 &&
+ status.members[3].state == 2 &&
+ status.members[4].state == 2 &&
+ friendlyEqual(status.members[3].optime, status.members[4].optime) &&
+ friendlyEqual(status.members[2].optime, status.members[4].optime);
+ });
+
+print("bring master back up, make sure everything's okay");
+replTest.restart(0);
+
+print("wait for sync");
+wait(function() {
+ var status = replTest.liveNodes.slaves[0].getDB("admin").runCommand({replSetGetStatus:1});
+ occasionally(function() {
+ printjson(status);
+ });
+ return status.members &&
+ status.members[2].state == 2 &&
+ status.members[3].state == 2 &&
+ status.members[4].state == 2 &&
+ friendlyEqual(status.members[3].optime, status.members[4].optime) &&
+ friendlyEqual(status.members[2].optime, status.members[4].optime);
+ });
diff --git a/jstests/replsets/toostale.js b/jstests/replsets/toostale.js
new file mode 100644
index 0000000..0b8da0d
--- /dev/null
+++ b/jstests/replsets/toostale.js
@@ -0,0 +1,121 @@
+
+// this tests that:
+// * stale members get into state 3 (recovering)
+// * they stay in state 3 after restarting
+// * they can recover and go into state 2 if someone less up-to-date becomes primary
+
+/*
+ * 1: initial insert
+ * 2: initial sync
+ * 3: blind s2
+ * 4: overflow oplog
+ * 5: unblind s2
+ * 6: check s2.state == 3
+ * 7: restart s2
+ * 8: check s2.state == 3
+ */
+
+
+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.bar.stats();
+ return true;
+ } catch(e) {
+ print(e);
+ return false;
+ }
+ });
+};
+
+
+var name = "toostale"
+var replTest = new ReplSetTest( {name: name, nodes: 3});
+
+var nodes = replTest.startSet();
+replTest.initiate();
+var master = replTest.getMaster();
+var mdb = master.getDB("foo");
+
+
+print("1: initial insert");
+mdb.foo.save({a: 1000});
+
+
+print("2: initial sync");
+replTest.awaitReplication();
+
+print("3: blind 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 });
+print("okay");
+
+print("4: overflow oplog");
+reconnect(master.getDB("local"));
+var count = master.getDB("local").oplog.rs.count();
+var prevCount = -1;
+while (count != prevCount) {
+ print("inserting 10000");
+ for (var i = 0; i < 10000; i++) {
+ mdb.bar.insert({x:i, date : new Date(), str : "safkaldmfaksndfkjansfdjanfjkafa"});
+ }
+ prevCount = count;
+ replTest.awaitReplication();
+ count = master.getDB("local").oplog.rs.count();
+ print("count: "+count+" prev: "+prevCount);
+}
+
+
+print("5: unblind 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 });
+print("okay");
+
+
+print("6: check s2.state == 3");
+var goStale = function() {
+ wait(function() {
+ var status = master.getDB("admin").runCommand({replSetGetStatus:1});
+ printjson(status);
+ return status.members[2].state == 3;
+ });
+};
+goStale();
+
+
+print("7: restart s2");
+replTest.stop(2);
+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});
+}
+
+printjson(status);
+assert.eq(status.members[2].state, 3, 'recovering');
+
+
+replTest.stopSet(15);
diff --git a/jstests/replsets/two_initsync.js b/jstests/replsets/two_initsync.js
index 6ae8475..7d1442d 100755
--- a/jstests/replsets/two_initsync.js
+++ b/jstests/replsets/two_initsync.js
@@ -32,6 +32,7 @@ function wait(f) {
if (++n == 4) {
print("" + f);
}
+ assert(n < 200, 'tried 200 times, giving up');
sleep(1000);
}
}
diff --git a/jstests/replsets/twosets.js b/jstests/replsets/twosets.js
index 7cf367b..aae1113 100644
--- a/jstests/replsets/twosets.js
+++ b/jstests/replsets/twosets.js
@@ -5,19 +5,13 @@ 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();
-
- sleep(5000);
-
- orig.initiate();
interloper.initiate();
- sleep(5000);
-
- var master = orig.getMaster();
-
var conf = master.getDB("local").system.replset.findOne();
var nodes = interloper.nodeList();
@@ -26,8 +20,13 @@ doTest = function( signal ) {
conf.members.push({_id : id, host : host});
conf.version++;
- var result = master.getDB("admin").runCommand({replSetReconfig : conf});
-
+ try {
+ var result = master.getDB("admin").runCommand({replSetReconfig : conf});
+ }
+ catch(e) {
+ print(e);
+ }
+
// now... stuff should blow up?
sleep(10);