1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 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")
}
|