summaryrefslogtreecommitdiff
path: root/jstests/multiClient
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/multiClient')
-rw-r--r--jstests/multiClient/rsDurKillRestart1.js139
1 files changed, 139 insertions, 0 deletions
diff --git a/jstests/multiClient/rsDurKillRestart1.js b/jstests/multiClient/rsDurKillRestart1.js
new file mode 100644
index 0000000..03e658b
--- /dev/null
+++ b/jstests/multiClient/rsDurKillRestart1.js
@@ -0,0 +1,139 @@
+/* NOTE: This test requires mongo shell to be built with V8 javascript engines so
+fork() is available */
+
+/*
+1. Starts up a replica set with 2 servers and 1 arbiter, all with --dur option.
+2. Loads 10000 1K docs into a collection
+3. Forks 5 client threads, each $pushes then $pulls its own id to/from the same array in all document (multi-update)
+5. A 6th thread kills a random server in the replica set every 0-60 secs then restarts it 0-30 secs later.
+-Tony */
+
+load('jstests/libs/fun.js')
+load('jstests/libs/concurrent.js')
+
+function random(n) {
+ return Math.floor(Math.random() * n)
+}
+
+function makeText(size) {
+ var text = ''
+ for (var i = 0; i < size; i++) text += 'a'
+ return text
+}
+
+function checkEqual (value, expected) {
+ if (value != expected) throw ('expected ' + expected + ' got ' + value)
+}
+
+function deploy() {
+ var rs = new ReplSetTest({nodes: 3, oplogSize: 1000})
+ rs.startSet({dur: null})
+ var cfg = rs.getReplSetConfig()
+ cfg.members[2]['arbiterOnly'] = true
+ rs.initiate(cfg)
+ rs.awaitReplication()
+ return rs
+}
+
+function confirmWrite(db) {
+ var cmd = {getlasterror: 1, fsync: true, w: 2}
+ var res = db.runCommand(cmd)
+ if (! res.ok) throw (tojson(cmd) + 'failed: ' + tojson(res))
+}
+
+N = 10000
+Text = makeText(1000)
+
+function loadInitialData(rs) {
+ var db = rs.getMaster().getDB('test')
+ for (var i = 0; i < N; i++) db['col'].insert({x: i, text: Text})
+ confirmWrite(db)
+}
+
+function newMasterConnection(ports) {
+ for (var i = 0; i < ports.length; i++) {
+ try {
+ print ('Try connect to '+ i)
+ var conn = new Mongo("127.0.0.1:" + ports[i])
+ var rec = conn.getDB('admin').runCommand({ismaster: 1})
+ if (rec && rec.ok && rec['ismaster']) {
+ print ('Connected ' + i)
+ return conn }
+ // else close conn
+ } catch(e) {}
+ }
+ throw 'no master: ' + ports
+}
+
+function rsMaster(ports, oldConn) {
+ try {
+ var rec = oldConn.getDB('admin').runCommand({ismaster: 1})
+ if (rec['ismaster']) return oldConn
+ } catch (e) {}
+ return newMasterConnection(ports)
+}
+
+function queryAndUpdateData(ports) {return function(z) {
+ var conn = null
+ return function(i) {
+ function printFailure(e) {print ('Q&U' + z + '-' + i + ': ' + e)}
+ try {
+ sleep(1000 + (z * 500))
+ print('update ' + z + ' round ' + i)
+ var db
+ try {
+ conn = rsMaster(ports, conn)
+ db = conn.getDB('test')
+ } catch (e) {
+ printFailure(e)
+ return
+ }
+ var n
+ try {
+ db['col'].update({}, {$push: {'z': z}}, false, true)
+ n = db['col'].count({'z': z})
+ } catch (e) {
+ printFailure(e)
+ return
+ }
+ checkEqual (n, N)
+ sleep(1000)
+ try {
+ db['col'].update({}, {$pull: {'z': z}}, false, true)
+ n = db['col'].count({'z': z})
+ } catch (e) {
+ printFailure(e)
+ return
+ }
+ checkEqual (n, 0)
+ } catch (e) {throw ('(Q&U' + z + '-' + i + ') ' + e)}
+ }
+}}
+
+function killer(rs) {return function(i) {
+ try {
+ sleep(random(30) * 1000)
+ var r = random(rs.ports.length - 1)
+ print('Killing ' + r)
+ stopMongod(rs.getPort(r), 9) // hard kill
+ sleep(random(30) * 1000)
+ print('Restarting ' + r)
+ rs.restart(r, {dur: null})
+ } catch (e) {throw ('(Killer-' + i + ') ' + e)}
+}}
+
+function rsPorts(rs) {
+ ports = new Array()
+ for (var i = 0; i < rs.ports.length; i++) ports[i] = rs.getPort(i)
+ return ports
+}
+
+function go(numRounds) {
+ var rs = deploy()
+ loadInitialData(rs)
+ var jobs = map(queryAndUpdateData(rsPorts(rs)), [1,2,3,4,5])
+ parallel (numRounds, jobs, [killer(rs)])
+ sleep (2000)
+ rs.stopSet()
+ print("rsDurKillRestart1.js SUCCESS")
+}