diff options
author | Dwight <dmerriman@gmail.com> | 2009-03-25 17:30:54 -0400 |
---|---|---|
committer | Dwight <dmerriman@gmail.com> | 2009-03-25 17:30:54 -0400 |
commit | 724e71fa653d0064766cd9c515d0d1ce21f97f23 (patch) | |
tree | ec698e96685f547c301ee122560e903da59451bc | |
parent | b2b5506629cb733392197d6c9f6d07ac463ec7e4 (diff) | |
parent | 265436b22df4830b711227c7cf9f441c7f7dc4dd (diff) | |
download | mongo-724e71fa653d0064766cd9c515d0d1ce21f97f23.tar.gz |
Merge branch 'master' of git@github.com:mongodb/mongo
-rw-r--r-- | SConstruct | 5 | ||||
-rw-r--r-- | client/dbclient.cpp | 71 | ||||
-rw-r--r-- | client/dbclient.h | 112 | ||||
-rw-r--r-- | client/model.h | 6 | ||||
-rw-r--r-- | db/instance.h | 5 | ||||
-rw-r--r-- | db/jsobj.cpp | 2 | ||||
-rw-r--r-- | db/jsobj.h | 7 | ||||
-rw-r--r-- | dbtests/jsobjtests.cpp | 8 | ||||
-rw-r--r-- | dbtests/mockdbclient.h | 8 | ||||
-rw-r--r-- | jstests/repl/repl6.js | 76 | ||||
-rw-r--r-- | mongo.xcodeproj/project.pbxproj | 2 | ||||
-rw-r--r-- | shell/dbshell.cpp | 30 | ||||
-rw-r--r-- | util/builder.h | 4 |
13 files changed, 238 insertions, 98 deletions
diff --git a/SConstruct b/SConstruct index 9cc6a744477..24dfc86bc3b 100644 --- a/SConstruct +++ b/SConstruct @@ -162,6 +162,7 @@ allClientFiles = commonFiles + coreDbFiles + [ "client/clientOnly.cpp" , "client onlyServer = len( COMMAND_LINE_TARGETS ) == 0 or ( len( COMMAND_LINE_TARGETS ) == 1 and str( COMMAND_LINE_TARGETS[0] ) == "mongod" ) nix = False useJavaHome = False +linux = False linux64 = False darwin = False windows = False @@ -231,6 +232,7 @@ if "darwin" == os.sys.platform: env.Append( LIBPATH=["/sw/lib/", "/opt/local/lib"] ) elif "linux2" == os.sys.platform: + linux = True useJavaHome = True javaOS = "linux" platform = "linux" @@ -480,6 +482,9 @@ def doConfigure( myenv , needJava=True , needPcre=True , shell=False ): else: print( "WARNING: no readline, shell will be a bit ugly" ) + if linux: + myCheckLib( "rt" , True ) + # this will add it iff it exists and works myCheckLib( "boost_system-mt" ) diff --git a/client/dbclient.cpp b/client/dbclient.cpp index 2cfba890fa7..47c7bfc33bc 100644 --- a/client/dbclient.cpp +++ b/client/dbclient.cpp @@ -28,7 +28,7 @@ namespace mongo { - Query& Query::where(const char *jscode, BSONObj scope) { + Query& Query::where(const string &jscode, BSONObj scope) { /* use where() before sort() and hint() and explain(), else this will assert. */ assert( !obj.hasField("query") ); BSONObjBuilder b; @@ -104,16 +104,16 @@ namespace mongo { return o.getIntField("ok") == 1; } - inline bool DBClientWithCommands::runCommand(const char *dbname, const BSONObj& cmd, BSONObj &info) { - string ns = string(dbname) + ".$cmd"; - info = findOne(ns.c_str(), cmd); + inline bool DBClientWithCommands::runCommand(const string &dbname, const BSONObj& cmd, BSONObj &info) { + string ns = dbname + ".$cmd"; + info = findOne(ns, cmd); return isOk(info); } /* note - we build a bson obj here -- for something that is super common like getlasterror you should have that object prebuilt as that would be faster. */ - bool DBClientWithCommands::simpleCommand(const char *dbname, BSONObj *info, const char *command) { + bool DBClientWithCommands::simpleCommand(const string &dbname, BSONObj *info, const string &command) { BSONObj o; if ( info == 0 ) info = &o; @@ -122,7 +122,7 @@ namespace mongo { return runCommand(dbname, b.done(), *info); } - unsigned long long DBClientWithCommands::count(const char *_ns, BSONObj query) { + unsigned long long DBClientWithCommands::count(const string &_ns, BSONObj query) { NamespaceString ns(_ns); BSONObj cmd = BSON( "count" << ns.coll << "query" << query ); BSONObj res; @@ -152,20 +152,20 @@ namespace mongo { BSONObj getnoncecmdobj = fromjson("{getnonce:1}"); - string DBClientWithCommands::createPasswordDigest( const char * username , const char * clearTextPassword ){ + string DBClientWithCommands::createPasswordDigest( const string & username , const string & clearTextPassword ){ md5digest d; { md5_state_t st; md5_init(&st); - md5_append(&st, (const md5_byte_t *) username, strlen(username)); + md5_append(&st, (const md5_byte_t *) username.data(), username.length()); md5_append(&st, (const md5_byte_t *) ":mongo:", 7 ); - md5_append(&st, (const md5_byte_t *) clearTextPassword, strlen(clearTextPassword)); + md5_append(&st, (const md5_byte_t *) clearTextPassword.data(), clearTextPassword.length()); md5_finish(&st, d); } return digestToString( d ); } - bool DBClientWithCommands::auth(const char *dbname, const char *username, const char *password_text, string& errmsg, bool digestPassword) { + bool DBClientWithCommands::auth(const string &dbname, const string &username, const string &password_text, string& errmsg, bool digestPassword) { //cout << "TEMP AUTH " << toString() << dbname << ' ' << username << ' ' << password_text << ' ' << digestPassword << endl; string password = password_text; @@ -194,7 +194,7 @@ namespace mongo { md5_state_t st; md5_init(&st); md5_append(&st, (const md5_byte_t *) nonce.c_str(), nonce.size() ); - md5_append(&st, (const md5_byte_t *) username, strlen(username)); + md5_append(&st, (const md5_byte_t *) username.data(), username.length()); md5_append(&st, (const md5_byte_t *) password.c_str(), password.size() ); md5_finish(&st, d); } @@ -219,7 +219,7 @@ namespace mongo { return ok; } - bool DBClientWithCommands::createCollection(const char *ns, unsigned size, bool capped, int max, BSONObj *info) { + bool DBClientWithCommands::createCollection(const string &ns, unsigned size, bool capped, int max, BSONObj *info) { BSONObj o; if ( info == 0 ) info = &o; BSONObjBuilder b; @@ -227,12 +227,11 @@ namespace mongo { if ( size ) b.append("size", size); if ( capped ) b.append("capped", true); if ( max ) b.append("max", max); - string db = nsToClient(ns); + string db = nsToClient(ns.c_str()); return runCommand(db.c_str(), b.done(), *info); } - bool DBClientWithCommands::copyDatabase(const char *fromdb, const char *todb, const char *fromhost, BSONObj *info) { - assert( *fromdb && *todb ); + bool DBClientWithCommands::copyDatabase(const string &fromdb, const string &todb, const string &fromhost, BSONObj *info) { BSONObj o; if ( info == 0 ) info = &o; BSONObjBuilder b; @@ -243,7 +242,7 @@ namespace mongo { return runCommand("admin", b.done(), *info); } - bool DBClientWithCommands::setDbProfilingLevel(const char *dbname, ProfilingLevel level, BSONObj *info ) { + bool DBClientWithCommands::setDbProfilingLevel(const string &dbname, ProfilingLevel level, BSONObj *info ) { BSONObj o; if ( info == 0 ) info = &o; @@ -251,7 +250,7 @@ namespace mongo { // Create system.profile collection. If it already exists this does nothing. // TODO: move this into the db instead of here so that all // drivers don't have to do this. - string ns = string(dbname) + ".system.profile"; + string ns = dbname + ".system.profile"; createCollection(ns.c_str(), 1024 * 1024, true, 0, info); } @@ -262,7 +261,7 @@ namespace mongo { BSONObj getprofilingcmdobj = fromjson("{\"profile\":-1}"); - bool DBClientWithCommands::getDbProfilingLevel(const char *dbname, ProfilingLevel& level, BSONObj *info) { + bool DBClientWithCommands::getDbProfilingLevel(const string &dbname, ProfilingLevel& level, BSONObj *info) { BSONObj o; if ( info == 0 ) info = &o; if ( runCommand(dbname, getprofilingcmdobj, *info) ) { @@ -272,9 +271,9 @@ namespace mongo { return false; } - bool DBClientWithCommands::eval(const char *dbname, const char *jscode, BSONObj& info, BSONElement& retValue, BSONObj *args) { + bool DBClientWithCommands::eval(const string &dbname, const string &jscode, BSONObj& info, BSONElement& retValue, BSONObj *args) { BSONObjBuilder b; - b.appendCode("$eval", jscode); + b.appendCode("$eval", jscode.c_str()); if ( args ) b.appendArray("args", *args); bool ok = runCommand(dbname, b.done(), info); @@ -283,7 +282,7 @@ namespace mongo { return ok; } - bool DBClientWithCommands::eval(const char *dbname, const char *jscode) { + bool DBClientWithCommands::eval(const string &dbname, const string &jscode) { BSONObj info; BSONElement retValue; return eval(dbname, jscode, info, retValue); @@ -349,7 +348,7 @@ namespace mongo { /* --- dbclientconnection --- */ - bool DBClientConnection::auth(const char *dbname, const char *username, const char *password_text, string& errmsg, bool digestPassword) { + bool DBClientConnection::auth(const string &dbname, const string &username, const string &password_text, string& errmsg, bool digestPassword) { string password = password_text; if( digestPassword ) password = createPasswordDigest( username , password_text ); @@ -365,7 +364,7 @@ namespace mongo { return DBClientBase::auth(dbname, username, password.c_str(), errmsg, false); } - BSONObj DBClientBase::findOne(const char *ns, Query query, BSONObj *fieldsToReturn, int queryOptions) { + BSONObj DBClientBase::findOne(const string &ns, Query query, BSONObj *fieldsToReturn, int queryOptions) { auto_ptr<DBClientCursor> c = this->query(ns, query, 1, 0, fieldsToReturn, queryOptions); @@ -377,7 +376,7 @@ namespace mongo { return c->next().copy(); } - bool DBClientConnection::connect(const char *_serverAddress, string& errmsg) { + bool DBClientConnection::connect(const string &_serverAddress, string& errmsg) { serverAddress = _serverAddress; string ip; @@ -436,7 +435,7 @@ namespace mongo { } } - auto_ptr<DBClientCursor> DBClientBase::query(const char *ns, Query query, int nToReturn, + auto_ptr<DBClientCursor> DBClientBase::query(const string &ns, Query query, int nToReturn, int nToSkip, BSONObj *fieldsToReturn, int queryOptions) { auto_ptr<DBClientCursor> c( new DBClientCursor( this, ns, query.obj, nToReturn, nToSkip, @@ -446,14 +445,14 @@ namespace mongo { return auto_ptr< DBClientCursor >( 0 ); } - auto_ptr<DBClientCursor> DBClientBase::getMore( const char *ns, long long cursorId, int nToReturn, int options ) { + auto_ptr<DBClientCursor> DBClientBase::getMore( const string &ns, long long cursorId, int nToReturn, int options ) { auto_ptr<DBClientCursor> c( new DBClientCursor( this, ns, cursorId, nToReturn, options ) ); if ( c->init() ) return c; return auto_ptr< DBClientCursor >( 0 ); } - void DBClientBase::insert( const char * ns , BSONObj obj ) { + void DBClientBase::insert( const string & ns , BSONObj obj ) { Message toSend; BufBuilder b; @@ -467,7 +466,7 @@ namespace mongo { say( toSend ); } - void DBClientBase::insert( const char * ns , const vector< BSONObj > &v ) { + void DBClientBase::insert( const string & ns , const vector< BSONObj > &v ) { Message toSend; BufBuilder b; @@ -482,7 +481,7 @@ namespace mongo { say( toSend ); } - void DBClientBase::remove( const char * ns , Query obj , bool justOne ) { + void DBClientBase::remove( const string & ns , Query obj , bool justOne ) { Message toSend; BufBuilder b; @@ -502,7 +501,7 @@ namespace mongo { say( toSend ); } - void DBClientBase::update( const char * ns , Query query , BSONObj obj , bool upsert ) { + void DBClientBase::update( const string & ns , Query query , BSONObj obj , bool upsert ) { BufBuilder b; b.append( (int)0 ); // reserverd @@ -519,7 +518,7 @@ namespace mongo { say( toSend ); } - bool DBClientBase::ensureIndex( const string &ns , BSONObj keys , const char * name ) { + bool DBClientBase::ensureIndex( const string &ns , BSONObj keys , const string & name ) { BSONObjBuilder toSave; toSave.append( "ns" , ns ); toSave.append( "key" , keys ); @@ -527,7 +526,7 @@ namespace mongo { string cacheKey(ns); cacheKey += "--"; - if ( name ) { + if ( name != "" ) { toSave.append( "name" , name ); cacheKey += name; } @@ -840,7 +839,7 @@ again: return master == Left ? left : right; } - bool DBClientPaired::connect(const char *serverHostname1, const char *serverHostname2) { + bool DBClientPaired::connect(const string &serverHostname1, const string &serverHostname2) { string errmsg; bool l = left.connect(serverHostname1, errmsg); bool r = right.connect(serverHostname2, errmsg); @@ -856,7 +855,7 @@ again: return true; } - bool DBClientPaired::auth(const char *dbname, const char *username, const char *pwd, string& errmsg) { + bool DBClientPaired::auth(const string &dbname, const string &username, const string &pwd, string& errmsg) { DBClientConnection& m = checkMaster(); if( !m.auth(dbname, username, pwd, errmsg) ) return false; @@ -873,13 +872,13 @@ again: return true; } - auto_ptr<DBClientCursor> DBClientPaired::query(const char *a, Query b, int c, int d, + auto_ptr<DBClientCursor> DBClientPaired::query(const string &a, Query b, int c, int d, BSONObj *e, int f) { return checkMaster().query(a,b,c,d,e,f); } - BSONObj DBClientPaired::findOne(const char *a, Query b, BSONObj *c, int d) { + BSONObj DBClientPaired::findOne(const string &a, Query b, BSONObj *c, int d) { return checkMaster().findOne(a,b,c,d); } diff --git a/client/dbclient.h b/client/dbclient.h index ce65f44c495..a5b2374fc14 100644 --- a/client/dbclient.h +++ b/client/dbclient.h @@ -60,8 +60,8 @@ namespace mongo { Query(const BSONObj& b) : obj(b) { } Query(const string &json) : obj(fromjson(json)) { } - Query(const char *json) : - obj(fromjson(json)) { } + Query(const char * json) : + obj(fromjson(json)) { } /** Add a sort (ORDER BY) criteria to the query expression. @param sortPattern the sort order template. For example to order by name ascending, time descending: @@ -78,7 +78,7 @@ namespace mongo { @param asc = 1 for ascending order asc = -1 for descending order */ - Query& sort(const char *field, int asc = 1) { sort( BSON( field << asc ) ); return *this; } + Query& sort(const string &field, int asc = 1) { sort( BSON( field << asc ) ); return *this; } /** Provide a hint to the query. @param keyPattern Key pattern for the index to use. @@ -86,7 +86,7 @@ namespace mongo { hint("{ts:1}") */ Query& hint(BSONObj keyPattern); - Query& hint(const char *jsonKeyPatt) { return hint(fromjson(jsonKeyPatt)); } + Query& hint(const string &jsonKeyPatt) { return hint(fromjson(jsonKeyPatt)); } /** Return explain information about execution of this query instead of the actual query results. Normally it is easier to use the mongo shell to run db.find(...).explain(). @@ -109,8 +109,8 @@ namespace mongo { conn.findOne("test.coll", Query("{a:3}").where("this.b == 2 || this.c == 3")); Query badBalance = Query().where("this.debits - this.credits < 0"); */ - Query& where(const char *jscode, BSONObj scope); - Query& where(const char *jscode) { return where(jscode, BSONObj()); } + Query& where(const string &jscode, BSONObj scope); + Query& where(const string &jscode) { return where(jscode, BSONObj()); } /** @@ -141,7 +141,7 @@ namespace mongo { virtual bool call( Message &toSend, Message &response, bool assertOk=true ) = 0; virtual void say( Message &toSend ) = 0; virtual void sayPiggyBack( Message &toSend ) = 0; - virtual void checkResponse( const char *data, int nReturned ) {} + virtual void checkResponse( const string &data, int nReturned ) {} }; /** Queries return a cursor object */ @@ -181,7 +181,7 @@ namespace mongo { bool init(); - DBClientCursor( DBConnector *_connector, const char * _ns, BSONObj _query, int _nToReturn, + DBClientCursor( DBConnector *_connector, const string &_ns, BSONObj _query, int _nToReturn, int _nToSkip, BSONObj *_fieldsToReturn, int queryOptions ) : connector(_connector), ns(_ns), @@ -198,7 +198,7 @@ namespace mongo { ownCursor_( true ) { } - DBClientCursor( DBConnector *_connector, const char *_ns, long long _cursorId, int _nToReturn, int options ) : + DBClientCursor( DBConnector *_connector, const string &_ns, long long _cursorId, int _nToReturn, int options ) : connector(_connector), ns(_ns), nToReturn( _nToReturn ), @@ -241,20 +241,20 @@ namespace mongo { */ class DBClientInterface : boost::noncopyable { public: - virtual auto_ptr<DBClientCursor> query(const char *ns, Query query, int nToReturn = 0, int nToSkip = 0, + virtual auto_ptr<DBClientCursor> query(const string &ns, Query query, int nToReturn = 0, int nToSkip = 0, BSONObj *fieldsToReturn = 0, int queryOptions = 0) = 0; - virtual auto_ptr<DBClientCursor> getMore( const char *ns, long long cursorId, int nToReturn = 0, int options = 0 ) = 0; + virtual auto_ptr<DBClientCursor> getMore( const string &ns, long long cursorId, int nToReturn = 0, int options = 0 ) = 0; - virtual BSONObj findOne(const char *ns, Query query, BSONObj *fieldsToReturn = 0, int queryOptions = 0) = 0; + virtual BSONObj findOne(const string &ns, Query query, BSONObj *fieldsToReturn = 0, int queryOptions = 0) = 0; - virtual void insert( const char * ns, BSONObj obj ) = 0; + virtual void insert( const string &ns, BSONObj obj ) = 0; - virtual void insert( const char * ns, const vector< BSONObj >& v ) = 0; + virtual void insert( const string &ns, const vector< BSONObj >& v ) = 0; - virtual void remove( const char * ns , Query query, bool justOne = 0 ) = 0; + virtual void remove( const string &ns , Query query, bool justOne = 0 ) = 0; - virtual void update( const char * ns , Query query , BSONObj obj , bool upsert = 0 ) = 0; + virtual void update( const string &ns , Query query , BSONObj obj , bool upsert = 0 ) = 0; virtual ~DBClientInterface() { } }; @@ -265,7 +265,7 @@ namespace mongo { */ class DBClientWithCommands : public DBClientInterface { bool isOk(const BSONObj&); - bool simpleCommand(const char *dbname, BSONObj *info, const char *command); + bool simpleCommand(const string &dbname, BSONObj *info, const string &command); public: /** Run a database command. Database commands are represented as BSON objects. Common database commands have prebuilt helper functions -- see below. If a helper is not available you can @@ -278,7 +278,7 @@ namespace mongo { @return true if the command returned "ok". */ - bool runCommand(const char *dbname, const BSONObj& cmd, BSONObj &info); + bool runCommand(const string &dbname, const BSONObj& cmd, BSONObj &info); /** Authorize access to a particular database. Authentication is separate for each database on the server -- you may authenticate for any @@ -288,14 +288,14 @@ namespace mongo { @param digestPassword if password is plain text, set this to true. otherwise assumed to be pre-digested @return true if successful */ - virtual bool auth(const char *dbname, const char *username, const char *pwd, string& errmsg, bool digestPassword = true); + virtual bool auth(const string &dbname, const string &username, const string &pwd, string& errmsg, bool digestPassword = true); /** count number of objects in collection ns that match the query criteria specified throws UserAssertion if database returns an error */ - unsigned long long count(const char *ns, BSONObj query = BSONObj()); + unsigned long long count(const string &ns, BSONObj query = BSONObj()); - string createPasswordDigest( const char * username , const char * clearTextPassword ); + string createPasswordDigest( const string &username , const string &clearTextPassword ); /** returns true in isMaster parm if this db is the current master of a replica pair. @@ -323,7 +323,7 @@ namespace mongo { returns true if successful. */ - bool createCollection(const char *ns, unsigned size = 0, bool capped = false, int max = 0, BSONObj *info = 0); + bool createCollection(const string &ns, unsigned size = 0, bool capped = false, int max = 0, BSONObj *info = 0); /** Get error result from the last operation on this connection. @return error or empty string if no error. @@ -345,7 +345,7 @@ namespace mongo { bool resetError() { return simpleCommand("admin", 0, "reseterror"); } /** Erase / drop an entire database */ - bool dropDatabase(const char *dbname, BSONObj *info = 0) { + bool dropDatabase(const string &dbname, BSONObj *info = 0) { return simpleCommand(dbname, info, "dropDatabase"); } @@ -364,7 +364,7 @@ namespace mongo { /** Perform a repair and compaction of the specified database. May take a long time to run. Disk space must be available equal to the size of the database while repairing. */ - bool repairDatabase(const char *dbname, BSONObj *info = 0) { + bool repairDatabase(const string &dbname, BSONObj *info = 0) { return simpleCommand(dbname, info, "repairDatabase"); } @@ -387,7 +387,7 @@ namespace mongo { returns true if successful */ - bool copyDatabase(const char *fromdb, const char *todb, const char *fromhost = "", BSONObj *info = 0); + bool copyDatabase(const string &fromdb, const string &todb, const string &fromhost = "", BSONObj *info = 0); /** The Mongo database provides built-in performance profiling capabilities. Uset setDbProfilingLevel() to enable. Profiling information is then written to the system.profiling collection, which one can @@ -398,8 +398,8 @@ namespace mongo { ProfileSlow = 1, // log very slow (>100ms) operations ProfileAll = 2 }; - bool setDbProfilingLevel(const char *dbname, ProfilingLevel level, BSONObj *info = 0); - bool getDbProfilingLevel(const char *dbname, ProfilingLevel& level, BSONObj *info = 0); + bool setDbProfilingLevel(const string &dbname, ProfilingLevel level, BSONObj *info = 0); + bool getDbProfilingLevel(const string &dbname, ProfilingLevel& level, BSONObj *info = 0); /** Run javascript code on the database server. dbname database context in which the code runs. The javascript variable 'db' will be assigned @@ -416,12 +416,12 @@ namespace mongo { See testDbEval() in dbclient.cpp for an example of usage. */ - bool eval(const char *dbname, const char *jscode, BSONObj& info, BSONElement& retValue, BSONObj *args = 0); + bool eval(const string &dbname, const string &jscode, BSONObj& info, BSONElement& retValue, BSONObj *args = 0); /** */ - bool validate( const char * ns , bool scandata=true ){ + bool validate( const string &ns , bool scandata=true ){ BSONObj cmd = BSON( "validate" << nsGetCollection( ns ) << "scandata" << scandata ); BSONObj info; return runCommand( nsGetDB( ns ).c_str() , cmd , info ); @@ -430,9 +430,9 @@ namespace mongo { /* The following helpers are simply more convenient forms of eval() for certain common cases */ /* invocation with no return value of interest -- with or without one simple parameter */ - bool eval(const char *dbname, const char *jscode); + bool eval(const string &dbname, const string &jscode); template< class T > - bool eval(const char *dbname, const char *jscode, T parm1) { + bool eval(const string &dbname, const string &jscode, T parm1) { BSONObj info; BSONElement retValue; BSONObjBuilder b; @@ -443,7 +443,7 @@ namespace mongo { /** eval invocation with one parm to server and one numeric field (either int or double) returned */ template< class T, class NumType > - bool eval(const char *dbname, const char *jscode, T parm1, NumType& ret) { + bool eval(const string &dbname, const string &jscode, T parm1, NumType& ret) { BSONObj info; BSONElement retValue; BSONObjBuilder b; @@ -497,41 +497,41 @@ namespace mongo { @return cursor. 0 if error (connection failure) @throws AssertionException */ - virtual auto_ptr<DBClientCursor> query(const char *ns, Query query, int nToReturn = 0, int nToSkip = 0, + virtual auto_ptr<DBClientCursor> query(const string &ns, Query query, int nToReturn = 0, int nToSkip = 0, BSONObj *fieldsToReturn = 0, int queryOptions = 0); /** @param cursorId id of cursor to retrieve @return an handle to a previously allocated cursor @throws AssertionException */ - virtual auto_ptr<DBClientCursor> getMore( const char *ns, long long cursorId, int nToReturn = 0, int options = 0 ); + virtual auto_ptr<DBClientCursor> getMore( const string &ns, long long cursorId, int nToReturn = 0, int options = 0 ); /** @return a single object that matches the query. if none do, then the object is empty @throws AssertionException */ - virtual BSONObj findOne(const char *ns, Query query, BSONObj *fieldsToReturn = 0, int queryOptions = 0); + virtual BSONObj findOne(const string &ns, Query query, BSONObj *fieldsToReturn = 0, int queryOptions = 0); /** insert an object into the database */ - virtual void insert( const char * ns , BSONObj obj ); + virtual void insert( const string &ns , BSONObj obj ); /** insert a vector of objects into the database */ - virtual void insert( const char * ns, const vector< BSONObj >& v ); + virtual void insert( const string &ns, const vector< BSONObj >& v ); /** remove matching objects from the database @param justOne if this true, then once a single match is found will stop */ - virtual void remove( const char * ns , Query q , bool justOne = 0 ); + virtual void remove( const string &ns , Query q , bool justOne = 0 ); /** updates objects matching query */ - virtual void update( const char * ns , Query query , BSONObj obj , bool upsert = 0 ); + virtual void update( const string &ns , Query query , BSONObj obj , bool upsert = 0 ); /** Create an index if it does not already exist. ensureIndex calls are remembered so it is safe/fast to call this function many @@ -541,12 +541,14 @@ namespace mongo { @return whether or not sent message to db. should be true on first call, false on subsequent unless resetIndexCache was called */ - virtual bool ensureIndex( const string &ns , BSONObj keys , const char * name = 0 ); + virtual bool ensureIndex( const string &ns , BSONObj keys , const string &name = "" ); /** clears the index cache, so the subsequent call to ensureIndex for any index will go to the server */ virtual void resetIndexCache(); + + virtual string getServerAddress() const = 0; private: set<string> _seenIndexes; @@ -592,7 +594,7 @@ namespace mongo { @param errmsg any relevant error message will appended to the string @return false if fails to connect. */ - virtual bool connect(const char *serverHostname, string& errmsg); + virtual bool connect(const string &serverHostname, string& errmsg); /** Connect to a Mongo database server. Exception throwing version. Throws a UserException if cannot connect. @@ -608,9 +610,9 @@ namespace mongo { throw ConnectException(string("can't connect ") + errmsg); } - virtual bool auth(const char *dbname, const char *username, const char *pwd, string& errmsg, bool digestPassword = true); + virtual bool auth(const string &dbname, const string &username, const string &pwd, string& errmsg, bool digestPassword = true); - virtual auto_ptr<DBClientCursor> query(const char *ns, Query query, int nToReturn = 0, int nToSkip = 0, + virtual auto_ptr<DBClientCursor> query(const string &ns, Query query, int nToReturn = 0, int nToSkip = 0, BSONObj *fieldsToReturn = 0, int queryOptions = 0) { checkConnection(); return DBClientBase::query( ns, query, nToReturn, nToSkip, fieldsToReturn, queryOptions ); @@ -639,6 +641,10 @@ namespace mongo { string toString() { return serverAddress; } + + string getServerAddress() const { + return serverAddress; + } protected: virtual bool call( Message &toSend, Message &response, bool assertOk = true ); @@ -673,7 +679,7 @@ namespace mongo { when false returned, you can still try to use this connection object, it will try reconnects. */ - bool connect(const char *serverHostname1, const char *serverHostname2); + bool connect(const string &serverHostname1, const string &serverHostname2); /** Connect to a server pair using a host pair string of the form hostname[:port],hostname[:port] @@ -686,35 +692,35 @@ namespace mongo { /** Authorize. Authorizes both sides of the pair as needed. */ - bool auth(const char *dbname, const char *username, const char *pwd, string& errmsg); + bool auth(const string &dbname, const string &username, const string &pwd, string& errmsg); /** throws userassertion "no master found" */ virtual - auto_ptr<DBClientCursor> query(const char *ns, Query query, int nToReturn = 0, int nToSkip = 0, + auto_ptr<DBClientCursor> query(const string &ns, Query query, int nToReturn = 0, int nToSkip = 0, BSONObj *fieldsToReturn = 0, int queryOptions = 0); /** throws userassertion "no master found" */ virtual - BSONObj findOne(const char *ns, Query query, BSONObj *fieldsToReturn = 0, int queryOptions = 0); + BSONObj findOne(const string &ns, Query query, BSONObj *fieldsToReturn = 0, int queryOptions = 0); /** insert */ - virtual void insert( const char * ns , BSONObj obj ) { + virtual void insert( const string &ns , BSONObj obj ) { checkMaster().insert(ns, obj); } /** insert multiple objects. Note that single object insert is asynchronous, so this version is only nominally faster and not worth a special effort to try to use. */ - virtual void insert( const char * ns, const vector< BSONObj >& v ) { + virtual void insert( const string &ns, const vector< BSONObj >& v ) { checkMaster().insert(ns, v); } /** remove */ - virtual void remove( const char * ns , Query obj , bool justOne = 0 ) { + virtual void remove( const string &ns , Query obj , bool justOne = 0 ) { checkMaster().remove(ns, obj, justOne); } /** update */ - virtual void update( const char * ns , Query query , BSONObj obj , bool upsert = 0 ) { + virtual void update( const string &ns , Query query , BSONObj obj , bool upsert = 0 ) { return checkMaster().update(ns, query, obj, upsert); } @@ -726,6 +732,10 @@ namespace mongo { master = ( ( master == Left ) ? NotSetR : NotSetL ); } + string getServerAddress() const { + return left.getServerAddress() + "," + right.getServerAddress(); + } + /* TODO - not yet implemented. mongos may need these. */ virtual bool call( Message &toSend, Message &response, bool assertOk=true ) { assert(false); return false; } virtual void say( Message &toSend ) { assert(false); } diff --git a/client/model.h b/client/model.h index f50bab2f98b..f0c57149e70 100644 --- a/client/model.h +++ b/client/model.h @@ -43,12 +43,12 @@ namespace mongo { virtual void unserialize(const BSONObj& from) = 0; virtual string modelServer() = 0; - + /** Load a single object. @return true if successful. */ - bool load(BSONObj& query); - void save( bool check=false ); + virtual bool load(BSONObj& query); + virtual void save( bool check=false ); private: BSONObj _id; diff --git a/db/instance.h b/db/instance.h index 925cdb49ac3..4b45df78e33 100644 --- a/db/instance.h +++ b/db/instance.h @@ -99,11 +99,14 @@ namespace mongo { // --- local client --- - + class DBDirectClient : public DBClientBase { virtual string toString() { return "DBDirectClient"; } + virtual string getServerAddress() const{ + return "localhost"; // TODO: should this have the port? + } virtual bool call( Message &toSend, Message &response, bool assertOk=true ); virtual void say( Message &toSend ); virtual void sayPiggyBack( Message &toSend ) { diff --git a/db/jsobj.cpp b/db/jsobj.cpp index 5beda57f66c..e6588dc73cf 100644 --- a/db/jsobj.cpp +++ b/db/jsobj.cpp @@ -1056,7 +1056,7 @@ namespace mongo { BSONElement::BSONElement() { data = &js0.eoo; fieldNameSize_ = 0; - totalSize = 5; + totalSize = 1; } struct BsonUnitTest : public UnitTest { diff --git a/db/jsobj.h b/db/jsobj.h index b551b4bf828..b64535e3ee5 100644 --- a/db/jsobj.h +++ b/db/jsobj.h @@ -858,6 +858,10 @@ namespace mongo { b.append(fieldName); b.append(n); } + /** Append a 32 bit integer element */ + void append(const string &fieldName, int n) { + append( fieldName.c_str(), n ); + } void append(const char *fieldName, unsigned n) { append(fieldName, (int) n); } /** Append a double element */ BSONObjBuilder& append(const char *fieldName, double n) { @@ -1014,6 +1018,9 @@ namespace mongo { void appendWhere( const char *code, const BSONObj &scope ){ appendCodeWScope( "$where" , code , scope ); } + void appendWhere( const string &code, const BSONObj &scope ){ + appendWhere( code.c_str(), scope ); + } /** Append an array of values. */ template < class T > diff --git a/dbtests/jsobjtests.cpp b/dbtests/jsobjtests.cpp index 45ca4938143..fad6a181e69 100644 --- a/dbtests/jsobjtests.cpp +++ b/dbtests/jsobjtests.cpp @@ -25,6 +25,13 @@ #include "dbtests.h" namespace JsobjTests { + class BSONElementBasic { + public: + void run() { + ASSERT_EQUALS( 1, BSONElement().size() ); + } + }; + namespace BSONObjTests { class Create { public: @@ -567,6 +574,7 @@ namespace JsobjTests { class All : public UnitTest::Suite { public: All() { + add< BSONElementBasic >(); add< BSONObjTests::Create >(); add< BSONObjTests::WoCompareBasic >(); add< BSONObjTests::NumericCompareBasic >(); diff --git a/dbtests/mockdbclient.h b/dbtests/mockdbclient.h index 23ae226b4d2..be6c420e5f0 100644 --- a/dbtests/mockdbclient.h +++ b/dbtests/mockdbclient.h @@ -25,11 +25,11 @@ class MockDBClientConnection : public DBClientConnection { public: MockDBClientConnection() : connect_() {} virtual - BSONObj findOne(const char *ns, Query query, BSONObj *fieldsToReturn = 0, int queryOptions = 0) { + BSONObj findOne(const string &ns, Query query, BSONObj *fieldsToReturn = 0, int queryOptions = 0) { return one_; } virtual - bool connect(const char *serverHostname, string& errmsg) { + bool connect(const string &serverHostname, string& errmsg) { return connect_; } virtual @@ -62,7 +62,7 @@ public: rp_( rp ), cc_( cc ) { } - virtual BSONObj findOne(const char *ns, Query query, BSONObj *fieldsToReturn = 0, int queryOptions = 0) { + virtual BSONObj findOne(const string &ns, Query query, BSONObj *fieldsToReturn = 0, int queryOptions = 0) { if ( cc_ ) cc_->beforeCommand(); SetGlobalReplPair s( rp_ ); BSONObjBuilder result; @@ -70,7 +70,7 @@ public: if ( cc_ ) cc_->afterCommand(); return result.obj(); } - virtual bool connect( const char *serverHostname, string& errmsg ) { + virtual bool connect( const string &serverHostname, string& errmsg ) { return true; } private: diff --git a/jstests/repl/repl6.js b/jstests/repl/repl6.js new file mode 100644 index 00000000000..7d3f265f328 --- /dev/null +++ b/jstests/repl/repl6.js @@ -0,0 +1,76 @@ +// Test one master replicating to two slaves + +var baseName = "jstests_repl6test"; + +soonCount = function( m, count ) { + assert.soon( function() { + // print( "check count" ); + if ( -1 == m.getDBNames().indexOf( baseName ) ) + return false; + if ( -1 == m.getDB( baseName ).getCollectionNames().indexOf( "a" ) ) + return false; + // print( "count: " + s.getDB( baseName ).z.find().count() ); + return m.getDB( baseName ).a.find().count() == count; + } ); +} + +doTest = function( signal ) { + + // spec small oplog for fast startup on 64bit machines + m = startMongod( "--port", "27018", "--dbpath", "/data/db/" + baseName + "-master", "--master", "--oplogSize", "1" ); + s1 = startMongod( "--port", "27019", "--dbpath", "/data/db/" + baseName + "-slave1", "--slave", "--source", "127.0.0.1:27018" ); + s2 = startMongod( "--port", "27020", "--dbpath", "/data/db/" + baseName + "-slave2", "--slave", "--source", "127.0.0.1:27018" ); + + am = m.getDB( baseName ).a + + for( i = 0; i < 1000; ++i ) + am.save( { _id: new ObjectId(), i: i } ); + + soonCount( s1, 1000 ); + soonCount( s2, 1000 ); + + check = function( as ) { + assert.eq( 1, as.find( { i: 0 } ).count() ); + assert.eq( 1, as.find( { i: 999 } ).count() ); + } + + as = s1.getDB( baseName ).a + check( as ); + as = s2.getDB( baseName ).a + check( as ); + + stopMongod( 27019, signal ); + stopMongod( 27020, signal ); + + for( i = 1000; i < 1010; ++i ) + am.save( { _id: new ObjectId(), i: i } ); + + s1 = startMongoProgram( "mongod", "--port", "27019", "--dbpath", "/data/db/" + baseName + "-slave1", "--slave", "--source", "127.0.0.1:27018" ); + soonCount( s1, 1010 ); + as = s1.getDB( baseName ).a + assert.eq( 1, as.find( { i: 1009 } ).count() ); + + stopMongod( 27018, signal ); + + m = startMongoProgram( "mongod", "--port", "27018", "--dbpath", "/data/db/" + baseName + "-master", "--master", "--oplogSize", "1" ); + am = m.getDB( baseName ).a + + for( i = 1010; i < 1020; ++i ) + am.save( { _id: new ObjectId(), i: i } ); + + soonCount( s1, 1020 ); + assert.eq( 1, as.find( { i: 1019 } ).count() ); + + s2 = startMongoProgram( "mongod", "--port", "27020", "--dbpath", "/data/db/" + baseName + "-slave2", "--slave", "--source", "127.0.0.1:27018" ); + soonCount( s2, 1020 ); + as = s2.getDB( baseName ).a + assert.eq( 1, as.find( { i: 1009 } ).count() ); + assert.eq( 1, as.find( { i: 1019 } ).count() ); + + stopMongod( 27018 ); + stopMongod( 27019 ); + stopMongod( 27020 ); +} + +doTest( 15 ); // SIGTERM +doTest( 9 ); // SIGKILL diff --git a/mongo.xcodeproj/project.pbxproj b/mongo.xcodeproj/project.pbxproj index e5deaeb86e8..37c7cd616b9 100644 --- a/mongo.xcodeproj/project.pbxproj +++ b/mongo.xcodeproj/project.pbxproj @@ -243,6 +243,7 @@ 93D6BC9B0F266FC300FE5722 /* querytests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = querytests.cpp; sourceTree = "<group>"; }; 93D941BF0F77D64F00C3C768 /* replacePeer1.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = replacePeer1.js; sourceTree = "<group>"; }; 93D941C00F77D64F00C3C768 /* replacePeer2.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = replacePeer2.js; sourceTree = "<group>"; }; + 93D9469F0F7ABB0600C3C768 /* repl6.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = repl6.js; sourceTree = "<group>"; }; 93E3C5310F704C9D0029011E /* repl4.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = repl4.js; sourceTree = "<group>"; }; 93E3C5960F7149F40029011E /* repl5.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = repl5.js; sourceTree = "<group>"; }; 93E727090F4B5B5B004F9B5D /* shardkey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shardkey.cpp; sourceTree = "<group>"; }; @@ -608,6 +609,7 @@ 93A8D2040F37544800C92B85 /* repl */ = { isa = PBXGroup; children = ( + 93D9469F0F7ABB0600C3C768 /* repl6.js */, 93D941BF0F77D64F00C3C768 /* replacePeer1.js */, 93D941C00F77D64F00C3C768 /* replacePeer2.js */, 93E3C5960F7149F40029011E /* repl5.js */, diff --git a/shell/dbshell.cpp b/shell/dbshell.cpp index edaa3d9625a..35860c370a8 100644 --- a/shell/dbshell.cpp +++ b/shell/dbshell.cpp @@ -46,18 +46,42 @@ char * shellReadline( const char * prompt ){ #endif } +#if !defined(_WIN32) +#include <execinfo.h> +#include <string.h> + void quitNicely( int sig ){ shellHistoryDone(); exit(0); } +/* use "addr2line -CFe <exe>" to parse. */ +inline void printStackTrace() { + void *b[20]; + size_t size; + char **strings; + size_t i; + + size = backtrace(b, 20); + strings = backtrace_symbols(b, size); + + for (i = 0; i < size; i++) + cout << hex << b[i] << ' '; + cout << '\n'; + for (i = 0; i < size; i++) + cout << ' ' << strings[i] << '\n'; + cout << dec; + free (strings); +} + void quitAbruptly( int sig ) { + cout << "mongo got signal" << sig << " (" << strsignal( sig ) << "), stack trace: " << endl; + printStackTrace(); KillMongoProgramInstances(); exit(14); } void setupSignals() { -#ifndef _WIN32 signal( SIGINT , quitNicely ); signal( SIGTERM , quitNicely ); signal( SIGPIPE , quitNicely ); // Maybe just log and continue? @@ -65,8 +89,10 @@ void setupSignals() { signal( SIGSEGV , quitAbruptly ); signal( SIGBUS , quitAbruptly ); signal( SIGFPE , quitAbruptly ); -#endif } +#else +inline void setupSignals() {} +#endif string fixHost( string url , string host , string port ){ if ( host.size() == 0 && port.size() == 0 ){ diff --git a/util/builder.h b/util/builder.h index a637d5743b8..85e1c3639e5 100644 --- a/util/builder.h +++ b/util/builder.h @@ -83,6 +83,10 @@ namespace mongo { void append(const char *str) { append((void*) str, strlen(str)+1); } + + void append(const string &str) { + append( (void *)str.c_str(), str.length() + 1 ); + } int len() { return l; |