diff options
Diffstat (limited to 'src')
40 files changed, 312 insertions, 209 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript index c3ed86b1d9b..9abc6ccd67c 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -357,9 +357,8 @@ env.Library( env.Library('lasterror', [ "db/lasterror.cpp", ], - LIBDEPS=[ - 'foundation', - 'service_context', + LIBDEPS=['network', + 'foundation', ]) def getSysInfo(): @@ -710,8 +709,7 @@ env.Library( 'db/service_context_noop.cpp', ], LIBDEPS=[ - 'hostandport', - 'spin_lock', + 'lasterror', # TODO(schwerin): REMOVE! 'util/decorable', ]) diff --git a/src/mongo/client/scoped_db_conn_test.cpp b/src/mongo/client/scoped_db_conn_test.cpp index b8aec56844f..6adfca400cd 100644 --- a/src/mongo/client/scoped_db_conn_test.cpp +++ b/src/mongo/client/scoped_db_conn_test.cpp @@ -103,7 +103,9 @@ namespace mongo { virtual void connected(AbstractMessagingPort* p) { } - virtual void process(Message& m, AbstractMessagingPort* por) { + virtual void process(Message& m, + AbstractMessagingPort* port, + LastError * le) { boost::this_thread::interruption_point(); } }; diff --git a/src/mongo/db/client.cpp b/src/mongo/db/client.cpp index a2e510f4bb0..cc4a7c69cab 100644 --- a/src/mongo/db/client.cpp +++ b/src/mongo/db/client.cpp @@ -83,6 +83,7 @@ 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 63750b69523..f81bc91bf37 100644 --- a/src/mongo/db/client.h +++ b/src/mongo/db/client.h @@ -40,6 +40,7 @@ #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 7dcdab369a2..b8e76b8e0a2 100644 --- a/src/mongo/db/commands/find_and_modify.cpp +++ b/src/mongo/db/commands/find_and_modify.cpp @@ -43,7 +43,6 @@ #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 54a9fb469d5..b3a6ffe84ec 100644 --- a/src/mongo/db/commands/get_last_error.cpp +++ b/src/mongo/db/commands/get_last_error.cpp @@ -72,7 +72,9 @@ namespace mongo { int, string& errmsg, BSONObjBuilder& result) { - LastError::get(txn->getClient()).reset(); + LastError *le = lastError.get(); + verify( le ); + le->reset(); return true; } } cmdResetError; @@ -86,7 +88,7 @@ namespace mongo { const BSONObj& cmdObj, std::vector<Privilege>* out) {} // No auth required virtual void help( stringstream& help ) const { - LastError::get(cc()).disable(); // SERVER-11492 + lastError.disableForCommand(); // 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" @@ -126,8 +128,7 @@ namespace mongo { // err is null. // - LastError *le = &LastError::get(txn->getClient()); - le->disable(); + LastError *le = lastError.disableForCommand(); // Always append lastOp and connectionId Client& c = *txn->getClient(); @@ -172,7 +173,7 @@ namespace mongo { // Errors aren't reported when wOpTime is used if ( !lastOpTimePresent ) { - if ( le->getNPrev() != 1 ) { + if ( le->nPrev != 1 ) { errorOccurred = LastError::noError.appendSelf( result, false ); } else { @@ -283,13 +284,12 @@ namespace mongo { int, string& errmsg, BSONObjBuilder& result) { - LastError *le = &LastError::get(txn->getClient()); - le->disable(); - le->appendSelf(result, true); - if (le->isValid()) - result.append("nPrev", le->getNPrev()); + LastError *le = lastError.disableForCommand(); + le->appendSelf( result ); + if ( le->valid ) + result.append( "nPrev", le->nPrev ); 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 ae57fdbecbb..72bdb1fc144 100644 --- a/src/mongo/db/commands/write_commands/batch_executor.cpp +++ b/src/mongo/db/commands/write_commands/batch_executor.cpp @@ -550,10 +550,8 @@ 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() ) { @@ -564,7 +562,7 @@ namespace mongo { ++_stats->numUpserted; } - if (!error) { + if ( !error ) { _le->recordUpdate( stats.upsertedID.isEmpty() && stats.n > 0, stats.n, stats.upsertedID ); @@ -579,8 +577,8 @@ namespace mongo { currentOp->debug().ndeleted += stats.n; } - if (error) { - _le->setLastError(error->getErrCode(), error->getErrMessage().c_str()); + if (error && !_le->disabled) { + _le->raiseError(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 e5d55a5b9fb..613fb281777 100644 --- a/src/mongo/db/commands/write_commands/batch_executor.h +++ b/src/mongo/db/commands/write_commands/batch_executor.h @@ -44,11 +44,12 @@ namespace mongo { class BSONObjBuilder; class CurOp; - class LastError; class OpCounters; class OperationContext; - class WriteBatchStats; + struct LastError; + struct WriteOpStats; + class WriteBatchStats; /** * 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 a1d217d7525..d6d6d7ff137 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() ) { - LastError::get(client).setLastError(status.code(), status.reason()); + setLastError( status.code(), status.reason().c_str() ); } return status; @@ -145,7 +145,7 @@ namespace mongo { WriteBatchExecutor writeBatchExecutor(txn, &globalOpCounters, - &LastError::get(txn->getClient())); + lastError.get()); writeBatchExecutor.executeBatch( request, &response ); diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp index aed1bf00958..92bb4177c91 100644 --- a/src/mongo/db/db.cpp +++ b/src/mongo/db/db.cpp @@ -70,6 +70,7 @@ #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" @@ -156,7 +157,7 @@ namespace mongo { Client::initThread("conn", p); } - virtual void process(Message& m , AbstractMessagingPort* port) { + virtual void process( Message& m , AbstractMessagingPort* port , LastError * le) { OperationContextImpl txn; while ( true ) { if ( inShutdown() ) { @@ -164,6 +165,8 @@ 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 b9a3c7ef6af..c07dc30a1dc 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) { - LastError::get(txn->getClient()).setLastError(10038, "forced error"); + setLastError(10038, "forced error"); return false; } } cmdForceError; diff --git a/src/mongo/db/dbdirectclient.cpp b/src/mongo/db/dbdirectclient.cpp index 3aee1750172..41b75377060 100644 --- a/src/mongo/db/dbdirectclient.cpp +++ b/src/mongo/db/dbdirectclient.cpp @@ -33,7 +33,6 @@ #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" @@ -123,7 +122,9 @@ namespace mongo { bool assertOk, string* actualServer) { DirectClientScope directClientScope(_txn); - LastError::get(_txn->getClient()).startRequest(); + if (lastError._get()) { + lastError.startRequest(toSend, lastError._get()); + } DbResponse dbResponse; assembleResponse(_txn, toSend, dbResponse, dummyHost); @@ -138,7 +139,9 @@ namespace mongo { void DBDirectClient::say(Message& toSend, bool isRetry, string* actualServer) { DirectClientScope directClientScope(_txn); - LastError::get(_txn->getClient()).startRequest(); + if (lastError._get()) { + lastError.startRequest(toSend, lastError._get()); + } DbResponse dbResponse; assembleResponse(_txn, toSend, dbResponse, dummyHost); diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp index 099492d607a..80bf95116ce 100644 --- a/src/mongo/db/instance.cpp +++ b/src/mongo/db/instance.cpp @@ -389,7 +389,6 @@ 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 @@ -557,14 +556,14 @@ namespace { } } catch (const UserException& ue) { - LastError::get(c).setLastError(ue.getCode(), ue.getInfo().msg); + setLastError(ue.getCode(), ue.getInfo().msg.c_str()); MONGO_LOG_COMPONENT(3, responseComponent) << " Caught Assertion in " << opToString(op) << ", continuing " << ue.toString() << endl; debug.exceptionInfo = ue.getInfo(); } catch (const AssertionException& e) { - LastError::get(c).setLastError(e.getCode(), e.getInfo().msg); + setLastError(e.getCode(), e.getInfo().msg.c_str()); MONGO_LOG_COMPONENT(3, responseComponent) << " Caught Assertion in " << opToString(op) << ", continuing " << e.toString() << endl; @@ -605,7 +604,6 @@ namespace { } void receivedKillCursors(OperationContext* txn, Message& m) { - LastError::get(txn->getClient()).disable(); DbMessage dbmessage(m); int n = dbmessage.pullInt(); @@ -702,8 +700,7 @@ namespace { UpdateResult res = UpdateStage::makeUpdateResult(exec.get(), &op.debug()); // for getlasterror - LastError::get(txn->getClient()).recordUpdate( - res.existing, res.numMatched, res.upserted); + lastError.getSafe()->recordUpdate( res.existing , res.numMatched , res.upserted ); return; } break; @@ -756,8 +753,7 @@ namespace { uassertStatusOK(exec->executePlan()); UpdateResult res = UpdateStage::makeUpdateResult(exec.get(), &op.debug()); - LastError::get(txn->getClient()).recordUpdate( - res.existing, res.numMatched, res.upserted); + lastError.getSafe()->recordUpdate( res.existing , res.numMatched , res.upserted ); } MONGO_WRITE_CONFLICT_RETRY_LOOP_END(txn, "update", nsString.ns()); } @@ -815,7 +811,7 @@ namespace { // Run the plan and get the number of docs deleted. uassertStatusOK(exec->executePlan()); long long n = DeleteStage::getNumDeleted(exec.get()); - LastError::get(txn->getClient()).recordDelete(n); + lastError.getSafe()->recordDelete(n); op.debug().ndeleted = n; break; @@ -1005,7 +1001,7 @@ namespace { globalOpCounters.incInsertInWriteLock(i); throw; } - LastError::get(txn->getClient()).setLastError(ex.getCode(), ex.getInfo().msg); + setLastError(ex.getCode(), ex.getInfo().msg.c_str()); // otherwise ignore and keep going } } @@ -1059,7 +1055,7 @@ namespace { convertSystemIndexInsertsToCommands(d, &allCmdsBuilder); } catch (const DBException& ex) { - LastError::get(txn->getClient()).setLastError(ex.getCode(), ex.getInfo().msg); + setLastError(ex.getCode(), ex.getInfo().msg.c_str()); curOp.debug().exceptionInfo = ex.getInfo(); return; } @@ -1081,7 +1077,7 @@ namespace { uassertStatusOK(Command::getStatusFromCommandResult(resultBuilder.done())); } catch (const DBException& ex) { - LastError::get(txn->getClient()).setLastError(ex.getCode(), ex.getInfo().msg); + setLastError(ex.getCode(), ex.getInfo().msg.c_str()); curOp.debug().exceptionInfo = ex.getInfo(); if (!keepGoing) { return; diff --git a/src/mongo/db/lasterror.cpp b/src/mongo/db/lasterror.cpp index d242cdedc1a..d0a22d56b51 100644 --- a/src/mongo/db/lasterror.cpp +++ b/src/mongo/db/lasterror.cpp @@ -27,91 +27,139 @@ * 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/assert_util.h" +#include "mongo/util/debug_util.h" +#include "mongo/util/log.h" +#include "mongo/util/net/message.h" namespace mongo { - LastError LastError::noError; - - const Client::Decoration<LastError> LastError::get = Client::declareDecoration<LastError>(); - - void LastError::reset(bool valid) { - *this = LastError(); - _valid = valid; - } + using std::endl; - void LastError::setLastError(int code, std::string msg) { - if (_disabled) { - return; + 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); } - reset(true); - _code = code; - _msg = std::move(msg); - } - - void LastError::recordInsert(long long nObjects) { - reset(true); - _nObjects = nObjects; - } - - 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; - } - - void LastError::recordDelete(long long nDeleted) { - reset(true); - _nObjects = nDeleted; } - bool LastError::appendSelf(BSONObjBuilder &b , bool blankErr) const { + bool LastError::appendSelf( BSONObjBuilder &b , bool blankErr ) { - if (!_valid) { - if (blankErr) + if ( !valid ) { + if ( blankErr ) b.appendNull( "err" ); b.append( "n", 0 ); return false; } - if (_msg.empty()) { - if (blankErr) { + if ( msg.empty() ) { + if ( blankErr ) { b.appendNull( "err" ); } } else { - b.append("err", _msg); + b.append( "err", msg ); } - if (_code) - b.append("code" , _code); - if (_updatedExisting != NotUpdate) - b.appendBool("updatedExisting", _updatedExisting == True); - if (!_upsertedId.isEmpty()) { - b.append(_upsertedId[kUpsertedFieldName]); + 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); + b.appendNumber( "n", nObjects ); + + return ! msg.empty(); + } - return !_msg.empty(); + LastErrorHolder::~LastErrorHolder() { } - void LastError::disable() { - invariant(!_disabled); - _disabled = true; - _nPrev--; // caller is a command that shouldn't count as an operation + 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; + } + + LastError * LastErrorHolder::get( bool create ) { + LastError *ret = _get( create ); + if ( ret && !ret->disabled ) + return ret; + return 0; + } + + LastError * LastErrorHolder::getSafe() { + LastError * le = get(false); + if ( ! le ) { + error() << " no LastError!" << std::endl; + verify( le ); + } + return le; + } + + LastError * LastErrorHolder::_get( bool create ) { + LastError * le = _tl.get(); + if ( ! le && create ) { + le = new LastError(); + _tl.reset( le ); + } + return le; + } + + void LastErrorHolder::release() { + _tl.release(); + } + + /** ok to call more than once. */ + void LastErrorHolder::initThread() { + if( ! _tl.get() ) + _tl.reset( new LastError() ); + } + + 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::startRequest() { - _disabled = false; - ++_nPrev; + LastError * LastErrorHolder::startRequest( Message& m , LastError * le ) { + verify( le ); + prepareErrForNewRequest( m, le ); + return le; } } // namespace mongo diff --git a/src/mongo/db/lasterror.h b/src/mongo/db/lasterror.h index 55a04c8334d..5b04b69a57a 100644 --- a/src/mongo/db/lasterror.h +++ b/src/mongo/db/lasterror.h @@ -29,13 +29,16 @@ #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"; @@ -43,80 +46,107 @@ namespace mongo { static const char kGLEStatsLastOpTimeTermFieldName[] = "lastOpTimeTerm"; static const char kGLEStatsElectionIdFieldName[] = "electionId"; - class LastError { - public: - static const Client::Decoration<LastError> get; + 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(); + } /** - * Resets the object to a newly constructed state. If "valid" is true, marks the last-error - * object as "valid". + * @return if there is an err */ - void reset(bool valid = false); + 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; + } + } - /** - * when db receives a message/request, call this - */ - void startRequest(); + ~Disabled() { + if ( _le ) + _le->disabled = _prev; + } - /** - * Disables error recording for the current operation. - */ - void disable(); + LastError * _le; + bool _prev; + }; - /** - * 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); + static LastError noError; + }; - void recordInsert(long long nObjects); + extern class LastErrorHolder { + public: + LastErrorHolder(){} + ~LastErrorHolder(); - void recordUpdate(bool updateObjects, long long nObjects, BSONObj upsertedId); + LastError * get( bool create = false ); + LastError * getSafe(); + LastError * _get( bool create = false ); // may return a disabled LastError - void recordDelete(long long nDeleted); + void reset( LastError * le ); - /** - * 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; + /** ok to call more than once. */ + void initThread(); - bool isValid() const { return _valid; } - int const getNPrev() const { return _nPrev; } + void release(); - class Disabled { - public: - explicit Disabled(LastError* le) : _le(le), _prev(le->_disabled) { - _le->_disabled = true; - } + /** when db receives a message/request, call this */ + LastError * startRequest( Message& m , LastError * connectionOwned ); - ~Disabled() { - _le->_disabled = _prev; - } + // 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; - private: - LastError * const _le; - const bool _prev; + struct Status { + time_t time; + LastError *lerr; }; + } lastError; - 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; - }; + void setLastError(int code , const char *msg); } // namespace mongo diff --git a/src/mongo/db/ops/update_result.cpp b/src/mongo/db/ops/update_result.cpp index 64b33243131..f5e31c1a3d8 100644 --- a/src/mongo/db/ops/update_result.cpp +++ b/src/mongo/db/ops/update_result.cpp @@ -34,7 +34,6 @@ #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 a5303072fbd..f4cd02426a2 100644 --- a/src/mongo/db/repl/replication_info.cpp +++ b/src/mongo/db/repl/replication_info.cpp @@ -37,7 +37,6 @@ #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" @@ -217,7 +216,7 @@ namespace repl { authenticated. */ if ( cmdObj["forShell"].trueValue() ) - LastError::get(txn->getClient()).disable(); + lastError.disableForCommand(); appendReplicationInfo(txn, result, 0); diff --git a/src/mongo/db/repl/replset_commands.cpp b/src/mongo/db/repl/replset_commands.cpp index e4cc257dcb4..d160351c6b0 100644 --- a/src/mongo/db/repl/replset_commands.cpp +++ b/src/mongo/db/repl/replset_commands.cpp @@ -41,7 +41,6 @@ #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" @@ -151,7 +150,7 @@ namespace repl { string& errmsg, BSONObjBuilder& result) { if ( cmdObj["forShell"].trueValue() ) - LastError::get(txn->getClient()).disable(); + lastError.disableForCommand(); Status status = getGlobalReplicationCoordinator()->checkReplEnabledForCommand(&result); if (!status.isOK()) diff --git a/src/mongo/dbtests/directclienttests.cpp b/src/mongo/dbtests/directclienttests.cpp index fc076a9f926..822db3b58f4 100644 --- a/src/mongo/dbtests/directclienttests.cpp +++ b/src/mongo/dbtests/directclienttests.cpp @@ -33,7 +33,6 @@ #include <iostream> -#include "mongo/db/client.h" #include "mongo/db/db.h" #include "mongo/db/dbdirectclient.h" #include "mongo/db/json.h" @@ -50,11 +49,15 @@ namespace DirectClientTests { class ClientBase { public: ClientBase() { - mongo::LastError::get(cc()).reset(); + _prevError = mongo::lastError._get( false ); + mongo::lastError.release(); + mongo::lastError.reset( new LastError() ); } virtual ~ClientBase() { - mongo::LastError::get(cc()).reset(); + mongo::lastError.reset( _prevError ); } + private: + LastError* _prevError; }; const char *ns = "a.b"; diff --git a/src/mongo/dbtests/perftests.cpp b/src/mongo/dbtests/perftests.cpp index 310ae31e3a1..90c0d74c632 100644 --- a/src/mongo/dbtests/perftests.cpp +++ b/src/mongo/dbtests/perftests.cpp @@ -49,7 +49,6 @@ #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" @@ -92,10 +91,12 @@ namespace PerfTests { class ClientBase { public: ClientBase() : _client(&_txn) { - mongo::LastError::get(_txn.getClient()).reset(); + _prevError = mongo::lastError._get( false ); + mongo::lastError.release(); + mongo::lastError.reset( new LastError() ); } virtual ~ClientBase() { - mongo::LastError::get(_txn.getClient()).reset(); + mongo::lastError.reset( _prevError ); } protected: @@ -113,6 +114,7 @@ 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 5aac0a989e5..bab0f1e22fe 100644 --- a/src/mongo/dbtests/querytests.cpp +++ b/src/mongo/dbtests/querytests.cpp @@ -216,11 +216,13 @@ namespace QueryTests { class ClientBase { public: ClientBase() : _client(&_txn) { - mongo::LastError::get(_txn.getClient()).reset(); + _prevError = mongo::lastError._get( false ); + mongo::lastError.release(); + mongo::lastError.reset( new LastError() ); _txn.getCurOp()->reset(); } virtual ~ClientBase() { - mongo::LastError::get(_txn.getClient()).reset(); + mongo::lastError.reset( _prevError ); } protected: @@ -236,6 +238,9 @@ 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 fa7271bcb6b..4d2f527c54a 100644 --- a/src/mongo/dbtests/updatetests.cpp +++ b/src/mongo/dbtests/updatetests.cpp @@ -54,10 +54,12 @@ namespace UpdateTests { class ClientBase { public: ClientBase() : _client(&_txn) { - mongo::LastError::get(_txn.getClient()).reset(); + _prevError = mongo::lastError._get( false ); + mongo::lastError.release(); + mongo::lastError.reset( new LastError() ); } virtual ~ClientBase() { - mongo::LastError::get(_txn.getClient()).reset(); + mongo::lastError.reset( _prevError ); } protected: @@ -73,6 +75,9 @@ 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 a95ef130618..74bd0e54fc7 100644 --- a/src/mongo/s/SConscript +++ b/src/mongo/s/SConscript @@ -174,9 +174,8 @@ env.Library( ], LIBDEPS=[ '$BUILD_DIR/mongo/bson', - '$BUILD_DIR/mongo/db/common', # for Message - '$BUILD_DIR/mongo/lasterror', 'cluster_ops', + '$BUILD_DIR/mongo/db/common', # for Message ], ) diff --git a/src/mongo/s/chunk.cpp b/src/mongo/s/chunk.cpp index 8fe331f9c26..b62a0da7512 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(cc())); + LastError::Disabled d( lastError.get() ); try { _dataWritten += dataWritten; diff --git a/src/mongo/s/client/shard_connection.cpp b/src/mongo/s/client/shard_connection.cpp index 6f059b485fa..abce4b04db2 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(cc())); + LastError::Disabled ignoreForGLE(lastError.get(false)); // 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 a703d705b6d..2ee08b3aab9 100644 --- a/src/mongo/s/commands/cluster_get_last_error_cmd.cpp +++ b/src/mongo/s/commands/cluster_get_last_error_cmd.cpp @@ -88,13 +88,12 @@ namespace { // about 2.4 behavior? // - LastError *le = &LastError::get(cc()); - le->disable(); - + LastError *le = lastError.disableForCommand(); + invariant(le); // Write commands always have the error stored in the mongos last error bool errorOccurred = false; - if (le->getNPrev() == 1) { + if (le->nPrev == 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 0164fe3cc15..bacb5da705e 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::get(cc()).disable(); + lastError.disableForCommand(); 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 8bc2af039f3..182daedaa66 100644 --- a/src/mongo/s/commands/cluster_reset_error_cmd.cpp +++ b/src/mongo/s/commands/cluster_reset_error_cmd.cpp @@ -66,7 +66,10 @@ namespace { std::string& errmsg, BSONObjBuilder& result) { - LastError::get(cc()).reset(); + LastError* le = lastError.get(); + if (le) { + le->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 83a039a3f3b..925a944eb4d 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()) { - LastError::get(client).setLastError(status.code(), status.reason()); + setLastError(status.code(), status.reason().c_str()); } return status; @@ -149,7 +149,8 @@ namespace { ClusterWriter writer(true, 0); - LastError* cmdLastError = &LastError::get(cc()); + // NOTE: Sometimes this command is invoked with LE disabled for legacy writes + LastError* cmdLastError = lastError.get(false); { // Disable the last error object for the duration of the write @@ -173,9 +174,11 @@ namespace { dassert(response.isValid(NULL)); } - // Populate the lastError object based on the write response - cmdLastError->reset(); - batchErrorToLastError(request, response, cmdLastError); + if (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 43600e9eca8..e8dd8e60d44 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(cc())); + LastError::Disabled ignoreForGLE(lastError.get(false)); try{ return getChunkManager( ns, shouldReload, forceReload ); diff --git a/src/mongo/s/cursors.cpp b/src/mongo/s/cursors.cpp index e7e623eeed9..dd339627668 100644 --- a/src/mongo/s/cursors.cpp +++ b/src/mongo/s/cursors.cpp @@ -46,7 +46,6 @@ #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" @@ -368,7 +367,6 @@ 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 de29c5908e5..09197770db1 100644 --- a/src/mongo/s/d_state.cpp +++ b/src/mongo/s/d_state.cpp @@ -48,7 +48,6 @@ #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" @@ -1029,7 +1028,7 @@ namespace mongo { // step 1 - LastError::get(txn->getClient()).disable(); + lastError.disableForCommand(); 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 5c231d507c9..8c8b40dc608 100644 --- a/src/mongo/s/request.cpp +++ b/src/mongo/s/request.cpp @@ -37,7 +37,6 @@ #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" @@ -68,7 +67,6 @@ 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 4c51e534d7d..f2f21915b5b 100644 --- a/src/mongo/s/server.cpp +++ b/src/mongo/s/server.cpp @@ -141,10 +141,13 @@ namespace mongo { Client::initThread("conn", getGlobalServiceContext(), p); } - virtual void process(Message& m, AbstractMessagingPort* p) { + virtual void process( Message& m , AbstractMessagingPort* p , LastError * le) { verify( p ); Request r( m , p ); + verify( le ); + lastError.startRequest( m , le ); + try { r.init(); r.process(); @@ -161,7 +164,7 @@ namespace mongo { } // We *always* populate the last error for now - LastError::get(cc()).setLastError(ex.getCode(), ex.what()); + le->raiseError( ex.getCode() , ex.what() ); } catch ( const DBException& ex ) { @@ -175,7 +178,7 @@ namespace mongo { } // We *always* populate the last error for now - LastError::get(cc()).setLastError(ex.getCode(), ex.what()); + le->raiseError( 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 887595836ee..acffa2e79e1 100644 --- a/src/mongo/s/strategy.cpp +++ b/src/mongo/s/strategy.cpp @@ -653,7 +653,7 @@ namespace mongo { void Strategy::writeOp( int op , Request& r ) { // make sure we have a last error - dassert(&LastError::get(cc())); + dassert( lastError.get( false /* don't create */) ); OwnedPointerVector<BatchedCommandRequest> requestsOwned; vector<BatchedCommandRequest*>& requests = requestsOwned.mutableVector(); @@ -665,7 +665,7 @@ namespace mongo { // Multiple commands registered to last error as multiple requests if ( it != requests.begin() ) - LastError::get(cc()).startRequest(); + lastError.startRequest( r.m(), lastError.get( false ) ); BatchedCommandRequest* request = *it; @@ -680,7 +680,7 @@ namespace mongo { { // Disable the last error object for the duration of the write cmd - LastError::Disabled disableLastError(&LastError::get(cc())); + LastError::Disabled disableLastError( lastError.get( false ) ); Command::runAgainstRegistered( cmdNS.c_str(), requestBSON, builder, 0 ); } @@ -690,8 +690,8 @@ namespace mongo { dassert( parsed && response.isValid( NULL ) ); // Populate the lastError object based on the write response - LastError::get(cc()).reset(); - bool hadError = batchErrorToLastError(*request, response, &LastError::get(cc())); + lastError.get( false )->reset(); + bool hadError = batchErrorToLastError( *request, response, lastError.get( false ) ); // 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 e81d35ea9db..3df74fd614f 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->setLastError(lastBatchError->getErrCode(), - errMsg.empty() ? "see code for details" : errMsg.c_str()); + error->raiseError( 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 c802411c9e5..12c60982da1 100644 --- a/src/mongo/s/write_ops/batch_upconvert_test.cpp +++ b/src/mongo/s/write_ops/batch_upconvert_test.cpp @@ -25,7 +25,6 @@ * 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 ceafa7375b5..8abfcecbc9f 100644 --- a/src/mongo/shell/dbshell.cpp +++ b/src/mongo/shell/dbshell.cpp @@ -424,6 +424,10 @@ 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 ); @@ -584,6 +588,7 @@ 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 7bb9759eeff..66bdec58ad7 100644 --- a/src/mongo/util/net/message_server.h +++ b/src/mongo/util/net/message_server.h @@ -38,6 +38,8 @@ namespace mongo { + struct LastError; + class MessageHandler { public: virtual ~MessageHandler() {} @@ -51,7 +53,7 @@ namespace mongo { * called every time a message comes in * handler is responsible for responding to client */ - virtual void process(Message& m, AbstractMessagingPort* p) = 0; + virtual void process( Message& m , AbstractMessagingPort* p , LastError * err ) = 0; }; class MessageServer { diff --git a/src/mongo/util/net/message_server_port.cpp b/src/mongo/util/net/message_server_port.cpp index 682a7361ede..8db034fbe6e 100644 --- a/src/mongo/util/net/message_server_port.cpp +++ b/src/mongo/util/net/message_server_port.cpp @@ -207,6 +207,9 @@ 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() ) { @@ -224,7 +227,7 @@ namespace { break; } - handler->process(m, portWithHandler.get()); + handler->process(m, portWithHandler.get(), le); networkCounter.hit(portWithHandler->psock->getBytesIn(), portWithHandler->psock->getBytesOut()); |