summaryrefslogtreecommitdiff
path: root/db
diff options
context:
space:
mode:
authorDwight <dmerriman@gmail.com>2009-01-05 15:30:07 -0500
committerDwight <dmerriman@gmail.com>2009-01-05 15:30:07 -0500
commit2e35206b4781ee72378ddddc4c2f99a1c290ab58 (patch)
tree9fc17cd26512cc9680d13b11cd196369908cca97 /db
parentffc3bb2216da756a77c18065a52c3cc1bb694cd3 (diff)
downloadmongo-2e35206b4781ee72378ddddc4c2f99a1c290ab58.tar.gz
getlasterror
Diffstat (limited to 'db')
-rw-r--r--db/db.cpp6
-rw-r--r--db/db.vcproj8
-rw-r--r--db/dbcommands.cpp70
-rw-r--r--db/instance.cpp1
-rw-r--r--db/lasterror.cpp6
-rw-r--r--db/lasterror.h44
-rw-r--r--db/makefile4
7 files changed, 137 insertions, 2 deletions
diff --git a/db/db.cpp b/db/db.cpp
index 3e662b5c2cc..619e9a43069 100644
--- a/db/db.cpp
+++ b/db/db.cpp
@@ -136,11 +136,15 @@ public:
Message & container;
};
+#include "lasterror.h"
+
/* we create one thread for each connection from an app server database.
app server will open a pool of threads.
*/
void connThread()
{
+ LastError *le = new LastError();
+ lastError.reset(le);
try {
MessagingPort& dbMsgPort = *grab;
@@ -156,6 +160,8 @@ void connThread()
break;
}
+ le->nPrev++;
+
DbResponse dbresponse;
if ( !assembleResponse( m, dbresponse ) ) {
cout << curTimeMillis() % 10000 << " end msg " << dbMsgPort.farEnd.toString() << endl;
diff --git a/db/db.vcproj b/db/db.vcproj
index bfda85c5f79..bf1b32c5e33 100644
--- a/db/db.vcproj
+++ b/db/db.vcproj
@@ -328,6 +328,10 @@
>
</File>
<File
+ RelativePath=".\lasterror.cpp"
+ >
+ </File>
+ <File
RelativePath=".\matcher.cpp"
>
</File>
@@ -545,6 +549,10 @@
>
</File>
<File
+ RelativePath=".\lasterror.h"
+ >
+ </File>
+ <File
RelativePath="..\util\log.h"
>
</File>
diff --git a/db/dbcommands.cpp b/db/dbcommands.cpp
index 5d81ddb426d..37cf1d7b239 100644
--- a/db/dbcommands.cpp
+++ b/db/dbcommands.cpp
@@ -30,6 +30,7 @@
#include "commands.h"
#include "db.h"
#include "instance.h"
+#include "lasterror.h"
extern bool quiet;
extern int queryTraceLevel;
@@ -177,6 +178,75 @@ string validateNS(const char *ns, NamespaceDetails *d) {
return ss.str();
}
+/* reset any errors so that getlasterror comes back clean.
+
+ useful before performing a long series of operations where we want to
+ see if any of the operations triggered an error, but don't want to check
+ after each op as that woudl be a client/server turnaround.
+*/
+class CmdResetError : public Command {
+public:
+ virtual bool logTheOp() { return false; }
+ virtual bool slaveOk() { return true; }
+ CmdResetError() : Command("reseterror") {}
+ bool run(const char *ns, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ LastError *le = lastError.get();
+ assert( le );
+ le->resetError();
+ return true;
+ }
+} cmdResetError;
+
+class CmdGetLastError : public Command {
+public:
+ virtual bool logTheOp() { return false; }
+ virtual bool slaveOk() { return true; }
+ CmdGetLastError() : Command("getlasterror") {}
+ bool run(const char *ns, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ LastError *le = lastError.get();
+ assert( le );
+ le->nPrev--; // we don't count as an operation
+ if( le->nPrev != 1 || !le->haveError() ) {
+ result.appendNull("err");
+ return true;
+ }
+ result.append("err", le->msg);
+ return true;
+ }
+} cmdGetLastError;
+
+/* for testing purposes only */
+class CmdForceError : public Command {
+public:
+ virtual bool logTheOp() { return false; }
+ virtual bool slaveOk() { return true; }
+ CmdForceError() : Command("forceerror") {}
+ bool run(const char *ns, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ uassert("forced error", false);
+ return true;
+ }
+} cmdForceError;
+
+class CmdGetPrevError : public Command {
+public:
+ virtual bool logTheOp() { return false; }
+ virtual bool slaveOk() { return true; }
+ CmdGetPrevError() : Command("getpreverror") {}
+ bool run(const char *ns, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ LastError *le = lastError.get();
+ assert( le );
+ le->nPrev--; // we don't count as an operation
+ if( !le->haveError() ) {
+ result.appendNull("err");
+ result.append("nPrev", 1);
+ return true;
+ }
+ result.append("err", le->msg);
+ result.append("nPrev", le->nPrev);
+ return true;
+ }
+} cmdGetPrevError;
+
class CmdDropDatabase : public Command {
public:
virtual bool logTheOp() {
diff --git a/db/instance.cpp b/db/instance.cpp
index 6d1250b046c..2dcb0f4dbc8 100644
--- a/db/instance.cpp
+++ b/db/instance.cpp
@@ -24,6 +24,7 @@
#include "repl.h"
#include "dbmessage.h"
#include "instance.h"
+#include "lasterror.h"
int nloggedsome = 0;
#define LOGSOME if( ++nloggedsome < 1000 || nloggedsome % 100 == 0 )
diff --git a/db/lasterror.cpp b/db/lasterror.cpp
new file mode 100644
index 00000000000..a3f33cd5703
--- /dev/null
+++ b/db/lasterror.cpp
@@ -0,0 +1,6 @@
+// lasterror.cpp
+
+#include "stdafx.h"
+#include "lasterror.h"
+
+boost::thread_specific_ptr<LastError> lastError;
diff --git a/db/lasterror.h b/db/lasterror.h
new file mode 100644
index 00000000000..6030cb9e19b
--- /dev/null
+++ b/db/lasterror.h
@@ -0,0 +1,44 @@
+// lasterror.h
+
+/**
+* Copyright (C) 2009 10gen Inc.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License, version 3,
+* as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#include <boost/thread/tss.hpp>
+
+struct LastError {
+ string msg;
+ int nPrev;
+ void raiseError(const char *_msg) {
+ msg = _msg;
+ nPrev = 1;
+ }
+ bool haveError() const { return !msg.empty(); }
+ void resetError() { msg.clear(); }
+ LastError() { nPrev = 0; }
+};
+
+extern boost::thread_specific_ptr<LastError> lastError;
+
+inline void raiseError(const char *msg) {
+ LastError *le = lastError.get();
+ if( le == 0 ) {
+ DEV log() << "warning: lastError==0 can't report:" << msg << '\n';
+ return;
+ }
+ le->raiseError(msg);
+}
diff --git a/db/makefile b/db/makefile
index b819ddd3bc9..fdc05d8df2e 100644
--- a/db/makefile
+++ b/db/makefile
@@ -12,9 +12,9 @@ DBTEST_LIBS= $(LIBS) -lunittest
JVM_LIBS = -L/opt/java/lib/
-OBJS=../stdafx.o ../util/sock.o ../grid/message.o ../util/mmap.o pdfile.o query.o jsobj.o introspect.o btree.o clientcursor.o ../util/util.o javajs.o tests.o json.o repl.o ../client/dbclient.o btreecursor.o cloner.o namespace.o commands.o matcher.o dbcommands.o dbeval.o ../util/background.o ../util/miniwebserver.o dbwebserver.o dbinfo.o instance.o dbhelpers.o
+OBJS=../stdafx.o ../util/sock.o ../grid/message.o ../util/mmap.o pdfile.o query.o jsobj.o introspect.o btree.o clientcursor.o ../util/util.o javajs.o tests.o json.o repl.o ../client/dbclient.o btreecursor.o cloner.o namespace.o commands.o matcher.o dbcommands.o dbeval.o ../util/background.o ../util/miniwebserver.o dbwebserver.o dbinfo.o instance.o dbhelpers.o lasterror.o
-DBGRID_OBJS=../stdafx.o json.o ../util/sock.o ../grid/message.o ../util/util.o jsobj.o ../client/dbclient.o ../dbgrid/dbgrid.o ../dbgrid/request.o ../client/connpool.o ../dbgrid/gridconfig.o commands.o ../dbgrid/dbgrid_commands.o ../dbgrid/griddatabase.o ../client/model.o ../util/background.o ../dbgrid/shard.o
+DBGRID_OBJS=../stdafx.o json.o ../util/sock.o ../grid/message.o ../util/util.o jsobj.o ../client/dbclient.o ../dbgrid/dbgrid.o ../dbgrid/request.o ../client/connpool.o ../dbgrid/gridconfig.o commands.o ../dbgrid/dbgrid_commands.o ../dbgrid/griddatabase.o ../client/model.o ../util/background.o ../dbgrid/shard.o lasterror.o
DBTEST_OBJS= $(OBJS) ../dbtests/dbtests.o ../dbtests/btreetests.o ../dbtests/jsobjtests.o ../dbtests/namespacetests.o ../dbtests/pairingtests.o