123 lines
5.0 KiB
JavaScript
123 lines
5.0 KiB
JavaScript
'use strict';
|
|
|
|
load('jstests/concurrency/fsm_libs/assert.js');
|
|
load('jstests/concurrency/fsm_libs/cluster.js'); // for Cluster.isStandalone
|
|
load('jstests/concurrency/fsm_libs/parse_config.js'); // for parseConfig
|
|
|
|
var workerThread = (function() {
|
|
|
|
// workloads = list of workload filenames
|
|
// args.tid = the thread identifier
|
|
// args.data = map of workload -> 'this' parameter passed to the FSM state functions
|
|
// args.host = the address to make a new connection to
|
|
// args.latch = CountDownLatch instance for starting all threads
|
|
// args.dbName = the database name
|
|
// args.collName = the collection name
|
|
// args.cluster = connection strings for all cluster nodes (see cluster.js for format)
|
|
// args.clusterOptions = the configuration of the cluster
|
|
// args.seed = seed for the random number generator
|
|
// args.globalAssertLevel = the global assertion level to use
|
|
// args.errorLatch = CountDownLatch instance that threads count down when they error
|
|
// run = callback that takes a map of workloads to their associated $config
|
|
function main(workloads, args, run) {
|
|
var myDB;
|
|
var configs = {};
|
|
|
|
globalAssertLevel = args.globalAssertLevel;
|
|
|
|
try {
|
|
if (Cluster.isStandalone(args.clusterOptions)) {
|
|
myDB = db.getSiblingDB(args.dbName);
|
|
} else {
|
|
if (typeof db !== 'undefined') {
|
|
// The implicit database connection created within the thread's scope
|
|
// is unneeded, so forcibly clean it up.
|
|
db = null;
|
|
gc();
|
|
}
|
|
|
|
myDB = new Mongo(args.host).getDB(args.dbName);
|
|
}
|
|
|
|
workloads.forEach(function(workload) {
|
|
load(workload); // for $config
|
|
var config = parseConfig($config); // to normalize
|
|
|
|
// Copy any modifications that were made to $config.data
|
|
// during the setup function of the workload (see caveat
|
|
// below).
|
|
|
|
// XXX: Changing the order of extend calls causes problems
|
|
// for workloads that reference $super.
|
|
// Suppose you have workloads A and B, where workload B extends
|
|
// workload A. The $config.data of workload B can define a
|
|
// function that closes over the $config object of workload A
|
|
// (known as $super to workload B). This reference is lost when
|
|
// the config object is serialized to BSON, which results in
|
|
// undefined variables in the derived workload.
|
|
var data = Object.extend({}, args.data[workload], true);
|
|
data = Object.extend(data, config.data, true);
|
|
|
|
// Object.extend() defines all properties added to the destination object as
|
|
// configurable, enumerable, and writable. To prevent workloads from changing
|
|
// the iterations and threadCount properties in their state functions, we redefine
|
|
// them here as non-configurable, non-enumerable, and non-writable.
|
|
Object.defineProperties(data, {
|
|
'iterations': {
|
|
configurable: false,
|
|
enumerable: false,
|
|
writable: false,
|
|
value: data.iterations
|
|
},
|
|
'threadCount': {
|
|
configurable: false,
|
|
enumerable: false,
|
|
writable: false,
|
|
value: data.threadCount
|
|
}
|
|
});
|
|
|
|
data.tid = args.tid;
|
|
configs[workload] = {
|
|
data: data,
|
|
db: myDB,
|
|
collName: args.collName,
|
|
cluster: args.cluster,
|
|
iterations: data.iterations,
|
|
passConnectionCache: config.passConnectionCache,
|
|
startState: config.startState,
|
|
states: config.states,
|
|
transitions: config.transitions
|
|
};
|
|
});
|
|
|
|
args.latch.countDown();
|
|
|
|
// Converts any exceptions to a return status. In order for the
|
|
// parent thread to call countDown() on our behalf, we must throw
|
|
// an exception. Nothing prior to (and including) args.latch.countDown()
|
|
// should be wrapped in a try/catch statement.
|
|
try {
|
|
args.latch.await(); // wait for all threads to start
|
|
|
|
Random.setRandomSeed(args.seed);
|
|
run(configs);
|
|
return { ok: 1 };
|
|
} catch(e) {
|
|
args.errorLatch.countDown();
|
|
return { ok: 0, err: e.toString(), stack: e.stack, workloads: workloads };
|
|
}
|
|
} finally {
|
|
// Avoid retention of connection object
|
|
configs = null;
|
|
myDB = null;
|
|
gc();
|
|
}
|
|
}
|
|
|
|
return {
|
|
main: main
|
|
};
|
|
|
|
})();
|