mirror of
https://github.com/mongodb/mongo.git
synced 2024-11-30 00:56:44 +01:00
2007 lines
66 KiB
C++
2007 lines
66 KiB
C++
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"
|
|
"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"
|
|
"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"
|
|
"else {\n"
|
|
"Object.extend( ret , options );\n"
|
|
"}\n"
|
|
"}\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"
|
|
");\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"
|
|
");\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"
|
|
"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"
|
|
"if ( typeof DB == \"undefined\" ){\n"
|
|
"DB = function( mongo , name ){\n"
|
|
"this._mongo = mongo;\n"
|
|
"this._name = name;\n"
|
|
"}\n"
|
|
"}\n"
|
|
"DB.prototype.getMongo = function(){\n"
|
|
"assert( this._mongo , \"why no mongo!\" );\n"
|
|
"return this._mongo;\n"
|
|
"}\n"
|
|
"DB.prototype.getSisterDB = function( name ){\n"
|
|
"return this.getMongo().getDB( name );\n"
|
|
"}\n"
|
|
"DB.prototype.getName = function(){\n"
|
|
"return this._name;\n"
|
|
"}\n"
|
|
"DB.prototype.getCollection = function( name ){\n"
|
|
"return new DBCollection( this._mongo , this , name , this._name + \".\" + name );\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"
|
|
"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"
|
|
"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"
|
|
"var c = this.getCollection( \"system.users\" );\n"
|
|
"var u = c.findOne( { user : username } ) || { user : username };\n"
|
|
"u.pwd = hex_md5( username + \":mongo:\" + pass );\n"
|
|
"print( tojson( u ) );\n"
|
|
"c.save( u );\n"
|
|
"}\n"
|
|
"DB.prototype.removeUser = function( username ){\n"
|
|
"this.getCollection( \"system.users\" ).remove( { user : username } );\n"
|
|
"}\n"
|
|
"DB.prototype.auth = function( username , pass ){\n"
|
|
"var n = this.runCommand( { getnonce : 1 } );\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"
|
|
"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"
|
|
"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"
|
|
"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"
|
|
"DB.prototype.dropDatabase = function() {\n"
|
|
"if ( arguments.length )\n"
|
|
"throw \"dropDatabase doesn't take arguments\";\n"
|
|
"return this._dbCommand( { dropDatabase: 1 } );\n"
|
|
"}\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"
|
|
"try {\n"
|
|
"this._dbCommand(\"shutdown\");\n"
|
|
"throw \"shutdownServer failed\";\n"
|
|
"}\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"
|
|
"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"
|
|
"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"
|
|
"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"
|
|
"DB.prototype.repairDatabase = function() {\n"
|
|
"return this._dbCommand( { repairDatabase: 1 } );\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.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.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() - just returns the err msg string\");\n"
|
|
"print(\"\\tdb.getLastErrorObj() - return full status object\");\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.printCollectionStats()\" );\n"
|
|
"print(\"\\tdb.version() current version of the server\" );\n"
|
|
"}\n"
|
|
"DB.prototype.printCollectionStats = function(){\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"
|
|
"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"
|
|
"DB.prototype.eval = function(jsfunction) {\n"
|
|
"var cmd = { $eval : jsfunction };\n"
|
|
"if ( arguments.length > 1 ) {\n"
|
|
"cmd.args = argumentsToArray( arguments ).slice(1);\n"
|
|
"}\n"
|
|
"var res = this._dbCommand( cmd );\n"
|
|
"if (!res.ok)\n"
|
|
"throw tojson( res );\n"
|
|
"return res.retval;\n"
|
|
"}\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"
|
|
"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 pkl = pks ? pks.length : 0;\n"
|
|
"var key = {};\n"
|
|
"while( c.hasNext() ) {\n"
|
|
"var obj = c.next();\n"
|
|
"if ( pks ) {\n"
|
|
"for( var i=0; i<pkl; i++ ){\n"
|
|
"var k = pks[i];\n"
|
|
"key[k] = obj[k];\n"
|
|
"}\n"
|
|
"}\n"
|
|
"else {\n"
|
|
"key = parms.$keyf(obj);\n"
|
|
"}\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"
|
|
"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"
|
|
"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"
|
|
"if( parms.keyf ) {\n"
|
|
"parms.$keyf = parms.keyf;\n"
|
|
"delete parms.keyf;\n"
|
|
"}\n"
|
|
"return parms;\n"
|
|
"}\n"
|
|
"DB.prototype.resetError = function(){\n"
|
|
"return this.runCommand( { reseterror : 1 } );\n"
|
|
"}\n"
|
|
"DB.prototype.forceError = function(){\n"
|
|
"return this.runCommand( { forceerror : 1 } );\n"
|
|
"}\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"
|
|
"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 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"
|
|
"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"
|
|
"return;\n"
|
|
"all.push( name.substring( nsLength ) );\n"
|
|
"}\n"
|
|
");\n"
|
|
"return all;\n"
|
|
"}\n"
|
|
"DB.prototype.tojson = function(){\n"
|
|
"return this._name;\n"
|
|
"}\n"
|
|
"DB.prototype.toString = function(){\n"
|
|
"return this._name;\n"
|
|
"}\n"
|
|
"DB.prototype.currentOp = function(){\n"
|
|
"return db.$cmd.sys.inprog.findOne();\n"
|
|
"}\n"
|
|
"DB.prototype.currentOP = DB.prototype.currentOp;\n"
|
|
"DB.prototype.killOp = function(){\n"
|
|
"return db.$cmd.sys.killop.findOne();\n"
|
|
"}\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.prototype.getReplicationInfo = function() {\n"
|
|
"var db = this.getSisterDB(\"local\");\n"
|
|
"var result = { };\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 (not --master?)\";\n"
|
|
"return result;\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"
|
|
"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 = 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"
|
|
"else {\n"
|
|
"result.errmsg = \"ts element not found in oplog objects\";\n"
|
|
"}\n"
|
|
"}\n"
|
|
"return result;\n"
|
|
"}\n"
|
|
"DB.prototype.printReplicationInfo = function() {\n"
|
|
"var result = this.getReplicationInfo();\n"
|
|
"if( result.errmsg ) {\n"
|
|
"print(tojson(result));\n"
|
|
"return;\n"
|
|
"}\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"
|
|
"DB.prototype.printSlaveReplicationInfo = function() {\n"
|
|
"function g(x) {\n"
|
|
"print(\"source: \" + x.host);\n"
|
|
"var st = new Date(x.syncedTo/4294967296*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"
|
|
"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"
|
|
"DB.prototype.serverBuildInfo = function(){\n"
|
|
"return this._adminCommand( \"buildinfo\" );\n"
|
|
"}\n"
|
|
"DB.prototype.serverStatus = function(){\n"
|
|
"return this._adminCommand( \"serverStatus\" );\n"
|
|
"}\n"
|
|
"DB.prototype.version = function(){\n"
|
|
"return this.serverBuildInfo().version;\n"
|
|
"}\n"
|
|
"if ( typeof Mongo == \"undefined\" ){\n"
|
|
"Mongo = function( host ){\n"
|
|
"this.init( host );\n"
|
|
"}\n"
|
|
"}\n"
|
|
"if ( ! Mongo.prototype ){\n"
|
|
"throw \"Mongo.prototype not defined\";\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"
|
|
"if ( typeof mongoInject == \"function\" ){\n"
|
|
"mongoInject( Mongo.prototype );\n"
|
|
"}\n"
|
|
"Mongo.prototype.setSlaveOk = function() {\n"
|
|
"this.slaveOk = true;\n"
|
|
"}\n"
|
|
"Mongo.prototype.getDB = function( name ){\n"
|
|
"return new DB( this , name );\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"
|
|
"Mongo.prototype.getDBNames = function(){\n"
|
|
"return this.getDBs().databases.map(\n"
|
|
"function(z){\n"
|
|
"return z.name;\n"
|
|
"}\n"
|
|
");\n"
|
|
"}\n"
|
|
"Mongo.prototype.toString = function(){\n"
|
|
"return \"mongo connection to \" + this.host;\n"
|
|
"}\n"
|
|
"connect = function( url , user , pass ){\n"
|
|
"print( \"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"
|
|
"var db;\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"
|
|
"if ( user && pass ){\n"
|
|
"if ( ! db.auth( user , pass ) ){\n"
|
|
"throw \"couldn't login\";\n"
|
|
"}\n"
|
|
"}\n"
|
|
"return db;\n"
|
|
"}\n"
|
|
"MR = {};\n"
|
|
"MR.init = function(){\n"
|
|
"$max = 0;\n"
|
|
"$arr = [];\n"
|
|
"emit = MR.emit;\n"
|
|
"gc();\n"
|
|
"}\n"
|
|
"MR.cleanup = function(){\n"
|
|
"MR.init();\n"
|
|
"gc();\n"
|
|
"}\n"
|
|
"MR.emit = function(k,v){\n"
|
|
"var num = 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"
|
|
"MR.doReduce = function( useDB ){\n"
|
|
"$max = 0;\n"
|
|
"for ( var i=0; i<$arr.length; i++){\n"
|
|
"var data = $arr[i];\n"
|
|
"if ( ! data )\n"
|
|
"continue;\n"
|
|
"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 = r;\n"
|
|
"}\n"
|
|
"else{\n"
|
|
"data.values = [ r ];\n"
|
|
"}\n"
|
|
"$max = Math.max( $max , data.values.length );\n"
|
|
"if ( useDB ){\n"
|
|
"if ( data.values.length == 1 ){\n"
|
|
"tempcoll.save( { _id : data.key , value : data.values[0] } );\n"
|
|
"}\n"
|
|
"else {\n"
|
|
"tempcoll.save( { _id : data.key , value : data.values } );\n"
|
|
"}\n"
|
|
"}\n"
|
|
"}\n"
|
|
"}\n"
|
|
"MR.check = function(){\n"
|
|
"if ( $max < 2000 && $arr.length < 1000 ){\n"
|
|
"return 0;\n"
|
|
"}\n"
|
|
"MR.doReduce();\n"
|
|
"if ( $max < 2000 && $arr.length < 1000 ){\n"
|
|
"return 1;\n"
|
|
"}\n"
|
|
"MR.doReduce( true );\n"
|
|
"$arr = [];\n"
|
|
"$max = 0;\n"
|
|
"reset_num();\n"
|
|
"gc();\n"
|
|
"return 2;\n"
|
|
"}\n"
|
|
"if ( typeof DBQuery == \"undefined\" ){\n"
|
|
"DBQuery = function( mongo , db , collection , ns , query , fields , limit , skip ){\n"
|
|
"this._mongo = mongo;\n"
|
|
"this._db = db;\n"
|
|
"this._collection = collection;\n"
|
|
"this._ns = ns;\n"
|
|
"this._query = query || {};\n"
|
|
"this._fields = fields;\n"
|
|
"this._limit = limit || 0;\n"
|
|
"this._skip = skip || 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"
|
|
"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.explain()\" )\n"
|
|
"print( \"\\t.forEach( func )\" )\n"
|
|
"print( \"\\t.map( func )\" )\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"
|
|
"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"
|
|
"DBQuery.prototype._checkModify = function(){\n"
|
|
"if ( this._cursor )\n"
|
|
"throw \"query already executed\";\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"
|
|
"DBQuery.prototype.limit = function( limit ){\n"
|
|
"this._checkModify();\n"
|
|
"this._limit = limit;\n"
|
|
"return this;\n"
|
|
"}\n"
|
|
"DBQuery.prototype.skip = function( skip ){\n"
|
|
"this._checkModify();\n"
|
|
"this._skip = skip;\n"
|
|
"return this;\n"
|
|
"}\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"
|
|
"DBQuery.prototype.next = function(){\n"
|
|
"this._exec();\n"
|
|
"var o = this._cursor.hasNext();\n"
|
|
"if ( o )\n"
|
|
"this._cursorSeen++;\n"
|
|
"else\n"
|
|
"throw \"error hasNext: \" + o;\n"
|
|
"var ret = this._cursor.next();\n"
|
|
"if ( ret.$err && this._numReturned == 0 && ! this.hasNext() )\n"
|
|
"throw \"error: \" + tojson( ret );\n"
|
|
"this._numReturned++;\n"
|
|
"return ret;\n"
|
|
"}\n"
|
|
"DBQuery.prototype.toArray = function(){\n"
|
|
"if ( this._arr )\n"
|
|
"return this._arr;\n"
|
|
"var a = [];\n"
|
|
"while ( this.hasNext() )\n"
|
|
"a.push( this.next() );\n"
|
|
"this._arr = a;\n"
|
|
"return a;\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"
|
|
"var res = this._db.runCommand( cmd );\n"
|
|
"if( res && res.n != null ) return res.n;\n"
|
|
"throw \"count failed: \" + tojson( res );\n"
|
|
"}\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"
|
|
"DBQuery.prototype.itcount = function(){\n"
|
|
"var num = 0;\n"
|
|
"while ( this.hasNext() ){\n"
|
|
"num++;\n"
|
|
"this.next();\n"
|
|
"}\n"
|
|
"return num;\n"
|
|
"}\n"
|
|
"DBQuery.prototype.length = function(){\n"
|
|
"return this.toArray().length;\n"
|
|
"}\n"
|
|
"DBQuery.prototype.sort = function( sortBy ){\n"
|
|
"this._ensureSpecial();\n"
|
|
"this._query.orderby = sortBy;\n"
|
|
"return this;\n"
|
|
"}\n"
|
|
"DBQuery.prototype.hint = function( hint ){\n"
|
|
"this._ensureSpecial();\n"
|
|
"this._query[\"$hint\"] = hint;\n"
|
|
"return this;\n"
|
|
"}\n"
|
|
"DBQuery.prototype.min = function( min ) {\n"
|
|
"this._ensureSpecial();\n"
|
|
"this._query[\"$min\"] = min;\n"
|
|
"return this;\n"
|
|
"}\n"
|
|
"DBQuery.prototype.max = function( max ) {\n"
|
|
"this._ensureSpecial();\n"
|
|
"this._query[\"$max\"] = max;\n"
|
|
"return this;\n"
|
|
"}\n"
|
|
"DBQuery.prototype.forEach = function( func ){\n"
|
|
"while ( this.hasNext() )\n"
|
|
"func( this.next() );\n"
|
|
"}\n"
|
|
"DBQuery.prototype.map = function( func ){\n"
|
|
"var a = [];\n"
|
|
"while ( this.hasNext() )\n"
|
|
"a.push( func( this.next() ) );\n"
|
|
"return a;\n"
|
|
"}\n"
|
|
"DBQuery.prototype.arrayAccess = function( idx ){\n"
|
|
"return this.toArray()[idx];\n"
|
|
"}\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"
|
|
"DBQuery.prototype.snapshot = function(){\n"
|
|
"this._ensureSpecial();\n"
|
|
"this._query.$snapshot = true;\n"
|
|
"return this;\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"
|
|
"___it___ = this;\n"
|
|
"}\n"
|
|
"else {\n"
|
|
"___it___ = null;\n"
|
|
"}\n"
|
|
"}\n"
|
|
"catch ( e ){\n"
|
|
"print( e );\n"
|
|
"}\n"
|
|
"}\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"
|
|
"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"
|
|
"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"
|
|
"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"
|
|
"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"
|
|
"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"
|
|
"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"
|
|
;
|
|
|