summaryrefslogtreecommitdiff
path: root/src/mongo/shell
diff options
context:
space:
mode:
authorScott Hernandez <scotthernandez@gmail.com>2014-02-26 11:25:50 -0500
committerScott Hernandez <scotthernandez@gmail.com>2014-02-26 12:11:30 -0500
commita56653e1df978f68b887788b39d053e3f88bb0ea (patch)
tree4ba0d7d3114f6edc4a924a6ed40b42632bfe3736 /src/mongo/shell
parentf4c7d400c8f938374474a37cde54e36168e60b26 (diff)
downloadmongo-a56653e1df978f68b887788b39d053e3f88bb0ea.tar.gz
SERVER-12786: add shell writeMode option
Diffstat (limited to 'src/mongo/shell')
-rw-r--r--src/mongo/shell/assert.js10
-rw-r--r--src/mongo/shell/bulk_api.js3
-rw-r--r--src/mongo/shell/collection.js24
-rw-r--r--src/mongo/shell/mongo.js53
-rw-r--r--src/mongo/shell/shell_options.cpp18
-rw-r--r--src/mongo/shell/shell_options.h6
-rw-r--r--src/mongo/shell/shell_utils.cpp5
-rw-r--r--src/mongo/shell/utils.js9
8 files changed, 94 insertions, 34 deletions
diff --git a/src/mongo/shell/assert.js b/src/mongo/shell/assert.js
index 97bb780f883..ac483bc8bb5 100644
--- a/src/mongo/shell/assert.js
+++ b/src/mongo/shell/assert.js
@@ -347,7 +347,7 @@ assert.writeOK = function(res, msg) {
if (!res)
errMsg = "missing first argument, no response to check"
- if (!res.getWriteError)
+ else if (!res.getWriteError)
assert.gleOK(res, msg)
else {
if (res.getWriteError()) {
@@ -371,8 +371,7 @@ assert.gleOK = function(res, msg) {
if (!res)
errMsg = "missing first argument, no response to check"
-
- if (!res.ok)
+ else if (!res.ok)
errMsg = "command failed: " + tojson(res);
if ('code' in res || 'errMsg' in res || 'errInfo' in res || 'writeErrors' in res)
@@ -387,11 +386,12 @@ assert.gleOK = function(res, msg) {
return res;
}
-
assert.writeError = function(res, msg) {
var errMsg = "";
- if (!res.getWriteConcernError) {
+ if (!res)
+ errMsg = "The response arg was missing or undefined! -- " + res
+ else if (!res.getWriteConcernError) {
if (!res.err)
errMsg = "no error" + tojson(res);
} else {
diff --git a/src/mongo/shell/bulk_api.js b/src/mongo/shell/bulk_api.js
index 21c5ce1e232..6418633954e 100644
--- a/src/mongo/shell/bulk_api.js
+++ b/src/mongo/shell/bulk_api.js
@@ -913,7 +913,8 @@ var _bulk_api_module = (function() {
for(var i = 0; i < batches.length; i++) {
// Execute the batch
- if(useWriteCommands) {
+ if(collection.getMongo().hasWriteCommands() &&
+ collection.getMongo().writeMode() == "commands") {
executeBatch(batches[i]);
} else {
executeBatchWithLegacyOps(batches[i]);
diff --git a/src/mongo/shell/collection.js b/src/mongo/shell/collection.js
index 1023d8ce1ec..f57443ee85e 100644
--- a/src/mongo/shell/collection.js
+++ b/src/mongo/shell/collection.js
@@ -21,6 +21,7 @@ DBCollection.prototype.verify = function(){
assert.eq( this._fullName , this._db._name + "." + this._shortName , "name mismatch" );
assert( this._mongo , "no mongo in DBCollection" );
+ assert( this.getMongo() , "no mongo from getMongo()" );
}
DBCollection.prototype.getName = function(){
@@ -132,7 +133,7 @@ DBCollection.prototype._massageObject = function( q ){
DBCollection.prototype._validateObject = function( o ){
// Hidden property for testing purposes.
- if (this._mongo._skipValidation) return;
+ if (this.getMongo()._skipValidation) return;
if (typeof(o) != "object")
throw "attempted to save a " + typeof(o) + " value. document expected.";
@@ -145,7 +146,7 @@ DBCollection._allowedFields = { $id : 1 , $ref : 1 , $db : 1 };
DBCollection.prototype._validateForStorage = function( o ){
// Hidden property for testing purposes.
- if (this._mongo._skipValidation) return;
+ if (this.getMongo()._skipValidation) return;
this._validateObject( o );
for ( var k in o ){
@@ -225,7 +226,7 @@ DBCollection.prototype.insert = function( obj , options, _allow_dot ){
var startTime = (typeof(_verboseShell) === 'undefined' ||
!_verboseShell) ? 0 : new Date().getTime();
- if ( this._mongo.useWriteCommands() ) {
+ if ( this.getMongo().writeMode() != "legacy" ) {
// Bit 1 of option flag is continueOnError. Bit 0 (stop on error) is the default.
var batch = ordered ? this.initializeOrderedBulkOp() : this.initializeUnorderedBulkOp();
@@ -253,7 +254,7 @@ DBCollection.prototype.insert = function( obj , options, _allow_dot ){
}
}
- this._mongo.insert( this._fullName , obj, flags );
+ this.getMongo().insert( this._fullName , obj, flags );
// enforce write concern, if required
if (wc)
@@ -267,7 +268,7 @@ DBCollection.prototype.insert = function( obj , options, _allow_dot ){
DBCollection.prototype._validateRemoveDoc = function(doc) {
// Hidden property for testing purposes.
- if (this._mongo._skipValidation) return;
+ if (this.getMongo()._skipValidation) return;
for (var k in doc) {
if (k == "_id" && typeof( doc[k] ) == "undefined") {
@@ -292,7 +293,7 @@ DBCollection.prototype.remove = function( t , justOne ){
if (!wc)
wc = this.getWriteConcern();
- if ( this._mongo.useWriteCommands() ) {
+ if ( this.getMongo().writeMode() != "legacy" ) {
var query = (typeof(t) == 'undefined')? {} : this._massageObject(t);
var batch = this.initializeOrderedBulkOp();
var removeOp = batch.find(query);
@@ -308,7 +309,7 @@ DBCollection.prototype.remove = function( t , justOne ){
}
else {
this._validateRemoveDoc(t);
- this._mongo.remove(this._fullName, this._massageObject(t), justOne ? true : false );
+ this.getMongo().remove(this._fullName, this._massageObject(t), justOne ? true : false );
// enforce write concern, if required
if (wc)
@@ -322,7 +323,7 @@ DBCollection.prototype.remove = function( t , justOne ){
DBCollection.prototype._validateUpdateDoc = function(doc) {
// Hidden property for testing purposes.
- if (this._mongo._skipValidation) return;
+ if (this.getMongo()._skipValidation) return;
var firstKey = null;
for (var key in doc) { firstKey = key; break; }
@@ -359,7 +360,7 @@ DBCollection.prototype.update = function( query , obj , upsert , multi ){
if (!wc)
wc = this.getWriteConcern();
- if ( this._mongo.useWriteCommands() ) {
+ if ( this.getMongo().writeMode() != "legacy" ) {
var batch = this.initializeOrderedBulkOp();
var updateOp = batch.find(query);
@@ -378,7 +379,7 @@ DBCollection.prototype.update = function( query , obj , upsert , multi ){
}
else {
this._validateUpdateDoc(obj);
- this._mongo.update(this._fullName, query, obj,
+ this.getMongo().update(this._fullName, query, obj,
upsert ? true : false, multi ? true : false );
// enforce write concern, if required
@@ -490,8 +491,7 @@ DBCollection.prototype._indexSpec = function( keys, options ) {
DBCollection.prototype.createIndex = function( keys , options ){
var o = this._indexSpec( keys, options );
- if ( this._mongo.useWriteCommands() ) {
-
+ if ( this.getMongo().writeMode() != "legacy" ) {
// TODO: Use createIndexes command once fully supported by upgrade process
var bulk = this.getDB().system.indexes.initializeOrderedBulkOp();
bulk.insert(o);
diff --git a/src/mongo/shell/mongo.js b/src/mongo/shell/mongo.js
index 6dc3d9da064..08764a7b87f 100644
--- a/src/mongo/shell/mongo.js
+++ b/src/mongo/shell/mongo.js
@@ -155,31 +155,60 @@ connect = function(url, user, pass) {
return db;
}
+/** deprecated, use writeMode below
+ *
+ */
+Mongo.prototype.useWriteCommands = function() {
+ return (this.writeMode() != "legacy");
+}
+
+Mongo.prototype.forceWriteMode = function( mode ) {
+ this._writeMode = mode;
+}
+
+Mongo.prototype.hasWriteCommands = function() {
+ if ( !('_hasWriteCommands' in this) ) {
+ var isMaster = this.getDB("admin").runCommand({ isMaster : 1 });
+ this._hasWriteCommands = (isMaster.ok &&
+ 'minWireVersion' in isMaster &&
+ isMaster.minWireVersion <= 2 &&
+ 2 <= isMaster.maxWireVersion );
+ }
+
+ return this._hasWriteCommands;
+}
+
/**
- * {Boolean} If true, uses the write commands instead of the legacy write ops.
+ * {String} Returns the current mode set. Will be commands/legacy/compatibility
*
* Sends isMaster to determine if the connection is capable of using bulk write operations, and
* caches the result.
*/
-Mongo.prototype.useWriteCommands = function() {
- if ( '_useWriteCommands' in this ) {
- return this._useWriteCommands;
+Mongo.prototype.writeMode = function() {
+
+ if ( '_writeMode' in this ) {
+ return this._writeMode;
}
- // always use legacy write commands against old servers
- var isMaster = this.getDB("admin").runCommand({ isMaster : 1 });
- if ( isMaster.ok && 'minWireVersion' in isMaster &&
- isMaster.minWireVersion <= 2 && 2 <= isMaster.maxWireVersion ) {
- this._useWriteCommands = _useWriteCommandsDefault();
+ // get default from shell params
+ if ( _writeMode )
+ this._writeMode = _writeMode();
+
+ // can't use "commands" mode unless server version is good.
+ if ( this.hasWriteCommands() ) {
+ // good with whatever is already set
}
- else {
- this._useWriteCommands = false;
+ else if ( this._writeMode == "commands" ) {
+ print("Cannot use commands write mode, degrading to compatability mode");
+ this._writeMode = "compatibility";
}
- return this._useWriteCommands;
+ return this._writeMode;
};
+
+
//
// Write Concern can be set at the connection level, and is used for all write operations unless
// overridden at the collection level.
diff --git a/src/mongo/shell/shell_options.cpp b/src/mongo/shell/shell_options.cpp
index 08042fd2997..2832989ffe3 100644
--- a/src/mongo/shell/shell_options.cpp
+++ b/src/mongo/shell/shell_options.cpp
@@ -34,6 +34,7 @@
#include "mongo/bson/util/builder.h"
#include "mongo/db/server_options.h"
#include "mongo/shell/shell_utils.h"
+#include "mongo/util/mongoutils/str.h"
#include "mongo/util/net/sock.h"
#include "mongo/util/net/ssl_options.h"
#include "mongo/util/options_parser/startup_options.h"
@@ -116,6 +117,12 @@ namespace mongo {
moe::Switch,
"use legacy write ops instead of write commands").hidden();
+ options->addOptionChaining("writeMode",
+ "writeMode",
+ moe::String,
+ "mode to determine how writes are done:"
+ " commands, compatibility, legacy").hidden();
+
return Status::OK();
}
@@ -215,7 +222,16 @@ namespace mongo {
shellGlobalParams.autoKillOp = true;
}
if (params.count("useLegacyWriteOps")) {
- shellGlobalParams.useWriteCommandsDefault = false;
+ shellGlobalParams.writeMode = "legacy";
+ }
+ if (params.count("writeMode")) {
+ std::string mode = params["writeMode"].as<string>();
+ if (mode != "commands" && mode != "legacy" && mode != "compatibility") {
+ throw MsgAssertionException(17396,
+ mongoutils::str::stream() <<
+ "Unknown writeMode option: " << mode);
+ }
+ shellGlobalParams.writeMode = mode;
}
/* This is a bit confusing, here are the rules:
diff --git a/src/mongo/shell/shell_options.h b/src/mongo/shell/shell_options.h
index 04f6f5222a2..12d0ed5c89c 100644
--- a/src/mongo/shell/shell_options.h
+++ b/src/mongo/shell/shell_options.h
@@ -62,8 +62,12 @@ namespace mongo {
bool autoKillOp;
bool useWriteCommandsDefault;
+ std::string writeMode;
- ShellGlobalParams() : autoKillOp(false), useWriteCommandsDefault(true) { }
+ ShellGlobalParams() : autoKillOp(false),
+ useWriteCommandsDefault(true),
+ writeMode("commands") {
+ }
};
extern ShellGlobalParams shellGlobalParams;
diff --git a/src/mongo/shell/shell_utils.cpp b/src/mongo/shell/shell_utils.cpp
index b9b256c1c7e..ce3cf42a7a0 100644
--- a/src/mongo/shell/shell_utils.cpp
+++ b/src/mongo/shell/shell_utils.cpp
@@ -178,6 +178,10 @@ namespace mongo {
return BSON("" << shellGlobalParams.useWriteCommandsDefault);
}
+ BSONObj writeMode(const BSONObj&, void*) {
+ return BSON("" << shellGlobalParams.writeMode);
+ }
+
BSONObj interpreterVersion(const BSONObj& a, void* data) {
uassert( 16453, "interpreterVersion accepts no arguments", a.nFields() == 0 );
return BSON( "" << globalScriptEngine->getInterpreterVersionString() );
@@ -205,6 +209,7 @@ namespace mongo {
void initScope( Scope &scope ) {
// Need to define this method before JSFiles::utils is executed.
scope.injectNative("_useWriteCommandsDefault", useWriteCommandsDefault);
+ scope.injectNative("_writeMode", writeMode);
scope.externalSetup();
mongo::shell_utils::installShellUtils( scope );
scope.execSetup(JSFiles::servers);
diff --git a/src/mongo/shell/utils.js b/src/mongo/shell/utils.js
index 2c48a3c24d6..41735768dd8 100644
--- a/src/mongo/shell/utils.js
+++ b/src/mongo/shell/utils.js
@@ -594,16 +594,21 @@ if (typeof(_useWriteCommandsDefault) == 'undefined') {
_useWriteCommandsDefault = function() { return false; };
};
+if (typeof(_writeMode) == 'undefined') {
+ // This is for cases when the v8 engine is used other than the mongo shell, like map reduce.
+ _writeMode = function() { return "commands"; };
+};
+
shellPrintHelper = function (x) {
if (typeof (x) == "undefined") {
// Make sure that we have a db var before we use it
// TODO: This implicit calling of GLE can cause subtle, hard to track issues - remove?
if (__callLastError && typeof( db ) != "undefined" &&
db.getMongo &&
- !db.getMongo().useWriteCommands) {
+ db.getMongo().writeMode == "legacy") {
__callLastError = false;
- // explicit w:1 so that replset getLastErrorDefaults aren't used here which would be bad.
+ // explicit w:1 so that replset getLastErrorDefaults aren't used here which would be bad
var err = db.getLastError(1);
if (err != null) {
print(err);