From 2d934d1006c7c018fad0cdfe91dc4e2b00d2107e Mon Sep 17 00:00:00 2001 From: Dwight Date: Tue, 13 Oct 2009 16:01:02 -0400 Subject: [PATCH] move curNs to Client object --- db/client.h | 26 ++++++++++++++++++++++---- db/cloner.cpp | 2 +- db/db.cpp | 9 ++++++++- db/db.h | 29 ++++++++++++----------------- db/dbcommands.cpp | 10 +++++----- db/dbhelpers.h | 4 ++-- db/dbinfo.h | 2 +- db/instance.h | 2 +- db/matcher.cpp | 6 +++--- db/namespace.cpp | 4 ++-- db/namespace.h | 5 ++--- db/pdfile.cpp | 6 ++---- db/repl.cpp | 23 ++++++++++++++--------- db/security.cpp | 9 +++++++++ dbtests/dbtests.cpp | 1 + s/server.cpp | 1 - util/log.h | 23 ++++++++++++----------- util/util.cpp | 5 ++++- 18 files changed, 101 insertions(+), 66 deletions(-) diff --git a/db/client.h b/db/client.h index c497dae87d5..0eb887cd396 100644 --- a/db/client.h +++ b/db/client.h @@ -25,27 +25,45 @@ #pragma once #include "lasterror.h" -#include "security.h" namespace mongo { - /* TODO: _ i bet these are not cleaned up on thread exit? if so fix */ + class AuthenticationInfo; + /* TODO: _ i bet these are not cleaned up on thread exit? if so fix */ class Client { + Namespace _ns; + NamespaceString _nsstr; public: AuthenticationInfo *ai; - Client() { ai = new AuthenticationInfo(); } - ~Client() { delete ai; } + const char *ns() { return _ns.buf; } + void setns(const char *ns) { + _ns = ns; + _nsstr = ns; + } + + Client(); + ~Client(); + + /* each thread which does db operations has a Client object in TLS. + call this when your thread starts. + */ static void initThread(); }; + /* defined in security.cpp */ extern boost::thread_specific_ptr currentClient; + inline Client& cc() { + return *currentClient.get(); + } + inline void Client::initThread() { assert( currentClient.get() == 0 ); currentClient.reset( new Client() ); } }; + diff --git a/db/cloner.cpp b/db/cloner.cpp index c7f4fb3df16..7d61f5c219b 100644 --- a/db/cloner.cpp +++ b/db/cloner.cpp @@ -665,7 +665,7 @@ namespace mongo { theDataFileMgr.insert( targetIndexes.c_str(), n ); } - setClientTempNs( source.c_str() ); + setClient( source.c_str() ); dropCollection( source, errmsg, result ); return true; } diff --git a/db/db.cpp b/db/db.cpp index 9e92a618616..067bc80efd9 100644 --- a/db/db.cpp +++ b/db/db.cpp @@ -72,6 +72,11 @@ namespace mongo { void pairWith(const char *remoteEnd, const char *arb); void setRecCacheSize(unsigned MB); + const char *ourgetns() { + Client *c = currentClient.get(); + return c ? c->ns() : ""; + } + struct MyStartupTests { MyStartupTests() { assert( sizeof(OID) == 12 ); @@ -319,7 +324,7 @@ namespace mongo { getDatabaseNames( dbNames ); for ( vector< string >::iterator i = dbNames.begin(); i != dbNames.end(); ++i ) { string dbName = *i; - assert( !setClientTempNs( dbName.c_str() ) ); + assert( !setClient( dbName.c_str() ) ); MongoDataFile *p = database->getFile( 0 ); MDFHeader *h = p->getHeader(); if ( !h->currentVersion() || forceRepair ) { @@ -507,6 +512,8 @@ string arg_error_check(int argc, char* argv[]) { int main(int argc, char* argv[], char *envp[] ) { + getcurns = ourgetns; + po::options_description general_options("General options"); po::options_description replication_options("Replication options"); po::options_description visible_options("Allowed options"); diff --git a/db/db.h b/db/db.h index f29b581a4c0..28284a25b51 100644 --- a/db/db.h +++ b/db/db.h @@ -22,6 +22,7 @@ #include "boost/version.hpp" #include "concurrency.h" #include "pdfile.h" +#include "client.h" namespace mongo { @@ -43,28 +44,32 @@ namespace mongo { // tempish...move to TLS or pass all the way down as a parm extern map databases; extern Database *database; - extern const char *curNs; extern bool master; - inline string getKey( const char *ns, const string& path ) { + /* sometimes we deal with databases with the same name in different directories - thus this */ + inline string makeDbKeyStr( const char *ns, const string& path ) { char cl[256]; nsToClient(ns, cl); return string( cl ) + ":" + path; } - /* returns true if the database ("database") did not exist, and it was created on this call */ + /* returns true if the database ("database") did not exist, and it was created on this call + path - datafiles directory, if not the default, so we can differentiate between db's of the same + name in different places (for example temp ones on repair). + */ inline bool setClient(const char *ns, const string& path=dbpath) { /* we must be in critical section at this point as these are global variables. */ requireInWriteLock(); - log( 5 ) << "setClient: " << ns << endl; + if( logLevel > 5 ) + log() << "setClient: " << ns << endl; Top::clientStart( ns ); - curNs = ns; - string key = getKey( ns, path ); + cc().setns(ns); + string key = makeDbKeyStr( ns, path ); map::iterator it = databases.find(key); if ( it != databases.end() ) { database = it->second; @@ -97,20 +102,10 @@ namespace mongo { /* remove database from the databases map */ inline void eraseDatabase( const char *ns, const string& path=dbpath ) { - string key = getKey( ns, path ); + string key = makeDbKeyStr( ns, path ); databases.erase( key ); } - /* We normally keep around a curNs ptr -- if this ns is temporary, - use this instead so we don't have a bad ptr. we could have made a copy, - but trying to be fast as we call setClient this for every single operation. - */ - inline bool setClientTempNs(const char *ns) { - bool jc = setClient(ns); - curNs = ""; - return jc; - } - inline bool clientIsEmpty() { return !database->namespaceIndex.allocated(); } diff --git a/db/dbcommands.cpp b/db/dbcommands.cpp index 5f3ed585a1d..5f87f6d9def 100644 --- a/db/dbcommands.cpp +++ b/db/dbcommands.cpp @@ -866,7 +866,7 @@ namespace mongo { b.append( "name", i->c_str() ); boost::intmax_t size = dbSize( i->c_str() ); b.append( "sizeOnDisk", (double) size ); - setClientTempNs( i->c_str() ); + setClient( i->c_str() ); b.appendBool( "empty", clientIsEmpty() ); totalSize += size; dbInfos.push_back( b.obj() ); @@ -883,7 +883,7 @@ namespace mongo { BSONObjBuilder b; b << "name" << name << "sizeOnDisk" << double( 1 ); - setClientTempNs( name.c_str() ); + setClient( name.c_str() ); b.appendBool( "empty", clientIsEmpty() ); dbInfos.push_back( b.obj() ); @@ -908,7 +908,7 @@ namespace mongo { dbs.insert( name ); } for( set< string >::iterator i = dbs.begin(); i != dbs.end(); ++i ) { - setClientTempNs( i->c_str() ); + setClient( i->c_str() ); closeClient( i->c_str() ); } @@ -1149,7 +1149,7 @@ namespace mongo { string fromNs = string( realDbName ) + "." + from; string toNs = string( realDbName ) + "." + to; - massert( "source collection " + fromNs + " does not exist", !setClientTempNs( fromNs.c_str() ) ); + massert( "source collection " + fromNs + " does not exist", !setClient( fromNs.c_str() ) ); NamespaceDetails *nsd = nsdetails( fromNs.c_str() ); massert( "source collection " + fromNs + " does not exist", nsd ); long long excessSize = nsd->datasize - size * 2; @@ -1173,7 +1173,7 @@ namespace mongo { } DBDirectClient client; - setClientTempNs( toNs.c_str() ); + setClient( toNs.c_str() ); BSONObjBuilder spec; spec.appendBool( "capped", true ); spec.append( "size", double( size ) ); diff --git a/db/dbhelpers.h b/db/dbhelpers.h index c6060ddc8df..8904c23667a 100644 --- a/db/dbhelpers.h +++ b/db/dbhelpers.h @@ -77,11 +77,11 @@ namespace mongo { public: DBContext(const char *ns) { old = database; - setClientTempNs(ns); + setClient(ns); } DBContext(string ns) { old = database; - setClientTempNs(ns.c_str()); + setClient(ns.c_str()); } ~DBContext() { database = old; diff --git a/db/dbinfo.h b/db/dbinfo.h index 4c70a78f507..71dee48fca1 100644 --- a/db/dbinfo.h +++ b/db/dbinfo.h @@ -35,7 +35,7 @@ namespace mongo { DBInfo(const char *db) { dbold = database; ns = string("local.dbinfo.") + db; - setClientTempNs(ns.c_str()); + setClient(ns.c_str()); } BSONObj getDbInfoObj() { diff --git a/db/instance.h b/db/instance.h index 75c926cd54f..b1089fed579 100644 --- a/db/instance.h +++ b/db/instance.h @@ -144,7 +144,7 @@ namespace mongo { c->ai = oldAuth; if ( !oldName.empty() ) { dblock lk; - setClientTempNs( oldName.c_str() ); + setClient( oldName.c_str() ); } } private: diff --git a/db/matcher.cpp b/db/matcher.cpp index 4bbd83adb9d..ed4a79b5b08 100644 --- a/db/matcher.cpp +++ b/db/matcher.cpp @@ -23,8 +23,9 @@ #include "../util/goodies.h" #include "../util/unittest.h" #include "storage.h" - #include "../scripting/engine.h" +#include "db.h" +#include "client.h" namespace mongo { @@ -107,8 +108,7 @@ namespace mongo { where = new Where(); uassert( "$where query, but no script engine", globalScriptEngine ); - assert( curNs ); - where->scope = globalScriptEngine->getPooledScope( curNs ); + where->scope = globalScriptEngine->getPooledScope( cc().ns() ); where->scope->localConnect( database->name.c_str() ); if ( e.type() == CodeWScope ) { diff --git a/db/namespace.cpp b/db/namespace.cpp index c3fe9485402..edcc6827f02 100644 --- a/db/namespace.cpp +++ b/db/namespace.cpp @@ -576,7 +576,7 @@ namespace mongo { stringstream spec; // 128MB spec << "{size:" << logSizeMb * 1024 * 1024 << ",capped:true,autoIndexId:false}"; - setClientTempNs( logNS_.c_str() ); + setClient( logNS_.c_str() ); string err; massert( "Could not create log ns", userCreateNS( logNS_.c_str(), fromjson( spec.str() ), err, false ) ); NamespaceDetails *d = nsdetails( logNS_.c_str() ); @@ -599,7 +599,7 @@ namespace mongo { void NamespaceDetailsTransient::dropLog() { if ( !logValid_ ) return; - setClientTempNs( logNS_.c_str() ); + setClient( logNS_.c_str() ); dropNS( logNS_ ); } diff --git a/db/namespace.h b/db/namespace.h index 3fba1e964fe..9b3a822ba3f 100644 --- a/db/namespace.h +++ b/db/namespace.h @@ -46,7 +46,7 @@ namespace mongo { } *q = 0; if (q-database>=MaxClientLen) { - problem() << "nsToClient: ns too long. terminating, buf overrun condition" << endl; + log() << "nsToClient: ns too long. terminating, buf overrun condition" << endl; dbexit( EXIT_POSSIBLE_CORRUPTION ); } } @@ -89,7 +89,7 @@ namespace mongo { } Namespace& operator=(const char *ns) { uassert("ns name too long, max size is 128", strlen(ns) < MaxNsLen); - memset(buf, 0, MaxNsLen); /* this is just to keep stuff clean in the files for easy dumping and reading */ + //memset(buf, 0, MaxNsLen); /* this is just to keep stuff clean in the files for easy dumping and reading */ strcpy_s(buf, MaxNsLen, ns); return *this; } @@ -114,7 +114,6 @@ namespace mongo { return (x & 0x7fffffff) | 0x8000000; // must be > 0 } - /** ( foo.bar ).getSisterNS( "blah" ) == foo.blah perhaps this should move to the NamespaceString helper? diff --git a/db/pdfile.cpp b/db/pdfile.cpp index 6c05c4770dd..8afa94aa68b 100644 --- a/db/pdfile.cpp +++ b/db/pdfile.cpp @@ -49,7 +49,6 @@ namespace mongo { DataFileMgr theDataFileMgr; map databases; Database *database; - const char *curNs = ""; int MAGIC = 0x1000; int curOp = -2; int callDepth = 0; @@ -67,8 +66,7 @@ namespace mongo { stringstream ss; if ( database ) { ss << database->name << ' '; - if ( curNs ) - ss << curNs << ' '; + ss << cc().ns() << ' '; } ss<< "op:" << curOp << ' ' << callDepth; return ss.str(); @@ -1732,7 +1730,7 @@ namespace mongo { return false; } - assert( !setClientTempNs( dbName ) ); + assert( !setClient( dbName ) ); closeClient( dbName ); if ( backupOriginalFiles ) diff --git a/db/repl.cpp b/db/repl.cpp index 8cada9d770e..94d06979722 100644 --- a/db/repl.cpp +++ b/db/repl.cpp @@ -734,7 +734,7 @@ namespace mongo { string ReplSource::resyncDrop( const char *db, const char *requester ) { log() << "resync: dropping database " << db << endl; string dummyns = string( db ) + "."; - setClientTempNs(dummyns.c_str()); + setClient(dummyns.c_str()); assert( database->name == db ); dropDatabase(dummyns.c_str()); return dummyns; @@ -743,7 +743,7 @@ namespace mongo { /* grab initial copy of a database from the master */ bool ReplSource::resync(string db) { string dummyNs = resyncDrop( db.c_str(), "internal" ); - setClientTempNs( dummyNs.c_str() ); + setClient( dummyNs.c_str() ); { log() << "resync: cloning database " << db << endl; ReplInfo r("resync: cloning a database"); @@ -865,7 +865,7 @@ namespace mongo { bool justCreated; try { - justCreated = setClientTempNs(ns); + justCreated = setClient(ns); } catch ( AssertionException& ) { problem() << "skipping bad(?) op in oplog, setClient() failed, ns: '" << ns << "'\n"; addDbNextPass.erase(clientName); @@ -900,7 +900,7 @@ namespace mongo { log() << "An earlier initial clone of '" << clientName << "' did not complete, now resyncing." << endl; } save(); - setClientTempNs( ns ); + setClient( ns ); nClonedThisPass++; resync(database->name); addDbNextPass.erase(clientName); @@ -1210,6 +1210,11 @@ namespace mongo { { time_t saveLast = time(0); while ( 1 ) { + /* TODO: WHY is c->more() called twice here? Once in this block it's clearly false? + Also: isn't it bad to call more() without a temprelease? seems like we need + another helper haveMoreWithoutRequesting(), and then if that is false, we temp + release and try more(). + */ if ( !c->more() ) { dblock lk; OpTime nextLastSaved = nextLastSavedLocalTs(); @@ -1229,14 +1234,14 @@ namespace mongo { break; } - OCCASIONALLY if( n > 100000 || time(0) - saveLast > 60 ) { + OCCASIONALLY if( n > 100000 || time(0) - saveLast > 60 ) { // periodically note our progress, in case we are doing a lot of work and crash dblock lk; syncedTo = nextOpTime; // can't update local log ts since there are pending operations from our peer save(); - log() << "repl: applied " << n << " operations" << endl; - log() << "repl: end sync_pullOpLog syncedTo: " << syncedTo.toStringLong() << endl; + log() << "repl: checkpoint applied " << n << " operations" << endl; + log() << "repl: syncedTo: " << syncedTo.toStringLong() << endl; saveLast = time(0); n = 0; } @@ -1426,7 +1431,7 @@ namespace mongo { Record *r; if ( strncmp( logNS, "local.", 6 ) == 0 ) { // For now, assume this is olog main if ( localOplogMainDetails == 0 ) { - setClientTempNs("local."); + setClient("local."); localOplogClient = database; localOplogMainDetails = nsdetails(logNS); } @@ -1621,7 +1626,7 @@ namespace mongo { dblock lk; const char * ns = "local.oplog.$main"; - setClientTempNs(ns); + setClient(ns); if ( nsdetails( ns ) ) return; diff --git a/db/security.cpp b/db/security.cpp index d8e35aa1b23..6730be9afc4 100644 --- a/db/security.cpp +++ b/db/security.cpp @@ -24,6 +24,15 @@ namespace mongo { boost::thread_specific_ptr currentClient; + Client::Client() : _ns(""), _nsstr("") { + ai = new AuthenticationInfo(); + } + + Client::~Client() { +cout << "TEMP" << endl; + delete ai; + } + bool noauth = true; int AuthenticationInfo::warned; diff --git a/dbtests/dbtests.cpp b/dbtests/dbtests.cpp index 3069ad21b31..38211636938 100644 --- a/dbtests/dbtests.cpp +++ b/dbtests/dbtests.cpp @@ -24,3 +24,4 @@ int main( int argc, char** argv ) { return Suite::run(argc, argv, "/tmp/unittest"); } + diff --git a/s/server.cpp b/s/server.cpp index 0d54724de30..28319524971 100644 --- a/s/server.cpp +++ b/s/server.cpp @@ -30,7 +30,6 @@ namespace mongo { int port = 27017; - const char *curNs = ""; Database *database = 0; string ourHostname; OID serverID; diff --git a/util/log.h b/util/log.h index ffc2ff3ac88..a74aa60834d 100644 --- a/util/log.h +++ b/util/log.h @@ -20,8 +20,6 @@ namespace mongo { - extern const char *curNs; - // Utility interface for stringifying object only when val() called. class LazyString { public: @@ -165,13 +163,11 @@ namespace mongo { return *this; } - Logstream& prolog(bool withNs = false) { + Logstream& prolog() { char now[64]; time_t_to_String(time(0), now); now[20] = 0; ss << now; - if ( withNs && /*database && */curNs ) - ss << curNs << ' '; return *this; } @@ -188,12 +184,6 @@ namespace mongo { extern int logLevel; - inline Nullstream& problem( int level = 0 ) { - if ( level > logLevel ) - return nullstream; - return Logstream::get().prolog(true); - } - inline Nullstream& out( int level = 0 ) { if ( level > logLevel ) return nullstream; @@ -225,4 +215,15 @@ namespace mongo { return cout; } + /* default impl returns "" -- mongod overrides */ + extern const char * (*getcurns)(); + + inline Nullstream& problem( int level = 0 ) { + if ( level > logLevel ) + return nullstream; + Logstream& l = Logstream::get().prolog(); + l << ' ' << getcurns() << ' '; + return l; + } + } // namespace mongo diff --git a/util/util.cpp b/util/util.cpp index 25fcee870fe..ad57905d044 100644 --- a/util/util.cpp +++ b/util/util.cpp @@ -32,6 +32,9 @@ namespace mongo { thread_specific_ptr Logstream::tsp; + const char *default_getcurns() { return ""; } + const char * (*getcurns)() = default_getcurns; + int logLevel = 0; boost::mutex &Logstream::mutex = *( new boost::mutex ); @@ -142,5 +145,5 @@ namespace mongo { ss << "db version v" << versionString << ", pdfile version " << VERSION << "." << VERSION_MINOR; return ss.str(); } - + } // namespace mongo