summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorAndy Schwerin <schwerin@mongodb.com>2015-04-23 17:50:55 -0400
committerAndy Schwerin <schwerin@mongodb.com>2015-04-23 18:02:53 -0400
commitab8295bf7cc572a391e8c364b5291f1d9b3b0720 (patch)
tree440f00fab6ef56747c46bdc995fc41a07aa45845 /src/mongo/db
parent1f24d43e419b674bfe866bdebf8224d44fa163b0 (diff)
downloadmongo-ab8295bf7cc572a391e8c364b5291f1d9b3b0720.tar.gz
Revert "SERVER-18131 Clean up LastError."
This reverts commit 54c25da33ec7270295c8948f6a51376ec4fd278c and commit c952a9396a1843aa45d6afa3c6785dec607de112.
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/client.cpp1
-rw-r--r--src/mongo/db/client.h1
-rw-r--r--src/mongo/db/commands/find_and_modify.cpp1
-rw-r--r--src/mongo/db/commands/get_last_error.cpp22
-rw-r--r--src/mongo/db/commands/write_commands/batch_executor.cpp10
-rw-r--r--src/mongo/db/commands/write_commands/batch_executor.h5
-rw-r--r--src/mongo/db/commands/write_commands/write_commands.cpp4
-rw-r--r--src/mongo/db/db.cpp5
-rw-r--r--src/mongo/db/dbcommands_generic.cpp2
-rw-r--r--src/mongo/db/dbdirectclient.cpp9
-rw-r--r--src/mongo/db/instance.cpp20
-rw-r--r--src/mongo/db/lasterror.cpp156
-rw-r--r--src/mongo/db/lasterror.h150
-rw-r--r--src/mongo/db/ops/update_result.cpp1
-rw-r--r--src/mongo/db/repl/replication_info.cpp3
-rw-r--r--src/mongo/db/repl/replset_commands.cpp3
16 files changed, 235 insertions, 158 deletions
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())