diff options
Diffstat (limited to 'jstests/replsets')
44 files changed, 1190 insertions, 322 deletions
diff --git a/jstests/replsets/auth1.js b/jstests/replsets/auth1.js index 40a131a3e44..0d0ca76d1c0 100644 --- a/jstests/replsets/auth1.js +++ b/jstests/replsets/auth1.js @@ -8,9 +8,7 @@ var path = "jstests/libs/"; print("try starting mongod with auth"); -var pargs = new MongodRunner( port[4], "/data/db/wrong-auth", false, false, - ["--auth"], {no_bind : true} ); -var m = pargs.start(); +var m = MongoRunner.runMongod({auth : "", port : port[4], dbpath : "/data/db/wrong-auth"}); assert.eq(m.getDB("local").auth("__system", ""), 0); @@ -25,8 +23,9 @@ run("chmod", "644", path+"key2"); print("try starting mongod"); 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"); +assert.eq(m, _isWindows()? 100 : 2, "mongod should exit w/ 2: permissions too open"); stopMongod(port[0]); @@ -43,6 +42,7 @@ print("make sure user is written before shutting down"); m.getDB("test").getLastError(); stopMongod(port[0]); +if ( !_isWindows() ) { // SERVER-5024 print("start up rs"); var rs = new ReplSetTest({"name" : name, "nodes" : 3, "startPort" : port[0]}); @@ -160,7 +160,7 @@ 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.members.push({_id : 3, host : rs.host+":"+port[3]}); config.version++; try { master.adminCommand({replSetReconfig:config}); @@ -214,3 +214,4 @@ assert.soon(function() { } return true; }); + } // !isWindows
\ No newline at end of file diff --git a/jstests/replsets/auth2.js b/jstests/replsets/auth2.js index 0fe1ae404de..4a38c387aee 100644 --- a/jstests/replsets/auth2.js +++ b/jstests/replsets/auth2.js @@ -1,3 +1,4 @@ +if ( !_isWindows() ) { //SERVER-5024 var name = "rs_auth2"; var port = allocatePorts(3); var path = "jstests/libs/"; @@ -40,6 +41,7 @@ var checkInvalidAuthStates = function() { assert.soon(function() { try { var result = m.getDB("admin").runCommand({isMaster: 1}); + printjson(result); return !result.ismaster && !result.secondary; } catch ( e ) { @@ -53,6 +55,7 @@ var checkInvalidAuthStates = function() { assert.soon(function() { var result = m.getDB("admin").runCommand({isMaster: 1}); + printjson(result); return !result.ismaster && !result.secondary; }); @@ -61,6 +64,7 @@ var checkInvalidAuthStates = function() { assert.soon(function() { var result = m.getDB("admin").runCommand({isMaster: 1}); + printjson(result); return result.secondary; }); @@ -71,6 +75,7 @@ var checkInvalidAuthStates = function() { var checkValidAuthState = function() { assert.soon(function() { var result = m.getDB("admin").runCommand({isMaster : 1}); + printjson(result); return result.secondary; }); }; @@ -79,7 +84,7 @@ var rs = setupReplSet(); var master = rs.getMaster(); print("add an admin user"); -master.getDB("admin").addUser("foo","bar"); +master.getDB("admin").addUser("foo","bar",false,3); m = rs.nodes[0]; print("starting 1 and 2 with key file"); @@ -101,3 +106,4 @@ rs.stop(0); m = rs.restart(0, {"keyFile" : path+"key1"}); print("0 becomes a secondary"); +} // !_isWindows()
\ No newline at end of file diff --git a/jstests/replsets/auth3.js b/jstests/replsets/auth3.js new file mode 100644 index 00000000000..7408e8a34a5 --- /dev/null +++ b/jstests/replsets/auth3.js @@ -0,0 +1,69 @@ +if ( !_isWindows() ) { // SERVER-5024 +var path = "jstests/libs/"; + +var rs = new ReplSetTest({"nodes" : {node0 : {}, node1 : {}, arbiter : {}}, keyFile : path+"key1"}); +rs.startSet(); +rs.initiate(); + +master = rs.getMaster(); +print("adding user"); +master.getDB("admin").addUser("foo", "bar", false, 2); + +var checkValidState = function(i) { + assert.soon(function() { + var result = rs.nodes[i].getDB("admin").runCommand({isMaster : 1}); + printjson(result); + return result.secondary || result.ismaster; + }); +}; + +var safeInsert = function() { + master = rs.getMaster(); + master.getDB("admin").auth("foo", "bar"); + master.getDB("foo").bar.insert({x:1}); + var insertWorked = master.getDB("foo").runCommand({getlasterror:1}); + printjson(insertWorked); + assert.eq(insertWorked.ok, 1); +} + +print("authing"); +assert.soon(function() { + for (var i=0; i<2; i++) { + checkValidState(i); + + // if this is run before initial sync finishes, we won't be logged in + var res = rs.nodes[i].getDB("admin").auth("foo", "bar"); + if (res != 1) { + print("couldn't log into "+rs.nodes[i].host); + return false; + } + } + return true; +}); + +print("make common point"); + +safeInsert(); +rs.awaitReplication(); + +print("write stuff to 0&2") +rs.stop(1); + +master = rs.getMaster(); +master.getDB("foo").bar.drop(); +print("last op: "+tojson(master.getDB("local").oplog.rs.find().sort({$natural:-1}).limit(1).next())); + +print("write stuff to 1&2") +rs.stop(0); +rs.restart(1); + +safeInsert(); +print("last op: "+tojson(master.getDB("local").oplog.rs.find().sort({$natural:-1}).limit(1).next())); + +rs.restart(0); + +print("doing rollback!"); + +checkValidState(0); +checkValidState(1); +} // !_isWindows()
\ No newline at end of file diff --git a/jstests/replsets/capped_id.js b/jstests/replsets/capped_id.js new file mode 100644 index 00000000000..2fd3369e277 --- /dev/null +++ b/jstests/replsets/capped_id.js @@ -0,0 +1,145 @@ +// Check that capped collections get an _id index when replicated + +// Test # +// 0) create capped collection on replset, check _id index appears on secondary +// 1) create normal collection, then convertToCapped, check _id index on secondaries +// 2) create capped collection, do updates instead of inserts, check _id index on secondaries +// 3) create capped collection with autoIndexId=false. make sure no _id index. then create one +// and check it got created on secondaries. + +// Create a new replica set test with name 'testSet' and 3 members +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(); + +// wait for secondaries to be up, since we'll be reading from them +replTest.awaitSecondaryNodes(); +// And get the slaves from the liveNodes +var slave1 = replTest.liveNodes.slaves[0]; +var slave2 = replTest.liveNodes.slaves[1]; + +// Calling getMaster made available the liveNodes structure, +// which looks like this: +// liveNodes = {master: masterNode, slaves: [slave1, slave2] } +printjson( replTest.liveNodes ); + +// define db names to use for this test +var dbname = "dbname"; +var masterdb = master.getDB( dbname ); +var slave1db = slave1.getDB( dbname ); +var slave2db = slave2.getDB( dbname ); + +var numtests = 4; +for( testnum=0; testnum < numtests; testnum++ ){ + + //define collection name + coll = "coll" + testnum; + + // drop the coll on the master (just in case it already existed) + // and wait for the drop to replicate + masterdb.getCollection( coll ).drop(); + replTest.awaitReplication(); + + if ( testnum == 0 ){ + // create a capped collection on the master + // insert a bunch of things in it + // wait for it to replicate + masterdb.runCommand( {create : coll , capped : true , size : 1024} ); + for(i=0; i < 500 ; i++){ + masterdb.getCollection( coll ).insert( {a: 1000} ); + } + replTest.awaitReplication(); + } + else if ( testnum == 1 ){ + // create a non-capped collection on the master + // insert a bunch of things in it + // wait for it to replicate + masterdb.runCommand( {create : coll } ); + for(i=0; i < 500 ; i++){ + masterdb.getCollection( coll ).insert( {a: 1000} ); + } + replTest.awaitReplication(); + + // make sure _id index exists on primary + assert.eq( 1 , + masterdb.system.indexes.find( { key:{"_id" : 1}, ns: dbname + "." + coll } ).count() , + "master does not have _id index on normal collection"); + + // then convert it to capped + masterdb.runCommand({convertToCapped: coll , size: 1024 } ); + replTest.awaitReplication(); + } + else if ( testnum == 2 ){ + // similar to first test, but check that a bunch of updates instead + // of inserts triggers the _id index creation on secondaries. + masterdb.runCommand( {create : coll , capped : true , size : 1024} ); + masterdb.getCollection( coll ).insert( {a : 0} ); + for(i=0; i < 500 ; i++){ + masterdb.getCollection( coll ).update( {} , {$inc : {a : 1} } ); + } + replTest.awaitReplication(); + } + else if ( testnum == 3 ){ + // explicitly set autoIndexId : false + masterdb.runCommand( {create : coll , capped : true , size : 1024 , autoIndexId : false } ) + for(i=0; i < 500 ; i++){ + masterdb.getCollection( coll ).insert( {a: 1000} ); + } + replTest.awaitReplication(); + + assert.eq( 0 , + masterdb.system.indexes.find( { key:{"_id" : 1}, ns: dbname + "." + coll } ).count() , + "master has an _id index on capped collection when autoIndexId is false"); + assert.eq( 0 , + slave1db.system.indexes.find( { key:{"_id" : 1}, ns: dbname + "." + coll } ).count() , + "slave1 has an _id index on capped collection when autoIndexId is false"); + assert.eq( 0 , + slave2db.system.indexes.find( { key:{"_id" : 1}, ns: dbname + "." + coll } ).count() , + "slave2 has an _id index on capped collection when autoIndexId is false"); + + // now create the index and make sure it works + masterdb.getCollection( coll ).ensureIndex( { "_id" : 1 } ); + replTest.awaitReplication(); + } + + // what indexes do we have? + print("**********Master indexes:**********"); + masterdb.system.indexes.find().forEach(printjson); + print(""); + + print("**********Slave1 indexes:**********"); + slave1db.system.indexes.find().forEach(printjson); + print(""); + + print("**********Slave2 indexes:**********"); + slave2db.system.indexes.find().forEach(printjson); + print(""); + + // insure all nodes have _id index + assert.eq( 1 , + masterdb.system.indexes.find( { key:{"_id" : 1}, ns: dbname + "." + coll } ).count() , + "master has an _id index on capped collection"); + assert.eq( 1 , + slave1db.system.indexes.find( { key:{"_id" : 1}, ns: dbname + "." + coll } ).count() , + "slave1 does not have _id index on capped collection"); + assert.eq( 1 , + slave2db.system.indexes.find( { key:{"_id" : 1}, ns: dbname + "." + coll } ).count() , + "slave2 does not have _id index on capped collection"); + + print("capped_id.js Test # " + testnum + " SUCCESS"); +} + +//Finally, stop set +replTest.stopSet(); + + diff --git a/jstests/replsets/cloneDb.js b/jstests/replsets/cloneDb.js index 2519c09b42b..d6356031e2c 100644 --- a/jstests/replsets/cloneDb.js +++ b/jstests/replsets/cloneDb.js @@ -19,7 +19,10 @@ doTest = function( signal ) { print("Insert data"); for (var i = 0; i < N; i++) { db1['foo'].insert({x: i, text: Text}) - db1.getLastError(2) // wait to be copied to at least one secondary + var le = db1.getLastErrorObj(2, 1000); // wait to be copied to at least one secondary + if (le.err) { + printjson(le); + } } print("Create single server"); @@ -50,5 +53,9 @@ doTest = function( signal ) { repset.stopSet( signal ) } -doTest( 15 );
-print("replsets/cloneDb.js SUCCESS");
+if (jsTest.options().keyFile) { + print("Skipping test because clone command doesn't work with authentication enabled: SERVER-4245") +} else { + doTest( 15 ); + print("replsets/cloneDb.js SUCCESS"); +} diff --git a/jstests/replsets/fastsync.js b/jstests/replsets/fastsync.js index 1c9c2152ebb..06da6a8d82b 100644 --- a/jstests/replsets/fastsync.js +++ b/jstests/replsets/fastsync.js @@ -97,9 +97,21 @@ var startSlave = function(n) { config.version++; config.members.push({_id:n, host:hostname+":"+ports[n]}); - result = admin.runCommand({replSetReconfig : config}); - printjson(result); - assert(result.ok, "reconfig worked"); + // When the slave is started, it'll try to load the config and find that it's + // not in the config and close all connections in preparation for transitioning + // to "removed" state. If the reconfig adding it to the set happens to occur at + // this point, the heartbeat request's connection will be cut off, causing the + // reconfig to fail.. + assert.soon(function() { + try { + result = admin.runCommand({replSetReconfig : config}); + } + catch (e) { + print("failed to reconfig: "+e); + return false; + } + return result.ok; + }); reconnect(p); print("4"); @@ -132,10 +144,16 @@ var startSlave = function(n) { admin.foo.insert({x:1}); assert.soon(function() { - var last = local.oplog.rs.find().sort({$natural:-1}).limit(1).next(); - var cur = conn.getDB("local").oplog.rs.find().sort({$natural:-1}).limit(1).next(); - print("last: "+tojson(last)+" cur: "+tojson(cur)); - return cur != null && last != null && cur.ts.t == last.ts.t && cur.ts.i == last.ts.i; + try { + var last = local.oplog.rs.find().sort({$natural:-1}).limit(1).next(); + var cur = conn.getDB("local").oplog.rs.find().sort({$natural:-1}).limit(1).next(); + print("last: "+tojson(last)+" cur: "+tojson(cur)); + return cur != null && last != null && cur.ts.t == last.ts.t && cur.ts.i == last.ts.i; + } + catch (e) { + print(e); + } + return false; }); return conn; @@ -143,10 +161,19 @@ var startSlave = function(n) { var s1 = startSlave(1); -var me1 = s1.getDB("local").me.findOne(); +var me1 = null; + +// local.me will not be populated until the secondary reports back to the +// primary that it is syncing +assert.soon(function() { + me1 = s1.getDB("local").me.findOne(); + if (me1 == null) { + return false; + } -print("me: " +me1._id); -assert(me1._id != null); + print("me: " +me1._id); + return me1._id != null; +}); print("5"); s1.getDB("admin").runCommand( {fsync:1,lock:1} ); @@ -172,14 +199,25 @@ sleep(10000); pargs = new MongodRunner( ports[ 3 ], basePath + "-p", false, false, ["--replSet", basename, "--oplogSize", 2], {no_bind : true} ); -p = pargs.start(true); +pargs.start(true); -printjson(p.getDB("admin").runCommand({replSetGetStatus:1})); +p = new Mongo("localhost:"+ports[3]); -p.getDB("admin").runCommand({replSetReconfig : { - _id : basename, - members : [{_id:0, host : hostname+":"+ports[3]}] +// initFromConfig will keep closing sockets, so we'll a couple of times +assert.soon(function() { + try { + p.getDB("admin").runCommand({replSetReconfig : { + _id : basename, + members : [{_id:0, host : hostname+":"+ports[3]}] }, force : true}); + } + catch (e) { + print(e); + return false; + } + + return true; +}); print("start waiting for primary..."); assert.soon(function() { diff --git a/jstests/replsets/fsync_lock_read_secondaries.js b/jstests/replsets/fsync_lock_read_secondaries.js new file mode 100644 index 00000000000..b89c01dd52c --- /dev/null +++ b/jstests/replsets/fsync_lock_read_secondaries.js @@ -0,0 +1,61 @@ +/* @file : jstests/fsync_lock_read_secondaries.js + * + * SERVER 4243 : If there is a pending write due to an fsync lock, all reads are blocked + * + * This test validates part of SERVER-4243 ticket. Allow reading on secondaries with fsyncLock + * mode enabled. Previously oplog application would cause blocking. + * The corresponding commit : + * https://github.com/mongodb/mongo/commit/73aa870d129bd7d51de946b91c16cc056aaacbc7 + */ + +/* + * 1) Create a replica set. + * 2) Add some documents to master. + * 3) Wait until the secondary nodes are in state "SECONDARY". + * 4) Set slaveOk on secondary. + * 5) Take the fsync lock on a secondary. This will stop replication. + * 6) Insert some more documents to master. + * 7) Expect to be able to read from the secondary; the count of documents should + * be equal to the number of documents added in step 2. + * 8) Release the fsync lock. This will resume replication. + * 9) Soon, the secondary should be applying the oplog again, which we should + * witness as an increase in the count of documents stored on the secondary. + */ + +// Load utility methods for replica set tests +load("jstests/replsets/rslib.js"); + +var replTest = new ReplSetTest({name: 'testSet', nodes: 2, oplogSize: 5}); +// Start each mongod in the replica set. Returns a list of nodes +var nodes = replTest.startSet(); +// This will wait for initiation +replTest.initiate(); +var master = replTest.getMaster(); +var docNum = 100; +for(var i=0; i<docNum; i++) { + master.getDB("foo").bar.save({a: i}); +} +waitForAllMembers(master.getDB("foo")); + +// Calling getMaster also makes available the liveNodes structure, which looks like this: +// liveNodes = {master: masterNode, slaves: [slave1, slave2] } +var slaves = replTest.liveNodes.slaves; +slaves[0].setSlaveOk(); + +assert.commandWorked(slaves[0].getDB("admin").runCommand({fsync:1, lock: 1})); +var docNum = 1000; +for (var i=0; i<docNum; i++) { + master.getDB("foo").bar.save({a: i}); +} +// Issue a read query on the secondary while holding the fsync lock. +// This is what we are testing. Previously this would block. After the fix +// this should work just fine. +var slave0count = slaves[0].getDB("foo").bar.count(); +assert.eq(slave0count, 100, "Doc count in fsync lock wrong. Expected (=100), found " + slave0count); +assert(slaves[0].getDB("admin").$cmd.sys.unlock.findOne().ok); + +// The secondary should have equal or more documents than what it had before. +assert.soon(function() { + return slaves[0].getDB("foo").bar.count() > 100 + }, "count of documents stored on the secondary did not increase"); +replTest.stopSet(); diff --git a/jstests/replsets/getlasterror_w2.js b/jstests/replsets/getlasterror_w2.js deleted file mode 100644 index 795e6671d46..00000000000 --- a/jstests/replsets/getlasterror_w2.js +++ /dev/null @@ -1,36 +0,0 @@ -// 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 index 539fe44b264..a60ce82f5f8 100644 --- a/jstests/replsets/groupAndMapReduce.js +++ b/jstests/replsets/groupAndMapReduce.js @@ -1,3 +1,5 @@ +load("jstests/replsets/rslib.js"); + doTest = function( signal ) { // Test basic replica set functionality. @@ -26,11 +28,10 @@ doTest = function( signal ) { master.getDB("foo").foo.save({a: i}); } + waitForAllMembers(master.getDB("foo")); // 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 ); @@ -101,5 +102,5 @@ doTest = function( signal ) { replTest.stopSet( signal ); } -doTest( 15 );
-print("SUCCESS");
+doTest( 15 ); +print("SUCCESS"); diff --git a/jstests/replsets/initSyncV1Index.js b/jstests/replsets/initSyncV1Index.js new file mode 100644 index 00000000000..deec0177382 --- /dev/null +++ b/jstests/replsets/initSyncV1Index.js @@ -0,0 +1,32 @@ +// Create {v:0} index on primary. Add new secondary. Make sure same index on secondary is {v:1} - SERVER-3852 + +var rs = new ReplSetTest( {name: 'rs', nodes: 1, host: 'localhost'} ); +rs.startSet(); +rs.initiate(); +var r1 = rs.getMaster(); +var db1 = r1.getDB('test'); + +var t = ''; +for (var i = 0; i < 1000; i++) t += 'a'; +for (var i = 0; i < 10000; i++) db1.foo.insert( {_id:i, x:i%1000, t:t} ); +db1.foo.createIndex( {x:1}, {v: 0} ); + +var r2 = rs.add(); +rs.reInitiate(); +rs.awaitSecondaryNodes(); +var db2 = r2.getDB('test'); +r2.setSlaveOk(); + +var idx = db2.system.indexes.findOne( {key: {x:1}} ); +assert.eq (idx.v, 1, 'expected all indexes generated on Mongo version >= 2.0 to be {v:1}. See SERVER-3852'); + +// add another new node, make sure ports _aren't_ closed SERVER-4315 +r1 = rs.getMaster(); +rs.add(); +var c = r1.getDB("local").system.replset.findOne(); +var config = rs.getReplSetConfig(); +config.version = c.version+1; +var result = r1.getDB("admin").runCommand({replSetReconfig:config}); +assert.eq(result.ok, 1); + +rs.stopSet(15); diff --git a/jstests/replsets/initial_sync1.js b/jstests/replsets/initial_sync1.js index 4cfd606ec9c..e2d415d75bb 100644 --- a/jstests/replsets/initial_sync1.js +++ b/jstests/replsets/initial_sync1.js @@ -50,17 +50,14 @@ 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 slave2 = startMongodTest (ports[2], basename, false, {replSet : basename, oplogSize : 2} ) + 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}); } @@ -123,3 +120,9 @@ for (var i=0; i<10000; i++) { print("11. Everyone happy eventually"); replTest.awaitReplication(300000); + +print("13. Check hbmsg"); +master.getDB("admin").runCommand({replSetTest:1, sethbmsg:"foo bar baz"}); +var status = master.getDB("admin").runCommand({replSetGetStatus:1}); +printjson(status); +assert.eq(status.members[0].errmsg, "foo bar baz"); diff --git a/jstests/replsets/initial_sync2.js b/jstests/replsets/initial_sync2.js index 3ad39725834..cc5237a7fb3 100644 --- a/jstests/replsets/initial_sync2.js +++ b/jstests/replsets/initial_sync2.js @@ -54,10 +54,8 @@ 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 slave2 = startMongodTest (ports[2], basename, false, {replSet : basename, oplogSize : 2} ) + var local_s2 = slave2.getDB("local"); var admin_s2 = slave2.getDB("admin"); diff --git a/jstests/replsets/initial_sync3.js b/jstests/replsets/initial_sync3.js index ef45581d618..f63e79b868b 100644 --- a/jstests/replsets/initial_sync3.js +++ b/jstests/replsets/initial_sync3.js @@ -3,6 +3,7 @@ * Make sure member can't sync from a member with a different buildIndexes setting. */ + load("jstests/replsets/rslib.js"); var name = "initialsync3"; var host = getHostName(); @@ -33,7 +34,6 @@ replTest.start(1); print("make sure 1 does not become a secondary (because it cannot clone from 2)"); sleep(10000); -reconnect(nodes[1]); var result = nodes[1].getDB("admin").runCommand({isMaster : 1}); assert(!result.ismaster, tojson(result)); assert(!result.secondary, tojson(result)); @@ -66,7 +66,7 @@ try { master.getDB("admin").runCommand({replSetReconfig : config}); } catch(e) { - print("trying to reconfigure: "+e); + assert((e.message || e) == "error doing query: failed"); } // wait for a heartbeat, too, just in case sync happens before hb @@ -93,8 +93,10 @@ rs2.partition(0, 2); master.getDB("foo").bar.baz.insert({x:1}); rs2.awaitReplication(); +master = rs2.getMaster(); + master.getDB("foo").bar.baz.insert({x:2}); -var x = master.getDB("foo").runCommand({getLastError : 1, w : 3, wtimeout : 5000}); +var x = master.getDB("foo").runCommand({getLastError : 1, w : 3, wtimeout : 60000}); printjson(x); assert.eq(null, x.err); diff --git a/jstests/replsets/initial_sync4.js b/jstests/replsets/initial_sync4.js new file mode 100644 index 00000000000..efcc8e435ed --- /dev/null +++ b/jstests/replsets/initial_sync4.js @@ -0,0 +1,67 @@ +// Test update modifier uassert during initial sync. SERVER-4781 + +if( 0 ) { // SERVER-4781 + +load("jstests/replsets/rslib.js"); +basename = "jstests_initsync4"; + +print("1. Bring up set"); +replTest = new ReplSetTest( {name: basename, nodes: 1} ); +replTest.startSet(); +replTest.initiate(); + +m = replTest.getMaster(); +md = m.getDB("d"); +mc = m.getDB("d")["c"]; + +print("2. Insert some data"); +N = 500000; +for( i = 0; i < N; ++i ) { + mc.save( {_id:i,a:{}} ); +} +md.getLastError(); + +print("3. Make sure synced"); +replTest.awaitReplication(); + +print("4. Bring up a new node"); +ports = allocatePorts( 3 ); +basePath = "/data/db/" + basename; +hostname = getHostName(); + +s = startMongodTest (ports[2], basename, false, {replSet : basename, oplogSize : 2} ); + +var config = replTest.getReplSetConfig(); +config.version = 2; +config.members.push({_id:2, host:hostname+":"+ports[2]}); +try { + m.getDB("admin").runCommand({replSetReconfig:config}); +} +catch(e) { + print(e); +} +reconnect(s); + +print("5. Wait for new node to start cloning"); + +s.setSlaveOk(); +sc = s.getDB("d")["c"]; + +wait( function() { printjson( sc.stats() ); return sc.stats().count > 0; } ); + +print("6. Start updating documents on primary"); +for( i = N-1; i >= N-10000; --i ) { + // If the document is cloned as {a:1}, the {$set:{'a.b':1}} modifier will uassert. + mc.update( {_id:i}, {$set:{'a.b':1}} ); + mc.update( {_id:i}, {$set:{a:1}} ); +} + +print("7. Wait for new node to become SECONDARY"); +wait(function() { + var status = s.getDB("admin").runCommand({replSetGetStatus:1}); + printjson(status); + return status.members && + (status.members[1].state == 2); + }); + +}
\ No newline at end of file diff --git a/jstests/replsets/maintenance.js b/jstests/replsets/maintenance.js index 5b068cd3d8e..65b1ccfd851 100644 --- a/jstests/replsets/maintenance.js +++ b/jstests/replsets/maintenance.js @@ -1,6 +1,6 @@ -var replTest = new ReplSetTest( {name: 'unicomplex', nodes: 3} ); +var replTest = new ReplSetTest( {name: 'unicomplex', nodes: 2} ); var conns = replTest.startSet(); replTest.initiate(); @@ -12,21 +12,70 @@ for (i=0;i<1000; i++) { master.getDB("bar").foo.update({y:i},{$push :{foo : "bar replTest.awaitReplication(); -assert.soon(function() { return conns[2].getDB("admin").isMaster().secondary; }); +assert.soon(function() { return conns[1].getDB("admin").isMaster().secondary; }); -join = startParallelShell( "db.getSisterDB('bar').runCommand({compact : 'foo'});", replTest.ports[2] ); - -print("check secondary goes to recovering"); -assert.soon(function() { return !conns[2].getDB("admin").isMaster().secondary; }); +join = startParallelShell( "db.getSisterDB('bar').runCommand({compact : 'foo'});", replTest.ports[1] ); print("joining"); join(); print("check secondary becomes a secondary again"); +var secondarySoon = function() { + var x = 0; + assert.soon(function() { + var im = conns[1].getDB("admin").isMaster(); + if (x++ % 5 == 0) printjson(im); + return im.secondary; + }); +}; + +secondarySoon(); + +print("make sure compact works on a secondary (SERVER-3923)"); +master.getDB("foo").bar.drop(); +replTest.awaitReplication(); +var result = conns[1].getDB("foo").runCommand({compact : "bar"}); +assert.eq(result.ok, 0, tojson(result)); + +secondarySoon(); + +print("use replSetMaintenance command to go in/out of maintence mode"); + +print("primary cannot go into maintence mode"); +result = master.getDB("admin").runCommand({replSetMaintenance : 1}); +assert.eq(result.ok, 0, tojson(result)); + +print("check getMore works on a secondary, not on a recovering node"); +var cursor = conns[1].getDB("bar").foo.find(); +for (var i=0; i<50; i++) { + cursor.next(); +} + +print("secondary can"); +result = conns[1].getDB("admin").runCommand({replSetMaintenance : 1}); +assert.eq(result.ok, 1, tojson(result)); + +print("make sure secondary goes into recovering"); var x = 0; assert.soon(function() { - var im = conns[2].getDB("admin").isMaster(); + var im = conns[1].getDB("admin").isMaster(); if (x++ % 5 == 0) printjson(im); - return im.secondary; + return !im.secondary && !im.ismaster; }); +print("now getmore shouldn't work"); +lastDoc = null; +while (cursor.hasNext()) { + lastDoc = cursor.next(); +} + +print("the shell is currently stupid and won't throw once it's returned any query results"); +printjson(lastDoc); +assert("$err" in lastDoc); +assert.eq(lastDoc.code, 13436); + +result = conns[1].getDB("admin").runCommand({replSetMaintenance : 0}); +assert.eq(result.ok, 1, tojson(result)); + +secondarySoon(); + diff --git a/jstests/replsets/maintenance2.js b/jstests/replsets/maintenance2.js new file mode 100644 index 00000000000..463f6c78a4e --- /dev/null +++ b/jstests/replsets/maintenance2.js @@ -0,0 +1,63 @@ +function shouldFail( f ) { + e = assert.throws( function() { + f(); + if( db.getLastError() ) { + throw db.getLastError(); + } + } ); +} + +doTest = function( signal ) { + // Test that certain operations fail in recovery mode + + // 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(); + + slaves = replTest.liveNodes.slaves; + assert( slaves.length == 2, "Expected 2 slaves but length was " + slaves.length ); + + slaves.forEach(function(slave) { + // put slave into maintenance (recovery) mode + slave.getDB("foo").adminCommand({replSetMaintenance:1}); + + stats = slave.getDB("foo").adminCommand({replSetGetStatus:1}); + assert.eq(stats.myState, 3, "Slave should be in recovering state."); + + print("group should fail in recovering state..."); + slave.slaveOk = true; + shouldFail( function() { slave.getDB("foo").foo.group({initial: {n:0}, reduce: function(obj,out){out.n++;}}); } ); + + print("count should fail in recovering state..."); + slave.slaveOk = true; + shouldFail( function() { slave.getDB("foo").foo.count(); } ); + }); + + // Shut down the set and finish the test. + replTest.stopSet( signal ); +} + +doTest( 15 ); +print("SUCCESS"); diff --git a/jstests/replsets/majority.js b/jstests/replsets/majority.js index 5bb3cde33f0..a763dcc9641 100644 --- a/jstests/replsets/majority.js +++ b/jstests/replsets/majority.js @@ -1,3 +1,5 @@ +if (!_isWindows()) { + var testInsert = function() { master.getDB("foo").bar.insert({x:1}); var result = master.getDB("foo").runCommand({getLastError:1, w:"majority", wtimeout:timeout}); @@ -8,7 +10,7 @@ var testInsert = function() { var num = 7; var host = getHostName(); var name = "tags"; -var timeout = 10000; +var timeout = 60000; var replTest = new ReplSetTest( {name: name, nodes: num, startPort:31000} ); var nodes = replTest.startSet(); @@ -94,3 +96,5 @@ master = replTest.getMaster(); print("make sure majority works"); assert.eq(testInsert().err, null); +replTest.stopSet(); +}
\ No newline at end of file diff --git a/jstests/replsets/reconfig.js b/jstests/replsets/reconfig.js index 7d43720b5ad..aba5c5b6519 100644 --- a/jstests/replsets/reconfig.js +++ b/jstests/replsets/reconfig.js @@ -11,13 +11,21 @@ print("initial sync"); master.getDB("foo").bar.insert({X:1}); replTest.awaitReplication(); +print("invalid reconfig"); +var config = master.getDB("local").system.replset.findOne(); +config.version++; +config.members.push({_id : 5, host : "localhost:12345, votes:0"}); +var result = master.adminCommand({replSetReconfig : config}); +printjson(result); +assert.eq(result.ok, 0); + print("stopping 3 & 4"); replTest.stop(3); replTest.stop(4); print("reconfiguring"); master = replTest.getMaster(); -var config = master.getDB("local").system.replset.findOne(); +config = master.getDB("local").system.replset.findOne(); var oldVersion = config.version++; config.members[0].votes = 2; config.members[3].votes = 2; @@ -28,8 +36,16 @@ catch(e) { print(e); } -var config = master.getDB("local").system.replset.findOne(); -assert.eq(oldVersion+1, config.version); +assert.soon(function() { + try { + var config = master.getDB("local").system.replset.findOne(); + return oldVersion+1 == config.version; + } + catch (e) { + print("Query failed: "+e); + return false; + } +}); print("0 & 3 up; 1, 2, 4 down"); diff --git a/jstests/replsets/reindex_secondary.js b/jstests/replsets/reindex_secondary.js new file mode 100644 index 00000000000..d0fd5d71123 --- /dev/null +++ b/jstests/replsets/reindex_secondary.js @@ -0,0 +1,34 @@ +var replTest = new ReplSetTest( {name: 'reindexTest', nodes: 2} ); + +var nodes = replTest.startSet(); + +replTest.initiate(); + +var master = replTest.getMaster(); +replTest.awaitSecondaryNodes() + +var slaves = replTest.liveNodes.slaves; +assert( slaves.length == 1, "Expected 1 slave but length was " + slaves.length ); +slave = slaves[0]; + +db = master.getDB("reindexTest"); +slaveDb = slave.getDB("reindexTest"); + +// Setup index +db.foo.insert({a:1000}); + +db.foo.ensureIndex({a:1}); + +replTest.awaitReplication(); + +assert.eq(2, db.system.indexes.count(), "Master didn't have proper indexes before reindex"); +assert.eq(2, slaveDb.system.indexes.count(), "Slave didn't have proper indexes before reindex"); + + +// Try to reindex secondary +slaveDb.foo.reIndex(); + +assert.eq(2, db.system.indexes.count(), "Master didn't have proper indexes after reindex"); +assert.eq(2, slaveDb.system.indexes.count(), "Slave didn't have proper indexes after reindex"); + +replTest.stopSet(15);
\ No newline at end of file diff --git a/jstests/replsets/remove1.js b/jstests/replsets/remove1.js index f93fe9eb071..a1bbc75b99d 100644 --- a/jstests/replsets/remove1.js +++ b/jstests/replsets/remove1.js @@ -1,53 +1,54 @@ /* test removing a node from a replica set * - * Start set with three nodes + * Start set with two 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 + * Remove secondary + * Bring secondary back up + * Add it back as secondary + * Make sure both nodes are either primary or secondary */ load("jstests/replsets/rslib.js"); var name = "removeNodes"; var host = getHostName(); - -print("Start set with three nodes"); +print("Start set with two nodes"); var replTest = new ReplSetTest( {name: name, nodes: 2} ); 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 slaves"); +print("Remove secondary"); var config = replTest.getReplSetConfig(); config.members.pop(); config.version = 2; + +assert.eq(replTest.nodes[1].getDB("admin").runCommand({ping:1}).ok, 1, "we are connected to node[1]"); + +try { + master.getDB("admin").runCommand({replSetReconfig:config}); +} +catch(e) { + print(e); +} + +assert.throws(replTest.nodes[1].getDB("admin").runCommand({ping:1}).ok, 1, "we are not connected to node[1]"); +assert.eq(replTest.nodes[1].getDB("admin").runCommand({ping:1}).ok, 1, "we are connected to node[1]"); + +reconnect(master); + assert.soon(function() { - try { - master.getDB("admin").runCommand({replSetReconfig:config}); - } - catch(e) { - print(e); - } - - reconnect(master); - reconnect(replTest.nodes[1]); var c = master.getDB("local").system.replset.findOne(); return c.version == 2; - }); +}); -print("Add it back as a slave"); +print("Add it back as a secondary"); config.members.push({_id:1, host : host+":"+replTest.getPort(1)}); config.version = 3; printjson(config); @@ -67,8 +68,7 @@ wait(function() { return newConfig.version == 3; } , "wait1" ); - -print("Make sure everyone's secondary"); +print("Make sure both nodes are either primary or secondary"); wait(function() { var status = master.getDB("admin").runCommand({replSetGetStatus:1}); occasionally(function() { @@ -87,7 +87,6 @@ wait(function() { return true; } , "wait2" ); - print("reconfig with minority"); replTest.stop(1); @@ -98,7 +97,7 @@ assert.soon(function() { catch(e) { print("trying to get master: "+e); } -}); +},"waiting for primary to step down",(60*1000),1000); config.version = 4; config.members.pop(); @@ -112,11 +111,10 @@ catch(e) { reconnect(master); assert.soon(function() { return master.getDB("admin").runCommand({isMaster : 1}).ismaster; -}); +},"waiting for old primary to accept reconfig and step up",(60*1000),1000); config = master.getDB("local").system.replset.findOne(); printjson(config); assert(config.version > 4); replTest.stopSet(); - diff --git a/jstests/replsets/replset1.js b/jstests/replsets/replset1.js index 6387c5d8624..4b48f980cef 100644 --- a/jstests/replsets/replset1.js +++ b/jstests/replsets/replset1.js @@ -1,3 +1,5 @@ +load("jstests/replsets/rslib.js") + doTest = function( signal ) { // Test basic replica set functionality. @@ -43,7 +45,7 @@ doTest = function( signal ) { var temp = replTest.getURL(); temp = temp.substring( 0 , temp.lastIndexOf( "," ) ); temp = new Mongo( temp ).getDB( "foo" ); - assert.eq( 1000 , temp.foo.findOne().a , "cppconn 1" ); + assert.eq( 1000 , temp.foo.findOne().a , "cppconn 1" ); } @@ -59,16 +61,8 @@ doTest = function( signal ) { assert( master_id != new_master_id, "Old master shouldn't be equal to new master." ); - { - // this may fail since it has to reconnect - try { - cppconn.foo.findOne() - } - catch ( e ){ - } - assert.eq( 1000 , cppconn.foo.findOne().a , "cppconn 2" ); - - } + reconnect(cppconn); + assert.eq( 1000 , cppconn.foo.findOne().a , "cppconn 2" ); // Now let's write some documents to the new master for(var i=0; i<1000; i++) { @@ -121,7 +115,11 @@ doTest = function( signal ) { t.save({a: 1000}); t.ensureIndex( { a : 1 } ) - db.getLastError( 3 , 30000 ) + result = db.runCommand({getLastError : 1, w: 3 , wtimeout :30000 }) + printjson(result); + lastOp = result.lastOp; + lastOplogOp = master.getDB("local").oplog.rs.find().sort({$natural : -1}).limit(1).next(); + assert.eq(lastOplogOp['ts'], lastOp); ts.forEach( function(z){ assert.eq( 2 , z.getIndexKeys().length , "A " + z.getMongo() ); } ) @@ -134,5 +132,5 @@ doTest = function( signal ) { replTest.stopSet( signal ); } -doTest( 15 );
-print("replset1.js SUCCESS");
+doTest( 15 ); +print("replset1.js SUCCESS"); diff --git a/jstests/replsets/replset2.js b/jstests/replsets/replset2.js index 484962036ef..9588567ea50 100644 --- a/jstests/replsets/replset2.js +++ b/jstests/replsets/replset2.js @@ -1,4 +1,4 @@ -print("\n\nreplset2.js BEGIN"); +load("jstests/replsets/rslib.js"); doTest = function (signal) { @@ -28,8 +28,8 @@ doTest = function (signal) { // Wait for replication to a single node master.getDB(testDB).bar.insert({ n: 1 }); - // Wait for initial sync - replTest.awaitReplication(); + // Wait for states to become PRI,SEC,SEC + waitForAllMembers(master.getDB(testDB)); var slaves = replTest.liveNodes.slaves; slaves.forEach(function (slave) { slave.setSlaveOk(); }); diff --git a/jstests/replsets/replset4.js b/jstests/replsets/replset4.js index 9b1f2e9e1f9..2b06567cfff 100644 --- a/jstests/replsets/replset4.js +++ b/jstests/replsets/replset4.js @@ -1,44 +1,44 @@ -doTest = function (signal) {
-
- // Test orphaned master steps down
- var replTest = new ReplSetTest({ name: 'testSet', nodes: 3 });
-
- replTest.startSet();
- replTest.initiate();
-
- var master = replTest.getMaster();
-
- // Kill both slaves, simulating a network partition
- var slaves = replTest.liveNodes.slaves;
- for (var i = 0; i < slaves.length; i++) {
- var slave_id = replTest.getNodeId(slaves[i]);
- replTest.stop(slave_id);
- }
-
- print("replset4.js 1");
-
- var result = master.getDB("admin").runCommand({ ismaster: 1 });
-
- print("replset4.js 2");
- printjson(result);
-
- assert.soon(
- function () {
- try {
- var result = master.getDB("admin").runCommand({ ismaster: 1 });
- return (result['ok'] == 1 && result['ismaster'] == false);
- } catch (e) {
- print("replset4.js caught " + e);
- return false;
- }
- },
- "Master fails to step down when orphaned."
- );
-
- print("replset4.js worked, stopping");
- replTest.stopSet(signal);
-}
-
+doTest = function (signal) { + + // Test orphaned master steps down + var replTest = new ReplSetTest({ name: 'testSet', nodes: 3 }); + + replTest.startSet(); + replTest.initiate(); + + var master = replTest.getMaster(); + + // Kill both slaves, simulating a network partition + var slaves = replTest.liveNodes.slaves; + for (var i = 0; i < slaves.length; i++) { + var slave_id = replTest.getNodeId(slaves[i]); + replTest.stop(slave_id); + } + + print("replset4.js 1"); + + var result = master.getDB("admin").runCommand({ ismaster: 1 }); + + print("replset4.js 2"); + printjson(result); + + assert.soon( + function () { + try { + var result = master.getDB("admin").runCommand({ ismaster: 1 }); + return (result['ok'] == 1 && result['ismaster'] == false); + } catch (e) { + print("replset4.js caught " + e); + return false; + } + }, + "Master fails to step down when orphaned." + ); + + print("replset4.js worked, stopping"); + replTest.stopSet(signal); +} + print("replset4.js"); doTest( 15 ); print("replset4.js SUCCESS"); diff --git a/jstests/replsets/replset6.js b/jstests/replsets/replset6.js new file mode 100644 index 00000000000..f9111e28dbd --- /dev/null +++ b/jstests/replsets/replset6.js @@ -0,0 +1,52 @@ + +// Test replication of collection renaming + +baseName = "jstests_replsets_replset6"; + +var rt = new ReplSetTest({ name : "replset6tests" , nodes: 2 }); +var nodes = rt.startSet(); +rt.initiate(); +var m = rt.getMaster(); +rt.awaitSecondaryNodes(); +var slaves = rt.liveNodes.slaves; +s = slaves[0]; +s.setSlaveOk(); +admin = m.getDB( "admin" ); + +debug = function( foo ) {} // print( foo ); } + +// rename within db + +m.getDB( baseName ).one.save( { a: 1 } ); +assert.soon( function() { v = s.getDB( baseName ).one.findOne(); return v && 1 == v.a } ); + +assert.commandWorked( admin.runCommand( {renameCollection:"jstests_replsets_replset6.one", to:"jstests_replsets_replset6.two"} ) ); +assert.soon( function() { + if ( -1 == s.getDB( baseName ).getCollectionNames().indexOf( "two" ) ) { + debug( "no two coll" ); + debug( tojson( s.getDB( baseName ).getCollectionNames() ) ); + return false; + } + if ( !s.getDB( baseName ).two.findOne() ) { + debug( "no two object" ); + return false; + } + return 1 == s.getDB( baseName ).two.findOne().a; }); +assert.eq( -1, s.getDB( baseName ).getCollectionNames().indexOf( "one" ) ); + +// rename to new db + +first = baseName + "_first"; +second = baseName + "_second"; + +m.getDB( first ).one.save( { a: 1 } ); +assert.soon( function() { return s.getDB( first ).one.findOne() && 1 == s.getDB( first ).one.findOne().a; } ); + +assert.commandWorked( admin.runCommand( {renameCollection:"jstests_replsets_replset6_first.one", to:"jstests_replsets_replset6_second.two"} ) ); +assert.soon( function() { + return -1 != s.getDBNames().indexOf( second ) && + -1 != s.getDB( second ).getCollectionNames().indexOf( "two" ) && + s.getDB( second ).two.findOne() && + 1 == s.getDB( second ).two.findOne().a; } ); +assert.eq( -1, s.getDB( first ).getCollectionNames().indexOf( "one" ) ); + diff --git a/jstests/replsets/replset7.js b/jstests/replsets/replset7.js index f29c1fbb953..0c4cbe2b841 100644 --- a/jstests/replsets/replset7.js +++ b/jstests/replsets/replset7.js @@ -11,7 +11,7 @@ var md = master.getDB( 'd' ); var mdc = md[ 'c' ]; // prep the data -var doccount = 100000; +var doccount = 50000; for( i = 0; i < doccount; ++i ) { mdc.insert( { _id:i, x:i } ); } diff --git a/jstests/replsets/replset8.js b/jstests/replsets/replset8.js new file mode 100644 index 00000000000..cc900195cde --- /dev/null +++ b/jstests/replsets/replset8.js @@ -0,0 +1,61 @@ + +// test for SERVER-6303 - if documents move backward during an initial sync. + +var rt = new ReplSetTest( { name : "replset8tests" , nodes: 1 } ); + +var nodes = rt.startSet(); +rt.initiate(); +var master = rt.getMaster(); +var bigstring = "a"; +var md = master.getDB( 'd' ); +var mdc = md[ 'c' ]; + +// prep the data + +// idea: create x documents of increasing size, then create x documents of size n. +// delete first x documents. start initial sync (cloner). update all remaining +// documents to be increasing size. +// this should result in the updates moving the docs backwards. + +var doccount = 10000; +// Avoid empty extent issues +mdc.insert( { _id:-1, x:"dummy" } ); + +print ("inserting bigstrings"); +for( i = 0; i < doccount; ++i ) { + mdc.insert( { _id:i, x:bigstring } ); + bigstring += "a"; +} +md.getLastError(); + +print ("inserting x"); +for( i = doccount; i < doccount*2; ++i ) { + mdc.insert( { _id:i, x:i } ); +} +md.getLastError(); + +print ("deleting bigstrings"); +for( i = 0; i < doccount; ++i ) { + mdc.remove( { _id:i } ); +} +md.getLastError(); + +// add a secondary +var slave = rt.add(); +rt.reInitiate(); +print ("initiation complete!"); +var sc = slave.getDB( 'd' )[ 'c' ]; +slave.setSlaveOk(); +sleep(25000); +print ("updating documents backwards"); +// Move all documents to the beginning by growing them to sizes that should +// fit the holes we made in phase 1 +for (i = doccount*2; i > doccount; --i) { + mdc.update( { _id:i, x:i }, { _id:i, x:bigstring } ); + md.getLastError(); + bigstring = bigstring.slice(0, -1); // remove last char +} +print ("finished"); +// Wait for replication to catch up. +rt.awaitSecondaryNodes(); +assert.eq(doccount+1, slave.getDB( 'd' )['c'].count()); diff --git a/jstests/replsets/replsetadd.js b/jstests/replsets/replsetadd.js index 44ef7c61fdf..711a173931b 100644 --- a/jstests/replsets/replsetadd.js +++ b/jstests/replsets/replsetadd.js @@ -22,7 +22,9 @@ doTest = function( signal ) { return result['ok'] == 1; }); - replTest.getMaster(); + db = replTest.getMaster().getDB( "test"); + db.foo.insert( { x : 1} ); + db.foo.ensureIndex( { x : 1 } ); // Start a second node var second = replTest.add(); @@ -50,8 +52,16 @@ doTest = function( signal ) { print("trying reconfig that shouldn't work"); var result = master.getDB("admin").runCommand({replSetReconfig: config}); - assert.eq(result.ok, 0); - assert.eq(result.assertionCode, 13645); + assert.eq(result.ok, 0, tojson(result)); + assert.eq(result.code, 13645, tojson(result)); + + replTest.awaitReplication(); + + hashes = replTest.getHashes( "test" ); + printjson( hashes ); + for ( i=0; i<hashes.slaves.length; i++ ) { + assert.eq( hashes.master.collections.foo , hashes.slaves[i].collections.foo ); + } replTest.stopSet( signal ); } diff --git a/jstests/replsets/replsetfreeze.js b/jstests/replsets/replsetfreeze.js index 70963497a0d..03e9f724f8a 100644 --- a/jstests/replsets/replsetfreeze.js +++ b/jstests/replsets/replsetfreeze.js @@ -49,7 +49,9 @@ var config = {"_id" : "unicomplex", "members" : [ {"_id" : 2, "host" : nodes[2], "arbiterOnly" : true}]}; var r = replTest.initiate(config); var master = replTest.getMaster(); +var secondary = replTest.getSecondary(); +replTest.awaitSecondaryNodes(); print("2: step down m1"); try { @@ -59,14 +61,16 @@ catch(e) { print(e); } reconnect(master); +printjson( master.getDB("admin").runCommand({replSetGetStatus: 1}) ); print("3: freeze set for 30 seconds"); +secondary.getDB("admin").runCommand({replSetFreeze : 30}); 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) { +while ((new Date()).getTime() - start < (28 * 1000) ) { // we need less 30 since it takes some time to return... hacky var result = master.getDB("admin").runCommand({isMaster:1}); assert.eq(result.ismaster, false); assert.eq(result.primary, undefined); diff --git a/jstests/replsets/replsethostnametrim.js b/jstests/replsets/replsethostnametrim.js new file mode 100644 index 00000000000..44f4c7b2320 --- /dev/null +++ b/jstests/replsets/replsethostnametrim.js @@ -0,0 +1,21 @@ +// try reconfiguring with space at the end of the host:port + +var replTest = new ReplSetTest({ name: 'testSet', nodes: 1 }); +var nodes = replTest.startSet(); +replTest.initiate(); + +var master = replTest.getMaster(); +var config = master.getDB("local").system.replset.findOne(); +config.version++; +var origHost = config.members[0].host; +config.members[0].host = origHost + " "; +var result = master.adminCommand({replSetReconfig : config}); +assert.eq(result.ok, 1, tojson(result)); +//print("current (bad) config:"); printjson(config); + +//check new config to make sure it doesn't have a space in the hostname +config = master.getDB("local").system.replset.findOne(); +assert.eq(origHost, config.members[0].host); +//print("current (good) config:"); printjson(config); + +replTest.stopSet();
\ No newline at end of file diff --git a/jstests/replsets/replsetprio1.js b/jstests/replsets/replsetprio1.js index aeeb7494a0b..218bbc04314 100644 --- a/jstests/replsets/replsetprio1.js +++ b/jstests/replsets/replsetprio1.js @@ -47,7 +47,7 @@ doTest = function( signal ) { print(e); } return false; - }, 'node 2 is master again'); + }, 'node 2 is master again', 60000); // make sure nothing was rolled back master = replTest.getMaster(); diff --git a/jstests/replsets/replsetrestart1.js b/jstests/replsets/replsetrestart1.js index d9f5093783d..212bf783e1d 100644 --- a/jstests/replsets/replsetrestart1.js +++ b/jstests/replsets/replsetrestart1.js @@ -52,18 +52,18 @@ doTest = function( signal ) { assert.soon(function() { stat = master.getDB("admin").runCommand({replSetGetStatus: 1}); return stat.myState == 1; - }); + }, "checking master", 3 * 60 * 1000, 1000 ); // Slaves to be set to 2 (secondary) assert.soon(function() { stat = slaves[0].getDB("admin").runCommand({replSetGetStatus: 1}); return stat.myState == 2; - }); + }, "checking slave 0", 3 * 60 * 1000, 1000 ); assert.soon(function() { stat = slaves[1].getDB("admin").runCommand({replSetGetStatus: 1}); return stat.myState == 2; - }); + }, "checking slave 1", 3 * 60 * 1000, 1000 ); } doTest( 15 ); diff --git a/jstests/replsets/rollback.js b/jstests/replsets/rollback.js index 6370e4173c6..7ec3810fbdc 100644 --- a/jstests/replsets/rollback.js +++ b/jstests/replsets/rollback.js @@ -1,12 +1,24 @@ // test rollback in replica sets // try running as : -// +// // mongo --nodb rollback.js | tee out | grep -v ^m31 // var debugging = 0; +function ifReady(db, f) { + var stats = db.adminCommand({ replSetGetStatus: 1 }); + + + // only eval if state isn't recovery + if (stats && stats.myState != 3) { + return f(); + } + + return false; +} + function pause(s) { print(s); while (debugging) { @@ -15,10 +27,10 @@ function pause(s) { } } -function deb(obj) { +function deb(obj) { if( debugging ) { print("\n\n\n" + obj + "\n\n"); - } + } } w = 0; @@ -105,7 +117,7 @@ doTest = function (signal) { assert(a.bar.count() == 3, "t.count"); // wait for secondary to get this data - wait(function () { return b.bar.count() == 3; }); + wait(function () { return ifReady(b, function() { return b.bar.count() == 3 }); }); A.runCommand({ replSetTest: 1, blind: true }); reconnect(a,b); @@ -126,7 +138,7 @@ doTest = function (signal) { print("*************** B ****************"); wait(function () { try { return !B.isMaster().ismaster; } catch(e) { return false; } }); print("*************** A ****************"); - reconnect(a,b); + reconnect(a,b); wait(function () { try { return A.isMaster().ismaster; @@ -151,17 +163,22 @@ doTest = function (signal) { // A is 1 2 3 7 8 // B is 1 2 3 4 5 6 - // bring B back online + // bring B back online B.runCommand({ replSetTest: 1, blind: false }); reconnect(a,b); - wait(function () { return B.isMaster().ismaster || B.isMaster().secondary; }); + assert.soon(function() { + return (A.isMaster().ismaster || A.isMaster().secondary) && + (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.soon(function() { + return (A.isMaster().ismaster || A.isMaster().secondary) && + (B.isMaster().ismaster || B.isMaster().secondary); + }); + 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"); @@ -170,7 +187,7 @@ doTest = function (signal) { var reconnect = function(a,b) { - wait(function() { + wait(function() { try { a.bar.stats(); b.bar.stats(); diff --git a/jstests/replsets/rollback2.js b/jstests/replsets/rollback2.js index 7ab3c6bf4ee..d80e7b7349e 100644 --- a/jstests/replsets/rollback2.js +++ b/jstests/replsets/rollback2.js @@ -7,6 +7,18 @@ var debugging = 0; +function ifReady(db, f) { + var stats = db.adminCommand({ replSetGetStatus: 1 }); + + + // only eval if state isn't recovery + if (stats && stats.myState != 3) { + return f(); + } + + return false; +} + function pause(s) { print(s); while (debugging) { @@ -165,7 +177,7 @@ doTest = function (signal) { doInitialWrites(a); // wait for secondary to get this data - wait(function () { return b.bar.count() == a.bar.count(); }); + wait(function () { return ifReady(a, function() { return ifReady(b, function() { return b.bar.count() == a.bar.count(); }); }); }); wait(function () { var status = A.runCommand({replSetGetStatus : 1}); return status.members[1].state == 2; diff --git a/jstests/replsets/rollback3.js b/jstests/replsets/rollback3.js index fa923d87a46..188394a1263 100755 --- a/jstests/replsets/rollback3.js +++ b/jstests/replsets/rollback3.js @@ -4,9 +4,22 @@ // // mongo --nodb rollback.js | tee out | grep -v ^m31 // +load("jstests/replsets/rslib.js"); var debugging = 0; +function ifReady(db, f) { + var stats = db.adminCommand({ replSetGetStatus: 1 }); + + + // only eval if state isn't recovery + if (stats && stats.myState != 3) { + return f(); + } + + return false; +} + function pause(s) { print(s); while (debugging) { @@ -185,7 +198,7 @@ doTest = function (signal) { doInitialWrites(a); // wait for secondary to get this data - wait(function () { return b.bar.count() == a.bar.count(); }); + wait(function () { return ifReady(a, function() { return ifReady(b, function() { return b.bar.count() == a.bar.count(); }); }); }); A.runCommand({ replSetTest: 1, blind: true }); reconnect(a,b); @@ -220,7 +233,9 @@ doTest = function (signal) { assert(A.isMaster().ismaster || A.isMaster().secondary, "A up"); assert(B.isMaster().ismaster || B.isMaster().secondary, "B up"); replTest.awaitReplication(); - + + assert.soon(function() { return B.isMaster().secondary; }); + assert( dbs_match(a,b), "server data sets do not match after rollback, something is wrong"); pause("rollback3.js SUCCESS"); diff --git a/jstests/replsets/rollback4.js b/jstests/replsets/rollback4.js index 5d3299b130b..2fc1386a66f 100644 --- a/jstests/replsets/rollback4.js +++ b/jstests/replsets/rollback4.js @@ -97,7 +97,18 @@ replTest.unPartition(2,5) replTest.unPartition(2,6) printjson({endUnPartition: new Date()}); -printjson(master2.adminCommand({getLastError:1, w:7, wtimeout:30*1000})); +assert.soon(function() { + try { + printjson(master2.adminCommand({getLastError:1, w:7, wtimeout:30*1000})); + return true; + } + catch (e) { + print("getLastError returned an exception; retrying"); + print(e); + return false; + } +}); + printjson(master2.adminCommand("replSetGetStatus")); assert.soon(function() {return master.adminCommand('isMaster').ismaster}, @@ -114,4 +125,3 @@ replTest.stopSet(); } - diff --git a/jstests/replsets/rslib.js b/jstests/replsets/rslib.js index 19271c9e13d..562f6e8c4ed 100644 --- a/jstests/replsets/rslib.js +++ b/jstests/replsets/rslib.js @@ -38,10 +38,14 @@ var reconnect = function(a) { try { // make this work with either dbs or connections if (typeof(a.getDB) == "function") { - a.getDB("foo").bar.stats(); + db = a.getDB('foo'); } else { - a.bar.stats(); + db = a; + } + db.bar.stats(); + if (jsTest.options().keyFile) { // SERVER-4241: Shell connections don't re-authenticate on reconnect + return jsTest.authenticate(db.getMongo()); } return true; } catch(e) { @@ -63,26 +67,36 @@ var getLatestOp = function(server) { }; -var waitForAllMembers = function(master) { - var ready = false; - var count = 0; - - outer: - while (count < 60) { - count++; - var state = master.getSisterDB("admin").runCommand({replSetGetStatus:1}); - occasionally(function() { printjson(state); }, 10); +var waitForAllMembers = function(master, timeout) { + var failCount = 0; - for (var m in state.members) { - if (state.members[m].state != 2 && state.members[m].state != 1) { - sleep(1000); - continue outer; - } - } - return; - } + assert.soon( function() { + var state = null + try { + state = master.getSisterDB("admin").runCommand({replSetGetStatus:1}); + failCount = 0; + } catch ( e ) { + // Connection can get reset on replica set failover causing a socket exception + print( "Calling replSetGetStatus failed" ); + printjson( e ); + failCount++; + assert.lt( failCount, 3, "replSetGetStatus failed 3 times in a row" ); + return false; + } + occasionally(function() { printjson(state); }, 10); + + for (var m in state.members) { + if (state.members[m].state != 1 && // PRIMARY + state.members[m].state != 2 && // SECONDARY + state.members[m].state != 7) { // ARBITER + return false; + } + } + printjson( state ); + return true; + }, "not all members ready", timeout || 60000); - assert(false, "all members not ready"); + print( "All members are now in state PRIMARY, SECONDARY, or ARBITER" ); }; var reconfig = function(rs, config) { diff --git a/jstests/replsets/slaveDelay2.js b/jstests/replsets/slaveDelay2.js index 2d9dd1ff15b..3ef968f3a53 100644 --- a/jstests/replsets/slaveDelay2.js +++ b/jstests/replsets/slaveDelay2.js @@ -1,27 +1,8 @@ +load("jstests/replsets/rslib.js"); 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} ); @@ -57,7 +38,8 @@ doTest = function( signal ) { * initializing. Make sure it syncs all of these writes before going into * syncDelay. */ - var conn = startMongodTest(31008, name + "-sd", 0, { useHostname: true, replSet: name }); + var conn = MongoRunner.runMongod({port : 31008, dbpath : name + "-sd", useHostname: true, + replSet: name, oplogSize : 128}); conn.setSlaveOk(); config = master.getSisterDB("local").system.replset.findOne(); @@ -67,7 +49,7 @@ doTest = function( signal ) { assert.eq(ok.ok,1); // do inserts during initial sync - count = 0; + var count = 0; while (count < 10) { for (var i = 100*count; i<100*(count+1); i++) { master.foo.insert({x:i}); @@ -91,7 +73,7 @@ doTest = function( signal ) { } // wait a bit for the syncs to be applied - waitForAllMembers(master); + waitForAllMembers(master); for (var i=0; i<(100*count); i++) { var obj = conn.getDB(name).foo.findOne({x : i}); diff --git a/jstests/replsets/slavedelay1.js b/jstests/replsets/slavedelay1.js index 9301c8ebb8a..13c6adfcdf3 100644 --- a/jstests/replsets/slavedelay1.js +++ b/jstests/replsets/slavedelay1.js @@ -4,7 +4,7 @@ doTest = function( signal ) { var name = "slaveDelay"; var host = getHostName(); - + var replTest = new ReplSetTest( {name: name, nodes: 3} ); var nodes = replTest.startSet(); @@ -13,7 +13,7 @@ doTest = function( signal ) { var config = replTest.getReplSetConfig(); config.members[2].priority = 0; config.members[2].slaveDelay = 10; - + replTest.initiate(config); var master = replTest.getMaster().getDB(name); @@ -26,14 +26,14 @@ doTest = function( signal ) { } 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); @@ -45,18 +45,18 @@ doTest = function( signal ) { assert.eq(slave[1].foo.findOne(), null); sleep(1000); } - + // now delayed slave should have it assert.soon(function() { var z = slave[1].foo.findOne(); return z && z.x == 1; }); - + /************* Part 2 *******************/ // how about non-initial sync? - + for (var i=0; i<100; i++) { master.foo.insert({_id : i, "foo" : "bar"}); } @@ -70,26 +70,26 @@ doTest = function( signal ) { assert.eq(slave[1].foo.findOne({_id:99}), null); sleep(1000); } - + assert.soon(function() { var z = slave[1].foo.findOne({_id : 99}); return z && z.foo == "bar"; }); - + /************* Part 3 *******************/ // how about if we add a new server? will it sync correctly? - var conn = startMongodTest( 31007 , name+"-part3" , 0 , {useHostname : true, replSet : name} ); - + conn = replTest.add(); + config = master.getSisterDB("local").system.replset.findOne(); printjson(config); config.version++; - config.members.push({_id : 3, host : host+":31007",priority:0, slaveDelay:10}); + config.members.push({_id : 3, host : host+":"+replTest.ports[replTest.ports.length-1],priority:0, slaveDelay:10}); master = reconfig(replTest, config); master = master.getSisterDB(name); - + // it should be all caught up now master.foo.insert({_id : 123, "x" : "foo"}); @@ -101,39 +101,43 @@ doTest = function( signal ) { assert.eq(conn.getDB(name).foo.findOne({_id:123}), null); sleep(1000); } - + assert.soon(function() { var z = conn.getDB(name).foo.findOne({_id:123}); return z != null && z.x == "foo" - }); - + }); + /************* Part 4 ******************/ - + print("reconfigure slavedelay"); - + config.version++; config.members[3].slaveDelay = 15; - master = reconfig(replTest, config); - master = master.getSisterDB(name); + reconfig(replTest, config); + master = replTest.getMaster().getDB(name); assert.soon(function() { return conn.getDB("local").system.replset.findOne().version == config.version; }); - + + assert.soon(function() { + var result = conn.getDB("admin").isMaster(); + printjson(result); + return result.secondary; + }); + + print("testing insert"); master.foo.insert({_id : 124, "x" : "foo"}); - + assert(master.foo.findOne({_id:124}) != null); + for (var i=0; i<13; i++) { assert.eq(conn.getDB(name).foo.findOne({_id:124}), null); sleep(1000); } - - assert.soon(function() { - var z = conn.getDB(name).foo.findOne({_id:124}); - return z != null && z.x == "foo" - }); - - - replTest.stopSet(); + + replTest.awaitReplication(); + + replTest.stopSet(); } doTest(15); diff --git a/jstests/replsets/stale_clustered.js b/jstests/replsets/stale_clustered.js index 457231eb838..916a0647750 100644 --- a/jstests/replsets/stale_clustered.js +++ b/jstests/replsets/stale_clustered.js @@ -79,7 +79,7 @@ prt("6: stop non-overflowed secondary") rsA.stop( goodSec, undefined, true ) -prt("7: check our regular and slaveok query") +prt("7: check our regular and slaveOk query") assert.eq( coll.find().itcount(), collSOk.find().itcount() ) @@ -91,7 +91,7 @@ prt("9: wait for recovery") rsA.waitForState( rsA.getSecondaries(), rsA.SECONDARY, 5 * 60 * 1000 ) -prt("10: check our regular and slaveok query") +prt("10: check our regular and slaveOk query") assert.eq( coll.find().itcount(), collSOk.find().itcount() ) diff --git a/jstests/replsets/stepdown.js b/jstests/replsets/stepdown.js index 67f10f9bcfd..f21772785ea 100644 --- a/jstests/replsets/stepdown.js +++ b/jstests/replsets/stepdown.js @@ -108,13 +108,26 @@ catch (e) { print(e); } -print("\nsleeping"); -sleep(2000); +master = replTest.getMaster(); +assert.soon(function() { + var result = master.getDB("admin").runCommand({replSetGetStatus:1}); + for (var i in result.members) { + if (result.members[i].self) { + continue; + } + + return result.members[i].health == 0; + } + +}, 'make sure master knows that slave is down before proceeding'); + print("\nrunning shutdown without force on master: "+master); -result = replTest.getMaster().getDB("admin").runCommand({shutdown : 1, timeoutSecs : 3}); +// this should fail because the master can't reach an up-to-date secondary (because the only +// secondary is down) +result = master.getDB("admin").runCommand({shutdown : 1, timeoutSecs : 3}); assert.eq(result.ok, 0); print("\nsend shutdown command"); diff --git a/jstests/replsets/sync2.js b/jstests/replsets/sync2.js index 9f6c20550d0..eabd4b89ce1 100644 --- a/jstests/replsets/sync2.js +++ b/jstests/replsets/sync2.js @@ -46,3 +46,4 @@ replTest.awaitReplication(); result = master.getDB("admin").runCommand({getLastError:1,w:5,wtimeout:1000}); assert.eq(null, result.err, tojson(result)); +replTest.stopSet();
\ No newline at end of file diff --git a/jstests/replsets/sync_passive2.js b/jstests/replsets/sync_passive2.js index 230d71c65ad..63a1e58e63e 100644 --- a/jstests/replsets/sync_passive2.js +++ b/jstests/replsets/sync_passive2.js @@ -19,6 +19,10 @@ var config = replTest.getReplSetConfig(); config.members[1].arbiterOnly = true; for (i=2; i<config.members.length; i++) { config.members[i].priority = 0; + if (i == 4) { + config.members[i].buildIndexes = false; + config.members[i].hidden = true; + } } replTest.initiate(config); @@ -118,3 +122,64 @@ wait(function() { friendlyEqual(status.members[3].optime, status.members[4].optime) && friendlyEqual(status.members[2].optime, status.members[4].optime); }); + + +print("force sync from various members"); +master = replTest.getMaster(); + +print("sync from self: error"); +var result = replTest.nodes[3].getDB("admin").runCommand({replSetSyncFrom: replTest.host+":"+replTest.ports[3]}); +printjson(result); +assert.eq(result.ok, 0); +assert.eq(result.errmsg, "I cannot sync from myself"); + +print("sync from arbiter: error"); +result = replTest.nodes[3].getDB("admin").runCommand({replSetSyncFrom: replTest.host+":"+replTest.ports[1]}); +printjson(result); +assert.eq(result.ok, 0); + +print("sync arbiter from someone: error"); +result = replTest.nodes[1].getDB("admin").runCommand({replSetSyncFrom: replTest.host+":"+replTest.ports[3]}); +printjson(result); +assert.eq(result.ok, 0); + +print("sync from non-index-building member: error"); +result = replTest.nodes[3].getDB("admin").runCommand({replSetSyncFrom: replTest.host+":"+replTest.ports[4]}); +printjson(result) +assert.eq(result.ok, 0); + +var checkSyncingFrom = function(node, target) { + var status = node.getDB("admin").runCommand({replSetGetStatus:1}); + occasionally(function() { + printjson(status); + }); + return status.syncingTo == target; +} + +print("sync from primary"); +result = replTest.nodes[3].getDB("admin").runCommand({replSetSyncFrom: replTest.host+":"+replTest.ports[0]}); +printjson(result) +assert.eq(result.ok, 1); +assert.soon(function() { + return checkSyncingFrom(nodes[3], replTest.host+":"+replTest.ports[0]) +}); + +print("sync from another passive"); +result = replTest.nodes[3].getDB("admin").runCommand({replSetSyncFrom: replTest.host+":"+replTest.ports[2]}); +printjson(result) +assert.eq(result.ok, 1); +assert.soon(function() { + return checkSyncingFrom(nodes[3], replTest.host+":"+replTest.ports[2]) +}); + +/** + * Test forcing a primary to sync from another member + */ + +print("sync a primary from another member: error"); +result = replTest.nodes[0].getDB("admin").runCommand({replSetSyncFrom: replTest.host+":"+replTest.ports[2]}); +printjson(result); +assert.eq(result.ok, 0); +assert.eq(result.errmsg, "primaries don't sync"); + +replTest.stopSet(); diff --git a/jstests/replsets/tags.js b/jstests/replsets/tags.js index 4e738862afe..f7e843848f3 100644 --- a/jstests/replsets/tags.js +++ b/jstests/replsets/tags.js @@ -1,3 +1,7 @@ +if (!_isWindows()) { +function myprint( x ) { + print( "tags output: " + x ); +} var num = 5; var host = getHostName(); @@ -16,8 +20,8 @@ replTest.initiate({_id : name, members : ], settings : { getLastErrorModes : { - "important" : {"dc" : 2, "server" : 3}, - "a machine" : {"server" : 1} + "2 dc and 3 server" : {"dc" : 2, "server" : 3}, + "1 and 2" : {"server" : 1} } }}); @@ -28,54 +32,61 @@ var config = master.getDB("local").system.replset.findOne(); printjson(config); var modes = config.settings.getLastErrorModes; assert.eq(typeof modes, "object"); -assert.eq(modes.important.dc, 2); -assert.eq(modes.important.server, 3); -assert.eq(modes["a machine"]["server"], 1); +assert.eq(modes["2 dc and 3 server"].dc, 2); +assert.eq(modes["2 dc and 3 server"].server, 3); +assert.eq(modes["1 and 2"]["server"], 1); config.version++; config.members[1].priority = 1.5; config.members[2].priority = 2; -modes.rack = {"sf" : 1}; -modes.niceRack = {"sf" : 2}; -modes["a machine"]["2"] = 1; -modes.on2 = {"2" : 1} +modes["3 or 4"] = {"sf" : 1}; +modes["3 and 4"] = {"sf" : 2}; +modes["1 and 2"]["2"] = 1; +modes["2"] = {"2" : 1} try { master.getDB("admin").runCommand({replSetReconfig : config}); } catch(e) { - print(e); + myprint(e); } replTest.awaitReplication(); -print("primary should now be 2"); +myprint("primary should now be 2"); master = replTest.getMaster(); config = master.getDB("local").system.replset.findOne(); printjson(config); modes = config.settings.getLastErrorModes; assert.eq(typeof modes, "object"); -assert.eq(modes.important.dc, 2); -assert.eq(modes.important.server, 3); -assert.eq(modes["a machine"]["server"], 1); -assert.eq(modes.rack["sf"], 1); -assert.eq(modes.niceRack["sf"], 2); +assert.eq(modes["2 dc and 3 server"].dc, 2); +assert.eq(modes["2 dc and 3 server"].server, 3); +assert.eq(modes["1 and 2"]["server"], 1); +assert.eq(modes["3 or 4"]["sf"], 1); +assert.eq(modes["3 and 4"]["sf"], 2); -print("bridging"); +myprint("bridging"); replTest.bridge(); - +myprint("bridge 1"); replTest.partition(0, 3); +myprint("bridge 2"); replTest.partition(0, 4); +myprint("bridge 3"); replTest.partition(1, 3); +myprint("bridge 4"); replTest.partition(1, 4); +myprint("bridge 5"); replTest.partition(2, 3); +myprint("bridge 6"); replTest.partition(2, 4); +myprint("bridge 7"); replTest.partition(3, 4); -print("done bridging"); +myprint("done bridging"); -print("test1"); -print("2 should be primary"); +myprint("paritions: [0-1-2-0] [3] [4]") +myprint("test1"); +myprint("2 should be primary"); master = replTest.getMaster(); printjson(master.getDB("admin").runCommand({replSetGetStatus:1})); @@ -83,51 +94,56 @@ printjson(master.getDB("admin").runCommand({replSetGetStatus:1})); var timeout = 20000; master.getDB("foo").bar.insert({x:1}); -var result = master.getDB("foo").runCommand({getLastError:1,w:"rack",wtimeout:timeout}); +var result = master.getDB("foo").runCommand({getLastError:1,w:"3 or 4",wtimeout:timeout}); printjson(result); assert.eq(result.err, "timeout"); replTest.unPartition(1,4); -print("test2"); +myprint("partitions: [1-4] [0-1-2-0] [3]"); +myprint("test2"); master.getDB("foo").bar.insert({x:1}); -result = master.getDB("foo").runCommand({getLastError:1,w:"rack",wtimeout:timeout}); +result = master.getDB("foo").runCommand({getLastError:1,w:"3 or 4",wtimeout:timeout}); printjson(result); assert.eq(result.err, null); -print("test3"); -result = master.getDB("foo").runCommand({getLastError:1,w:"niceRack",wtimeout:timeout}); +myprint("partitions: [1-4] [0-1-2-0] [3]"); +myprint("test3"); +result = master.getDB("foo").runCommand({getLastError:1,w:"3 and 4",wtimeout:timeout}); printjson(result); assert.eq(result.err, "timeout"); replTest.unPartition(3,4); -print("test4"); -result = master.getDB("foo").runCommand({getLastError:1,w:"niceRack",wtimeout:timeout}); +myprint("partitions: [0-4-3] [0-1-2-0]"); +myprint("31004 should sync from 31001 (31026)"); +myprint("31003 should sync from 31004 (31024)"); +myprint("test4"); +result = master.getDB("foo").runCommand({getLastError:1,w:"3 and 4",wtimeout:timeout}); printjson(result); assert.eq(result.err, null); -print("non-existent w"); +myprint("non-existent w"); result = master.getDB("foo").runCommand({getLastError:1,w:"blahblah",wtimeout:timeout}); printjson(result); -assert.eq(result.assertionCode, 14830); +assert.eq(result.code, 14830); assert.eq(result.ok, 0); -print("test on2"); +myprint("test mode 2"); master.getDB("foo").bar.insert({x:1}); -result = master.getDB("foo").runCommand({getLastError:1,w:"on2",wtimeout:0}); +result = master.getDB("foo").runCommand({getLastError:1,w:"2",wtimeout:0}); printjson(result); assert.eq(result.err, null); -print("test two on the primary"); +myprint("test two on the primary"); master.getDB("foo").bar.insert({x:1}); -result = master.getDB("foo").runCommand({getLastError:1,w:"a machine",wtimeout:0}); +result = master.getDB("foo").runCommand({getLastError:1,w:"1 and 2",wtimeout:0}); printjson(result); assert.eq(result.err, null); -print("test5"); +myprint("test5"); master.getDB("foo").bar.insert({x:1}); -result = master.getDB("foo").runCommand({getLastError:1,w:"important",wtimeout:timeout}); +result = master.getDB("foo").runCommand({getLastError:1,w:"2 dc and 3 server",wtimeout:timeout}); printjson(result); assert.eq(result.err, null); @@ -137,18 +153,22 @@ replTest.partition(2, 0); replTest.partition(2, 1); replTest.stop(2); -print("1 must become primary here because otherwise the other members will take too long timing out their old sync threads"); +myprint("1 must become primary here because otherwise the other members will take too long timing out their old sync threads"); master = replTest.getMaster(); -print("test6"); +myprint("test6"); master.getDB("foo").bar.insert({x:1}); -result = master.getDB("foo").runCommand({getLastError:1,w:"niceRack",wtimeout:timeout}); +result = master.getDB("foo").runCommand({getLastError:1,w:"3 and 4",wtimeout:timeout}); printjson(result); assert.eq(result.err, null); -print("test on2"); +myprint("test mode 2"); master.getDB("foo").bar.insert({x:1}); -result = master.getDB("foo").runCommand({getLastError:1,w:"on2",wtimeout:timeout}); +result = master.getDB("foo").runCommand({getLastError:1,w:"2",wtimeout:timeout}); printjson(result); assert.eq(result.err, "timeout"); +replTest.stopSet(); +myprint("\n\ntags.js SUCCESS\n\n"); + +} diff --git a/jstests/replsets/tags2.js b/jstests/replsets/tags2.js index 16dfcdf4983..068574bc9c9 100644 --- a/jstests/replsets/tags2.js +++ b/jstests/replsets/tags2.js @@ -1,16 +1,27 @@ // Change a getLastErrorMode from 2 to 3 servers var host = getHostName(); -var replTest = new ReplSetTest( {name: "rstag", nodes: 3, startPort: 31000} ); +var replTest = new ReplSetTest( {name: "rstag", nodes: 4, startPort: 31000} ); var nodes = replTest.startSet(); var ports = replTest.ports; var conf = {_id : "rstag", version: 1, members : [ {_id : 0, host : host+":"+ports[0], tags : {"backup" : "A"}}, {_id : 1, host : host+":"+ports[1], tags : {"backup" : "B"}}, - {_id : 2, host : host+":"+ports[2], tags : {"backup" : "C"}} ], + {_id : 2, host : host+":"+ports[2], tags : {"backup" : "C"}}, + {_id : 3, host : host+":"+ports[3], tags : {"backup" : "D"}, arbiterOnly : true}], settings : {getLastErrorModes : { backedUp : {backup : 2} }} }; + +print("arbiters can't have tags"); +var result = nodes[0].getDB("admin").runCommand({replSetInitiate : conf}); +printjson(result); +assert.eq(result.ok, 0); + +conf.members.pop(); +replTest.stop(3); +replTest.remove(3); replTest.initiate( conf ); + replTest.awaitReplication(); master = replTest.getMaster(); |
