diff options
Diffstat (limited to 'jstests/replsets/rslib.js')
-rw-r--r-- | jstests/replsets/rslib.js | 353 |
1 files changed, 181 insertions, 172 deletions
diff --git a/jstests/replsets/rslib.js b/jstests/replsets/rslib.js index a02ba448227..48e934a88d8 100644 --- a/jstests/replsets/rslib.js +++ b/jstests/replsets/rslib.js @@ -1,186 +1,195 @@ var wait, occasionally, reconnect, getLatestOp, waitForAllMembers, reconfig, awaitOpTime; var waitUntilAllNodesCaughtUp; -(function () { -"use strict"; -var count = 0; -var w = 0; - -wait = function(f,msg) { - w++; - var n = 0; - while (!f()) { - if( n % 4 == 0 ) - print("waiting " + w); - if (++n == 4) { - print("" + f); - } - if (n >= 200) { - throw new Error('tried 200 times, giving up on ' + msg); - } - 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> - */ -occasionally = function(f, n) { - var interval = n || 4; - if (count % interval == 0) { - f(); - } - count++; -}; - -reconnect = function(a) { - wait(function() { - var db; - try { - // make this work with either dbs or connections - if (typeof(a.getDB) == "function") { - db = a.getDB('foo'); - } - else { - 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) { - print(e); - return false; - } - }); -}; - - -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; -}; - - -waitForAllMembers = function(master, timeout) { - var failCount = 0; - - 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" ); - print( e ); - 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; +(function() { + "use strict"; + var count = 0; + var w = 0; + + wait = function(f, msg) { + w++; + var n = 0; + while (!f()) { + if (n % 4 == 0) + print("waiting " + w); + if (++n == 4) { + print("" + f); } + if (n >= 200) { + throw new Error('tried 200 times, giving up on ' + msg); + } + sleep(1000); } - printjson( state ); - return true; - }, "not all members ready", timeout || 60000); - - print( "All members are now in state PRIMARY, SECONDARY, or ARBITER" ); -}; - -reconfig = function(rs, config, force) { - "use strict"; - var admin = rs.getPrimary().getDB("admin"); - var e; - var master; - try { - assert.commandWorked(admin.runCommand({replSetReconfig: config, force: force})); - } - catch (e) { - if (tojson(e).indexOf( "error doing query: failed" ) < 0) { - throw e; + }; + + /** + * Use this to do something once every 4 iterations. + * + * <pre> + * for (i=0; i<1000; i++) { + * occasionally(function() { print("4 more iterations"); }); + * } + * </pre> + */ + occasionally = function(f, n) { + var interval = n || 4; + if (count % interval == 0) { + f(); } - } - - var master = rs.getPrimary().getDB("admin"); - waitForAllMembers(master); - - return master; -}; - -awaitOpTime = function (node, opTime) { - var ts, ex; - assert.soon(function () { - try { - // The following statement extracts the timestamp field from the most recent element of - // the oplog, and stores it in "ts". - ts = node.getDB("local")['oplog.rs'].find({}).sort({'$natural': -1}).limit(1).next().ts; - if ((ts.t == opTime.t) && (ts.i == opTime.i)) { + count++; + }; + + reconnect = function(a) { + wait(function() { + var db; + try { + // make this work with either dbs or connections + if (typeof(a.getDB) == "function") { + db = a.getDB('foo'); + } else { + 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) { + print(e); + return false; } - ex = null; - return false; + }); + }; + + 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(); } - catch (ex) { - return false; - } - }, function () { - var message = "Node " + node + " only reached optime " + tojson(ts) + " not " + - tojson(opTime); - if (ex) { - message += "; last attempt failed with exception " + tojson(ex); - } - return message; - }); -}; - -/** - * Uses the results of running replSetGetStatus against an arbitrary replset node to wait until - * all nodes in the set are replicated through the same optime. - * 'rs' is an array of connections to replica set nodes. This function is useful when you - * don't have a ReplSetTest object to use, otherwise ReplSetTest.awaitReplication is preferred. - */ -waitUntilAllNodesCaughtUp = function(rs, timeout) { - var rsStatus; - var firstConflictingIndex; - var ot; - var otherOt; - assert.soon(function () { - rsStatus = rs[0].adminCommand('replSetGetStatus'); - if (rsStatus.ok != 1) { - return false; - } - assert.eq(rs.length, rsStatus.members.length, tojson(rsStatus)); - ot = rsStatus.members[0].optime; - for (var i = 1; i < rsStatus.members.length; ++i) { - otherOt = rsStatus.members[i].optime; - if (bsonWoCompare({ts: otherOt.ts}, {ts: ot.ts}) || - bsonWoCompare({t: otherOt.t}, {t: ot.t})) { - firstConflictingIndex = i; + return null; + }; + + waitForAllMembers = function(master, timeout) { + var failCount = 0; + + 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"); + print(e); 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); + + print("All members are now in state PRIMARY, SECONDARY, or ARBITER"); + }; + + reconfig = function(rs, config, force) { + "use strict"; + var admin = rs.getPrimary().getDB("admin"); + var e; + var master; + try { + assert.commandWorked(admin.runCommand({replSetReconfig: config, force: force})); + } catch (e) { + if (tojson(e).indexOf("error doing query: failed") < 0) { + throw e; + } } - return true; - }, function () { - return "Optimes of members 0 (" + tojson(ot) + ") and " + firstConflictingIndex + " (" + - tojson(otherOt) + ") are different in " + tojson(rsStatus); - }, timeout); -}; + + var master = rs.getPrimary().getDB("admin"); + waitForAllMembers(master); + + return master; + }; + + awaitOpTime = function(node, opTime) { + var ts, ex; + assert.soon( + function() { + try { + // The following statement extracts the timestamp field from the most recent + // element of + // the oplog, and stores it in "ts". + ts = node.getDB("local")['oplog.rs'] + .find({}) + .sort({'$natural': -1}) + .limit(1) + .next() + .ts; + if ((ts.t == opTime.t) && (ts.i == opTime.i)) { + return true; + } + ex = null; + return false; + } catch (ex) { + return false; + } + }, + function() { + var message = "Node " + node + " only reached optime " + tojson(ts) + " not " + + tojson(opTime); + if (ex) { + message += "; last attempt failed with exception " + tojson(ex); + } + return message; + }); + }; + + /** + * Uses the results of running replSetGetStatus against an arbitrary replset node to wait until + * all nodes in the set are replicated through the same optime. + * 'rs' is an array of connections to replica set nodes. This function is useful when you + * don't have a ReplSetTest object to use, otherwise ReplSetTest.awaitReplication is preferred. + */ + waitUntilAllNodesCaughtUp = function(rs, timeout) { + var rsStatus; + var firstConflictingIndex; + var ot; + var otherOt; + assert.soon( + function() { + rsStatus = rs[0].adminCommand('replSetGetStatus'); + if (rsStatus.ok != 1) { + return false; + } + assert.eq(rs.length, rsStatus.members.length, tojson(rsStatus)); + ot = rsStatus.members[0].optime; + for (var i = 1; i < rsStatus.members.length; ++i) { + otherOt = rsStatus.members[i].optime; + if (bsonWoCompare({ts: otherOt.ts}, {ts: ot.ts}) || + bsonWoCompare({t: otherOt.t}, {t: ot.t})) { + firstConflictingIndex = i; + return false; + } + } + return true; + }, + function() { + return "Optimes of members 0 (" + tojson(ot) + ") and " + firstConflictingIndex + + " (" + tojson(otherOt) + ") are different in " + tojson(rsStatus); + }, + timeout); + }; }()); |