1 
  2 friendlyEqual = function( a , b ){
  3     if ( a == b )
  4         return true;
  5 
  6     if ( tojson( a ) == tojson( b ) )
  7         return true;
  8 
  9     return false;
 10 }
 11 
 12 
 13 doassert = function( msg ){
 14     print( "assert: " + msg );
 15     throw msg;
 16 }
 17 
 18 assert = function( b , msg ){
 19     if ( assert._debug && msg ) print( "in assert for: " + msg );
 20 
 21     if ( b )
 22         return;
 23     
 24     doassert( "assert failed : " + msg );
 25 }
 26 
 27 assert._debug = false;
 28 
 29 assert.eq = function( a , b , msg ){
 30     if ( assert._debug && msg ) print( "in assert for: " + msg );
 31 
 32     if ( a == b )
 33         return;
 34 
 35     if ( ( a != null && b != null ) && friendlyEqual( a , b ) )
 36         return;
 37 
 38     doassert( "[" + tojson( a ) + "] != [" + tojson( b ) + "] are not equal : " + msg );
 39 }
 40 
 41 assert.neq = function( a , b , msg ){
 42     if ( assert._debug && msg ) print( "in assert for: " + msg );
 43     if ( a != b )
 44         return;
 45 
 46     doassert( "[" + a + "] != [" + b + "] are equal : " + msg );
 47 }
 48 
 49 assert.soon = function( f, msg, timeout, interval ) {
 50     if ( assert._debug && msg ) print( "in assert for: " + msg );
 51 
 52     var start = new Date();
 53     timeout = timeout || 30000;
 54     interval = interval || 200;
 55     var last;
 56     while( 1 ) {
 57         
 58         if ( typeof( f ) == "string" ){
 59             if ( eval( f ) )
 60                 return;
 61         }
 62         else {
 63             if ( f() )
 64                 return;
 65         }
 66         
 67         if ( ( new Date() ).getTime() - start.getTime() > timeout )
 68             doassert( "assert.soon failed: " + f + ", msg:" + msg );
 69         sleep( interval );
 70     }
 71 }
 72 
 73 assert.throws = function( func , params , msg ){
 74     if ( assert._debug && msg ) print( "in assert for: " + msg );
 75     try {
 76         func.apply( null , params );
 77     }
 78     catch ( e ){
 79         return e;
 80     }
 81 
 82     doassert( "did not throw exception: " + msg );
 83 }
 84 
 85 assert.commandWorked = function( res , msg ){
 86     if ( assert._debug && msg ) print( "in assert for: " + msg );
 87 
 88     if ( res.ok == 1 )
 89         return;
 90     
 91     doassert( "command failed: " + tojson( res ) + " : " + msg );
 92 }
 93 
 94 assert.commandFailed = function( res , msg ){
 95     if ( assert._debug && msg ) print( "in assert for: " + msg );
 96 
 97     if ( res.ok == 0 )
 98         return;
 99     
100     doassert( "command worked when it should have failed: " + tojson( res ) + " : " + msg );
101 }
102 
103 assert.isnull = function( what , msg ){
104     if ( assert._debug && msg ) print( "in assert for: " + msg );
105 
106     if ( what == null )
107         return;
108     
109     doassert( "supposed to null (" + ( msg || "" ) + ") was: " + tojson( what ) );
110 }
111 
112 assert.lt = function( a , b , msg ){
113     if ( assert._debug && msg ) print( "in assert for: " + msg );
114 
115     if ( a < b )
116         return;
117     doassert( a + " is not less than " + b + " : " + msg );
118 }
119 
120 assert.gt = function( a , b , msg ){
121     if ( assert._debug && msg ) print( "in assert for: " + msg );
122 
123     if ( a > b )
124         return;
125     doassert( a + " is not greater than " + b + " : " + msg );
126 }
127 
128 Object.extend = function( dst , src , deep ){
129     for ( var k in src ){
130         var v = src[k];
131         if ( deep && typeof(v) == "object" ){
132             v = Object.extend( typeof ( v.length ) == "number" ? [] : {} , v , true );
133         }
134         dst[k] = v;
135     }
136     return dst;
137 }
138 
139 argumentsToArray = function( a ){
140     var arr = [];
141     for ( var i=0; i<a.length; i++ )
142         arr[i] = a[i];
143     return arr;
144 }
145 
146 isString = function( x ){
147     return typeof( x ) == "string";
148 }
149 
150 isNumber = function(x){
151     return typeof( x ) == "number";
152 }
153 
154 isObject = function( x ){
155     return typeof( x ) == "object";
156 }
157 
158 String.prototype.trim = function() {
159     return this.replace(/^\s+|\s+$/g,"");
160 }
161 String.prototype.ltrim = function() {
162     return this.replace(/^\s+/,"");
163 }
164 String.prototype.rtrim = function() {
165     return this.replace(/\s+$/,"");
166 }
167 
168 Date.timeFunc = function( theFunc , numTimes ){
169 
170     var start = new Date();
171     
172     numTimes = numTimes || 1;
173     for ( var i=0; i<numTimes; i++ ){
174         theFunc.apply( null , argumentsToArray( arguments ).slice( 2 ) );
175     }
176 
177     return (new Date()).getTime() - start.getTime();
178 }
179 
180 Date.prototype.tojson = function(){
181     return "\"" + this.toString() + "\"";
182 }
183 
184 RegExp.prototype.tojson = RegExp.prototype.toString;
185 
186 Array.contains = function( a  , x ){
187     for ( var i=0; i<a.length; i++ ){
188         if ( a[i] == x )
189             return true;
190     }
191     return false;
192 }
193 
194 Array.unique = function( a ){
195     var u = [];
196     for ( var i=0; i<a.length; i++){
197         var o = a[i];
198         if ( ! Array.contains( u , o ) ){
199             u.push( o );
200         }
201     }
202     return u;
203 }
204 
205 Array.shuffle = function( arr ){
206     for ( var i=0; i<arr.length-1; i++ ){
207         var pos = i+Math.floor(Math.random()*(arr.length-i));
208         var save = arr[i];
209         arr[i] = arr[pos];
210         arr[pos] = save;
211     }
212     return arr;
213 }
214 
215 
216 Array.tojson = function( a , indent ){
217     if (!indent) 
218         indent = "";
219 
220     var s = "[\n";
221     indent += "\t";
222     for ( var i=0; i<a.length; i++){
223         s += indent + tojson( a[i], indent );
224         if ( i < a.length - 1 ){
225             s += ",\n";
226         }
227     }
228     if ( a.length == 0 ) {
229         s += indent;
230     }
231 
232     indent = indent.substring(1);
233     s += "\n"+indent+"]";
234     return s;
235 }
236 
237 Array.fetchRefs = function( arr , coll ){
238     var n = [];
239     for ( var i=0; i<arr.length; i ++){
240         var z = arr[i];
241         if ( coll && coll != z.getCollection() )
242             continue;
243         n.push( z.fetch() );
244     }
245     
246     return n;
247 }
248 
249 
250 if ( ! ObjectId.prototype )
251     ObjectId.prototype = {}
252 
253 ObjectId.prototype.toString = function(){
254     return this.str;
255 }
256 
257 ObjectId.prototype.tojson = function(){
258     return "ObjectId(\"" + this.str + "\")";
259 }
260 
261 ObjectId.prototype.isObjectId = true;
262 
263 if ( typeof( DBPointer ) != "undefined" ){
264     DBPointer.prototype.fetch = function(){
265         assert( this.ns , "need a ns" );
266         assert( this.id , "need an id" );
267         
268         return db[ this.ns ].findOne( { _id : this.id } );
269     }
270     
271     DBPointer.prototype.tojson = function(indent){
272         return tojson({"ns" : this.ns, "id" : this.id}, indent);
273     }
274 
275     DBPointer.prototype.getCollection = function(){
276         return this.ns;
277     }
278     
279     DBPointer.prototype.toString = function(){
280         return "DBPointer " + this.ns + ":" + this.id;
281     }
282 }
283 else {
284     print( "warning: no DBPointer" );
285 }
286 
287 if ( typeof( DBRef ) != "undefined" ){
288     DBRef.prototype.fetch = function(){
289         assert( this.$ref , "need a ns" );
290         assert( this.$id , "need an id" );
291         
292         return db[ this.$ref ].findOne( { _id : this.$id } );
293     }
294     
295     DBRef.prototype.tojson = function(indent){
296         return tojson({"$ref" : this.$ref, "$id" : this.$id}, indent);
297     }
298 
299     DBRef.prototype.getCollection = function(){
300         return this.$ref;
301     }
302     
303     DBRef.prototype.toString = function(){
304         return this.tojson();
305     }
306 }
307 else {
308     print( "warning: no DBRef" );
309 }
310 
311 if ( typeof( BinData ) != "undefined" ){
312     BinData.prototype.tojson = function(){
313         return "BinData type: " + this.type + " len: " + this.len;
314     }
315 }
316 else {
317     print( "warning: no BinData" );
318 }
319 
320 tojson = function( x, indent , nolint ){
321     if ( x == null )
322         return "null";
323     
324     if ( x == undefined )
325         return "undefined";
326     
327     if (!indent) 
328         indent = "";
329 
330     switch ( typeof x ){
331         
332     case "string": {
333         var s = "\"";
334         for ( var i=0; i<x.length; i++ ){
335             if ( x[i] == '"' ){
336                 s += "\\\"";
337             }
338             else
339                 s += x[i];
340         }
341         return s + "\"";
342     }
343         
344     case "number": 
345     case "boolean":
346         return "" + x;
347             
348     case "object":{
349         var s = tojsonObject( x, indent , nolint );
350         if ( ( nolint == null || nolint == true ) && s.length < 70 && ( indent == null || indent.length == 0 ) ){
351             s = s.replace( /[\s\r\n ]+/gm , " " );
352         }
353         return s;
354     }
355         
356     case "function":
357         return x.toString();
358         
359 
360     default:
361         throw "tojson can't handle type " + ( typeof x );
362     }
363     
364 }
365 
366 tojsonObject = function( x, indent , nolint ){
367     var lineEnding = nolint ? " " : "\n";
368     var tabSpace = nolint ? "" : "\t";
369     
370     assert.eq( ( typeof x ) , "object" , "tojsonObject needs object, not [" + ( typeof x ) + "]" );
371 
372     if (!indent) 
373         indent = "";
374     
375     if ( typeof( x.tojson ) == "function" && x.tojson != tojson ) {
376         return x.tojson(indent,nolint);
377     }
378     
379     if ( typeof( x.constructor.tojson ) == "function" && x.constructor.tojson != tojson ) {
380         return x.constructor.tojson( x, indent , nolint );
381     }
382 
383     if ( x.toString() == "[object MaxKey]" )
384         return "{ $maxKey : 1 }";
385     if ( x.toString() == "[object MinKey]" )
386         return "{ $minKey : 1 }";
387     
388     var s = "{" + lineEnding;
389 
390     // push one level of indent
391     indent += tabSpace;
392     
393     var total = 0;
394     for ( var k in x ) total++;
395     if ( total == 0 ) {
396         s += indent + lineEnding;
397     }
398 
399     var num = 1;
400     for ( var k in x ){
401 
402         var val = x[k];
403         if ( val == DB.prototype || val == DBCollection.prototype )
404             continue;
405 
406         s += indent + "\"" + k + "\" : " + tojson( val, indent , nolint );
407         if (num != total) {
408             s += ",";
409             num++;
410         }
411         s += lineEnding;
412     }
413 
414     // pop one level of indent
415     indent = indent.substring(1);
416     return s + indent + "}";
417 }
418 
419 shellPrint = function( x ){
420     it = x;
421     if ( x != undefined )
422         shellPrintHelper( x );
423     
424     if ( db ){
425         var e = db.getPrevError();
426         if ( e.err ) {
427 	    if( e.nPrev <= 1 )
428 		print( "error on last call: " + tojson( e.err ) );
429 	    else
430 		print( "an error " + tojson(e.err) + " occurred " + e.nPrev + " operations back in the command invocation" );
431         }
432         db.resetError();
433     }
434 }
435 
436 printjson = function(x){
437     print( tojson( x ) );
438 }
439 
440 shellPrintHelper = function( x ){
441 
442     if ( typeof( x ) == "undefined" ){
443 
444         if ( typeof( db ) != "undefined" && db.getLastError ){
445             var e = db.getLastError();
446             if ( e != null )
447                 print( e );
448         }
449 
450         return;
451     }
452     
453     if ( x == null ){
454         print( "null" );
455         return;
456     }
457 
458     if ( typeof x != "object" ) 
459         return print( x );
460     
461     var p = x.shellPrint;
462     if ( typeof p == "function" )
463         return x.shellPrint();
464 
465     var p = x.tojson;
466     if ( typeof p == "function" )
467         print( x.tojson() );
468     else
469         print( tojson( x ) );
470 }
471 
472 shellHelper = function( command , rest , shouldPrint ){
473     command = command.trim();
474     var args = rest.trim().replace(/;$/,"").split( "\s+" );
475     
476     if ( ! shellHelper[command] )
477         throw "no command [" + command + "]";
478     
479     var res = shellHelper[command].apply( null , args );
480     if ( shouldPrint ){
481         shellPrintHelper( res );
482     }
483     return res;
484 }
485 
486 help = shellHelper.help = function(){
487     print( "HELP" );
488     print( "\t" + "show dbs                     show database names");
489     print( "\t" + "show collections             show collections in current database");
490     print( "\t" + "show users                   show users in current database");
491     print( "\t" + "show profile                 show most recent system.profile entries with time >= 1ms");
492     print( "\t" + "use <db name>                set curent database to <db name>" );
493     print( "\t" + "db.help()                    help on DB methods");
494     print( "\t" + "db.foo.help()                help on collection methods");
495     print( "\t" + "db.foo.find()                list objects in collection foo" );
496     print( "\t" + "db.foo.find( { a : 1 } )     list objects in foo where a == 1" );
497     print( "\t" + "it                           result of the last line evaluated; use to further iterate");
498 }
499 
500 shellHelper.use = function( dbname ){
501     db = db.getMongo().getDB( dbname );
502     print( "switched to db " + db.getName() );
503 }
504 
505 shellHelper.it = function(){
506     if ( typeof( ___it___ ) == "undefined" || ___it___ == null ){
507         print( "no cursor" );
508         return;
509     }
510     shellPrintHelper( ___it___ );
511 }
512 
513 shellHelper.show = function( what ){
514     assert( typeof what == "string" );
515     
516     if( what == "profile" ) { 
517 	if( db.system.profile.count() == 0 ) { 
518 	    print("db.system.profile is empty");
519 	    print("Use db.setProfilingLevel(2) will enable profiling");
520 	    print("Use db.system.profile.find() to show raw profile entries");
521 	} 
522 	else { 
523 	    print(); 
524 	    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");} )
525         }
526 	return "";
527     }
528 
529     if ( what == "users" ){
530 	db.system.users.find().forEach( printjson );
531         return "";
532     }
533 
534     if ( what == "collections" || what == "tables" ) {
535         db.getCollectionNames().forEach( function(x){print(x)} );
536 	return "";
537     }
538     
539     if ( what == "dbs" ) {
540         db.getMongo().getDBNames().sort().forEach( function(x){print(x)} );
541 	return "";
542     }
543     
544     throw "don't know how to show [" + what + "]";
545 
546 }
547 
548 if ( typeof( Map ) == "undefined" ){
549     Map = function(){
550         this._data = {};
551     }
552 }
553 
554 Map.hash = function( val ){
555     if ( ! val )
556         return val;
557 
558     switch ( typeof( val ) ){
559     case 'string':
560     case 'number':
561     case 'date':
562         return val.toString();
563     case 'object':
564     case 'array':
565         var s = "";
566         for ( var k in val ){
567             s += k + val[k];
568         }
569         return s;
570     }
571 
572     throw "can't hash : " + typeof( val );
573 }
574 
575 Map.prototype.put = function( key , value ){
576     var o = this._get( key );
577     var old = o.value;
578     o.value = value;
579     return old;
580 }
581 
582 Map.prototype.get = function( key ){
583     return this._get( key ).value;
584 }
585 
586 Map.prototype._get = function( key ){
587     var h = Map.hash( key );
588     var a = this._data[h];
589     if ( ! a ){
590         a = [];
591         this._data[h] = a;
592     }
593     
594     for ( var i=0; i<a.length; i++ ){
595         if ( friendlyEqual( key , a[i].key ) ){
596             return a[i];
597         }
598     }
599     var o = { key : key , value : null };
600     a.push( o );
601     return o;
602 }
603 
604 Map.prototype.values = function(){
605     var all = [];
606     for ( var k in this._data ){
607         this._data[k].forEach( function(z){ all.push( z.value ); } );
608     }
609     return all;
610 }
611 
612 if ( typeof( gc ) == "undefined" ){
613     gc = function(){
614     }
615 }
616    
617 
618 Math.sigFig = function( x , N ){
619     if ( ! N ){
620         N = 3;
621     }
622     var p = Math.pow( 10, N - Math.ceil( Math.log( Math.abs(x) ) / Math.log( 10 )) );
623     return Math.round(x*p)/p;
624 }
625 
626