diff --git a/bson/stringdata.h b/bson/stringdata.h index ced4cd8b56718..c787b06087314 100644 --- a/bson/stringdata.h +++ b/bson/stringdata.h @@ -31,8 +31,8 @@ namespace mongo { // 'data' *always* finishes with a null terminator // 'size' does *not* account for the null terminator // These assumptions may make it easier to minimize changes to existing code - const char* data; - const unsigned size; + const char* const data; + const unsigned size; StringData( const char* c ) : data(c), size(strlen(c)) {} diff --git a/db/btree.cpp b/db/btree.cpp index ca873c37ba5c1..3610c1dbe921f 100644 --- a/db/btree.cpp +++ b/db/btree.cpp @@ -310,14 +310,13 @@ namespace mongo { topSize = 0; int i = 0; for ( int j = 0; j < n; j++ ) { - if( j > 0 && k( j ).isUnused() && k( j ).prevChildBucket.isNull() ) { - if ( i < refPos ) { - --refPos; - } - // FIXME don't drop ref pos + if( j > 0 && ( j != refPos ) && k( j ).isUnused() && k( j ).prevChildBucket.isNull() ) { continue; // key is unused and has no children - drop it } if( i != j ) { + if ( j == refPos ) { + refPos = i; // i < j so j will never be refPos again + } k( i ) = k( j ); } short ofsold = k(i).keyDataOfs(); diff --git a/db/db.rc b/db/db.rc index 6dba160ba75fa..b589458cf73e1 100755 --- a/db/db.rc +++ b/db/db.rc @@ -1,70 +1,12 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (United States) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_ICON2 ICON "mongo.ico" -#endif // English (United States) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON2 ICON "mongo.ico" +///////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/db/repl/heartbeat.cpp b/db/repl/heartbeat.cpp index eb2b1cde42a9c..752dd6b6f2758 100644 --- a/db/repl/heartbeat.cpp +++ b/db/repl/heartbeat.cpp @@ -89,6 +89,10 @@ namespace mongo { /* throws dbexception */ bool requestHeartbeat(string setName, string memberFullName, BSONObj& result, int myCfgVersion, int& theirCfgVersion, bool checkEmpty) { BSONObj cmd = BSON( "replSetHeartbeat" << setName << "v" << myCfgVersion << "pv" << 1 << "checkEmpty" << checkEmpty ); + + // we might be talking to ourself - generally not a great idea to do outbound waiting calls in a write lock + assert( !dbMutex.isWriteLocked() ); + ScopedConn conn(memberFullName); return conn->runCommand("admin", cmd, result); } diff --git a/db/repl/rs_initiate.cpp b/db/repl/rs_initiate.cpp index d0cbce53b362f..9ea11bf5022fa 100644 --- a/db/repl/rs_initiate.cpp +++ b/db/repl/rs_initiate.cpp @@ -55,7 +55,7 @@ namespace mongo { } } catch(DBException& e) { - log() << "replSet info " << i->h.toString() << " : " << e.toString() << rsLog; + log() << "replSet requestHeartbeat " << i->h.toString() << " : " << e.toString() << rsLog; } catch(...) { log() << "replSet error exception in requestHeartbeat?" << rsLog; @@ -78,7 +78,7 @@ namespace mongo { class CmdReplSetInitiate : public ReplSetCommand { public: - virtual LockType locktype() const { return WRITE; } + virtual LockType locktype() const { return NONE; } CmdReplSetInitiate() : ReplSetCommand("replSetInitiate") { } virtual void help(stringstream& h) const { h << "Initiate/christen a replica set."; @@ -145,19 +145,19 @@ namespace mongo { log() << "replSet replSetInitiate all members seem up" << rsLog; + writelock lk(""); bo comment = BSON( "msg" << "initiating set"); newConfig.saveConfigLocally(comment); + log() << "replSet replSetInitiate config now saved locally. Should come online in about a minute." << rsLog; + result.append("info", "Config now saved locally. Should come online in about a minute."); + ReplSet::startupStatus = ReplSet::SOON; + ReplSet::startupStatusMsg = "Received replSetInitiate - should come online shortly."; } catch( DBException& e ) { log() << "replSet replSetInitiate exception: " << e.what() << rsLog; throw; } - log() << "replSet replSetInitiate config now saved locally. Should come online in about a minute." << rsLog; - result.append("info", "Config now saved locally. Should come online in about a minute."); - ReplSet::startupStatus = ReplSet::SOON; - ReplSet::startupStatusMsg = "Received replSetInitiate - should come online shortly."; - return true; } } cmdReplSetInitiate; diff --git a/dbtests/btreetests.cpp b/dbtests/btreetests.cpp index 0607deeb5e729..a90a0975c8897 100644 --- a/dbtests/btreetests.cpp +++ b/dbtests/btreetests.cpp @@ -322,7 +322,7 @@ namespace BtreeTests { ASSERT( unused2 < unused ); } - private: + protected: void insert( long long n ) { string val( 800, ' ' ); for( int i = 0; i < 800; i += 8 ) { @@ -337,6 +337,36 @@ namespace BtreeTests { } }; + class DontDropReferenceKey : public PackUnused { + public: + void run() { + // with 80 root node is full + for ( long long i = 0; i < 80; i += 1 ) { + insert( i ); + } + + BSONObjBuilder start; + start.appendMinKey( "a" ); + BSONObjBuilder end; + end.appendMaxKey( "a" ); + BSONObj l = bt()->keyNode( 0 ).key; + string toInsert; + auto_ptr< BtreeCursor > c( new BtreeCursor( nsdetails( ns() ), 1, id(), start.done(), end.done(), false, 1 ) ); + while( c->ok() ) { + if ( c->currKey().woCompare( l ) > 0 ) { + toInsert = c->currKey().firstElement().valuestr(); + break; + } + c->advance(); + } + // too much work to try to make this happen through inserts and deletes + const_cast< DiskLoc& >( bt()->keyNode( 1 ).prevChildBucket ) = DiskLoc(); + const_cast< DiskLoc& >( bt()->keyNode( 1 ).recordLoc ).GETOFS() |= 1; // make unused + BSONObj k = BSON( "a" << toInsert ); + Base::insert( k ); + } + }; + class All : public Suite { public: All() : Suite( "btree" ){ @@ -352,6 +382,7 @@ namespace BtreeTests { add< SERVER983 >(); add< ReuseUnused >(); add< PackUnused >(); + add< DontDropReferenceKey >(); } } myall; } diff --git a/dbtests/jstests.cpp b/dbtests/jstests.cpp index 0b664f1c082ab..2749abf70ed8a 100644 --- a/dbtests/jstests.cpp +++ b/dbtests/jstests.cpp @@ -825,7 +825,7 @@ namespace JSTests { // check that BinData js class is utilized s->invokeSafe( "q = x.b.toString();", BSONObj() ); stringstream expected; - expected << "BinData( type: " << BinDataGeneral << ", base64: \"" << base64 << "\" )"; + expected << "BinData(" << BinDataGeneral << ",\"" << base64 << "\")"; ASSERT_EQUALS( expected.str(), s->getString( "q" ) ); stringstream scriptBuilder; diff --git a/scripting/sm_db.cpp b/scripting/sm_db.cpp index 87396815544d8..ff218b786c9e0 100644 --- a/scripting/sm_db.cpp +++ b/scripting/sm_db.cpp @@ -343,7 +343,6 @@ namespace mongo { { 0 } }; - // ------------- db_collection ------------- JSBool db_collection_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){ @@ -590,8 +589,19 @@ namespace mongo { if ( argc == 2 ){ int type = (int)c.toNumber( argv[ 0 ] ); + if( type < 0 || type > 255 ) { + JS_ReportError( cx , "invalid BinData subtype -- range is 0..255 see bsonspec.org" ); + return JS_FALSE; + } string encoded = c.toString( argv[ 1 ] ); - string decoded = base64::decode( encoded ); + string decoded; + try { + decoded = base64::decode( encoded ); + } + catch(...) { + JS_ReportError(cx, "BinData could not decode base64 parameter"); + return JS_FALSE; + } assert( JS_SetPrivate( cx, obj, new BinDataHolder( decoded.data(), decoded.length() ) ) ); c.setProperty( obj, "len", c.toval( (double)decoded.length() ) ); @@ -600,7 +610,7 @@ namespace mongo { return JS_TRUE; } else { - JS_ReportError( cx , "BinData needs 2 arguments" ); + JS_ReportError( cx , "BinData needs 2 arguments -- BinData(subtype,data)" ); return JS_FALSE; } } @@ -613,13 +623,54 @@ namespace mongo { assert( holder ); const char *data = ( ( BinDataHolder* )( holder ) )->c_; stringstream ss; - ss << "BinData( type: " << type << ", base64: \""; + ss << "BinData(" << type << ",\""; base64::encode( ss, (const char *)data, len ); - ss << "\" )"; + ss << "\")"; string ret = ss.str(); return *rval = c.toval( ret.c_str() ); } + JSBool bindataBase64(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ + Convertor c(cx); + int len = (int)c.getNumber( obj, "len" ); + void *holder = JS_GetPrivate( cx, obj ); + assert( holder ); + const char *data = ( ( BinDataHolder* )( holder ) )->c_; + stringstream ss; + base64::encode( ss, (const char *)data, len ); + string ret = ss.str(); + return *rval = c.toval( ret.c_str() ); + } + + JSBool bindataAsHex(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ + Convertor c(cx); + int type = (int)c.getNumber( obj , "type" ); + int len = (int)c.getNumber( obj, "len" ); + void *holder = JS_GetPrivate( cx, obj ); + assert( holder ); + const char *data = ( ( BinDataHolder* )( holder ) )->c_; + stringstream ss; + ss << hex; + for( int i = 0; i < len; i++ ) { + unsigned v = (unsigned char) data[i]; + ss << v; + } + string ret = ss.str(); + return *rval = c.toval( ret.c_str() ); + } + + JSBool bindataLength(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ + Convertor c(cx); + int len = (int)c.getNumber( obj, "len" ); + return *rval = c.toval((double) len); + } + + JSBool bindataSubtype(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ + Convertor c(cx); + int t = (int)c.getNumber( obj, "type" ); + return *rval = c.toval((double) t); + } + void bindata_finalize( JSContext * cx , JSObject * obj ){ Convertor c(cx); void *holder = JS_GetPrivate( cx, obj ); @@ -638,6 +689,10 @@ namespace mongo { JSFunctionSpec bindata_functions[] = { { "toString" , bindata_tostring , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } , + { "hex", bindataAsHex, 0, JSPROP_READONLY | JSPROP_PERMANENT, 0 } , + { "base64", bindataBase64, 0, JSPROP_READONLY | JSPROP_PERMANENT, 0 } , + { "length", bindataLength, 0, JSPROP_READONLY | JSPROP_PERMANENT, 0 } , + { "subtype", bindataSubtype, 0, JSPROP_READONLY | JSPROP_PERMANENT, 0 } , { 0 } }; diff --git a/shell/mongo_vstudio.cpp b/shell/mongo_vstudio.cpp index bac5f3443f821..608e747327f99 100644 --- a/shell/mongo_vstudio.cpp +++ b/shell/mongo_vstudio.cpp @@ -211,6 +211,10 @@ const char * jsconcatcode = "if ( !( i in o.__proto__ && o[ i ] === o.__proto__[ i ] ) ) {\n" "ret.push( i );}}\n" "return ret;}\n" + "if ( ! NumberLong.prototype ) {\n" + "NumberLong.prototype = {}}\n" + "NumberLong.prototype.tojson = function() {\n" + "return this.toString();}\n" "if ( ! ObjectId.prototype )\n" "ObjectId.prototype = {}\n" "ObjectId.prototype.toString = function(){\n" @@ -220,6 +224,8 @@ const char * jsconcatcode = "ObjectId.prototype.isObjectId = true;\n" "ObjectId.prototype.getTimestamp = function(){\n" "return new Date(parseInt(this.toString().slice(0,8), 16)*1000);}\n" + "ObjectId.prototype.equals = function( other){\n" + "return this.str == other.str;}\n" "if ( typeof( DBPointer ) != \"undefined\" ){\n" "DBPointer.prototype.fetch = function(){\n" "assert( this.ns , \"need a ns\" );\n" @@ -247,10 +253,10 @@ const char * jsconcatcode = "else {\n" "print( \"warning: no DBRef\" );}\n" "if ( typeof( BinData ) != \"undefined\" ){\n" - "BinData.prototype.tojson = function(){\n" - "return \"BinData type: \" + this.type + \" len: \" + this.len;}}\n" + "BinData.prototype.tojson = function () {\n" + "return this.toString();}}\n" "else {\n" - "print( \"warning: no BinData\" );}\n" + "print( \"warning: no BinData class\" );}\n" "if ( typeof _threadInject != \"undefined\" ){\n" "print( \"fork() available!\" );\n" "Thread = function(){\n" @@ -401,10 +407,20 @@ const char * jsconcatcode = "case \"string\": {\n" "var s = \"\\\"\";\n" "for ( var i=0; i/ if not specified as the 2nd arg\");\n" "print(\"\\t returns a connection to the new server\");\n" "return;}\n" - "print(\"\\t\" + \"help connect connecting to a db\");\n" - "print(\"\\t\" + \"help admin misc shell commands\");\n" + "print(\"\\t\" + \"help connect connecting to a db help\");\n" + "print(\"\\t\" + \"help admin administrative help\");\n" + "print(\"\\t\" + \"help misc misc things to know\");\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" @@ -619,7 +644,8 @@ const char * jsconcatcode = "this._data[k].forEach( function(z){ all.push( z.value ); } );}\n" "return all;}\n" "if ( typeof( gc ) == \"undefined\" ){\n" - "gc = function(){}}\n" + "gc = function(){\n" + "print( \"warning: using noop gc()\" );}}\n" "Math.sigFig = function( x , N ){\n" "if ( ! N ){\n" "N = 3;}\n" @@ -992,16 +1018,18 @@ const char * jsconcatcode = "var x = this.runCommand( \"listCommands\" );\n" "for ( var name in x.commands ){\n" "var c = x.commands[name];\n" - "var s = name + \" lock: \";\n" + "var s = name + \": \";\n" "switch ( c.lockType ){\n" - "case -1: s += \"read\"; break;\n" - "case 0: s += \"node\"; break;\n" - "case 1: s += \"write\"; break;\n" + "case -1: s += \"read-lock\"; break;\n" + "case 0: s += \"no-lock\"; break;\n" + "case 1: s += \"write-lock\"; break;\n" "default: s += c.lockType;}\n" - "s += \" adminOnly: \" + c.adminOnly;\n" - "s += \" slaveOk: \" + c.slaveOk;\n" - "s += \" \" + c.help;\n" - "print( s )}}\n" + "if (c.adminOnly) s += \" adminOnly \";\n" + "if (c.adminOnly) s += \" slaveOk \";\n" + "s += \"\\n \";\n" + "s += c.help.replace(/\\n/g, '\\n ');\n" + "s += \"\\n\";\n" + "print( s );}}\n" "DB.prototype.printShardingStatus = function(){\n" "printShardingStatus( this.getSisterDB( \"config\" ) );}\n" "if ( typeof Mongo == \"undefined\" ){\n" @@ -1346,7 +1374,7 @@ const char * jsconcatcode = "print(\"\\tdb.\" + shortName + \".mapReduce( mapFunction , reduceFunction , )\");\n" "print(\"\\tdb.\" + shortName + \".remove(query)\");\n" "print(\"\\tdb.\" + shortName + \".renameCollection( newName , ) renames the collection.\");\n" - "print(\"\\tdb.\" + shortName + \".runCommand( name , ) runs a db command with the given name where the 1st param is the colleciton name\");\n" + "print(\"\\tdb.\" + shortName + \".runCommand( name , ) runs a db command with the given name where the first param is the collection name\");\n" "print(\"\\tdb.\" + shortName + \".save(obj)\");\n" "print(\"\\tdb.\" + shortName + \".stats()\");\n" "print(\"\\tdb.\" + shortName + \".storageSize() - includes free space allocated to this collection\");\n" @@ -1532,7 +1560,7 @@ const char * jsconcatcode = "var ret = this._db.runCommand( cmd );\n" "if ( ! ret.ok ){\n" "if (ret.errmsg == \"No matching object found\"){\n" - "return {};}\n" + "return null;}\n" "throw \"findAndModifyFailed failed: \" + tojson( ret.errmsg );}\n" "return ret.value;}\n" "DBCollection.prototype.renameCollection = function( newName , dropTarget ){\n" diff --git a/shell/utils.js b/shell/utils.js index cb5828423ac58..16dfb0094e184 100644 --- a/shell/utils.js +++ b/shell/utils.js @@ -421,13 +421,14 @@ else { print( "warning: no DBRef" ); } -if ( typeof( BinData ) != "undefined" ){ - BinData.prototype.tojson = function(){ - return "BinData type: " + this.type + " len: " + this.len; +if ( typeof( BinData ) != "undefined" ){ + BinData.prototype.tojson = function () { + //return "BinData type: " + this.type + " len: " + this.len; + return this.toString(); } } else { - print( "warning: no BinData" ); + print( "warning: no BinData class" ); } if ( typeof _threadInject != "undefined" ){ @@ -836,55 +837,65 @@ shellHelper = function( command , rest , shouldPrint ){ shellPrintHelper( res ); } return res; -} - -help = shellHelper.help = function (x) { - if (x == "connect") { - print("\nNormally one specifies the server on the mongo shell command line. Run mongo --help to see those options."); - print("Additional connections may be opened:\n"); - print(" var x = new Mongo('host[:port]');"); - print(" var mydb = x.getDB('mydb');"); - print(" or"); - print(" var mydb = connect('host[:port]/mydb');"); - print("\nNote: the REPL prompt only auto-reports getLastError() for the shell command line connection.\n"); - return; - } - if (x == "admin") { - print("\tls([path]) list files"); - print("\tpwd() returns current directory"); - print("\tlistFiles([path]) returns file list"); - print("\thostname() returns name of this host"); - print("\tcat(fname) returns contents of text file as a string"); - print("\tremoveFile(f) delete a file"); - print("\tload(jsfilename) load and execute a .js file"); - print("\trun(program[, args...]) spawn a program and wait for its completion"); - print("\tsleep(m) sleep m milliseconds"); - print("\tgetMemInfo() diagnostic"); - return; - } - if (x == "test") { - print("\tstartMongodEmpty(args) DELETES DATA DIR and then starts mongod"); - print("\t returns a connection to the new server"); - print("\tstartMongodTest() DELETES DATA DIR"); - print("\t automatically picks port #s starting at 27000 and increasing"); - print("\t or you can specify the port as the first arg"); - print("\t dir is /data/db// if not specified as the 2nd arg"); - print("\t returns a connection to the new server"); - return; - } - print("\t" + "help connect connecting to a db"); - print("\t" + "help admin misc shell commands"); - print("\t" + "show dbs show database names"); - print("\t" + "show collections show collections in current database"); - print("\t" + "show users show users in current database"); - print("\t" + "show profile show most recent system.profile entries with time >= 1ms"); - print("\t" + "use set current database to "); - print("\t" + "db.help() help on db methods"); - print("\t" + "db.foo.help() help on collection methods"); - print("\t" + "db.foo.find() list objects in collection foo"); - print("\t" + "db.foo.find( { a : 1 } ) list objects in foo where a == 1"); - print("\t" + "it result of the last line evaluated; use to further iterate"); - print("\t" + "exit quit the mongo shell"); +} + +help = shellHelper.help = function (x) { + if (x == "connect") { + print("\nNormally one specifies the server on the mongo shell command line. Run mongo --help to see those options."); + print("Additional connections may be opened:\n"); + print(" var x = new Mongo('host[:port]');"); + print(" var mydb = x.getDB('mydb');"); + print(" or"); + print(" var mydb = connect('host[:port]/mydb');"); + print("\nNote: the REPL prompt only auto-reports getLastError() for the shell command line connection.\n"); + return; + } + if (x == "misc") { + print("\tb = new BinData(subtype,base64str) create a BSON BinData value"); + print("\tb.subtype() the BinData subtype (0..255)"); + print("\tb.length() length of the BinData data in bytes"); + print("\tb.hex() the data as a hex encoded string"); + print("\tb.base64() the data as a base 64 encoded string"); + print("\tb.toString()"); + return; + } + if (x == "admin") { + print("\tls([path]) list files"); + print("\tpwd() returns current directory"); + print("\tlistFiles([path]) returns file list"); + print("\thostname() returns name of this host"); + print("\tcat(fname) returns contents of text file as a string"); + print("\tremoveFile(f) delete a file"); + print("\tload(jsfilename) load and execute a .js file"); + print("\trun(program[, args...]) spawn a program and wait for its completion"); + print("\tsleep(m) sleep m milliseconds"); + print("\tgetMemInfo() diagnostic"); + return; + } + if (x == "test") { + print("\tstartMongodEmpty(args) DELETES DATA DIR and then starts mongod"); + print("\t returns a connection to the new server"); + print("\tstartMongodTest() DELETES DATA DIR"); + print("\t automatically picks port #s starting at 27000 and increasing"); + print("\t or you can specify the port as the first arg"); + print("\t dir is /data/db// if not specified as the 2nd arg"); + print("\t returns a connection to the new server"); + return; + } + print("\t" + "help connect connecting to a db help"); + print("\t" + "help admin administrative help"); + print("\t" + "help misc misc things to know"); + print("\t" + "show dbs show database names"); + print("\t" + "show collections show collections in current database"); + print("\t" + "show users show users in current database"); + print("\t" + "show profile show most recent system.profile entries with time >= 1ms"); + print("\t" + "use set current database to "); + print("\t" + "db.help() help on db methods"); + print("\t" + "db.foo.help() help on collection methods"); + print("\t" + "db.foo.find() list objects in collection foo"); + print("\t" + "db.foo.find( { a : 1 } ) list objects in foo where a == 1"); + print("\t" + "it result of the last line evaluated; use to further iterate"); + print("\t" + "exit quit the mongo shell"); } shellHelper.use = function( dbname ){ diff --git a/tools/restore.cpp b/tools/restore.cpp index a2013a1afba0f..115297b72a499 100644 --- a/tools/restore.cpp +++ b/tools/restore.cpp @@ -33,11 +33,13 @@ class Restore : public BSONTool { public: bool _drop; + bool _indexesLast; const char * _curns; Restore() : BSONTool( "restore" ) , _drop(false){ add_options() ("drop" , "drop each collection before import" ) + ("indexesLast" , "wait to add indexes (faster if data isn't inserted in index order)" ) ; add_hidden_options() ("dir", po::value()->default_value("dump"), "directory to restore from") @@ -53,6 +55,7 @@ class Restore : public BSONTool { auth(); path root = getParam("dir"); _drop = hasParam( "drop" ); + _indexesLast = hasParam("indexesLast"); /* If _db is not "" then the user specified a db name to restore as. * @@ -74,6 +77,7 @@ class Restore : public BSONTool { if ( is_directory( root ) ) { directory_iterator end; directory_iterator i(root); + path indexes; while ( i != end ) { path p = *i; i++; @@ -96,8 +100,15 @@ class Restore : public BSONTool { } } - drillDown(p, use_db, use_coll); + if ( _indexesLast && p.leaf() == "system.indexes.bson" ) + indexes = p; + else + drillDown(p, use_db, use_coll); } + + if (!indexes.empty()) + drillDown(indexes, use_db, use_coll); + return; } diff --git a/tools/tool.cpp b/tools/tool.cpp index 2431710278020..9b2c656360722 100644 --- a/tools/tool.cpp +++ b/tools/tool.cpp @@ -344,12 +344,16 @@ namespace mongo { } - ifstream file( fileString.c_str() , ios_base::in | ios_base::binary); - if ( ! file.is_open() ){ + FILE* file = fopen( fileString.c_str() , "rb" ); + if ( ! file ){ log() << "error opening file: " << fileString << endl; return 0; } +#if !defined(__sunos__) && defined(POSIX_FADV_SEQUENTIAL) + posix_fadvise(fileno(file), 0, fileLength, POSIX_FADV_SEQUENTIAL); +#endif + log(1) << "\t file size: " << fileLength << endl; long long read = 0; @@ -363,14 +367,14 @@ namespace mongo { ProgressMeter m( fileLength ); while ( read < fileLength ) { - file.read( buf , 4 ); + fread(buf, 4, 1, file); int size = ((int*)buf)[0]; if ( size >= BUF_SIZE ){ cerr << "got an object of size: " << size << " terminating..." << endl; } uassert( 10264 , "invalid object size" , size < BUF_SIZE ); - file.read( buf + 4 , size - 4 ); + fread(buf+4, size-4, 1, file); BSONObj o( buf ); if ( _objcheck && ! o.valid() ){ diff --git a/util/log.h b/util/log.h index 8a26bd8f6a9eb..8279bb929813a 100644 --- a/util/log.h +++ b/util/log.h @@ -324,10 +324,43 @@ namespace mongo { void initLogging( const string& logpath , bool append ); void rotateLogs( int signal = 0 ); + std::string toUtf8String(const std::wstring& wide); + inline string errnoWithDescription(int x = errno) { stringstream s; - s << "errno:" << x << ' ' << strerror(x); - return s.str(); + s << "errno:" << x << ' '; + +#if defined(_WIN32) + LPTSTR errorText = NULL; + FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM + |FORMAT_MESSAGE_ALLOCATE_BUFFER + |FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + x, 0, + (LPTSTR) &errorText, // output + 0, // minimum size for output buffer + NULL); + if( errorText ) { + string x = toUtf8String(errorText); + s << x; + LocalFree(errorText); + } + else + s << strerror(x); + /* + DWORD n = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, x, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, 0, NULL); + */ +#else + s << strerror(x); +#endif + return s.str(); } /** output the error # and error message with prefix. diff --git a/util/message.cpp b/util/message.cpp index 26b7c94e6adf4..67fc4f07ac4fb 100644 --- a/util/message.cpp +++ b/util/message.cpp @@ -30,6 +30,12 @@ #ifndef _WIN32 #include +#else + +// errno doesn't work for winsock. +#undef errno +#define errno WSAGetLastError() + #endif namespace mongo { @@ -566,8 +572,9 @@ namespace mongo { throw SocketException(); } if ( ret == -1 ) { - if ( errno != EAGAIN || _timeout == 0 ) { - log(_logLevel) << "MessagingPort recv() " << errnoWithDescription() << " " << farEnd.toString()< 9 && arg.substr(0, 9) == "--service" ) { - continue; - } - commandLine << arg << " "; - } - + for ( int i = 1; i < argc; i++ ) { + std::string arg( argv[ i ] ); + // replace install command to indicate process is being started as a service + if ( arg == "--install" || arg == "--reinstall" ) { + arg = "--service"; + } else if ( arg == "--dbpath" && i + 1 < argc ) { + commandLine << arg << " \"" << dbpath << "\" "; + i++; + continue; + } else if ( arg.length() > 9 && arg.substr(0, 9) == "--service" ) { + // Strip off --service(Name|User|Password) arguments + continue; + } + commandLine << arg << " "; + } + SC_HANDLE schSCManager = ::OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if ( schSCManager == NULL ) { DWORD err = ::GetLastError();