diff options
Diffstat (limited to 'src')
41 files changed, 211 insertions, 312 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript index 1804251f3aa..8f54fddfdc5 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -156,8 +156,9 @@ env.Library( env.Library('lasterror', [ "db/lasterror.cpp", ], - LIBDEPS=['util/net/network', - 'util/foundation', + LIBDEPS=[ + 'service_context', + 'util/foundation', ]) def getSysInfo(): @@ -508,8 +509,9 @@ env.Library( 'db/service_context_noop.cpp', ], LIBDEPS=[ - 'lasterror', # TODO(schwerin): REMOVE! + 'util/concurrency/spin_lock', 'util/decorable', + 'util/net/hostandport', ]) # Memory-mapped files support. Used by mongod and some tools. diff --git a/src/mongo/client/scoped_db_conn_test.cpp b/src/mongo/client/scoped_db_conn_test.cpp index 6adfca400cd..b8aec56844f 100644 --- a/src/mongo/client/scoped_db_conn_test.cpp +++ b/src/mongo/client/scoped_db_conn_test.cpp @@ -103,9 +103,7 @@ namespace mongo { virtual void connected(AbstractMessagingPort* p) { } - virtual void process(Message& m, - AbstractMessagingPort* port, - LastError * le) { + virtual void process(Message& m, AbstractMessagingPort* por) { boost::this_thread::interruption_point(); } }; diff --git a/src/mongo/db/client.cpp b/src/mongo/db/client.cpp index cc4a7c69cab..a2e510f4bb0 100644 --- a/src/mongo/db/client.cpp +++ b/src/mongo/db/client.cpp @@ -83,7 +83,6 @@ namespace mongo { } setThreadName(fullDesc.c_str()); - mongo::lastError.initThread(); // Create the client obj, attach to thread *currentClient.get() = service->makeClient(fullDesc, mp); diff --git a/src/mongo/db/client.h b/src/mongo/db/client.h index f81bc91bf37..63750b69523 100644 --- a/src/mongo/db/client.h +++ b/src/mongo/db/client.h @@ -40,7 +40,6 @@ #include <boost/thread/thread.hpp> #include "mongo/db/client_basic.h" -#include "mongo/db/lasterror.h" #include "mongo/db/namespace_string.h" #include "mongo/db/operation_context.h" #include "mongo/db/service_context.h" diff --git a/src/mongo/db/commands/find_and_modify.cpp b/src/mongo/db/commands/find_and_modify.cpp index e94771683c2..7de1b1ff966 100644 --- a/src/mongo/db/commands/find_and_modify.cpp +++ b/src/mongo/db/commands/find_and_modify.cpp @@ -43,6 +43,7 @@ #include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/db_raii.h" #include "mongo/db/exec/working_set_common.h" +#include "mongo/db/lasterror.h" #include "mongo/db/namespace_string.h" #include "mongo/db/operation_context.h" #include "mongo/db/ops/delete_request.h" diff --git a/src/mongo/db/commands/get_last_error.cpp b/src/mongo/db/commands/get_last_error.cpp index b3a6ffe84ec..54a9fb469d5 100644 --- a/src/mongo/db/commands/get_last_error.cpp +++ b/src/mongo/db/commands/get_last_error.cpp @@ -72,9 +72,7 @@ namespace mongo { int, string& errmsg, BSONObjBuilder& result) { - LastError *le = lastError.get(); - verify( le ); - le->reset(); + LastError::get(txn->getClient()).reset(); return true; } } cmdResetError; @@ -88,7 +86,7 @@ namespace mongo { const BSONObj& cmdObj, std::vector<Privilege>* out) {} // No auth required virtual void help( stringstream& help ) const { - lastError.disableForCommand(); // SERVER-11492 + LastError::get(cc()).disable(); // SERVER-11492 help << "return error status of the last operation on this connection\n" << "options:\n" << " { fsync:true } - fsync before returning, or wait for journal commit if running with --journal\n" @@ -128,7 +126,8 @@ namespace mongo { // err is null. // - LastError *le = lastError.disableForCommand(); + LastError *le = &LastError::get(txn->getClient()); + le->disable(); // Always append lastOp and connectionId Client& c = *txn->getClient(); @@ -173,7 +172,7 @@ namespace mongo { // Errors aren't reported when wOpTime is used if ( !lastOpTimePresent ) { - if ( le->nPrev != 1 ) { + if ( le->getNPrev() != 1 ) { errorOccurred = LastError::noError.appendSelf( result, false ); } else { @@ -284,12 +283,13 @@ namespace mongo { int, string& errmsg, BSONObjBuilder& result) { - LastError *le = lastError.disableForCommand(); - le->appendSelf( result ); - if ( le->valid ) - result.append( "nPrev", le->nPrev ); + LastError *le = &LastError::get(txn->getClient()); + le->disable(); + le->appendSelf(result, true); + if (le->isValid()) + result.append("nPrev", le->getNPrev()); else - result.append( "nPrev", -1 ); + result.append("nPrev", -1); return true; } } cmdGetPrevError; diff --git a/src/mongo/db/commands/write_commands/batch_executor.cpp b/src/mongo/db/commands/write_commands/batch_executor.cpp index 72bdb1fc144..ae57fdbecbb 100644 --- a/src/mongo/db/commands/write_commands/batch_executor.cpp +++ b/src/mongo/db/commands/write_commands/batch_executor.cpp @@ -550,8 +550,10 @@ namespace mongo { if ( currWrite.getOpType() == BatchedCommandRequest::BatchType_Insert ) { _stats->numInserted += stats.n; - _le->nObjects = stats.n; currentOp->debug().ninserted += stats.n; + if (!error) { + _le->recordInsert(stats.n); + } } else if ( currWrite.getOpType() == BatchedCommandRequest::BatchType_Update ) { if ( stats.upsertedID.isEmpty() ) { @@ -562,7 +564,7 @@ namespace mongo { ++_stats->numUpserted; } - if ( !error ) { + if (!error) { _le->recordUpdate( stats.upsertedID.isEmpty() && stats.n > 0, stats.n, stats.upsertedID ); @@ -577,8 +579,8 @@ namespace mongo { currentOp->debug().ndeleted += stats.n; } - if (error && !_le->disabled) { - _le->raiseError(error->getErrCode(), error->getErrMessage().c_str()); + if (error) { + _le->setLastError(error->getErrCode(), error->getErrMessage().c_str()); } } diff --git a/src/mongo/db/commands/write_commands/batch_executor.h b/src/mongo/db/commands/write_commands/batch_executor.h index 613fb281777..e5d55a5b9fb 100644 --- a/src/mongo/db/commands/write_commands/batch_executor.h +++ b/src/mongo/db/commands/write_commands/batch_executor.h @@ -44,12 +44,11 @@ namespace mongo { class BSONObjBuilder; class CurOp; + class LastError; class OpCounters; class OperationContext; - struct LastError; - - struct WriteOpStats; class WriteBatchStats; + struct WriteOpStats; /** * An instance of WriteBatchExecutor is an object capable of issuing a write batch. diff --git a/src/mongo/db/commands/write_commands/write_commands.cpp b/src/mongo/db/commands/write_commands/write_commands.cpp index d6d6d7ff137..a1d217d7525 100644 --- a/src/mongo/db/commands/write_commands/write_commands.cpp +++ b/src/mongo/db/commands/write_commands/write_commands.cpp @@ -104,7 +104,7 @@ namespace mongo { // TODO: Remove this when we standardize GLE reporting from commands if ( !status.isOK() ) { - setLastError( status.code(), status.reason().c_str() ); + LastError::get(client).setLastError(status.code(), status.reason()); } return status; @@ -145,7 +145,7 @@ namespace mongo { WriteBatchExecutor writeBatchExecutor(txn, &globalOpCounters, - lastError.get()); + &LastError::get(txn->getClient())); writeBatchExecutor.executeBatch( request, &response ); diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp index 92bb4177c91..aed1bf00958 100644 --- a/src/mongo/db/db.cpp +++ b/src/mongo/db/db.cpp @@ -70,7 +70,6 @@ #include "mongo/db/instance.h" #include "mongo/db/introspect.h" #include "mongo/db/json.h" -#include "mongo/db/lasterror.h" #include "mongo/db/log_process_details.h" #include "mongo/db/mongod_options.h" #include "mongo/db/op_observer.h" @@ -157,7 +156,7 @@ namespace mongo { Client::initThread("conn", p); } - virtual void process( Message& m , AbstractMessagingPort* port , LastError * le) { + virtual void process(Message& m , AbstractMessagingPort* port) { OperationContextImpl txn; while ( true ) { if ( inShutdown() ) { @@ -165,8 +164,6 @@ namespace mongo { break; } - lastError.startRequest( m , le ); - DbResponse dbresponse; assembleResponse(&txn, m, dbresponse, port->remote()); diff --git a/src/mongo/db/dbcommands_generic.cpp b/src/mongo/db/dbcommands_generic.cpp index c07dc30a1dc..e01790b0b73 100644 --- a/src/mongo/db/dbcommands_generic.cpp +++ b/src/mongo/db/dbcommands_generic.cpp @@ -330,7 +330,7 @@ namespace mongo { int, string& errmsg, BSONObjBuilder& result) { - setLastError(10038, "forced error"); + LastError::get(cc()).setLastError(10038, "forced error"); return false; } } cmdForceError; diff --git a/src/mongo/db/dbdirectclient.cpp b/src/mongo/db/dbdirectclient.cpp index 41b75377060..3aee1750172 100644 --- a/src/mongo/db/dbdirectclient.cpp +++ b/src/mongo/db/dbdirectclient.cpp @@ -33,6 +33,7 @@ #include "mongo/db/client.h" #include "mongo/db/commands.h" #include "mongo/db/instance.h" +#include "mongo/db/lasterror.h" #include "mongo/db/operation_context.h" #include "mongo/util/log.h" @@ -122,9 +123,7 @@ namespace mongo { bool assertOk, string* actualServer) { DirectClientScope directClientScope(_txn); - if (lastError._get()) { - lastError.startRequest(toSend, lastError._get()); - } + LastError::get(_txn->getClient()).startRequest(); DbResponse dbResponse; assembleResponse(_txn, toSend, dbResponse, dummyHost); @@ -139,9 +138,7 @@ namespace mongo { void DBDirectClient::say(Message& toSend, bool isRetry, string* actualServer) { DirectClientScope directClientScope(_txn); - if (lastError._get()) { - lastError.startRequest(toSend, lastError._get()); - } + LastError::get(_txn->getClient()).startRequest(); DbResponse dbResponse; assembleResponse(_txn, toSend, dbResponse, dummyHost); diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp index c39978787f8..2a5bc8eb4e9 100644 --- a/src/mongo/db/instance.cpp +++ b/src/mongo/db/instance.cpp @@ -391,6 +391,7 @@ namespace { Client& c = *txn->getClient(); if (!c.isInDirectClient()) { + LastError::get(c).startRequest(); AuthorizationSession::get(c)->startRequest(txn); // We should not be holding any locks at this point @@ -558,14 +559,14 @@ namespace { } } catch (const UserException& ue) { - setLastError(ue.getCode(), ue.getInfo().msg.c_str()); + LastError::get(c).setLastError(ue.getCode(), ue.getInfo().msg); MONGO_LOG_COMPONENT(3, responseComponent) << " Caught Assertion in " << opToString(op) << ", continuing " << ue.toString() << endl; debug.exceptionInfo = ue.getInfo(); } catch (const AssertionException& e) { - setLastError(e.getCode(), e.getInfo().msg.c_str()); + LastError::get(c).setLastError(e.getCode(), e.getInfo().msg); MONGO_LOG_COMPONENT(3, responseComponent) << " Caught Assertion in " << opToString(op) << ", continuing " << e.toString() << endl; @@ -606,6 +607,7 @@ namespace { } void receivedKillCursors(OperationContext* txn, Message& m) { + LastError::get(txn->getClient()).disable(); DbMessage dbmessage(m); int n = dbmessage.pullInt(); @@ -702,7 +704,8 @@ namespace { UpdateResult res = UpdateStage::makeUpdateResult(exec.get(), &op.debug()); // for getlasterror - lastError.getSafe()->recordUpdate( res.existing , res.numMatched , res.upserted ); + LastError::get(txn->getClient()).recordUpdate( + res.existing, res.numMatched, res.upserted); return; } break; @@ -755,7 +758,8 @@ namespace { uassertStatusOK(exec->executePlan()); UpdateResult res = UpdateStage::makeUpdateResult(exec.get(), &op.debug()); - lastError.getSafe()->recordUpdate( res.existing , res.numMatched , res.upserted ); + LastError::get(txn->getClient()).recordUpdate( + res.existing, res.numMatched, res.upserted); } MONGO_WRITE_CONFLICT_RETRY_LOOP_END(txn, "update", nsString.ns()); } @@ -813,7 +817,7 @@ namespace { // Run the plan and get the number of docs deleted. uassertStatusOK(exec->executePlan()); long long n = DeleteStage::getNumDeleted(exec.get()); - lastError.getSafe()->recordDelete(n); + LastError::get(txn->getClient()).recordDelete(n); op.debug().ndeleted = n; break; @@ -1003,7 +1007,7 @@ namespace { globalOpCounters.incInsertInWriteLock(i); throw; } - setLastError(ex.getCode(), ex.getInfo().msg.c_str()); + LastError::get(txn->getClient()).setLastError(ex.getCode(), ex.getInfo().msg); // otherwise ignore and keep going } } @@ -1057,7 +1061,7 @@ namespace { convertSystemIndexInsertsToCommands(d, &allCmdsBuilder); } catch (const DBException& ex) { - setLastError(ex.getCode(), ex.getInfo().msg.c_str()); + LastError::get(txn->getClient()).setLastError(ex.getCode(), ex.getInfo().msg); curOp.debug().exceptionInfo = ex.getInfo(); return; } @@ -1079,7 +1083,7 @@ namespace { uassertStatusOK(Command::getStatusFromCommandResult(resultBuilder.done())); } catch (const DBException& ex) { - setLastError(ex.getCode(), ex.getInfo().msg.c_str()); + LastError::get(txn->getClient()).setLastError(ex.getCode(), ex.getInfo().msg); curOp.debug().exceptionInfo = ex.getInfo(); if (!keepGoing) { return; diff --git a/src/mongo/db/lasterror.cpp b/src/mongo/db/lasterror.cpp index d0a22d56b51..d242cdedc1a 100644 --- a/src/mongo/db/lasterror.cpp +++ b/src/mongo/db/lasterror.cpp @@ -27,139 +27,91 @@ * then also delete it in the license file. */ -#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault - #include "mongo/platform/basic.h" #include "mongo/db/lasterror.h" #include "mongo/db/jsobj.h" -#include "mongo/util/debug_util.h" -#include "mongo/util/log.h" -#include "mongo/util/net/message.h" +#include "mongo/util/assert_util.h" namespace mongo { - using std::endl; - LastError LastError::noError; - LastErrorHolder lastError; - - bool isShell = false; - void setLastError(int code , const char *msg) { - LastError *le = lastError.get(); - if ( le == 0 ) { - /* might be intentional (non-user thread) */ - DEV { - static unsigned n; - if( ++n < 4 && !isShell ) log() << "dev: lastError==0 won't report:" << msg << endl; - } - } - else if ( le->disabled ) { - log() << "lastError disabled, can't report: " << code << ":" << msg << endl; - } - else { - le->raiseError(code, msg); - } - } - bool LastError::appendSelf( BSONObjBuilder &b , bool blankErr ) { + const Client::Decoration<LastError> LastError::get = Client::declareDecoration<LastError>(); - if ( !valid ) { - if ( blankErr ) - b.appendNull( "err" ); - b.append( "n", 0 ); - return false; - } - - if ( msg.empty() ) { - if ( blankErr ) { - b.appendNull( "err" ); - } - } - else { - b.append( "err", msg ); - } + void LastError::reset(bool valid) { + *this = LastError(); + _valid = valid; + } - if ( code ) - b.append( "code" , code ); - if ( updatedExisting != NotUpdate ) - b.appendBool( "updatedExisting", updatedExisting == True ); - if ( !upsertedId.isEmpty() ) { - b.append( upsertedId[kUpsertedFieldName] ); + void LastError::setLastError(int code, std::string msg) { + if (_disabled) { + return; } - b.appendNumber( "n", nObjects ); - - return ! msg.empty(); + reset(true); + _code = code; + _msg = std::move(msg); } - LastErrorHolder::~LastErrorHolder() { + void LastError::recordInsert(long long nObjects) { + reset(true); + _nObjects = nObjects; } - - LastError * LastErrorHolder::disableForCommand() { - LastError *le = _get(); - uassert(13649, "no operation yet", le); - le->disabled = true; - le->nPrev--; // caller is a command that shouldn't count as an operation - return le; + void LastError::recordUpdate(bool updateObjects, long long nObjects, BSONObj upsertedId) { + reset(true); + _nObjects = nObjects; + _updatedExisting = updateObjects ? True : False; + if ( upsertedId.valid() && upsertedId.hasField(kUpsertedFieldName) ) + _upsertedId = upsertedId; } - LastError * LastErrorHolder::get( bool create ) { - LastError *ret = _get( create ); - if ( ret && !ret->disabled ) - return ret; - return 0; + void LastError::recordDelete(long long nDeleted) { + reset(true); + _nObjects = nDeleted; } - LastError * LastErrorHolder::getSafe() { - LastError * le = get(false); - if ( ! le ) { - error() << " no LastError!" << std::endl; - verify( le ); + bool LastError::appendSelf(BSONObjBuilder &b , bool blankErr) const { + + if (!_valid) { + if (blankErr) + b.appendNull( "err" ); + b.append( "n", 0 ); + return false; } - return le; - } - LastError * LastErrorHolder::_get( bool create ) { - LastError * le = _tl.get(); - if ( ! le && create ) { - le = new LastError(); - _tl.reset( le ); + if (_msg.empty()) { + if (blankErr) { + b.appendNull( "err" ); + } + } + else { + b.append("err", _msg); } - return le; - } - void LastErrorHolder::release() { - _tl.release(); - } + if (_code) + b.append("code" , _code); + if (_updatedExisting != NotUpdate) + b.appendBool("updatedExisting", _updatedExisting == True); + if (!_upsertedId.isEmpty()) { + b.append(_upsertedId[kUpsertedFieldName]); + } + b.appendNumber("n", _nObjects); - /** ok to call more than once. */ - void LastErrorHolder::initThread() { - if( ! _tl.get() ) - _tl.reset( new LastError() ); + return !_msg.empty(); } - void LastErrorHolder::reset( LastError * le ) { - _tl.reset( le ); - } - void prepareErrForNewRequest( Message &m, LastError * err ) { - // a killCursors message shouldn't affect last error - verify( err ); - if ( m.operation() == dbKillCursors ) { - err->disabled = true; - } - else { - err->disabled = false; - err->nPrev++; - } + void LastError::disable() { + invariant(!_disabled); + _disabled = true; + _nPrev--; // caller is a command that shouldn't count as an operation } - LastError * LastErrorHolder::startRequest( Message& m , LastError * le ) { - verify( le ); - prepareErrForNewRequest( m, le ); - return le; + void LastError::startRequest() { + _disabled = false; + ++_nPrev; } } // namespace mongo diff --git a/src/mongo/db/lasterror.h b/src/mongo/db/lasterror.h index 5b04b69a57a..55a04c8334d 100644 --- a/src/mongo/db/lasterror.h +++ b/src/mongo/db/lasterror.h @@ -29,16 +29,13 @@ #pragma once -#include <boost/noncopyable.hpp> -#include <boost/thread/tss.hpp> #include <string> +#include "mongo/db/client.h" #include "mongo/db/jsobj.h" -#include "mongo/bson/oid.h" namespace mongo { class BSONObjBuilder; - class Message; static const char kUpsertedFieldName[] = "upserted"; static const char kGLEStatsFieldName[] = "$gleStats"; @@ -46,107 +43,80 @@ namespace mongo { static const char kGLEStatsLastOpTimeTermFieldName[] = "lastOpTimeTerm"; static const char kGLEStatsElectionIdFieldName[] = "electionId"; - struct LastError { - int code; - std::string msg; - enum UpdatedExistingType { NotUpdate, True, False } updatedExisting; - // _id field value from inserted doc, returned as kUpsertedFieldName (above) - BSONObj upsertedId; - long long nObjects; - int nPrev; - bool valid; - bool disabled; - void raiseError(int _code , const char *_msg) { - reset( true ); - code = _code; - msg = _msg; - } - void recordUpdate( bool _updateObjects , long long _nObjects , BSONObj _upsertedId ) { - reset( true ); - nObjects = _nObjects; - updatedExisting = _updateObjects ? True : False; - if ( _upsertedId.valid() && _upsertedId.hasField(kUpsertedFieldName) ) - upsertedId = _upsertedId; - - } - void recordDelete( long long nDeleted ) { - reset( true ); - nObjects = nDeleted; - } - LastError() { - reset(); - } - void reset( bool _valid = false ) { - code = 0; - msg.clear(); - updatedExisting = NotUpdate; - nObjects = 0; - nPrev = 1; - valid = _valid; - disabled = false; - upsertedId = BSONObj(); - } + class LastError { + public: + static const Client::Decoration<LastError> get; /** - * @return if there is an err + * Resets the object to a newly constructed state. If "valid" is true, marks the last-error + * object as "valid". */ - bool appendSelf( BSONObjBuilder &b , bool blankErr = true ); - - struct Disabled : boost::noncopyable { - Disabled( LastError * le ) { - _le = le; - if ( _le ) { - _prev = _le->disabled; - _le->disabled = true; - } - else { - _prev = false; - } - } + void reset(bool valid = false); - ~Disabled() { - if ( _le ) - _le->disabled = _prev; - } + /** + * when db receives a message/request, call this + */ + void startRequest(); - LastError * _le; - bool _prev; - }; + /** + * Disables error recording for the current operation. + */ + void disable(); - static LastError noError; - }; + /** + * Sets the error information for the current operation, if error recording was not + * explicitly disabled via a call to disable() since the call to startRequest. + */ + void setLastError(int code, std::string msg); - extern class LastErrorHolder { - public: - LastErrorHolder(){} - ~LastErrorHolder(); + void recordInsert(long long nObjects); - LastError * get( bool create = false ); - LastError * getSafe(); - LastError * _get( bool create = false ); // may return a disabled LastError + void recordUpdate(bool updateObjects, long long nObjects, BSONObj upsertedId); - void reset( LastError * le ); + void recordDelete(long long nDeleted); - /** ok to call more than once. */ - void initThread(); + /** + * Writes the last-error state described by this object to "b". + * + * If "blankErr" is true, the "err" field will be explicitly set to null in the result + * instead of being omitted when the error string is empty. + * + * Returns true if there is a non-empty error message. + */ + bool appendSelf(BSONObjBuilder &b, bool blankErr) const; - void release(); + bool isValid() const { return _valid; } + int const getNPrev() const { return _nPrev; } - /** when db receives a message/request, call this */ - LastError * startRequest( Message& m , LastError * connectionOwned ); + class Disabled { + public: + explicit Disabled(LastError* le) : _le(le), _prev(le->_disabled) { + _le->_disabled = true; + } - // used to disable lastError reporting while processing a killCursors message - // disable causes get() to return 0. - LastError *disableForCommand(); // only call once per command invocation! - private: - boost::thread_specific_ptr<LastError> _tl; + ~Disabled() { + _le->_disabled = _prev; + } - struct Status { - time_t time; - LastError *lerr; + private: + LastError * const _le; + const bool _prev; }; - } lastError; - void setLastError(int code , const char *msg); + static LastError noError; + + private: + enum UpdatedExistingType { NotUpdate, True, False }; + + int _code = 0; + std::string _msg = {}; + UpdatedExistingType _updatedExisting = NotUpdate; + // _id field value from inserted doc, returned as kUpsertedFieldName (above) + BSONObj _upsertedId = {}; + long long _nObjects = 0; + int _nPrev = 1; + bool _valid = false; + bool _disabled = false; + }; } // namespace mongo diff --git a/src/mongo/db/ops/update_result.cpp b/src/mongo/db/ops/update_result.cpp index f5e31c1a3d8..64b33243131 100644 --- a/src/mongo/db/ops/update_result.cpp +++ b/src/mongo/db/ops/update_result.cpp @@ -34,6 +34,7 @@ #include "mongo/db/ops/update_result.h" +#include "mongo/db/lasterror.h" #include "mongo/util/log.h" namespace mongo { diff --git a/src/mongo/db/repl/replication_info.cpp b/src/mongo/db/repl/replication_info.cpp index f4cd02426a2..a5303072fbd 100644 --- a/src/mongo/db/repl/replication_info.cpp +++ b/src/mongo/db/repl/replication_info.cpp @@ -37,6 +37,7 @@ #include "mongo/db/db_raii.h" #include "mongo/db/dbhelpers.h" #include "mongo/db/jsobj.h" +#include "mongo/db/lasterror.h" #include "mongo/db/operation_context_impl.h" #include "mongo/db/query/internal_plans.h" #include "mongo/db/repl/is_master_response.h" @@ -216,7 +217,7 @@ namespace repl { authenticated. */ if ( cmdObj["forShell"].trueValue() ) - lastError.disableForCommand(); + LastError::get(txn->getClient()).disable(); appendReplicationInfo(txn, result, 0); diff --git a/src/mongo/db/repl/replset_commands.cpp b/src/mongo/db/repl/replset_commands.cpp index bedbf59a05a..342ee8e514b 100644 --- a/src/mongo/db/repl/replset_commands.cpp +++ b/src/mongo/db/repl/replset_commands.cpp @@ -41,6 +41,7 @@ #include "mongo/db/auth/authorization_session.h" #include "mongo/db/commands.h" #include "mongo/db/dbhelpers.h" +#include "mongo/db/lasterror.h" #include "mongo/db/service_context.h" #include "mongo/db/op_observer.h" #include "mongo/db/repl/initial_sync.h" @@ -152,7 +153,7 @@ namespace repl { string& errmsg, BSONObjBuilder& result) { if ( cmdObj["forShell"].trueValue() ) - lastError.disableForCommand(); + LastError::get(txn->getClient()).disable(); Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result); if (!status.isOK()) diff --git a/src/mongo/dbtests/directclienttests.cpp b/src/mongo/dbtests/directclienttests.cpp index 822db3b58f4..fc076a9f926 100644 --- a/src/mongo/dbtests/directclienttests.cpp +++ b/src/mongo/dbtests/directclienttests.cpp @@ -33,6 +33,7 @@ #include <iostream> +#include "mongo/db/client.h" #include "mongo/db/db.h" #include "mongo/db/dbdirectclient.h" #include "mongo/db/json.h" @@ -49,15 +50,11 @@ namespace DirectClientTests { class ClientBase { public: ClientBase() { - _prevError = mongo::lastError._get( false ); - mongo::lastError.release(); - mongo::lastError.reset( new LastError() ); + mongo::LastError::get(cc()).reset(); } virtual ~ClientBase() { - mongo::lastError.reset( _prevError ); + mongo::LastError::get(cc()).reset(); } - private: - LastError* _prevError; }; const char *ns = "a.b"; diff --git a/src/mongo/dbtests/perftests.cpp b/src/mongo/dbtests/perftests.cpp index 90c0d74c632..310ae31e3a1 100644 --- a/src/mongo/dbtests/perftests.cpp +++ b/src/mongo/dbtests/perftests.cpp @@ -49,6 +49,7 @@ #include <mutex> #include "mongo/config.h" +#include "mongo/db/client.h" #include "mongo/db/db.h" #include "mongo/db/dbdirectclient.h" #include "mongo/db/json.h" @@ -91,12 +92,10 @@ namespace PerfTests { class ClientBase { public: ClientBase() : _client(&_txn) { - _prevError = mongo::lastError._get( false ); - mongo::lastError.release(); - mongo::lastError.reset( new LastError() ); + mongo::LastError::get(_txn.getClient()).reset(); } virtual ~ClientBase() { - mongo::lastError.reset( _prevError ); + mongo::LastError::get(_txn.getClient()).reset(); } protected: @@ -114,7 +113,6 @@ namespace PerfTests { OperationContext* txn() { return &_txn; } private: - LastError* _prevError; OperationContextImpl _txn; DBDirectClient _client; }; diff --git a/src/mongo/dbtests/querytests.cpp b/src/mongo/dbtests/querytests.cpp index bab0f1e22fe..5aac0a989e5 100644 --- a/src/mongo/dbtests/querytests.cpp +++ b/src/mongo/dbtests/querytests.cpp @@ -216,13 +216,11 @@ namespace QueryTests { class ClientBase { public: ClientBase() : _client(&_txn) { - _prevError = mongo::lastError._get( false ); - mongo::lastError.release(); - mongo::lastError.reset( new LastError() ); + mongo::LastError::get(_txn.getClient()).reset(); _txn.getCurOp()->reset(); } virtual ~ClientBase() { - mongo::lastError.reset( _prevError ); + mongo::LastError::get(_txn.getClient()).reset(); } protected: @@ -238,9 +236,6 @@ namespace QueryTests { OperationContextImpl _txn; DBDirectClient _client; - - private: - LastError* _prevError; }; class BoundedKey : public ClientBase { diff --git a/src/mongo/dbtests/updatetests.cpp b/src/mongo/dbtests/updatetests.cpp index 4d2f527c54a..fa7271bcb6b 100644 --- a/src/mongo/dbtests/updatetests.cpp +++ b/src/mongo/dbtests/updatetests.cpp @@ -54,12 +54,10 @@ namespace UpdateTests { class ClientBase { public: ClientBase() : _client(&_txn) { - _prevError = mongo::lastError._get( false ); - mongo::lastError.release(); - mongo::lastError.reset( new LastError() ); + mongo::LastError::get(_txn.getClient()).reset(); } virtual ~ClientBase() { - mongo::lastError.reset( _prevError ); + mongo::LastError::get(_txn.getClient()).reset(); } protected: @@ -75,9 +73,6 @@ namespace UpdateTests { OperationContextImpl _txn; DBDirectClient _client; - - private: - LastError* _prevError; }; class Fail : public ClientBase { diff --git a/src/mongo/s/SConscript b/src/mongo/s/SConscript index aa3583ddb4a..2051f239ad7 100644 --- a/src/mongo/s/SConscript +++ b/src/mongo/s/SConscript @@ -169,8 +169,9 @@ env.Library( ], LIBDEPS=[ '$BUILD_DIR/mongo/bson', - 'cluster_ops', '$BUILD_DIR/mongo/db/common', # for Message + '$BUILD_DIR/mongo/lasterror', + 'cluster_ops', ], ) diff --git a/src/mongo/s/balance.cpp b/src/mongo/s/balance.cpp index 6e52b7e1346..a42738e512d 100644 --- a/src/mongo/s/balance.cpp +++ b/src/mongo/s/balance.cpp @@ -37,6 +37,7 @@ #include "mongo/base/owned_pointer_map.h" #include "mongo/client/connpool.h" #include "mongo/client/dbclientcursor.h" +#include "mongo/db/client.h" #include "mongo/db/jsobj.h" #include "mongo/db/namespace_string.h" #include "mongo/db/server_options.h" @@ -496,6 +497,7 @@ namespace mongo { void Balancer::run() { + Client::initThread("Balancer"); // this is the body of a BackgroundJob so if we throw here we're basically ending the balancer thread prematurely while ( ! inShutdown() ) { diff --git a/src/mongo/s/chunk.cpp b/src/mongo/s/chunk.cpp index b62a0da7512..8fe331f9c26 100644 --- a/src/mongo/s/chunk.cpp +++ b/src/mongo/s/chunk.cpp @@ -532,7 +532,7 @@ namespace { bool Chunk::splitIfShould( long dataWritten ) const { dassert( ShouldAutoSplit ); - LastError::Disabled d( lastError.get() ); + LastError::Disabled d(&LastError::get(cc())); try { _dataWritten += dataWritten; diff --git a/src/mongo/s/client/shard_connection.cpp b/src/mongo/s/client/shard_connection.cpp index b4bda6824c2..f27041c7167 100644 --- a/src/mongo/s/client/shard_connection.cpp +++ b/src/mongo/s/client/shard_connection.cpp @@ -282,7 +282,7 @@ namespace { Shard::getAllShards( all ); // Don't report exceptions here as errors in GetLastError - LastError::Disabled ignoreForGLE(lastError.get(false)); + LastError::Disabled ignoreForGLE(&LastError::get(cc())); // Now only check top-level shard connections for ( unsigned i=0; i<all.size(); i++ ) { diff --git a/src/mongo/s/commands/cluster_get_last_error_cmd.cpp b/src/mongo/s/commands/cluster_get_last_error_cmd.cpp index 2ee08b3aab9..a703d705b6d 100644 --- a/src/mongo/s/commands/cluster_get_last_error_cmd.cpp +++ b/src/mongo/s/commands/cluster_get_last_error_cmd.cpp @@ -88,12 +88,13 @@ namespace { // about 2.4 behavior? // - LastError *le = lastError.disableForCommand(); - invariant(le); + LastError *le = &LastError::get(cc()); + le->disable(); + // Write commands always have the error stored in the mongos last error bool errorOccurred = false; - if (le->nPrev == 1) { + if (le->getNPrev() == 1) { errorOccurred = le->appendSelf(result, false); } diff --git a/src/mongo/s/commands/cluster_repl_set_get_status_cmd.cpp b/src/mongo/s/commands/cluster_repl_set_get_status_cmd.cpp index bacb5da705e..0164fe3cc15 100644 --- a/src/mongo/s/commands/cluster_repl_set_get_status_cmd.cpp +++ b/src/mongo/s/commands/cluster_repl_set_get_status_cmd.cpp @@ -72,7 +72,7 @@ namespace { BSONObjBuilder& result) { if (cmdObj["forShell"].trueValue()) { - lastError.disableForCommand(); + LastError::get(cc()).disable(); ClusterLastErrorInfo::get(cc()).disableForCommand(); } diff --git a/src/mongo/s/commands/cluster_reset_error_cmd.cpp b/src/mongo/s/commands/cluster_reset_error_cmd.cpp index 182daedaa66..8bc2af039f3 100644 --- a/src/mongo/s/commands/cluster_reset_error_cmd.cpp +++ b/src/mongo/s/commands/cluster_reset_error_cmd.cpp @@ -66,10 +66,7 @@ namespace { std::string& errmsg, BSONObjBuilder& result) { - LastError* le = lastError.get(); - if (le) { - le->reset(); - } + LastError::get(cc()).reset(); const std::set<std::string>* shards = ClusterLastErrorInfo::get(cc()).getPrevShardHosts(); diff --git a/src/mongo/s/commands/cluster_write_cmd.cpp b/src/mongo/s/commands/cluster_write_cmd.cpp index 925a944eb4d..83a039a3f3b 100644 --- a/src/mongo/s/commands/cluster_write_cmd.cpp +++ b/src/mongo/s/commands/cluster_write_cmd.cpp @@ -85,7 +85,7 @@ namespace { // TODO: Remove this when we standardize GLE reporting from commands if (!status.isOK()) { - setLastError(status.code(), status.reason().c_str()); + LastError::get(client).setLastError(status.code(), status.reason()); } return status; @@ -149,8 +149,7 @@ namespace { ClusterWriter writer(true, 0); - // NOTE: Sometimes this command is invoked with LE disabled for legacy writes - LastError* cmdLastError = lastError.get(false); + LastError* cmdLastError = &LastError::get(cc()); { // Disable the last error object for the duration of the write @@ -174,11 +173,9 @@ namespace { dassert(response.isValid(NULL)); } - if (cmdLastError) { - // Populate the lastError object based on the write response - cmdLastError->reset(); - batchErrorToLastError(request, response, cmdLastError); - } + // Populate the lastError object based on the write response + cmdLastError->reset(); + batchErrorToLastError(request, response, cmdLastError); size_t numAttempts; diff --git a/src/mongo/s/config.cpp b/src/mongo/s/config.cpp index bd9c633b126..c5d4742095e 100644 --- a/src/mongo/s/config.cpp +++ b/src/mongo/s/config.cpp @@ -282,7 +282,7 @@ namespace mongo { ChunkManagerPtr DBConfig::getChunkManagerIfExists( const string& ns, bool shouldReload, bool forceReload ){ // Don't report exceptions here as errors in GetLastError - LastError::Disabled ignoreForGLE(lastError.get(false)); + LastError::Disabled ignoreForGLE(&LastError::get(cc())); try{ return getChunkManager( ns, shouldReload, forceReload ); diff --git a/src/mongo/s/cursors.cpp b/src/mongo/s/cursors.cpp index dd339627668..e7e623eeed9 100644 --- a/src/mongo/s/cursors.cpp +++ b/src/mongo/s/cursors.cpp @@ -46,6 +46,7 @@ #include "mongo/db/auth/privilege.h" #include "mongo/db/commands.h" #include "mongo/db/jsobj.h" +#include "mongo/db/lasterror.h" #include "mongo/db/max_time.h" #include "mongo/db/server_parameters.h" #include "mongo/util/concurrency/task.h" @@ -367,6 +368,7 @@ namespace mongo { } void CursorCache::gotKillCursors(Message& m ) { + LastError::get(cc()).disable(); DbMessage dbmessage(m); int n = dbmessage.pullInt(); diff --git a/src/mongo/s/d_state.cpp b/src/mongo/s/d_state.cpp index c409aad00d9..23dac9ad504 100644 --- a/src/mongo/s/d_state.cpp +++ b/src/mongo/s/d_state.cpp @@ -48,6 +48,7 @@ #include "mongo/db/db.h" #include "mongo/db/db_raii.h" #include "mongo/db/jsobj.h" +#include "mongo/db/lasterror.h" #include "mongo/db/operation_context.h" #include "mongo/db/repl/replication_coordinator_global.h" #include "mongo/db/wire_version.h" @@ -1028,7 +1029,7 @@ namespace mongo { // step 1 - lastError.disableForCommand(); + LastError::get(txn->getClient()).disable(); ShardedConnectionInfo* info = ShardedConnectionInfo::get( true ); bool authoritative = cmdObj.getBoolField( "authoritative" ); diff --git a/src/mongo/s/request.cpp b/src/mongo/s/request.cpp index 8c8b40dc608..5c231d507c9 100644 --- a/src/mongo/s/request.cpp +++ b/src/mongo/s/request.cpp @@ -37,6 +37,7 @@ #include "mongo/db/auth/authorization_session.h" #include "mongo/db/client.h" #include "mongo/db/commands.h" +#include "mongo/db/lasterror.h" #include "mongo/db/stats/counters.h" #include "mongo/s/cluster_last_error_info.h" #include "mongo/s/cursors.h" @@ -67,6 +68,7 @@ namespace mongo { } _m.header().setId(_id); + LastError::get(_clientInfo).startRequest(); ClusterLastErrorInfo::get(_clientInfo).clearRequestInfo(); if (_d.messageShouldHaveNs()) { diff --git a/src/mongo/s/server.cpp b/src/mongo/s/server.cpp index f76fec271b6..f3de417fc2e 100644 --- a/src/mongo/s/server.cpp +++ b/src/mongo/s/server.cpp @@ -142,13 +142,10 @@ namespace mongo { Client::initThread("conn", getGlobalServiceContext(), p); } - virtual void process( Message& m , AbstractMessagingPort* p , LastError * le) { + virtual void process(Message& m, AbstractMessagingPort* p) { verify( p ); Request r( m , p ); - verify( le ); - lastError.startRequest( m , le ); - try { r.init(); r.process(); @@ -165,7 +162,7 @@ namespace mongo { } // We *always* populate the last error for now - le->raiseError( ex.getCode() , ex.what() ); + LastError::get(cc()).setLastError(ex.getCode(), ex.what()); } catch ( const DBException& ex ) { @@ -179,7 +176,7 @@ namespace mongo { } // We *always* populate the last error for now - le->raiseError( ex.getCode() , ex.what() ); + LastError::get(cc()).setLastError(ex.getCode(), ex.what()); } // Release connections back to pool, if any still cached diff --git a/src/mongo/s/strategy.cpp b/src/mongo/s/strategy.cpp index fb1aaa32faa..87eccbe14f9 100644 --- a/src/mongo/s/strategy.cpp +++ b/src/mongo/s/strategy.cpp @@ -654,7 +654,7 @@ namespace mongo { void Strategy::writeOp( int op , Request& r ) { // make sure we have a last error - dassert( lastError.get( false /* don't create */) ); + dassert(&LastError::get(cc())); OwnedPointerVector<BatchedCommandRequest> requestsOwned; vector<BatchedCommandRequest*>& requests = requestsOwned.mutableVector(); @@ -666,7 +666,7 @@ namespace mongo { // Multiple commands registered to last error as multiple requests if ( it != requests.begin() ) - lastError.startRequest( r.m(), lastError.get( false ) ); + LastError::get(cc()).startRequest(); BatchedCommandRequest* request = *it; @@ -681,7 +681,7 @@ namespace mongo { { // Disable the last error object for the duration of the write cmd - LastError::Disabled disableLastError( lastError.get( false ) ); + LastError::Disabled disableLastError(&LastError::get(cc())); Command::runAgainstRegistered( cmdNS.c_str(), requestBSON, builder, 0 ); } @@ -691,8 +691,8 @@ namespace mongo { dassert( parsed && response.isValid( NULL ) ); // Populate the lastError object based on the write response - lastError.get( false )->reset(); - bool hadError = batchErrorToLastError( *request, response, lastError.get( false ) ); + LastError::get(cc()).reset(); + bool hadError = batchErrorToLastError(*request, response, &LastError::get(cc())); // Check if this is an ordered batch and we had an error which should stop processing if ( request->getOrdered() && hadError ) diff --git a/src/mongo/s/write_ops/batch_upconvert.cpp b/src/mongo/s/write_ops/batch_upconvert.cpp index 3df74fd614f..e81d35ea9db 100644 --- a/src/mongo/s/write_ops/batch_upconvert.cpp +++ b/src/mongo/s/write_ops/batch_upconvert.cpp @@ -203,8 +203,8 @@ namespace mongo { // Record an error if one exists if ( lastBatchError ) { string errMsg = lastBatchError->getErrMessage(); - error->raiseError( lastBatchError->getErrCode(), - errMsg.empty() ? "see code for details" : errMsg.c_str() ); + error->setLastError(lastBatchError->getErrCode(), + errMsg.empty() ? "see code for details" : errMsg.c_str()); return true; } diff --git a/src/mongo/s/write_ops/batch_upconvert_test.cpp b/src/mongo/s/write_ops/batch_upconvert_test.cpp index 12c60982da1..c802411c9e5 100644 --- a/src/mongo/s/write_ops/batch_upconvert_test.cpp +++ b/src/mongo/s/write_ops/batch_upconvert_test.cpp @@ -25,6 +25,7 @@ * exception statement from all source files in the program, then also delete * it in the license file. */ +#include "mongo/platform/basic.h" #include "mongo/s/write_ops/batch_upconvert.h" diff --git a/src/mongo/shell/dbshell.cpp b/src/mongo/shell/dbshell.cpp index 8abfcecbc9f..ceafa7375b5 100644 --- a/src/mongo/shell/dbshell.cpp +++ b/src/mongo/shell/dbshell.cpp @@ -424,10 +424,6 @@ string finishCode( string code ) { return code; } -namespace mongo { - extern bool isShell; -} - bool execPrompt( mongo::Scope &scope, const char *promptFunction, string &prompt ) { string execStatement = string( "__prompt__ = " ) + promptFunction + "();"; scope.exec( "delete __prompt__;", "", false, false, false, 0 ); @@ -588,7 +584,6 @@ static void edit( const string& whatToEdit ) { } int _main( int argc, char* argv[], char **envp ) { - mongo::isShell = true; setupSignalHandlers(true); setupSignals(); diff --git a/src/mongo/util/net/message_server.h b/src/mongo/util/net/message_server.h index 66bdec58ad7..7bb9759eeff 100644 --- a/src/mongo/util/net/message_server.h +++ b/src/mongo/util/net/message_server.h @@ -38,8 +38,6 @@ namespace mongo { - struct LastError; - class MessageHandler { public: virtual ~MessageHandler() {} @@ -53,7 +51,7 @@ namespace mongo { * called every time a message comes in * handler is responsible for responding to client */ - virtual void process( Message& m , AbstractMessagingPort* p , LastError * err ) = 0; + virtual void process(Message& m, AbstractMessagingPort* p) = 0; }; class MessageServer { diff --git a/src/mongo/util/net/message_server_port.cpp b/src/mongo/util/net/message_server_port.cpp index 8db034fbe6e..682a7361ede 100644 --- a/src/mongo/util/net/message_server_port.cpp +++ b/src/mongo/util/net/message_server_port.cpp @@ -207,9 +207,6 @@ namespace { Message m; int64_t counter = 0; try { - LastError * le = new LastError(); - lastError.reset( le ); // lastError now has ownership - handler->connected(portWithHandler.get()); while ( ! inShutdown() ) { @@ -227,7 +224,7 @@ namespace { break; } - handler->process(m, portWithHandler.get(), le); + handler->process(m, portWithHandler.get()); networkCounter.hit(portWithHandler->psock->getBytesIn(), portWithHandler->psock->getBytesOut()); |