summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatt dannenberg <matt.dannenberg@10gen.com>2014-01-07 11:22:05 -0500
committerDan Pasette <dan@mongodb.com>2014-03-09 19:28:26 -0400
commit435f6118c5c3f2515970c65aab53f59bb54f2982 (patch)
tree4680f0fd8fc39a06dd5ec6da20040af2cf63f42e
parent67c47db36f9195679382062d52db0151251c6074 (diff)
downloadmongo-435f6118c5c3f2515970c65aab53f59bb54f2982.tar.gz
SERVER-12264 prevent from tryToGoLiveAsSecondary() from waiting on global writelock during compact
-rw-r--r--jstests/replsets/compact.js55
-rw-r--r--src/mongo/db/repl/rs_sync.cpp15
2 files changed, 63 insertions, 7 deletions
diff --git a/jstests/replsets/compact.js b/jstests/replsets/compact.js
new file mode 100644
index 00000000000..7758f4fedf5
--- /dev/null
+++ b/jstests/replsets/compact.js
@@ -0,0 +1,55 @@
+// test that nodes still respond to heartbeats during compact() SERVER-12264
+var replTest = new ReplSetTest({ name: 'compact', nodes: 3 });
+
+replTest.startSet();
+replTest.initiate();
+
+var master = replTest.getMaster();
+var compactingSlave = replTest.liveNodes.slaves[0];
+
+// populate data
+for (i=0; i<1000; i++) {
+ var bulkInsertArr = [];
+ for (j=0; j<1000; j++) {
+ bulkInsertArr.push({x:i, y:j});
+ }
+ master.getDB("compact").foo.insert(bulkInsertArr);
+}
+
+// takes a while to replicate all this data...
+replTest.awaitReplication(1000*60*5);
+
+// run compact in parallel with this rest of the script
+var cmd = "tojson(db.getSiblingDB('compact').runCommand({'compact': 'foo', 'paddingFactor': 2}));";
+var compactor = startParallelShell(cmd, compactingSlave.port);;
+
+// wait for compact to show up in currentOp
+assert.soon(function() {
+ var curop = compactingSlave.getDB('compact').currentOp();
+ for (index in curop.inprog) {
+ entry = curop.inprog[index];
+ if (entry.query.hasOwnProperty("compact") && entry.query.compact === "foo"
+ && entry.hasOwnProperty("locks") && entry.locks.hasOwnProperty("^compact")
+ && entry.locks["^compact"] === "W") {
+ return true;
+ }
+ }
+ return false;
+}, "compact didn't start in 30 seconds", 30*1000, 100);
+
+// then check that it is still responding to heartbeats
+for (i=0; i<5; i++) {
+ var start = new Date();
+ var result = compactingSlave.getDB("admin").runCommand({"replSetHeartbeat": "compact",
+ "v": NumberInt(1),
+ "pv": NumberInt(1),
+ "checkEmpty": false,
+ "fromId": NumberInt(0)
+ });
+ var end = new Date();
+ assert.eq(result.ok, 1, "heartbeat didn't return properly");
+ // wait for 10 seconds because that's how long it takes for a node to be considered down
+ assert.lt(end - start, 10 * 1000, "heartbeat didn't return quickly enough");
+}
+
+replTest.stopSet();
diff --git a/src/mongo/db/repl/rs_sync.cpp b/src/mongo/db/repl/rs_sync.cpp
index e6e31943a9f..f904d86c5ad 100644
--- a/src/mongo/db/repl/rs_sync.cpp
+++ b/src/mongo/db/repl/rs_sync.cpp
@@ -585,13 +585,6 @@ namespace replset {
bool golive = false;
lock rsLock( this );
- Lock::GlobalWrite writeLock;
-
- // make sure we're not primary, secondary, rollback, or fatal already
- if (box.getState().primary() || box.getState().secondary() ||
- box.getState().fatal()) {
- return false;
- }
if (_maintenanceMode > 0) {
// we're not actually going live
@@ -603,6 +596,14 @@ namespace replset {
return false;
}
+ Lock::GlobalWrite writeLock;
+
+ // make sure we're not primary, secondary, rollback, or fatal already
+ if (box.getState().primary() || box.getState().secondary() ||
+ box.getState().fatal()) {
+ return false;
+ }
+
minvalid = getMinValid();
if( minvalid <= lastOpTimeWritten ) {
golive=true;