diff options
Diffstat (limited to 'shell')
-rw-r--r-- | shell/collection.js | 72 | ||||
-rw-r--r-- | shell/db.js | 30 | ||||
-rw-r--r-- | shell/dbshell.cpp | 65 | ||||
-rw-r--r-- | shell/mongo.js | 2 | ||||
-rw-r--r-- | shell/mongo_vstudio.cpp | 2795 | ||||
-rw-r--r-- | shell/query.js | 38 | ||||
-rw-r--r-- | shell/servers.js | 150 | ||||
-rw-r--r-- | shell/utils.cpp | 504 | ||||
-rw-r--r-- | shell/utils.h | 23 | ||||
-rw-r--r-- | shell/utils.js | 54 |
10 files changed, 1829 insertions, 1904 deletions
diff --git a/shell/collection.js b/shell/collection.js index d228ba7..edb07ae 100644 --- a/shell/collection.js +++ b/shell/collection.js @@ -26,15 +26,16 @@ DBCollection.prototype.getName = function(){ return this._shortName; } -DBCollection.prototype.help = function(){ +DBCollection.prototype.help = function() { print("DBCollection help"); print("\tdb.foo.count()"); print("\tdb.foo.dataSize()"); - print("\tdb.foo.distinct( key ) - eg. db.foo.distinct( 'x' )" ); + print("\tdb.foo.distinct( key ) - eg. db.foo.distinct( 'x' )"); print("\tdb.foo.drop() drop the collection"); print("\tdb.foo.dropIndex(name)"); print("\tdb.foo.dropIndexes()"); print("\tdb.foo.ensureIndex(keypattern,options) - options should be an object with these possible fields: name, unique, dropDups"); + print("\tdb.foo.reIndex()"); print("\tdb.foo.find( [query] , [fields]) - first parameter is an optional query filter. second parameter is optional set of fields to return."); print("\t e.g. db.foo.find( { x : 77 } , { name : 1 , x : 1 } )"); print("\tdb.foo.find(...).count()"); @@ -46,9 +47,10 @@ DBCollection.prototype.help = function(){ print("\tdb.foo.getDB() get DB object associated with collection"); print("\tdb.foo.getIndexes()"); print("\tdb.foo.group( { key : ..., initial: ..., reduce : ...[, cond: ...] } )"); - print("\tdb.foo.mapReduce( mapFunction , reduceFunction , <optional params> )" ); - print("\tdb.foo.remove(query)" ); + print("\tdb.foo.mapReduce( mapFunction , reduceFunction , <optional params> )"); + print("\tdb.foo.remove(query)"); print("\tdb.foo.renameCollection( newName , <dropTarget> ) renames the collection."); + print("\tdb.foo.runCommand( name , <options> ) runs a db command with the given name where the 1st param is the colleciton name" ); print("\tdb.foo.save(obj)"); print("\tdb.foo.stats()"); print("\tdb.foo.storageSize() - includes free space allocated to this collection"); @@ -56,7 +58,7 @@ DBCollection.prototype.help = function(){ print("\tdb.foo.totalSize() - storage allocated for all data and indexes"); print("\tdb.foo.update(query, object[, upsert_bool, multi_bool])"); print("\tdb.foo.validate() - SLOW"); - print("\tdb.foo.getShardVersion() - only for use with sharding" ); + print("\tdb.foo.getShardVersion() - only for use with sharding"); } DBCollection.prototype.getFullName = function(){ @@ -66,10 +68,19 @@ DBCollection.prototype.getDB = function(){ return this._db; } -DBCollection.prototype._dbCommand = function( cmd ){ - return this._db._dbCommand( cmd ); +DBCollection.prototype._dbCommand = function( cmd , params ){ + if ( typeof( cmd ) == "object" ) + return this._db._dbCommand( cmd ); + + var c = {}; + c[cmd] = this.getName(); + if ( params ) + Object.extend( c , params ); + return this._db._dbCommand( c ); } +DBCollection.prototype.runCommand = DBCollection.prototype._dbCommand; + DBCollection.prototype._massageObject = function( q ){ if ( ! q ) return {}; @@ -128,7 +139,7 @@ DBCollection.prototype.find = function( query , fields , limit , skip ){ } DBCollection.prototype.findOne = function( query , fields ){ - var cursor = this._mongo.find( this._fullName , this._massageObject( query ) || {} , fields , -1 , 0 ); + var cursor = this._mongo.find( this._fullName , this._massageObject( query ) || {} , fields , -1 , 0 , 0 ); if ( ! cursor.hasNext() ) return null; var ret = cursor.next(); @@ -144,7 +155,15 @@ DBCollection.prototype.insert = function( obj , _allow_dot ){ if ( ! _allow_dot ) { this._validateForStorage( obj ); } - return this._mongo.insert( this._fullName , obj ); + if ( typeof( obj._id ) == "undefined" ){ + var tmp = obj; // don't want to modify input + obj = {_id: new ObjectId()}; + for (var key in tmp){ + obj[key] = tmp[key]; + } + } + this._mongo.insert( this._fullName , obj ); + this._lastID = obj._id; } DBCollection.prototype.remove = function( t ){ @@ -275,12 +294,8 @@ DBCollection.prototype.resetIndexCache = function(){ this._indexCache = {}; } -DBCollection.prototype.reIndex = function(){ - var specs = this.getIndexSpecs(); - this.dropIndexes(); - for ( var i = 0; i < specs.length; ++i ){ - this.ensureIndex( specs[i].key, [ specs[i].unique, specs[i].name ] ); - } +DBCollection.prototype.reIndex = function() { + return this._db.runCommand({ reIndex: this.getName() }); } DBCollection.prototype.dropIndexes = function(){ @@ -311,7 +326,7 @@ DBCollection.prototype.drop = function(){ DBCollection.prototype.findAndModify = function(args){ var cmd = { findandmodify: this.getName() }; - for (key in args){ + for (var key in args){ cmd[key] = args[key]; } @@ -402,7 +417,7 @@ DBCollection.prototype.dropIndex = function(index) { if ( ! isString( index ) && isObject( index ) ) index = this._genIndexName( index ); - var res = this._dbCommand( { deleteIndexes: this.getName(), index: index } ); + var res = this._dbCommand( "deleteIndexes" ,{ index: index } ); this.resetIndexCache(); return res; } @@ -431,8 +446,8 @@ DBCollection.prototype.getCollection = function( subName ){ return this._db.getCollection( this._shortName + "." + subName ); } -DBCollection.prototype.stats = function(){ - return this._db.runCommand( { collstats : this._shortName } ); +DBCollection.prototype.stats = function( scale ){ + return this._db.runCommand( { collstats : this._shortName , scale : scale } ); } DBCollection.prototype.dataSize = function(){ @@ -444,20 +459,13 @@ DBCollection.prototype.storageSize = function(){ } DBCollection.prototype.totalIndexSize = function( verbose ){ - var total = 0; - var mydb = this._db; - var shortName = this._shortName; - this.getIndexes().forEach( - function( spec ){ - var coll = mydb.getCollection( shortName + ".$" + spec.name ); - var mysize = coll.dataSize(); - total += coll.dataSize(); - if ( verbose ) { - print( coll + "\t" + mysize ); - } + var stats = this.stats(); + if (verbose){ + for (var ns in stats.indexSizes){ + print( ns + "\t" + stats.indexSizes[ns] ); } - ); - return total; + } + return stats.totalIndexSize; } diff --git a/shell/db.js b/shell/db.js index ab79e22..bdb1153 100644 --- a/shell/db.js +++ b/shell/db.js @@ -20,6 +20,10 @@ DB.prototype.getName = function(){ return this._name; } +DB.prototype.stats = function(){ + return this.runCommand( { dbstats : 1 } ); +} + DB.prototype.getCollection = function( name ){ return new DBCollection( this._mongo , this , name , this._name + "." + name ); } @@ -48,10 +52,12 @@ DB.prototype._adminCommand = function( obj ){ return this.getSisterDB( "admin" ).runCommand( obj ); } -DB.prototype.addUser = function( username , pass ){ +DB.prototype.addUser = function( username , pass, readOnly ){ + readOnly = readOnly || false; var c = this.getCollection( "system.users" ); var u = c.findOne( { user : username } ) || { user : username }; + u.readOnly = readOnly; u.pwd = hex_md5( username + ":mongo:" + pass ); print( tojson( u ) ); @@ -62,6 +68,10 @@ DB.prototype.removeUser = function( username ){ this.getCollection( "system.users" ).remove( { user : username } ); } +DB.prototype.__pwHash = function( nonce, username, pass ) { + return hex_md5( nonce + username + hex_md5( username + ":mongo:" + pass ) ); +} + DB.prototype.auth = function( username , pass ){ var n = this.runCommand( { getnonce : 1 } ); @@ -70,7 +80,7 @@ DB.prototype.auth = function( username , pass ){ authenticate : 1 , user : username , nonce : n.nonce , - key : hex_md5( n.nonce + username + hex_md5( username + ":mongo:" + pass ) ) + key : this.__pwHash( n.nonce, username, pass ) } ); @@ -219,12 +229,16 @@ DB.prototype.cloneCollection = function(from, collection, query) { * @return Object returned has member ok set to true if operation succeeds, false otherwise. * See also: db.clone() */ -DB.prototype.copyDatabase = function(fromdb, todb, fromhost) { +DB.prototype.copyDatabase = function(fromdb, todb, fromhost, username, password) { assert( isString(fromdb) && fromdb.length ); assert( isString(todb) && todb.length ); fromhost = fromhost || ""; - //this.resetIndexCache(); - return this._adminCommand( { copydb:1, fromhost:fromhost, fromdb:fromdb, todb:todb } ); + if ( username && password ) { + var n = this._adminCommand( { copydbgetnonce : 1, fromhost:fromhost } ); + return this._adminCommand( { copydb:1, fromhost:fromhost, fromdb:fromdb, todb:todb, username:username, nonce:n.nonce, key:this.__pwHash( n.nonce, username, password ) } ); + } else { + return this._adminCommand( { copydb:1, fromhost:fromhost, fromdb:fromdb, todb:todb } ); + } } /** @@ -239,7 +253,7 @@ DB.prototype.repairDatabase = function() { DB.prototype.help = function() { print("DB methods:"); - print("\tdb.addUser(username, password)"); + print("\tdb.addUser(username, password[, readOnly=false])"); print("\tdb.auth(username, password)"); print("\tdb.cloneDatabase(fromhost)"); print("\tdb.commandHelp(name) returns the help for the command"); @@ -268,8 +282,10 @@ DB.prototype.help = function() { print("\tdb.repairDatabase()"); print("\tdb.resetError()"); print("\tdb.runCommand(cmdObj) run a database command. if cmdObj is a string, turns it into { cmdObj : 1 }"); + print("\tdb.serverStatus()"); print("\tdb.setProfilingLevel(level,<slowms>) 0=off 1=slow 2=all"); print("\tdb.shutdownServer()"); + print("\tdb.stats()"); print("\tdb.version() current version of the server" ); } @@ -490,7 +506,7 @@ DB.prototype.getCollectionNames = function(){ function(z){ var name = z.name; - if ( name.indexOf( "$" ) >= 0 ) + if ( name.indexOf( "$" ) >= 0 && name != "local.oplog.$main" ) return; all.push( name.substring( nsLength ) ); diff --git a/shell/dbshell.cpp b/shell/dbshell.cpp index 7984383..cad3698 100644 --- a/shell/dbshell.cpp +++ b/shell/dbshell.cpp @@ -1,4 +1,20 @@ // dbshell.cpp +/* + * Copyright 2010 10gen Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include <stdio.h> @@ -51,7 +67,8 @@ void shellHistoryAdd( const char * line ){ if ( strlen(line) == 0 ) return; #ifdef USE_READLINE - add_history( line ); + if ((strstr(line, ".auth")) == NULL) + add_history( line ); #endif } @@ -62,6 +79,21 @@ void intr( int sig ){ } #if !defined(_WIN32) +void killOps() { + if ( mongo::shellUtils::_nokillop || mongo::shellUtils::_allMyUris.size() == 0 ) + return; + vector< string > uris; + for( map< const void*, string >::iterator i = mongo::shellUtils::_allMyUris.begin(); i != mongo::shellUtils::_allMyUris.end(); ++i ) + uris.push_back( i->second ); + mongo::BSONObj spec = BSON( "" << uris ); + try { + auto_ptr< mongo::Scope > scope( mongo::globalScriptEngine->newScope() ); + scope->invoke( "function( x ) { killWithUris( x ); }", spec ); + } catch ( ... ) { + mongo::rawOut( "exception while cleaning up any db ops started by this shell\n" ); + } +} + void quitNicely( int sig ){ if ( sig == SIGINT && inMultiLine ){ gotInterrupted = 1; @@ -69,6 +101,7 @@ void quitNicely( int sig ){ } if ( sig == SIGPIPE ) mongo::rawOut( "mongo got signal SIGPIPE\n" ); + killOps(); shellHistoryDone(); exit(0); } @@ -93,7 +126,7 @@ char * shellReadline( const char * prompt , int handlesigint = 0 ){ signal( SIGINT , quitNicely ); return ret; #else - printf( prompt ); + printf("%s", prompt); char * buf = new char[1024]; char * l = fgets( buf , 1024 , stdin ); int len = strlen( buf ); @@ -289,6 +322,7 @@ int _main(int argc, char* argv[]) { hidden_options.add_options() ("dbaddress", po::value<string>(), "dbaddress") ("files", po::value< vector<string> >(), "files") + ("nokillop", "nokillop") // for testing, kill op will also be disabled automatically if the tests starts a mongo program ; positional_options.add("dbaddress", 1); @@ -336,7 +370,10 @@ int _main(int argc, char* argv[]) { if (params.count("quiet")) { mongo::cmdLine.quiet = true; } - + if (params.count("nokillop")) { + mongo::shellUtils::_nokillop = true; + } + /* This is a bit confusing, here are the rules: * * if nodb is set then all positional parameters are files @@ -382,6 +419,7 @@ int _main(int argc, char* argv[]) { } + mongo::ScriptEngine::setConnectCallback( mongo::shellUtils::onConnect ); mongo::ScriptEngine::setup(); mongo::globalScriptEngine->setScopeInitCallback( mongo::shellUtils::initScope ); auto_ptr< mongo::Scope > scope( mongo::globalScriptEngine->newScope() ); @@ -433,7 +471,7 @@ int _main(int argc, char* argv[]) { } string code = line; - if ( code == "exit" ){ + if ( code == "exit" || code == "exit;" ){ break; } if ( code.size() == 0 ) @@ -455,9 +493,15 @@ int _main(int argc, char* argv[]) { cmd = cmd.substr( 0 , cmd.find( " " ) ); if ( cmd.find( "\"" ) == string::npos ){ - scope->exec( (string)"__iscmd__ = shellHelper[\"" + cmd + "\"];" , "(shellhelp1)" , false , true , true ); - if ( scope->getBoolean( "__iscmd__" ) ){ - scope->exec( (string)"shellHelper( \"" + cmd + "\" , \"" + code.substr( cmd.size() ) + "\");" , "(shellhelp2)" , false , true , false ); + try { + scope->exec( (string)"__iscmd__ = shellHelper[\"" + cmd + "\"];" , "(shellhelp1)" , false , true , true ); + if ( scope->getBoolean( "__iscmd__" ) ){ + scope->exec( (string)"shellHelper( \"" + cmd + "\" , \"" + code.substr( cmd.size() ) + "\");" , "(shellhelp2)" , false , true , false ); + wascmd = true; + } + } + catch ( std::exception& e ){ + cout << "error2:" << e.what() << endl; wascmd = true; } } @@ -485,6 +529,7 @@ int _main(int argc, char* argv[]) { } int main(int argc, char* argv[]) { + static mongo::StaticObserver staticObserver; try { return _main( argc , argv ); } @@ -494,10 +539,4 @@ int main(int argc, char* argv[]) { } } -namespace mongo { - DBClientBase * createDirectClient(){ - uassert( 10256 , "no createDirectClient in shell" , 0 ); - return 0; - } -} diff --git a/shell/mongo.js b/shell/mongo.js index dc7fcd9..acd028b 100644 --- a/shell/mongo.js +++ b/shell/mongo.js @@ -34,7 +34,7 @@ Mongo.prototype.getDB = function( name ){ Mongo.prototype.getDBs = function(){ var res = this.getDB( "admin" ).runCommand( { "listDatabases" : 1 } ); - assert( res.ok == 1 , "listDatabases failed" ); + assert( res.ok == 1 , "listDatabases failed:" + tojson( res ) ); return res; } diff --git a/shell/mongo_vstudio.cpp b/shell/mongo_vstudio.cpp index d0f1b48..f88b3c2 100644 --- a/shell/mongo_vstudio.cpp +++ b/shell/mongo_vstudio.cpp @@ -1,446 +1,616 @@ const char * jsconcatcode = -"if ( ( typeof DBCollection ) == \"undefined\" ){\n" - "DBCollection = function( mongo , db , shortName , fullName ){\n" - "this._mongo = mongo;\n" - "this._db = db;\n" - "this._shortName = shortName;\n" - "this._fullName = fullName;\n" - "this.verify();\n" - "}\n" - "}\n" - "DBCollection.prototype.verify = function(){\n" - "assert( this._fullName , \"no fullName\" );\n" - "assert( this._shortName , \"no shortName\" );\n" - "assert( this._db , \"no db\" );\n" - "assert.eq( this._fullName , this._db._name + \".\" + this._shortName , \"name mismatch\" );\n" - "assert( this._mongo , \"no mongo in DBCollection\" );\n" - "}\n" - "DBCollection.prototype.getName = function(){\n" - "return this._shortName;\n" - "}\n" - "DBCollection.prototype.help = function(){\n" - "print(\"DBCollection help\");\n" - "print(\"\\tdb.foo.getDB() get DB object associated with collection\");\n" - "print(\"\\tdb.foo.findOne([query])\");\n" - "print(\"\\tdb.foo.find( [query] , [fields]) - first parameter is an optional query filter. second parameter is optional set of fields to return.\");\n" - "print(\"\\t e.g. db.foo.find( { x : 77 } , { name : 1 , x : 1 } )\");\n" - "print(\"\\tdb.foo.find(...).sort(...)\");\n" - "print(\"\\tdb.foo.find(...).limit(n)\");\n" - "print(\"\\tdb.foo.find(...).skip(n)\");\n" - "print(\"\\tdb.foo.find(...).count()\");\n" - "print(\"\\tdb.foo.count()\");\n" - "print(\"\\tdb.foo.group( { key : ..., initial: ..., reduce : ...[, cond: ...] } )\");\n" - "print(\"\\tdb.foo.save(obj)\");\n" - "print(\"\\tdb.foo.update(query, object[, upsert_bool])\");\n" - "print(\"\\tdb.foo.remove(query)\" );\n" - "print(\"\\tdb.foo.ensureIndex(keypattern,options) - options should be an object with these possible fields: name, unique, dropDups\");\n" - "print(\"\\tdb.foo.dropIndexes()\");\n" - "print(\"\\tdb.foo.dropIndex(name)\");\n" - "print(\"\\tdb.foo.getIndexes()\");\n" - "print(\"\\tdb.foo.drop() drop the collection\");\n" - "print(\"\\tdb.foo.renameCollection( newName ) renames the collection\");\n" - "print(\"\\tdb.foo.validate() - SLOW\");\n" - "print(\"\\tdb.foo.stats()\");\n" - "print(\"\\tdb.foo.dataSize()\");\n" - "print(\"\\tdb.foo.storageSize() - includes free space allocated to this collection\");\n" - "print(\"\\tdb.foo.totalIndexSize() - size in bytes of all the indexes\");\n" - "print(\"\\tdb.foo.totalSize() - storage allocated for all data and indexes\");\n" - "}\n" - "DBCollection.prototype.getFullName = function(){\n" - "return this._fullName;\n" - "}\n" - "DBCollection.prototype.getDB = function(){\n" - "return this._db;\n" - "}\n" - "DBCollection.prototype._dbCommand = function( cmd ){\n" - "return this._db._dbCommand( cmd );\n" - "}\n" - "DBCollection.prototype._massageObject = function( q ){\n" - "if ( ! q )\n" - "return {};\n" - "var type = typeof q;\n" - "if ( type == \"function\" )\n" - "return { $where : q };\n" - "if ( q.isObjectId )\n" - "return { _id : q };\n" - "if ( type == \"object\" )\n" - "return q;\n" - "if ( type == \"string\" ){\n" - "if ( q.length == 24 )\n" - "return { _id : q };\n" - "return { $where : q };\n" - "}\n" - "throw \"don't know how to massage : \" + type;\n" - "}\n" - "DBCollection.prototype._validateObject = function( o ){\n" - "if ( o._ensureSpecial && o._checkModify )\n" - "throw \"can't save a DBQuery object\";\n" - "}\n" - "DBCollection._allowedFields = { $id : 1 , $ref : 1 };\n" - "DBCollection.prototype._validateForStorage = function( o ){\n" - "this._validateObject( o );\n" - "for ( var k in o ){\n" - "if ( k.indexOf( \".\" ) >= 0 ) {\n" - "throw \"can't have . in field names [\" + k + \"]\" ;\n" - "}\n" - "if ( k.indexOf( \"$\" ) == 0 && ! DBCollection._allowedFields[k] ) {\n" - "throw \"field names cannot start with $ [\" + k + \"]\";\n" - "}\n" - "if ( o[k] !== null && typeof( o[k] ) === \"object\" ) {\n" - "this._validateForStorage( o[k] );\n" - "}\n" - "}\n" - "};\n" - "DBCollection.prototype.find = function( query , fields , limit , skip ){\n" - "return new DBQuery( this._mongo , this._db , this ,\n" - "this._fullName , this._massageObject( query ) , fields , limit , skip );\n" - "}\n" - "DBCollection.prototype.findOne = function( query , fields ){\n" - "var cursor = this._mongo.find( this._fullName , this._massageObject( query ) || {} , fields , -1 , 0 );\n" - "if ( ! cursor.hasNext() )\n" +"__quiet = false;\n" + "chatty = function(s){\n" + "if ( ! __quiet )\n" + "print( s );}\n" + "friendlyEqual = function( a , b ){\n" + "if ( a == b )\n" + "return true;\n" + "if ( tojson( a ) == tojson( b ) )\n" + "return true;\n" + "return false;}\n" + "doassert = function( msg ){\n" + "print( \"assert: \" + msg );\n" + "throw msg;}\n" + "assert = function( b , msg ){\n" + "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" + "if ( b )\n" + "return;\n" + "doassert( \"assert failed : \" + msg );}\n" + "assert._debug = false;\n" + "assert.eq = function( a , b , msg ){\n" + "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" + "if ( a == b )\n" + "return;\n" + "if ( ( a != null && b != null ) && friendlyEqual( a , b ) )\n" + "return;\n" + "doassert( \"[\" + tojson( a ) + \"] != [\" + tojson( b ) + \"] are not equal : \" + msg );}\n" + "assert.neq = function( a , b , msg ){\n" + "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" + "if ( a != b )\n" + "return;\n" + "doassert( \"[\" + a + \"] != [\" + b + \"] are equal : \" + msg );}\n" + "assert.soon = function( f, msg, timeout, interval ) {\n" + "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" + "var start = new Date();\n" + "timeout = timeout || 30000;\n" + "interval = interval || 200;\n" + "var last;\n" + "while( 1 ) {\n" + "if ( typeof( f ) == \"string\" ){\n" + "if ( eval( f ) )\n" + "return;}\n" + "else {\n" + "if ( f() )\n" + "return;}\n" + "if ( ( new Date() ).getTime() - start.getTime() > timeout )\n" + "doassert( \"assert.soon failed: \" + f + \", msg:\" + msg );\n" + "sleep( interval );}}\n" + "assert.throws = function( func , params , msg ){\n" + "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" + "try {\n" + "func.apply( null , params );}\n" + "catch ( e ){\n" + "return e;}\n" + "doassert( \"did not throw exception: \" + msg );}\n" + "assert.commandWorked = function( res , msg ){\n" + "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" + "if ( res.ok == 1 )\n" + "return;\n" + "doassert( \"command failed: \" + tojson( res ) + \" : \" + msg );}\n" + "assert.commandFailed = function( res , msg ){\n" + "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" + "if ( res.ok == 0 )\n" + "return;\n" + "doassert( \"command worked when it should have failed: \" + tojson( res ) + \" : \" + msg );}\n" + "assert.isnull = function( what , msg ){\n" + "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" + "if ( what == null )\n" + "return;\n" + "doassert( \"supposed to null (\" + ( msg || \"\" ) + \") was: \" + tojson( what ) );}\n" + "assert.lt = function( a , b , msg ){\n" + "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" + "if ( a < b )\n" + "return;\n" + "doassert( a + \" is not less than \" + b + \" : \" + msg );}\n" + "assert.gt = function( a , b , msg ){\n" + "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" + "if ( a > b )\n" + "return;\n" + "doassert( a + \" is not greater than \" + b + \" : \" + msg );}\n" + "assert.close = function( a , b , msg ){\n" + "var diff = Math.abs( (a-b)/((a+b)/2) );\n" + "if ( diff < .001 )\n" + "return;\n" + "doassert( a + \" is not close to \" + b + \" diff: \" + diff + \" : \" + msg );}\n" + "Object.extend = function( dst , src , deep ){\n" + "for ( var k in src ){\n" + "var v = src[k];\n" + "if ( deep && typeof(v) == \"object\" ){\n" + "v = Object.extend( typeof ( v.length ) == \"number\" ? [] : {} , v , true );}\n" + "dst[k] = v;}\n" + "return dst;}\n" + "argumentsToArray = function( a ){\n" + "var arr = [];\n" + "for ( var i=0; i<a.length; i++ )\n" + "arr[i] = a[i];\n" + "return arr;}\n" + "isString = function( x ){\n" + "return typeof( x ) == \"string\";}\n" + "isNumber = function(x){\n" + "return typeof( x ) == \"number\";}\n" + "isObject = function( x ){\n" + "return typeof( x ) == \"object\";}\n" + "String.prototype.trim = function() {\n" + "return this.replace(/^\\s+|\\s+$/g,\"\");}\n" + "String.prototype.ltrim = function() {\n" + "return this.replace(/^\\s+/,\"\");}\n" + "String.prototype.rtrim = function() {\n" + "return this.replace(/\\s+$/,\"\");}\n" + "Date.timeFunc = function( theFunc , numTimes ){\n" + "var start = new Date();\n" + "numTimes = numTimes || 1;\n" + "for ( var i=0; i<numTimes; i++ ){\n" + "theFunc.apply( null , argumentsToArray( arguments ).slice( 2 ) );}\n" + "return (new Date()).getTime() - start.getTime();}\n" + "Date.prototype.tojson = function(){\n" + "return \"\\\"\" + this.toString() + \"\\\"\";}\n" + "RegExp.prototype.tojson = RegExp.prototype.toString;\n" + "Array.contains = function( a , x ){\n" + "for ( var i=0; i<a.length; i++ ){\n" + "if ( a[i] == x )\n" + "return true;}\n" + "return false;}\n" + "Array.unique = function( a ){\n" + "var u = [];\n" + "for ( var i=0; i<a.length; i++){\n" + "var o = a[i];\n" + "if ( ! Array.contains( u , o ) ){\n" + "u.push( o );}}\n" + "return u;}\n" + "Array.shuffle = function( arr ){\n" + "for ( var i=0; i<arr.length-1; i++ ){\n" + "var pos = i+Random.randInt(arr.length-i);\n" + "var save = arr[i];\n" + "arr[i] = arr[pos];\n" + "arr[pos] = save;}\n" + "return arr;}\n" + "Array.tojson = function( a , indent ){\n" + "if (!indent)\n" + "indent = \"\";\n" + "if (a.length == 0) {\n" + "return \"[ ]\";}\n" + "var s = \"[\\n\";\n" + "indent += \"\\t\";\n" + "for ( var i=0; i<a.length; i++){\n" + "s += indent + tojson( a[i], indent );\n" + "if ( i < a.length - 1 ){\n" + "s += \",\\n\";}}\n" + "if ( a.length == 0 ) {\n" + "s += indent;}\n" + "indent = indent.substring(1);\n" + "s += \"\\n\"+indent+\"]\";\n" + "return s;}\n" + "Array.fetchRefs = function( arr , coll ){\n" + "var n = [];\n" + "for ( var i=0; i<arr.length; i ++){\n" + "var z = arr[i];\n" + "if ( coll && coll != z.getCollection() )\n" + "continue;\n" + "n.push( z.fetch() );}\n" + "return n;}\n" + "Array.sum = function( arr ){\n" + "if ( arr.length == 0 )\n" "return null;\n" - "var ret = cursor.next();\n" - "if ( cursor.hasNext() ) throw \"findOne has more than 1 result!\";\n" - "if ( ret.$err )\n" - "throw \"error \" + tojson( ret );\n" - "return ret;\n" - "}\n" - "DBCollection.prototype.insert = function( obj , _allow_dot ){\n" - "if ( ! obj )\n" - "throw \"no object!\";\n" - "if ( ! _allow_dot ) {\n" - "this._validateForStorage( obj );\n" - "}\n" - "return this._mongo.insert( this._fullName , obj );\n" - "}\n" - "DBCollection.prototype.remove = function( t ){\n" - "this._mongo.remove( this._fullName , this._massageObject( t ) );\n" - "}\n" - "DBCollection.prototype.update = function( query , obj , upsert ){\n" - "assert( query , \"need a query\" );\n" - "assert( obj , \"need an object\" );\n" - "this._validateObject( obj );\n" - "return this._mongo.update( this._fullName , query , obj , upsert ? true : false );\n" - "}\n" - "DBCollection.prototype.save = function( obj ){\n" - "if ( obj == null || typeof( obj ) == \"undefined\" )\n" - "throw \"can't save a null\";\n" - "if ( typeof( obj._id ) == \"undefined\" ){\n" - "obj._id = new ObjectId();\n" - "return this.insert( obj );\n" - "}\n" + "var s = arr[0];\n" + "for ( var i=1; i<arr.length; i++ )\n" + "s += arr[i];\n" + "return s;}\n" + "Array.avg = function( arr ){\n" + "if ( arr.length == 0 )\n" + "return null;\n" + "return Array.sum( arr ) / arr.length;}\n" + "Array.stdDev = function( arr ){\n" + "var avg = Array.avg( arr );\n" + "var sum = 0;\n" + "for ( var i=0; i<arr.length; i++ ){\n" + "sum += Math.pow( arr[i] - avg , 2 );}\n" + "return Math.sqrt( sum / arr.length );}\n" + "Object.keySet = function( o ) {\n" + "var ret = new Array();\n" + "for( i in o ) {\n" + "if ( !( i in o.__proto__ && o[ i ] === o.__proto__[ i ] ) ) {\n" + "ret.push( i );}}\n" + "return ret;}\n" + "if ( ! ObjectId.prototype )\n" + "ObjectId.prototype = {}\n" + "ObjectId.prototype.toString = function(){\n" + "return this.str;}\n" + "ObjectId.prototype.tojson = function(){\n" + "return \"ObjectId(\\\"\" + this.str + \"\\\")\";}\n" + "ObjectId.prototype.isObjectId = true;\n" + "if ( typeof( DBPointer ) != \"undefined\" ){\n" + "DBPointer.prototype.fetch = function(){\n" + "assert( this.ns , \"need a ns\" );\n" + "assert( this.id , \"need an id\" );\n" + "return db[ this.ns ].findOne( { _id : this.id } );}\n" + "DBPointer.prototype.tojson = function(indent){\n" + "return tojson({\"ns\" : this.ns, \"id\" : this.id}, indent);}\n" + "DBPointer.prototype.getCollection = function(){\n" + "return this.ns;}\n" + "DBPointer.prototype.toString = function(){\n" + "return \"DBPointer \" + this.ns + \":\" + this.id;}}\n" "else {\n" - "return this.update( { _id : obj._id } , obj , true );\n" - "}\n" - "}\n" - "DBCollection.prototype._genIndexName = function( keys ){\n" - "var name = \"\";\n" - "for ( var k in keys ){\n" - "if ( name.length > 0 )\n" - "name += \"_\";\n" - "name += k + \"_\";\n" - "var v = keys[k];\n" - "if ( typeof v == \"number\" )\n" - "name += v;\n" - "}\n" - "return name;\n" - "}\n" - "DBCollection.prototype._indexSpec = function( keys, options ) {\n" - "var ret = { ns : this._fullName , key : keys , name : this._genIndexName( keys ) };\n" - "if ( ! options ){\n" - "}\n" - "else if ( typeof ( options ) == \"string\" )\n" - "ret.name = options;\n" - "else if ( typeof ( options ) == \"boolean\" )\n" - "ret.unique = true;\n" - "else if ( typeof ( options ) == \"object\" ){\n" - "if ( options.length ){\n" - "var nb = 0;\n" - "for ( var i=0; i<options.length; i++ ){\n" - "if ( typeof ( options[i] ) == \"string\" )\n" - "ret.name = options[i];\n" - "else if ( typeof( options[i] ) == \"boolean\" ){\n" - "if ( options[i] ){\n" - "if ( nb == 0 )\n" - "ret.unique = true;\n" - "if ( nb == 1 )\n" - "ret.dropDups = true;\n" - "}\n" - "nb++;\n" - "}\n" - "}\n" - "}\n" + "print( \"warning: no DBPointer\" );}\n" + "if ( typeof( DBRef ) != \"undefined\" ){\n" + "DBRef.prototype.fetch = function(){\n" + "assert( this.$ref , \"need a ns\" );\n" + "assert( this.$id , \"need an id\" );\n" + "return db[ this.$ref ].findOne( { _id : this.$id } );}\n" + "DBRef.prototype.tojson = function(indent){\n" + "return tojson({\"$ref\" : this.$ref, \"$id\" : this.$id}, indent);}\n" + "DBRef.prototype.getCollection = function(){\n" + "return this.$ref;}\n" + "DBRef.prototype.toString = function(){\n" + "return this.tojson();}}\n" "else {\n" - "Object.extend( ret , options );\n" - "}\n" - "}\n" + "print( \"warning: no DBRef\" );}\n" + "if ( typeof( BinData ) != \"undefined\" ){\n" + "BinData.prototype.tojson = function(){\n" + "return \"BinData type: \" + this.type + \" len: \" + this.len;}}\n" "else {\n" - "throw \"can't handle: \" + typeof( options );\n" - "}\n" - "/*\n" - "return ret;\n" - "var name;\n" - "var nTrue = 0;\n" - "if ( ! isObject( options ) ) {\n" - "options = [ options ];\n" - "}\n" - "if ( options.length ){\n" - "for( var i = 0; i < options.length; ++i ) {\n" - "var o = options[ i ];\n" - "if ( isString( o ) ) {\n" - "ret.name = o;\n" - "} else if ( typeof( o ) == \"boolean\" ) {\n" - "if ( o ) {\n" - "++nTrue;\n" - "}\n" - "}\n" - "}\n" - "if ( nTrue > 0 ) {\n" - "ret.unique = true;\n" - "}\n" - "if ( nTrue > 1 ) {\n" - "ret.dropDups = true;\n" - "}\n" - "}\n" - "*/\n" - "return ret;\n" - "}\n" - "DBCollection.prototype.createIndex = function( keys , options ){\n" - "var o = this._indexSpec( keys, options );\n" - "this._db.getCollection( \"system.indexes\" ).insert( o , true );\n" - "}\n" - "DBCollection.prototype.ensureIndex = function( keys , options ){\n" - "var name = this._indexSpec( keys, options ).name;\n" - "this._indexCache = this._indexCache || {};\n" - "if ( this._indexCache[ name ] ){\n" - "return false;\n" - "}\n" - "this.createIndex( keys , options );\n" - "if ( this.getDB().getLastError() == \"\" ) {\n" - "this._indexCache[name] = true;\n" - "}\n" - "return true;\n" - "}\n" - "DBCollection.prototype.resetIndexCache = function(){\n" - "this._indexCache = {};\n" - "}\n" - "DBCollection.prototype.reIndex = function(){\n" - "var specs = this.getIndexSpecs();\n" - "this.dropIndexes();\n" - "for ( var i = 0; i < specs.length; ++i ){\n" - "this.ensureIndex( specs[i].key, [ specs[i].unique, specs[i].name ] );\n" - "}\n" - "}\n" - "DBCollection.prototype.dropIndexes = function(){\n" - "this.resetIndexCache();\n" - "var res = this._db.runCommand( { deleteIndexes: this.getName(), index: \"*\" } );\n" - "assert( res , \"no result from dropIndex result\" );\n" - "if ( res.ok )\n" - "return res;\n" - "if ( res.errmsg.match( /not found/ ) )\n" - "return res;\n" - "throw \"error dropping indexes : \" + tojson( res );\n" - "}\n" - "DBCollection.prototype.drop = function(){\n" - "this.resetIndexCache();\n" - "return this._db.runCommand( { drop: this.getName() } );\n" - "}\n" - "DBCollection.prototype.renameCollection = function( newName ){\n" - "return this._db._adminCommand( { renameCollection : this._fullName , to : this._db._name + \".\" + newName } ).ok;\n" - "}\n" - "DBCollection.prototype.validate = function() {\n" - "var res = this._db.runCommand( { validate: this.getName() } );\n" - "res.valid = false;\n" - "if ( res.result ){\n" - "var str = \"-\" + tojson( res.result );\n" - "res.valid = ! ( str.match( /exception/ ) || str.match( /corrupt/ ) );\n" - "var p = /lastExtentSize:(\\d+)/;\n" - "var r = p.exec( str );\n" - "if ( r ){\n" - "res.lastExtentSize = Number( r[1] );\n" - "}\n" - "}\n" - "return res;\n" - "}\n" - "DBCollection.prototype.getIndexes = function(){\n" - "return this.getDB().getCollection( \"system.indexes\" ).find( { ns : this.getFullName() } ).toArray();\n" - "}\n" - "DBCollection.prototype.getIndices = DBCollection.prototype.getIndexes;\n" - "DBCollection.prototype.getIndexSpecs = DBCollection.prototype.getIndexes;\n" - "DBCollection.prototype.getIndexKeys = function(){\n" - "return this.getIndexes().map(\n" - "function(i){\n" - "return i.key;\n" - "}\n" + "print( \"warning: no BinData\" );}\n" + "if ( typeof _threadInject != \"undefined\" ){\n" + "print( \"fork() available!\" );\n" + "Thread = function(){\n" + "this.init.apply( this, arguments );}\n" + "_threadInject( Thread.prototype );\n" + "ScopedThread = function() {\n" + "this.init.apply( this, arguments );}\n" + "ScopedThread.prototype = new Thread( function() {} );\n" + "_scopedThreadInject( ScopedThread.prototype );\n" + "fork = function() {\n" + "var t = new Thread( function() {} );\n" + "Thread.apply( t, arguments );\n" + "return t;}\n" + "EventGenerator = function( me, collectionName, mean ) {\n" + "this.mean = mean;\n" + "this.events = new Array( me, collectionName );}\n" + "EventGenerator.prototype._add = function( action ) {\n" + "this.events.push( [ Random.genExp( this.mean ), action ] );}\n" + "EventGenerator.prototype.addInsert = function( obj ) {\n" + "this._add( \"t.insert( \" + tojson( obj ) + \" )\" );}\n" + "EventGenerator.prototype.addRemove = function( obj ) {\n" + "this._add( \"t.remove( \" + tojson( obj ) + \" )\" );}\n" + "EventGenerator.prototype.addUpdate = function( objOld, objNew ) {\n" + "this._add( \"t.update( \" + tojson( objOld ) + \", \" + tojson( objNew ) + \" )\" );}\n" + "EventGenerator.prototype.addCheckCount = function( count, query, shouldPrint, checkQuery ) {\n" + "query = query || {};\n" + "shouldPrint = shouldPrint || false;\n" + "checkQuery = checkQuery || false;\n" + "var action = \"assert.eq( \" + count + \", t.count( \" + tojson( query ) + \" ) );\"\n" + "if ( checkQuery ) {\n" + "action += \" assert.eq( \" + count + \", t.find( \" + tojson( query ) + \" ).toArray().length );\"}\n" + "if ( shouldPrint ) {\n" + "action += \" print( me + ' ' + \" + count + \" );\";}\n" + "this._add( action );}\n" + "EventGenerator.prototype.getEvents = function() {\n" + "return this.events;}\n" + "EventGenerator.dispatch = function() {\n" + "var args = argumentsToArray( arguments );\n" + "var me = args.shift();\n" + "var collectionName = args.shift();\n" + "var m = new Mongo( db.getMongo().host );\n" + "var t = m.getDB( \"test\" )[ collectionName ];\n" + "for( var i in args ) {\n" + "sleep( args[ i ][ 0 ] );\n" + "eval( args[ i ][ 1 ] );}}\n" + "ParallelTester = function() {\n" + "this.params = new Array();}\n" + "ParallelTester.prototype.add = function( fun, args ) {\n" + "args = args || [];\n" + "args.unshift( fun );\n" + "this.params.push( args );}\n" + "ParallelTester.prototype.run = function( msg, newScopes ) {\n" + "newScopes = newScopes || false;\n" + "assert.parallelTests( this.params, msg, newScopes );}\n" + "ParallelTester.createJstestsLists = function( n ) {\n" + "var params = new Array();\n" + "for( var i = 0; i < n; ++i ) {\n" + "params.push( [] );}\n" + "var makeKeys = function( a ) {\n" + "var ret = {};\n" + "for( var i in a ) {\n" + "ret[ a[ i ] ] = 1;}\n" + "return ret;}\n" + "var skipTests = makeKeys( [ \"jstests/dbadmin.js\",\n" + "\"jstests/repair.js\",\n" + "\"jstests/cursor8.js\",\n" + "\"jstests/recstore.js\",\n" + "\"jstests/extent.js\",\n" + "\"jstests/indexb.js\",\n" + "\"jstests/profile1.js\",\n" + "\"jstests/mr3.js\",\n" + "\"jstests/apitest_db.js\"] );\n" + "var serialTestsArr = [ \"jstests/fsync.js\",\n" + "\"jstests/fsync2.js\" ];\n" + "var serialTests = makeKeys( serialTestsArr );\n" + "params[ 0 ] = serialTestsArr;\n" + "var files = listFiles(\"jstests\");\n" + "files = Array.shuffle( files );\n" + "var i = 0;\n" + "files.forEach(\n" + "function(x) {\n" + "if ( /_runner/.test(x.name) ||\n" + "/_lodeRunner/.test(x.name) ||\n" + "( x.name in skipTests ) ||\n" + "( x.name in serialTests ) ||\n" + "! /\\.js$/.test(x.name ) ){\n" + "print(\" >>>>>>>>>>>>>>> skipping \" + x.name);\n" + "return;}\n" + "params[ i % n ].push( x.name );\n" + "++i;}\n" ");\n" - "}\n" - "DBCollection.prototype.count = function( x ){\n" - "return this.find( x ).count();\n" - "}\n" - "/**\n" - "* Drop free lists. Normally not used.\n" - "* Note this only does the collection itself, not the namespaces of its indexes (see cleanAll).\n" - "*/\n" - "DBCollection.prototype.clean = function() {\n" - "return this._dbCommand( { clean: this.getName() } );\n" - "}\n" - "/**\n" - "* <p>Drop a specified index.</p>\n" - "*\n" - "* <p>\n" - "* Name is the name of the index in the system.indexes name field. (Run db.system.indexes.find() to\n" - "* see example data.)\n" - "* </p>\n" - "*\n" - "* <p>Note : alpha: space is not reclaimed </p>\n" - "* @param {String} name of index to delete.\n" - "* @return A result object. result.ok will be true if successful.\n" - "*/\n" - "DBCollection.prototype.dropIndex = function(index) {\n" - "assert(index , \"need to specify index to dropIndex\" );\n" - "if ( ! isString( index ) && isObject( index ) )\n" - "index = this._genIndexName( index );\n" - "var res = this._dbCommand( { deleteIndexes: this.getName(), index: index } );\n" - "this.resetIndexCache();\n" - "return res;\n" - "}\n" - "DBCollection.prototype.copyTo = function( newName ){\n" - "return this.getDB().eval(\n" - "function( collName , newName ){\n" - "var from = db[collName];\n" - "var to = db[newName];\n" - "to.ensureIndex( { _id : 1 } );\n" - "var count = 0;\n" - "var cursor = from.find();\n" - "while ( cursor.hasNext() ){\n" - "var o = cursor.next();\n" - "count++;\n" - "to.save( o );\n" - "}\n" - "return count;\n" - "} , this.getName() , newName\n" + "params[ 0 ] = Array.shuffle( params[ 0 ] );\n" + "for( var i in params ) {\n" + "params[ i ].unshift( i );}\n" + "return params;}\n" + "ParallelTester.fileTester = function() {\n" + "var args = argumentsToArray( arguments );\n" + "var suite = args.shift();\n" + "args.forEach(\n" + "function( x ) {\n" + "print(\" S\" + suite + \" Test : \" + x + \" ...\");\n" + "var time = Date.timeFunc( function() { load(x); }, 1);\n" + "print(\" S\" + suite + \" Test : \" + x + \" \" + time + \"ms\" );}\n" + ");}\n" + "assert.parallelTests = function( params, msg, newScopes ) {\n" + "newScopes = newScopes || false;\n" + "var wrapper = function( fun, argv ) {\n" + "eval (\n" + "\"var z = function() {\" +\n" + "\"var __parallelTests__fun = \" + fun.toString() + \";\" +\n" + "\"var __parallelTests__argv = \" + tojson( argv ) + \";\" +\n" + "\"var __parallelTests__passed = false;\" +\n" + "\"try {\" +\n" + "\"__parallelTests__fun.apply( 0, __parallelTests__argv );\" +\n" + "\"__parallelTests__passed = true;\" +\n" + "\"} catch ( e ) {\" +\n" + "\"print( e );\" +\n" + "\"}\" +\n" + "\"return __parallelTests__passed;\" +\n" + "\"}\"\n" ");\n" - "}\n" - "DBCollection.prototype.getCollection = function( subName ){\n" - "return this._db.getCollection( this._shortName + \".\" + subName );\n" - "}\n" - "DBCollection.prototype.stats = function(){\n" - "return this._db.runCommand( { collstats : this._shortName } );\n" - "}\n" - "DBCollection.prototype.dataSize = function(){\n" - "return this.stats().size;\n" - "}\n" - "DBCollection.prototype.storageSize = function(){\n" - "return this.stats().storageSize;\n" - "}\n" - "DBCollection.prototype.totalIndexSize = function( verbose ){\n" + "return z;}\n" + "var runners = new Array();\n" + "for( var i in params ) {\n" + "var param = params[ i ];\n" + "var test = param.shift();\n" + "var t;\n" + "if ( newScopes )\n" + "t = new ScopedThread( wrapper( test, param ) );\n" + "else\n" + "t = new Thread( wrapper( test, param ) );\n" + "runners.push( t );}\n" + "runners.forEach( function( x ) { x.start(); } );\n" + "var nFailed = 0;\n" + "runners.forEach( function( x ) { if( !x.returnData() ) { ++nFailed; } } );\n" + "assert.eq( 0, nFailed, msg );}}\n" + "tojson = function( x, indent , nolint ){\n" + "if ( x === null )\n" + "return \"null\";\n" + "if ( x === undefined )\n" + "return \"undefined\";\n" + "if (!indent)\n" + "indent = \"\";\n" + "switch ( typeof x ){\n" + "case \"string\": {\n" + "var s = \"\\\"\";\n" + "for ( var i=0; i<x.length; i++ ){\n" + "if ( x[i] == '\"' ){\n" + "s += \"\\\\\\\"\";}\n" + "else\n" + "s += x[i];}\n" + "return s + \"\\\"\";}\n" + "case \"number\":\n" + "case \"boolean\":\n" + "return \"\" + x;\n" + "case \"object\":{\n" + "var s = tojsonObject( x, indent , nolint );\n" + "if ( ( nolint == null || nolint == true ) && s.length < 80 && ( indent == null || indent.length == 0 ) ){\n" + "s = s.replace( /[\\s\\r\\n ]+/gm , \" \" );}\n" + "return s;}\n" + "case \"function\":\n" + "return x.toString();\n" + "default:\n" + "throw \"tojson can't handle type \" + ( typeof x );}}\n" + "tojsonObject = function( x, indent , nolint ){\n" + "var lineEnding = nolint ? \" \" : \"\\n\";\n" + "var tabSpace = nolint ? \"\" : \"\\t\";\n" + "assert.eq( ( typeof x ) , \"object\" , \"tojsonObject needs object, not [\" + ( typeof x ) + \"]\" );\n" + "if (!indent)\n" + "indent = \"\";\n" + "if ( typeof( x.tojson ) == \"function\" && x.tojson != tojson ) {\n" + "return x.tojson(indent,nolint);}\n" + "if ( typeof( x.constructor.tojson ) == \"function\" && x.constructor.tojson != tojson ) {\n" + "return x.constructor.tojson( x, indent , nolint );}\n" + "if ( x.toString() == \"[object MaxKey]\" )\n" + "return \"{ $maxKey : 1 }\";\n" + "if ( x.toString() == \"[object MinKey]\" )\n" + "return \"{ $minKey : 1 }\";\n" + "var s = \"{\" + lineEnding;\n" + "indent += tabSpace;\n" "var total = 0;\n" - "var mydb = this._db;\n" - "var shortName = this._shortName;\n" - "this.getIndexes().forEach(\n" - "function( spec ){\n" - "var coll = mydb.getCollection( shortName + \".$\" + spec.name );\n" - "var mysize = coll.dataSize();\n" - "total += coll.dataSize();\n" - "if ( verbose ) {\n" - "print( coll + \"\\t\" + mysize );\n" - "}\n" - "}\n" - ");\n" - "return total;\n" - "}\n" - "DBCollection.prototype.totalSize = function(){\n" - "var total = this.storageSize();\n" - "var mydb = this._db;\n" - "var shortName = this._shortName;\n" - "this.getIndexes().forEach(\n" - "function( spec ){\n" - "var coll = mydb.getCollection( shortName + \".$\" + spec.name );\n" - "var mysize = coll.storageSize();\n" - "total += coll.dataSize();\n" - "}\n" - ");\n" - "return total;\n" - "}\n" - "DBCollection.prototype.convertToCapped = function( bytes ){\n" - "if ( ! bytes )\n" - "throw \"have to specify # of bytes\";\n" - "return this._dbCommand( { convertToCapped : this._shortName , size : bytes } )\n" - "}\n" - "DBCollection.prototype.exists = function(){\n" - "return this._db.system.namespaces.findOne( { name : this._fullName } );\n" - "}\n" - "DBCollection.prototype.isCapped = function(){\n" - "var e = this.exists();\n" - "return ( e && e.options && e.options.capped ) ? true : false;\n" - "}\n" - "DBCollection.prototype.distinct = function( keyString ){\n" - "var res = this._dbCommand( { distinct : this._shortName , key : keyString } );\n" - "if ( ! res.ok )\n" - "throw \"distinct failed: \" + tojson( res );\n" - "return res.values;\n" - "}\n" - "DBCollection.prototype.group = function( params ){\n" - "params.ns = this._shortName;\n" - "return this._db.group( params );\n" - "}\n" - "DBCollection.prototype.groupcmd = function( params ){\n" - "params.ns = this._shortName;\n" - "return this._db.groupcmd( params );\n" - "}\n" - "DBCollection.prototype.toString = function(){\n" - "return this.getFullName();\n" - "}\n" - "DBCollection.prototype.shellPrint = DBCollection.prototype.toString;\n" + "for ( var k in x ) total++;\n" + "if ( total == 0 ) {\n" + "s += indent + lineEnding;}\n" + "var keys = x;\n" + "if ( typeof( x._simpleKeys ) == \"function\" )\n" + "keys = x._simpleKeys();\n" + "var num = 1;\n" + "for ( var k in keys ){\n" + "var val = x[k];\n" + "if ( val == DB.prototype || val == DBCollection.prototype )\n" + "continue;\n" + "s += indent + \"\\\"\" + k + \"\\\" : \" + tojson( val, indent , nolint );\n" + "if (num != total) {\n" + "s += \",\";\n" + "num++;}\n" + "s += lineEnding;}\n" + "indent = indent.substring(1);\n" + "return s + indent + \"}\";}\n" + "shellPrint = function( x ){\n" + "it = x;\n" + "if ( x != undefined )\n" + "shellPrintHelper( x );\n" + "if ( db ){\n" + "var e = db.getPrevError();\n" + "if ( e.err ) {\n" + "if( e.nPrev <= 1 )\n" + "print( \"error on last call: \" + tojson( e.err ) );\n" + "else\n" + "print( \"an error \" + tojson(e.err) + \" occurred \" + e.nPrev + \" operations back in the command invocation\" );}\n" + "db.resetError();}}\n" + "printjson = function(x){\n" + "print( tojson( x ) );}\n" + "shellPrintHelper = function( x ){\n" + "if ( typeof( x ) == \"undefined\" ){\n" + "if ( typeof( db ) != \"undefined\" && db.getLastError ){\n" + "var e = db.getLastError();\n" + "if ( e != null )\n" + "print( e );}\n" + "return;}\n" + "if ( x == null ){\n" + "print( \"null\" );\n" + "return;}\n" + "if ( typeof x != \"object\" )\n" + "return print( x );\n" + "var p = x.shellPrint;\n" + "if ( typeof p == \"function\" )\n" + "return x.shellPrint();\n" + "var p = x.tojson;\n" + "if ( typeof p == \"function\" )\n" + "print( x.tojson() );\n" + "else\n" + "print( tojson( x ) );}\n" + "shellHelper = function( command , rest , shouldPrint ){\n" + "command = command.trim();\n" + "var args = rest.trim().replace(/;$/,\"\").split( \"\\s+\" );\n" + "if ( ! shellHelper[command] )\n" + "throw \"no command [\" + command + \"]\";\n" + "var res = shellHelper[command].apply( null , args );\n" + "if ( shouldPrint ){\n" + "shellPrintHelper( res );}\n" + "return res;}\n" + "help = shellHelper.help = function(){\n" + "print( \"HELP\" );\n" + "print( \"\\t\" + \"show dbs show database names\");\n" + "print( \"\\t\" + \"show collections show collections in current database\");\n" + "print( \"\\t\" + \"show users show users in current database\");\n" + "print( \"\\t\" + \"show profile show most recent system.profile entries with time >= 1ms\");\n" + "print( \"\\t\" + \"use <db name> set curent database to <db name>\" );\n" + "print( \"\\t\" + \"db.help() help on DB methods\");\n" + "print( \"\\t\" + \"db.foo.help() help on collection methods\");\n" + "print( \"\\t\" + \"db.foo.find() list objects in collection foo\" );\n" + "print( \"\\t\" + \"db.foo.find( { a : 1 } ) list objects in foo where a == 1\" );\n" + "print( \"\\t\" + \"it result of the last line evaluated; use to further iterate\");}\n" + "shellHelper.use = function( dbname ){\n" + "db = db.getMongo().getDB( dbname );\n" + "print( \"switched to db \" + db.getName() );}\n" + "shellHelper.it = function(){\n" + "if ( typeof( ___it___ ) == \"undefined\" || ___it___ == null ){\n" + "print( \"no cursor\" );\n" + "return;}\n" + "shellPrintHelper( ___it___ );}\n" + "shellHelper.show = function( what ){\n" + "assert( typeof what == \"string\" );\n" + "if( what == \"profile\" ) {\n" + "if( db.system.profile.count() == 0 ) {\n" + "print(\"db.system.profile is empty\");\n" + "print(\"Use db.setProfilingLevel(2) will enable profiling\");\n" + "print(\"Use db.system.profile.find() to show raw profile entries\");}\n" + "else {\n" + "print();\n" + "db.system.profile.find({ millis : { $gt : 0 } }).sort({$natural:-1}).limit(5).forEach( function(x){print(\"\"+x.millis+\"ms \" + String(x.ts).substring(0,24)); print(x.info); print(\"\\n\");} )}\n" + "return \"\";}\n" + "if ( what == \"users\" ){\n" + "db.system.users.find().forEach( printjson );\n" + "return \"\";}\n" + "if ( what == \"collections\" || what == \"tables\" ) {\n" + "db.getCollectionNames().forEach( function(x){print(x)} );\n" + "return \"\";}\n" + "if ( what == \"dbs\" ) {\n" + "db.getMongo().getDBNames().sort().forEach( function(x){print(x)} );\n" + "return \"\";}\n" + "throw \"don't know how to show [\" + what + \"]\";}\n" + "if ( typeof( Map ) == \"undefined\" ){\n" + "Map = function(){\n" + "this._data = {};}}\n" + "Map.hash = function( val ){\n" + "if ( ! val )\n" + "return val;\n" + "switch ( typeof( val ) ){\n" + "case 'string':\n" + "case 'number':\n" + "case 'date':\n" + "return val.toString();\n" + "case 'object':\n" + "case 'array':\n" + "var s = \"\";\n" + "for ( var k in val ){\n" + "s += k + val[k];}\n" + "return s;}\n" + "throw \"can't hash : \" + typeof( val );}\n" + "Map.prototype.put = function( key , value ){\n" + "var o = this._get( key );\n" + "var old = o.value;\n" + "o.value = value;\n" + "return old;}\n" + "Map.prototype.get = function( key ){\n" + "return this._get( key ).value;}\n" + "Map.prototype._get = function( key ){\n" + "var h = Map.hash( key );\n" + "var a = this._data[h];\n" + "if ( ! a ){\n" + "a = [];\n" + "this._data[h] = a;}\n" + "for ( var i=0; i<a.length; i++ ){\n" + "if ( friendlyEqual( key , a[i].key ) ){\n" + "return a[i];}}\n" + "var o = { key : key , value : null };\n" + "a.push( o );\n" + "return o;}\n" + "Map.prototype.values = function(){\n" + "var all = [];\n" + "for ( var k in this._data ){\n" + "this._data[k].forEach( function(z){ all.push( z.value ); } );}\n" + "return all;}\n" + "if ( typeof( gc ) == \"undefined\" ){\n" + "gc = function(){}}\n" + "Math.sigFig = function( x , N ){\n" + "if ( ! N ){\n" + "N = 3;}\n" + "var p = Math.pow( 10, N - Math.ceil( Math.log( Math.abs(x) ) / Math.log( 10 )) );\n" + "return Math.round(x*p)/p;}\n" + "Random = function() {}\n" + "Random.srand = function( s ) { _srand( s ); }\n" + "Random.rand = function() { return _rand(); }\n" + "Random.randInt = function( n ) { return Math.floor( Random.rand() * n ); }\n" + "Random.setRandomSeed = function( s ) {\n" + "s = s || new Date().getTime();\n" + "print( \"setting random seed: \" + s );\n" + "Random.srand( s );}\n" + "Random.genExp = function( mean ) {\n" + "return -Math.log( Random.rand() ) * mean;}\n" + "killWithUris = function( uris ) {\n" + "var inprog = db.currentOp().inprog;\n" + "for( var u in uris ) {\n" + "for ( var i in inprog ) {\n" + "if ( uris[ u ] == inprog[ i ].client ) {\n" + "db.killOp( inprog[ i ].opid );}}}}\n" "if ( typeof DB == \"undefined\" ){\n" "DB = function( mongo , name ){\n" "this._mongo = mongo;\n" - "this._name = name;\n" - "}\n" - "}\n" + "this._name = name;}}\n" "DB.prototype.getMongo = function(){\n" "assert( this._mongo , \"why no mongo!\" );\n" - "return this._mongo;\n" - "}\n" + "return this._mongo;}\n" "DB.prototype.getSisterDB = function( name ){\n" - "return this.getMongo().getDB( name );\n" - "}\n" + "return this.getMongo().getDB( name );}\n" "DB.prototype.getName = function(){\n" - "return this._name;\n" - "}\n" + "return this._name;}\n" + "DB.prototype.stats = function(){\n" + "return this.runCommand( { dbstats : 1 } );}\n" "DB.prototype.getCollection = function( name ){\n" - "return new DBCollection( this._mongo , this , name , this._name + \".\" + name );\n" - "}\n" + "return new DBCollection( this._mongo , this , name , this._name + \".\" + name );}\n" "DB.prototype.commandHelp = function( name ){\n" "var c = {};\n" "c[name] = 1;\n" "c.help = true;\n" - "return this.runCommand( c ).help;\n" - "}\n" + "return this.runCommand( c ).help;}\n" "DB.prototype.runCommand = function( obj ){\n" "if ( typeof( obj ) == \"string\" ){\n" "var n = {};\n" "n[obj] = 1;\n" - "obj = n;\n" - "}\n" - "return this.getCollection( \"$cmd\" ).findOne( obj );\n" - "}\n" + "obj = n;}\n" + "return this.getCollection( \"$cmd\" ).findOne( obj );}\n" "DB.prototype._dbCommand = DB.prototype.runCommand;\n" "DB.prototype._adminCommand = function( obj ){\n" "if ( this._name == \"admin\" )\n" "return this.runCommand( obj );\n" - "return this.getSisterDB( \"admin\" ).runCommand( obj );\n" - "}\n" - "DB.prototype.addUser = function( username , pass ){\n" + "return this.getSisterDB( \"admin\" ).runCommand( obj );}\n" + "DB.prototype.addUser = function( username , pass, readOnly ){\n" + "readOnly = readOnly || false;\n" "var c = this.getCollection( \"system.users\" );\n" "var u = c.findOne( { user : username } ) || { user : username };\n" + "u.readOnly = readOnly;\n" "u.pwd = hex_md5( username + \":mongo:\" + pass );\n" "print( tojson( u ) );\n" - "c.save( u );\n" - "}\n" + "c.save( u );}\n" "DB.prototype.removeUser = function( username ){\n" - "this.getCollection( \"system.users\" ).remove( { user : username } );\n" - "}\n" + "this.getCollection( \"system.users\" ).remove( { user : username } );}\n" + "DB.prototype.__pwHash = function( nonce, username, pass ) {\n" + "return hex_md5( nonce + username + hex_md5( username + \":mongo:\" + pass ) );}\n" "DB.prototype.auth = function( username , pass ){\n" "var n = this.runCommand( { getnonce : 1 } );\n" "var a = this.runCommand(\n" @@ -448,277 +618,127 @@ const char * jsconcatcode = "authenticate : 1 ,\n" "user : username ,\n" "nonce : n.nonce ,\n" - "key : hex_md5( n.nonce + username + hex_md5( username + \":mongo:\" + pass ) )\n" - "}\n" + "key : this.__pwHash( n.nonce, username, pass )}\n" ");\n" - "return a.ok;\n" - "}\n" - "/**\n" - "Create a new collection in the database. Normally, collection creation is automatic. You would\n" - "use this function if you wish to specify special options on creation.\n" - "If the collection already exists, no action occurs.\n" - "<p>Options:</p>\n" - "<ul>\n" - "<li>\n" - "size: desired initial extent size for the collection. Must be <= 1000000000.\n" - "for fixed size (capped) collections, this size is the total/max size of the\n" - "collection.\n" - "</li>\n" - "<li>\n" - "capped: if true, this is a capped collection (where old data rolls out).\n" - "</li>\n" - "<li> max: maximum number of objects if capped (optional).</li>\n" - "</ul>\n" - "<p>Example: </p>\n" - "<code>db.createCollection(\"movies\", { size: 10 * 1024 * 1024, capped:true } );</code>\n" - "* @param {String} name Name of new collection to create\n" - "* @param {Object} options Object with options for call. Options are listed above.\n" - "* @return SOMETHING_FIXME\n" - "*/\n" + "return a.ok;}\n" + "\n" "DB.prototype.createCollection = function(name, opt) {\n" "var options = opt || {};\n" "var cmd = { create: name, capped: options.capped, size: options.size, max: options.max };\n" "var res = this._dbCommand(cmd);\n" - "return res;\n" - "}\n" - "/**\n" - "* Returns the current profiling level of this database\n" - "* @return SOMETHING_FIXME or null on error\n" - "*/\n" + "return res;}\n" + "\n" "DB.prototype.getProfilingLevel = function() {\n" "var res = this._dbCommand( { profile: -1 } );\n" - "return res ? res.was : null;\n" - "}\n" - "/**\n" - "Erase the entire database. (!)\n" - "* @return Object returned has member ok set to true if operation succeeds, false otherwise.\n" - "*/\n" + "return res ? res.was : null;}\n" + "\n" "DB.prototype.dropDatabase = function() {\n" "if ( arguments.length )\n" "throw \"dropDatabase doesn't take arguments\";\n" - "return this._dbCommand( { dropDatabase: 1 } );\n" - "}\n" + "return this._dbCommand( { dropDatabase: 1 } );}\n" "DB.prototype.shutdownServer = function() {\n" "if( \"admin\" != this._name ){\n" - "return \"shutdown command only works with the admin database; try 'use admin'\";\n" - "}\n" + "return \"shutdown command only works with the admin database; try 'use admin'\";}\n" "try {\n" - "this._dbCommand(\"shutdown\");\n" - "throw \"shutdownServer failed\";\n" - "}\n" + "var res = this._dbCommand(\"shutdown\");\n" + "if( res )\n" + "throw \"shutdownServer failed: \" + res.errmsg;\n" + "throw \"shutdownServer failed\";}\n" "catch ( e ){\n" "assert( tojson( e ).indexOf( \"error doing query: failed\" ) >= 0 , \"unexpected error: \" + tojson( e ) );\n" - "print( \"server should be down...\" );\n" - "}\n" - "}\n" - "/**\n" - "Clone database on another server to here.\n" - "<p>\n" - "Generally, you should dropDatabase() first as otherwise the cloned information will MERGE\n" - "into whatever data is already present in this database. (That is however a valid way to use\n" - "clone if you are trying to do something intentionally, such as union three non-overlapping\n" - "databases into one.)\n" - "<p>\n" - "This is a low level administrative function will is not typically used.\n" - "* @param {String} from Where to clone from (dbhostname[:port]). May not be this database\n" - "(self) as you cannot clone to yourself.\n" - "* @return Object returned has member ok set to true if operation succeeds, false otherwise.\n" - "* See also: db.copyDatabase()\n" - "*/\n" + "print( \"server should be down...\" );}}\n" + "\n" "DB.prototype.cloneDatabase = function(from) {\n" "assert( isString(from) && from.length );\n" - "return this._dbCommand( { clone: from } );\n" - "}\n" - "/**\n" - "Clone collection on another server to here.\n" - "<p>\n" - "Generally, you should drop() first as otherwise the cloned information will MERGE\n" - "into whatever data is already present in this collection. (That is however a valid way to use\n" - "clone if you are trying to do something intentionally, such as union three non-overlapping\n" - "collections into one.)\n" - "<p>\n" - "This is a low level administrative function is not typically used.\n" - "* @param {String} from mongod instance from which to clnoe (dbhostname:port). May\n" - "not be this mongod instance, as clone from self is not allowed.\n" - "* @param {String} collection name of collection to clone.\n" - "* @param {Object} query query specifying which elements of collection are to be cloned.\n" - "* @return Object returned has member ok set to true if operation succeeds, false otherwise.\n" - "* See also: db.cloneDatabase()\n" - "*/\n" + "return this._dbCommand( { clone: from } );}\n" + "\n" "DB.prototype.cloneCollection = function(from, collection, query) {\n" "assert( isString(from) && from.length );\n" "assert( isString(collection) && collection.length );\n" "collection = this._name + \".\" + collection;\n" "query = query || {};\n" - "return this._dbCommand( { cloneCollection:collection, from:from, query:query } );\n" - "}\n" - "/**\n" - "Copy database from one server or name to another server or name.\n" - "Generally, you should dropDatabase() first as otherwise the copied information will MERGE\n" - "into whatever data is already present in this database (and you will get duplicate objects\n" - "in collections potentially.)\n" - "For security reasons this function only works when executed on the \"admin\" db. However,\n" - "if you have access to said db, you can copy any database from one place to another.\n" - "This method provides a way to \"rename\" a database by copying it to a new db name and\n" - "location. Additionally, it effectively provides a repair facility.\n" - "* @param {String} fromdb database name from which to copy.\n" - "* @param {String} todb database name to copy to.\n" - "* @param {String} fromhost hostname of the database (and optionally, \":port\") from which to\n" - "copy the data. default if unspecified is to copy from self.\n" - "* @return Object returned has member ok set to true if operation succeeds, false otherwise.\n" - "* See also: db.clone()\n" - "*/\n" - "DB.prototype.copyDatabase = function(fromdb, todb, fromhost) {\n" + "return this._dbCommand( { cloneCollection:collection, from:from, query:query } );}\n" + "\n" + "DB.prototype.copyDatabase = function(fromdb, todb, fromhost, username, password) {\n" "assert( isString(fromdb) && fromdb.length );\n" "assert( isString(todb) && todb.length );\n" "fromhost = fromhost || \"\";\n" - "return this._adminCommand( { copydb:1, fromhost:fromhost, fromdb:fromdb, todb:todb } );\n" - "}\n" - "/**\n" - "Repair database.\n" - "* @return Object returned has member ok set to true if operation succeeds, false otherwise.\n" - "*/\n" + "if ( username && password ) {\n" + "var n = this._adminCommand( { copydbgetnonce : 1, fromhost:fromhost } );\n" + "return this._adminCommand( { copydb:1, fromhost:fromhost, fromdb:fromdb, todb:todb, username:username, nonce:n.nonce, key:this.__pwHash( n.nonce, username, password ) } );\n" + "} else {\n" + "return this._adminCommand( { copydb:1, fromhost:fromhost, fromdb:fromdb, todb:todb } );}}\n" + "\n" "DB.prototype.repairDatabase = function() {\n" - "return this._dbCommand( { repairDatabase: 1 } );\n" - "}\n" + "return this._dbCommand( { repairDatabase: 1 } );}\n" "DB.prototype.help = function() {\n" "print(\"DB methods:\");\n" + "print(\"\\tdb.addUser(username, password[, readOnly=false])\");\n" "print(\"\\tdb.auth(username, password)\");\n" - "print(\"\\tdb.getMongo() get the server connection object\");\n" - "print(\"\\tdb.getMongo().setSlaveOk() allow this connection to read from the nonmaster member of a replica pair\");\n" - "print(\"\\tdb.getSisterDB(name) get the db at the same server as this onew\");\n" - "print(\"\\tdb.getName()\");\n" - "print(\"\\tdb.getCollection(cname) same as db['cname'] or db.cname\");\n" - "print(\"\\tdb.runCommand(cmdObj) run a database command. if cmdObj is a string, turns it into { cmdObj : 1 }\");\n" - "print(\"\\tdb.commandHelp(name) returns the help for the command\");\n" - "print(\"\\tdb.addUser(username, password)\");\n" - "print(\"\\tdb.removeUser(username)\");\n" - "print(\"\\tdb.createCollection(name, { size : ..., capped : ..., max : ... } )\");\n" - "print(\"\\tdb.getReplicationInfo()\");\n" - "print(\"\\tdb.printReplicationInfo()\");\n" - "print(\"\\tdb.printSlaveReplicationInfo()\");\n" - "print(\"\\tdb.getProfilingLevel()\");\n" - "print(\"\\tdb.setProfilingLevel(level) 0=off 1=slow 2=all\");\n" "print(\"\\tdb.cloneDatabase(fromhost)\");\n" + "print(\"\\tdb.commandHelp(name) returns the help for the command\");\n" "print(\"\\tdb.copyDatabase(fromdb, todb, fromhost)\");\n" - "print(\"\\tdb.shutdownServer()\");\n" + "print(\"\\tdb.createCollection(name, { size : ..., capped : ..., max : ... } )\");\n" + "print(\"\\tdb.currentOp() displays the current operation in the db\" );\n" "print(\"\\tdb.dropDatabase()\");\n" - "print(\"\\tdb.repairDatabase()\");\n" "print(\"\\tdb.eval(func, args) run code server-side\");\n" + "print(\"\\tdb.getCollection(cname) same as db['cname'] or db.cname\");\n" + "print(\"\\tdb.getCollectionNames()\");\n" "print(\"\\tdb.getLastError() - just returns the err msg string\");\n" "print(\"\\tdb.getLastErrorObj() - return full status object\");\n" + "print(\"\\tdb.getMongo() get the server connection object\");\n" + "print(\"\\tdb.getMongo().setSlaveOk() allow this connection to read from the nonmaster member of a replica pair\");\n" + "print(\"\\tdb.getName()\");\n" "print(\"\\tdb.getPrevError()\");\n" - "print(\"\\tdb.resetError()\");\n" - "print(\"\\tdb.getCollectionNames()\");\n" - "print(\"\\tdb.currentOp() displays the current operation in the db\" );\n" - "print(\"\\tdb.killOp() kills the current operation in the db\" );\n" + "print(\"\\tdb.getProfilingLevel()\");\n" + "print(\"\\tdb.getReplicationInfo()\");\n" + "print(\"\\tdb.getSisterDB(name) get the db at the same server as this onew\");\n" + "print(\"\\tdb.killOp(opid) kills the current operation in the db\" );\n" "print(\"\\tdb.printCollectionStats()\" );\n" - "print(\"\\tdb.version() current version of the server\" );\n" - "}\n" + "print(\"\\tdb.printReplicationInfo()\");\n" + "print(\"\\tdb.printSlaveReplicationInfo()\");\n" + "print(\"\\tdb.printShardingStatus()\");\n" + "print(\"\\tdb.removeUser(username)\");\n" + "print(\"\\tdb.repairDatabase()\");\n" + "print(\"\\tdb.resetError()\");\n" + "print(\"\\tdb.runCommand(cmdObj) run a database command. if cmdObj is a string, turns it into { cmdObj : 1 }\");\n" + "print(\"\\tdb.setProfilingLevel(level,<slowms>) 0=off 1=slow 2=all\");\n" + "print(\"\\tdb.shutdownServer()\");\n" + "print(\"\\tdb.stats()\");\n" + "print(\"\\tdb.version() current version of the server\" );}\n" "DB.prototype.printCollectionStats = function(){\n" + "var mydb = this;\n" "this.getCollectionNames().forEach(\n" "function(z){\n" "print( z );\n" - "printjson( db[z].stats() );\n" - "print( \"---\" );\n" - "}\n" - ");\n" - "}\n" - "/**\n" - "* <p> Set profiling level for your db. Profiling gathers stats on query performance. </p>\n" - "*\n" - "* <p>Default is off, and resets to off on a database restart -- so if you want it on,\n" - "* turn it on periodically. </p>\n" - "*\n" - "* <p>Levels :</p>\n" - "* <ul>\n" - "* <li>0=off</li>\n" - "* <li>1=log very slow (>100ms) operations</li>\n" - "* <li>2=log all</li>\n" - "* @param {String} level Desired level of profiling\n" - "* @return SOMETHING_FIXME or null on error\n" - "*/\n" - "DB.prototype.setProfilingLevel = function(level) {\n" + "printjson( mydb.getCollection(z).stats() );\n" + "print( \"---\" );}\n" + ");}\n" + "\n" + "DB.prototype.setProfilingLevel = function(level,slowms) {\n" "if (level < 0 || level > 2) {\n" - "throw { dbSetProfilingException : \"input level \" + level + \" is out of range [0..2]\" };\n" - "}\n" - "if (level) {\n" - "this.createCollection(\"system.profile\", { capped: true, size: 128 * 1024 } );\n" - "}\n" - "return this._dbCommand( { profile: level } );\n" - "}\n" - "/**\n" - "* <p> Evaluate a js expression at the database server.</p>\n" - "*\n" - "* <p>Useful if you need to touch a lot of data lightly; in such a scenario\n" - "* the network transfer of the data could be a bottleneck. A good example\n" - "* is \"select count(*)\" -- can be done server side via this mechanism.\n" - "* </p>\n" - "*\n" - "* <p>\n" - "* If the eval fails, an exception is thrown of the form:\n" - "* </p>\n" - "* <code>{ dbEvalException: { retval: functionReturnValue, ok: num [, errno: num] [, errmsg: str] } }</code>\n" - "*\n" - "* <p>Example: </p>\n" - "* <code>print( \"mycount: \" + db.eval( function(){db.mycoll.find({},{_id:ObjId()}).length();} );</code>\n" - "*\n" - "* @param {Function} jsfunction Javascript function to run on server. Note this it not a closure, but rather just \"code\".\n" - "* @return result of your function, or null if error\n" - "*\n" - "*/\n" + "throw { dbSetProfilingException : \"input level \" + level + \" is out of range [0..2]\" };}\n" + "var cmd = { profile: level };\n" + "if ( slowms )\n" + "cmd[\"slowms\"] = slowms;\n" + "return this._dbCommand( cmd );}\n" + "\n" "DB.prototype.eval = function(jsfunction) {\n" "var cmd = { $eval : jsfunction };\n" "if ( arguments.length > 1 ) {\n" - "cmd.args = argumentsToArray( arguments ).slice(1);\n" - "}\n" + "cmd.args = argumentsToArray( arguments ).slice(1);}\n" "var res = this._dbCommand( cmd );\n" "if (!res.ok)\n" "throw tojson( res );\n" - "return res.retval;\n" - "}\n" + "return res.retval;}\n" "DB.prototype.dbEval = DB.prototype.eval;\n" - "/**\n" - "*\n" - "* <p>\n" - "* Similar to SQL group by. For example: </p>\n" - "*\n" - "* <code>select a,b,sum(c) csum from coll where active=1 group by a,b</code>\n" - "*\n" - "* <p>\n" - "* corresponds to the following in 10gen:\n" - "* </p>\n" - "*\n" - "* <code>\n" - "db.group(\n" - "{\n" - "ns: \"coll\",\n" - "key: { a:true, b:true },\n" - "cond: { active:1 },\n" - "reduce: function(obj,prev) { prev.csum += obj.c; } ,\n" - "initial: { csum: 0 }\n" - "});\n" - "</code>\n" - "*\n" - "*\n" - "* <p>\n" - "* An array of grouped items is returned. The array must fit in RAM, thus this function is not\n" - "* suitable when the return set is extremely large.\n" - "* </p>\n" - "* <p>\n" - "* To order the grouped data, simply sort it client side upon return.\n" - "* <p>\n" - "Defaults\n" - "cond may be null if you want to run against all rows in the collection\n" - "keyf is a function which takes an object and returns the desired key. set either key or keyf (not both).\n" - "* </p>\n" - "*/\n" + "\n" "DB.prototype.groupeval = function(parmsObj) {\n" "var groupFunction = function() {\n" "var parms = args[0];\n" "var c = db[parms.ns].find(parms.cond||{});\n" "var map = new Map();\n" - "var pks = parms.key ? parms.key.keySet() : null;\n" + "var pks = parms.key ? Object.keySet( parms.key ) : null;\n" "var pkl = pks ? pks.length : 0;\n" "var key = {};\n" "while( c.hasNext() ) {\n" @@ -726,114 +746,82 @@ const char * jsconcatcode = "if ( pks ) {\n" "for( var i=0; i<pkl; i++ ){\n" "var k = pks[i];\n" - "key[k] = obj[k];\n" - "}\n" - "}\n" + "key[k] = obj[k];}}\n" "else {\n" - "key = parms.$keyf(obj);\n" - "}\n" + "key = parms.$keyf(obj);}\n" "var aggObj = map.get(key);\n" "if( aggObj == null ) {\n" "var newObj = Object.extend({}, key);\n" "aggObj = Object.extend(newObj, parms.initial)\n" - "map.put( key , aggObj );\n" - "}\n" - "parms.$reduce(obj, aggObj);\n" - "}\n" - "return map.values();\n" - "}\n" - "return this.eval(groupFunction, this._groupFixParms( parmsObj ));\n" - "}\n" + "map.put( key , aggObj );}\n" + "parms.$reduce(obj, aggObj);}\n" + "return map.values();}\n" + "return this.eval(groupFunction, this._groupFixParms( parmsObj ));}\n" "DB.prototype.groupcmd = function( parmsObj ){\n" "var ret = this.runCommand( { \"group\" : this._groupFixParms( parmsObj ) } );\n" "if ( ! ret.ok ){\n" - "throw \"group command failed: \" + tojson( ret );\n" - "}\n" - "return ret.retval;\n" - "}\n" + "throw \"group command failed: \" + tojson( ret );}\n" + "return ret.retval;}\n" "DB.prototype.group = DB.prototype.groupcmd;\n" "DB.prototype._groupFixParms = function( parmsObj ){\n" "var parms = Object.extend({}, parmsObj);\n" "if( parms.reduce ) {\n" "parms.$reduce = parms.reduce;\n" - "delete parms.reduce;\n" - "}\n" + "delete parms.reduce;}\n" "if( parms.keyf ) {\n" "parms.$keyf = parms.keyf;\n" - "delete parms.keyf;\n" - "}\n" - "return parms;\n" - "}\n" + "delete parms.keyf;}\n" + "return parms;}\n" "DB.prototype.resetError = function(){\n" - "return this.runCommand( { reseterror : 1 } );\n" - "}\n" + "return this.runCommand( { reseterror : 1 } );}\n" "DB.prototype.forceError = function(){\n" - "return this.runCommand( { forceerror : 1 } );\n" - "}\n" + "return this.runCommand( { forceerror : 1 } );}\n" "DB.prototype.getLastError = function(){\n" "var res = this.runCommand( { getlasterror : 1 } );\n" "if ( ! res.ok )\n" "throw \"getlasterror failed: \" + tojson( res );\n" - "return res.err;\n" - "}\n" + "return res.err;}\n" "DB.prototype.getLastErrorObj = function(){\n" "var res = this.runCommand( { getlasterror : 1 } );\n" "if ( ! res.ok )\n" "throw \"getlasterror failed: \" + tojson( res );\n" - "return res;\n" - "}\n" + "return res;}\n" + "DB.prototype.getLastErrorCmd = DB.prototype.getLastErrorObj;\n" "/* Return the last error which has occurred, even if not the very last error.\n" "Returns:\n" "{ err : <error message>, nPrev : <how_many_ops_back_occurred>, ok : 1 }\n" "result.err will be null if no error has occurred.\n" "*/\n" "DB.prototype.getPrevError = function(){\n" - "return this.runCommand( { getpreverror : 1 } );\n" - "}\n" + "return this.runCommand( { getpreverror : 1 } );}\n" "DB.prototype.getCollectionNames = function(){\n" "var all = [];\n" "var nsLength = this._name.length + 1;\n" "this.getCollection( \"system.namespaces\" ).find().sort({name:1}).forEach(\n" "function(z){\n" "var name = z.name;\n" - "if ( name.indexOf( \"$\" ) >= 0 )\n" + "if ( name.indexOf( \"$\" ) >= 0 && name != \"local.oplog.$main\" )\n" "return;\n" - "all.push( name.substring( nsLength ) );\n" - "}\n" + "all.push( name.substring( nsLength ) );}\n" ");\n" - "return all;\n" - "}\n" + "return all;}\n" "DB.prototype.tojson = function(){\n" - "return this._name;\n" - "}\n" + "return this._name;}\n" "DB.prototype.toString = function(){\n" - "return this._name;\n" - "}\n" + "return this._name;}\n" "DB.prototype.currentOp = function(){\n" - "return db.$cmd.sys.inprog.findOne();\n" - "}\n" + "return db.$cmd.sys.inprog.findOne();}\n" "DB.prototype.currentOP = DB.prototype.currentOp;\n" - "DB.prototype.killOp = function(){\n" - "return db.$cmd.sys.killop.findOne();\n" - "}\n" + "DB.prototype.killOp = function(op) {\n" + "if( !op )\n" + "throw \"no opNum to kill specified\";\n" + "return db.$cmd.sys.killop.findOne({'op':op});}\n" "DB.prototype.killOP = DB.prototype.killOp;\n" - "/**\n" - "Get a replication log information summary.\n" - "<p>\n" - "This command is for the database/cloud administer and not applicable to most databases.\n" - "It is only used with the local database. One might invoke from the JS shell:\n" - "<pre>\n" - "use local\n" - "db.getReplicationInfo();\n" - "</pre>\n" - "It is assumed that this database is a replication master -- the information returned is\n" - "about the operation log stored at local.oplog.$main on the replication master. (It also\n" - "works on a machine in a replica pair: for replica pairs, both machines are \"masters\" from\n" - "an internal database perspective.\n" - "<p>\n" - "* @return Object timeSpan: time span of the oplog from start to end if slave is more out\n" - "* of date than that, it can't recover without a complete resync\n" - "*/\n" + "DB.tsToSeconds = function(x){\n" + "if ( x.t && x.i )\n" + "return x.t / 1000;\n" + "return x / 4294967296;}\n" + "\n" "DB.prototype.getReplicationInfo = function() {\n" "var db = this.getSisterDB(\"local\");\n" "var result = { };\n" @@ -842,81 +830,66 @@ const char * jsconcatcode = "result.logSizeMB = ol.options.size / 1000 / 1000;\n" "} else {\n" "result.errmsg = \"local.oplog.$main, or its options, not found in system.namespaces collection (not --master?)\";\n" - "return result;\n" - "}\n" + "return result;}\n" "var firstc = db.oplog.$main.find().sort({$natural:1}).limit(1);\n" "var lastc = db.oplog.$main.find().sort({$natural:-1}).limit(1);\n" "if( !firstc.hasNext() || !lastc.hasNext() ) {\n" "result.errmsg = \"objects not found in local.oplog.$main -- is this a new and empty db instance?\";\n" "result.oplogMainRowCount = db.oplog.$main.count();\n" - "return result;\n" - "}\n" + "return result;}\n" "var first = firstc.next();\n" "var last = lastc.next();\n" "{\n" "var tfirst = first.ts;\n" "var tlast = last.ts;\n" "if( tfirst && tlast ) {\n" - "tfirst = tfirst / 4294967296;\n" - "tlast = tlast / 4294967296;\n" + "tfirst = DB.tsToSeconds( tfirst );\n" + "tlast = DB.tsToSeconds( tlast );\n" "result.timeDiff = tlast - tfirst;\n" "result.timeDiffHours = Math.round(result.timeDiff / 36)/100;\n" "result.tFirst = (new Date(tfirst*1000)).toString();\n" "result.tLast = (new Date(tlast*1000)).toString();\n" - "result.now = Date();\n" - "}\n" + "result.now = Date();}\n" "else {\n" - "result.errmsg = \"ts element not found in oplog objects\";\n" - "}\n" - "}\n" - "return result;\n" - "}\n" + "result.errmsg = \"ts element not found in oplog objects\";}}\n" + "return result;}\n" "DB.prototype.printReplicationInfo = function() {\n" "var result = this.getReplicationInfo();\n" "if( result.errmsg ) {\n" "print(tojson(result));\n" - "return;\n" - "}\n" + "return;}\n" "print(\"configured oplog size: \" + result.logSizeMB + \"MB\");\n" "print(\"log length start to end: \" + result.timeDiff + \"secs (\" + result.timeDiffHours + \"hrs)\");\n" "print(\"oplog first event time: \" + result.tFirst);\n" "print(\"oplog last event time: \" + result.tLast);\n" - "print(\"now: \" + result.now);\n" - "}\n" + "print(\"now: \" + result.now);}\n" "DB.prototype.printSlaveReplicationInfo = function() {\n" "function g(x) {\n" "print(\"source: \" + x.host);\n" - "var st = new Date(x.syncedTo/4294967296*1000);\n" + "var st = new Date( DB.tsToSeconds( x.syncedTo ) * 1000 );\n" "var now = new Date();\n" "print(\"syncedTo: \" + st.toString() );\n" "var ago = (now-st)/1000;\n" "var hrs = Math.round(ago/36)/100;\n" - "print(\" = \" + Math.round(ago) + \"secs ago (\" + hrs + \"hrs)\");\n" - "}\n" + "print(\" = \" + Math.round(ago) + \"secs ago (\" + hrs + \"hrs)\");}\n" "var L = this.getSisterDB(\"local\");\n" "if( L.sources.count() == 0 ) {\n" "print(\"local.sources is empty; is this db a --slave?\");\n" - "return;\n" - "}\n" - "L.sources.find().forEach(g);\n" - "}\n" + "return;}\n" + "L.sources.find().forEach(g);}\n" "DB.prototype.serverBuildInfo = function(){\n" - "return this._adminCommand( \"buildinfo\" );\n" - "}\n" + "return this._adminCommand( \"buildinfo\" );}\n" "DB.prototype.serverStatus = function(){\n" - "return this._adminCommand( \"serverStatus\" );\n" - "}\n" + "return this._adminCommand( \"serverStatus\" );}\n" "DB.prototype.version = function(){\n" - "return this.serverBuildInfo().version;\n" - "}\n" + "return this.serverBuildInfo().version;}\n" + "DB.prototype.printShardingStatus = function(){\n" + "printShardingStatus( this.getSisterDB( \"config\" ) );}\n" "if ( typeof Mongo == \"undefined\" ){\n" "Mongo = function( host ){\n" - "this.init( host );\n" - "}\n" - "}\n" + "this.init( host );}}\n" "if ( ! Mongo.prototype ){\n" - "throw \"Mongo.prototype not defined\";\n" - "}\n" + "throw \"Mongo.prototype not defined\";}\n" "if ( ! Mongo.prototype.find )\n" "Mongo.prototype.find = function( ns , query , fields , limit , skip ){ throw \"find not implemented\"; }\n" "if ( ! Mongo.prototype.insert )\n" @@ -926,31 +899,31 @@ const char * jsconcatcode = "if ( ! Mongo.prototype.update )\n" "Mongo.prototype.update = function( ns , query , obj , upsert ){ throw \"update not implemented;\" }\n" "if ( typeof mongoInject == \"function\" ){\n" - "mongoInject( Mongo.prototype );\n" - "}\n" + "mongoInject( Mongo.prototype );}\n" "Mongo.prototype.setSlaveOk = function() {\n" - "this.slaveOk = true;\n" - "}\n" + "this.slaveOk = true;}\n" "Mongo.prototype.getDB = function( name ){\n" - "return new DB( this , name );\n" - "}\n" + "return new DB( this , name );}\n" "Mongo.prototype.getDBs = function(){\n" "var res = this.getDB( \"admin\" ).runCommand( { \"listDatabases\" : 1 } );\n" - "assert( res.ok == 1 , \"listDatabases failed\" );\n" - "return res;\n" - "}\n" + "assert( res.ok == 1 , \"listDatabases failed:\" + tojson( res ) );\n" + "return res;}\n" "Mongo.prototype.getDBNames = function(){\n" "return this.getDBs().databases.map(\n" "function(z){\n" - "return z.name;\n" - "}\n" - ");\n" - "}\n" + "return z.name;}\n" + ");}\n" + "Mongo.prototype.getCollection = function(ns){\n" + "var idx = ns.indexOf( \".\" );\n" + "if ( idx < 0 )\n" + "throw \"need . in ns\";\n" + "var db = ns.substring( 0 , idx );\n" + "var c = ns.substring( idx + 1 );\n" + "return this.getDB( db ).getCollection( c );}\n" "Mongo.prototype.toString = function(){\n" - "return \"mongo connection to \" + this.host;\n" - "}\n" + "return \"mongo connection to \" + this.host;}\n" "connect = function( url , user , pass ){\n" - "print( \"connecting to: \" + url )\n" + "chatty( \"connecting to: \" + url )\n" "if ( user && ! pass )\n" "throw \"you specified a user and not a password. either you need a password, or you're using the old connect api\";\n" "var idx = url.indexOf( \"/\" );\n" @@ -961,33 +934,33 @@ const char * jsconcatcode = "db = new Mongo( url.substring( 0 , idx ) ).getDB( url.substring( idx + 1 ) );\n" "if ( user && pass ){\n" "if ( ! db.auth( user , pass ) ){\n" - "throw \"couldn't login\";\n" - "}\n" - "}\n" - "return db;\n" - "}\n" + "throw \"couldn't login\";}}\n" + "return db;}\n" "MR = {};\n" "MR.init = function(){\n" "$max = 0;\n" "$arr = [];\n" "emit = MR.emit;\n" - "gc();\n" - "}\n" + "$numEmits = 0;\n" + "$numReduces = 0;\n" + "$numReducesToDB = 0;\n" + "gc();}\n" "MR.cleanup = function(){\n" "MR.init();\n" - "gc();\n" - "}\n" + "gc();}\n" "MR.emit = function(k,v){\n" - "var num = get_num( k );\n" + "$numEmits++;\n" + "var num = nativeHelper.apply( get_num_ , [ k ] );\n" "var data = $arr[num];\n" "if ( ! data ){\n" - "data = { key : k , values : [] };\n" - "$arr[num] = data;\n" - "}\n" - "data.values.push( v );\n" - "$max = Math.max( $max , data.values.length );\n" - "}\n" + "data = { key : k , values : new Array(1000) , count : 0 };\n" + "$arr[num] = data;}\n" + "data.values[data.count++] = v;\n" + "$max = Math.max( $max , data.count );}\n" "MR.doReduce = function( useDB ){\n" + "$numReduces++;\n" + "if ( useDB )\n" + "$numReducesToDB++;\n" "$max = 0;\n" "for ( var i=0; i<$arr.length; i++){\n" "var data = $arr[i];\n" @@ -996,44 +969,40 @@ const char * jsconcatcode = "if ( useDB ){\n" "var x = tempcoll.findOne( { _id : data.key } );\n" "if ( x ){\n" - "data.values.push( x.value );\n" - "}\n" - "}\n" - "var r = $reduce( data.key , data.values );\n" - "if ( r.length && r[0] ){\n" + "data.values[data.count++] = x.value;}}\n" + "var r = $reduce( data.key , data.values.slice( 0 , data.count ) );\n" + "if ( r && r.length && r[0] ){\n" "data.values = r;\n" - "}\n" + "data.count = r.length;}\n" "else{\n" - "data.values = [ r ];\n" - "}\n" - "$max = Math.max( $max , data.values.length );\n" + "data.values[0] = r;\n" + "data.count = 1;}\n" + "$max = Math.max( $max , data.count );\n" "if ( useDB ){\n" - "if ( data.values.length == 1 ){\n" - "tempcoll.save( { _id : data.key , value : data.values[0] } );\n" - "}\n" + "if ( data.count == 1 ){\n" + "tempcoll.save( { _id : data.key , value : data.values[0] } );}\n" "else {\n" - "tempcoll.save( { _id : data.key , value : data.values } );\n" - "}\n" - "}\n" - "}\n" - "}\n" + "tempcoll.save( { _id : data.key , value : data.values.slice( 0 , data.count ) } );}}}}\n" "MR.check = function(){\n" "if ( $max < 2000 && $arr.length < 1000 ){\n" - "return 0;\n" - "}\n" + "return 0;}\n" "MR.doReduce();\n" "if ( $max < 2000 && $arr.length < 1000 ){\n" - "return 1;\n" - "}\n" + "return 1;}\n" "MR.doReduce( true );\n" "$arr = [];\n" "$max = 0;\n" "reset_num();\n" "gc();\n" - "return 2;\n" - "}\n" + "return 2;}\n" + "MR.finalize = function(){\n" + "tempcoll.find().forEach(\n" + "function(z){\n" + "z.value = $finalize( z._id , z.value );\n" + "tempcoll.save( z );}\n" + ");}\n" "if ( typeof DBQuery == \"undefined\" ){\n" - "DBQuery = function( mongo , db , collection , ns , query , fields , limit , skip ){\n" + "DBQuery = function( mongo , db , collection , ns , query , fields , limit , skip , batchSize ){\n" "this._mongo = mongo;\n" "this._db = db;\n" "this._collection = collection;\n" @@ -1042,65 +1011,60 @@ const char * jsconcatcode = "this._fields = fields;\n" "this._limit = limit || 0;\n" "this._skip = skip || 0;\n" + "this._batchSize = batchSize || 0;\n" "this._cursor = null;\n" "this._numReturned = 0;\n" - "this._special = false;\n" - "}\n" - "print( \"DBQuery probably won't have array access \" );\n" - "}\n" + "this._special = false;}\n" + "print( \"DBQuery probably won't have array access \" );}\n" "DBQuery.prototype.help = function(){\n" "print( \"DBQuery help\" );\n" "print( \"\\t.sort( {...} )\" )\n" "print( \"\\t.limit( n )\" )\n" "print( \"\\t.skip( n )\" )\n" - "print( \"\\t.count()\" )\n" + "print( \"\\t.count() - total # of objects matching query, ignores skip,limit\" )\n" + "print( \"\\t.size() - total # of objects cursor would return skip,limit effect this\" )\n" "print( \"\\t.explain()\" )\n" "print( \"\\t.forEach( func )\" )\n" - "print( \"\\t.map( func )\" )\n" - "}\n" + "print( \"\\t.map( func )\" )}\n" "DBQuery.prototype.clone = function(){\n" "var q = new DBQuery( this._mongo , this._db , this._collection , this._ns ,\n" "this._query , this._fields ,\n" - "this._limit , this._skip );\n" + "this._limit , this._skip , this._batchSize );\n" "q._special = this._special;\n" - "return q;\n" - "}\n" + "return q;}\n" "DBQuery.prototype._ensureSpecial = function(){\n" "if ( this._special )\n" "return;\n" "var n = { query : this._query };\n" "this._query = n;\n" - "this._special = true;\n" - "}\n" + "this._special = true;}\n" "DBQuery.prototype._checkModify = function(){\n" "if ( this._cursor )\n" - "throw \"query already executed\";\n" - "}\n" + "throw \"query already executed\";}\n" "DBQuery.prototype._exec = function(){\n" "if ( ! this._cursor ){\n" "assert.eq( 0 , this._numReturned );\n" - "this._cursor = this._mongo.find( this._ns , this._query , this._fields , this._limit , this._skip );\n" - "this._cursorSeen = 0;\n" - "}\n" - "return this._cursor;\n" - "}\n" + "this._cursor = this._mongo.find( this._ns , this._query , this._fields , this._limit , this._skip , this._batchSize );\n" + "this._cursorSeen = 0;}\n" + "return this._cursor;}\n" "DBQuery.prototype.limit = function( limit ){\n" "this._checkModify();\n" "this._limit = limit;\n" - "return this;\n" - "}\n" + "return this;}\n" + "DBQuery.prototype.batchSize = function( batchSize ){\n" + "this._checkModify();\n" + "this._batchSize = batchSize;\n" + "return this;}\n" "DBQuery.prototype.skip = function( skip ){\n" "this._checkModify();\n" "this._skip = skip;\n" - "return this;\n" - "}\n" + "return this;}\n" "DBQuery.prototype.hasNext = function(){\n" "this._exec();\n" "if ( this._limit > 0 && this._cursorSeen >= this._limit )\n" "return false;\n" "var o = this._cursor.hasNext();\n" - "return o;\n" - "}\n" + "return o;}\n" "DBQuery.prototype.next = function(){\n" "this._exec();\n" "var o = this._cursor.hasNext();\n" @@ -1112,8 +1076,7 @@ const char * jsconcatcode = "if ( ret.$err && this._numReturned == 0 && ! this.hasNext() )\n" "throw \"error: \" + tojson( ret );\n" "this._numReturned++;\n" - "return ret;\n" - "}\n" + "return ret;}\n" "DBQuery.prototype.toArray = function(){\n" "if ( this._arr )\n" "return this._arr;\n" @@ -1121,886 +1084,446 @@ const char * jsconcatcode = "while ( this.hasNext() )\n" "a.push( this.next() );\n" "this._arr = a;\n" - "return a;\n" - "}\n" - "DBQuery.prototype.count = function(){\n" + "return a;}\n" + "DBQuery.prototype.count = function( applySkipLimit ){\n" "var cmd = { count: this._collection.getName() };\n" "if ( this._query ){\n" "if ( this._special )\n" "cmd.query = this._query.query;\n" "else\n" - "cmd.query = this._query;\n" - "}\n" + "cmd.query = this._query;}\n" "cmd.fields = this._fields || {};\n" + "if ( applySkipLimit ){\n" + "if ( this._limit )\n" + "cmd.limit = this._limit;\n" + "if ( this._skip )\n" + "cmd.skip = this._skip;}\n" "var res = this._db.runCommand( cmd );\n" "if( res && res.n != null ) return res.n;\n" - "throw \"count failed: \" + tojson( res );\n" - "}\n" + "throw \"count failed: \" + tojson( res );}\n" + "DBQuery.prototype.size = function(){\n" + "return this.count( true );}\n" "DBQuery.prototype.countReturn = function(){\n" "var c = this.count();\n" "if ( this._skip )\n" "c = c - this._skip;\n" "if ( this._limit > 0 && this._limit < c )\n" "return this._limit;\n" - "return c;\n" - "}\n" - "/**\n" - "* iterative count - only for testing\n" - "*/\n" + "return c;}\n" + "\n" "DBQuery.prototype.itcount = function(){\n" "var num = 0;\n" "while ( this.hasNext() ){\n" "num++;\n" - "this.next();\n" - "}\n" - "return num;\n" - "}\n" + "this.next();}\n" + "return num;}\n" "DBQuery.prototype.length = function(){\n" - "return this.toArray().length;\n" - "}\n" - "DBQuery.prototype.sort = function( sortBy ){\n" + "return this.toArray().length;}\n" + "DBQuery.prototype._addSpecial = function( name , value ){\n" "this._ensureSpecial();\n" - "this._query.orderby = sortBy;\n" - "return this;\n" - "}\n" + "this._query[name] = value;\n" + "return this;}\n" + "DBQuery.prototype.sort = function( sortBy ){\n" + "return this._addSpecial( \"orderby\" , sortBy );}\n" "DBQuery.prototype.hint = function( hint ){\n" - "this._ensureSpecial();\n" - "this._query[\"$hint\"] = hint;\n" - "return this;\n" - "}\n" + "return this._addSpecial( \"$hint\" , hint );}\n" "DBQuery.prototype.min = function( min ) {\n" - "this._ensureSpecial();\n" - "this._query[\"$min\"] = min;\n" - "return this;\n" - "}\n" + "return this._addSpecial( \"$min\" , min );}\n" "DBQuery.prototype.max = function( max ) {\n" - "this._ensureSpecial();\n" - "this._query[\"$max\"] = max;\n" - "return this;\n" - "}\n" + "return this._addSpecial( \"$max\" , max );}\n" "DBQuery.prototype.forEach = function( func ){\n" "while ( this.hasNext() )\n" - "func( this.next() );\n" - "}\n" + "func( this.next() );}\n" "DBQuery.prototype.map = function( func ){\n" "var a = [];\n" "while ( this.hasNext() )\n" "a.push( func( this.next() ) );\n" - "return a;\n" - "}\n" + "return a;}\n" "DBQuery.prototype.arrayAccess = function( idx ){\n" - "return this.toArray()[idx];\n" - "}\n" + "return this.toArray()[idx];}\n" "DBQuery.prototype.explain = function(){\n" "var n = this.clone();\n" "n._ensureSpecial();\n" "n._query.$explain = true;\n" "n._limit = n._limit * -1;\n" - "return n.next();\n" - "}\n" + "return n.next();}\n" "DBQuery.prototype.snapshot = function(){\n" "this._ensureSpecial();\n" "this._query.$snapshot = true;\n" - "return this;\n" - "}\n" + "return this;}\n" "DBQuery.prototype.shellPrint = function(){\n" "try {\n" "var n = 0;\n" "while ( this.hasNext() && n < 20 ){\n" - "var s = tojson( this.next() );\n" + "var s = tojson( this.next() , \"\" , true );\n" "print( s );\n" - "n++;\n" - "}\n" + "n++;}\n" "if ( this.hasNext() ){\n" "print( \"has more\" );\n" - "___it___ = this;\n" - "}\n" + "___it___ = this;}\n" "else {\n" - "___it___ = null;\n" - "}\n" - "}\n" + "___it___ = null;}}\n" "catch ( e ){\n" - "print( e );\n" - "}\n" - "}\n" + "print( e );}}\n" "DBQuery.prototype.toString = function(){\n" - "return \"DBQuery: \" + this._ns + \" -> \" + tojson( this.query );\n" - "}\n" - "_parsePath = function() {\n" - "var dbpath = \"\";\n" - "for( var i = 0; i < arguments.length; ++i )\n" - "if ( arguments[ i ] == \"--dbpath\" )\n" - "dbpath = arguments[ i + 1 ];\n" - "if ( dbpath == \"\" )\n" - "throw \"No dbpath specified\";\n" - "return dbpath;\n" - "}\n" - "_parsePort = function() {\n" - "var port = \"\";\n" - "for( var i = 0; i < arguments.length; ++i )\n" - "if ( arguments[ i ] == \"--port\" )\n" - "port = arguments[ i + 1 ];\n" - "if ( port == \"\" )\n" - "throw \"No port specified\";\n" - "return port;\n" - "}\n" - "createMongoArgs = function( binaryName , args ){\n" - "var fullArgs = [ binaryName ];\n" - "if ( args.length == 1 && isObject( args[0] ) ){\n" - "var o = args[0];\n" + "return \"DBQuery: \" + this._ns + \" -> \" + tojson( this.query );}\n" + "if ( ( typeof DBCollection ) == \"undefined\" ){\n" + "DBCollection = function( mongo , db , shortName , fullName ){\n" + "this._mongo = mongo;\n" + "this._db = db;\n" + "this._shortName = shortName;\n" + "this._fullName = fullName;\n" + "this.verify();}}\n" + "DBCollection.prototype.verify = function(){\n" + "assert( this._fullName , \"no fullName\" );\n" + "assert( this._shortName , \"no shortName\" );\n" + "assert( this._db , \"no db\" );\n" + "assert.eq( this._fullName , this._db._name + \".\" + this._shortName , \"name mismatch\" );\n" + "assert( this._mongo , \"no mongo in DBCollection\" );}\n" + "DBCollection.prototype.getName = function(){\n" + "return this._shortName;}\n" + "DBCollection.prototype.help = function() {\n" + "print(\"DBCollection help\");\n" + "print(\"\\tdb.foo.count()\");\n" + "print(\"\\tdb.foo.dataSize()\");\n" + "print(\"\\tdb.foo.distinct( key ) - eg. db.foo.distinct( 'x' )\");\n" + "print(\"\\tdb.foo.drop() drop the collection\");\n" + "print(\"\\tdb.foo.dropIndex(name)\");\n" + "print(\"\\tdb.foo.dropIndexes()\");\n" + "print(\"\\tdb.foo.ensureIndex(keypattern,options) - options should be an object with these possible fields: name, unique, dropDups\");\n" + "print(\"\\tdb.foo.reIndex()\");\n" + "print(\"\\tdb.foo.find( [query] , [fields]) - first parameter is an optional query filter. second parameter is optional set of fields to return.\");\n" + "print(\"\\t e.g. db.foo.find( { x : 77 } , { name : 1 , x : 1 } )\");\n" + "print(\"\\tdb.foo.find(...).count()\");\n" + "print(\"\\tdb.foo.find(...).limit(n)\");\n" + "print(\"\\tdb.foo.find(...).skip(n)\");\n" + "print(\"\\tdb.foo.find(...).sort(...)\");\n" + "print(\"\\tdb.foo.findOne([query])\");\n" + "print(\"\\tdb.foo.findAndModify( { update : ... , remove : bool [, query: {}, sort: {}, 'new': false] } )\");\n" + "print(\"\\tdb.foo.getDB() get DB object associated with collection\");\n" + "print(\"\\tdb.foo.getIndexes()\");\n" + "print(\"\\tdb.foo.group( { key : ..., initial: ..., reduce : ...[, cond: ...] } )\");\n" + "print(\"\\tdb.foo.mapReduce( mapFunction , reduceFunction , <optional params> )\");\n" + "print(\"\\tdb.foo.remove(query)\");\n" + "print(\"\\tdb.foo.renameCollection( newName , <dropTarget> ) renames the collection.\");\n" + "print(\"\\tdb.foo.runCommand( name , <options> ) runs a db command with the given name where the 1st param is the colleciton name\" );\n" + "print(\"\\tdb.foo.save(obj)\");\n" + "print(\"\\tdb.foo.stats()\");\n" + "print(\"\\tdb.foo.storageSize() - includes free space allocated to this collection\");\n" + "print(\"\\tdb.foo.totalIndexSize() - size in bytes of all the indexes\");\n" + "print(\"\\tdb.foo.totalSize() - storage allocated for all data and indexes\");\n" + "print(\"\\tdb.foo.update(query, object[, upsert_bool, multi_bool])\");\n" + "print(\"\\tdb.foo.validate() - SLOW\");\n" + "print(\"\\tdb.foo.getShardVersion() - only for use with sharding\");}\n" + "DBCollection.prototype.getFullName = function(){\n" + "return this._fullName;}\n" + "DBCollection.prototype.getDB = function(){\n" + "return this._db;}\n" + "DBCollection.prototype._dbCommand = function( cmd , params ){\n" + "if ( typeof( cmd ) == \"object\" )\n" + "return this._db._dbCommand( cmd );\n" + "var c = {};\n" + "c[cmd] = this.getName();\n" + "if ( params )\n" + "Object.extend( c , params );\n" + "return this._db._dbCommand( c );}\n" + "DBCollection.prototype.runCommand = DBCollection.prototype._dbCommand;\n" + "DBCollection.prototype._massageObject = function( q ){\n" + "if ( ! q )\n" + "return {};\n" + "var type = typeof q;\n" + "if ( type == \"function\" )\n" + "return { $where : q };\n" + "if ( q.isObjectId )\n" + "return { _id : q };\n" + "if ( type == \"object\" )\n" + "return q;\n" + "if ( type == \"string\" ){\n" + "if ( q.length == 24 )\n" + "return { _id : q };\n" + "return { $where : q };}\n" + "throw \"don't know how to massage : \" + type;}\n" + "DBCollection.prototype._validateObject = function( o ){\n" + "if ( o._ensureSpecial && o._checkModify )\n" + "throw \"can't save a DBQuery object\";}\n" + "DBCollection._allowedFields = { $id : 1 , $ref : 1 };\n" + "DBCollection.prototype._validateForStorage = function( o ){\n" + "this._validateObject( o );\n" "for ( var k in o ){\n" - "if ( k == \"v\" && isNumber( o[k] ) ){\n" - "var n = o[k];\n" - "if ( n > 0 ){\n" - "var temp = \"-\";\n" - "while ( n-- > 0 ) temp += \"v\";\n" - "fullArgs.push( temp );\n" - "}\n" - "}\n" - "else {\n" - "fullArgs.push( \"--\" + k );\n" - "if ( o[k] != \"\" )\n" - "fullArgs.push( \"\" + o[k] );\n" - "}\n" - "}\n" - "}\n" - "else {\n" - "for ( var i=0; i<args.length; i++ )\n" - "fullArgs.push( args[i] )\n" - "}\n" - "return fullArgs;\n" - "}\n" - "startMongod = function(){\n" - "var args = createMongoArgs( \"mongod\" , arguments );\n" - "var dbpath = _parsePath.apply( null, args );\n" - "resetDbpath( dbpath );\n" - "return startMongoProgram.apply( null, args );\n" - "}\n" - "startMongos = function(){\n" - "return startMongoProgram.apply( null, createMongoArgs( \"mongos\" , arguments ) );\n" - "}\n" - "startMongoProgram = function(){\n" - "var port = _parsePort.apply( null, arguments );\n" - "_startMongoProgram.apply( null, arguments );\n" - "var m;\n" - "assert.soon\n" - "( function() {\n" - "try {\n" - "m = new Mongo( \"127.0.0.1:\" + port );\n" - "return true;\n" - "} catch( e ) {\n" - "}\n" - "return false;\n" - "}, \"unable to connect to mongo program on port \" + port, 30000 );\n" - "return m;\n" - "}\n" - "startMongoProgramNoConnect = function() {\n" - "return _startMongoProgram.apply( null, arguments );\n" - "}\n" - "myPort = function() {\n" - "var m = db.getMongo();\n" - "if ( m.host.match( /:/ ) )\n" - "return m.host.match( /:(.*)/ )[ 1 ];\n" - "else\n" - "return 27017;\n" - "}\n" - "ShardingTest = function( testName , numServers , verboseLevel , numMongos ){\n" - "this._connections = [];\n" - "this._serverNames = [];\n" - "for ( var i=0; i<numServers; i++){\n" - "var conn = startMongod( { port : 30000 + i , dbpath : \"/data/db/\" + testName + i , noprealloc : \"\" } );\n" - "conn.name = \"localhost:\" + ( 30000 + i );\n" - "this._connections.push( conn );\n" - "this._serverNames.push( conn.name );\n" - "}\n" - "this._configDB = \"localhost:30000\";\n" - "this._mongos = [];\n" - "var startMongosPort = 39999;\n" - "for ( var i=0; i<(numMongos||1); i++ ){\n" - "var myPort = startMongosPort - i;\n" - "var conn = startMongos( { port : startMongosPort - i , v : verboseLevel || 0 , configdb : this._configDB } );\n" - "conn.name = \"localhost:\" + myPort;\n" - "this._mongos.push( conn );\n" - "if ( i == 0 )\n" - "this.s = conn;\n" - "}\n" - "var admin = this.admin = this.s.getDB( \"admin\" );\n" - "this.config = this.s.getDB( \"config\" );\n" - "this._serverNames.forEach(\n" - "function(z){\n" - "admin.runCommand( { addshard : z } );\n" - "}\n" - ");\n" - "}\n" - "ShardingTest.prototype.getDB = function( name ){\n" - "return this.s.getDB( name );\n" - "}\n" - "ShardingTest.prototype.getServerName = function( dbname ){\n" - "return this.config.databases.findOne( { name : dbname } ).primary;\n" - "}\n" - "ShardingTest.prototype.getServer = function( dbname ){\n" - "var name = this.getServerName( dbname );\n" - "for ( var i=0; i<this._serverNames.length; i++ ){\n" - "if ( name == this._serverNames[i] )\n" - "return this._connections[i];\n" - "}\n" - "throw \"can't find server for: \" + dbname + \" name:\" + name;\n" - "}\n" - "ShardingTest.prototype.getOther = function( one ){\n" - "if ( this._connections.length != 2 )\n" - "throw \"getOther only works with 2 servers\";\n" - "if ( this._connections[0] == one )\n" - "return this._connections[1];\n" - "return this._connections[0];\n" - "}\n" - "ShardingTest.prototype.stop = function(){\n" - "for ( var i=0; i<this._mongos.length; i++ ){\n" - "stopMongoProgram( 39999 - i );\n" - "}\n" - "for ( var i=0; i<this._connections.length; i++){\n" - "stopMongod( 30000 + i );\n" - "}\n" - "}\n" - "ShardingTest.prototype.adminCommand = function(cmd){\n" - "var res = this.admin.runCommand( cmd );\n" - "if ( res && res.ok == 1 )\n" - "return true;\n" - "throw \"command \" + tojson( cmd ) + \" failed: \" + tojson( res );\n" - "}\n" - "ShardingTest.prototype.getChunksString = function( ns ){\n" - "var q = {}\n" - "if ( ns )\n" - "q.ns = ns;\n" - "return Array.tojson( this.config.chunks.find( q ).toArray() , \"\\n\" );\n" - "}\n" - "ShardingTest.prototype.printChunks = function( ns ){\n" - "print( this.getChunksString( ns ) );\n" - "}\n" - "ShardingTest.prototype.sync = function(){\n" - "this.adminCommand( \"connpoolsync\" );\n" - "}\n" - "MongodRunner = function( port, dbpath, peer, arbiter, extraArgs ) {\n" - "this.port_ = port;\n" - "this.dbpath_ = dbpath;\n" - "this.peer_ = peer;\n" - "this.arbiter_ = arbiter;\n" - "this.extraArgs_ = extraArgs;\n" - "}\n" - "MongodRunner.prototype.start = function( reuseData ) {\n" - "var args = [];\n" - "if ( reuseData ) {\n" - "args.push( \"mongod\" );\n" - "}\n" - "args.push( \"--port\" );\n" - "args.push( this.port_ );\n" - "args.push( \"--dbpath\" );\n" - "args.push( this.dbpath_ );\n" - "if ( this.peer_ && this.arbiter_ ) {\n" - "args.push( \"--pairwith\" );\n" - "args.push( this.peer_ );\n" - "args.push( \"--arbiter\" );\n" - "args.push( this.arbiter_ );\n" - "args.push( \"--oplogSize\" );\n" - "args.push( \"1\" );\n" - "}\n" - "args.push( \"--nohttpinterface\" );\n" - "args.push( \"--noprealloc\" );\n" - "args.push( \"--bind_ip\" );\n" - "args.push( \"127.0.0.1\" );\n" - "if ( this.extraArgs_ ) {\n" - "args = args.concat( this.extraArgs_ );\n" - "}\n" - "if ( reuseData ) {\n" - "return startMongoProgram.apply( null, args );\n" - "} else {\n" - "return startMongod.apply( null, args );\n" - "}\n" - "}\n" - "MongodRunner.prototype.port = function() { return this.port_; }\n" - "MongodRunner.prototype.toString = function() { return [ this.port_, this.dbpath_, this.peer_, this.arbiter_ ].toString(); }\n" - "ReplPair = function( left, right, arbiter ) {\n" - "this.left_ = left;\n" - "this.leftC_ = null;\n" - "this.right_ = right;\n" - "this.rightC_ = null;\n" - "this.arbiter_ = arbiter;\n" - "this.arbiterC_ = null;\n" - "this.master_ = null;\n" - "this.slave_ = null;\n" - "}\n" - "ReplPair.prototype.start = function( reuseData ) {\n" - "if ( this.arbiterC_ == null ) {\n" - "this.arbiterC_ = this.arbiter_.start();\n" - "}\n" - "if ( this.leftC_ == null ) {\n" - "this.leftC_ = this.left_.start( reuseData );\n" - "}\n" - "if ( this.rightC_ == null ) {\n" - "this.rightC_ = this.right_.start( reuseData );\n" - "}\n" - "}\n" - "ReplPair.prototype.isMaster = function( mongo, debug ) {\n" - "var im = mongo.getDB( \"admin\" ).runCommand( { ismaster : 1 } );\n" - "assert( im && im.ok, \"command ismaster failed\" );\n" - "if ( debug ) {\n" - "printjson( im );\n" - "}\n" - "return im.ismaster;\n" - "}\n" - "ReplPair.prototype.isInitialSyncComplete = function( mongo, debug ) {\n" - "var isc = mongo.getDB( \"admin\" ).runCommand( { isinitialsynccomplete : 1 } );\n" - "assert( isc && isc.ok, \"command isinitialsynccomplete failed\" );\n" - "if ( debug ) {\n" - "printjson( isc );\n" - "}\n" - "return isc.initialsynccomplete;\n" - "}\n" - "ReplPair.prototype.checkSteadyState = function( state, expectedMasterHost, twoMasterOk, leftValues, rightValues, debug ) {\n" - "leftValues = leftValues || {};\n" - "rightValues = rightValues || {};\n" - "var lm = null;\n" - "var lisc = null;\n" - "if ( this.leftC_ != null ) {\n" - "lm = this.isMaster( this.leftC_, debug );\n" - "leftValues[ lm ] = true;\n" - "lisc = this.isInitialSyncComplete( this.leftC_, debug );\n" - "}\n" - "var rm = null;\n" - "var risc = null;\n" - "if ( this.rightC_ != null ) {\n" - "rm = this.isMaster( this.rightC_, debug );\n" - "rightValues[ rm ] = true;\n" - "risc = this.isInitialSyncComplete( this.rightC_, debug );\n" - "}\n" - "var stateSet = {}\n" - "state.forEach( function( i ) { stateSet[ i ] = true; } );\n" - "if ( !( 1 in stateSet ) || ( ( risc || risc == null ) && ( lisc || lisc == null ) ) ) {\n" - "if ( rm == 1 && lm != 1 ) {\n" - "assert( twoMasterOk || !( 1 in leftValues ) );\n" - "this.master_ = this.rightC_;\n" - "this.slave_ = this.leftC_;\n" - "} else if ( lm == 1 && rm != 1 ) {\n" - "assert( twoMasterOk || !( 1 in rightValues ) );\n" - "this.master_ = this.leftC_;\n" - "this.slave_ = this.rightC_;\n" - "}\n" - "if ( !twoMasterOk ) {\n" - "assert( lm != 1 || rm != 1, \"two masters\" );\n" - "}\n" - "if ( state.sort().toString() == [ lm, rm ].sort().toString() ) {\n" - "if ( expectedMasterHost != null ) {\n" - "if( expectedMasterHost == this.master_.host ) {\n" - "return true;\n" - "}\n" - "} else {\n" - "return true;\n" - "}\n" - "}\n" - "}\n" - "this.master_ = null;\n" - "this.slave_ = null;\n" - "return false;\n" - "}\n" - "ReplPair.prototype.waitForSteadyState = function( state, expectedMasterHost, twoMasterOk, debug ) {\n" - "state = state || [ 1, 0 ];\n" - "twoMasterOk = twoMasterOk || false;\n" - "var rp = this;\n" - "var leftValues = {};\n" - "var rightValues = {};\n" - "assert.soon( function() { return rp.checkSteadyState( state, expectedMasterHost, twoMasterOk, leftValues, rightValues, debug ); },\n" - "\"rp (\" + rp + \") failed to reach expected steady state (\" + state + \")\" );\n" - "}\n" - "ReplPair.prototype.master = function() { return this.master_; }\n" - "ReplPair.prototype.slave = function() { return this.slave_; }\n" - "ReplPair.prototype.right = function() { return this.rightC_; }\n" - "ReplPair.prototype.left = function() { return this.leftC_; }\n" - "ReplPair.prototype.killNode = function( mongo, signal ) {\n" - "signal = signal || 15;\n" - "if ( this.leftC_ != null && this.leftC_.host == mongo.host ) {\n" - "stopMongod( this.left_.port_ );\n" - "this.leftC_ = null;\n" - "}\n" - "if ( this.rightC_ != null && this.rightC_.host == mongo.host ) {\n" - "stopMongod( this.right_.port_ );\n" - "this.rightC_ = null;\n" - "}\n" - "}\n" - "ReplPair.prototype._annotatedNode = function( mongo ) {\n" - "var ret = \"\";\n" - "if ( mongo != null ) {\n" - "ret += \" (connected)\";\n" - "if ( this.master_ != null && mongo.host == this.master_.host ) {\n" - "ret += \"(master)\";\n" - "}\n" - "if ( this.slave_ != null && mongo.host == this.slave_.host ) {\n" - "ret += \"(slave)\";\n" - "}\n" - "}\n" - "return ret;\n" - "}\n" - "ReplPair.prototype.toString = function() {\n" - "var ret = \"\";\n" - "ret += \"left: \" + this.left_;\n" - "ret += \" \" + this._annotatedNode( this.leftC_ );\n" - "ret += \" right: \" + this.right_;\n" - "ret += \" \" + this._annotatedNode( this.rightC_ );\n" - "return ret;\n" - "}\n" - "friendlyEqual = function( a , b ){\n" - "if ( a == b )\n" - "return true;\n" - "if ( tojson( a ) == tojson( b ) )\n" - "return true;\n" - "return false;\n" - "}\n" - "doassert = function( msg ){\n" - "print( \"assert: \" + msg );\n" - "throw msg;\n" - "}\n" - "assert = function( b , msg ){\n" - "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" - "if ( b )\n" - "return;\n" - "doassert( \"assert failed : \" + msg );\n" - "}\n" - "assert._debug = false;\n" - "assert.eq = function( a , b , msg ){\n" - "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" - "if ( a == b )\n" - "return;\n" - "if ( ( a != null && b != null ) && friendlyEqual( a , b ) )\n" - "return;\n" - "doassert( \"[\" + tojson( a ) + \"] != [\" + tojson( b ) + \"] are not equal : \" + msg );\n" - "}\n" - "assert.neq = function( a , b , msg ){\n" - "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" - "if ( a != b )\n" - "return;\n" - "doassert( \"[\" + a + \"] != [\" + b + \"] are equal : \" + msg );\n" - "}\n" - "assert.soon = function( f, msg, timeout, interval ) {\n" - "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" - "var start = new Date();\n" - "timeout = timeout || 30000;\n" - "interval = interval || 200;\n" - "var last;\n" - "while( 1 ) {\n" - "if ( typeof( f ) == \"string\" ){\n" - "if ( eval( f ) )\n" - "return;\n" - "}\n" + "if ( k.indexOf( \".\" ) >= 0 ) {\n" + "throw \"can't have . in field names [\" + k + \"]\" ;}\n" + "if ( k.indexOf( \"$\" ) == 0 && ! DBCollection._allowedFields[k] ) {\n" + "throw \"field names cannot start with $ [\" + k + \"]\";}\n" + "if ( o[k] !== null && typeof( o[k] ) === \"object\" ) {\n" + "this._validateForStorage( o[k] );}}\n" + "};\n" + "DBCollection.prototype.find = function( query , fields , limit , skip ){\n" + "return new DBQuery( this._mongo , this._db , this ,\n" + "this._fullName , this._massageObject( query ) , fields , limit , skip );}\n" + "DBCollection.prototype.findOne = function( query , fields ){\n" + "var cursor = this._mongo.find( this._fullName , this._massageObject( query ) || {} , fields , -1 , 0 , 0 );\n" + "if ( ! cursor.hasNext() )\n" + "return null;\n" + "var ret = cursor.next();\n" + "if ( cursor.hasNext() ) throw \"findOne has more than 1 result!\";\n" + "if ( ret.$err )\n" + "throw \"error \" + tojson( ret );\n" + "return ret;}\n" + "DBCollection.prototype.insert = function( obj , _allow_dot ){\n" + "if ( ! obj )\n" + "throw \"no object passed to insert!\";\n" + "if ( ! _allow_dot ) {\n" + "this._validateForStorage( obj );}\n" + "if ( typeof( obj._id ) == \"undefined\" ){\n" + "var tmp = obj;\n" + "obj = {_id: new ObjectId()};\n" + "for (var key in tmp){\n" + "obj[key] = tmp[key];}}\n" + "this._mongo.insert( this._fullName , obj );\n" + "return obj._id;}\n" + "DBCollection.prototype.remove = function( t ){\n" + "this._mongo.remove( this._fullName , this._massageObject( t ) );}\n" + "DBCollection.prototype.update = function( query , obj , upsert , multi ){\n" + "assert( query , \"need a query\" );\n" + "assert( obj , \"need an object\" );\n" + "this._validateObject( obj );\n" + "this._mongo.update( this._fullName , query , obj , upsert ? true : false , multi ? true : false );}\n" + "DBCollection.prototype.save = function( obj ){\n" + "if ( obj == null || typeof( obj ) == \"undefined\" )\n" + "throw \"can't save a null\";\n" + "if ( typeof( obj._id ) == \"undefined\" ){\n" + "obj._id = new ObjectId();\n" + "return this.insert( obj );}\n" "else {\n" - "if ( f() )\n" - "return;\n" - "}\n" - "if ( ( new Date() ).getTime() - start.getTime() > timeout )\n" - "doassert( \"assert.soon failed: \" + f + \", msg:\" + msg );\n" - "sleep( interval );\n" - "}\n" - "}\n" - "assert.throws = function( func , params , msg ){\n" - "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" - "try {\n" - "func.apply( null , params );\n" - "}\n" - "catch ( e ){\n" - "return e;\n" - "}\n" - "doassert( \"did not throw exception: \" + msg );\n" - "}\n" - "assert.commandWorked = function( res , msg ){\n" - "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" - "if ( res.ok == 1 )\n" - "return;\n" - "doassert( \"command failed: \" + tojson( res ) + \" : \" + msg );\n" - "}\n" - "assert.commandFailed = function( res , msg ){\n" - "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" - "if ( res.ok == 0 )\n" - "return;\n" - "doassert( \"command worked when it should have failed: \" + tojson( res ) + \" : \" + msg );\n" - "}\n" - "assert.isnull = function( what , msg ){\n" - "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" - "if ( what == null )\n" - "return;\n" - "doassert( \"supposed to null (\" + ( msg || \"\" ) + \") was: \" + tojson( what ) );\n" - "}\n" - "assert.lt = function( a , b , msg ){\n" - "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" - "if ( a < b )\n" - "return;\n" - "doassert( a + \" is not less than \" + b + \" : \" + msg );\n" - "}\n" - "assert.gt = function( a , b , msg ){\n" - "if ( assert._debug && msg ) print( \"in assert for: \" + msg );\n" - "if ( a > b )\n" - "return;\n" - "doassert( a + \" is not greater than \" + b + \" : \" + msg );\n" - "}\n" - "Object.extend = function( dst , src ){\n" - "for ( var k in src ){\n" - "dst[k] = src[k];\n" - "}\n" - "return dst;\n" - "}\n" - "argumentsToArray = function( a ){\n" - "var arr = [];\n" - "for ( var i=0; i<a.length; i++ )\n" - "arr[i] = a[i];\n" - "return arr;\n" - "}\n" - "isString = function( x ){\n" - "return typeof( x ) == \"string\";\n" - "}\n" - "isNumber = function(x){\n" - "return typeof( x ) == \"number\";\n" - "}\n" - "isObject = function( x ){\n" - "return typeof( x ) == \"object\";\n" - "}\n" - "String.prototype.trim = function() {\n" - "return this.replace(/^\\s+|\\s+$/g,\"\");\n" - "}\n" - "String.prototype.ltrim = function() {\n" - "return this.replace(/^\\s+/,\"\");\n" - "}\n" - "String.prototype.rtrim = function() {\n" - "return this.replace(/\\s+$/,\"\");\n" - "}\n" - "Date.timeFunc = function( theFunc , numTimes ){\n" - "var start = new Date();\n" - "numTimes = numTimes || 1;\n" - "for ( var i=0; i<numTimes; i++ ){\n" - "theFunc.apply( null , argumentsToArray( arguments ).slice( 2 ) );\n" - "}\n" - "return (new Date()).getTime() - start.getTime();\n" - "}\n" - "Date.prototype.tojson = function(){\n" - "return \"\\\"\" + this.toString() + \"\\\"\";\n" - "}\n" - "RegExp.prototype.tojson = RegExp.prototype.toString;\n" - "Array.contains = function( a , x ){\n" - "for ( var i=0; i<a.length; i++ ){\n" - "if ( a[i] == x )\n" - "return true;\n" - "}\n" - "return false;\n" - "}\n" - "Array.unique = function( a ){\n" - "var u = [];\n" - "for ( var i=0; i<a.length; i++){\n" - "var o = a[i];\n" - "if ( ! Array.contains( u , o ) ){\n" - "u.push( o );\n" - "}\n" - "}\n" - "return u;\n" - "}\n" - "Array.shuffle = function( arr ){\n" - "for ( var i=0; i<arr.length-1; i++ ){\n" - "var pos = i+Math.floor(Math.random()*(arr.length-i));\n" - "var save = arr[i];\n" - "arr[i] = arr[pos];\n" - "arr[pos] = save;\n" - "}\n" - "return arr;\n" - "}\n" - "Array.tojson = function( a , sepLines ){\n" - "var s = \"[\";\n" - "if ( sepLines ) s += \"\\n\";\n" - "for ( var i=0; i<a.length; i++){\n" - "if ( i > 0 ){\n" - "s += \",\";\n" - "if ( sepLines ) s += \"\\n\";\n" - "}\n" - "s += tojson( a[i] );\n" - "}\n" - "s += \"]\";\n" - "if ( sepLines ) s += \"\\n\";\n" - "return s;\n" - "}\n" - "Array.fetchRefs = function( arr , coll ){\n" - "var n = [];\n" - "for ( var i=0; i<arr.length; i ++){\n" - "var z = arr[i];\n" - "if ( coll && coll != z.getCollection() )\n" + "return this.update( { _id : obj._id } , obj , true );}}\n" + "DBCollection.prototype._genIndexName = function( keys ){\n" + "var name = \"\";\n" + "for ( var k in keys ){\n" + "var v = keys[k];\n" + "if ( typeof v == \"function\" )\n" "continue;\n" - "n.push( z.fetch() );\n" - "}\n" - "return n;\n" - "}\n" - "if ( ! ObjectId.prototype )\n" - "ObjectId.prototype = {}\n" - "ObjectId.prototype.toString = function(){\n" - "return this.str;\n" - "}\n" - "ObjectId.prototype.tojson = function(){\n" - "return \" ObjectId( \\\"\" + this.str + \"\\\") \";\n" - "}\n" - "ObjectId.prototype.isObjectId = true;\n" - "if ( typeof( DBPointer ) != \"undefined\" ){\n" - "DBPointer.prototype.fetch = function(){\n" - "assert( this.ns , \"need a ns\" );\n" - "assert( this.id , \"need an id\" );\n" - "return db[ this.ns ].findOne( { _id : this.id } );\n" - "}\n" - "DBPointer.prototype.tojson = function(){\n" - "return \"{ 'ns' : \\\"\" + this.ns + \"\\\" , 'id' : \\\"\" + this.id + \"\\\" } \";\n" - "}\n" - "DBPointer.prototype.getCollection = function(){\n" - "return this.ns;\n" - "}\n" - "DBPointer.prototype.toString = function(){\n" - "return \"DBPointer \" + this.ns + \":\" + this.id;\n" - "}\n" - "}\n" - "else {\n" - "print( \"warning: no DBPointer\" );\n" - "}\n" - "if ( typeof( DBRef ) != \"undefined\" ){\n" - "DBRef.prototype.fetch = function(){\n" - "assert( this.$ref , \"need a ns\" );\n" - "assert( this.$id , \"need an id\" );\n" - "return db[ this.$ref ].findOne( { _id : this.$id } );\n" - "}\n" - "DBRef.prototype.tojson = function(){\n" - "return \"{ '$ref' : \\\"\" + this.$ref + \"\\\" , '$id' : \\\"\" + this.$id + \"\\\" } \";\n" - "}\n" - "DBRef.prototype.getCollection = function(){\n" - "return this.$ref;\n" - "}\n" - "DBRef.prototype.toString = function(){\n" - "return this.tojson();\n" - "}\n" - "}\n" + "if ( name.length > 0 )\n" + "name += \"_\";\n" + "name += k + \"_\";\n" + "if ( typeof v == \"number\" )\n" + "name += v;}\n" + "return name;}\n" + "DBCollection.prototype._indexSpec = function( keys, options ) {\n" + "var ret = { ns : this._fullName , key : keys , name : this._genIndexName( keys ) };\n" + "if ( ! options ){}\n" + "else if ( typeof ( options ) == \"string\" )\n" + "ret.name = options;\n" + "else if ( typeof ( options ) == \"boolean\" )\n" + "ret.unique = true;\n" + "else if ( typeof ( options ) == \"object\" ){\n" + "if ( options.length ){\n" + "var nb = 0;\n" + "for ( var i=0; i<options.length; i++ ){\n" + "if ( typeof ( options[i] ) == \"string\" )\n" + "ret.name = options[i];\n" + "else if ( typeof( options[i] ) == \"boolean\" ){\n" + "if ( options[i] ){\n" + "if ( nb == 0 )\n" + "ret.unique = true;\n" + "if ( nb == 1 )\n" + "ret.dropDups = true;}\n" + "nb++;}}}\n" "else {\n" - "print( \"warning: no DBRef\" );\n" - "}\n" - "if ( typeof( BinData ) != \"undefined\" ){\n" - "BinData.prototype.tojson = function(){\n" - "return \"BinData type: \" + this.type + \" len: \" + this.len;\n" - "}\n" - "}\n" + "Object.extend( ret , options );}}\n" "else {\n" - "print( \"warning: no BinData\" );\n" - "}\n" - "tojson = function( x ){\n" - "if ( x == null )\n" - "return \"null\";\n" - "if ( x == undefined )\n" - "return \"\";\n" - "switch ( typeof x ){\n" - "case \"string\": {\n" - "var s = \"\\\"\";\n" - "for ( var i=0; i<x.length; i++ ){\n" - "if ( x[i] == '\"' ){\n" - "s += \"\\\\\\\"\";\n" - "}\n" - "else\n" - "s += x[i];\n" - "}\n" - "return s + \"\\\"\";\n" - "}\n" - "case \"number\":\n" - "case \"boolean\":\n" - "return \"\" + x;\n" - "case \"object\":\n" - "return tojsonObject( x );\n" - "case \"function\":\n" - "return x.toString();\n" - "default:\n" - "throw \"tojson can't handle type \" + ( typeof x );\n" - "}\n" - "}\n" - "tojsonObject = function( x ){\n" - "assert.eq( ( typeof x ) , \"object\" , \"tojsonObject needs object, not [\" + ( typeof x ) + \"]\" );\n" - "if ( typeof( x.tojson ) == \"function\" && x.tojson != tojson )\n" - "return x.tojson();\n" - "if ( typeof( x.constructor.tojson ) == \"function\" && x.constructor.tojson != tojson )\n" - "return x.constructor.tojson( x );\n" - "if ( x.toString() == \"[object MaxKey]\" )\n" - "return \"{ $maxKey : 1 }\";\n" - "if ( x.toString() == \"[object MinKey]\" )\n" - "return \"{ $minKey : 1 }\";\n" - "var s = \"{\";\n" - "var first = true;\n" - "for ( var k in x ){\n" - "var val = x[k];\n" - "if ( val == DB.prototype || val == DBCollection.prototype )\n" - "continue;\n" - "if ( first ) first = false;\n" - "else s += \" , \";\n" - "s += \"\\\"\" + k + \"\\\" : \" + tojson( val );\n" - "}\n" - "return s + \"}\";\n" - "}\n" - "shellPrint = function( x ){\n" - "it = x;\n" - "if ( x != undefined )\n" - "shellPrintHelper( x );\n" - "if ( db ){\n" - "var e = db.getPrevError();\n" - "if ( e.err ) {\n" - "if( e.nPrev <= 1 )\n" - "print( \"error on last call: \" + tojson( e.err ) );\n" - "else\n" - "print( \"an error \" + tojson(e.err) + \" occurred \" + e.nPrev + \" operations back in the command invocation\" );\n" - "}\n" - "db.resetError();\n" - "}\n" - "}\n" - "printjson = function(x){\n" - "print( tojson( x ) );\n" - "}\n" - "shellPrintHelper = function( x ){\n" - "if ( typeof( x ) == \"undefined\" ){\n" - "if ( typeof( db ) != \"undefined\" && db.getLastError ){\n" - "var e = db.getLastError();\n" - "if ( e != null )\n" - "print( e );\n" - "}\n" - "return;\n" - "}\n" - "if ( x == null ){\n" - "print( \"null\" );\n" - "return;\n" - "}\n" - "if ( typeof x != \"object\" )\n" - "return print( x );\n" - "var p = x.shellPrint;\n" - "if ( typeof p == \"function\" )\n" - "return x.shellPrint();\n" - "var p = x.tojson;\n" - "if ( typeof p == \"function\" )\n" - "print( x.tojson() );\n" - "else\n" - "print( tojson( x ) );\n" - "}\n" - "shellHelper = function( command , rest , shouldPrint ){\n" - "command = command.trim();\n" - "var args = rest.trim().replace(/;$/,\"\").split( \"\\s+\" );\n" - "if ( ! shellHelper[command] )\n" - "throw \"no command [\" + command + \"]\";\n" - "var res = shellHelper[command].apply( null , args );\n" - "if ( shouldPrint ){\n" - "shellPrintHelper( res );\n" - "}\n" + "throw \"can't handle: \" + typeof( options );}\n" + "/*\n" + "return ret;\n" + "var name;\n" + "var nTrue = 0;\n" + "if ( ! isObject( options ) ) {\n" + "options = [ options ];}\n" + "if ( options.length ){\n" + "for( var i = 0; i < options.length; ++i ) {\n" + "var o = options[ i ];\n" + "if ( isString( o ) ) {\n" + "ret.name = o;\n" + "} else if ( typeof( o ) == \"boolean\" ) {\n" + "if ( o ) {\n" + "++nTrue;}}}\n" + "if ( nTrue > 0 ) {\n" + "ret.unique = true;}\n" + "if ( nTrue > 1 ) {\n" + "ret.dropDups = true;}}\n" + "*/\n" + "return ret;}\n" + "DBCollection.prototype.createIndex = function( keys , options ){\n" + "var o = this._indexSpec( keys, options );\n" + "this._db.getCollection( \"system.indexes\" ).insert( o , true );}\n" + "DBCollection.prototype.ensureIndex = function( keys , options ){\n" + "var name = this._indexSpec( keys, options ).name;\n" + "this._indexCache = this._indexCache || {};\n" + "if ( this._indexCache[ name ] ){\n" + "return;}\n" + "this.createIndex( keys , options );\n" + "if ( this.getDB().getLastError() == \"\" ) {\n" + "this._indexCache[name] = true;}}\n" + "DBCollection.prototype.resetIndexCache = function(){\n" + "this._indexCache = {};}\n" + "DBCollection.prototype.reIndex = function() {\n" + "return this._db.runCommand({ reIndex: this.getName() });}\n" + "DBCollection.prototype.dropIndexes = function(){\n" + "this.resetIndexCache();\n" + "var res = this._db.runCommand( { deleteIndexes: this.getName(), index: \"*\" } );\n" + "assert( res , \"no result from dropIndex result\" );\n" + "if ( res.ok )\n" "return res;\n" - "}\n" - "help = shellHelper.help = function(){\n" - "print( \"HELP\" );\n" - "print( \"\\t\" + \"show dbs show database names\");\n" - "print( \"\\t\" + \"show collections show collections in current database\");\n" - "print( \"\\t\" + \"show users show users in current database\");\n" - "print( \"\\t\" + \"show profile show most recent system.profile entries with time >= 1ms\");\n" - "print( \"\\t\" + \"use <db name> set curent database to <db name>\" );\n" - "print( \"\\t\" + \"db.help() help on DB methods\");\n" - "print( \"\\t\" + \"db.foo.help() help on collection methods\");\n" - "print( \"\\t\" + \"db.foo.find() list objects in collection foo\" );\n" - "print( \"\\t\" + \"db.foo.find( { a : 1 } ) list objects in foo where a == 1\" );\n" - "print( \"\\t\" + \"it result of the last line evaluated; use to further iterate\");\n" - "}\n" - "shellHelper.use = function( dbname ){\n" - "db = db.getMongo().getDB( dbname );\n" - "print( \"switched to db \" + db.getName() );\n" - "}\n" - "shellHelper.it = function(){\n" - "if ( typeof( ___it___ ) == \"undefined\" || ___it___ == null ){\n" - "print( \"no cursor\" );\n" - "return;\n" - "}\n" - "shellPrintHelper( ___it___ );\n" - "}\n" - "shellHelper.show = function( what ){\n" - "assert( typeof what == \"string\" );\n" - "if( what == \"profile\" ) {\n" - "if( db.system.profile.count() == 0 ) {\n" - "print(\"db.system.profile is empty\");\n" - "print(\"Use db.setProfilingLevel(2) will enable profiling\");\n" - "print(\"Use db.system.profile.find() to show raw profile entries\");\n" - "}\n" - "else {\n" - "print();\n" - "db.system.profile.find({ millis : { $gt : 0 } }).sort({$natural:-1}).limit(5).forEach( function(x){print(\"\"+x.millis+\"ms \" + String(x.ts).substring(0,24)); print(x.info); print(\"\\n\");} )\n" - "}\n" - "return \"\";\n" - "}\n" - "if ( what == \"users\" ){\n" - "db.system.users.find().forEach( printjson );\n" - "return \"\";\n" - "}\n" - "if ( what == \"collections\" || what == \"tables\" ) {\n" - "db.getCollectionNames().forEach( function(x){print(x)} );\n" - "return \"\";\n" - "}\n" - "if ( what == \"dbs\" ) {\n" - "db.getMongo().getDBNames().sort().forEach( function(x){print(x)} );\n" - "return \"\";\n" - "}\n" - "throw \"don't know how to show [\" + what + \"]\";\n" - "}\n" - "if ( typeof( Map ) == \"undefined\" ){\n" - "Map = function(){\n" - "this._data = {};\n" - "}\n" - "}\n" - "Map.hash = function( val ){\n" - "if ( ! val )\n" - "return val;\n" - "switch ( typeof( val ) ){\n" - "case 'string':\n" - "case 'number':\n" - "case 'date':\n" - "return val.toString();\n" - "case 'object':\n" - "case 'array':\n" - "var s = \"\";\n" - "for ( var k in val ){\n" - "s += k + val[k];\n" - "}\n" - "return s;\n" - "}\n" - "throw \"can't hash : \" + typeof( val );\n" - "}\n" - "Map.prototype.put = function( key , value ){\n" - "var o = this._get( key );\n" - "var old = o.value;\n" - "o.value = value;\n" - "return old;\n" - "}\n" - "Map.prototype.get = function( key ){\n" - "return this._get( key ).value;\n" - "}\n" - "Map.prototype._get = function( key ){\n" - "var h = Map.hash( key );\n" - "var a = this._data[h];\n" - "if ( ! a ){\n" - "a = [];\n" - "this._data[h] = a;\n" - "}\n" - "for ( var i=0; i<a.length; i++ ){\n" - "if ( friendlyEqual( key , a[i].key ) ){\n" - "return a[i];\n" - "}\n" - "}\n" - "var o = { key : key , value : null };\n" - "a.push( o );\n" - "return o;\n" - "}\n" - "Map.prototype.values = function(){\n" - "var all = [];\n" - "for ( var k in this._data ){\n" - "this._data[k].forEach( function(z){ all.push( z.value ); } );\n" - "}\n" - "return all;\n" - "}\n" - "Math.sigFig = function( x , N ){\n" - "if ( ! N ){\n" - "N = 3;\n" - "}\n" - "var p = Math.pow( 10, N - Math.ceil( Math.log( Math.abs(x) ) / Math.log( 10 )) );\n" - "return Math.round(x*p)/p;\n" - "}\n" + "if ( res.errmsg.match( /not found/ ) )\n" + "return res;\n" + "throw \"error dropping indexes : \" + tojson( res );}\n" + "DBCollection.prototype.drop = function(){\n" + "this.resetIndexCache();\n" + "var ret = this._db.runCommand( { drop: this.getName() } );\n" + "if ( ! ret.ok ){\n" + "if ( ret.errmsg == \"ns not found\" )\n" + "return false;\n" + "throw \"drop failed: \" + tojson( ret );}\n" + "return true;}\n" + "DBCollection.prototype.findAndModify = function(args){\n" + "var cmd = { findandmodify: this.getName() };\n" + "for (var key in args){\n" + "cmd[key] = args[key];}\n" + "var ret = this._db.runCommand( cmd );\n" + "if ( ! ret.ok ){\n" + "if (ret.errmsg == \"No matching object found\"){\n" + "return {};}\n" + "throw \"findAndModifyFailed failed: \" + tojson( ret.errmsg );}\n" + "return ret.value;}\n" + "DBCollection.prototype.renameCollection = function( newName , dropTarget ){\n" + "return this._db._adminCommand( { renameCollection : this._fullName ,\n" + "to : this._db._name + \".\" + newName ,\n" + "dropTarget : dropTarget } )}\n" + "DBCollection.prototype.validate = function() {\n" + "var res = this._db.runCommand( { validate: this.getName() } );\n" + "res.valid = false;\n" + "if ( res.result ){\n" + "var str = \"-\" + tojson( res.result );\n" + "res.valid = ! ( str.match( /exception/ ) || str.match( /corrupt/ ) );\n" + "var p = /lastExtentSize:(\\d+)/;\n" + "var r = p.exec( str );\n" + "if ( r ){\n" + "res.lastExtentSize = Number( r[1] );}}\n" + "return res;}\n" + "DBCollection.prototype.getShardVersion = function(){\n" + "return this._db._adminCommand( { getShardVersion : this._fullName } );}\n" + "DBCollection.prototype.getIndexes = function(){\n" + "return this.getDB().getCollection( \"system.indexes\" ).find( { ns : this.getFullName() } ).toArray();}\n" + "DBCollection.prototype.getIndices = DBCollection.prototype.getIndexes;\n" + "DBCollection.prototype.getIndexSpecs = DBCollection.prototype.getIndexes;\n" + "DBCollection.prototype.getIndexKeys = function(){\n" + "return this.getIndexes().map(\n" + "function(i){\n" + "return i.key;}\n" + ");}\n" + "DBCollection.prototype.count = function( x ){\n" + "return this.find( x ).count();}\n" + "\n" + "DBCollection.prototype.clean = function() {\n" + "return this._dbCommand( { clean: this.getName() } );}\n" + "\n" + "DBCollection.prototype.dropIndex = function(index) {\n" + "assert(index , \"need to specify index to dropIndex\" );\n" + "if ( ! isString( index ) && isObject( index ) )\n" + "index = this._genIndexName( index );\n" + "var res = this._dbCommand( \"deleteIndexes\" ,{ index: index } );\n" + "this.resetIndexCache();\n" + "return res;}\n" + "DBCollection.prototype.copyTo = function( newName ){\n" + "return this.getDB().eval(\n" + "function( collName , newName ){\n" + "var from = db[collName];\n" + "var to = db[newName];\n" + "to.ensureIndex( { _id : 1 } );\n" + "var count = 0;\n" + "var cursor = from.find();\n" + "while ( cursor.hasNext() ){\n" + "var o = cursor.next();\n" + "count++;\n" + "to.save( o );}\n" + "return count;\n" + "} , this.getName() , newName\n" + ");}\n" + "DBCollection.prototype.getCollection = function( subName ){\n" + "return this._db.getCollection( this._shortName + \".\" + subName );}\n" + "DBCollection.prototype.stats = function( scale ){\n" + "return this._db.runCommand( { collstats : this._shortName , scale : scale } );}\n" + "DBCollection.prototype.dataSize = function(){\n" + "return this.stats().size;}\n" + "DBCollection.prototype.storageSize = function(){\n" + "return this.stats().storageSize;}\n" + "DBCollection.prototype.totalIndexSize = function( verbose ){\n" + "var stats = this.stats();\n" + "if (verbose){\n" + "for (var ns in stats.indexSizes){\n" + "print( ns + \"\\t\" + stats.indexSizes[ns] );}}\n" + "return stats.totalIndexSize;}\n" + "DBCollection.prototype.totalSize = function(){\n" + "var total = this.storageSize();\n" + "var mydb = this._db;\n" + "var shortName = this._shortName;\n" + "this.getIndexes().forEach(\n" + "function( spec ){\n" + "var coll = mydb.getCollection( shortName + \".$\" + spec.name );\n" + "var mysize = coll.storageSize();\n" + "total += coll.dataSize();}\n" + ");\n" + "return total;}\n" + "DBCollection.prototype.convertToCapped = function( bytes ){\n" + "if ( ! bytes )\n" + "throw \"have to specify # of bytes\";\n" + "return this._dbCommand( { convertToCapped : this._shortName , size : bytes } )}\n" + "DBCollection.prototype.exists = function(){\n" + "return this._db.system.namespaces.findOne( { name : this._fullName } );}\n" + "DBCollection.prototype.isCapped = function(){\n" + "var e = this.exists();\n" + "return ( e && e.options && e.options.capped ) ? true : false;}\n" + "DBCollection.prototype.distinct = function( keyString , query ){\n" + "var res = this._dbCommand( { distinct : this._shortName , key : keyString , query : query || {} } );\n" + "if ( ! res.ok )\n" + "throw \"distinct failed: \" + tojson( res );\n" + "return res.values;}\n" + "DBCollection.prototype.group = function( params ){\n" + "params.ns = this._shortName;\n" + "return this._db.group( params );}\n" + "DBCollection.prototype.groupcmd = function( params ){\n" + "params.ns = this._shortName;\n" + "return this._db.groupcmd( params );}\n" + "MapReduceResult = function( db , o ){\n" + "Object.extend( this , o );\n" + "this._o = o;\n" + "this._keys = Object.keySet( o );\n" + "this._db = db;\n" + "this._coll = this._db.getCollection( this.result );}\n" + "MapReduceResult.prototype._simpleKeys = function(){\n" + "return this._o;}\n" + "MapReduceResult.prototype.find = function(){\n" + "return DBCollection.prototype.find.apply( this._coll , arguments );}\n" + "MapReduceResult.prototype.drop = function(){\n" + "return this._coll.drop();}\n" + "\n" + "MapReduceResult.prototype.convertToSingleObject = function(){\n" + "var z = {};\n" + "this._coll.find().forEach( function(a){ z[a._id] = a.value; } );\n" + "return z;}\n" + "\n" + "DBCollection.prototype.mapReduce = function( map , reduce , optional ){\n" + "var c = { mapreduce : this._shortName , map : map , reduce : reduce };\n" + "if ( optional )\n" + "Object.extend( c , optional );\n" + "var raw = this._db.runCommand( c );\n" + "if ( ! raw.ok )\n" + "throw \"map reduce failed: \" + tojson( raw );\n" + "return new MapReduceResult( this._db , raw );}\n" + "DBCollection.prototype.toString = function(){\n" + "return this.getFullName();}\n" + "DBCollection.prototype.toString = function(){\n" + "return this.getFullName();}\n" + "DBCollection.prototype.tojson = DBCollection.prototype.toString;\n" + "DBCollection.prototype.shellPrint = DBCollection.prototype.toString;\n" ; diff --git a/shell/query.js b/shell/query.js index aabd12e..508fba2 100644 --- a/shell/query.js +++ b/shell/query.js @@ -1,7 +1,7 @@ // query.js if ( typeof DBQuery == "undefined" ){ - DBQuery = function( mongo , db , collection , ns , query , fields , limit , skip ){ + DBQuery = function( mongo , db , collection , ns , query , fields , limit , skip , batchSize ){ this._mongo = mongo; // 0 this._db = db; // 1 @@ -12,7 +12,8 @@ if ( typeof DBQuery == "undefined" ){ this._fields = fields; // 5 this._limit = limit || 0; // 6 this._skip = skip || 0; // 7 - + this._batchSize = batchSize || 0; + this._cursor = null; this._numReturned = 0; this._special = false; @@ -36,7 +37,7 @@ DBQuery.prototype.help = function(){ DBQuery.prototype.clone = function(){ var q = new DBQuery( this._mongo , this._db , this._collection , this._ns , this._query , this._fields , - this._limit , this._skip ); + this._limit , this._skip , this._batchSize ); q._special = this._special; return q; } @@ -58,7 +59,7 @@ DBQuery.prototype._checkModify = function(){ DBQuery.prototype._exec = function(){ if ( ! this._cursor ){ assert.eq( 0 , this._numReturned ); - this._cursor = this._mongo.find( this._ns , this._query , this._fields , this._limit , this._skip ); + this._cursor = this._mongo.find( this._ns , this._query , this._fields , this._limit , this._skip , this._batchSize ); this._cursorSeen = 0; } return this._cursor; @@ -70,6 +71,13 @@ DBQuery.prototype.limit = function( limit ){ return this; } +DBQuery.prototype.batchSize = function( batchSize ){ + this._checkModify(); + this._batchSize = batchSize; + return this; +} + + DBQuery.prototype.skip = function( skip ){ this._checkModify(); this._skip = skip; @@ -167,28 +175,26 @@ DBQuery.prototype.length = function(){ return this.toArray().length; } -DBQuery.prototype.sort = function( sortBy ){ +DBQuery.prototype._addSpecial = function( name , value ){ this._ensureSpecial(); - this._query.orderby = sortBy; + this._query[name] = value; return this; } +DBQuery.prototype.sort = function( sortBy ){ + return this._addSpecial( "orderby" , sortBy ); +} + DBQuery.prototype.hint = function( hint ){ - this._ensureSpecial(); - this._query["$hint"] = hint; - return this; + return this._addSpecial( "$hint" , hint ); } DBQuery.prototype.min = function( min ) { - this._ensureSpecial(); - this._query["$min"] = min; - return this; + return this._addSpecial( "$min" , min ); } DBQuery.prototype.max = function( max ) { - this._ensureSpecial(); - this._query["$max"] = max; - return this; + return this._addSpecial( "$max" , max ); } DBQuery.prototype.forEach = function( func ){ @@ -219,7 +225,7 @@ DBQuery.prototype.snapshot = function(){ this._ensureSpecial(); this._query.$snapshot = true; return this; - } +} DBQuery.prototype.shellPrint = function(){ try { diff --git a/shell/servers.js b/shell/servers.js index 109f871..f681263 100644 --- a/shell/servers.js +++ b/shell/servers.js @@ -32,6 +32,7 @@ createMongoArgs = function( binaryName , args ){ if ( k == "v" && isNumber( o[k] ) ){ var n = o[k]; if ( n > 0 ){ + if ( n > 10 ) n = 10; var temp = "-"; while ( n-- > 0 ) temp += "v"; fullArgs.push( temp ); @@ -52,6 +53,25 @@ createMongoArgs = function( binaryName , args ){ return fullArgs; } +startMongodTest = function( port , dirname , restart ){ + var f = startMongod; + if ( restart ) + f = startMongodNoReset; + var conn = f.apply( null , [ + { + port : port , + dbpath : "/data/db/" + dirname , + noprealloc : "" , + smallfiles : "" , + oplogSize : "2" , + nohttpinterface : "" + } + ] + ); + conn.name = "localhost:" + port; + return conn; +} + // Start a mongod instance and return a 'Mongo' object connected to it. // This function's arguments are passed as command line arguments to mongod. // The specified 'dbpath' is cleared if it exists, created if not. @@ -65,6 +85,11 @@ startMongod = function(){ return startMongoProgram.apply( null, args ); } +startMongodNoReset = function(){ + var args = createMongoArgs( "mongod" , arguments ); + return startMongoProgram.apply( null, args ); +} + startMongos = function(){ return startMongoProgram.apply( null, createMongoArgs( "mongos" , arguments ) ); } @@ -87,7 +112,7 @@ startMongoProgram = function(){ } catch( e ) { } return false; - }, "unable to connect to mongo program on port " + port, 30000 ); + }, "unable to connect to mongo program on port " + port, 60000 ); return m; } @@ -107,24 +132,31 @@ myPort = function() { return 27017; } -ShardingTest = function( testName , numServers , verboseLevel , numMongos ){ +ShardingTest = function( testName , numServers , verboseLevel , numMongos , otherParams ){ + if ( ! otherParams ) + otherParams = {} this._connections = []; - this._serverNames = []; + + if ( otherParams.sync && numServers < 3 ) + throw "if you want sync, you need at least 3 servers"; for ( var i=0; i<numServers; i++){ - var conn = startMongod( { port : 30000 + i , dbpath : "/data/db/" + testName + i , - noprealloc : "" , smallfiles : "" , oplogSize : "2" } ); - conn.name = "localhost:" + ( 30000 + i ); - + var conn = startMongodTest( 30000 + i , testName + i ); this._connections.push( conn ); - this._serverNames.push( conn.name ); } - this._configDB = "localhost:30000"; - + if ( otherParams.sync ){ + this._configDB = "localhost:30000,localhost:30001,localhost:30002"; + this._configConnection = new Mongo( this._configDB ); + this._configConnection.getDB( "config" ).settings.insert( { _id : "chunksize" , value : otherParams.chunksize || 50 } ); + } + else { + this._configDB = "localhost:30000"; + this._connections[0].getDB( "config" ).settings.insert( { _id : "chunksize" , value : otherParams.chunksize || 50 } ); + } this._mongos = []; - var startMongosPort = 39999; + var startMongosPort = 31000; for ( var i=0; i<(numMongos||1); i++ ){ var myPort = startMongosPort - i; var conn = startMongos( { port : startMongosPort - i , v : verboseLevel || 0 , configdb : this._configDB } ); @@ -137,9 +169,9 @@ ShardingTest = function( testName , numServers , verboseLevel , numMongos ){ var admin = this.admin = this.s.getDB( "admin" ); this.config = this.s.getDB( "config" ); - this._serverNames.forEach( + this._connections.forEach( function(z){ - admin.runCommand( { addshard : z , allowLocal : true } ); + admin.runCommand( { addshard : z.name , allowLocal : true } ); } ); } @@ -154,9 +186,10 @@ ShardingTest.prototype.getServerName = function( dbname ){ ShardingTest.prototype.getServer = function( dbname ){ var name = this.getServerName( dbname ); - for ( var i=0; i<this._serverNames.length; i++ ){ - if ( name == this._serverNames[i] ) - return this._connections[i]; + for ( var i=0; i<this._connections.length; i++ ){ + var c = this._connections[i]; + if ( name == c.name ) + return c; } throw "can't find server for: " + dbname + " name:" + name; @@ -171,9 +204,17 @@ ShardingTest.prototype.getOther = function( one ){ return this._connections[0]; } +ShardingTest.prototype.getFirstOther = function( one ){ + for ( var i=0; i<this._connections.length; i++ ){ + if ( this._connections[i] != one ) + return this._connections[i]; + } + throw "impossible"; +} + ShardingTest.prototype.stop = function(){ for ( var i=0; i<this._mongos.length; i++ ){ - stopMongoProgram( 39999 - i ); + stopMongoProgram( 31000 - i ); } for ( var i=0; i<this._connections.length; i++){ stopMongod( 30000 + i ); @@ -322,6 +363,7 @@ MongodRunner.prototype.start = function( reuseData ) { if ( this.extraArgs_ ) { args = args.concat( this.extraArgs_ ); } + removeFile( this.dbpath_ + "/mongod.lock" ); if ( reuseData ) { return startMongoProgram.apply( null, args ); } else { @@ -551,7 +593,7 @@ ReplTest.prototype.getPath = function( master ){ } -ReplTest.prototype.getOptions = function( master , extra , putBinaryFirst ){ +ReplTest.prototype.getOptions = function( master , extra , putBinaryFirst, norepl ){ if ( ! extra ) extra = {}; @@ -571,13 +613,15 @@ ReplTest.prototype.getOptions = function( master , extra , putBinaryFirst ){ a.push( this.getPath( master ) ); - if ( master ){ - a.push( "--master" ); - } - else { - a.push( "--slave" ); - a.push( "--source" ); - a.push( "127.0.0.1:" + this.ports[0] ); + if ( !norepl ) { + if ( master ){ + a.push( "--master" ); + } + else { + a.push( "--slave" ); + a.push( "--source" ); + a.push( "127.0.0.1:" + this.ports[0] ); + } } for ( var k in extra ){ @@ -590,8 +634,10 @@ ReplTest.prototype.getOptions = function( master , extra , putBinaryFirst ){ return a; } -ReplTest.prototype.start = function( master , options , restart ){ - var o = this.getOptions( master , options , restart ); +ReplTest.prototype.start = function( master , options , restart, norepl ){ + var lockFile = this.getPath( master ) + "/mongod.lock"; + removeFile( lockFile ); + var o = this.getOptions( master , options , restart, norepl ); if ( restart ) return startMongoProgram.apply( null , o ); else @@ -604,5 +650,53 @@ ReplTest.prototype.stop = function( master , signal ){ this.stop( false ); return; } - stopMongod( this.getPort( master ) , signal || 15 ); + return stopMongod( this.getPort( master ) , signal || 15 ); +} + +allocatePorts = function( n ) { + var ret = []; + for( var i = 31000; i < 31000 + n; ++i ) + ret.push( i ); + return ret; +} + + +SyncCCTest = function( testName ){ + this._testName = testName; + this._connections = []; + + for ( var i=0; i<3; i++ ){ + this._connections.push( startMongodTest( 30000 + i , testName + i ) ); + } + + this.url = this._connections.map( function(z){ return z.name; } ).join( "," ); + this.conn = new Mongo( this.url ); +} + +SyncCCTest.prototype.stop = function(){ + for ( var i=0; i<this._connections.length; i++){ + stopMongod( 30000 + i ); + } +} + +SyncCCTest.prototype.checkHashes = function( dbname , msg ){ + var hashes = this._connections.map( + function(z){ + return z.getDB( dbname ).runCommand( "dbhash" ); + } + ); + + for ( var i=1; i<hashes.length; i++ ){ + assert.eq( hashes[0].md5 , hashes[i].md5 , "checkHash on " + dbname + " " + msg + "\n" + tojson( hashes ) ) + } +} + +SyncCCTest.prototype.tempKill = function( num ){ + num = num || 0; + stopMongod( 30000 + num ); +} + +SyncCCTest.prototype.tempStart = function( num ){ + num = num || 0; + this._connections[num] = startMongodTest( 30000 + num , this._testName + num , true ); } diff --git a/shell/utils.cpp b/shell/utils.cpp index c4735ee..b10c93d 100644 --- a/shell/utils.cpp +++ b/shell/utils.cpp @@ -1,4 +1,22 @@ // utils.cpp +/* + * Copyright 2010 10gen Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "../stdafx.h" #include <boost/thread/xtime.hpp> @@ -10,20 +28,32 @@ #include <map> #include <sstream> #include <vector> +#include <fcntl.h> -#ifndef _WIN32 -#include <sys/socket.h> -#include <netinet/in.h> +#ifdef _WIN32 +# include <io.h> +# define SIGKILL 9 +#else +# include <sys/socket.h> +# include <netinet/in.h> +# include <signal.h> +# include <sys/stat.h> +# include <sys/wait.h> #endif #include "../client/dbclient.h" #include "../util/processinfo.h" -#include "../util/md5.hpp" #include "utils.h" extern const char * jsconcatcode_server; namespace mongo { +#ifdef _WIN32 + inline int close(int fd) { return _close(fd); } + inline int read(int fd, void* buf, size_t size) { return _read(fd, buf, size); } + + inline int pipe(int fds[2]) { return _pipe(fds, 1024, _O_TEXT | _O_NOINHERIT); } +#endif namespace shellUtils { @@ -73,6 +103,32 @@ namespace mongo { return undefined_; } + + BSONObj Quit(const BSONObj& args) { + // If not arguments are given first element will be EOO, which + // converts to the integer value 0. + int exit_code = int( args.firstElement().number() ); + ::exit(exit_code); + return undefined_; + } + + BSONObj JSGetMemInfo( const BSONObj& args ){ + ProcessInfo pi; + uassert( 10258 , "processinfo not supported" , pi.supported() ); + + BSONObjBuilder e; + e.append( "virtual" , pi.getVirtualMemorySize() ); + e.append( "resident" , pi.getResidentSize() ); + + BSONObjBuilder b; + b.append( "ret" , e.obj() ); + + return b.obj(); + } + + +#ifndef MONGO_SAFE_SHELL + BSONObj listFiles(const BSONObj& args){ uassert( 10257 , "need to specify 1 argument to listFiles" , args.nFields() == 1 ); @@ -80,7 +136,10 @@ namespace mongo { string rootname = args.firstElement().valuestrsafe(); path root( rootname ); - uassert( 12581, "listFiles: no such directory", boost::filesystem::exists( root ) ); + stringstream ss; + ss << "listFiles: no such directory: " << rootname; + string msg = ss.str(); + uassert( 12581, msg.c_str(), boost::filesystem::exists( root ) ); directory_iterator end; directory_iterator i( root); @@ -113,92 +172,34 @@ namespace mongo { ret.appendArray( "", lst.done() ); return ret.obj(); } - - BSONObj Quit(const BSONObj& args) { - // If not arguments are given first element will be EOO, which - // converts to the integer value 0. - int exit_code = int( args.firstElement().number() ); - ::exit(exit_code); - return undefined_; - } - BSONObj JSGetMemInfo( const BSONObj& args ){ - ProcessInfo pi; - uassert( 10258 , "processinfo not supported" , pi.supported() ); - - BSONObjBuilder e; - e.append( "virtual" , pi.getVirtualMemorySize() ); - e.append( "resident" , pi.getResidentSize() ); - - BSONObjBuilder b; - b.append( "ret" , e.obj() ); - - return b.obj(); - } - BSONObj JSVersion( const BSONObj& args ){ - cout << "version: " << versionString << endl; - if ( strstr( versionString , "+" ) ) - printGitVersion(); - return BSONObj(); - } - -#ifndef _WIN32 -#include <signal.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/wait.h> - - BSONObj AllocatePorts( const BSONObj &args ) { - uassert( 10259 , "allocatePorts takes exactly 1 argument", args.nFields() == 1 ); - uassert( 10260 , "allocatePorts needs to be passed an integer", args.firstElement().isNumber() ); + BSONObj removeFile(const BSONObj& args){ + uassert( 12597 , "need to specify 1 argument to listFiles" , args.nFields() == 1 ); - int n = int( args.firstElement().number() ); + bool found = false; - vector< int > ports; - vector< int > sockets; - for( int i = 0; i < n; ++i ) { - int s = socket( AF_INET, SOCK_STREAM, 0 ); - assert( s ); - - sockaddr_in address; - memset(address.sin_zero, 0, sizeof(address.sin_zero)); - address.sin_family = AF_INET; - address.sin_port = 0; - address.sin_addr.s_addr = inet_addr( "127.0.0.1" ); - assert( 0 == ::bind( s, (sockaddr*)&address, sizeof( address ) ) ); - - sockaddr_in newAddress; - socklen_t len = sizeof( newAddress ); - assert( 0 == getsockname( s, (sockaddr*)&newAddress, &len ) ); - ports.push_back( ntohs( newAddress.sin_port ) ); - sockets.push_back( s ); + path root( args.firstElement().valuestrsafe() ); + if ( boost::filesystem::exists( root ) ){ + found = true; + boost::filesystem::remove_all( root ); } - for( vector< int >::const_iterator i = sockets.begin(); i != sockets.end(); ++i ) - assert( 0 == close( *i ) ); - - sort( ports.begin(), ports.end() ); - for( unsigned i = 1; i < ports.size(); ++i ) - massert( 10434 , "duplicate ports allocated", ports[ i - 1 ] != ports[ i ] ); + BSONObjBuilder b; - b.append( "", ports ); + b.appendBool( "removed" , found ); return b.obj(); } - map< int, pair< pid_t, int > > dbs; map< pid_t, int > shells; +#ifdef _WIN32 + map< pid_t, HANDLE > handles; +#endif - char *copyString( const char *original ) { - char *ret = reinterpret_cast< char * >( malloc( strlen( original ) + 1 ) ); - strcpy( ret, original ); - return ret; - } - - boost::mutex &mongoProgramOutputMutex( *( new boost::mutex ) ); + mongo::mutex mongoProgramOutputMutex; stringstream mongoProgramOutput_; - + void writeMongoProgramOutputLine( int port, int pid, const char *line ) { - boost::mutex::scoped_lock lk( mongoProgramOutputMutex ); + mongo::mutex::scoped_lock lk( mongoProgramOutputMutex ); stringstream buf; if ( port > 0 ) buf << "m" << port << "| " << line; @@ -208,38 +209,52 @@ namespace mongo { mongoProgramOutput_ << buf.str() << endl; } + // only returns last 100000 characters BSONObj RawMongoProgramOutput( const BSONObj &args ) { - boost::mutex::scoped_lock lk( mongoProgramOutputMutex ); - return BSON( "" << mongoProgramOutput_.str() ); + mongo::mutex::scoped_lock lk( mongoProgramOutputMutex ); + string out = mongoProgramOutput_.str(); + size_t len = out.length(); + if ( len > 100000 ) + out = out.substr( len - 100000, 100000 ); + return BSON( "" << out ); } - - class MongoProgramRunner { - char **argv_; + + BSONObj ClearRawMongoProgramOutput( const BSONObj &args ) { + mongo::mutex::scoped_lock lk( mongoProgramOutputMutex ); + mongoProgramOutput_.str( "" ); + return undefined_; + } + + class ProgramRunner { + vector<string> argv_; int port_; int pipe_; pid_t pid_; public: pid_t pid() const { return pid_; } - MongoProgramRunner( const BSONObj &args ) { - assert( args.nFields() > 0 ); + ProgramRunner( const BSONObj &args , bool isMongoProgram=true) + { + assert( !args.isEmpty() ); + string program( args.firstElement().valuestrsafe() ); - assert( !program.empty() ); - boost::filesystem::path programPath = ( boost::filesystem::path( argv0 ) ).branch_path() / program; - massert( 10435 , "couldn't find " + programPath.native_file_string(), boost::filesystem::exists( programPath ) ); + boost::filesystem::path programPath = program; + + if (isMongoProgram){ + programPath = boost::filesystem::initial_path() / programPath; +#ifdef _WIN32 + programPath = change_extension(programPath, ".exe"); +#endif + massert( 10435 , "couldn't find " + programPath.native_file_string(), boost::filesystem::exists( programPath ) ); + } + + argv_.push_back( programPath.native_file_string() ); port_ = -1; - argv_ = new char *[ args.nFields() + 1 ]; - { - string s = programPath.native_file_string(); - if ( s == program ) - s = "./" + s; - argv_[ 0 ] = copyString( s.c_str() ); - } BSONObjIterator j( args ); - j.next(); - for( int i = 1; i < args.nFields(); ++i ) { + j.next(); // skip program name (handled above) + while(j.more()) { BSONElement e = j.next(); string str; if ( e.isNumber() ) { @@ -250,14 +265,12 @@ namespace mongo { assert( e.type() == mongo::String ); str = e.valuestr(); } - char *s = copyString( str.c_str() ); - if ( string( "--port" ) == s ) + if ( str == "--port" ) port_ = -2; else if ( port_ == -2 ) - port_ = strtol( s, 0, 10 ); - argv_[ i ] = s; + port_ = strtol( str.c_str(), 0, 10 ); + argv_.push_back(str); } - argv_[ args.nFields() ] = 0; if ( program != "mongod" && program != "mongos" && program != "mongobridge" ) port_ = 0; @@ -274,27 +287,12 @@ namespace mongo { assert( pipe( pipeEnds ) != -1 ); fflush( 0 ); - pid_ = fork(); - assert( pid_ != -1 ); - - if ( pid_ == 0 ) { - - assert( dup2( pipeEnds[ 1 ], STDOUT_FILENO ) != -1 ); - assert( dup2( pipeEnds[ 1 ], STDERR_FILENO ) != -1 ); - execvp( argv_[ 0 ], argv_ ); - massert( 10436 , "Unable to start program" , 0 ); - } + launch_process(pipeEnds[1]); //sets pid_ cout << "shell: started mongo program"; - int i = 0; - while( argv_[ i ] ) - cout << " " << argv_[ i++ ]; + for (unsigned i=0; i < argv_.size(); i++) + cout << " " << argv_[i]; cout << endl; - - i = 0; - while( argv_[ i ] ) - free( argv_[ i++ ] ); - free( argv_ ); if ( port_ > 0 ) dbs.insert( make_pair( port_, make_pair( pid_, pipeEnds[ 1 ] ) ) ); @@ -332,30 +330,136 @@ namespace mongo { strcpy( temp, last ); strcpy( buf, temp ); } else { - assert( strlen( buf ) < 1023 ); + assert( strlen( buf ) <= 1023 ); } start = buf + strlen( buf ); } } + void launch_process(int child_stdout){ +#ifdef _WIN32 + stringstream ss; + for (int i=0; i < argv_.size(); i++){ + if (i) ss << ' '; + if (argv_[i].find(' ') == string::npos) + ss << argv_[i]; + else + ss << '"' << argv_[i] << '"'; + } + + string args = ss.str(); + + boost::scoped_array<TCHAR> args_tchar (new TCHAR[args.size() + 1]); + for (size_t i=0; i < args.size()+1; i++) + args_tchar[i] = args[i]; + + HANDLE h = (HANDLE)_get_osfhandle(child_stdout); + assert(h != INVALID_HANDLE_VALUE); + assert(SetHandleInformation(h, HANDLE_FLAG_INHERIT, 1)); + + STARTUPINFO si; + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + si.hStdError = h; + si.hStdOutput = h; + si.dwFlags |= STARTF_USESTDHANDLES; + + PROCESS_INFORMATION pi; + ZeroMemory(&pi, sizeof(pi)); + + bool success = CreateProcess( NULL, args_tchar.get(), NULL, NULL, true, 0, NULL, NULL, &si, &pi); + assert(success); + + CloseHandle(pi.hThread); + + pid_ = pi.dwProcessId; + handles.insert( make_pair( pid_, pi.hProcess ) ); + +#else + + pid_ = fork(); + assert( pid_ != -1 ); + + if ( pid_ == 0 ) { + // DON'T ASSERT IN THIS BLOCK - very bad things will happen + + const char** argv = new const char* [argv_.size()+1]; // don't need to free - in child + for (unsigned i=0; i < argv_.size(); i++){ + argv[i] = argv_[i].c_str(); + } + argv[argv_.size()] = 0; + + if ( dup2( child_stdout, STDOUT_FILENO ) == -1 || + dup2( child_stdout, STDERR_FILENO ) == -1 ) + { + cout << "Unable to dup2 child output: " << OUTPUT_ERRNO << endl; + ::_Exit(-1); //do not pass go, do not call atexit handlers + } + + execvp( argv[ 0 ], const_cast<char**>(argv) ); + + cout << "Unable to start program: " << OUTPUT_ERRNO << endl; + ::_Exit(-1); + } + +#endif + } }; + //returns true if process exited + bool wait_for_pid(pid_t pid, bool block=true, int* exit_code=NULL){ +#ifdef _WIN32 + assert(handles.count(pid)); + HANDLE h = handles[pid]; + + if (block) + WaitForSingleObject(h, INFINITE); + + DWORD tmp; + if(GetExitCodeProcess(h, &tmp)){ + CloseHandle(h); + handles.erase(pid); + if (exit_code) + *exit_code = tmp; + return true; + }else{ + return false; + } +#else + int tmp; + bool ret = (pid == waitpid(pid, &tmp, (block ? 0 : WNOHANG))); + if (exit_code) + *exit_code = WEXITSTATUS(tmp); + return ret; + +#endif + } BSONObj StartMongoProgram( const BSONObj &a ) { - MongoProgramRunner r( a ); + _nokillop = true; + ProgramRunner r( a ); r.start(); boost::thread t( r ); return BSON( string( "" ) << int( r.pid() ) ); } BSONObj RunMongoProgram( const BSONObj &a ) { - MongoProgramRunner r( a ); + ProgramRunner r( a ); r.start(); boost::thread t( r ); - int temp; - waitpid( r.pid() , &temp , 0 ); + wait_for_pid(r.pid()); shells.erase( r.pid() ); return BSON( string( "" ) << int( r.pid() ) ); } + BSONObj RunProgram(const BSONObj &a) { + ProgramRunner r( a, false ); + r.start(); + boost::thread t( r ); + int exit_code; + wait_for_pid(r.pid(), true, &exit_code); + shells.erase( r.pid() ); + return BSON( string( "" ) << exit_code ); + } + BSONObj ResetDbpath( const BSONObj &a ) { assert( a.nFields() == 1 ); string path = a.firstElement().valuestrsafe(); @@ -366,19 +470,73 @@ namespace mongo { return undefined_; } - void killDb( int port, pid_t _pid, int signal ) { + void copyDir( const path &from, const path &to ) { + directory_iterator end; + directory_iterator i( from ); + while( i != end ) { + path p = *i; + if ( p.leaf() != "mongod.lock" ) { + if ( is_directory( p ) ) { + path newDir = to / p.leaf(); + boost::filesystem::create_directory( newDir ); + copyDir( p, newDir ); + } else { + boost::filesystem::copy_file( p, to / p.leaf() ); + } + } + ++i; + } + } + + // NOTE target dbpath will be cleared first + BSONObj CopyDbpath( const BSONObj &a ) { + assert( a.nFields() == 2 ); + BSONObjIterator i( a ); + string from = i.next().str(); + string to = i.next().str(); + assert( !from.empty() ); + assert( !to.empty() ); + if ( boost::filesystem::exists( to ) ) + boost::filesystem::remove_all( to ); + boost::filesystem::create_directory( to ); + copyDir( from, to ); + return undefined_; + } + + inline void kill_wrapper(pid_t pid, int sig, int port){ +#ifdef _WIN32 + if (sig == SIGKILL || port == 0){ + assert( handles.count(pid) ); + TerminateProcess(handles[pid], 1); // returns failure for "zombie" processes. + }else{ + DBClientConnection conn; + conn.connect("127.0.0.1:" + BSONObjBuilder::numStr(port)); + try { + conn.simpleCommand("admin", NULL, "shutdown"); + } catch (...) { + //Do nothing. This command never returns data to the client and the driver doesn't like that. + } + } +#else + assert( 0 == kill( pid, sig ) ); +#endif + } + + + int killDb( int port, pid_t _pid, int signal ) { pid_t pid; + int exitCode = 0; if ( port > 0 ) { if( dbs.count( port ) != 1 ) { cout << "No db started on port: " << port << endl; - return; + return 0; } pid = dbs[ port ].first; } else { pid = _pid; } - assert( 0 == kill( pid, signal ) ); + kill_wrapper( pid, signal, port ); int i = 0; for( ; i < 65; ++i ) { @@ -387,11 +545,9 @@ namespace mongo { time_t_to_String(time(0), now); now[ 20 ] = 0; cout << now << " process on port " << port << ", with pid " << pid << " not terminated, sending sigkill" << endl; - assert( 0 == kill( pid, SIGKILL ) ); + kill_wrapper( pid, SIGKILL, port ); } - int temp; - int ret = waitpid( pid, &temp, WNOHANG ); - if ( ret == pid ) + if(wait_for_pid(pid, false, &exitCode)) break; sleepms( 1000 ); } @@ -402,7 +558,7 @@ namespace mongo { cout << now << " failed to terminate process on port " << port << ", with pid " << pid << endl; assert( "Failed to terminate process" == 0 ); } - + if ( port > 0 ) { close( dbs[ port ].second ); dbs.erase( port ); @@ -413,6 +569,8 @@ namespace mongo { if ( i > 4 || signal == SIGKILL ) { sleepms( 4000 ); // allow operating system to reclaim resources } + + return exitCode; } int getSignal( const BSONObj &a ) { @@ -431,18 +589,18 @@ namespace mongo { assert( a.nFields() == 1 || a.nFields() == 2 ); assert( a.firstElement().isNumber() ); int port = int( a.firstElement().number() ); - killDb( port, 0, getSignal( a ) ); + int code = killDb( port, 0, getSignal( a ) ); cout << "shell: stopped mongo program on port " << port << endl; - return undefined_; + return BSON( "" << code ); } BSONObj StopMongoProgramByPid( const BSONObj &a ) { assert( a.nFields() == 1 || a.nFields() == 2 ); assert( a.firstElement().isNumber() ); int pid = int( a.firstElement().number() ); - killDb( 0, pid, getSignal( a ) ); + int code = killDb( 0, pid, getSignal( a ) ); cout << "shell: stopped mongo program on pid " << pid << endl; - return undefined_; + return BSON( "" << code ); } void KillMongoProgramInstances() { @@ -457,39 +615,23 @@ namespace mongo { for( vector< pid_t >::iterator i = pids.begin(); i != pids.end(); ++i ) killDb( 0, *i, SIGTERM ); } +#else // ndef MONGO_SAFE_SHELL + void KillMongoProgramInstances() {} +#endif MongoProgramScope::~MongoProgramScope() { - try { + DESTRUCTOR_GUARD( KillMongoProgramInstances(); - } catch ( ... ) { - assert( false ); - } + ClearRawMongoProgramOutput( BSONObj() ); + ) } -#else - MongoProgramScope::~MongoProgramScope() {} - void KillMongoProgramInstances() {} -#endif - - BSONObj jsmd5( const BSONObj &a ){ - uassert( 10261 , "js md5 needs a string" , a.firstElement().type() == String ); - const char * s = a.firstElement().valuestrsafe(); - - md5digest d; - md5_state_t st; - md5_init(&st); - md5_append( &st , (const md5_byte_t*)s , strlen( s ) ); - md5_finish(&st, d); - - return BSON( "" << digestToString( d ) ); - } - unsigned _randomSeed; BSONObj JSSrand( const BSONObj &a ) { uassert( 12518, "srand requires a single numeric argument", a.nFields() == 1 && a.firstElement().isNumber() ); - _randomSeed = a.firstElement().numberLong(); // grab least significant digits + _randomSeed = (unsigned)a.firstElement().numberLong(); // grab least significant digits return undefined_; } @@ -503,25 +645,40 @@ namespace mongo { #endif return BSON( "" << double( r ) / ( double( RAND_MAX ) + 1 ) ); } + + BSONObj isWindows(const BSONObj& a){ + uassert( 13006, "isWindows accepts no arguments", a.nFields() == 0 ); +#ifdef _WIN32 + return BSON( "" << true ); +#else + return BSON( "" << false ); +#endif + } void installShellUtils( Scope& scope ){ - scope.injectNative( "listFiles" , listFiles ); scope.injectNative( "sleep" , JSSleep ); scope.injectNative( "quit", Quit ); scope.injectNative( "getMemInfo" , JSGetMemInfo ); - scope.injectNative( "version" , JSVersion ); - scope.injectNative( "hex_md5" , jsmd5 ); scope.injectNative( "_srand" , JSSrand ); scope.injectNative( "_rand" , JSRand ); -#if !defined(_WIN32) - scope.injectNative( "allocatePorts", AllocatePorts ); + scope.injectNative( "_isWindows" , isWindows ); + +#ifndef MONGO_SAFE_SHELL + //can't launch programs scope.injectNative( "_startMongoProgram", StartMongoProgram ); + scope.injectNative( "runProgram", RunProgram ); scope.injectNative( "runMongoProgram", RunMongoProgram ); scope.injectNative( "stopMongod", StopMongoProgram ); scope.injectNative( "stopMongoProgram", StopMongoProgram ); scope.injectNative( "stopMongoProgramByPid", StopMongoProgramByPid ); - scope.injectNative( "resetDbpath", ResetDbpath ); scope.injectNative( "rawMongoProgramOutput", RawMongoProgramOutput ); + scope.injectNative( "clearRawMongoProgramOutput", ClearRawMongoProgramOutput ); + + //can't access filesystem + scope.injectNative( "removeFile" , removeFile ); + scope.injectNative( "listFiles" , listFiles ); + scope.injectNative( "resetDbpath", ResetDbpath ); + scope.injectNative( "copyDbpath", CopyDbpath ); #endif } @@ -533,9 +690,24 @@ namespace mongo { if ( !_dbConnect.empty() ) { uassert( 12513, "connect failed", scope.exec( _dbConnect , "(connect)" , false , true , false ) ); if ( !_dbAuth.empty() ) { + installGlobalUtils( scope ); uassert( 12514, "login failed", scope.exec( _dbAuth , "(auth)" , true , true , false ) ); } } } + + map< const void*, string > _allMyUris; + bool _nokillop = false; + void onConnect( DBClientWithCommands &c ) { + if ( _nokillop ) { + return; + } + BSONObj info; + if ( c.runCommand( "admin", BSON( "whatsmyuri" << 1 ), info ) ) { + // There's no way to explicitly disconnect a DBClientConnection, but we might allocate + // a new uri on automatic reconnect. So just store one uri per connection. + _allMyUris[ &c ] = info[ "you" ].str(); + } + } } } diff --git a/shell/utils.h b/shell/utils.h index 7c98e2c..a2d420d 100644 --- a/shell/utils.h +++ b/shell/utils.h @@ -1,19 +1,37 @@ // utils.h +/* + * Copyright 2010 10gen Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #pragma once #include "../scripting/engine.h" namespace mongo { - + namespace shellUtils { extern std::string _dbConnect; extern std::string _dbAuth; + extern map< const void*, string > _allMyUris; + extern bool _nokillop; void RecordMyLocation( const char *_argv0 ); void installShellUtils( Scope& scope ); - + // Scoped management of mongo program instances. Simple implementation: // destructor kills all mongod instances created by the shell. struct MongoProgramScope { @@ -23,5 +41,6 @@ namespace mongo { void KillMongoProgramInstances(); void initScope( Scope &scope ); + void onConnect( DBClientWithCommands &c ); } } diff --git a/shell/utils.js b/shell/utils.js index 2d59b80..027ba0d 100644 --- a/shell/utils.js +++ b/shell/utils.js @@ -132,6 +132,17 @@ assert.gt = function( a , b , msg ){ doassert( a + " is not greater than " + b + " : " + msg ); } +assert.close = function( a , b , msg , places ){ + if (places === undefined) { + places = 4; + } + if (Math.round((a - b) * Math.pow(10, places)) === 0) { + return; + } + doassert( a + " is not equal to " + b + " within " + places + + " places, diff: " + (a-b) + " : " + msg ); +}; + Object.extend = function( dst , src , deep ){ for ( var k in src ){ var v = src[k]; @@ -477,7 +488,8 @@ if ( typeof _threadInject != "undefined" ){ "jstests/extent.js", "jstests/indexb.js", "jstests/profile1.js", - "jstests/mr3.js"] ); + "jstests/mr3.js", + "jstests/apitest_db.js"] ); // some tests can't be run in parallel with each other var serialTestsArr = [ "jstests/fsync.js", @@ -576,10 +588,10 @@ if ( typeof _threadInject != "undefined" ){ } tojson = function( x, indent , nolint ){ - if ( x == null ) + if ( x === null ) return "null"; - if ( x == undefined ) + if ( x === undefined ) return "undefined"; if (!indent) @@ -905,3 +917,39 @@ Random.setRandomSeed = function( s ) { Random.genExp = function( mean ) { return -Math.log( Random.rand() ) * mean; } + +killWithUris = function( uris ) { + var inprog = db.currentOp().inprog; + for( var u in uris ) { + for ( var i in inprog ) { + if ( uris[ u ] == inprog[ i ].client ) { + db.killOp( inprog[ i ].opid ); + } + } + } +} + +Geo = {}; +Geo.distance = function( a , b ){ + var ax = null; + var ay = null; + var bx = null; + var by = null; + + for ( var key in a ){ + if ( ax == null ) + ax = a[key]; + else if ( ay == null ) + ay = a[key]; + } + + for ( var key in b ){ + if ( bx == null ) + bx = b[key]; + else if ( by == null ) + by = b[key]; + } + + return Math.sqrt( Math.pow( by - ay , 2 ) + + Math.pow( bx - ax , 2 ) ); +} |