0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-30 09:06:21 +01:00

some cleaning/optmizing of Database* storage, also just a little encaspulation

This commit is contained in:
Eliot Horowitz 2010-01-02 01:25:53 -05:00
parent 23326c222d
commit fcf2d5721c
6 changed files with 128 additions and 56 deletions

113
db/db.h
View File

@ -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"

View File

@ -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;

View File

@ -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';

View File

@ -444,7 +444,7 @@ namespace mongo {
NamespaceDetailsTransient::clearForPrefix( prefix.c_str() );
eraseDatabase( cl, path );
dbHolder.erase( cl, path );
delete database; // closes files
cc().clearns();
}

View File

@ -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

14
jstests/dbadmin.js Normal file
View File

@ -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 );