Files
mongo/jstests/multiClient/rsDurKillRestart1.js

140 lines
3.8 KiB
JavaScript

/* 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")
}