summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/dbclient.h4
-rw-r--r--db/commands.h6
-rw-r--r--jstests/sharding/group_slaveok.js62
-rw-r--r--s/commands_public.cpp26
-rw-r--r--s/strategy_single.cpp4
-rw-r--r--shell/mongo.js9
-rwxr-xr-xshell/servers.js22
-rw-r--r--util/goodies.h2
8 files changed, 115 insertions, 20 deletions
diff --git a/client/dbclient.h b/client/dbclient.h
index b27eab5c545..3f3b9441b6d 100644
--- a/client/dbclient.h
+++ b/client/dbclient.h
@@ -80,7 +80,9 @@ namespace mongo {
*/
QueryOption_PartialResults = 1 << 7 ,
- QueryOption_AllSupported = QueryOption_CursorTailable | QueryOption_SlaveOk | QueryOption_OplogReplay | QueryOption_NoCursorTimeout | QueryOption_AwaitData | QueryOption_Exhaust | QueryOption_PartialResults
+ QueryOption_NoOplog = 1 << 8 ,
+
+ QueryOption_AllSupported = QueryOption_CursorTailable | QueryOption_SlaveOk | QueryOption_OplogReplay | QueryOption_NoCursorTimeout | QueryOption_AwaitData | QueryOption_Exhaust | QueryOption_PartialResults | QueryOption_NoOplog
};
diff --git a/db/commands.h b/db/commands.h
index 454e2277e06..ff26d041817 100644
--- a/db/commands.h
+++ b/db/commands.h
@@ -20,6 +20,7 @@
#include "../pch.h"
#include "jsobj.h"
#include "../util/timer.h"
+#include "../client/dbclient.h"
namespace mongo {
@@ -46,6 +47,9 @@ namespace mongo {
return value is true if succeeded. if false, set errmsg text.
*/
virtual bool run(const string& db, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) = 0;
+ virtual bool run(const string& db, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, int options){
+ return run( db, cmdObj, errmsg, result, ( options & QueryOption_NoOplog ) > 0 );
+ }
/*
note: logTheTop() MUST be false if READ
@@ -120,7 +124,7 @@ namespace mongo {
static const map<string,Command*>* commandsByBestName() { return _commandsByBestName; }
static const map<string,Command*>* webCommands() { return _webCommands; }
/** @return if command was found and executed */
- static bool runAgainstRegistered(const char *ns, BSONObj& jsobj, BSONObjBuilder& anObjBuilder);
+ static bool runAgainstRegistered(const char *ns, BSONObj& jsobj, BSONObjBuilder& anObjBuilder, int queryOptions = 0);
static LockType locktype( const string& name );
static Command * findCommand( const string& name );
};
diff --git a/jstests/sharding/group_slaveok.js b/jstests/sharding/group_slaveok.js
new file mode 100644
index 00000000000..930ea095351
--- /dev/null
+++ b/jstests/sharding/group_slaveok.js
@@ -0,0 +1,62 @@
+// Tests group using slaveOk
+
+var st = new ShardingTest( testName = "groupSlaveOk",
+ numShards = 1,
+ verboseLevel = 0,
+ numMongos = 1,
+ { rs : true,
+ rs0 : { nodes : 2 }
+ })
+
+var rst = st._rs[0].test
+
+// Insert data into replica set
+var conn = new Mongo( st.s.host )
+conn.setLogLevel( 3 )
+
+var coll = conn.getCollection( "test.groupSlaveOk" )
+coll.drop()
+
+for( var i = 0; i < 300; i++ ){
+ coll.insert( { i : i % 10 } )
+}
+
+// Make sure the writes get through, otherwise we can continue to error these one-at-a-time
+coll.getDB().getLastError()
+
+st.printShardingStatus()
+
+// Wait for client to update itself and replication to finish
+rst.awaitReplication()
+
+// Data now inserted... stop the master, since only two in set, other will still be secondary
+rst.stop( rst.getMaster(), undefined, true )
+printjson( rst.status() )
+
+// Need to check slaveOk=true first, since slaveOk=false will destroy conn in pool when
+// master is down
+conn.setSlaveOk()
+
+// Should throw exception, since not slaveOk'd
+assert.eq( 10, coll.group({ key : { i : true } ,
+ reduce : function( obj, ctx ){ ctx.count += 1 } ,
+ initial : { count : 0 } }).length )
+
+try {
+
+ conn.setSlaveOk( false )
+ coll.group({ key : { i : true } ,
+ reduce : function( obj, ctx ){ ctx.count += 1 } ,
+ initial : { count : 0 } })
+
+ print( "Should not reach here!" )
+ printjson( coll.getDB().getLastError() )
+ assert( false )
+
+}
+catch( e ){
+ print( "Non-slaveOk'd connection failed." )
+}
+
+// Finish
+st.stop()
diff --git a/s/commands_public.cpp b/s/commands_public.cpp
index 713b9489fc2..890972b9ee6 100644
--- a/s/commands_public.cpp
+++ b/s/commands_public.cpp
@@ -57,18 +57,26 @@ namespace mongo {
virtual LockType locktype() const { return NONE; }
protected:
+
bool passthrough( DBConfigPtr conf, const BSONObj& cmdObj , BSONObjBuilder& result ) {
- return _passthrough(conf->getName(), conf, cmdObj, result);
+ return _passthrough(conf->getName(), conf, cmdObj, 0, result);
}
bool adminPassthrough( DBConfigPtr conf, const BSONObj& cmdObj , BSONObjBuilder& result ) {
- return _passthrough("admin", conf, cmdObj, result);
+ return _passthrough("admin", conf, cmdObj, 0, result);
+ }
+
+ bool passthrough( DBConfigPtr conf, const BSONObj& cmdObj , int options, BSONObjBuilder& result ) {
+ return _passthrough(conf->getName(), conf, cmdObj, options, result);
+ }
+ bool adminPassthrough( DBConfigPtr conf, const BSONObj& cmdObj , int options, BSONObjBuilder& result ) {
+ return _passthrough("admin", conf, cmdObj, options, result);
}
private:
- bool _passthrough(const string& db, DBConfigPtr conf, const BSONObj& cmdObj , BSONObjBuilder& result ) {
+ bool _passthrough(const string& db, DBConfigPtr conf, const BSONObj& cmdObj , int options , BSONObjBuilder& result ) {
ShardConnection conn( conf->getPrimary() , "" );
BSONObj res;
- bool ok = conn->runCommand( db , cmdObj , res );
+ bool ok = conn->runCommand( db , cmdObj , res , options );
if ( ! ok && res["code"].numberInt() == StaleConfigInContextCode ) {
conn.done();
throw StaleConfigException("foo","command failed because of stale config");
@@ -160,12 +168,16 @@ namespace mongo {
virtual string getFullNS( const string& dbName , const BSONObj& cmdObj ) = 0;
virtual bool run(const string& dbName , BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool) {
+ return run( dbName, cmdObj, errmsg, result, 0);
+ }
+
+ virtual bool run(const string& dbName , BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, int options) {
string fullns = getFullNS( dbName , cmdObj );
DBConfigPtr conf = grid.getDBConfig( dbName , false );
if ( ! conf || ! conf->isShardingEnabled() || ! conf->isSharded( fullns ) ) {
- return passthrough( conf , cmdObj , result );
+ return passthrough( conf , cmdObj , options, result );
}
errmsg = "can't do command: " + name + " on sharded collection";
return false;
@@ -1285,7 +1297,7 @@ namespace mongo {
}
- bool Command::runAgainstRegistered(const char *ns, BSONObj& jsobj, BSONObjBuilder& anObjBuilder) {
+ bool Command::runAgainstRegistered(const char *ns, BSONObj& jsobj, BSONObjBuilder& anObjBuilder, int queryOptions) {
const char *p = strchr(ns, '.');
if ( !p ) return false;
if ( strcmp(p, ".$cmd") != 0 ) return false;
@@ -1326,7 +1338,7 @@ namespace mongo {
anObjBuilder.append( "help" , help.str() );
}
else {
- ok = c->run( nsToDatabase( ns ) , jsobj, errmsg, anObjBuilder, false);
+ ok = c->run( nsToDatabase( ns ) , jsobj, errmsg, anObjBuilder, queryOptions);
}
BSONObj tmp = anObjBuilder.asTempObj();
diff --git a/s/strategy_single.cpp b/s/strategy_single.cpp
index b3eef9dafa4..fac21895a4c 100644
--- a/s/strategy_single.cpp
+++ b/s/strategy_single.cpp
@@ -36,7 +36,7 @@ namespace mongo {
virtual void queryOp( Request& r ) {
QueryMessage q( r.d() );
- log(3) << "single query: " << q.ns << " " << q.query << " ntoreturn: " << q.ntoreturn << endl;
+ log(3) << "single query: " << q.ns << " " << q.query << " ntoreturn: " << q.ntoreturn << " options : " << q.queryOptions << endl;
if ( r.isCommand() ) {
@@ -55,7 +55,7 @@ namespace mongo {
: str::equals("query", e.fieldName())))
cmdObj = e.embeddedObject();
}
- bool ok = Command::runAgainstRegistered(q.ns, cmdObj, builder);
+ bool ok = Command::runAgainstRegistered(q.ns, cmdObj, builder, q.queryOptions);
if ( ok ) {
BSONObj x = builder.done();
replyToQuery(0, r.p(), r.m(), x);
diff --git a/shell/mongo.js b/shell/mongo.js
index e129784bf66..25357691c51 100644
--- a/shell/mongo.js
+++ b/shell/mongo.js
@@ -24,8 +24,9 @@ if ( typeof mongoInject == "function" ){
mongoInject( Mongo.prototype );
}
-Mongo.prototype.setSlaveOk = function() {
- this.slaveOk = true;
+Mongo.prototype.setSlaveOk = function( value ) {
+ if( value == undefined ) value = true
+ this.slaveOk = value
}
Mongo.prototype.getDB = function( name ){
@@ -43,6 +44,10 @@ Mongo.prototype.adminCommand = function( cmd ){
return this.getDB( "admin" ).runCommand( cmd );
}
+Mongo.prototype.setLogLevel = function( logLevel ){
+ return this.adminCommand({ setParameter : 1, logLevel : logLevel })
+}
+
Mongo.prototype.getDBNames = function(){
return this.getDBs().databases.map(
function(z){
diff --git a/shell/servers.js b/shell/servers.js
index e8797ae1a5d..29d6f220ea1 100755
--- a/shell/servers.js
+++ b/shell/servers.js
@@ -170,8 +170,7 @@ ShardingTest = function( testName , numShards , verboseLevel , numMongos , other
var localhost = otherParams.useHostname ? getHostName() : "localhost";
this._alldbpaths = []
-
-
+
if ( otherParams.rs ){
localhost = getHostName();
// start replica sets
@@ -179,16 +178,18 @@ ShardingTest = function( testName , numShards , verboseLevel , numMongos , other
for ( var i=0; i<numShards; i++){
var setName = testName + "-rs" + i;
- var rsDefaults = { oplogSize : 40 }
+ var rsDefaults = { oplogSize : 40, nodes : 3 }
var rsParams = otherParams["rs" + i]
for( var param in rsParams ){
rsDefaults[param] = rsParams[param]
}
- var numReplicas = otherParams.numReplicas || 3
+ var numReplicas = rsDefaults.nodes || otherParams.numReplicas || 3
+ delete rsDefaults.nodes
+
var rs = new ReplSetTest( { name : setName , nodes : numReplicas , startPort : 31100 + ( i * 100 ) } );
- this._rs[i] = { setName : setName , test : rs , nodes : rs.startSet( rsParams ) , url : rs.getURL() };
+ this._rs[i] = { setName : setName , test : rs , nodes : rs.startSet( rsDefaults ) , url : rs.getURL() };
rs.initiate();
}
@@ -1297,6 +1298,7 @@ ReplSetTest.prototype.getMaster = function( timeout ) {
return master;
}
+ReplSetTest.prototype.getPrimary = ReplSetTest.prototype.getMaster
ReplSetTest.prototype.getSecondaries = function( timeout ){
var master = this.getMaster( timeout )
@@ -1309,6 +1311,12 @@ ReplSetTest.prototype.getSecondaries = function( timeout ){
return secs
}
+ReplSetTest.prototype.status = function( timeout ){
+ var master = this.callIsMaster()
+ if( ! master ) master = this.liveNodes.slaves[0]
+ return master.getDB("admin").runCommand({replSetGetStatus: 1})
+}
+
// Add a node to the test set
ReplSetTest.prototype.add = function( config ) {
if(this.ports.length == 0) {
@@ -1719,10 +1727,10 @@ ReplSetTest.prototype.waitForIndicator = function( node, states, ind, timeout ){
var lastTime = null
var currTime = new Date().getTime()
var status = undefined
-
+
this.attempt({context: this, timeout: timeout, desc: "waiting for state indicator " + ind + " for " + timeout + "ms" }, function() {
- status = this.getMaster().getDB("admin").runCommand({ replSetGetStatus : 1 })
+ status = this.status()
if( lastTime == null || ( currTime = new Date().getTime() ) - (1000 * 5) > lastTime ){
if( lastTime == null ) print( "ReplSetTest waitForIndicator Initial status ( timeout : " + timeout + " ) :" )
diff --git a/util/goodies.h b/util/goodies.h
index 51a80f6783c..65bfbaba982 100644
--- a/util/goodies.h
+++ b/util/goodies.h
@@ -109,6 +109,8 @@ namespace mongo {
// PRINTFL; prints file:line
#define MONGO_PRINTFL cout << __FILE__ ":" << __LINE__ << endl
#define PRINTFL MONGO_PRINTFL
+#define MONGO_FLOG log() << __FILE__ ":" << __LINE__ << endl
+#define FLOG MONGO_FLOG
#undef assert
#define assert MONGO_assert