From 8fc2c86e0afc8e12421e245b95a16b5f3d7d4bbf Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 13 Feb 2009 12:01:37 -0500 Subject: [PATCH] Now can start any 'mongo program' from within mongo shell --- jstests/recovery/dbNoCreate.js | 2 +- jstests/repl/pair2.js | 2 +- jstests/repl/repl2.js | 2 +- jstests/repl/repl3.js | 2 +- shell/ShellUtils.cpp | 75 +++++++++++++++++++--------------- shell/ShellUtils.h | 12 +++--- shell/dbshell.cpp | 10 ++--- shell/mongo.js | 27 ++++++++---- 8 files changed, 76 insertions(+), 56 deletions(-) diff --git a/jstests/recovery/dbNoCreate.js b/jstests/recovery/dbNoCreate.js index 73efe904c4f..20a16085f86 100644 --- a/jstests/recovery/dbNoCreate.js +++ b/jstests/recovery/dbNoCreate.js @@ -15,5 +15,5 @@ t.drop(); stopMongod( 27018 ); -var m = startMongodNoReset( "--port", "27018", "--dbpath", "/data/db/" + baseName ); +var m = startMongoProgramNoReset( "mongod", "--port", "27018", "--dbpath", "/data/db/" + baseName ); assert.eq( -1, m.getDBNames().indexOf( baseName ) ); diff --git a/jstests/repl/pair2.js b/jstests/repl/pair2.js index 1b4544a91de..0984e6e16c0 100644 --- a/jstests/repl/pair2.js +++ b/jstests/repl/pair2.js @@ -29,7 +29,7 @@ big = new Array( 2000 ).toString(); for( i = 0; i < 1000; ++i ) rz.save( { _id: new ObjectId(), i: i, b: big } ); -l = startMongodNoReset( "--port", "27019", "--dbpath", "/data/db/" + baseName + "-left", "--pairwith", "127.0.0.1:27020", "127.0.0.1:27018", "--oplogSize", "1" ); +l = startMongoProgramNoReset( "mongod", "--port", "27019", "--dbpath", "/data/db/" + baseName + "-left", "--pairwith", "127.0.0.1:27020", "127.0.0.1:27018", "--oplogSize", "1" ); l.setSlaveOk(); assert.soon( function() { return 1 == l.getDB( "admin" ).runCommand( { "resync" : 1 } ).ok; } ); diff --git a/jstests/repl/repl2.js b/jstests/repl/repl2.js index 7b275fa2703..d8e9995ee2c 100644 --- a/jstests/repl/repl2.js +++ b/jstests/repl/repl2.js @@ -18,7 +18,7 @@ big = new Array( 2000 ).toString(); for( i = 0; i < 1000; ++i ) am.save( { _id: new ObjectId(), i: i, b: big } ); -s = startMongodNoReset( "--port", "27019", "--dbpath", "/data/db/" + baseName + "-slave", "--slave", "--source", "127.0.0.1:27018" ); +s = startMongoProgramNoReset( "mongod", "--port", "27019", "--dbpath", "/data/db/" + baseName + "-slave", "--slave", "--source", "127.0.0.1:27018" ); assert.soon( function() { return 1 == s.getDB( "admin" ).runCommand( { "resync" : 1 } ).ok; } ); assert.soon( function() { return s.getDBNames().indexOf( baseName ) != -1; } ); diff --git a/jstests/repl/repl3.js b/jstests/repl/repl3.js index 704a116c064..4a708ca3987 100644 --- a/jstests/repl/repl3.js +++ b/jstests/repl/repl3.js @@ -17,7 +17,7 @@ big = new Array( 2000 ).toString(); for( i = 0; i < 1000; ++i ) am.save( { _id: new ObjectId(), i: i, b: big } ); -s = startMongodNoReset( "--port", "27019", "--dbpath", "/data/db/" + baseName + "-slave", "--slave", "--source", "127.0.0.1:27018", "--autoresync" ); +s = startMongoProgramNoReset( "mongod", "--port", "27019", "--dbpath", "/data/db/" + baseName + "-slave", "--slave", "--source", "127.0.0.1:27018", "--autoresync" ); // after SyncException, mongod waits 10 secs. sleep( 12000 ); diff --git a/shell/ShellUtils.cpp b/shell/ShellUtils.cpp index 1eb6b975af2..e98a54450b5 100644 --- a/shell/ShellUtils.cpp +++ b/shell/ShellUtils.cpp @@ -240,46 +240,51 @@ char *copyString( const char *original ) { return ret; } -boost::mutex &mongodOutputMutex( *( new boost::mutex ) ); -const v8::Arguments *mongodArgs = 0; +boost::mutex &mongoProgramOutputMutex( *( new boost::mutex ) ); +const v8::Arguments *mongoProgramArgs = 0; -void writeMongodOutputLine( int port, const char *line ) { - boost::mutex::scoped_lock lk( mongodOutputMutex ); - cout << "d" << port << "| " << line << endl; +void writeMongoProgramOutputLine( int port, const char *line ) { + boost::mutex::scoped_lock lk( mongoProgramOutputMutex ); + cout << "m" << port << "| " << line << endl; } -void mongodThread() { +void mongoProgramThread() { + assert( mongoProgramArgs->Length() > 0 ); + v8::String::Utf8Value programParse( (*mongoProgramArgs)[ 0 ] ); + assert( *programParse ); + string program( *programParse ); + assert( argv0 ); - boost::filesystem::path mongod = ( boost::filesystem::path( argv0 ) ).branch_path() / "mongod"; - assert( boost::filesystem::exists( mongod ) ); + boost::filesystem::path programPath = ( boost::filesystem::path( argv0 ) ).branch_path() / program; + assert( boost::filesystem::exists( programPath ) ); int port = -1; - char * argv[ mongodArgs->Length() + 2 ]; + char * argv[ mongoProgramArgs->Length() + 1 ]; { - string s = mongod.native_file_string(); - if ( s == "mongod" ) + string s = programPath.native_file_string(); + if ( s == program ) s = "./" + s; argv[ 0 ] = copyString( s.c_str() ); } - for( int i = 0; i < mongodArgs->Length(); ++i ) { - v8::String::Utf8Value str( (*mongodArgs)[ i ] ); + for( int i = 1; i < mongoProgramArgs->Length(); ++i ) { + v8::String::Utf8Value str( (*mongoProgramArgs)[ i ] ); assert( *str ); char *s = copyString( *str ); if ( string( "--port" ) == s ) port = -2; else if ( port == -2 ) port = strtol( s, 0, 10 ); - argv[ 1 + i ] = s; + argv[ i ] = s; } - argv[ mongodArgs->Length() + 1 ] = 0; + argv[ mongoProgramArgs->Length() ] = 0; assert( port > 0 ); assert( dbs.count( port ) == 0 ); int pipeEnds[ 2 ]; assert( pipe( pipeEnds ) != -1 ); - + fflush( 0 ); pid_t pid = fork(); assert( pid != -1 ); @@ -298,9 +303,10 @@ void mongodThread() { dbs.insert( make_pair( port, make_pair( pid, pipeEnds[ 1 ] ) ) ); // Allow caller to return -- this is our low rent lock - mongodArgs = 0; + mongoProgramArgs = 0; - // This assumes there aren't any 0's in the mongod output. Hope that's ok. + // This assumes there aren't any 0's in the mongo program output. + // Hope that's ok. char buf[ 1024 ]; char temp[ 1024 ]; char *start = buf; @@ -312,11 +318,11 @@ void mongodThread() { char *last = buf; for( char *i = strchr( buf, '\n' ); i; last = i + 1, i = strchr( last, '\n' ) ) { *i = '\0'; - writeMongodOutputLine( port, last ); + writeMongoProgramOutputLine( port, last ); } if ( ret == 0 ) { if ( *last ) - writeMongodOutputLine( port, last ); + writeMongoProgramOutputLine( port, last ); break; } if ( last != buf ) { @@ -329,12 +335,12 @@ void mongodThread() { } } -// Relies on global mongodArgs; not thread-safe -v8::Handle< v8::Value > StartMongod( const v8::Arguments &a ) { - assert( !mongodArgs ); - mongodArgs = &a; - boost::thread t( mongodThread ); - while( mongodArgs ) +// Relies on global mongoProgramArgs; not thread-safe +v8::Handle< v8::Value > StartMongoProgram( const v8::Arguments &a ) { + assert( !mongoProgramArgs ); + mongoProgramArgs = &a; + boost::thread t( mongoProgramThread ); + while( mongoProgramArgs ) sleepms( 2 ); return v8::Undefined(); } @@ -374,7 +380,7 @@ void killDb( int port ) { dbs.erase( port ); } -v8::Handle< v8::Value > StopMongod( const v8::Arguments &a ) { +v8::Handle< v8::Value > StopMongoProgram( const v8::Arguments &a ) { assert( a.Length() == 1 ); assert( a[ 0 ]->IsInt32() ); int port = a[ 0 ]->ToInt32()->Value(); @@ -382,22 +388,22 @@ v8::Handle< v8::Value > StopMongod( const v8::Arguments &a ) { return v8::Undefined(); } -void KillMongodbInstances() { +void KillMongoProgramInstances() { for( map< int, pair< pid_t, int > >::iterator i = dbs.begin(); i != dbs.end(); ++i ) killDb( i->first ); } -MongodScope::~MongodScope() { +MongoProgramScope::~MongoProgramScope() { try { - KillMongodbInstances(); + KillMongoProgramInstances(); } catch ( ... ) { assert( false ); } } #else -MongodScope::~MongodScope() {} -void KillMongodbInstances() {} +MongoProgramScope::~MongoProgramScope() {} +void KillMongoProgramInstances() {} #endif void installShellUtils( Handle& global ){ @@ -408,8 +414,9 @@ void installShellUtils( Handle& global ){ global->Set(v8::String::New("quit"), v8::FunctionTemplate::New(Quit)); global->Set(v8::String::New("version"), v8::FunctionTemplate::New(Version)); #if !defined(_WIN32) - global->Set(v8::String::New("_startMongod"), v8::FunctionTemplate::New(StartMongod)); - global->Set(v8::String::New("stopMongod"), v8::FunctionTemplate::New(StopMongod)); + global->Set(v8::String::New("_startMongoProgram"), v8::FunctionTemplate::New(StartMongoProgram)); + global->Set(v8::String::New("stopMongod"), v8::FunctionTemplate::New(StopMongoProgram)); + global->Set(v8::String::New("stopMongoProgram"), v8::FunctionTemplate::New(StopMongoProgram)); global->Set(v8::String::New("resetDbpath"), v8::FunctionTemplate::New(ResetDbpath)); #endif } diff --git a/shell/ShellUtils.h b/shell/ShellUtils.h index 2e3b09cbe97..942ba860f00 100644 --- a/shell/ShellUtils.h +++ b/shell/ShellUtils.h @@ -37,12 +37,12 @@ std::ostream& operator<<( std::ostream &s, const v8::Handle & o ); std::ostream& operator<<( std::ostream &s, const v8::Handle * try_catch ); std::string toSTLString( const v8::Handle & o ); -// Scoped management of mongod instances. Simple implementation: destructor -// kills all mongod instances created by the shell. -struct MongodScope { - MongodScope() {} // Avoid 'unused variable' warning. - ~MongodScope(); +// Scoped management of mongo program instances. Simple implementation: +// destructor kills all mongod instances created by the shell. +struct MongoProgramScope { + MongoProgramScope() {} // Avoid 'unused variable' warning. + ~MongoProgramScope(); }; void RecordMyLocation( const char *_argv0 ); -void KillMongodbInstances(); +void KillMongoProgramInstances(); diff --git a/shell/dbshell.cpp b/shell/dbshell.cpp index 80462053f9d..22b9c23c545 100644 --- a/shell/dbshell.cpp +++ b/shell/dbshell.cpp @@ -52,7 +52,7 @@ void quitNicely( int sig ){ } void quitAbruptly( int sig ) { - KillMongodbInstances(); + KillMongoProgramInstances(); exit(14); } @@ -186,7 +186,7 @@ int main(int argc, char* argv[]) { << " -p - notice no space\n" << " --host - server to connect to\n" << " --port - port to connect to\n" - << " --nodb don't connect to mongod on startup. No 'db address' arg expected.\n" + << " --nodb don't connect to mongo program on startup. No 'db address' arg expected.\n" << "file names: a list of files to run. will exit after unless --shell is specified\n" ; @@ -264,7 +264,7 @@ int main(int argc, char* argv[]) { return 1; } - MongodScope s; + MongoProgramScope s; if (!ExecuteString(source, file_name, false, true)){ cout << "error processing: " << file_name << endl; return 1; @@ -278,9 +278,9 @@ int main(int argc, char* argv[]) { if ( runShell ){ - MongodScope s; + MongoProgramScope s; - shellHistoryInit(); + shellHistoryInit(); cout << "type \"help\" for help" << endl; diff --git a/shell/mongo.js b/shell/mongo.js index 480eca531b6..38c2181c2da 100644 --- a/shell/mongo.js +++ b/shell/mongo.js @@ -83,16 +83,29 @@ _portAndDbpath = function() { // This function's arguments are passed as command line arguments to mongod. // The specified 'dbpath' is cleared if it exists, created if not. startMongod = function() { - var dbpath = _portAndDbpath.apply( null, arguments ).dbpath; - resetDbpath( dbpath ); - return startMongodNoReset.apply( null, arguments ); + var fullArgs = Array(); + fullArgs[ 0 ] = "mongod"; + for( i = 0; i < arguments.length; ++i ) + fullArgs[ i + 1 ] = arguments[ i ]; + return startMongoProgram.apply( null, fullArgs ); } -// Same as startDb, but uses existing files in dbpath -startMongodNoReset = function() { +// Start a mongo program instance (generally mongod or mongos) and return a +// 'Mongo' object connected to it. This function's first argument is the +// program name, and subsequent arguments to this function are passed as +// command line arguments to the program. The specified 'dbpath' is cleared if +// it exists, created if not. +startMongoProgram = function() { + var dbpath = _portAndDbpath.apply( null, arguments ).dbpath; + resetDbpath( dbpath ); + return startMongoProgramNoReset.apply( null, arguments ); +} + +// Same as startMongoProgram, but uses existing files in dbpath +startMongoProgramNoReset = function() { var port = _portAndDbpath.apply( null, arguments ).port; - - _startMongod.apply( null, arguments ); + + _startMongoProgram.apply( null, arguments ); var m; assert.soon