1 
  2 __quiet = false;
  3 __magicNoPrint = { __magicNoPrint : 1111 }
  4 
  5 chatty = function(s){
  6     if ( ! __quiet )
  7         print( s );
  8 }
  9 
 10 friendlyEqual = function( a , b ){
 11     if ( a == b )
 12         return true;
 13 
 14     if ( tojson( a ) == tojson( b ) )
 15         return true;
 16 
 17     return false;
 18 }
 19 
 20 
 21 doassert = function (msg) {
 22     if (msg.indexOf("assert") == 0)
 23         print(msg);
 24     else
 25         print("assert: " + msg);
 26     throw msg;
 27 }
 28 
 29 assert = function( b , msg ){
 30     if ( assert._debug && msg ) print( "in assert for: " + msg );
 31 
 32     if ( b )
 33         return;
 34     
 35     doassert( msg == undefined ? "assert failed" : "assert failed : " + msg );
 36 }
 37 
 38 assert.automsg = function( b ) {
 39     assert( eval( b ), b );
 40 }
 41 
 42 assert._debug = false;
 43 
 44 assert.eq = function( a , b , msg ){
 45     if ( assert._debug && msg ) print( "in assert for: " + msg );
 46 
 47     if ( a == b )
 48         return;
 49 
 50     if ( ( a != null && b != null ) && friendlyEqual( a , b ) )
 51         return;
 52 
 53     doassert( "[" + tojson( a ) + "] != [" + tojson( b ) + "] are not equal : " + msg );
 54 }
 55 
 56 assert.eq.automsg = function( a, b ) {
 57     assert.eq( eval( a ), eval( b ), "[" + a + "] != [" + b + "]" );
 58 }
 59 
 60 assert.neq = function( a , b , msg ){
 61     if ( assert._debug && msg ) print( "in assert for: " + msg );
 62     if ( a != b )
 63         return;
 64 
 65     doassert( "[" + a + "] != [" + b + "] are equal : " + msg );
 66 }
 67 
 68 assert.repeat = function( f, msg, timeout, interval ) {
 69     if ( assert._debug && msg ) print( "in assert for: " + msg );
 70 
 71     var start = new Date();
 72     timeout = timeout || 30000;
 73     interval = interval || 200;
 74     var last;
 75     while( 1 ) {
 76         
 77         if ( typeof( f ) == "string" ){
 78             if ( eval( f ) )
 79                 return;
 80         }
 81         else {
 82             if ( f() )
 83                 return;
 84         }
 85         
 86         if ( ( new Date() ).getTime() - start.getTime() > timeout )
 87             break;
 88         sleep( interval );
 89     }
 90 }
 91     
 92 assert.soon = function( f, msg, timeout, interval ) {
 93     if ( assert._debug && msg ) print( "in assert for: " + msg );
 94 
 95     var start = new Date();
 96     timeout = timeout || 30000;
 97     interval = interval || 200;
 98     var last;
 99     while( 1 ) {
100         
101         if ( typeof( f ) == "string" ){
102             if ( eval( f ) )
103                 return;
104         }
105         else {
106             if ( f() )
107                 return;
108         }
109         
110         if ( ( new Date() ).getTime() - start.getTime() > timeout )
111             doassert( "assert.soon failed: " + f + ", msg:" + msg );
112         sleep( interval );
113     }
114 }
115 
116 assert.throws = function( func , params , msg ){
117     if ( assert._debug && msg ) print( "in assert for: " + msg );
118     try {
119         func.apply( null , params );
120     }
121     catch ( e ){
122         return e;
123     }
124 
125     doassert( "did not throw exception: " + msg );
126 }
127 
128 assert.throws.automsg = function( func, params ) {
129     assert.throws( func, params, func.toString() );
130 }
131 
132 assert.commandWorked = function( res , msg ){
133     if ( assert._debug && msg ) print( "in assert for: " + msg );
134 
135     if ( res.ok == 1 )
136         return;
137     
138     doassert( "command failed: " + tojson( res ) + " : " + msg );
139 }
140 
141 assert.commandFailed = function( res , msg ){
142     if ( assert._debug && msg ) print( "in assert for: " + msg );
143 
144     if ( res.ok == 0 )
145         return;
146     
147     doassert( "command worked when it should have failed: " + tojson( res ) + " : " + msg );
148 }
149 
150 assert.isnull = function( what , msg ){
151     if ( assert._debug && msg ) print( "in assert for: " + msg );
152 
153     if ( what == null )
154         return;
155     
156     doassert( "supposed to null (" + ( msg || "" ) + ") was: " + tojson( what ) );
157 }
158 
159 assert.lt = function( a , b , msg ){
160     if ( assert._debug && msg ) print( "in assert for: " + msg );
161 
162     if ( a < b )
163         return;
164     doassert( a + " is not less than " + b + " : " + msg );
165 }
166 
167 assert.gt = function( a , b , msg ){
168     if ( assert._debug && msg ) print( "in assert for: " + msg );
169 
170     if ( a > b )
171         return;
172     doassert( a + " is not greater than " + b + " : " + msg );
173 }
174 
175 assert.close = function( a , b , msg , places ){
176     if (places === undefined) {
177         places = 4;
178     }
179     if (Math.round((a - b) * Math.pow(10, places)) === 0) {
180         return;
181     }
182     doassert( a + " is not equal to " + b + " within " + places +
183               " places, diff: " + (a-b) + " : " + msg );
184 };
185 
186 Object.extend = function( dst , src , deep ){
187     for ( var k in src ){
188         var v = src[k];
189         if ( deep && typeof(v) == "object" ){
190             v = Object.extend( typeof ( v.length ) == "number" ? [] : {} , v , true );
191         }
192         dst[k] = v;
193     }
194     return dst;
195 }
196 
197 argumentsToArray = function( a ){
198     var arr = [];
199     for ( var i=0; i<a.length; i++ )
200         arr[i] = a[i];
201     return arr;
202 }
203 
204 isString = function( x ){
205     return typeof( x ) == "string";
206 }
207 
208 isNumber = function(x){
209     return typeof( x ) == "number";
210 }
211 
212 isObject = function( x ){
213     return typeof( x ) == "object";
214 }
215 
216 String.prototype.trim = function() {
217     return this.replace(/^\s+|\s+$/g,"");
218 }
219 String.prototype.ltrim = function() {
220     return this.replace(/^\s+/,"");
221 }
222 String.prototype.rtrim = function() {
223     return this.replace(/\s+$/,"");
224 }
225 
226 Date.timeFunc = function( theFunc , numTimes ){
227 
228     var start = new Date();
229     
230     numTimes = numTimes || 1;
231     for ( var i=0; i<numTimes; i++ ){
232         theFunc.apply( null , argumentsToArray( arguments ).slice( 2 ) );
233     }
234 
235     return (new Date()).getTime() - start.getTime();
236 }
237 
238 Date.prototype.tojson = function(){
239     return "\"" + this.toString() + "\"";
240 }
241 
242 RegExp.prototype.tojson = RegExp.prototype.toString;
243 
244 Array.contains = function( a  , x ){
245     for ( var i=0; i<a.length; i++ ){
246         if ( a[i] == x )
247             return true;
248     }
249     return false;
250 }
251 
252 Array.unique = function( a ){
253     var u = [];
254     for ( var i=0; i<a.length; i++){
255         var o = a[i];
256         if ( ! Array.contains( u , o ) ){
257             u.push( o );
258         }
259     }
260     return u;
261 }
262 
263 Array.shuffle = function( arr ){
264     for ( var i=0; i<arr.length-1; i++ ){
265         var pos = i+Random.randInt(arr.length-i);
266         var save = arr[i];
267         arr[i] = arr[pos];
268         arr[pos] = save;
269     }
270     return arr;
271 }
272 
273 
274 Array.tojson = function( a , indent ){
275     if (!indent) 
276         indent = "";
277 
278     if (a.length == 0) {
279         return "[ ]";
280     }
281 
282     var s = "[\n";
283     indent += "\t";
284     for ( var i=0; i<a.length; i++){
285         s += indent + tojson( a[i], indent );
286         if ( i < a.length - 1 ){
287             s += ",\n";
288         }
289     }
290     if ( a.length == 0 ) {
291         s += indent;
292     }
293 
294     indent = indent.substring(1);
295     s += "\n"+indent+"]";
296     return s;
297 }
298 
299 Array.fetchRefs = function( arr , coll ){
300     var n = [];
301     for ( var i=0; i<arr.length; i ++){
302         var z = arr[i];
303         if ( coll && coll != z.getCollection() )
304             continue;
305         n.push( z.fetch() );
306     }
307     
308     return n;
309 }
310 
311 Array.sum = function( arr ){
312     if ( arr.length == 0 )
313         return null;
314     var s = arr[0];
315     for ( var i=1; i<arr.length; i++ )
316         s += arr[i];
317     return s;
318 }
319 
320 Array.avg = function( arr ){
321     if ( arr.length == 0 )
322         return null;
323     return Array.sum( arr ) / arr.length;
324 }
325 
326 Array.stdDev = function( arr ){
327     var avg = Array.avg( arr );
328     var sum = 0;
329 
330     for ( var i=0; i<arr.length; i++ ){
331         sum += Math.pow( arr[i] - avg , 2 );
332     }
333 
334     return Math.sqrt( sum / arr.length );
335 }
336 
337 Object.keySet = function( o ) {
338     var ret = new Array();
339     for( i in o ) {
340         if ( !( i in o.__proto__ && o[ i ] === o.__proto__[ i ] ) ) {
341             ret.push( i );
342         }
343     }
344     return ret;
345 }
346 
347 if ( ! ObjectId.prototype )
348     ObjectId.prototype = {}
349 
350 ObjectId.prototype.toString = function(){
351     return this.str;
352 }
353 
354 ObjectId.prototype.tojson = function(){
355     return "ObjectId(\"" + this.str + "\")";
356 }
357 
358 ObjectId.prototype.isObjectId = true;
359 
360 ObjectId.prototype.getTimestamp = function(){
361     return new Date(parseInt(this.toString().slice(0,8), 16)*1000);
362 }
363 
364 if ( typeof( DBPointer ) != "undefined" ){
365     DBPointer.prototype.fetch = function(){
366         assert( this.ns , "need a ns" );
367         assert( this.id , "need an id" );
368         
369         return db[ this.ns ].findOne( { _id : this.id } );
370     }
371     
372     DBPointer.prototype.tojson = function(indent){
373         return tojson({"ns" : this.ns, "id" : this.id}, indent);
374     }
375 
376     DBPointer.prototype.getCollection = function(){
377         return this.ns;
378     }
379     
380     DBPointer.prototype.toString = function(){
381         return "DBPointer " + this.ns + ":" + this.id;
382     }
383 }
384 else {
385     print( "warning: no DBPointer" );
386 }
387 
388 if ( typeof( DBRef ) != "undefined" ){
389     DBRef.prototype.fetch = function(){
390         assert( this.$ref , "need a ns" );
391         assert( this.$id , "need an id" );
392         
393         return db[ this.$ref ].findOne( { _id : this.$id } );
394     }
395     
396     DBRef.prototype.tojson = function(indent){
397         return tojson({"$ref" : this.$ref, "$id" : this.$id}, indent);
398     }
399 
400     DBRef.prototype.getCollection = function(){
401         return this.$ref;
402     }
403     
404     DBRef.prototype.toString = function(){
405         return this.tojson();
406     }
407 }
408 else {
409     print( "warning: no DBRef" );
410 }
411 
412 if ( typeof( BinData ) != "undefined" ){
413     BinData.prototype.tojson = function(){
414         return "BinData type: " + this.type + " len: " + this.len;
415     }
416 }
417 else {
418     print( "warning: no BinData" );
419 }
420 
421 if ( typeof _threadInject != "undefined" ){
422     print( "fork() available!" );
423     
424     Thread = function(){
425         this.init.apply( this, arguments );
426     }
427     _threadInject( Thread.prototype );
428     
429     ScopedThread = function() {
430         this.init.apply( this, arguments );
431     }
432     ScopedThread.prototype = new Thread( function() {} );
433     _scopedThreadInject( ScopedThread.prototype );
434     
435     fork = function() {
436         var t = new Thread( function() {} );
437         Thread.apply( t, arguments );
438         return t;
439     }    
440 
441     // Helper class to generate a list of events which may be executed by a ParallelTester
442     EventGenerator = function( me, collectionName, mean ) {
443         this.mean = mean;
444         this.events = new Array( me, collectionName );
445     }
446     
447     EventGenerator.prototype._add = function( action ) {
448         this.events.push( [ Random.genExp( this.mean ), action ] );
449     }
450     
451     EventGenerator.prototype.addInsert = function( obj ) {
452         this._add( "t.insert( " + tojson( obj ) + " )" );
453     }
454 
455     EventGenerator.prototype.addRemove = function( obj ) {
456         this._add( "t.remove( " + tojson( obj ) + " )" );
457     }
458 
459     EventGenerator.prototype.addUpdate = function( objOld, objNew ) {
460         this._add( "t.update( " + tojson( objOld ) + ", " + tojson( objNew ) + " )" );
461     }
462     
463     EventGenerator.prototype.addCheckCount = function( count, query, shouldPrint, checkQuery ) {
464         query = query || {};
465         shouldPrint = shouldPrint || false;
466         checkQuery = checkQuery || false;
467         var action = "assert.eq( " + count + ", t.count( " + tojson( query ) + " ) );"
468         if ( checkQuery ) {
469             action += " assert.eq( " + count + ", t.find( " + tojson( query ) + " ).toArray().length );"
470         }
471         if ( shouldPrint ) {
472             action += " print( me + ' ' + " + count + " );";
473         }
474         this._add( action );
475     }
476     
477     EventGenerator.prototype.getEvents = function() {
478         return this.events;
479     }
480     
481     EventGenerator.dispatch = function() {
482         var args = argumentsToArray( arguments );
483         var me = args.shift();
484         var collectionName = args.shift();
485         var m = new Mongo( db.getMongo().host );
486         var t = m.getDB( "test" )[ collectionName ];
487         for( var i in args ) {
488             sleep( args[ i ][ 0 ] );
489             eval( args[ i ][ 1 ] );
490         }
491     }
492     
493     // Helper class for running tests in parallel.  It assembles a set of tests
494     // and then calls assert.parallelests to run them.
495     ParallelTester = function() {
496         this.params = new Array();
497     }
498     
499     ParallelTester.prototype.add = function( fun, args ) {
500         args = args || [];
501         args.unshift( fun );
502         this.params.push( args );
503     }
504     
505     ParallelTester.prototype.run = function( msg, newScopes ) {
506         newScopes = newScopes || false;
507         assert.parallelTests( this.params, msg, newScopes );
508     }
509     
510     // creates lists of tests from jstests dir in a format suitable for use by
511     // ParallelTester.fileTester.  The lists will be in random order.
512     // n: number of lists to split these tests into
513     ParallelTester.createJstestsLists = function( n ) {
514         var params = new Array();
515         for( var i = 0; i < n; ++i ) {
516             params.push( [] );
517         }
518 
519         var makeKeys = function( a ) {
520             var ret = {};
521             for( var i in a ) {
522                 ret[ a[ i ] ] = 1;
523             }
524             return ret;
525         }
526         
527         // some tests can't run in parallel with most others
528         var skipTests = makeKeys( [ "jstests/dbadmin.js",
529                                    "jstests/repair.js",
530                                    "jstests/cursor8.js",
531                                    "jstests/recstore.js",
532                                    "jstests/extent.js",
533                                    "jstests/indexb.js",
534                                    "jstests/profile1.js",
535                                    "jstests/mr3.js",
536                                    "jstests/indexh.js",
537                                    "jstests/apitest_db.js"] );
538         
539         // some tests can't be run in parallel with each other
540         var serialTestsArr = [ "jstests/fsync.js",
541                               "jstests/fsync2.js" ];
542         var serialTests = makeKeys( serialTestsArr );
543         
544         params[ 0 ] = serialTestsArr;
545         
546         var files = listFiles("jstests");
547         files = Array.shuffle( files );
548         
549         var i = 0;
550         files.forEach(
551                       function(x) {
552                       
553                       if ( /_runner/.test(x.name) ||
554                           /_lodeRunner/.test(x.name) ||
555                           ( x.name in skipTests ) ||
556                           ( x.name in serialTests ) ||
557                           ! /\.js$/.test(x.name ) ){ 
558                       print(" >>>>>>>>>>>>>>> skipping " + x.name);
559                       return;
560                       }
561                       
562                       params[ i % n ].push( x.name );
563                       ++i;
564                       }
565         );
566         
567         // randomize ordering of the serialTests
568         params[ 0 ] = Array.shuffle( params[ 0 ] );
569         
570         for( var i in params ) {
571             params[ i ].unshift( i );
572         }
573         
574         return params;
575     }
576     
577     // runs a set of test files
578     // first argument is an identifier for this tester, remaining arguments are file names
579     ParallelTester.fileTester = function() {
580         var args = argumentsToArray( arguments );
581         var suite = args.shift();
582         args.forEach(
583                      function( x ) {
584                      print("         S" + suite + " Test : " + x + " ...");
585                      var time = Date.timeFunc( function() { load(x); }, 1);
586                      print("         S" + suite + " Test : " + x + " " + time + "ms" );
587                      }
588                      );        
589     }
590     
591     // params: array of arrays, each element of which consists of a function followed
592     // by zero or more arguments to that function.  Each function and its arguments will
593     // be called in a separate thread.
594     // msg: failure message
595     // newScopes: if true, each thread starts in a fresh scope
596     assert.parallelTests = function( params, msg, newScopes ) {
597         newScopes = newScopes || false;
598         var wrapper = function( fun, argv ) {
599                    eval (
600                          "var z = function() {" +
601                          "var __parallelTests__fun = " + fun.toString() + ";" +
602                          "var __parallelTests__argv = " + tojson( argv ) + ";" +
603                          "var __parallelTests__passed = false;" +
604                          "try {" +
605                             "__parallelTests__fun.apply( 0, __parallelTests__argv );" +
606                             "__parallelTests__passed = true;" +
607                          "} catch ( e ) {" +
608                             "print( e );" +
609                          "}" +
610                          "return __parallelTests__passed;" +
611                          "}"
612                          );
613             return z;
614         }
615         var runners = new Array();
616         for( var i in params ) {
617             var param = params[ i ];
618             var test = param.shift();
619             var t;
620             if ( newScopes )
621                 t = new ScopedThread( wrapper( test, param ) );
622             else
623                 t = new Thread( wrapper( test, param ) );
624             runners.push( t );
625         }
626         
627         runners.forEach( function( x ) { x.start(); } );
628         var nFailed = 0;
629         // v8 doesn't like it if we exit before all threads are joined (SERVER-529)
630         runners.forEach( function( x ) { if( !x.returnData() ) { ++nFailed; } } );        
631         assert.eq( 0, nFailed, msg );
632     }
633 }
634 
635 tojsononeline = function( x ){
636     return tojson( x , " " , true );
637 }
638 
639 tojson = function( x, indent , nolint ){
640     if ( x === null )
641         return "null";
642     
643     if ( x === undefined )
644         return "undefined";
645     
646     if (!indent) 
647         indent = "";
648 
649     switch ( typeof x ) {
650     case "string": {
651         var s = "\"";
652         for ( var i=0; i<x.length; i++ ){
653             if ( x[i] == '"' ){
654                 s += "\\\"";
655             }
656             else
657                 s += x[i];
658         }
659         return s + "\"";
660     }
661     case "number": 
662     case "boolean":
663         return "" + x;
664     case "object":{
665         var s = tojsonObject( x, indent , nolint );
666         if ( ( nolint == null || nolint == true ) && s.length < 80 && ( indent == null || indent.length == 0 ) ){
667             s = s.replace( /[\s\r\n ]+/gm , " " );
668         }
669         return s;
670     }
671     case "function":
672         return x.toString();
673     default:
674         throw "tojson can't handle type " + ( typeof x );
675     }
676     
677 }
678 
679 tojsonObject = function( x, indent , nolint ){
680     var lineEnding = nolint ? " " : "\n";
681     var tabSpace = nolint ? "" : "\t";
682     
683     assert.eq( ( typeof x ) , "object" , "tojsonObject needs object, not [" + ( typeof x ) + "]" );
684 
685     if (!indent) 
686         indent = "";
687     
688     if ( typeof( x.tojson ) == "function" && x.tojson != tojson ) {
689         return x.tojson(indent,nolint);
690     }
691     
692     if ( x.constructor && typeof( x.constructor.tojson ) == "function" && x.constructor.tojson != tojson ) {
693         return x.constructor.tojson( x, indent , nolint );
694     }
695 
696     if ( x.toString() == "[object MaxKey]" )
697         return "{ $maxKey : 1 }";
698     if ( x.toString() == "[object MinKey]" )
699         return "{ $minKey : 1 }";
700     
701     var s = "{" + lineEnding;
702 
703     // push one level of indent
704     indent += tabSpace;
705     
706     var total = 0;
707     for ( var k in x ) total++;
708     if ( total == 0 ) {
709         s += indent + lineEnding;
710     }
711 
712     var keys = x;
713     if ( typeof( x._simpleKeys ) == "function" )
714         keys = x._simpleKeys();
715     var num = 1;
716     for ( var k in keys ){
717         
718         var val = x[k];
719         if ( val == DB.prototype || val == DBCollection.prototype )
720             continue;
721 
722         s += indent + "\"" + k + "\" : " + tojson( val, indent , nolint );
723         if (num != total) {
724             s += ",";
725             num++;
726         }
727         s += lineEnding;
728     }
729 
730     // pop one level of indent
731     indent = indent.substring(1);
732     return s + indent + "}";
733 }
734 
735 shellPrint = function( x ){
736     it = x;
737     if ( x != undefined )
738         shellPrintHelper( x );
739     
740     if ( db ){
741         var e = db.getPrevError();
742         if ( e.err ) {
743 	    if( e.nPrev <= 1 )
744 		print( "error on last call: " + tojson( e.err ) );
745 	    else
746 		print( "an error " + tojson(e.err) + " occurred " + e.nPrev + " operations back in the command invocation" );
747         }
748         db.resetError();
749     }
750 }
751 
752 printjson = function(x){
753     print( tojson( x ) );
754 }
755 
756 printjsononeline = function(x){
757     print( tojsononeline( x ) );
758 }
759 
760 shellPrintHelper = function( x ){
761 
762     if ( typeof( x ) == "undefined" ){
763 
764         if ( typeof( db ) != "undefined" && db.getLastError ){
765             var e = db.getLastError();
766             if ( e != null )
767                 print( e );
768         }
769 
770         return;
771     }
772     
773     if ( x == __magicNoPrint )
774         return;
775 
776     if ( x == null ){
777         print( "null" );
778         return;
779     }
780 
781     if ( typeof x != "object" ) 
782         return print( x );
783     
784     var p = x.shellPrint;
785     if ( typeof p == "function" )
786         return x.shellPrint();
787 
788     var p = x.tojson;
789     if ( typeof p == "function" )
790         print( x.tojson() );
791     else
792         print( tojson( x ) );
793 }
794 
795 shellAutocomplete = function( prefix ){
796     var a = [];
797     //a.push( prefix + "z" )
798     //a.push( prefix + "y" )
799     __autocomplete__ = a;
800 }
801 
802 shellHelper = function( command , rest , shouldPrint ){
803     command = command.trim();
804     var args = rest.trim().replace(/;$/,"").split( "\s+" );
805     
806     if ( ! shellHelper[command] )
807         throw "no command [" + command + "]";
808     
809     var res = shellHelper[command].apply( null , args );
810     if ( shouldPrint ){
811         shellPrintHelper( res );
812     }
813     return res;
814 }
815 
816 help = shellHelper.help = function (x) {
817     if (x == "admin") {
818         print("\tls([path])                    list files");
819         print("\tpwd()                         returns current directory");
820         print("\tlistFiles([path])             returns file list");
821         print("\thostname()                    returns name of this host");
822         print("\tremoveFile(f)                 delete a file");
823         print("\tload(jsfilename)              load and execute a .js file");
824         print("\trun(program[, args...])       spawn a program and wait for its completion");
825         print("\tsleep(m)                      sleep m milliseconds");
826         print("\tgetMemInfo()                  diagnostic");
827     }
828     if (x == "test") {
829         print("\tstartMongodEmpty(args)        DELETES DATA DIR and then starts mongod");
830         print("\t                              returns a connection to the new server");
831         print("\tstartMongodTest()             DELETES DATA DIR");
832         print("\t                              automatically picks port #s starting at 27000 and increasing");
833         print("\t                              or you can specify the port as the first arg");
834         print("\t                              dir is /data/db/<port>/ if not specified as the 2nd arg");
835         print("\t                              returns a connection to the new server");
836         return;
837     }
838     print("\t" + "help admin                   misc shell commands");
839     print("\t" + "show dbs                     show database names");
840     print("\t" + "show collections             show collections in current database");
841     print("\t" + "show users                   show users in current database");
842     print("\t" + "show profile                 show most recent system.profile entries with time >= 1ms");
843     print("\t" + "use <db name>                set current database to <db name>");
844     print("\t" + "db.help()                    help on DB methods");
845     print("\t" + "db.foo.help()                help on collection methods");
846     print("\t" + "db.foo.find()                list objects in collection foo");
847     print("\t" + "db.foo.find( { a : 1 } )     list objects in foo where a == 1");
848     print("\t" + "it                           result of the last line evaluated; use to further iterate");
849     print("\t" + "exit                         quit the mongo shell");
850 }
851 
852 shellHelper.use = function( dbname ){
853     db = db.getMongo().getDB( dbname );
854     print( "switched to db " + db.getName() );
855 }
856 
857 shellHelper.it = function(){
858     if ( typeof( ___it___ ) == "undefined" || ___it___ == null ){
859         print( "no cursor" );
860         return;
861     }
862     shellPrintHelper( ___it___ );
863 }
864 
865 shellHelper.show = function( what ){
866     assert( typeof what == "string" );
867     
868     if( what == "profile" ) { 
869 	if( db.system.profile.count() == 0 ) { 
870 	    print("db.system.profile is empty");
871 	    print("Use db.setProfilingLevel(2) will enable profiling");
872 	    print("Use db.system.profile.find() to show raw profile entries");
873 	} 
874 	else { 
875 	    print(); 
876 	    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");} )
877         }
878 	return "";
879     }
880 
881     if ( what == "users" ){
882 	db.system.users.find().forEach( printjson );
883         return "";
884     }
885 
886     if ( what == "collections" || what == "tables" ) {
887         db.getCollectionNames().forEach( function(x){print(x)} );
888 	return "";
889     }
890     
891     if ( what == "dbs" ) {
892         db.getMongo().getDBNames().sort().forEach( function(x){print(x)} );
893 	return "";
894     }
895     
896     throw "don't know how to show [" + what + "]";
897 
898 }
899 
900 if ( typeof( Map ) == "undefined" ){
901     Map = function(){
902         this._data = {};
903     }
904 }
905 
906 Map.hash = function( val ){
907     if ( ! val )
908         return val;
909 
910     switch ( typeof( val ) ){
911     case 'string':
912     case 'number':
913     case 'date':
914         return val.toString();
915     case 'object':
916     case 'array':
917         var s = "";
918         for ( var k in val ){
919             s += k + val[k];
920         }
921         return s;
922     }
923 
924     throw "can't hash : " + typeof( val );
925 }
926 
927 Map.prototype.put = function( key , value ){
928     var o = this._get( key );
929     var old = o.value;
930     o.value = value;
931     return old;
932 }
933 
934 Map.prototype.get = function( key ){
935     return this._get( key ).value;
936 }
937 
938 Map.prototype._get = function( key ){
939     var h = Map.hash( key );
940     var a = this._data[h];
941     if ( ! a ){
942         a = [];
943         this._data[h] = a;
944     }
945     
946     for ( var i=0; i<a.length; i++ ){
947         if ( friendlyEqual( key , a[i].key ) ){
948             return a[i];
949         }
950     }
951     var o = { key : key , value : null };
952     a.push( o );
953     return o;
954 }
955 
956 Map.prototype.values = function(){
957     var all = [];
958     for ( var k in this._data ){
959         this._data[k].forEach( function(z){ all.push( z.value ); } );
960     }
961     return all;
962 }
963 
964 if ( typeof( gc ) == "undefined" ){
965     gc = function(){
966     }
967 }
968    
969 
970 Math.sigFig = function( x , N ){
971     if ( ! N ){
972         N = 3;
973     }
974     var p = Math.pow( 10, N - Math.ceil( Math.log( Math.abs(x) ) / Math.log( 10 )) );
975     return Math.round(x*p)/p;
976 }
977 
978 Random = function() {}
979 
980 // set random seed
981 Random.srand = function( s ) { _srand( s ); }
982 
983 // random number 0 <= r < 1
984 Random.rand = function() { return _rand(); }
985 
986 // random integer 0 <= r < n
987 Random.randInt = function( n ) { return Math.floor( Random.rand() * n ); }
988 
989 Random.setRandomSeed = function( s ) {
990     s = s || new Date().getTime();
991     print( "setting random seed: " + s );
992     Random.srand( s );
993 }
994 
995 // generate a random value from the exponential distribution with the specified mean
996 Random.genExp = function( mean ) {
997     return -Math.log( Random.rand() ) * mean;
998 }
999 
1000 killWithUris = function( uris ) {
1001     var inprog = db.currentOp().inprog;
1002     for( var u in uris ) {
1003         for ( var i in inprog ) {
1004             if ( uris[ u ] == inprog[ i ].client ) {
1005                 db.killOp( inprog[ i ].opid );
1006             }
1007         }
1008     }
1009 }
1010 
1011 Geo = {};
1012 Geo.distance = function( a , b ){
1013     var ax = null;
1014     var ay = null;
1015     var bx = null;
1016     var by = null;
1017     
1018     for ( var key in a ){
1019         if ( ax == null )
1020             ax = a[key];
1021         else if ( ay == null )
1022             ay = a[key];
1023     }
1024     
1025     for ( var key in b ){
1026         if ( bx == null )
1027             bx = b[key];
1028         else if ( by == null )
1029             by = b[key];
1030     }
1031 
1032     return Math.sqrt( Math.pow( by - ay , 2 ) + 
1033                       Math.pow( bx - ax , 2 ) );
1034 }
1035