diff options
Diffstat (limited to 'src/mongo/shell/bench.cpp')
-rw-r--r-- | src/mongo/shell/bench.cpp | 1486 |
1 files changed, 737 insertions, 749 deletions
diff --git a/src/mongo/shell/bench.cpp b/src/mongo/shell/bench.cpp index 99311f23f62..bd446e49018 100644 --- a/src/mongo/shell/bench.cpp +++ b/src/mongo/shell/bench.cpp @@ -54,459 +54,505 @@ // TODO: Maybe extract as library to avoid code duplication? namespace { - inline pcrecpp::RE_Options flags2options(const char* flags) { - pcrecpp::RE_Options options; - options.set_utf8(true); - while ( flags && *flags ) { - if ( *flags == 'i' ) - options.set_caseless(true); - else if ( *flags == 'm' ) - options.set_multiline(true); - else if ( *flags == 'x' ) - options.set_extended(true); - flags++; - } - return options; - } +inline pcrecpp::RE_Options flags2options(const char* flags) { + pcrecpp::RE_Options options; + options.set_utf8(true); + while (flags && *flags) { + if (*flags == 'i') + options.set_caseless(true); + else if (*flags == 'm') + options.set_multiline(true); + else if (*flags == 'x') + options.set_extended(true); + flags++; + } + return options; +} } namespace mongo { - using std::unique_ptr; - using std::cout; - using std::endl; - using std::map; - - BenchRunEventCounter::BenchRunEventCounter() { - reset(); - } - - BenchRunEventCounter::~BenchRunEventCounter() {} +using std::unique_ptr; +using std::cout; +using std::endl; +using std::map; - void BenchRunEventCounter::reset() { - _numEvents = 0; - _totalTimeMicros = 0; - } - - void BenchRunEventCounter::updateFrom(const BenchRunEventCounter &other) { - _numEvents += other._numEvents; - _totalTimeMicros += other._totalTimeMicros; - } - - BenchRunStats::BenchRunStats() { - reset(); - } +BenchRunEventCounter::BenchRunEventCounter() { + reset(); +} - BenchRunStats::~BenchRunStats() {} +BenchRunEventCounter::~BenchRunEventCounter() {} - void BenchRunStats::reset() { - error = false; - errCount = 0; - opCount = 0; +void BenchRunEventCounter::reset() { + _numEvents = 0; + _totalTimeMicros = 0; +} - findOneCounter.reset(); - updateCounter.reset(); - insertCounter.reset(); - deleteCounter.reset(); - queryCounter.reset(); - commandCounter.reset(); - trappedErrors.clear(); - } +void BenchRunEventCounter::updateFrom(const BenchRunEventCounter& other) { + _numEvents += other._numEvents; + _totalTimeMicros += other._totalTimeMicros; +} - void BenchRunStats::updateFrom(const BenchRunStats &other) { - if (other.error) - error = true; - errCount += other.errCount; - opCount += other.opCount; - - findOneCounter.updateFrom(other.findOneCounter); - updateCounter.updateFrom(other.updateCounter); - insertCounter.updateFrom(other.insertCounter); - deleteCounter.updateFrom(other.deleteCounter); - queryCounter.updateFrom(other.queryCounter); - commandCounter.updateFrom(other.commandCounter); - - for (size_t i = 0; i < other.trappedErrors.size(); ++i) - trappedErrors.push_back(other.trappedErrors[i]); - } +BenchRunStats::BenchRunStats() { + reset(); +} - BenchRunConfig::BenchRunConfig() { - initializeToDefaults(); - } +BenchRunStats::~BenchRunStats() {} - void BenchRunConfig::initializeToDefaults() { - host = "localhost"; - db = "test"; - username = ""; - password = ""; +void BenchRunStats::reset() { + error = false; + errCount = 0; + opCount = 0; - parallel = 1; - seconds = 1.0; - hideResults = true; - handleErrors = false; - hideErrors = false; + findOneCounter.reset(); + updateCounter.reset(); + insertCounter.reset(); + deleteCounter.reset(); + queryCounter.reset(); + commandCounter.reset(); + trappedErrors.clear(); +} - trapPattern.reset(); - noTrapPattern.reset(); - watchPattern.reset(); - noWatchPattern.reset(); +void BenchRunStats::updateFrom(const BenchRunStats& other) { + if (other.error) + error = true; + errCount += other.errCount; + opCount += other.opCount; + + findOneCounter.updateFrom(other.findOneCounter); + updateCounter.updateFrom(other.updateCounter); + insertCounter.updateFrom(other.insertCounter); + deleteCounter.updateFrom(other.deleteCounter); + queryCounter.updateFrom(other.queryCounter); + commandCounter.updateFrom(other.commandCounter); + + for (size_t i = 0; i < other.trappedErrors.size(); ++i) + trappedErrors.push_back(other.trappedErrors[i]); +} - ops = BSONObj(); +BenchRunConfig::BenchRunConfig() { + initializeToDefaults(); +} - throwGLE = false; - breakOnTrap = true; - randomSeed = 1314159265358979323; - } +void BenchRunConfig::initializeToDefaults() { + host = "localhost"; + db = "test"; + username = ""; + password = ""; - BenchRunConfig *BenchRunConfig::createFromBson( const BSONObj &args ) { - BenchRunConfig *config = new BenchRunConfig(); - config->initializeFromBson( args ); - return config; - } + parallel = 1; + seconds = 1.0; + hideResults = true; + handleErrors = false; + hideErrors = false; - void BenchRunConfig::initializeFromBson( const BSONObj &args ) { - initializeToDefaults(); - - if ( args["host"].type() == String ) - this->host = args["host"].String(); - if ( args["db"].type() == String ) - this->db = args["db"].String(); - if ( args["username"].type() == String ) - this->username = args["username"].String(); - if ( args["password"].type() == String ) - this->password = args["password"].String(); - - if ( args["parallel"].isNumber() ) - this->parallel = args["parallel"].numberInt(); - if ( args["randomSeed"].isNumber() ) - this->randomSeed = args["randomSeed"].numberInt(); - if ( args["seconds"].isNumber() ) - this->seconds = args["seconds"].number(); - if ( ! args["hideResults"].eoo() ) - this->hideResults = args["hideResults"].trueValue(); - if ( ! args["handleErrors"].eoo() ) - this->handleErrors = args["handleErrors"].trueValue(); - if ( ! args["hideErrors"].eoo() ) - this->hideErrors = args["hideErrors"].trueValue(); - if ( ! args["throwGLE"].eoo() ) - this->throwGLE = args["throwGLE"].trueValue(); - if ( ! args["breakOnTrap"].eoo() ) - this->breakOnTrap = args["breakOnTrap"].trueValue(); - - uassert(16164, "loopCommands config not supported", args["loopCommands"].eoo()); - - if ( ! args["trapPattern"].eoo() ){ - const char* regex = args["trapPattern"].regex(); - const char* flags = args["trapPattern"].regexFlags(); - this->trapPattern = std::shared_ptr< pcrecpp::RE >( new pcrecpp::RE( regex, flags2options( flags ) ) ); - } + trapPattern.reset(); + noTrapPattern.reset(); + watchPattern.reset(); + noWatchPattern.reset(); - if ( ! args["noTrapPattern"].eoo() ){ - const char* regex = args["noTrapPattern"].regex(); - const char* flags = args["noTrapPattern"].regexFlags(); - this->noTrapPattern = std::shared_ptr< pcrecpp::RE >( new pcrecpp::RE( regex, flags2options( flags ) ) ); - } + ops = BSONObj(); - if ( ! args["watchPattern"].eoo() ){ - const char* regex = args["watchPattern"].regex(); - const char* flags = args["watchPattern"].regexFlags(); - this->watchPattern = std::shared_ptr< pcrecpp::RE >( new pcrecpp::RE( regex, flags2options( flags ) ) ); - } + throwGLE = false; + breakOnTrap = true; + randomSeed = 1314159265358979323; +} - if ( ! args["noWatchPattern"].eoo() ){ - const char* regex = args["noWatchPattern"].regex(); - const char* flags = args["noWatchPattern"].regexFlags(); - this->noWatchPattern = std::shared_ptr< pcrecpp::RE >( new pcrecpp::RE( regex, flags2options( flags ) ) ); - } +BenchRunConfig* BenchRunConfig::createFromBson(const BSONObj& args) { + BenchRunConfig* config = new BenchRunConfig(); + config->initializeFromBson(args); + return config; +} - this->ops = args["ops"].Obj().getOwned(); - } +void BenchRunConfig::initializeFromBson(const BSONObj& args) { + initializeToDefaults(); + + if (args["host"].type() == String) + this->host = args["host"].String(); + if (args["db"].type() == String) + this->db = args["db"].String(); + if (args["username"].type() == String) + this->username = args["username"].String(); + if (args["password"].type() == String) + this->password = args["password"].String(); + + if (args["parallel"].isNumber()) + this->parallel = args["parallel"].numberInt(); + if (args["randomSeed"].isNumber()) + this->randomSeed = args["randomSeed"].numberInt(); + if (args["seconds"].isNumber()) + this->seconds = args["seconds"].number(); + if (!args["hideResults"].eoo()) + this->hideResults = args["hideResults"].trueValue(); + if (!args["handleErrors"].eoo()) + this->handleErrors = args["handleErrors"].trueValue(); + if (!args["hideErrors"].eoo()) + this->hideErrors = args["hideErrors"].trueValue(); + if (!args["throwGLE"].eoo()) + this->throwGLE = args["throwGLE"].trueValue(); + if (!args["breakOnTrap"].eoo()) + this->breakOnTrap = args["breakOnTrap"].trueValue(); + + uassert(16164, "loopCommands config not supported", args["loopCommands"].eoo()); + + if (!args["trapPattern"].eoo()) { + const char* regex = args["trapPattern"].regex(); + const char* flags = args["trapPattern"].regexFlags(); + this->trapPattern = + std::shared_ptr<pcrecpp::RE>(new pcrecpp::RE(regex, flags2options(flags))); + } + + if (!args["noTrapPattern"].eoo()) { + const char* regex = args["noTrapPattern"].regex(); + const char* flags = args["noTrapPattern"].regexFlags(); + this->noTrapPattern = + std::shared_ptr<pcrecpp::RE>(new pcrecpp::RE(regex, flags2options(flags))); + } + + if (!args["watchPattern"].eoo()) { + const char* regex = args["watchPattern"].regex(); + const char* flags = args["watchPattern"].regexFlags(); + this->watchPattern = + std::shared_ptr<pcrecpp::RE>(new pcrecpp::RE(regex, flags2options(flags))); + } + + if (!args["noWatchPattern"].eoo()) { + const char* regex = args["noWatchPattern"].regex(); + const char* flags = args["noWatchPattern"].regexFlags(); + this->noWatchPattern = + std::shared_ptr<pcrecpp::RE>(new pcrecpp::RE(regex, flags2options(flags))); + } + + this->ops = args["ops"].Obj().getOwned(); +} - DBClientBase *BenchRunConfig::createConnection() const { - const ConnectionString connectionString = uassertStatusOK(ConnectionString::parse(host)); +DBClientBase* BenchRunConfig::createConnection() const { + const ConnectionString connectionString = uassertStatusOK(ConnectionString::parse(host)); - std::string errorMessage; - DBClientBase *connection = connectionString.connect(errorMessage); - uassert( 16158, errorMessage, connection != NULL ); + std::string errorMessage; + DBClientBase* connection = connectionString.connect(errorMessage); + uassert(16158, errorMessage, connection != NULL); - return connection; - } + return connection; +} - BenchRunState::BenchRunState( unsigned numWorkers ) - : _mutex(), - _numUnstartedWorkers( numWorkers ), - _numActiveWorkers( 0 ), - _isShuttingDown( 0 ), - _isCollectingStats( 0 ) { - } +BenchRunState::BenchRunState(unsigned numWorkers) + : _mutex(), + _numUnstartedWorkers(numWorkers), + _numActiveWorkers(0), + _isShuttingDown(0), + _isCollectingStats(0) {} - BenchRunState::~BenchRunState() { - wassert(_numActiveWorkers == 0 && _numUnstartedWorkers == 0); - } +BenchRunState::~BenchRunState() { + wassert(_numActiveWorkers == 0 && _numUnstartedWorkers == 0); +} - void BenchRunState::waitForState(State awaitedState) { - stdx::unique_lock<stdx::mutex> lk(_mutex); +void BenchRunState::waitForState(State awaitedState) { + stdx::unique_lock<stdx::mutex> lk(_mutex); - switch ( awaitedState ) { + switch (awaitedState) { case BRS_RUNNING: - while ( _numUnstartedWorkers > 0 ) { - massert( 16147, "Already finished.", _numUnstartedWorkers + _numActiveWorkers > 0 ); - _stateChangeCondition.wait( lk ); + while (_numUnstartedWorkers > 0) { + massert(16147, "Already finished.", _numUnstartedWorkers + _numActiveWorkers > 0); + _stateChangeCondition.wait(lk); } break; case BRS_FINISHED: - while ( _numUnstartedWorkers + _numActiveWorkers > 0 ) { - _stateChangeCondition.wait( lk ); + while (_numUnstartedWorkers + _numActiveWorkers > 0) { + _stateChangeCondition.wait(lk); } break; default: - msgasserted(16152, mongoutils::str::stream() << "Cannot wait for state " << awaitedState); - } + msgasserted(16152, + mongoutils::str::stream() << "Cannot wait for state " << awaitedState); } +} - void BenchRunState::tellWorkersToFinish() { - _isShuttingDown.store( 1 ); - } +void BenchRunState::tellWorkersToFinish() { + _isShuttingDown.store(1); +} - void BenchRunState::tellWorkersToCollectStats() { - _isCollectingStats.store( 1 ); - } +void BenchRunState::tellWorkersToCollectStats() { + _isCollectingStats.store(1); +} - void BenchRunState::assertFinished() { - stdx::lock_guard<stdx::mutex> lk(_mutex); - verify(0 == _numUnstartedWorkers + _numActiveWorkers); - } +void BenchRunState::assertFinished() { + stdx::lock_guard<stdx::mutex> lk(_mutex); + verify(0 == _numUnstartedWorkers + _numActiveWorkers); +} - bool BenchRunState::shouldWorkerFinish() { - return (_isShuttingDown.loadRelaxed() == 1); - } +bool BenchRunState::shouldWorkerFinish() { + return (_isShuttingDown.loadRelaxed() == 1); +} - bool BenchRunState::shouldWorkerCollectStats() { - return (_isCollectingStats.loadRelaxed() == 1); - } +bool BenchRunState::shouldWorkerCollectStats() { + return (_isCollectingStats.loadRelaxed() == 1); +} - void BenchRunState::onWorkerStarted() { - stdx::lock_guard<stdx::mutex> lk(_mutex); - verify( _numUnstartedWorkers > 0 ); - --_numUnstartedWorkers; - ++_numActiveWorkers; - if (_numUnstartedWorkers == 0) { - _stateChangeCondition.notify_all(); - } +void BenchRunState::onWorkerStarted() { + stdx::lock_guard<stdx::mutex> lk(_mutex); + verify(_numUnstartedWorkers > 0); + --_numUnstartedWorkers; + ++_numActiveWorkers; + if (_numUnstartedWorkers == 0) { + _stateChangeCondition.notify_all(); } +} - void BenchRunState::onWorkerFinished() { - stdx::lock_guard<stdx::mutex> lk(_mutex); - verify( _numActiveWorkers > 0 ); - --_numActiveWorkers; - if (_numActiveWorkers + _numUnstartedWorkers == 0) { - _stateChangeCondition.notify_all(); - } +void BenchRunState::onWorkerFinished() { + stdx::lock_guard<stdx::mutex> lk(_mutex); + verify(_numActiveWorkers > 0); + --_numActiveWorkers; + if (_numActiveWorkers + _numUnstartedWorkers == 0) { + _stateChangeCondition.notify_all(); } +} - BSONObj benchStart( const BSONObj& , void* ); - BSONObj benchFinish( const BSONObj& , void* ); +BSONObj benchStart(const BSONObj&, void*); +BSONObj benchFinish(const BSONObj&, void*); - static bool _hasSpecial( const BSONObj& obj ) { - BSONObjIterator i( obj ); - while ( i.more() ) { - BSONElement e = i.next(); - if ( e.fieldName()[0] == '#' ) - return true; +static bool _hasSpecial(const BSONObj& obj) { + BSONObjIterator i(obj); + while (i.more()) { + BSONElement e = i.next(); + if (e.fieldName()[0] == '#') + return true; - if ( ! e.isABSONObj() ) - continue; + if (!e.isABSONObj()) + continue; - if ( _hasSpecial( e.Obj() ) ) - return true; - } - return false; + if (_hasSpecial(e.Obj())) + return true; } + return false; +} - static BSONObj fixQuery( const BSONObj& obj, BsonTemplateEvaluator& btl ) { - if ( ! _hasSpecial( obj ) ) - return obj; - BSONObjBuilder b( obj.objsize() + 128 ); +static BSONObj fixQuery(const BSONObj& obj, BsonTemplateEvaluator& btl) { + if (!_hasSpecial(obj)) + return obj; + BSONObjBuilder b(obj.objsize() + 128); - verify(BsonTemplateEvaluator::StatusSuccess == btl.evaluate(obj, b)); - return b.obj(); - } + verify(BsonTemplateEvaluator::StatusSuccess == btl.evaluate(obj, b)); + return b.obj(); +} - BenchRunWorker::BenchRunWorker(size_t id, const BenchRunConfig *config, BenchRunState *brState, - int64_t randomSeed) - : _id(id), _config(config), _brState(brState), _randomSeed(randomSeed) { - } +BenchRunWorker::BenchRunWorker(size_t id, + const BenchRunConfig* config, + BenchRunState* brState, + int64_t randomSeed) + : _id(id), _config(config), _brState(brState), _randomSeed(randomSeed) {} - BenchRunWorker::~BenchRunWorker() {} +BenchRunWorker::~BenchRunWorker() {} - void BenchRunWorker::start() { - stdx::thread(stdx::bind(&BenchRunWorker::run, this)); - } +void BenchRunWorker::start() { + stdx::thread(stdx::bind(&BenchRunWorker::run, this)); +} - bool BenchRunWorker::shouldStop() const { - return _brState->shouldWorkerFinish(); - } +bool BenchRunWorker::shouldStop() const { + return _brState->shouldWorkerFinish(); +} - bool BenchRunWorker::shouldCollectStats() const { - return _brState->shouldWorkerCollectStats(); - } +bool BenchRunWorker::shouldCollectStats() const { + return _brState->shouldWorkerCollectStats(); +} - void doNothing(const BSONObj&) { } +void doNothing(const BSONObj&) {} - void BenchRunWorker::generateLoadOnConnection( DBClientBase* conn ) { - verify( conn ); - long long count = 0; - mongo::Timer timer; +void BenchRunWorker::generateLoadOnConnection(DBClientBase* conn) { + verify(conn); + long long count = 0; + mongo::Timer timer; - BsonTemplateEvaluator bsonTemplateEvaluator(_randomSeed); - invariant(bsonTemplateEvaluator.setId(_id) == BsonTemplateEvaluator::StatusSuccess); + BsonTemplateEvaluator bsonTemplateEvaluator(_randomSeed); + invariant(bsonTemplateEvaluator.setId(_id) == BsonTemplateEvaluator::StatusSuccess); - if (_config->username != "") { - string errmsg; - if (!conn->auth("admin", _config->username, _config->password, errmsg)) { - uasserted(15931, "Authenticating to connection for _benchThread failed: " + errmsg); - } + if (_config->username != "") { + string errmsg; + if (!conn->auth("admin", _config->username, _config->password, errmsg)) { + uasserted(15931, "Authenticating to connection for _benchThread failed: " + errmsg); } + } - while ( !shouldStop() ) { - BSONObjIterator i( _config->ops ); - while ( i.more() ) { - - if ( shouldStop() ) break; - auto& stats = shouldCollectStats() ? _stats : _statsBlackHole; - BSONElement e = i.next(); - - string ns = e["ns"].String(); - string op = e["op"].String(); + while (!shouldStop()) { + BSONObjIterator i(_config->ops); + while (i.more()) { + if (shouldStop()) + break; + auto& stats = shouldCollectStats() ? _stats : _statsBlackHole; + BSONElement e = i.next(); - int delay = e["delay"].eoo() ? 0 : e["delay"].Int(); + string ns = e["ns"].String(); + string op = e["op"].String(); - // Let's default to writeCmd == false. - bool useWriteCmd = e["writeCmd"].eoo() ? false : - e["writeCmd"].Bool(); + int delay = e["delay"].eoo() ? 0 : e["delay"].Int(); - BSONObj context = e["context"].eoo() ? BSONObj() : e["context"].Obj(); + // Let's default to writeCmd == false. + bool useWriteCmd = e["writeCmd"].eoo() ? false : e["writeCmd"].Bool(); - unique_ptr<Scope> scope; - ScriptingFunction scopeFunc = 0; - BSONObj scopeObj; + BSONObj context = e["context"].eoo() ? BSONObj() : e["context"].Obj(); - bool check = ! e["check"].eoo(); - if( check ){ - if ( e["check"].type() == CodeWScope || e["check"].type() == Code || e["check"].type() == String ) { - scope = globalScriptEngine->getPooledScope(NULL, ns, "benchrun"); - verify( scope.get() ); + unique_ptr<Scope> scope; + ScriptingFunction scopeFunc = 0; + BSONObj scopeObj; - if ( e.type() == CodeWScope ) { - scopeFunc = scope->createFunction( e["check"].codeWScopeCode() ); - scopeObj = BSONObj( e.codeWScopeScopeDataUnsafe() ); - } - else { - scopeFunc = scope->createFunction( e["check"].valuestr() ); - } + bool check = !e["check"].eoo(); + if (check) { + if (e["check"].type() == CodeWScope || e["check"].type() == Code || + e["check"].type() == String) { + scope = globalScriptEngine->getPooledScope(NULL, ns, "benchrun"); + verify(scope.get()); - scope->init( &scopeObj ); - invariant(scopeFunc); - } - else { - warning() << "Invalid check type detected in benchRun op : " << e << endl; - check = false; + if (e.type() == CodeWScope) { + scopeFunc = scope->createFunction(e["check"].codeWScopeCode()); + scopeObj = BSONObj(e.codeWScopeScopeDataUnsafe()); + } else { + scopeFunc = scope->createFunction(e["check"].valuestr()); } + + scope->init(&scopeObj); + invariant(scopeFunc); + } else { + warning() << "Invalid check type detected in benchRun op : " << e << endl; + check = false; } + } - try { - if ( op == "nop") { - // do nothing + try { + if (op == "nop") { + // do nothing + } else if (op == "findOne") { + BSONObj result; + { + BenchRunEventTrace _bret(&stats.findOneCounter); + result = + conn->findOne(ns, fixQuery(e["query"].Obj(), bsonTemplateEvaluator)); } - else if ( op == "findOne" ) { - - BSONObj result; - { - BenchRunEventTrace _bret(&stats.findOneCounter); - result = conn->findOne( ns , fixQuery( e["query"].Obj(), - bsonTemplateEvaluator ) ); - } - if( check ){ - int err = scope->invoke( scopeFunc , 0 , &result, 1000 * 60 , false ); - if( err ){ - log() << "Error checking in benchRun thread [findOne]" << causedBy( scope->getError() ) << endl; + if (check) { + int err = scope->invoke(scopeFunc, 0, &result, 1000 * 60, false); + if (err) { + log() << "Error checking in benchRun thread [findOne]" + << causedBy(scope->getError()) << endl; - stats.errCount++; + stats.errCount++; - return; - } + return; } + } - if( ! _config->hideResults || e["showResult"].trueValue() ) log() << "Result from benchRun thread [findOne] : " << result << endl; - + if (!_config->hideResults || e["showResult"].trueValue()) + log() << "Result from benchRun thread [findOne] : " << result << endl; + + } else if (op == "command") { + bool ok; + BSONObj result; + { + BenchRunEventTrace _bret(&stats.commandCounter); + ok = conn->runCommand(ns, + fixQuery(e["command"].Obj(), bsonTemplateEvaluator), + result, + e["options"].numberInt()); } - else if ( op == "command" ) { - - bool ok; - BSONObj result; - { - BenchRunEventTrace _bret(&stats.commandCounter); - ok = conn->runCommand( ns, - fixQuery( e["command"].Obj(), - bsonTemplateEvaluator ), - result, - e["options"].numberInt()); - } - if (!ok) { - stats.errCount++; - } - else if( check ){ - int err = scope->invoke( scopeFunc , 0 , &result, 1000 * 60 , false ); - if( err ){ - log() << "Error checking in benchRun thread [command]" << causedBy( scope->getError() ) << endl; + if (!ok) { + stats.errCount++; + } else if (check) { + int err = scope->invoke(scopeFunc, 0, &result, 1000 * 60, false); + if (err) { + log() << "Error checking in benchRun thread [command]" + << causedBy(scope->getError()) << endl; - stats.errCount++; + stats.errCount++; - return; - } + return; } + } - if( ! _config->hideResults || e["showResult"].trueValue() ) log() << "Result from benchRun thread [command] : " << result << endl; - + if (!_config->hideResults || e["showResult"].trueValue()) + log() << "Result from benchRun thread [command] : " << result << endl; + + } else if (op == "find" || op == "query") { + int limit = e["limit"].eoo() ? 0 : e["limit"].numberInt(); + int skip = e["skip"].eoo() ? 0 : e["skip"].Int(); + int options = e["options"].eoo() ? 0 : e["options"].Int(); + int batchSize = e["batchSize"].eoo() ? 0 : e["batchSize"].Int(); + BSONObj filter = e["filter"].eoo() ? BSONObj() : e["filter"].Obj(); + int expected = e["expected"].eoo() ? -1 : e["expected"].Int(); + + unique_ptr<DBClientCursor> cursor; + int count; + + BSONObj fixedQuery = fixQuery(e["query"].Obj(), bsonTemplateEvaluator); + + // use special query function for exhaust query option + if (options & QueryOption_Exhaust) { + BenchRunEventTrace _bret(&stats.queryCounter); + stdx::function<void(const BSONObj&)> castedDoNothing(doNothing); + count = conn->query(castedDoNothing, ns, fixedQuery, &filter, options); + } else { + BenchRunEventTrace _bret(&stats.queryCounter); + cursor = + conn->query(ns, fixedQuery, limit, skip, &filter, options, batchSize); + count = cursor->itcount(); } - else if( op == "find" || op == "query" ) { - int limit = e["limit"].eoo() ? 0 : e["limit"].numberInt(); - int skip = e["skip"].eoo() ? 0 : e["skip"].Int(); - int options = e["options"].eoo() ? 0 : e["options"].Int(); - int batchSize = e["batchSize"].eoo() ? 0 : e["batchSize"].Int(); - BSONObj filter = e["filter"].eoo() ? BSONObj() : e["filter"].Obj(); - int expected = e["expected"].eoo() ? -1 : e["expected"].Int(); + if (expected >= 0 && count != expected) { + cout << "bench query on: " << ns << " expected: " << expected + << " got: " << count << endl; + verify(false); + } - unique_ptr<DBClientCursor> cursor; - int count; + if (check) { + BSONObj thisValue = BSON("count" << count << "context" << context); + int err = scope->invoke(scopeFunc, 0, &thisValue, 1000 * 60, false); + if (err) { + log() << "Error checking in benchRun thread [find]" + << causedBy(scope->getError()) << endl; - BSONObj fixedQuery = fixQuery(e["query"].Obj(), bsonTemplateEvaluator); + stats.errCount++; - // use special query function for exhaust query option - if (options & QueryOption_Exhaust) { - BenchRunEventTrace _bret(&stats.queryCounter); - stdx::function<void (const BSONObj&)> castedDoNothing(doNothing); - count = conn->query(castedDoNothing, ns, fixedQuery, &filter, options); - } - else { - BenchRunEventTrace _bret(&stats.queryCounter); - cursor = conn->query(ns, fixedQuery, limit, skip, &filter, options, - batchSize); - count = cursor->itcount(); + return; } + } - if ( expected >= 0 && count != expected ) { - cout << "bench query on: " << ns << " expected: " << expected << " got: " << count << endl; - verify(false); + if (!_config->hideResults || e["showResult"].trueValue()) + log() << "Result from benchRun thread [query] : " << count << endl; + + } else if (op == "update") { + bool multi = e["multi"].trueValue(); + bool upsert = e["upsert"].trueValue(); + BSONObj queryOrginal = e["query"].eoo() ? BSONObj() : e["query"].Obj(); + BSONObj updateOriginal = e["update"].Obj(); + BSONObj result; + bool safe = e["safe"].trueValue(); + + { + BenchRunEventTrace _bret(&stats.updateCounter); + BSONObj query = fixQuery(queryOrginal, bsonTemplateEvaluator); + BSONObj update = fixQuery(updateOriginal, bsonTemplateEvaluator); + + if (useWriteCmd) { + // TODO: Replace after SERVER-11774. + BSONObjBuilder builder; + builder.append("update", nsToCollectionSubstring(ns)); + BSONArrayBuilder docBuilder(builder.subarrayStart("updates")); + docBuilder.append(BSON("q" << query << "u" << update << "multi" << multi + << "upsert" << upsert)); + docBuilder.done(); + conn->runCommand( + nsToDatabaseSubstring(ns).toString(), builder.done(), result); + } else { + conn->update(ns, query, update, upsert, multi); + if (safe) + result = conn->getLastErrorDetailed(); } + } - if( check ){ - BSONObj thisValue = BSON( "count" << count << "context" << context ); - int err = scope->invoke( scopeFunc , 0 , &thisValue, 1000 * 60 , false ); - if( err ){ - log() << "Error checking in benchRun thread [find]" << causedBy( scope->getError() ) << endl; + if (safe) { + if (check) { + int err = scope->invoke(scopeFunc, 0, &result, 1000 * 60, false); + if (err) { + log() << "Error checking in benchRun thread [update]" + << causedBy(scope->getError()) << endl; stats.errCount++; @@ -514,464 +560,406 @@ namespace mongo { } } - if( ! _config->hideResults || e["showResult"].trueValue() ) log() << "Result from benchRun thread [query] : " << count << endl; + if (!_config->hideResults || e["showResult"].trueValue()) + log() << "Result from benchRun thread [safe update] : " << result + << endl; + if (!result["err"].eoo() && result["err"].type() == String && + (_config->throwGLE || e["throwGLE"].trueValue())) + throw DBException((string) "From benchRun GLE" + + causedBy(result["err"].String()), + result["code"].eoo() ? 0 : result["code"].Int()); } - else if( op == "update" ) { - - bool multi = e["multi"].trueValue(); - bool upsert = e["upsert"].trueValue(); - BSONObj queryOrginal = e["query"].eoo() ? BSONObj() : e["query"].Obj(); - BSONObj updateOriginal = e["update"].Obj(); - BSONObj result; - bool safe = e["safe"].trueValue(); - - { - BenchRunEventTrace _bret(&stats.updateCounter); - BSONObj query = fixQuery(queryOrginal, bsonTemplateEvaluator); - BSONObj update = fixQuery(updateOriginal, bsonTemplateEvaluator); - - if (useWriteCmd) { - // TODO: Replace after SERVER-11774. - BSONObjBuilder builder; - builder.append("update", - nsToCollectionSubstring(ns)); - BSONArrayBuilder docBuilder( - builder.subarrayStart("updates")); - docBuilder.append(BSON("q" << query << - "u" << update << - "multi" << multi << - "upsert" << upsert)); - docBuilder.done(); - conn->runCommand( - nsToDatabaseSubstring(ns).toString(), - builder.done(), result); - } - else { - conn->update(ns, query, update, - upsert , multi); - if (safe) - result = conn->getLastErrorDetailed(); - } + } else if (op == "insert") { + bool safe = e["safe"].trueValue(); + BSONObj result; + + { + BenchRunEventTrace _bret(&stats.insertCounter); + + BSONObj insertDoc = fixQuery(e["doc"].Obj(), bsonTemplateEvaluator); + + if (useWriteCmd) { + BSONObjBuilder builder; + builder.append("insert", nsToCollectionSubstring(ns)); + BSONArrayBuilder docBuilder(builder.subarrayStart("documents")); + docBuilder.append(insertDoc); + docBuilder.done(); + // TODO: Replace after SERVER-11774. + conn->runCommand( + nsToDatabaseSubstring(ns).toString(), builder.done(), result); + } else { + conn->insert(ns, insertDoc); + if (safe) + result = conn->getLastErrorDetailed(); } + } - if( safe ){ - if( check ){ - int err = scope->invoke( scopeFunc , 0 , &result, 1000 * 60 , false ); - if( err ){ - log() << "Error checking in benchRun thread [update]" << causedBy( scope->getError() ) << endl; + if (safe) { + if (check) { + int err = scope->invoke(scopeFunc, 0, &result, 1000 * 60, false); + if (err) { + log() << "Error checking in benchRun thread [insert]" + << causedBy(scope->getError()) << endl; - stats.errCount++; + stats.errCount++; - return; - } + return; } + } - if( ! _config->hideResults || e["showResult"].trueValue() ) log() << "Result from benchRun thread [safe update] : " << result << endl; + if (!_config->hideResults || e["showResult"].trueValue()) + log() << "Result from benchRun thread [safe insert] : " << result + << endl; - if( ! result["err"].eoo() && result["err"].type() == String && ( _config->throwGLE || e["throwGLE"].trueValue() ) ) - throw DBException( (string)"From benchRun GLE" + causedBy( result["err"].String() ), - result["code"].eoo() ? 0 : result["code"].Int() ); - } + if (!result["err"].eoo() && result["err"].type() == String && + (_config->throwGLE || e["throwGLE"].trueValue())) + throw DBException((string) "From benchRun GLE" + + causedBy(result["err"].String()), + result["code"].eoo() ? 0 : result["code"].Int()); } - else if( op == "insert" ) { - bool safe = e["safe"].trueValue(); - BSONObj result; - - { - BenchRunEventTrace _bret(&stats.insertCounter); - - BSONObj insertDoc = fixQuery(e["doc"].Obj(), bsonTemplateEvaluator); - - if (useWriteCmd) { - BSONObjBuilder builder; - builder.append("insert", nsToCollectionSubstring(ns)); - BSONArrayBuilder docBuilder( - builder.subarrayStart("documents")); - docBuilder.append(insertDoc); - docBuilder.done(); - // TODO: Replace after SERVER-11774. - conn->runCommand( - nsToDatabaseSubstring(ns).toString(), - builder.done(), result); - } - else { - conn->insert(ns, insertDoc); - if (safe) - result = conn->getLastErrorDetailed(); - } + } else if (op == "delete" || op == "remove") { + bool multi = e["multi"].eoo() ? true : e["multi"].trueValue(); + BSONObj query = e["query"].eoo() ? BSONObj() : e["query"].Obj(); + bool safe = e["safe"].trueValue(); + BSONObj result; + { + BenchRunEventTrace _bret(&stats.deleteCounter); + BSONObj predicate = fixQuery(query, bsonTemplateEvaluator); + if (useWriteCmd) { + // TODO: Replace after SERVER-11774. + BSONObjBuilder builder; + builder.append("delete", nsToCollectionSubstring(ns)); + BSONArrayBuilder docBuilder(builder.subarrayStart("deletes")); + int limit = (multi == true) ? 0 : 1; + docBuilder.append(BSON("q" << predicate << "limit" << limit)); + docBuilder.done(); + conn->runCommand( + nsToDatabaseSubstring(ns).toString(), builder.done(), result); + } else { + conn->remove(ns, predicate, !multi); + if (safe) + result = conn->getLastErrorDetailed(); } + } - if( safe ){ - if( check ){ - int err = scope->invoke( scopeFunc , 0 , &result, 1000 * 60 , false ); - if( err ){ - log() << "Error checking in benchRun thread [insert]" << causedBy( scope->getError() ) << endl; - - stats.errCount++; - - return; - } - } + if (safe) { + if (check) { + int err = scope->invoke(scopeFunc, 0, &result, 1000 * 60, false); + if (err) { + log() << "Error checking in benchRun thread [delete]" + << causedBy(scope->getError()) << endl; - if( ! _config->hideResults || e["showResult"].trueValue() ) log() << "Result from benchRun thread [safe insert] : " << result << endl; + stats.errCount++; - if( ! result["err"].eoo() && result["err"].type() == String && ( _config->throwGLE || e["throwGLE"].trueValue() ) ) - throw DBException( (string)"From benchRun GLE" + causedBy( result["err"].String() ), - result["code"].eoo() ? 0 : result["code"].Int() ); - } - } - else if( op == "delete" || op == "remove" ) { - - bool multi = e["multi"].eoo() ? true : e["multi"].trueValue(); - BSONObj query = e["query"].eoo() ? BSONObj() : e["query"].Obj(); - bool safe = e["safe"].trueValue(); - BSONObj result; - { - BenchRunEventTrace _bret(&stats.deleteCounter); - BSONObj predicate = fixQuery(query, bsonTemplateEvaluator); - if (useWriteCmd) { - - // TODO: Replace after SERVER-11774. - BSONObjBuilder builder; - builder.append("delete", - nsToCollectionSubstring(ns)); - BSONArrayBuilder docBuilder( - builder.subarrayStart("deletes")); - int limit = (multi == true) ? 0 : 1; - docBuilder.append( - BSON("q" << predicate << - "limit" << limit)); - docBuilder.done(); - conn->runCommand( - nsToDatabaseSubstring(ns).toString(), - builder.done(), result); - } - else { - conn->remove(ns, predicate, !multi); - if (safe) - result = conn->getLastErrorDetailed(); + return; } } - if( safe ){ - if( check ){ - int err = scope->invoke( scopeFunc , 0 , &result, 1000 * 60 , false ); - if( err ){ - log() << "Error checking in benchRun thread [delete]" << causedBy( scope->getError() ) << endl; - - stats.errCount++; + if (!_config->hideResults || e["showResult"].trueValue()) + log() << "Result from benchRun thread [safe remove] : " << result + << endl; - return; - } - } + if (!result["err"].eoo() && result["err"].type() == String && + (_config->throwGLE || e["throwGLE"].trueValue())) + throw DBException((string) "From benchRun GLE " + + causedBy(result["err"].String()), + result["code"].eoo() ? 0 : result["code"].Int()); + } + } else if (op == "createIndex") { + conn->ensureIndex(ns, e["key"].Obj(), false, "", false); + } else if (op == "dropIndex") { + conn->dropIndex(ns, e["key"].Obj()); + } else if (op == "let") { + string target = e["target"].eoo() ? string() : e["target"].String(); + BSONElement value = e["value"].eoo() ? BSONElement() : e["value"]; + BSONObjBuilder valBuilder; + BSONObjBuilder templateBuilder; + valBuilder.append(value); + bsonTemplateEvaluator.evaluate(valBuilder.done(), templateBuilder); + bsonTemplateEvaluator.setVariable(target, + templateBuilder.done().firstElement()); + } else { + log() << "don't understand op: " << op << endl; + stats.error = true; + return; + } + // Count 1 for total ops. Successfully got through the try phrase + stats.opCount++; + } catch (DBException& ex) { + if (!_config->hideErrors || e["showError"].trueValue()) { + bool yesWatch = + (_config->watchPattern && _config->watchPattern->FullMatch(ex.what())); + bool noWatch = + (_config->noWatchPattern && _config->noWatchPattern->FullMatch(ex.what())); + + if ((!_config->watchPattern && _config->noWatchPattern && + !noWatch) || // If we're just ignoring things + (!_config->noWatchPattern && _config->watchPattern && + yesWatch) || // If we're just watching things + (_config->watchPattern && _config->noWatchPattern && yesWatch && !noWatch)) + log() << "Error in benchRun thread for op " << e << causedBy(ex) << endl; + } - if( ! _config->hideResults || e["showResult"].trueValue() ) log() << "Result from benchRun thread [safe remove] : " << result << endl; + bool yesTrap = (_config->trapPattern && _config->trapPattern->FullMatch(ex.what())); + bool noTrap = + (_config->noTrapPattern && _config->noTrapPattern->FullMatch(ex.what())); - if( ! result["err"].eoo() && result["err"].type() == String && ( _config->throwGLE || e["throwGLE"].trueValue() ) ) - throw DBException( (string)"From benchRun GLE " + causedBy( result["err"].String() ), - result["code"].eoo() ? 0 : result["code"].Int() ); - } - } - else if ( op == "createIndex" ) { - conn->ensureIndex(ns, e["key"].Obj(), false, "", false); + if ((!_config->trapPattern && _config->noTrapPattern && !noTrap) || + (!_config->noTrapPattern && _config->trapPattern && yesTrap) || + (_config->trapPattern && _config->noTrapPattern && yesTrap && !noTrap)) { + { + stats.trappedErrors.push_back( + BSON("error" << ex.what() << "op" << e << "count" << count)); } - else if ( op == "dropIndex" ) { - conn->dropIndex( ns , e["key"].Obj() ); - } - else if( op == "let" ) { - string target = e["target"].eoo() ? string() : e["target"].String(); - BSONElement value = e["value"].eoo() ? BSONElement() : e["value"]; - BSONObjBuilder valBuilder; - BSONObjBuilder templateBuilder; - valBuilder.append(value); - bsonTemplateEvaluator.evaluate(valBuilder.done(), templateBuilder); - bsonTemplateEvaluator.setVariable(target, templateBuilder.done().firstElement()); - } - else { - log() << "don't understand op: " << op << endl; - stats.error = true; + if (_config->breakOnTrap) return; - } - // Count 1 for total ops. Successfully got through the try phrase - stats.opCount++; } - catch( DBException& ex ){ - if( ! _config->hideErrors || e["showError"].trueValue() ){ - - bool yesWatch = ( _config->watchPattern && _config->watchPattern->FullMatch( ex.what() ) ); - bool noWatch = ( _config->noWatchPattern && _config->noWatchPattern->FullMatch( ex.what() ) ); + if (!_config->handleErrors && !e["handleError"].trueValue()) + return; + + stats.errCount++; + } catch (...) { + if (!_config->hideErrors || e["showError"].trueValue()) + log() << "Error in benchRun thread caused by unknown error for op " << e + << endl; + if (!_config->handleErrors && !e["handleError"].trueValue()) + return; + + stats.errCount++; + } - if( ( ! _config->watchPattern && _config->noWatchPattern && ! noWatch ) || // If we're just ignoring things - ( ! _config->noWatchPattern && _config->watchPattern && yesWatch ) || // If we're just watching things - ( _config->watchPattern && _config->noWatchPattern && yesWatch && ! noWatch ) ) - log() << "Error in benchRun thread for op " << e << causedBy( ex ) << endl; - } + if (++count % 100 == 0 && !useWriteCmd) { + conn->getLastError(); + } - bool yesTrap = ( _config->trapPattern && _config->trapPattern->FullMatch( ex.what() ) ); - bool noTrap = ( _config->noTrapPattern && _config->noTrapPattern->FullMatch( ex.what() ) ); + if (delay > 0) + sleepmillis(delay); + } + } - if( ( ! _config->trapPattern && _config->noTrapPattern && ! noTrap ) || - ( ! _config->noTrapPattern && _config->trapPattern && yesTrap ) || - ( _config->trapPattern && _config->noTrapPattern && yesTrap && ! noTrap ) ){ - { - stats.trappedErrors.push_back( BSON( "error" << ex.what() << "op" << e << "count" << count ) ); - } - if( _config->breakOnTrap ) return; - } - if( ! _config->handleErrors && ! e["handleError"].trueValue() ) return; + conn->getLastError(); +} - stats.errCount++; - } - catch( ... ){ - if( ! _config->hideErrors || e["showError"].trueValue() ) log() << "Error in benchRun thread caused by unknown error for op " << e << endl; - if( ! _config->handleErrors && ! e["handleError"].trueValue() ) return; +namespace { +class BenchRunWorkerStateGuard { + MONGO_DISALLOW_COPYING(BenchRunWorkerStateGuard); - stats.errCount++; - } +public: + explicit BenchRunWorkerStateGuard(BenchRunState* brState) : _brState(brState) { + _brState->onWorkerStarted(); + } - if (++count % 100 == 0 && !useWriteCmd) { - conn->getLastError(); - } + ~BenchRunWorkerStateGuard() { + _brState->onWorkerFinished(); + } - if (delay > 0) - sleepmillis( delay ); +private: + BenchRunState* _brState; +}; +} // namespace +void BenchRunWorker::run() { + try { + std::unique_ptr<DBClientBase> conn(_config->createConnection()); + if (!_config->username.empty()) { + string errmsg; + if (!conn->auth("admin", _config->username, _config->password, errmsg)) { + uasserted(15932, "Authenticating to connection for benchThread failed: " + errmsg); } } - - conn->getLastError(); + BenchRunWorkerStateGuard _workerStateGuard(_brState); + generateLoadOnConnection(conn.get()); + } catch (DBException& e) { + error() << "DBException not handled in benchRun thread" << causedBy(e) << endl; + } catch (std::exception& e) { + error() << "std::exception not handled in benchRun thread" << causedBy(e) << endl; + } catch (...) { + error() << "Unknown exception not handled in benchRun thread." << endl; } +} - namespace { - class BenchRunWorkerStateGuard { - MONGO_DISALLOW_COPYING(BenchRunWorkerStateGuard); - public: - explicit BenchRunWorkerStateGuard( BenchRunState *brState ) : _brState( brState ) { - _brState->onWorkerStarted(); - } +BenchRunner::BenchRunner(BenchRunConfig* config) : _brState(config->parallel), _config(config) { + _oid.init(); + stdx::lock_guard<stdx::mutex> lk(_staticMutex); + _activeRuns[_oid] = this; +} - ~BenchRunWorkerStateGuard() { - _brState->onWorkerFinished(); - } +BenchRunner::~BenchRunner() { + for (size_t i = 0; i < _workers.size(); ++i) + delete _workers[i]; +} - private: - BenchRunState *_brState; - }; - } // namespace - - void BenchRunWorker::run() { - try { - std::unique_ptr<DBClientBase> conn( _config->createConnection() ); - if ( !_config->username.empty() ) { - string errmsg; - if (!conn->auth("admin", _config->username, _config->password, errmsg)) { - uasserted(15932, - "Authenticating to connection for benchThread failed: " + errmsg); - } +void BenchRunner::start() { + { + std::unique_ptr<DBClientBase> conn(_config->createConnection()); + // Must authenticate to admin db in order to run serverStatus command + if (_config->username != "") { + string errmsg; + if (!conn->auth("admin", _config->username, _config->password, errmsg)) { + uasserted(16704, + str::stream() + << "User " << _config->username + << " could not authenticate to admin db; admin db access is " + "required to use benchRun with auth enabled"); } - BenchRunWorkerStateGuard _workerStateGuard( _brState ); - generateLoadOnConnection( conn.get() ); - } - catch( DBException& e ){ - error() << "DBException not handled in benchRun thread" << causedBy( e ) << endl; - } - catch( std::exception& e ){ - error() << "std::exception not handled in benchRun thread" << causedBy( e ) << endl; } - catch( ... ){ - error() << "Unknown exception not handled in benchRun thread." << endl; + + // Start threads + for (int64_t i = 0; i < _config->parallel; i++) { + // Make a unique random seed for the worker. + int64_t seed = _config->randomSeed + i; + BenchRunWorker* worker = new BenchRunWorker(i, _config.get(), &_brState, seed); + worker->start(); + _workers.push_back(worker); } - } - BenchRunner::BenchRunner( BenchRunConfig *config ) - : _brState(config->parallel), - _config(config) { + _brState.waitForState(BenchRunState::BRS_RUNNING); - _oid.init(); - stdx::lock_guard<stdx::mutex> lk(_staticMutex); - _activeRuns[_oid] = this; - } - - BenchRunner::~BenchRunner() { - for (size_t i = 0; i < _workers.size(); ++i) - delete _workers[i]; - } - - void BenchRunner::start( ) { - - { - std::unique_ptr<DBClientBase> conn( _config->createConnection() ); - // Must authenticate to admin db in order to run serverStatus command - if (_config->username != "") { - string errmsg; - if (!conn->auth("admin", _config->username, _config->password, errmsg)) { - uasserted(16704, - str::stream() << "User " << _config->username - << " could not authenticate to admin db; admin db access is " - "required to use benchRun with auth enabled"); - } - } - - // Start threads - for ( int64_t i = 0; i < _config->parallel; i++ ) { - // Make a unique random seed for the worker. - int64_t seed = _config->randomSeed + i; - BenchRunWorker *worker = new BenchRunWorker(i, _config.get(), - &_brState, seed); - worker->start(); - _workers.push_back(worker); - } - - _brState.waitForState(BenchRunState::BRS_RUNNING); - - // initial stats - _brState.tellWorkersToCollectStats(); - _brTimer = new mongo::Timer(); - } - } - - void BenchRunner::stop() { - _brState.tellWorkersToFinish(); - _brState.waitForState(BenchRunState::BRS_FINISHED); - _microsElapsed = _brTimer->micros(); - delete _brTimer; - - { - std::unique_ptr<DBClientBase> conn( _config->createConnection() ); - if (_config->username != "") { - string errmsg; - // this can only fail if admin access was revoked since start of run - if (!conn->auth("admin", _config->username, _config->password, errmsg)) { - uasserted(16705, - str::stream() << "User " << _config->username - << " could not authenticate to admin db; admin db access is " - "still required to use benchRun with auth enabled"); - } - } - } - - { - stdx::lock_guard<stdx::mutex> lk(_staticMutex); - _activeRuns.erase( _oid ); - } - } - - BenchRunner* BenchRunner::createWithConfig( const BSONObj &configArgs ) { - BenchRunConfig *config = BenchRunConfig::createFromBson( configArgs ); - return new BenchRunner(config); - } - - BenchRunner* BenchRunner::get( OID oid ) { - stdx::lock_guard<stdx::mutex> lk(_staticMutex); - return _activeRuns[ oid ]; - } - - void BenchRunner::populateStats( BenchRunStats *stats ) { - _brState.assertFinished(); - stats->reset(); - for ( size_t i = 0; i < _workers.size(); ++i ) - stats->updateFrom( _workers[i]->stats() ); + // initial stats + _brState.tellWorkersToCollectStats(); + _brTimer = new mongo::Timer(); } +} - static void appendAverageMicrosIfAvailable( - BSONObjBuilder &buf, const std::string &name, const BenchRunEventCounter &counter) { +void BenchRunner::stop() { + _brState.tellWorkersToFinish(); + _brState.waitForState(BenchRunState::BRS_FINISHED); + _microsElapsed = _brTimer->micros(); + delete _brTimer; - if (counter.getNumEvents() > 0) - buf.append(name, - static_cast<double>(counter.getTotalTimeMicros()) / counter.getNumEvents()); - } + { + std::unique_ptr<DBClientBase> conn(_config->createConnection()); + if (_config->username != "") { + string errmsg; + // this can only fail if admin access was revoked since start of run + if (!conn->auth("admin", _config->username, _config->password, errmsg)) { + uasserted(16705, + str::stream() + << "User " << _config->username + << " could not authenticate to admin db; admin db access is " + "still required to use benchRun with auth enabled"); + } + } + } - BSONObj BenchRunner::finish( BenchRunner* runner ) { + { + stdx::lock_guard<stdx::mutex> lk(_staticMutex); + _activeRuns.erase(_oid); + } +} - runner->stop(); +BenchRunner* BenchRunner::createWithConfig(const BSONObj& configArgs) { + BenchRunConfig* config = BenchRunConfig::createFromBson(configArgs); + return new BenchRunner(config); +} + +BenchRunner* BenchRunner::get(OID oid) { + stdx::lock_guard<stdx::mutex> lk(_staticMutex); + return _activeRuns[oid]; +} - BenchRunStats stats; - runner->populateStats(&stats); +void BenchRunner::populateStats(BenchRunStats* stats) { + _brState.assertFinished(); + stats->reset(); + for (size_t i = 0; i < _workers.size(); ++i) + stats->updateFrom(_workers[i]->stats()); +} - // vector<BSONOBj> errors = runner->config.errors; - bool error = stats.error; +static void appendAverageMicrosIfAvailable(BSONObjBuilder& buf, + const std::string& name, + const BenchRunEventCounter& counter) { + if (counter.getNumEvents() > 0) + buf.append(name, + static_cast<double>(counter.getTotalTimeMicros()) / counter.getNumEvents()); +} - if ( error ) - return BSON( "err" << 1 ); +BSONObj BenchRunner::finish(BenchRunner* runner) { + runner->stop(); - BSONObjBuilder buf; - buf.append( "note" , "values per second" ); - buf.append( "errCount", static_cast<long long>(stats.errCount) ); - buf.append( "trapped", "error: not implemented" ); - appendAverageMicrosIfAvailable(buf, "findOneLatencyAverageMicros", stats.findOneCounter); - appendAverageMicrosIfAvailable(buf, "insertLatencyAverageMicros", stats.insertCounter); - appendAverageMicrosIfAvailable(buf, "deleteLatencyAverageMicros", stats.deleteCounter); - appendAverageMicrosIfAvailable(buf, "updateLatencyAverageMicros", stats.updateCounter); - appendAverageMicrosIfAvailable(buf, "queryLatencyAverageMicros", stats.queryCounter); - appendAverageMicrosIfAvailable(buf, "commandsLatencyAverageMicros", stats.commandCounter); + BenchRunStats stats; + runner->populateStats(&stats); - buf.append("totalOps", static_cast<long long>(stats.opCount)); + // vector<BSONOBj> errors = runner->config.errors; + bool error = stats.error; - auto appendPerSec = [&buf, runner](StringData name, double total) { - buf.append(name, total / (runner->_microsElapsed / 1000000.0)); - }; + if (error) + return BSON("err" << 1); - appendPerSec("totalOps/s", stats.opCount); - appendPerSec("findOne", stats.findOneCounter.getNumEvents()); - appendPerSec("insert", stats.insertCounter.getNumEvents()); - appendPerSec("delete", stats.deleteCounter.getNumEvents()); - appendPerSec("update", stats.updateCounter.getNumEvents()); - appendPerSec("query", stats.queryCounter.getNumEvents()); - appendPerSec("command", stats.commandCounter.getNumEvents()); + BSONObjBuilder buf; + buf.append("note", "values per second"); + buf.append("errCount", static_cast<long long>(stats.errCount)); + buf.append("trapped", "error: not implemented"); + appendAverageMicrosIfAvailable(buf, "findOneLatencyAverageMicros", stats.findOneCounter); + appendAverageMicrosIfAvailable(buf, "insertLatencyAverageMicros", stats.insertCounter); + appendAverageMicrosIfAvailable(buf, "deleteLatencyAverageMicros", stats.deleteCounter); + appendAverageMicrosIfAvailable(buf, "updateLatencyAverageMicros", stats.updateCounter); + appendAverageMicrosIfAvailable(buf, "queryLatencyAverageMicros", stats.queryCounter); + appendAverageMicrosIfAvailable(buf, "commandsLatencyAverageMicros", stats.commandCounter); - BSONObj zoo = buf.obj(); + buf.append("totalOps", static_cast<long long>(stats.opCount)); - delete runner; - return zoo; - } + auto appendPerSec = [&buf, runner](StringData name, double total) { + buf.append(name, total / (runner->_microsElapsed / 1000000.0)); + }; - stdx::mutex BenchRunner::_staticMutex; - map< OID, BenchRunner* > BenchRunner::_activeRuns; + appendPerSec("totalOps/s", stats.opCount); + appendPerSec("findOne", stats.findOneCounter.getNumEvents()); + appendPerSec("insert", stats.insertCounter.getNumEvents()); + appendPerSec("delete", stats.deleteCounter.getNumEvents()); + appendPerSec("update", stats.updateCounter.getNumEvents()); + appendPerSec("query", stats.queryCounter.getNumEvents()); + appendPerSec("command", stats.commandCounter.getNumEvents()); - /** - * benchRun( { ops : [] , host : XXX , db : XXXX , parallel : 5 , seconds : 5 } - */ - BSONObj BenchRunner::benchRunSync( const BSONObj& argsFake, void* data ) { + BSONObj zoo = buf.obj(); - BSONObj start = benchStart( argsFake, data ); + delete runner; + return zoo; +} - OID oid = OID( start.firstElement().String() ); - BenchRunner* runner = BenchRunner::get( oid ); +stdx::mutex BenchRunner::_staticMutex; +map<OID, BenchRunner*> BenchRunner::_activeRuns; - sleepmillis( (int)(1000.0 * runner->config().seconds) ); +/** + * benchRun( { ops : [] , host : XXX , db : XXXX , parallel : 5 , seconds : 5 } + */ +BSONObj BenchRunner::benchRunSync(const BSONObj& argsFake, void* data) { + BSONObj start = benchStart(argsFake, data); - return benchFinish( start, data ); - } + OID oid = OID(start.firstElement().String()); + BenchRunner* runner = BenchRunner::get(oid); - /** - * benchRun( { ops : [] , host : XXX , db : XXXX , parallel : 5 , seconds : 5 } - */ - BSONObj BenchRunner::benchStart( const BSONObj& argsFake, void* data ) { + sleepmillis((int)(1000.0 * runner->config().seconds)); - verify( argsFake.firstElement().isABSONObj() ); - BSONObj args = argsFake.firstElement().Obj(); + return benchFinish(start, data); +} - // Get new BenchRunner object - BenchRunner* runner = BenchRunner::createWithConfig( args ); +/** + * benchRun( { ops : [] , host : XXX , db : XXXX , parallel : 5 , seconds : 5 } + */ +BSONObj BenchRunner::benchStart(const BSONObj& argsFake, void* data) { + verify(argsFake.firstElement().isABSONObj()); + BSONObj args = argsFake.firstElement().Obj(); - runner->start(); - return BSON( "" << runner->oid().toString() ); - } + // Get new BenchRunner object + BenchRunner* runner = BenchRunner::createWithConfig(args); - /** - * benchRun( { ops : [] , host : XXX , db : XXXX , parallel : 5 , seconds : 5 } - */ - BSONObj BenchRunner::benchFinish( const BSONObj& argsFake, void* data ) { + runner->start(); + return BSON("" << runner->oid().toString()); +} - OID oid = OID( argsFake.firstElement().String() ); +/** + * benchRun( { ops : [] , host : XXX , db : XXXX , parallel : 5 , seconds : 5 } + */ +BSONObj BenchRunner::benchFinish(const BSONObj& argsFake, void* data) { + OID oid = OID(argsFake.firstElement().String()); - // Get old BenchRunner object - BenchRunner* runner = BenchRunner::get( oid ); + // Get old BenchRunner object + BenchRunner* runner = BenchRunner::get(oid); - BSONObj finalObj = BenchRunner::finish( runner ); + BSONObj finalObj = BenchRunner::finish(runner); - return BSON( "" << finalObj ); - } + return BSON("" << finalObj); +} -} // namespace mongo +} // namespace mongo |