summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEliot Horowitz <eliot@10gen.com>2010-01-02 01:25:53 -0500
committerEliot Horowitz <eliot@10gen.com>2010-01-02 01:25:53 -0500
commitfcf2d5721c4e233009e12b0db325b164327db377 (patch)
treed795a7ae80bf35e450bc93e7e8e810a965c91eca
parent23326c222d8a88c6d4b372a348241528a8726b5c (diff)
downloadmongo-fcf2d5721c4e233009e12b0db325b164327db377.tar.gz
some cleaning/optmizing of Database* storage, also just a little encaspulation
-rw-r--r--db/db.h113
-rw-r--r--db/dbcommands.cpp22
-rw-r--r--db/dbwebserver.cpp4
-rw-r--r--db/instance.cpp2
-rw-r--r--db/pdfile.cpp29
-rw-r--r--jstests/dbadmin.js14
6 files changed, 128 insertions, 56 deletions
diff --git a/db/db.h b/db/db.h
index 4369a3dca30..87e157ab1ed 100644
--- a/db/db.h
+++ b/db/db.h
@@ -40,24 +40,80 @@ namespace mongo {
could be slightly larger.
*/
const int MaxBSONObjectSize = 4 * 1024 * 1024;
+
+ /**
+ * class to hold path + dbname -> Database
+ * might be able to optimizer further
+ */
+ class DatabaseHolder {
+ public:
+ DatabaseHolder() : _size(0){
+ }
- // tempish...move to TLS or pass all the way down as a parm
- extern map<string,Database*> databases;
- extern bool master;
+ Database * get( const string& ns , const string& path ){
+ dbMutex.assertAtLeastReadLocked();
+ map<string,Database*>& m = _paths[path];
+
+ string db = _todb( ns );
- /* 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];
- nsToDatabase(ns, cl);
- return string( cl ) + ":" + path;
- }
+ map<string,Database*>::iterator it = m.find(db);
+ if ( it != m.end() )
+ return it->second;
+ return 0;
+ }
+
+ void put( const string& ns , const string& path , Database * db ){
+ dbMutex.assertWriteLocked();
+ map<string,Database*>& m = _paths[path];
+ Database*& d = m[_todb(ns)];
+ if ( ! d )
+ _size++;
+ d = db;
+ }
+
+ void erase( const string& ns , const string& path ){
+ dbMutex.assertWriteLocked();
+ map<string,Database*>& m = _paths[path];
+ _size -= m.erase( _todb( ns ) );
+ }
+
+ bool closeAll( const string& path , BSONObjBuilder& result );
+
+ int size(){
+ return _size;
+ }
+
+ void getAllShortNames( set<string>& all ) const{
+ dbMutex.assertAtLeastReadLocked();
+ for ( map<string, map<string,Database*> >::const_iterator i=_paths.begin(); i!=_paths.end(); i++ ){
+ map<string,Database*> m = i->second;
+ for( map<string,Database*>::const_iterator j=m.begin(); j!=m.end(); j++ ){
+ all.insert( j->first );
+ }
+ }
+ }
+
+ private:
+
+ string _todb( const string& ns ){
+ size_t i = ns.find( '.' );
+ if ( i == string::npos )
+ return ns;
+ return ns.substr( 0 , i );
+ }
+
+ map<string, map<string,Database*> > _paths;
+ int _size;
+
+ };
+
+ extern DatabaseHolder dbHolder;
inline void resetClient(const char *ns, const string& path=dbpath) {
dbMutex.assertAtLeastReadLocked();
- string key = makeDbKeyStr( ns, path );
- map<string,Database*>::iterator it = databases.find(key);
- if ( it != databases.end() ) {
- cc().setns(ns, it->second);
+ Database * d = dbHolder.get( ns , path );
+ if ( d ){
+ cc().setns(ns, d);
return;
}
assert(false);
@@ -76,32 +132,22 @@ namespace mongo {
Client& c = cc();
c.top.clientStart( ns );
- string key = makeDbKeyStr( ns, path );
- map<string,Database*>::iterator it = databases.find(key);
- if ( it != databases.end() ) {
- c.setns(ns, it->second);
+ Database * db = dbHolder.get( ns , path );
+ if ( db ){
+ c.setns(ns, db );
return false;
}
if( lock )
lock->releaseAndWriteLock();
- // when master for replication, we advertise all the db's, and that
- // looks like a 'first operation'. so that breaks this log message's
- // meaningfulness. instead of fixing (which would be better), we just
- // stop showing for now.
- // 2008-12-22 We now open every database on startup, so this log is
- // no longer helpful. Commenting.
- // if( !master )
- // log() << "first operation for database " << key << endl;
-
assertInWriteLock();
-
+
char cl[256];
nsToDatabase(ns, cl);
bool justCreated;
Database *newdb = new Database(cl, justCreated, path);
- databases[key] = newdb;
+ dbHolder.put(ns,path,newdb);
c.setns(ns, newdb);
newdb->finishInit();
@@ -109,16 +155,10 @@ namespace mongo {
return justCreated;
}
-// shared functionality for removing references to a database from this program instance
-// does not delete the files on disk
+ // shared functionality for removing references to a database from this program instance
+ // does not delete the files on disk
void closeDatabase( const char *cl, const string& path = dbpath );
- /* remove database from the databases map */
- inline void eraseDatabase( const char *ns, const string& path=dbpath ) {
- string key = makeDbKeyStr( ns, path );
- databases.erase( key );
- }
-
inline bool clientIsEmpty() {
return !cc().database()->namespaceIndex.allocated();
}
@@ -183,6 +223,7 @@ namespace mongo {
extern TicketHolder connTicketHolder;
+
} // namespace mongo
//#include "dbinfo.h"
diff --git a/db/dbcommands.cpp b/db/dbcommands.cpp
index 278565ea151..3464ac7b010 100644
--- a/db/dbcommands.cpp
+++ b/db/dbcommands.cpp
@@ -720,10 +720,11 @@ namespace mongo {
seen.insert( i->c_str() );
}
-
- for ( map<string,Database*>::iterator i = databases.begin(); i != databases.end(); i++ ){
- string name = i->first;
- name = name.substr( 0 , name.find( ":" ) );
+
+ set<string> allShortNames;
+ dbHolder.getAllShortNames( allShortNames );
+ for ( set<string>::iterator i = allShortNames.begin(); i != allShortNames.end(); i++ ){
+ string name = *i;
if ( seen.count( name ) )
continue;
@@ -748,18 +749,7 @@ namespace mongo {
virtual bool slaveOk() { return false; }
CmdCloseAllDatabases() : Command( "closeAllDatabases" ) {}
bool run(const char *ns, BSONObj& jsobj, string& errmsg, BSONObjBuilder& result, bool /*fromRepl*/) {
- set< string > dbs;
- for ( map<string,Database*>::iterator i = databases.begin(); i != databases.end(); i++ ) {
- string name = i->first;
- name = name.substr( 0 , name.find( ":" ) );
- dbs.insert( name );
- }
- for( set< string >::iterator i = dbs.begin(); i != dbs.end(); ++i ) {
- setClient( i->c_str() );
- closeDatabase( i->c_str() );
- }
-
- return true;
+ return dbHolder.closeAll( dbpath , result );
}
} cmdCloseAllDatabases;
diff --git a/db/dbwebserver.cpp b/db/dbwebserver.cpp
index 837cb7caf89..1ba0a6c36e8 100644
--- a/db/dbwebserver.cpp
+++ b/db/dbwebserver.cpp
@@ -117,9 +117,9 @@ namespace mongo {
public:
// caller locks
void doLockedStuff(stringstream& ss) {
- ss << "# databases: " << databases.size() << '\n';
+ ss << "# databases: " << dbHolder.size() << '\n';
if ( cc().database() ) {
- ss << "curclient: " << cc().database()->name;
+ ss << "curclient: " << cc().database()->name; // TODO: isn't this useless?
ss << '\n';
}
ss << bold(ClientCursor::byLocSize()>10000) << "Cursors byLoc.size(): " << ClientCursor::byLocSize() << bold() << '\n';
diff --git a/db/instance.cpp b/db/instance.cpp
index f9b8619dba1..ec3191e24fa 100644
--- a/db/instance.cpp
+++ b/db/instance.cpp
@@ -444,7 +444,7 @@ namespace mongo {
NamespaceDetailsTransient::clearForPrefix( prefix.c_str() );
- eraseDatabase( cl, path );
+ dbHolder.erase( cl, path );
delete database; // closes files
cc().clearns();
}
diff --git a/db/pdfile.cpp b/db/pdfile.cpp
index 45e3b274571..0d6b000a204 100644
--- a/db/pdfile.cpp
+++ b/db/pdfile.cpp
@@ -46,7 +46,7 @@ namespace mongo {
string dbpath = "/data/db/";
DataFileMgr theDataFileMgr;
- map<string,Database*> databases;
+ DatabaseHolder dbHolder;
int MAGIC = 0x1000;
// int curOp = -2;
@@ -1812,4 +1812,31 @@ namespace mongo {
NamespaceDetails* nsdetails_notinline(const char *ns) { return nsdetails(ns); }
+ bool DatabaseHolder::closeAll( const string& path , BSONObjBuilder& result ){
+ log(2) << "DatabaseHolder::closeAll path:" << path << endl;
+ dbMutex.assertWriteLocked();
+
+ map<string,Database*>& m = _paths[path];
+ _size -= m.size();
+
+ set< string > dbs;
+ for ( map<string,Database*>::iterator i = m.begin(); i != m.end(); i++ ) {
+ dbs.insert( i->first );
+ }
+
+ BSONObjBuilder bb( result.subarrayStart( "dbs" ) );
+ int n = 0;
+ for( set< string >::iterator i = dbs.begin(); i != dbs.end(); ++i ) {
+ string name = *i;
+ log(2) << "DatabaseHolder::closeAll path:" << path << " name:" << name << endl;
+ setClient( name.c_str() , path );
+ closeDatabase( name.c_str() , path );
+ bb.append( bb.numStr( n++ ).c_str() , name );
+ }
+ bb.done();
+
+ return true;
+ }
+
+
} // namespace mongo
diff --git a/jstests/dbadmin.js b/jstests/dbadmin.js
new file mode 100644
index 00000000000..4bf0caed4f6
--- /dev/null
+++ b/jstests/dbadmin.js
@@ -0,0 +1,14 @@
+
+t = db.dbadmin;
+t.save( { x : 1 } );
+
+before = db._adminCommand( "serverStatus" );
+db._adminCommand( "closeAllDatabases" );
+after = db._adminCommand( "serverStatus" );
+assert( before.mem.mapped > after.mem.mapped , "closeAllDatabases does something" );
+
+t.save( { x : 1 } );
+
+res = db._adminCommand( "listDatabases" );
+assert( res.databases.length > 0 , "listDatabases 1" );
+printjson( res );