1 // db.js 2 3 if ( typeof DB == "undefined" ){ 4 DB = function( mongo , name ){ 5 this._mongo = mongo; 6 this._name = name; 7 } 8 } 9 10 DB.prototype.getMongo = function(){ 11 assert( this._mongo , "why no mongo!" ); 12 return this._mongo; 13 } 14 15 DB.prototype.getSiblingDB = function( name ){ 16 return this.getMongo().getDB( name ); 17 } 18 19 DB.prototype.getSisterDB = DB.prototype.getSiblingDB; 20 21 DB.prototype.getName = function(){ 22 return this._name; 23 } 24 25 DB.prototype.stats = function(){ 26 return this.runCommand( { dbstats : 1 } ); 27 } 28 29 DB.prototype.getCollection = function( name ){ 30 return new DBCollection( this._mongo , this , name , this._name + "." + name ); 31 } 32 33 DB.prototype.commandHelp = function( name ){ 34 var c = {}; 35 c[name] = 1; 36 c.help = true; 37 var res = this.runCommand( c ); 38 if ( ! res.ok ) 39 throw res.errmsg; 40 return res.help; 41 } 42 43 DB.prototype.runCommand = function( obj ){ 44 if ( typeof( obj ) == "string" ){ 45 var n = {}; 46 n[obj] = 1; 47 obj = n; 48 } 49 return this.getCollection( "$cmd" ).findOne( obj ); 50 } 51 52 DB.prototype._dbCommand = DB.prototype.runCommand; 53 54 DB.prototype.adminCommand = function( obj ){ 55 if ( this._name == "admin" ) 56 return this.runCommand( obj ); 57 return this.getSiblingDB( "admin" ).runCommand( obj ); 58 } 59 60 DB.prototype._adminCommand = DB.prototype.adminCommand; // alias old name 61 62 DB.prototype.addUser = function( username , pass, readOnly ){ 63 readOnly = readOnly || false; 64 var c = this.getCollection( "system.users" ); 65 66 var u = c.findOne( { user : username } ) || { user : username }; 67 u.readOnly = readOnly; 68 u.pwd = hex_md5( username + ":mongo:" + pass ); 69 print( tojson( u ) ); 70 71 c.save( u ); 72 } 73 74 DB.prototype.removeUser = function( username ){ 75 this.getCollection( "system.users" ).remove( { user : username } ); 76 } 77 78 DB.prototype.__pwHash = function( nonce, username, pass ) { 79 return hex_md5( nonce + username + hex_md5( username + ":mongo:" + pass ) ); 80 } 81 82 DB.prototype.auth = function( username , pass ){ 83 var n = this.runCommand( { getnonce : 1 } ); 84 85 var a = this.runCommand( 86 { 87 authenticate : 1 , 88 user : username , 89 nonce : n.nonce , 90 key : this.__pwHash( n.nonce, username, pass ) 91 } 92 ); 93 94 return a.ok; 95 } 96 97 /** 98 Create a new collection in the database. Normally, collection creation is automatic. You would 99 use this function if you wish to specify special options on creation. 100 101 If the collection already exists, no action occurs. 102 103 <p>Options:</p> 104 <ul> 105 <li> 106 size: desired initial extent size for the collection. Must be <= 1000000000. 107 for fixed size (capped) collections, this size is the total/max size of the 108 collection. 109 </li> 110 <li> 111 capped: if true, this is a capped collection (where old data rolls out). 112 </li> 113 <li> max: maximum number of objects if capped (optional).</li> 114 </ul> 115 116 <p>Example: </p> 117 118 <code>db.createCollection("movies", { size: 10 * 1024 * 1024, capped:true } );</code> 119 120 * @param {String} name Name of new collection to create 121 * @param {Object} options Object with options for call. Options are listed above. 122 * @return SOMETHING_FIXME 123 */ 124 DB.prototype.createCollection = function(name, opt) { 125 var options = opt || {}; 126 var cmd = { create: name, capped: options.capped, size: options.size, max: options.max }; 127 var res = this._dbCommand(cmd); 128 return res; 129 } 130 131 /** 132 * @deprecated use getProfilingStatus 133 * Returns the current profiling level of this database 134 * @return SOMETHING_FIXME or null on error 135 */ 136 DB.prototype.getProfilingLevel = function() { 137 var res = this._dbCommand( { profile: -1 } ); 138 return res ? res.was : null; 139 } 140 141 /** 142 * @return the current profiling status 143 * example { was : 0, slowms : 100 } 144 * @return SOMETHING_FIXME or null on error 145 */ 146 DB.prototype.getProfilingStatus = function() { 147 var res = this._dbCommand( { profile: -1 } ); 148 if ( ! res.ok ) 149 throw "profile command failed: " + tojson( res ); 150 delete res.ok 151 return res; 152 } 153 154 155 /** 156 Erase the entire database. (!) 157 158 * @return Object returned has member ok set to true if operation succeeds, false otherwise. 159 */ 160 DB.prototype.dropDatabase = function() { 161 if ( arguments.length ) 162 throw "dropDatabase doesn't take arguments"; 163 return this._dbCommand( { dropDatabase: 1 } ); 164 } 165 166 167 DB.prototype.shutdownServer = function() { 168 if( "admin" != this._name ){ 169 return "shutdown command only works with the admin database; try 'use admin'"; 170 } 171 172 try { 173 var res = this._dbCommand("shutdown"); 174 if( res ) 175 throw "shutdownServer failed: " + res.errmsg; 176 throw "shutdownServer failed"; 177 } 178 catch ( e ){ 179 assert( tojson( e ).indexOf( "error doing query: failed" ) >= 0 , "unexpected error: " + tojson( e ) ); 180 print( "server should be down..." ); 181 } 182 } 183 184 /** 185 Clone database on another server to here. 186 <p> 187 Generally, you should dropDatabase() first as otherwise the cloned information will MERGE 188 into whatever data is already present in this database. (That is however a valid way to use 189 clone if you are trying to do something intentionally, such as union three non-overlapping 190 databases into one.) 191 <p> 192 This is a low level administrative function will is not typically used. 193 194 * @param {String} from Where to clone from (dbhostname[:port]). May not be this database 195 (self) as you cannot clone to yourself. 196 * @return Object returned has member ok set to true if operation succeeds, false otherwise. 197 * See also: db.copyDatabase() 198 */ 199 DB.prototype.cloneDatabase = function(from) { 200 assert( isString(from) && from.length ); 201 //this.resetIndexCache(); 202 return this._dbCommand( { clone: from } ); 203 } 204 205 206 /** 207 Clone collection on another server to here. 208 <p> 209 Generally, you should drop() first as otherwise the cloned information will MERGE 210 into whatever data is already present in this collection. (That is however a valid way to use 211 clone if you are trying to do something intentionally, such as union three non-overlapping 212 collections into one.) 213 <p> 214 This is a low level administrative function is not typically used. 215 216 * @param {String} from mongod instance from which to clnoe (dbhostname:port). May 217 not be this mongod instance, as clone from self is not allowed. 218 * @param {String} collection name of collection to clone. 219 * @param {Object} query query specifying which elements of collection are to be cloned. 220 * @return Object returned has member ok set to true if operation succeeds, false otherwise. 221 * See also: db.cloneDatabase() 222 */ 223 DB.prototype.cloneCollection = function(from, collection, query) { 224 assert( isString(from) && from.length ); 225 assert( isString(collection) && collection.length ); 226 collection = this._name + "." + collection; 227 query = query || {}; 228 //this.resetIndexCache(); 229 return this._dbCommand( { cloneCollection:collection, from:from, query:query } ); 230 } 231 232 233 /** 234 Copy database from one server or name to another server or name. 235 236 Generally, you should dropDatabase() first as otherwise the copied information will MERGE 237 into whatever data is already present in this database (and you will get duplicate objects 238 in collections potentially.) 239 240 For security reasons this function only works when executed on the "admin" db. However, 241 if you have access to said db, you can copy any database from one place to another. 242 243 This method provides a way to "rename" a database by copying it to a new db name and 244 location. Additionally, it effectively provides a repair facility. 245 246 * @param {String} fromdb database name from which to copy. 247 * @param {String} todb database name to copy to. 248 * @param {String} fromhost hostname of the database (and optionally, ":port") from which to 249 copy the data. default if unspecified is to copy from self. 250 * @return Object returned has member ok set to true if operation succeeds, false otherwise. 251 * See also: db.clone() 252 */ 253 DB.prototype.copyDatabase = function(fromdb, todb, fromhost, username, password) { 254 assert( isString(fromdb) && fromdb.length ); 255 assert( isString(todb) && todb.length ); 256 fromhost = fromhost || ""; 257 if ( username && password ) { 258 var n = this._adminCommand( { copydbgetnonce : 1, fromhost:fromhost } ); 259 return this._adminCommand( { copydb:1, fromhost:fromhost, fromdb:fromdb, todb:todb, username:username, nonce:n.nonce, key:this.__pwHash( n.nonce, username, password ) } ); 260 } else { 261 return this._adminCommand( { copydb:1, fromhost:fromhost, fromdb:fromdb, todb:todb } ); 262 } 263 } 264 265 /** 266 Repair database. 267 268 * @return Object returned has member ok set to true if operation succeeds, false otherwise. 269 */ 270 DB.prototype.repairDatabase = function() { 271 return this._dbCommand( { repairDatabase: 1 } ); 272 } 273 274 275 DB.prototype.help = function() { 276 print("DB methods:"); 277 print("\tdb.addUser(username, password[, readOnly=false])"); 278 print("\tdb.auth(username, password)"); 279 print("\tdb.cloneDatabase(fromhost)"); 280 print("\tdb.commandHelp(name) returns the help for the command"); 281 print("\tdb.copyDatabase(fromdb, todb, fromhost)"); 282 print("\tdb.createCollection(name, { size : ..., capped : ..., max : ... } )"); 283 print("\tdb.currentOp() displays the current operation in the db"); 284 print("\tdb.dropDatabase()"); 285 print("\tdb.eval(func, args) run code server-side"); 286 print("\tdb.getCollection(cname) same as db['cname'] or db.cname"); 287 print("\tdb.getCollectionNames()"); 288 print("\tdb.getLastError() - just returns the err msg string"); 289 print("\tdb.getLastErrorObj() - return full status object"); 290 print("\tdb.getMongo() get the server connection object"); 291 print("\tdb.getMongo().setSlaveOk() allow this connection to read from the nonmaster member of a replica pair"); 292 print("\tdb.getName()"); 293 print("\tdb.getPrevError()"); 294 print("\tdb.getProfilingLevel() - deprecated"); 295 print("\tdb.getProfilingStatus() - returns if profiling is on and slow threshold "); 296 print("\tdb.getReplicationInfo()"); 297 print("\tdb.getSiblingDB(name) get the db at the same server as this one"); 298 print("\tdb.isMaster() check replica primary status"); 299 print("\tdb.killOp(opid) kills the current operation in the db"); 300 print("\tdb.listCommands() lists all the db commands"); 301 print("\tdb.printCollectionStats()"); 302 print("\tdb.printReplicationInfo()"); 303 print("\tdb.printSlaveReplicationInfo()"); 304 print("\tdb.printShardingStatus()"); 305 print("\tdb.removeUser(username)"); 306 print("\tdb.repairDatabase()"); 307 print("\tdb.resetError()"); 308 print("\tdb.runCommand(cmdObj) run a database command. if cmdObj is a string, turns it into { cmdObj : 1 }"); 309 print("\tdb.serverStatus()"); 310 print("\tdb.setProfilingLevel(level,<slowms>) 0=off 1=slow 2=all"); 311 print("\tdb.shutdownServer()"); 312 print("\tdb.stats()"); 313 print("\tdb.version() current version of the server"); 314 print("\tdb.getMongo().setSlaveOk() allow queries on a replication slave server"); 315 316 return __magicNoPrint; 317 } 318 319 DB.prototype.printCollectionStats = function(){ 320 var mydb = this; 321 this.getCollectionNames().forEach( 322 function(z){ 323 print( z ); 324 printjson( mydb.getCollection(z).stats() ); 325 print( "---" ); 326 } 327 ); 328 } 329 330 /** 331 * <p> Set profiling level for your db. Profiling gathers stats on query performance. </p> 332 * 333 * <p>Default is off, and resets to off on a database restart -- so if you want it on, 334 * turn it on periodically. </p> 335 * 336 * <p>Levels :</p> 337 * <ul> 338 * <li>0=off</li> 339 * <li>1=log very slow operations; optional argument slowms specifies slowness threshold</li> 340 * <li>2=log all</li> 341 * @param {String} level Desired level of profiling 342 * @param {String} slowms For slow logging, query duration that counts as slow (default 100ms) 343 * @return SOMETHING_FIXME or null on error 344 */ 345 DB.prototype.setProfilingLevel = function(level,slowms) { 346 347 if (level < 0 || level > 2) { 348 throw { dbSetProfilingException : "input level " + level + " is out of range [0..2]" }; 349 } 350 351 var cmd = { profile: level }; 352 if ( slowms ) 353 cmd["slowms"] = slowms; 354 return this._dbCommand( cmd ); 355 } 356 357 358 /** 359 * <p> Evaluate a js expression at the database server.</p> 360 * 361 * <p>Useful if you need to touch a lot of data lightly; in such a scenario 362 * the network transfer of the data could be a bottleneck. A good example 363 * is "select count(*)" -- can be done server side via this mechanism. 364 * </p> 365 * 366 * <p> 367 * If the eval fails, an exception is thrown of the form: 368 * </p> 369 * <code>{ dbEvalException: { retval: functionReturnValue, ok: num [, errno: num] [, errmsg: str] } }</code> 370 * 371 * <p>Example: </p> 372 * <code>print( "mycount: " + db.eval( function(){db.mycoll.find({},{_id:ObjId()}).length();} );</code> 373 * 374 * @param {Function} jsfunction Javascript function to run on server. Note this it not a closure, but rather just "code". 375 * @return result of your function, or null if error 376 * 377 */ 378 DB.prototype.eval = function(jsfunction) { 379 var cmd = { $eval : jsfunction }; 380 if ( arguments.length > 1 ) { 381 cmd.args = argumentsToArray( arguments ).slice(1); 382 } 383 384 var res = this._dbCommand( cmd ); 385 386 if (!res.ok) 387 throw tojson( res ); 388 389 return res.retval; 390 } 391 392 DB.prototype.dbEval = DB.prototype.eval; 393 394 395 /** 396 * 397 * <p> 398 * Similar to SQL group by. For example: </p> 399 * 400 * <code>select a,b,sum(c) csum from coll where active=1 group by a,b</code> 401 * 402 * <p> 403 * corresponds to the following in 10gen: 404 * </p> 405 * 406 * <code> 407 db.group( 408 { 409 ns: "coll", 410 key: { a:true, b:true }, 411 // keyf: ..., 412 cond: { active:1 }, 413 reduce: function(obj,prev) { prev.csum += obj.c; } , 414 initial: { csum: 0 } 415 }); 416 </code> 417 * 418 * 419 * <p> 420 * An array of grouped items is returned. The array must fit in RAM, thus this function is not 421 * suitable when the return set is extremely large. 422 * </p> 423 * <p> 424 * To order the grouped data, simply sort it client side upon return. 425 * <p> 426 Defaults 427 cond may be null if you want to run against all rows in the collection 428 keyf is a function which takes an object and returns the desired key. set either key or keyf (not both). 429 * </p> 430 */ 431 DB.prototype.groupeval = function(parmsObj) { 432 433 var groupFunction = function() { 434 var parms = args[0]; 435 var c = db[parms.ns].find(parms.cond||{}); 436 var map = new Map(); 437 var pks = parms.key ? Object.keySet( parms.key ) : null; 438 var pkl = pks ? pks.length : 0; 439 var key = {}; 440 441 while( c.hasNext() ) { 442 var obj = c.next(); 443 if ( pks ) { 444 for( var i=0; i<pkl; i++ ){ 445 var k = pks[i]; 446 key[k] = obj[k]; 447 } 448 } 449 else { 450 key = parms.$keyf(obj); 451 } 452 453 var aggObj = map.get(key); 454 if( aggObj == null ) { 455 var newObj = Object.extend({}, key); // clone 456 aggObj = Object.extend(newObj, parms.initial) 457 map.put( key , aggObj ); 458 } 459 parms.$reduce(obj, aggObj); 460 } 461 462 return map.values(); 463 } 464 465 return this.eval(groupFunction, this._groupFixParms( parmsObj )); 466 } 467 468 DB.prototype.groupcmd = function( parmsObj ){ 469 var ret = this.runCommand( { "group" : this._groupFixParms( parmsObj ) } ); 470 if ( ! ret.ok ){ 471 throw "group command failed: " + tojson( ret ); 472 } 473 return ret.retval; 474 } 475 476 DB.prototype.group = DB.prototype.groupcmd; 477 478 DB.prototype._groupFixParms = function( parmsObj ){ 479 var parms = Object.extend({}, parmsObj); 480 481 if( parms.reduce ) { 482 parms.$reduce = parms.reduce; // must have $ to pass to db 483 delete parms.reduce; 484 } 485 486 if( parms.keyf ) { 487 parms.$keyf = parms.keyf; 488 delete parms.keyf; 489 } 490 491 return parms; 492 } 493 494 DB.prototype.resetError = function(){ 495 return this.runCommand( { reseterror : 1 } ); 496 } 497 498 DB.prototype.forceError = function(){ 499 return this.runCommand( { forceerror : 1 } ); 500 } 501 502 DB.prototype.getLastError = function( w , wtimeout ){ 503 var res = this.getLastErrorObj( w , wtimeout ); 504 if ( ! res.ok ) 505 throw "getlasterror failed: " + tojson( res ); 506 return res.err; 507 } 508 DB.prototype.getLastErrorObj = function( w , wtimeout ){ 509 var cmd = { getlasterror : 1 }; 510 if ( w ){ 511 cmd.w = w; 512 if ( wtimeout ) 513 cmd.wtimeout = wtimeout; 514 } 515 var res = this.runCommand( cmd ); 516 517 if ( ! res.ok ) 518 throw "getlasterror failed: " + tojson( res ); 519 return res; 520 } 521 DB.prototype.getLastErrorCmd = DB.prototype.getLastErrorObj; 522 523 524 /* Return the last error which has occurred, even if not the very last error. 525 526 Returns: 527 { err : <error message>, nPrev : <how_many_ops_back_occurred>, ok : 1 } 528 529 result.err will be null if no error has occurred. 530 */ 531 DB.prototype.getPrevError = function(){ 532 return this.runCommand( { getpreverror : 1 } ); 533 } 534 535 DB.prototype.getCollectionNames = function(){ 536 var all = []; 537 538 var nsLength = this._name.length + 1; 539 540 var c = this.getCollection( "system.namespaces" ).find(); 541 while ( c.hasNext() ){ 542 var name = c.next().name; 543 544 if ( name.indexOf( "$" ) >= 0 && name.indexOf( ".oplog.$" ) < 0 ) 545 continue; 546 547 all.push( name.substring( nsLength ) ); 548 } 549 550 return all.sort(); 551 } 552 553 DB.prototype.tojson = function(){ 554 return this._name; 555 } 556 557 DB.prototype.toString = function(){ 558 return this._name; 559 } 560 561 DB.prototype.isMaster = function () { return this.runCommand("isMaster"); } 562 563 DB.prototype.currentOp = function( arg ){ 564 var q = {} 565 if ( arg ) { 566 if ( typeof( arg ) == "object" ) 567 Object.extend( q , arg ); 568 else if ( arg ) 569 q["$all"] = true; 570 } 571 return db.$cmd.sys.inprog.findOne( q ); 572 } 573 DB.prototype.currentOP = DB.prototype.currentOp; 574 575 DB.prototype.killOp = function(op) { 576 if( !op ) 577 throw "no opNum to kill specified"; 578 return db.$cmd.sys.killop.findOne({'op':op}); 579 } 580 DB.prototype.killOP = DB.prototype.killOp; 581 582 DB.tsToSeconds = function(x){ 583 if ( x.t && x.i ) 584 return x.t / 1000; 585 return x / 4294967296; // low 32 bits are ordinal #s within a second 586 } 587 588 /** 589 Get a replication log information summary. 590 <p> 591 This command is for the database/cloud administer and not applicable to most databases. 592 It is only used with the local database. One might invoke from the JS shell: 593 <pre> 594 use local 595 db.getReplicationInfo(); 596 </pre> 597 It is assumed that this database is a replication master -- the information returned is 598 about the operation log stored at local.oplog.$main on the replication master. (It also 599 works on a machine in a replica pair: for replica pairs, both machines are "masters" from 600 an internal database perspective. 601 <p> 602 * @return Object timeSpan: time span of the oplog from start to end if slave is more out 603 * of date than that, it can't recover without a complete resync 604 */ 605 DB.prototype.getReplicationInfo = function() { 606 var db = this.getSiblingDB("local"); 607 608 var result = { }; 609 var oplog; 610 if (db.system.namespaces.findOne({name:"local.oplog.rs"}) != null) { 611 oplog = 'oplog.rs'; 612 } 613 else if (db.system.namespaces.findOne({name:"local.oplog.$main"}) != null) { 614 oplog = 'oplog.$main'; 615 } 616 else { 617 result.errmsg = "neither master/slave nor replica set replication detected"; 618 return result; 619 } 620 621 var ol_entry = db.system.namespaces.findOne({name:"local."+oplog}); 622 if( ol_entry && ol_entry.options ) { 623 result.logSizeMB = ol_entry.options.size / ( 1024 * 1024 ); 624 } else { 625 result.errmsg = "local."+oplog+", or its options, not found in system.namespaces collection"; 626 return result; 627 } 628 ol = db.getCollection(oplog); 629 630 result.usedMB = ol.stats().size / ( 1024 * 1024 ); 631 result.usedMB = Math.ceil( result.usedMB * 100 ) / 100; 632 633 var firstc = ol.find().sort({$natural:1}).limit(1); 634 var lastc = ol.find().sort({$natural:-1}).limit(1); 635 if( !firstc.hasNext() || !lastc.hasNext() ) { 636 result.errmsg = "objects not found in local.oplog.$main -- is this a new and empty db instance?"; 637 result.oplogMainRowCount = ol.count(); 638 return result; 639 } 640 641 var first = firstc.next(); 642 var last = lastc.next(); 643 { 644 var tfirst = first.ts; 645 var tlast = last.ts; 646 647 if( tfirst && tlast ) { 648 tfirst = DB.tsToSeconds( tfirst ); 649 tlast = DB.tsToSeconds( tlast ); 650 result.timeDiff = tlast - tfirst; 651 result.timeDiffHours = Math.round(result.timeDiff / 36)/100; 652 result.tFirst = (new Date(tfirst*1000)).toString(); 653 result.tLast = (new Date(tlast*1000)).toString(); 654 result.now = Date(); 655 } 656 else { 657 result.errmsg = "ts element not found in oplog objects"; 658 } 659 } 660 661 return result; 662 }; 663 664 DB.prototype.printReplicationInfo = function() { 665 var result = this.getReplicationInfo(); 666 if( result.errmsg ) { 667 print(tojson(result)); 668 return; 669 } 670 print("configured oplog size: " + result.logSizeMB + "MB"); 671 print("log length start to end: " + result.timeDiff + "secs (" + result.timeDiffHours + "hrs)"); 672 print("oplog first event time: " + result.tFirst); 673 print("oplog last event time: " + result.tLast); 674 print("now: " + result.now); 675 } 676 677 DB.prototype.printSlaveReplicationInfo = function() { 678 function getReplLag(st) { 679 var now = new Date(); 680 print("\t syncedTo: " + st.toString() ); 681 var ago = (now-st)/1000; 682 var hrs = Math.round(ago/36)/100; 683 print("\t\t = " + Math.round(ago) + "secs ago (" + hrs + "hrs)"); 684 }; 685 686 function g(x) { 687 assert( x , "how could this be null (printSlaveReplicationInfo gx)" ) 688 print("source: " + x.host); 689 if ( x.syncedTo ){ 690 var st = new Date( DB.tsToSeconds( x.syncedTo ) * 1000 ); 691 getReplLag(st); 692 } 693 else { 694 print( "\t doing initial sync" ); 695 } 696 }; 697 698 function r(x) { 699 assert( x , "how could this be null (printSlaveReplicationInfo rx)" ); 700 if ( x.state == 1 ) { 701 return; 702 } 703 704 print("source: " + x.name); 705 if ( x.optime ) { 706 getReplLag(x.optimeDate); 707 } 708 else { 709 print( "\t no replication info, yet. State: " + x.stateStr ); 710 } 711 }; 712 713 var L = this.getSiblingDB("local"); 714 if( L.sources.count() != 0 ) { 715 L.sources.find().forEach(g); 716 } 717 else if (L.system.replset.count() != 0) { 718 var status = this.adminCommand({'replSetGetStatus' : 1}); 719 status.members.forEach(r); 720 } 721 else { 722 print("local.sources is empty; is this db a --slave?"); 723 return; 724 } 725 } 726 727 DB.prototype.serverBuildInfo = function(){ 728 return this._adminCommand( "buildinfo" ); 729 } 730 731 DB.prototype.serverStatus = function(){ 732 return this._adminCommand( "serverStatus" ); 733 } 734 735 DB.prototype.serverCmdLineOpts = function(){ 736 return this._adminCommand( "getCmdLineOpts" ); 737 } 738 739 DB.prototype.version = function(){ 740 return this.serverBuildInfo().version; 741 } 742 743 DB.prototype.serverBits = function(){ 744 return this.serverBuildInfo().bits; 745 } 746 747 DB.prototype.listCommands = function(){ 748 var x = this.runCommand( "listCommands" ); 749 for ( var name in x.commands ){ 750 var c = x.commands[name]; 751 752 var s = name + ": "; 753 754 switch ( c.lockType ){ 755 case -1: s += "read-lock"; break; 756 case 0: s += "no-lock"; break; 757 case 1: s += "write-lock"; break; 758 default: s += c.lockType; 759 } 760 761 if (c.adminOnly) s += " adminOnly "; 762 if (c.adminOnly) s += " slaveOk "; 763 764 s += "\n "; 765 s += c.help.replace(/\n/g, '\n '); 766 s += "\n"; 767 768 print( s ); 769 } 770 } 771 772 DB.prototype.printShardingStatus = function( verbose ){ 773 printShardingStatus( this.getSiblingDB( "config" ) , verbose ); 774 } 775 776 DB.autocomplete = function(obj){ 777 var colls = obj.getCollectionNames(); 778 var ret=[]; 779 for (var i=0; i<colls.length; i++){ 780 if (colls[i].match(/^[a-zA-Z0-9_.\$]+$/)) 781 ret.push(colls[i]); 782 } 783 return ret; 784 } 785