diff options
author | Dwight <dmerriman@gmail.com> | 2008-09-11 13:04:30 -0400 |
---|---|---|
committer | Dwight <dmerriman@gmail.com> | 2008-09-11 13:04:30 -0400 |
commit | 2b67b580854063516ed3892a52287239cc1bd706 (patch) | |
tree | 31b8c35db87a78854d231764591a522793765f62 | |
parent | 1d4379a5d203135ba457f5a992c3aa261d8876ad (diff) | |
download | mongo-2b67b580854063516ed3892a52287239cc1bd706.tar.gz |
Option_SlaveOk
-rw-r--r-- | db/dbclient.cpp | 13 | ||||
-rw-r--r-- | db/dbclient.h | 50 | ||||
-rw-r--r-- | db/query.cpp | 2 | ||||
-rw-r--r-- | db/repl.cpp | 9 | ||||
-rw-r--r-- | db/replset.h | 5 | ||||
-rw-r--r-- | stdafx.cpp | 1 |
6 files changed, 53 insertions, 27 deletions
diff --git a/db/dbclient.cpp b/db/dbclient.cpp index 8365ae759ac..ee0856a1a59 100644 --- a/db/dbclient.cpp +++ b/db/dbclient.cpp @@ -23,9 +23,11 @@ #include "jsobj.h" #include "query.h" -JSObj DBClientConnection::findOne(const char *ns, JSObj query, JSObj *fieldsToReturn) { +JSObj DBClientConnection::findOne(const char *ns, JSObj query, JSObj *fieldsToReturn, int queryOptions) { auto_ptr<DBClientCursor> c = - this->query(ns, query, 1, 0, fieldsToReturn); + this->query(ns, query, 1, 0, fieldsToReturn, queryOptions); + + massert( "DBClientConnection::findOne: transport error", c.get() ); if( !c->more() ) return JSObj(); @@ -63,10 +65,11 @@ bool DBClientConnection::connect(const char *serverAddress, string& errmsg) { return true;
}
-auto_ptr<DBClientCursor> DBClientConnection::query(const char *ns, JSObj query, int nToReturn, int nToSkip, JSObj *fieldsToReturn, bool tailable) {
+auto_ptr<DBClientCursor> DBClientConnection::query(const char *ns, JSObj query, int nToReturn, int nToSkip, JSObj *fieldsToReturn, int queryOptions) {
// see query.h for the protocol we are using here.
BufBuilder b;
- int opts = tailable ? Option_CursorTailable : 0;
+ int opts = queryOptions;
+ assert( (opts&Option_ALLMASK) == opts );
b.append(opts);
b.append(ns);
b.append(nToSkip);
@@ -159,7 +162,7 @@ void testClient() { assert( c.connect("127.0.0.1", err) );
cout << "query foo.bar..." << endl;
auto_ptr<DBClientCursor> cursor =
- c.query("foo.bar", emptyObj, 0, 0, 0, true);
+ c.query("foo.bar", emptyObj, 0, 0, 0, Option_CursorTailable);
DBClientCursor *cc = cursor.get();
while( 1 ) {
bool m = cc->more();
diff --git a/db/dbclient.h b/db/dbclient.h index e9eeb1c2e6e..d02dabc4d2b 100644 --- a/db/dbclient.h +++ b/db/dbclient.h @@ -22,7 +22,7 @@ /* the query field 'options' can have these bits set: */ enum { - /* Tailable means cursor is not closed when the last data is retrieved. rather, the cursor makrs + /* Tailable means cursor is not closed when the last data is retrieved. rather, the cursor marks the final object's position. you can resume using the cursor later, from where it was located, if more data were received. Set on dbQuery and dbGetMore. @@ -30,7 +30,13 @@ enum { final object it references were deleted. Thus, you should be prepared to requery if you get back ResultFlag_CursorNotFound. */ - Option_CursorTailable = 2 + Option_CursorTailable = 2, + + /* allow query of replica slave. normally these return an error except for namespace "local". + */ + Option_SlaveOk = 4, + + Option_ALLMASK = 6 }; class JSObj;
@@ -66,7 +72,19 @@ public: } bool more(); // if true, safe to call next() - JSObj next(); // returns next object in the result cursor + + /* returns next object in the result cursor. + on an error at the remote server, you will get back: + { $err: <string> } + if you do not want to handle that yourself, call nextSafe(). + */ + JSObj next(); + + JSObj nextSafe() { + JSObj o = next(); + Element e = o.firstElement(); + assert( strcmp(e.fieldName(), "$err") != 0 ); + } // cursor no longer valid -- use with tailable cursors. // note you should only rely on this once more() returns false; @@ -85,22 +103,22 @@ public: bool connect(const char *serverHostname, string& errmsg); /* send a query to the database. - ns: namespace to query, format is <dbname>.<collectname>[.<collectname>]* - query: query to perform on the collection. this is a JSObj (binary JSON) - You may format as - { query: { ... }, order: { ... } } - to specify a sort order. - nToReturn: n to return. 0 = unlimited - nToSkip: start with the nth item + ns: namespace to query, format is <dbname>.<collectname>[.<collectname>]* + query: query to perform on the collection. this is a JSObj (binary JSON) + You may format as + { query: { ... }, order: { ... } } + to specify a sort order. + nToReturn: n to return. 0 = unlimited + nToSkip: start with the nth item fieldsToReturn: - optional template of which fields to select. if unspecified, returns all fields - tailable: see query.h tailable comments + optional template of which fields to select. if unspecified, returns all fields + queryOptions: see options enum at top of this file - returns: cursor. - returns 0 if error + returns: cursor. + 0 if error (connection failure) */ auto_ptr<DBClientCursor> query(const char *ns, JSObj query, int nToReturn = 0, int nToSkip = 0, - JSObj *fieldsToReturn = 0, bool tailable = false); + JSObj *fieldsToReturn = 0, int queryOptions = 0); - JSObj findOne(const char *ns, JSObj query, JSObj *fieldsToReturn = 0); + JSObj findOne(const char *ns, JSObj query, JSObj *fieldsToReturn = 0, int queryOptions = 0); }; diff --git a/db/query.cpp b/db/query.cpp index 9dbd58d7882..0430f631084 100644 --- a/db/query.cpp +++ b/db/query.cpp @@ -535,7 +535,7 @@ QueryResult* runQuery(Message& message, const char *ns, int ntoskip, int _ntoret } else { - uassert("not master", isMaster()); + uassert("not master", isMaster() || (queryOptions & Option_SlaveOk)); JSObj query = jsobj.getObjectField("query"); JSObj order = jsobj.getObjectField("orderby"); diff --git a/db/repl.cpp b/db/repl.cpp index 32cbb1ff790..9be567a1426 100644 --- a/db/repl.cpp +++ b/db/repl.cpp @@ -443,7 +443,7 @@ void ReplSource::sync_pullOpLog() { query.append("ts", q.done()); // query = { ts: { $gte: syncedTo } } - cursor = conn->query( ns.c_str(), query.done(), 0, 0, 0, true ); + cursor = conn->query( ns.c_str(), query.done(), 0, 0, 0, Option_CursorTailable ); c = cursor.get(); tailing = false; } @@ -469,7 +469,7 @@ void ReplSource::sync_pullOpLog() { if( !c->more() ) { if( tailing ) - log() << "pull: " << ns << " no new activity\n"; + ; //log() << "pull: " << ns << " no new activity\n"; else log() << "pull: " << ns << " oplog is empty\n"; sleepsecs(3); @@ -479,7 +479,10 @@ void ReplSource::sync_pullOpLog() { int n = 0; JSObj op = c->next(); Element ts = op.findElement("ts"); - assert( ts.type() == Date ); + if( ts.type() != Date ) { + problem() << "pull: bad object read from remote oplog: " << op.toString() << '\n'; + assert(false); + } OpTime t( ts.date() ); bool initial = syncedTo.isNull(); if( initial || tailing ) { diff --git a/db/replset.h b/db/replset.h index 2999431e86c..98216d7530b 100644 --- a/db/replset.h +++ b/db/replset.h @@ -59,7 +59,10 @@ public: extern ReplPair *replPair; /* we should not allow most operations when not the master */ -inline bool isMaster() { return replPair == 0 || replPair->state == 1; } +inline bool isMaster() { + return replPair == 0 || replPair->state == 1 || + client->name == "local"; // local is always allowed +} inline ReplPair::ReplPair(const char *remoteEnd) { state = -1; diff --git a/stdafx.cpp b/stdafx.cpp index b050390966f..5fb9dcded68 100644 --- a/stdafx.cpp +++ b/stdafx.cpp @@ -57,4 +57,3 @@ void msgasserted(const char *msg) { cout << "Assertion: " << msg << '\n'; throw AssertionException(); } - |