mirror of
https://github.com/mongodb/mongo.git
synced 2024-12-01 01:21:03 +01:00
2062 lines
60 KiB
C++
2062 lines
60 KiB
C++
const char * jsconcatcode =
|
|
"\n"
|
|
"\n"
|
|
"\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"
|
|
"\n"
|
|
"this.verify();\n"
|
|
"}\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"
|
|
"\n"
|
|
"assert.eq( this._fullName , this._db._name + \".\" + this._shortName , \"name mismatch\" );\n"
|
|
"\n"
|
|
"assert( this._mongo , \"no mongo in DBCollection\" );\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBCollection.prototype.getName = function(){\n"
|
|
"return this._shortName;\n"
|
|
"}\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(...)\");\n"
|
|
"print(\"\\tdb.foo.find(...)\");\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.save(obj)\");\n"
|
|
"print(\"\\tdb.foo.update(query, object[, upsert_bool])\");\n"
|
|
"print(\"\\tdb.foo.ensureIndex(keypattern)\");\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.validate()\");\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBCollection.prototype.getFullName = function(){\n"
|
|
"return this._fullName;\n"
|
|
"}\n"
|
|
"DBCollection.prototype.getDB = function(){\n"
|
|
"return this._db;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBCollection.prototype._dbCommand = function( cmd ){\n"
|
|
"return this._db._dbCommand( cmd );\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBCollection.prototype._massageObject = function( q ){\n"
|
|
"if ( ! q )\n"
|
|
"return {};\n"
|
|
"\n"
|
|
"var type = typeof q;\n"
|
|
"\n"
|
|
"if ( type == \"function\" )\n"
|
|
"return { $where : q };\n"
|
|
"\n"
|
|
"if ( q.isObjectId )\n"
|
|
"return { _id : q };\n"
|
|
"\n"
|
|
"if ( type == \"object\" )\n"
|
|
"return q;\n"
|
|
"\n"
|
|
"if ( type == \"string\" ){\n"
|
|
"if ( q.length == 24 )\n"
|
|
"return { _id : q };\n"
|
|
"\n"
|
|
"return { $where : q };\n"
|
|
"}\n"
|
|
"\n"
|
|
"throw \"don't know how to massage : \" + type;\n"
|
|
"\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBCollection.prototype._validateForStorage = function( o ){\n"
|
|
"for ( var k in o ){\n"
|
|
"if ( k.indexOf( \".\" ) >= 0 )\n"
|
|
"throw \"can't have . in field names [\" + 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"
|
|
"\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"
|
|
"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"
|
|
"\n"
|
|
"DBCollection.prototype.insert = function( obj ){\n"
|
|
"if ( ! obj )\n"
|
|
"throw \"no object!\";\n"
|
|
"this._validateForStorage( obj );\n"
|
|
"return this._mongo.insert( this._fullName , obj );\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBCollection.prototype.remove = function( t ){\n"
|
|
"this._mongo.remove( this._fullName , this._massageObject( t ) );\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBCollection.prototype.update = function( query , obj , upsert ){\n"
|
|
"assert( query , \"need a query\" );\n"
|
|
"assert( obj , \"need an object\" );\n"
|
|
"return this._mongo.update( this._fullName , query , obj , upsert ? true : false );\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBCollection.prototype.save = function( obj ){\n"
|
|
"if ( ! obj._id ){\n"
|
|
"return this.insert( obj );\n"
|
|
"}\n"
|
|
"else {\n"
|
|
"return this.update( { _id : obj._id } , obj , true );\n"
|
|
"}\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"
|
|
"\n"
|
|
"var v = keys[k];\n"
|
|
"if ( typeof v == \"number\" )\n"
|
|
"name += v;\n"
|
|
"}\n"
|
|
"return name;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBCollection.prototype._indexSpec = function( keys, options ) {\n"
|
|
"var name;\n"
|
|
"var unique = false;\n"
|
|
"if ( !isObject( options ) ) {\n"
|
|
"options = [ options ];\n"
|
|
"}\n"
|
|
"for( var i = 0; i < options.length; ++i ) {\n"
|
|
"var o = options[ i ];\n"
|
|
"if ( isString( o ) ) {\n"
|
|
"name = o;\n"
|
|
"} else if ( typeof( o ) == \"boolean\" ) {\n"
|
|
"unique = o;\n"
|
|
"}\n"
|
|
"}\n"
|
|
"name = name || this._genIndexName( keys );\n"
|
|
"var ret = { ns : this._fullName , key : keys , name : name };\n"
|
|
"if ( unique == true ) {\n"
|
|
"ret.unique = true;\n"
|
|
"}\n"
|
|
"return ret;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBCollection.prototype.createIndex = function( keys , options ){\n"
|
|
"var o = this._indexSpec( keys, options );\n"
|
|
"this._db.getCollection( \"system.indexes\" ).insert( o );\n"
|
|
"}\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"
|
|
"this._indexCache[name] = true;\n"
|
|
"return true;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBCollection.prototype.resetIndexCache = function(){\n"
|
|
"this._indexCache = {};\n"
|
|
"}\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"
|
|
"\n"
|
|
"DBCollection.prototype.dropIndexes = function(){\n"
|
|
"this.resetIndexCache();\n"
|
|
"\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"
|
|
"if ( res.errmsg.match( /not found/ ) )\n"
|
|
"return res;\n"
|
|
"\n"
|
|
"throw \"error dropping indexes : \" + tojson( res );\n"
|
|
"}\n"
|
|
"\n"
|
|
"\n"
|
|
"DBCollection.prototype.drop = function(){\n"
|
|
"this.resetIndexCache();\n"
|
|
"return this._db.runCommand( { drop: this.getName() } );\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBCollection.prototype.validate = function() {\n"
|
|
"var res = this._db.runCommand( { validate: this.getName() } );\n"
|
|
"\n"
|
|
"res.valid = false;\n"
|
|
"\n"
|
|
"if ( res.result ){\n"
|
|
"var str = \"-\" + tojson( res.result );\n"
|
|
"res.valid = ! ( str.match( /exception/ ) || str.match( /corrupt/ ) );\n"
|
|
"\n"
|
|
"var p = /lastExtentSize:(\\d+)/;\n"
|
|
"var r = p.exec( str );\n"
|
|
"if ( r ){\n"
|
|
"res.lastExtentSize = Number( r[1] );\n"
|
|
"}\n"
|
|
"}\n"
|
|
"\n"
|
|
"return res;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBCollection.prototype.getIndexes = function(){\n"
|
|
"return this.getDB().getCollection( \"system.indexes\" ).find( { ns : this.getFullName() } );\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBCollection.prototype.getIndexSpecs = function(){\n"
|
|
"return this.getIndexes().toArray().map(\n"
|
|
"function(i){\n"
|
|
"return i;\n"
|
|
"}\n"
|
|
");\n"
|
|
"}\n"
|
|
"\n"
|
|
"\n"
|
|
"DBCollection.prototype.count = function(){\n"
|
|
"return this.find().count();\n"
|
|
"}\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"
|
|
"\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"
|
|
"\n"
|
|
"if ( ! isString( index ) && isObject( index ) )\n"
|
|
"index = this._genIndexName( index );\n"
|
|
"\n"
|
|
"var res = this._dbCommand( { deleteIndexes: this.getName(), index: index } );\n"
|
|
"this.resetIndexCache();\n"
|
|
"return res;\n"
|
|
"}\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"
|
|
"\n"
|
|
"var cursor = from.find();\n"
|
|
"while ( cursor.hasNext() ){\n"
|
|
"var o = cursor.next();\n"
|
|
"count++;\n"
|
|
"to.save( o );\n"
|
|
"}\n"
|
|
"\n"
|
|
"return count;\n"
|
|
"} , this.getName() , newName\n"
|
|
");\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBCollection.prototype.getCollection = function( subName ){\n"
|
|
"return this._db.getCollection( this._shortName + \".\" + subName );\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBCollection.prototype.toString = function(){\n"
|
|
"return this.getFullName();\n"
|
|
"}\n"
|
|
"\n"
|
|
"\n"
|
|
"if ( typeof DB == \"undefined\" ){\n"
|
|
"DB = function( mongo , name ){\n"
|
|
"this._mongo = mongo;\n"
|
|
"this._name = name;\n"
|
|
"}\n"
|
|
"}\n"
|
|
"\n"
|
|
"DB.prototype.getMongo = function(){\n"
|
|
"assert( this._mongo , \"why no mongo!\" );\n"
|
|
"return this._mongo;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DB.prototype.getSisterDB = function( name ){\n"
|
|
"return this.getMongo().getDB( name );\n"
|
|
"}\n"
|
|
"\n"
|
|
"DB.prototype.getName = function(){\n"
|
|
"return this._name;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DB.prototype.getCollection = function( name ){\n"
|
|
"return new DBCollection( this._mongo , this , name , this._name + \".\" + name );\n"
|
|
"}\n"
|
|
"\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"
|
|
"\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"
|
|
"\n"
|
|
"DB.prototype._dbCommand = DB.prototype.runCommand;\n"
|
|
"\n"
|
|
"DB.prototype.addUser = function( username , pass ){\n"
|
|
"var c = this.getCollection( \"system.users\" );\n"
|
|
"\n"
|
|
"var u = c.findOne( { user : username } ) || { user : username };\n"
|
|
"u.pwd = hex_md5( username + \":mongo:\" + pass );\n"
|
|
"print( tojson( u ) );\n"
|
|
"\n"
|
|
"c.save( u );\n"
|
|
"}\n"
|
|
"\n"
|
|
"DB.prototype.removeUser = function( username ){\n"
|
|
"this.getCollection( \"system.users\" ).remove( { user : username } );\n"
|
|
"}\n"
|
|
"\n"
|
|
"DB.prototype.auth = function( username , pass ){\n"
|
|
"var n = this.runCommand( { getnonce : 1 } );\n"
|
|
"\n"
|
|
"var a = this.runCommand(\n"
|
|
"{\n"
|
|
"authenticate : 1 ,\n"
|
|
"user : username ,\n"
|
|
"nonce : n.nonce ,\n"
|
|
"key : hex_md5( n.nonce + username + hex_md5( username + \":mongo:\" + pass ) )\n"
|
|
"}\n"
|
|
");\n"
|
|
"\n"
|
|
"return a.ok;\n"
|
|
"}\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"
|
|
"\n"
|
|
"If the collection already exists, no action occurs.\n"
|
|
"\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"
|
|
"\n"
|
|
"<p>Example: </p>\n"
|
|
"\n"
|
|
"<code>db.createCollection(\"movies\", { size: 10 * 1024 * 1024, capped:true } );</code>\n"
|
|
"\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"
|
|
"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"
|
|
"/**\n"
|
|
"* Returns the current profiling level of this database\n"
|
|
"* @return SOMETHING_FIXME or null on error\n"
|
|
"*/\n"
|
|
"DB.prototype.getProfilingLevel = function() {\n"
|
|
"var res = this._dbCommand( { profile: -1 } );\n"
|
|
"return res ? res.was : null;\n"
|
|
"}\n"
|
|
"\n"
|
|
"\n"
|
|
"/**\n"
|
|
"Erase the entire database. (!)\n"
|
|
"\n"
|
|
"* @return Object returned has member ok set to true if operation succeeds, false otherwise.\n"
|
|
"*/\n"
|
|
"DB.prototype.dropDatabase = function() {\n"
|
|
"return this._dbCommand( { dropDatabase: 1 } );\n"
|
|
"}\n"
|
|
"\n"
|
|
"\n"
|
|
"DB.prototype.shutdownServer = function() {\n"
|
|
"if( \"admin\" != db )\n"
|
|
"return \"shutdown command only works with the admin database; try 'use admin'\";\n"
|
|
"return this._dbCommand(\"shutdown\");\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"
|
|
"\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"
|
|
"DB.prototype.cloneDatabase = function(from) {\n"
|
|
"assert( isString(from) && from.length );\n"
|
|
"\n"
|
|
"return this._dbCommand( { clone: from } );\n"
|
|
"}\n"
|
|
"\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"
|
|
"\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"
|
|
"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"
|
|
"\n"
|
|
"return this._dbCommand( { cloneCollection:collection, from:from, query:query } );\n"
|
|
"}\n"
|
|
"\n"
|
|
"\n"
|
|
"/**\n"
|
|
"Copy database from one server or name to another server or name.\n"
|
|
"\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"
|
|
"\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"
|
|
"\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"
|
|
"\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"
|
|
"assert( isString(fromdb) && fromdb.length );\n"
|
|
"assert( isString(todb) && todb.length );\n"
|
|
"fromhost = fromhost || \"\";\n"
|
|
"\n"
|
|
"return this._dbCommand( { copydb:1, fromhost:fromhost, fromdb:fromdb, todb:todb } );\n"
|
|
"}\n"
|
|
"\n"
|
|
"/**\n"
|
|
"Repair database.\n"
|
|
"\n"
|
|
"* @return Object returned has member ok set to true if operation succeeds, false otherwise.\n"
|
|
"*/\n"
|
|
"DB.prototype.repairDatabase = function() {\n"
|
|
"return this._dbCommand( { repairDatabase: 1 } );\n"
|
|
"}\n"
|
|
"\n"
|
|
"\n"
|
|
"DB.prototype.help = function() {\n"
|
|
"print(\"DB methods:\");\n"
|
|
"print(\"\\tdb.auth(username, password)\");\n"
|
|
"print(\"\\tdb.getMongo() get the server connection object\");\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.getProfilingLevel()\");\n"
|
|
"print(\"\\tdb.setProfilingLevel(level) 0=off 1=slow 2=all\");\n"
|
|
"print(\"\\tdb.cloneDatabase(fromhost)\");\n"
|
|
"print(\"\\tdb.copyDatabase(fromdb, todb, fromhost)\");\n"
|
|
"print(\"\\tdb.shutdownServer()\");\n"
|
|
"print(\"\\tdb.dropDatabase()\");\n"
|
|
"print(\"\\tdb.repairDatabase()\");\n"
|
|
"print(\"\\tdb.eval(func, args) run code server-side\");\n"
|
|
"print(\"\\tdb.getLastError()\");\n"
|
|
"print(\"\\tdb.getPrevError()\");\n"
|
|
"print(\"\\tdb.resetError()\");\n"
|
|
"print(\"\\tdb.getCollectionNames()\");\n"
|
|
"print(\"\\tdb.group(ns, key[, keyf], cond, reduce, initial)\");\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"
|
|
"\n"
|
|
"if (level < 0 || level > 2) {\n"
|
|
"throw { dbSetProfilingException : \"input level \" + level + \" is out of range [0..2]\" };\n"
|
|
"}\n"
|
|
"\n"
|
|
"if (level) {\n"
|
|
"\n"
|
|
"this.createCollection(\"system.profile\", { capped: true, size: 128 * 1024 } );\n"
|
|
"}\n"
|
|
"return this._dbCommand( { profile: level } );\n"
|
|
"}\n"
|
|
"\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"
|
|
"DB.prototype.eval = function(jsfunction) {\n"
|
|
"var cmd = { $eval : jsfunction };\n"
|
|
"if ( arguments.length > 1 ) {\n"
|
|
"cmd.args = argumentsToArray( arguments ).slice(1);\n"
|
|
"}\n"
|
|
"\n"
|
|
"var res = this._dbCommand( cmd );\n"
|
|
"\n"
|
|
"if (!res.ok)\n"
|
|
"throw tojson( res );\n"
|
|
"\n"
|
|
"return res.retval;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DB.prototype.dbEval = DB.prototype.eval;\n"
|
|
"\n"
|
|
"\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"
|
|
"\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"
|
|
"DB.prototype.group = function(parmsObj) {\n"
|
|
"\n"
|
|
"var groupFunction = function() {\n"
|
|
"var parms = args[0];\n"
|
|
"var c = db[parms.ns].find(parms.cond||{});\n"
|
|
"var map = new Map();\n"
|
|
"\n"
|
|
"while( c.hasNext() ) {\n"
|
|
"var obj = c.next();\n"
|
|
"\n"
|
|
"var key = {};\n"
|
|
"if( parms.key ) {\n"
|
|
"for( var i in parms.key )\n"
|
|
"key[i] = obj[i];\n"
|
|
"}\n"
|
|
"else {\n"
|
|
"key = parms.$keyf(obj);\n"
|
|
"}\n"
|
|
"\n"
|
|
"var aggObj = map[key];\n"
|
|
"if( aggObj == null ) {\n"
|
|
"var newObj = Object.extend({}, key); \n"
|
|
"aggObj = map[key] = Object.extend(newObj, parms.initial)\n"
|
|
"}\n"
|
|
"parms.$reduce(obj, aggObj);\n"
|
|
"}\n"
|
|
"\n"
|
|
"var ret = map.values();\n"
|
|
"return ret;\n"
|
|
"}\n"
|
|
"\n"
|
|
"var parms = Object.extend({}, parmsObj);\n"
|
|
"\n"
|
|
"if( parms.reduce ) {\n"
|
|
"parms.$reduce = parms.reduce; \n"
|
|
"delete parms.reduce;\n"
|
|
"}\n"
|
|
"\n"
|
|
"if( parms.keyf ) {\n"
|
|
"parms.$keyf = parms.keyf;\n"
|
|
"delete parms.keyf;\n"
|
|
"}\n"
|
|
"\n"
|
|
"return this.eval(groupFunction, parms);\n"
|
|
"}\n"
|
|
"\n"
|
|
"DB.prototype.resetError = function(){\n"
|
|
"return this.runCommand( { reseterror : 1 } );\n"
|
|
"}\n"
|
|
"\n"
|
|
"DB.prototype.forceError = function(){\n"
|
|
"return this.runCommand( { forceerror : 1 } );\n"
|
|
"}\n"
|
|
"\n"
|
|
"DB.prototype.getLastError = function(){\n"
|
|
"return this.runCommand( { getlasterror : 1 } ).err;\n"
|
|
"}\n"
|
|
"\n"
|
|
"/* Return the last error which has occurred, even if not the very last error.\n"
|
|
"\n"
|
|
"Returns:\n"
|
|
"{ err : <error message>, nPrev : <how_many_ops_back_occurred>, ok : 1 }\n"
|
|
"\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"
|
|
"\n"
|
|
"DB.prototype.getCollectionNames = function(){\n"
|
|
"var all = [];\n"
|
|
"\n"
|
|
"var nsLength = this._name.length + 1;\n"
|
|
"\n"
|
|
"this.getCollection( \"system.namespaces\" ).find().sort({name:1}).forEach(\n"
|
|
"function(z){\n"
|
|
"var name = z.name;\n"
|
|
"\n"
|
|
"if ( name.indexOf( \"$\" ) >= 0 )\n"
|
|
"return;\n"
|
|
"\n"
|
|
"all.push( name.substring( nsLength ) );\n"
|
|
"}\n"
|
|
");\n"
|
|
"return all;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DB.prototype.tojson = function(){\n"
|
|
"return this.toString();\n"
|
|
"}\n"
|
|
"\n"
|
|
"DB.prototype.toString = function(){\n"
|
|
"return this._name;\n"
|
|
"}\n"
|
|
"\n"
|
|
"\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.prototype.getReplicationInfo = function() {\n"
|
|
"if( \"local\" != this )\n"
|
|
"return { errmsg : \"this command only works for database local\" };\n"
|
|
"\n"
|
|
"var result = { };\n"
|
|
"var db = this;\n"
|
|
"var ol = db.system.namespaces.findOne({name:\"local.oplog.$main\"});\n"
|
|
"if( ol && ol.options ) {\n"
|
|
"result.logSizeMB = ol.options.size / 1000 / 1000;\n"
|
|
"} else {\n"
|
|
"result.errmsg = \"local.oplog.$main, or its options, not found in system.namespaces collection\";\n"
|
|
"return result;\n"
|
|
"}\n"
|
|
"\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"
|
|
"\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"
|
|
"result.timeDiff = tlast - tfirst;\n"
|
|
"result.timeDiffHours = result.timeDiff / 3600;\n"
|
|
"result.tFirst = (new Date(tfirst*1000)).toString();\n"
|
|
"result.tLast = (new Date(tlast*1000)).toString();\n"
|
|
"result.now = Date();\n"
|
|
"}\n"
|
|
"else {\n"
|
|
"result.errmsg = \"ts element not found in oplog objects\";\n"
|
|
"}\n"
|
|
"}\n"
|
|
"\n"
|
|
"return result;\n"
|
|
"}\n"
|
|
"/**\n"
|
|
"* Copyright (C) 2008 10gen Inc.\n"
|
|
"*\n"
|
|
"* Licensed under the Apache License, Version 2.0 (the \"License\");\n"
|
|
"* you may not use this file except in compliance with the License.\n"
|
|
"* You may obtain a copy of the License at\n"
|
|
"*\n"
|
|
"* http:\n"
|
|
"*\n"
|
|
"* Unless required by applicable law or agreed to in writing, software\n"
|
|
"* distributed under the License is distributed on an \"AS IS\" BASIS,\n"
|
|
"* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
|
|
"* See the License for the specific language governing permissions and\n"
|
|
"* limitations under the License.\n"
|
|
"*/\n"
|
|
"\n"
|
|
"/*\n"
|
|
"* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message\n"
|
|
"* Digest Algorithm, as defined in RFC 1321.\n"
|
|
"* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.\n"
|
|
"* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet\n"
|
|
"* Distributed under the BSD License\n"
|
|
"* See http:\n"
|
|
"*/\n"
|
|
"\n"
|
|
"/*\n"
|
|
"* Configurable variables. You may need to tweak these to be compatible with\n"
|
|
"* the server-side, but the defaults work in most cases.\n"
|
|
"*/\n"
|
|
"var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */\n"
|
|
"var b64pad = \"\"; /* base-64 pad character. \"=\" for strict RFC compliance */\n"
|
|
"var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */\n"
|
|
"\n"
|
|
"/*\n"
|
|
"* These are the functions you'll usually want to call\n"
|
|
"* They take string arguments and return either hex or base-64 encoded strings\n"
|
|
"*/\n"
|
|
"function hex_md5(s){\n"
|
|
"var theCore = core_md5(str2binl(s), s.length * chrsz);\n"
|
|
"return binl2hex( theCore );\n"
|
|
"}\n"
|
|
"function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}\n"
|
|
"function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}\n"
|
|
"function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }\n"
|
|
"function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }\n"
|
|
"function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }\n"
|
|
"\n"
|
|
"/*\n"
|
|
"* Perform a simple self-test to see if the VM is working\n"
|
|
"*/\n"
|
|
"function md5_vm_test()\n"
|
|
"{\n"
|
|
"var actual = hex_md5(\"abc\");\n"
|
|
"return actual == \"900150983cd24fb0d6963f7d28e17f72\";\n"
|
|
"}\n"
|
|
"\n"
|
|
"/*\n"
|
|
"* Calculate the MD5 of an array of little-endian words, and a bit length\n"
|
|
"*/\n"
|
|
"function core_md5(x, len)\n"
|
|
"{\n"
|
|
"/* append padding */\n"
|
|
"x[len >> 5] |= 0x80 << ((len) % 32);\n"
|
|
"x[(((len + 64) >>> 9) << 4) + 14] = len;\n"
|
|
"\n"
|
|
"var a = 1732584193;\n"
|
|
"var b = -271733879;\n"
|
|
"var c = -1732584194;\n"
|
|
"var d = 271733878;\n"
|
|
"\n"
|
|
"for(var i = 0; i < x.length; i += 16)\n"
|
|
"{\n"
|
|
"var olda = a;\n"
|
|
"var oldb = b;\n"
|
|
"var oldc = c;\n"
|
|
"var oldd = d;\n"
|
|
"\n"
|
|
"a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);\n"
|
|
"d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);\n"
|
|
"c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);\n"
|
|
"b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);\n"
|
|
"a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);\n"
|
|
"d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);\n"
|
|
"\n"
|
|
"c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);\n"
|
|
"b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);\n"
|
|
"a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);\n"
|
|
"d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);\n"
|
|
"c = md5_ff(c, d, a, b, x[i+10], 17, -42063);\n"
|
|
"b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);\n"
|
|
"a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);\n"
|
|
"d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);\n"
|
|
"c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);\n"
|
|
"b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);\n"
|
|
"\n"
|
|
"a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);\n"
|
|
"d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);\n"
|
|
"c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);\n"
|
|
"b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);\n"
|
|
"a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);\n"
|
|
"d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);\n"
|
|
"c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);\n"
|
|
"b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);\n"
|
|
"a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);\n"
|
|
"d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);\n"
|
|
"c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);\n"
|
|
"b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);\n"
|
|
"a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);\n"
|
|
"d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);\n"
|
|
"c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);\n"
|
|
"b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);\n"
|
|
"\n"
|
|
"\n"
|
|
"a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);\n"
|
|
"d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);\n"
|
|
"c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);\n"
|
|
"b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);\n"
|
|
"a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);\n"
|
|
"d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);\n"
|
|
"c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);\n"
|
|
"b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);\n"
|
|
"a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);\n"
|
|
"d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);\n"
|
|
"c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);\n"
|
|
"b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);\n"
|
|
"a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);\n"
|
|
"d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);\n"
|
|
"c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);\n"
|
|
"b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);\n"
|
|
"\n"
|
|
"a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);\n"
|
|
"d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);\n"
|
|
"c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);\n"
|
|
"b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);\n"
|
|
"a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);\n"
|
|
"d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);\n"
|
|
"c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);\n"
|
|
"b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);\n"
|
|
"a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);\n"
|
|
"d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);\n"
|
|
"c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);\n"
|
|
"b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);\n"
|
|
"a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);\n"
|
|
"d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);\n"
|
|
"c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);\n"
|
|
"b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);\n"
|
|
"\n"
|
|
"a = safe_add(a, olda);\n"
|
|
"b = safe_add(b, oldb);\n"
|
|
"c = safe_add(c, oldc);\n"
|
|
"d = safe_add(d, oldd);\n"
|
|
"}\n"
|
|
"\n"
|
|
"return Array(a, b, c, d);\n"
|
|
"\n"
|
|
"}\n"
|
|
"\n"
|
|
"/*\n"
|
|
"* These functions implement the four basic operations the algorithm uses.\n"
|
|
"*/\n"
|
|
"function md5_cmn(q, a, b, x, s, t)\n"
|
|
"{\n"
|
|
"return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);\n"
|
|
"}\n"
|
|
"function md5_ff(a, b, c, d, x, s, t)\n"
|
|
"{\n"
|
|
"return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);\n"
|
|
"}\n"
|
|
"function md5_gg(a, b, c, d, x, s, t)\n"
|
|
"{\n"
|
|
"return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);\n"
|
|
"}\n"
|
|
"function md5_hh(a, b, c, d, x, s, t)\n"
|
|
"{\n"
|
|
"return md5_cmn(b ^ c ^ d, a, b, x, s, t);\n"
|
|
"}\n"
|
|
"function md5_ii(a, b, c, d, x, s, t)\n"
|
|
"{\n"
|
|
"return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);\n"
|
|
"}\n"
|
|
"\n"
|
|
"/*\n"
|
|
"* Calculate the HMAC-MD5, of a key and some data\n"
|
|
"*/\n"
|
|
"function core_hmac_md5(key, data)\n"
|
|
"{\n"
|
|
"var bkey = str2binl(key);\n"
|
|
"if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);\n"
|
|
"\n"
|
|
"var ipad = Array(16), opad = Array(16);\n"
|
|
"for(var i = 0; i < 16; i = i + 1)\n"
|
|
"{\n"
|
|
"ipad[i] = bkey[i] ^ 0x36363636;\n"
|
|
"opad[i] = bkey[i] ^ 0x5C5C5C5C;\n"
|
|
"}\n"
|
|
"\n"
|
|
"var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);\n"
|
|
"return core_md5(opad.concat(hash), 512 + 128);\n"
|
|
"}\n"
|
|
"\n"
|
|
"/*\n"
|
|
"* Add integers, wrapping at 2^32. This uses 16-bit operations internally\n"
|
|
"* to work around bugs in some JS interpreters.\n"
|
|
"*/\n"
|
|
"function safe_add(x, y)\n"
|
|
"{\n"
|
|
"var lsw = (x & 0xFFFF) + (y & 0xFFFF);\n"
|
|
"var msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n"
|
|
"return (msw << 16) | (lsw & 0xFFFF);\n"
|
|
"}\n"
|
|
"\n"
|
|
"/*\n"
|
|
"* Bitwise rotate a 32-bit number to the left.\n"
|
|
"*/\n"
|
|
"function bit_rol(num, cnt)\n"
|
|
"{\n"
|
|
"return (num << cnt) | (num >>> (32 - cnt));\n"
|
|
"}\n"
|
|
"\n"
|
|
"/*\n"
|
|
"* Convert a string to an array of little-endian words\n"
|
|
"* If chrsz is ASCII, characters >255 have their hi-byte silently ignored.\n"
|
|
"*/\n"
|
|
"function str2binl(str)\n"
|
|
"{\n"
|
|
"var bin = Array();\n"
|
|
"var mask = (1 << chrsz) - 1;\n"
|
|
"for(var i = 0; i < str.length * chrsz; i += chrsz)\n"
|
|
"bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);\n"
|
|
"return bin;\n"
|
|
"}\n"
|
|
"\n"
|
|
"/*\n"
|
|
"* Convert an array of little-endian words to a string\n"
|
|
"*/\n"
|
|
"function binl2str(bin)\n"
|
|
"{\n"
|
|
"var str = \"\";\n"
|
|
"var mask = (1 << chrsz) - 1;\n"
|
|
"for(var i = 0; i < bin.length * 32; i += chrsz)\n"
|
|
"str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);\n"
|
|
"return str;\n"
|
|
"}\n"
|
|
"\n"
|
|
"/*\n"
|
|
"* Convert an array of little-endian words to a hex string.\n"
|
|
"*/\n"
|
|
"function binl2hex(binarray)\n"
|
|
"{\n"
|
|
"var hex_tab = hexcase ? \"0123456789ABCDEF\" : \"0123456789abcdef\";\n"
|
|
"var str = \"\";\n"
|
|
"for(var i = 0; i < binarray.length * 4; i = 1 + i)\n"
|
|
"{\n"
|
|
"str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +\n"
|
|
"hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);\n"
|
|
"}\n"
|
|
"return str;\n"
|
|
"}\n"
|
|
"\n"
|
|
"/*\n"
|
|
"* Convert an array of little-endian words to a base-64 string\n"
|
|
"*/\n"
|
|
"function binl2b64(binarray)\n"
|
|
"{\n"
|
|
"var tab = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n"
|
|
"var str = \"\";\n"
|
|
"for(var i = 0; i < binarray.length * 4; i += 3)\n"
|
|
"{\n"
|
|
"var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16)\n"
|
|
"| (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )\n"
|
|
"| ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);\n"
|
|
"for(var j = 0; j < 4; j = j + 1)\n"
|
|
"{\n"
|
|
"if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;\n"
|
|
"else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);\n"
|
|
"}\n"
|
|
"}\n"
|
|
"return str;\n"
|
|
"}\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
"if ( typeof Mongo == \"undefined\" ){\n"
|
|
"Mongo = function( host ){\n"
|
|
"this.init( host );\n"
|
|
"}\n"
|
|
"}\n"
|
|
"\n"
|
|
"if ( ! Mongo.prototype ){\n"
|
|
"throw \"Mongo.prototype not defined\";\n"
|
|
"}\n"
|
|
"\n"
|
|
"\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"
|
|
"Mongo.prototype.insert = function( ns , obj ){ throw \"insert not implemented\"; }\n"
|
|
"if ( ! Mongo.prototype.remove )\n"
|
|
"Mongo.prototype.remove = function( ns , pattern ){ throw \"remove not implemented;\" }\n"
|
|
"if ( ! Mongo.prototype.update )\n"
|
|
"Mongo.prototype.update = function( ns , query , obj , upsert ){ throw \"update not implemented;\" }\n"
|
|
"\n"
|
|
"if ( typeof mongoInject == \"function\" ){\n"
|
|
"mongoInject( Mongo.prototype );\n"
|
|
"}\n"
|
|
"\n"
|
|
"Mongo.prototype.setSlaveOk = function() {\n"
|
|
"this.slaveOk = true;\n"
|
|
"}\n"
|
|
"\n"
|
|
"Mongo.prototype.getDB = function( name ){\n"
|
|
"return new DB( this , name );\n"
|
|
"}\n"
|
|
"\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"
|
|
"\n"
|
|
"Mongo.prototype.getDBNames = function(){\n"
|
|
"return this.getDBs().databases.map(\n"
|
|
"function(z){\n"
|
|
"return z.name;\n"
|
|
"}\n"
|
|
");\n"
|
|
"}\n"
|
|
"\n"
|
|
"Mongo.prototype.toString = function(){\n"
|
|
"return \"mongo connection to \" + this.host;\n"
|
|
"}\n"
|
|
"\n"
|
|
"connect = function( url , user , pass ){\n"
|
|
"print( \"connecting to: \" + url )\n"
|
|
"\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"
|
|
"\n"
|
|
"var idx = url.indexOf( \"/\" );\n"
|
|
"\n"
|
|
"var db;\n"
|
|
"\n"
|
|
"if ( idx < 0 )\n"
|
|
"db = new Mongo().getDB( url );\n"
|
|
"else\n"
|
|
"db = new Mongo( url.substring( 0 , idx ) ).getDB( url.substring( idx + 1 ) );\n"
|
|
"\n"
|
|
"if ( user && pass ){\n"
|
|
"if ( ! db.auth( user , pass ) ){\n"
|
|
"throw \"couldn't login\";\n"
|
|
"}\n"
|
|
"}\n"
|
|
"\n"
|
|
"return db;\n"
|
|
"}\n"
|
|
"\n"
|
|
"\n"
|
|
"if ( typeof DBQuery == \"undefined\" ){\n"
|
|
"DBQuery = function( mongo , db , collection , ns , query , fields , limit , skip ){\n"
|
|
"\n"
|
|
"this._mongo = mongo; \n"
|
|
"this._db = db; \n"
|
|
"this._collection = collection; \n"
|
|
"this._ns = ns; \n"
|
|
"\n"
|
|
"this._query = query || {}; \n"
|
|
"this._fields = fields; \n"
|
|
"this._limit = limit || 0; \n"
|
|
"this._skip = skip || 0; \n"
|
|
"\n"
|
|
"this._cursor = null;\n"
|
|
"this._numReturned = 0;\n"
|
|
"this._special = false;\n"
|
|
"}\n"
|
|
"}\n"
|
|
"\n"
|
|
"\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"
|
|
"q._special = this._special;\n"
|
|
"return q;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBQuery.prototype._ensureSpecial = function(){\n"
|
|
"if ( this._special )\n"
|
|
"return;\n"
|
|
"\n"
|
|
"var n = { query : this._query };\n"
|
|
"this._query = n;\n"
|
|
"this._special = true;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBQuery.prototype._checkModify = function(){\n"
|
|
"if ( this._cursor )\n"
|
|
"throw \"query already executed\";\n"
|
|
"}\n"
|
|
"\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"
|
|
"\n"
|
|
"DBQuery.prototype.limit = function( limit ){\n"
|
|
"this._checkModify();\n"
|
|
"this._limit = limit;\n"
|
|
"return this;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBQuery.prototype.skip = function( skip ){\n"
|
|
"this._checkModify();\n"
|
|
"this._skip = skip;\n"
|
|
"return this;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBQuery.prototype.hasNext = function(){\n"
|
|
"this._exec();\n"
|
|
"\n"
|
|
"if ( this._limit > 0 && this._cursorSeen >= this._limit )\n"
|
|
"return false;\n"
|
|
"var o = this._cursor.hasNext();\n"
|
|
"return o;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBQuery.prototype.next = function(){\n"
|
|
"this._exec();\n"
|
|
"\n"
|
|
"var o = this._cursor.hasNext();\n"
|
|
"if ( o )\n"
|
|
"this._cursorSeen++;\n"
|
|
"else\n"
|
|
"throw \"error hasNext: \" + o;\n"
|
|
"\n"
|
|
"var ret = this._cursor.next();\n"
|
|
"if ( ret.$err && this._numReturned == 0 && ! this.hasNext() )\n"
|
|
"throw \"error: \" + tojson( ret );\n"
|
|
"\n"
|
|
"this._numReturned++;\n"
|
|
"return ret;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBQuery.prototype.toArray = function(){\n"
|
|
"if ( this._arr )\n"
|
|
"return this._arr;\n"
|
|
"\n"
|
|
"var a = [];\n"
|
|
"while ( this.hasNext() )\n"
|
|
"a.push( this.next() );\n"
|
|
"this._arr = a;\n"
|
|
"return a;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBQuery.prototype.count = function(){\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.fields = this._fields || {};\n"
|
|
"\n"
|
|
"var res = this._db.runCommand( cmd );\n"
|
|
"if( res && res.n != null ) return res.n;\n"
|
|
"throw \"count failed: \" + tojson( res );\n"
|
|
"}\n"
|
|
"\n"
|
|
"/**\n"
|
|
"* iterative count - only for testing\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"
|
|
"\n"
|
|
"DBQuery.prototype.length = function(){\n"
|
|
"return this.toArray().length;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBQuery.prototype.sort = function( sortBy ){\n"
|
|
"this._ensureSpecial();\n"
|
|
"this._query.orderby = sortBy;\n"
|
|
"return this;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBQuery.prototype.hint = function( hint ){\n"
|
|
"this._ensureSpecial();\n"
|
|
"this._query[\"$hint\"] = hint;\n"
|
|
"return this;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBQuery.prototype.min = function( min ) {\n"
|
|
"this._ensureSpecial();\n"
|
|
"this._query[\"$min\"] = min;\n"
|
|
"return this;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBQuery.prototype.max = function( max ) {\n"
|
|
"this._ensureSpecial();\n"
|
|
"this._query[\"$max\"] = max;\n"
|
|
"return this;\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBQuery.prototype.forEach = function( func ){\n"
|
|
"while ( this.hasNext() )\n"
|
|
"func( this.next() );\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBQuery.prototype.arrayAccess = function( idx ){\n"
|
|
"return this.toArray()[idx];\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBQuery.prototype.explain = function(){\n"
|
|
"var n = this.clone();\n"
|
|
"n._ensureSpecial();\n"
|
|
"n._query.$explain = true;\n"
|
|
"return n.next();\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBQuery.prototype.shellPrint = function(){\n"
|
|
"try {\n"
|
|
"var n = 0;\n"
|
|
"while ( this.hasNext() && n < 20 ){\n"
|
|
"var s = tojson( this.next() );\n"
|
|
"print( s );\n"
|
|
"n++;\n"
|
|
"}\n"
|
|
"if ( this.hasNext() )\n"
|
|
"print( \"has more\" );\n"
|
|
"}\n"
|
|
"catch ( e ){\n"
|
|
"print( e );\n"
|
|
"}\n"
|
|
"\n"
|
|
"}\n"
|
|
"\n"
|
|
"DBQuery.prototype.toString = function(){\n"
|
|
"return \"DBQuery: \" + this._ns + \" -> \" + tojson( this.query );\n"
|
|
"}\n"
|
|
"\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"
|
|
"\n"
|
|
"if ( dbpath == \"\" )\n"
|
|
"throw \"No dbpath specified\";\n"
|
|
"\n"
|
|
"return dbpath;\n"
|
|
"}\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"
|
|
"\n"
|
|
"if ( port == \"\" )\n"
|
|
"throw \"No port specified\";\n"
|
|
"return port;\n"
|
|
"}\n"
|
|
"\n"
|
|
"createMongoArgs = function( binaryName , args ){\n"
|
|
"var fullArgs = [ binaryName ];\n"
|
|
"\n"
|
|
"if ( args.length == 1 && isObject( args[0] ) ){\n"
|
|
"var o = args[0];\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"
|
|
"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"
|
|
"\n"
|
|
"return fullArgs;\n"
|
|
"}\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
"startMongod = function(){\n"
|
|
"\n"
|
|
"var args = createMongoArgs( \"mongod\" , arguments );\n"
|
|
"\n"
|
|
"var dbpath = _parsePath.apply( null, args );\n"
|
|
"resetDbpath( dbpath );\n"
|
|
"\n"
|
|
"return startMongoProgram.apply( null, args );\n"
|
|
"}\n"
|
|
"\n"
|
|
"startMongos = function(){\n"
|
|
"return startMongoProgram.apply( null, createMongoArgs( \"mongos\" , arguments ) );\n"
|
|
"}\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
"startMongoProgram = function(){\n"
|
|
"var port = _parsePort.apply( null, arguments );\n"
|
|
"\n"
|
|
"_startMongoProgram.apply( null, arguments );\n"
|
|
"\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"
|
|
"} );\n"
|
|
"\n"
|
|
"return m;\n"
|
|
"}\n"
|
|
"\n"
|
|
"ShardingTest = function( testName , numServers , verboseLevel , numMongos ){\n"
|
|
"this._connections = [];\n"
|
|
"this._serverNames = [];\n"
|
|
"\n"
|
|
"for ( var i=0; i<numServers; i++){\n"
|
|
"var conn = startMongod( { port : 30000 + i , dbpath : \"/data/db/\" + testName + i } );\n"
|
|
"conn.name = \"localhost:\" + ( 30000 + i );\n"
|
|
"\n"
|
|
"this._connections.push( conn );\n"
|
|
"this._serverNames.push( conn.name );\n"
|
|
"}\n"
|
|
"\n"
|
|
"this._configDB = \"localhost:30000\";\n"
|
|
"\n"
|
|
"\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"
|
|
"\n"
|
|
"var admin = this.admin = this.s.getDB( \"admin\" );\n"
|
|
"this.config = this.s.getDB( \"config\" );\n"
|
|
"\n"
|
|
"this._serverNames.forEach(\n"
|
|
"function(z){\n"
|
|
"admin.runCommand( { addserver : z } );\n"
|
|
"}\n"
|
|
");\n"
|
|
"}\n"
|
|
"\n"
|
|
"ShardingTest.prototype.getDB = function( name ){\n"
|
|
"return this.s.getDB( name );\n"
|
|
"}\n"
|
|
"\n"
|
|
"ShardingTest.prototype.getServerName = function( dbname ){\n"
|
|
"return this.config.databases.findOne( { name : dbname } ).primary;\n"
|
|
"}\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"
|
|
"}\n"
|
|
"\n"
|
|
"ShardingTest.prototype.getOther = function( one ){\n"
|
|
"if ( this._connections.length != 2 )\n"
|
|
"throw \"getOther only works with 2 servers\";\n"
|
|
"\n"
|
|
"if ( this._connections[0] == one )\n"
|
|
"return this._connections[1];\n"
|
|
"return this._connections[0];\n"
|
|
"}\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"
|
|
"\n"
|
|
"ShardingTest.prototype.adminCommand = function(cmd){\n"
|
|
"var res = this.admin.runCommand( cmd );\n"
|
|
"if ( res && res.ok == 1 )\n"
|
|
"return true;\n"
|
|
"\n"
|
|
"throw \"command \" + tojson( cmd ) + \" failed: \" + tojson( res );\n"
|
|
"}\n"
|
|
"\n"
|
|
"MongodRunner = function( port, dbpath, peer, arbiter ) {\n"
|
|
"this.port_ = port;\n"
|
|
"this.dbpath_ = dbpath;\n"
|
|
"this.peer_ = peer;\n"
|
|
"this.arbiter_ = arbiter;\n"
|
|
"}\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( this.arbiter_ );\n"
|
|
"args.push( \"--oplogSize\" );\n"
|
|
"\n"
|
|
"args.push( \"1\" );\n"
|
|
"}\n"
|
|
"args.push( \"--nohttpinterface\" );\n"
|
|
"if ( reuseData ) {\n"
|
|
"return startMongoProgram.apply( null, args );\n"
|
|
"} else {\n"
|
|
"return startMongod.apply( null, args );\n"
|
|
"}\n"
|
|
"}\n"
|
|
"\n"
|
|
"MongodRunner.prototype.port = function() { return this.port_; }\n"
|
|
"\n"
|
|
"MongodRunner.prototype.toString = function() { return [ this.port_, this.dbpath_, this.peer_, this.arbiter_ ].toString(); }\n"
|
|
"\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"
|
|
"\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"
|
|
"\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"
|
|
"\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"
|
|
"\n"
|
|
"ReplPair.prototype.checkSteadyState = function( state, expectedMasterHost, twoMasterOk, leftValues, rightValues, debug ) {\n"
|
|
"leftValues = leftValues || {};\n"
|
|
"rightValues = rightValues || {};\n"
|
|
"\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"
|
|
"\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"
|
|
"\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"
|
|
"\n"
|
|
"this.master_ = null;\n"
|
|
"this.slave_ = null;\n"
|
|
"return false;\n"
|
|
"}\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"
|
|
"\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"
|
|
"\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"
|
|
"\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"
|
|
"\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"
|
|
"\n"
|
|
"assert = function( b , msg ){\n"
|
|
"if ( b )\n"
|
|
"return;\n"
|
|
"\n"
|
|
"throw \"assert failed : \" + msg;\n"
|
|
"}\n"
|
|
"\n"
|
|
"assert.eq = function( a , b , msg ){\n"
|
|
"if ( a == b )\n"
|
|
"return;\n"
|
|
"\n"
|
|
"if ( a != null && b != null && a.toString() == b.toString() )\n"
|
|
"return;\n"
|
|
"\n"
|
|
"throw \"[\" + a + \"] != [\" + b + \"] are not equal : \" + msg;\n"
|
|
"}\n"
|
|
"\n"
|
|
"assert.neq = function( a , b , msg ){\n"
|
|
"if ( a != b )\n"
|
|
"return;\n"
|
|
"\n"
|
|
"throw \"[\" + a + \"] != [\" + b + \"] are equal : \" + msg;\n"
|
|
"}\n"
|
|
"\n"
|
|
"assert.soon = function( f, msg ) {\n"
|
|
"var start = new Date();\n"
|
|
"var last;\n"
|
|
"while( 1 ) {\n"
|
|
"if ( f() )\n"
|
|
"return;\n"
|
|
"if ( ( new Date() ).getTime() - start.getTime() > 30000 )\n"
|
|
"throw \"assert.soon failed: \" + f + \", msg:\" + msg;\n"
|
|
"sleep( 200 );\n"
|
|
"}\n"
|
|
"}\n"
|
|
"\n"
|
|
"assert.throws = function( func , params , msg ){\n"
|
|
"\n"
|
|
"try {\n"
|
|
"func.apply( null , params );\n"
|
|
"}\n"
|
|
"catch ( e ){\n"
|
|
"return e;\n"
|
|
"}\n"
|
|
"\n"
|
|
"throw \"did not throw exception: \" + msg ;\n"
|
|
"}\n"
|
|
"\n"
|
|
"assert.commandWorked = function( res , msg ){\n"
|
|
"if ( res.ok == 1 )\n"
|
|
"return;\n"
|
|
"\n"
|
|
"throw \"command failed: \" + tojson( res ) + \" : \" + msg;\n"
|
|
"}\n"
|
|
"\n"
|
|
"assert.commandFailed = function( res , msg ){\n"
|
|
"if ( res.ok == 0 )\n"
|
|
"return;\n"
|
|
"\n"
|
|
"throw \"command worked when it should have failed: \" + tojson( res ) + \" : \" + msg;\n"
|
|
"}\n"
|
|
"\n"
|
|
"assert.isnull = function( what , msg ){\n"
|
|
"if ( what == null )\n"
|
|
"return;\n"
|
|
"\n"
|
|
"throw \"supposed to null (\" + ( msg || \"\" ) + \") was: \" + tojson( what );\n"
|
|
"}\n"
|
|
"\n"
|
|
"Object.extend = function( dst , src ){\n"
|
|
"for ( var k in src ){\n"
|
|
"dst[k] = src[k];\n"
|
|
"}\n"
|
|
"return dst;\n"
|
|
"}\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"
|
|
"\n"
|
|
"isString = function( x ){\n"
|
|
"return typeof( x ) == \"string\";\n"
|
|
"}\n"
|
|
"\n"
|
|
"isNumber = function(x){\n"
|
|
"return typeof( x ) == \"number\";\n"
|
|
"}\n"
|
|
"\n"
|
|
"isObject = function( x ){\n"
|
|
"return typeof( x ) == \"object\";\n"
|
|
"}\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"
|
|
"\n"
|
|
"Date.timeFunc = function( theFunc , numTimes ){\n"
|
|
"\n"
|
|
"var start = new Date();\n"
|
|
"\n"
|
|
"numTimes = numTimes || 1;\n"
|
|
"for ( var i=0; i<numTimes; i++ ){\n"
|
|
"theFunc.apply( null , argumentsToArray( arguments ).slice( 2 ) );\n"
|
|
"}\n"
|
|
"\n"
|
|
"return (new Date()).getTime() - start.getTime();\n"
|
|
"}\n"
|
|
"\n"
|
|
"Date.prototype.tojson = function(){\n"
|
|
"return \"\\\"\" + this.toString() + \"\\\"\";\n"
|
|
"}\n"
|
|
"\n"
|
|
"RegExp.prototype.tojson = RegExp.prototype.toString;\n"
|
|
"\n"
|
|
"Array.prototype.contains = function( x ){\n"
|
|
"for ( var i=0; i<this.length; i++ ){\n"
|
|
"if ( this[i] == x )\n"
|
|
"return true;\n"
|
|
"}\n"
|
|
"return false;\n"
|
|
"}\n"
|
|
"\n"
|
|
"Array.prototype.unique = function( ){\n"
|
|
"var u = [];\n"
|
|
"for ( var i=0; i<this.length; i++){\n"
|
|
"var o = this[i];\n"
|
|
"if ( ! u.contains( o ) )\n"
|
|
"u.push( o );\n"
|
|
"}\n"
|
|
"return u;\n"
|
|
"}\n"
|
|
"\n"
|
|
"Array.prototype.tojson = function( sepLines ){\n"
|
|
"var s = \"[\";\n"
|
|
"if ( sepLines ) s += \"\\n\";\n"
|
|
"for ( var i=0; i<this.length; i++){\n"
|
|
"if ( i > 0 ){\n"
|
|
"s += \",\";\n"
|
|
"if ( sepLines ) s += \"\\n\";\n"
|
|
"}\n"
|
|
"s += tojson( this[i] );\n"
|
|
"}\n"
|
|
"s += \"]\";\n"
|
|
"if ( sepLines ) s += \"\\n\";\n"
|
|
"return s;\n"
|
|
"}\n"
|
|
"\n"
|
|
"if ( ! ObjectId.prototype )\n"
|
|
"ObjectId.prototype = {}\n"
|
|
"\n"
|
|
"ObjectId.prototype.toString = function(){\n"
|
|
"return this.str;\n"
|
|
"}\n"
|
|
"\n"
|
|
"ObjectId.prototype.tojson = function(){\n"
|
|
"return \"\\\"\" + this.str + \"\\\"\";\n"
|
|
"}\n"
|
|
"\n"
|
|
"ObjectId.prototype.isObjectId = true;\n"
|
|
"\n"
|
|
"Thread = function(){\n"
|
|
"this.init.apply( this, arguments );\n"
|
|
"}\n"
|
|
"\n"
|
|
"if ( typeof( threadInject ) == \"function\" )\n"
|
|
"threadInject( Thread.prototype );\n"
|
|
"else\n"
|
|
"print( \"warning: thread management won't work\" );\n"
|
|
"\n"
|
|
"fork = function() {\n"
|
|
"var t = new Thread( function() {} );\n"
|
|
"Thread.apply( t, arguments );\n"
|
|
"return t;\n"
|
|
"}\n"
|
|
"\n"
|
|
"tojson = function( x ){\n"
|
|
"if ( x == null || x == undefined )\n"
|
|
"return \"\";\n"
|
|
"\n"
|
|
"switch ( typeof x ){\n"
|
|
"\n"
|
|
"case \"string\":\n"
|
|
"return \"\\\"\" + x + \"\\\"\";\n"
|
|
"\n"
|
|
"case \"number\":\n"
|
|
"case \"boolean\":\n"
|
|
"return \"\" + x;\n"
|
|
"\n"
|
|
"case \"object\":\n"
|
|
"return tojsonObject( x );\n"
|
|
"\n"
|
|
"default:\n"
|
|
"throw \"can't handle type \" + ( typeof v );\n"
|
|
"}\n"
|
|
"\n"
|
|
"}\n"
|
|
"\n"
|
|
"tojsonObject = function( x ){\n"
|
|
"assert.eq( ( typeof x ) , \"object\" , \"tojsonObject needs object, not [\" + ( typeof x ) + \"]\" );\n"
|
|
"\n"
|
|
"if ( x.tojson )\n"
|
|
"return x.tojson();\n"
|
|
"\n"
|
|
"var s = \"{\";\n"
|
|
"\n"
|
|
"var first = true;\n"
|
|
"for ( var k in x ){\n"
|
|
"if ( first ) first = false;\n"
|
|
"else s += \" , \";\n"
|
|
"\n"
|
|
"s += \"\\\"\" + k + \"\\\" : \" + tojson( x[k] );\n"
|
|
"}\n"
|
|
"\n"
|
|
"return s + \"}\";\n"
|
|
"}\n"
|
|
"\n"
|
|
"shellPrint = function( x ){\n"
|
|
"it = x;\n"
|
|
"if ( x != undefined )\n"
|
|
"shellPrintHelper( x );\n"
|
|
"\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"
|
|
"\n"
|
|
"printjson = function(x){\n"
|
|
"print( tojson( x ) );\n"
|
|
"}\n"
|
|
"\n"
|
|
"shellPrintHelper = function( x ){\n"
|
|
"\n"
|
|
"if ( typeof x != \"object\" )\n"
|
|
"return print( x );\n"
|
|
"\n"
|
|
"var p = x.shellPrint;\n"
|
|
"if ( typeof p == \"function\" )\n"
|
|
"return x.shellPrint();\n"
|
|
"\n"
|
|
"var p = x.tojson;\n"
|
|
"if ( typeof p == \"function\" )\n"
|
|
"print( x.tojson() );\n"
|
|
"else\n"
|
|
"print( tojson( x ) );\n"
|
|
"}\n"
|
|
"\n"
|
|
"shellHelper = function( command , rest ){\n"
|
|
"command = command.trim();\n"
|
|
"var args = rest.trim().replace(/;$/,\"\").split( \"\\s+\" );\n"
|
|
"\n"
|
|
"if ( ! shellHelper[command] )\n"
|
|
"throw \"no command [\" + command + \"]\";\n"
|
|
"\n"
|
|
"return shellHelper[command].apply( null , args );\n"
|
|
"}\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"
|
|
"\n"
|
|
"shellHelper.use = function( dbname ){\n"
|
|
"db = db.getMongo().getDB( dbname );\n"
|
|
"print( \"switched to db \" + db.getName() );\n"
|
|
"}\n"
|
|
"\n"
|
|
"shellHelper.show = function( what ){\n"
|
|
"assert( typeof what == \"string\" );\n"
|
|
"\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"
|
|
"\n"
|
|
"if ( what == \"users\" )\n"
|
|
"return db.system.users.find();\n"
|
|
"\n"
|
|
"if ( what == \"collections\" || what == \"tables\" ) {\n"
|
|
"db.getCollectionNames().forEach( function(x){print(x)} );\n"
|
|
"return \"\";\n"
|
|
"}\n"
|
|
"\n"
|
|
"if ( what == \"dbs\" ) {\n"
|
|
"db.getMongo().getDBNames().sort().forEach( function(x){print(x)} );\n"
|
|
"return \"\";\n"
|
|
"}\n"
|
|
"\n"
|
|
"throw \"don't know how to show [\" + what + \"]\";\n"
|
|
"\n"
|
|
"}\n"
|
|
"\n"
|
|
"\n"
|
|
"Map = function(){\n"
|
|
"print( \"warning: Map isn't a good thing to use\" );\n"
|
|
"}\n"
|
|
"\n"
|
|
"Map.prototype.values = function(){\n"
|
|
"\n"
|
|
"var a = [];\n"
|
|
"for ( var k in this ){\n"
|
|
"var v = this[k];\n"
|
|
"if ( v == Map.prototype.values )\n"
|
|
"continue;\n"
|
|
"a.push( v );\n"
|
|
"}\n"
|
|
"return a;\n"
|
|
"}\n"
|
|
;
|
|
|