233 lines
5.9 KiB
JavaScript
233 lines
5.9 KiB
JavaScript
/*
|
|
* 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( 4 );
|
|
|
|
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], priority:2}]};
|
|
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() { result = false;
|
|
try {
|
|
result = admin.runCommand({isMaster:1}).ismaster;
|
|
}
|
|
catch(e) {
|
|
print(e);
|
|
return false;
|
|
}
|
|
return result;
|
|
});
|
|
|
|
print("1");
|
|
for (var i=0; i<100000; i++) {
|
|
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"+1 );
|
|
admin.$cmd.sys.unlock.findOne();
|
|
|
|
print("3");
|
|
var startSlave = function(n) {
|
|
var sargs = new MongodRunner( ports[ n ], basePath + "-s"+n, false, false,
|
|
["--replSet", basename, "--fastsync",
|
|
"--oplogSize", 2], {no_bind : true} );
|
|
var reuseData = true;
|
|
var conn = sargs.start(reuseData);
|
|
|
|
config = local.system.replset.findOne();
|
|
config.version++;
|
|
config.members.push({_id:n, host:hostname+":"+ports[n]});
|
|
|
|
// 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");
|
|
var status = admin.runCommand({replSetGetStatus : 1});
|
|
var count = 0;
|
|
while (status.members[n].state != 2 && count < 200) {
|
|
print("not a secondary yet");
|
|
if (count % 10 == 0) {
|
|
printjson(status);
|
|
}
|
|
assert(!status.members[n].errmsg || !status.members[n].errmsg.match("^initial sync cloning db"));
|
|
|
|
sleep(1000);
|
|
|
|
// disconnection could happen here
|
|
try {
|
|
status = admin.runCommand({replSetGetStatus : 1});
|
|
}
|
|
catch (e) {
|
|
print(e);
|
|
}
|
|
count++;
|
|
}
|
|
|
|
assert.eq(status.members[n].state, 2);
|
|
|
|
assert.soon(function() {
|
|
return admin.runCommand({isMaster : 1}).ismaster;
|
|
});
|
|
|
|
admin.foo.insert({x:1});
|
|
assert.soon(function() {
|
|
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;
|
|
};
|
|
|
|
var s1 = startSlave(1);
|
|
|
|
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);
|
|
return me1._id != null;
|
|
});
|
|
|
|
print("5");
|
|
s1.getDB("admin").runCommand( {fsync:1,lock:1} );
|
|
copyDbpath( basePath + "-s1", basePath + "-s2" );
|
|
s1.getDB("admin").$cmd.sys.unlock.findOne();
|
|
|
|
var s2 = startSlave(2);
|
|
|
|
var me2 = s2.getDB("local").me.findOne();
|
|
|
|
print("me: " +me2._id);
|
|
assert(me1._id != me2._id);
|
|
|
|
print("restart member with a different port and make it a new set");
|
|
try {
|
|
p.getDB("admin").runCommand({shutdown:1});
|
|
}
|
|
catch(e) {
|
|
print("good, shutting down: " +e);
|
|
}
|
|
sleep(10000);
|
|
|
|
pargs = new MongodRunner( ports[ 3 ], basePath + "-p", false, false,
|
|
["--replSet", basename, "--oplogSize", 2],
|
|
{no_bind : true} );
|
|
pargs.start(true);
|
|
|
|
p = new Mongo("localhost:"+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() {
|
|
try {
|
|
return p.getDB("admin").runCommand({isMaster : 1}).ismaster;
|
|
}
|
|
catch(e) {
|
|
print(e);
|
|
}
|
|
return false;
|
|
}, "waiting for master", 60000);
|
|
|