diff --git a/db/db.cpp b/db/db.cpp index 7c3a8e44522..a327d8fbe45 100644 --- a/db/db.cpp +++ b/db/db.cpp @@ -253,22 +253,33 @@ void receivedQuery(DbResponse& dbresponse, /*AbstractMessagingPort& dbMsgPort, * try { msgdata = runQuery(m, ns, ntoskip, ntoreturn, query, fields, ss, m.data->dataAsInt()); } - catch( AssertionException ) { + catch( AssertionException e ) { ss << " exception "; - problem() << " Caught Assertion in runQuery ns:" << ns << endl; + problem() << " Caught Assertion in runQuery ns:" << ns << ' ' << e.toString() << '\n'; log() << " ntoskip:" << ntoskip << " ntoreturn:" << ntoreturn << '\n'; - log() << " query:" << query.toString() << '\n'; - msgdata = (QueryResult*) malloc(sizeof(QueryResult)); + log() << " query:" << query.toString() << endl; + + JSObjBuilder err; + err.append("$err", e.msg.empty() ? "assertion during query" : e.msg); + JSObj errObj = err.done(); + + BufBuilder b; + b.skip(sizeof(QueryResult)); + b.append((void*) errObj.objdata(), errObj.objsize()); + + msgdata = (QueryResult *) b.buf(); + b.decouple(); QueryResult *qr = msgdata; qr->_data[0] = 0; qr->_data[1] = 0; qr->_data[2] = 0; qr->_data[3] = 0; - qr->len = sizeof(QueryResult); + qr->len = b.len(); qr->setOperation(opReply); qr->cursorId = 0; qr->startingFrom = 0; - qr->nReturned = 0; + qr->nReturned = 1; + } Message *resp = new Message(); resp->setData(msgdata, true); // transport will free diff --git a/db/query.cpp b/db/query.cpp index 7f5a575dc3c..9dbd58d7882 100644 --- a/db/query.cpp +++ b/db/query.cpp @@ -28,6 +28,7 @@ #include "javajs.h" #include "json.h" #include "repl.h" +#include "replset.h" #include "scanandorder.h" /* We cut off further objects once we cross this threshold; thus, you might get @@ -418,8 +419,9 @@ bool runCommands(const char *ns, JSObj& jsobj, stringstream& ss, BufBuilder &b, try { return _runCommands(ns, jsobj, ss, b, anObjBuilder); } - catch( AssertionException ) { - ; + catch( AssertionException e ) { + if( !e.msg.empty() ) + anObjBuilder.append("assertion", e.msg); } ss << " assertion "; anObjBuilder.append("errmsg", "db assertion failure"); @@ -533,6 +535,8 @@ QueryResult* runQuery(Message& message, const char *ns, int ntoskip, int _ntoret } else { + uassert("not master", isMaster()); + JSObj query = jsobj.getObjectField("query"); JSObj order = jsobj.getObjectField("orderby"); if( query.isEmpty() && order.isEmpty() ) diff --git a/db/repl.cpp b/db/repl.cpp index 2c301f4735d..32cbb1ff790 100644 --- a/db/repl.cpp +++ b/db/repl.cpp @@ -35,7 +35,6 @@ #include "db.h" #include "commands.h" -extern int port; extern boost::mutex dbMutex; auto_ptr findTableScan(const char *ns, JSObj& order); bool userCreateNS(const char *ns, JSObj& j, string& err); diff --git a/db/replset.h b/db/replset.h index 9d3eb8dbe03..2999431e86c 100644 --- a/db/replset.h +++ b/db/replset.h @@ -16,6 +16,8 @@ #pragma once +extern int port; + /* ReplPair is a pair of db servers replicating to one another and cooperating. Only one member of the pair is active at a time; so this is a smart master/slave @@ -54,7 +56,12 @@ public: void negotiate(DBClientConnection *conn); }; -ReplPair::ReplPair(const char *remoteEnd) { +extern ReplPair *replPair; + +/* we should not allow most operations when not the master */ +inline bool isMaster() { return replPair == 0 || replPair->state == 1; } + +inline ReplPair::ReplPair(const char *remoteEnd) { state = -1; remote = remoteEnd; remotePort = DBPort; diff --git a/dbgrid/dbgrid.cpp b/dbgrid/dbgrid.cpp new file mode 100644 index 00000000000..03e6fbe80c2 --- /dev/null +++ b/dbgrid/dbgrid.cpp @@ -0,0 +1,63 @@ +// dbgrid.cpp + +/** +* Copyright (C) 2008 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 . +*/ + +#include "stdafx.h" +#include "../util/unittest.h" + +const char *curNs = ""; +Client *client = 0; + +/* this is a good place to set a breakpoint when debugging, as lots of warning things + (assert, wassert) call it. +*/ +void sayDbContext(const char *errmsg) { + if( errmsg ) + problem() << errmsg << endl; + printStackTrace(); +} + +#if !defined(_WIN32) + +#include + +void pipeSigHandler( int signal ) { + psignal( signal, "Signal Received : "); +} + +#else +void setupSignals() {} +#endif + +int main(int argc, char* argv[], char *envp[] ) { +#if !defined(_WIN32) + signal(SIGPIPE, pipeSigHandler); +#endif + + log() << "dbgrid starting" << endl; + + UnitTest::runTests(); + + dbexit(0); + return 0; +} + +#undef exit +void dbexit(int rc, const char *why) { + log() << "dbexit: " << why << " rc:" << rc << endl; + exit(rc); +} diff --git a/stdafx.h b/stdafx.h index 00ace4a66dc..51e5c8c003a 100644 --- a/stdafx.h +++ b/stdafx.h @@ -48,14 +48,15 @@ inline void * ourrealloc(void *ptr, size_t size) { #include "targetver.h" -//#include "assert.h" - +#include +using namespace std; // you can catch these class AssertionException { public: - const char *msg; - AssertionException() { msg = ""; } + string msg; + AssertionException() { } virtual bool isUserAssertion() { return false; } + virtual string toString() { return msg; } }; /* we use the same mechanism for bad things the user does -- which are really just errors */ @@ -63,6 +64,7 @@ class UserAssertionException : public AssertionException { public: UserAssertionException(const char *_msg) { msg = _msg; } virtual bool isUserAssertion() { return true; } + virtual string toString() { return "userassert:" + msg; } }; void asserted(const char *msg, const char *file, unsigned line); @@ -107,13 +109,11 @@ typedef char _TCHAR; #include #include -using namespace std; - #include "time.h" #include -#include #include #include +//using namespace std; #if !defined(_WIN32) typedef int HANDLE;