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:
parent
23326c222d
commit
fcf2d5721c
113
db/db.h
113
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"
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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';
|
||||
|
@ -444,7 +444,7 @@ namespace mongo {
|
||||
|
||||
NamespaceDetailsTransient::clearForPrefix( prefix.c_str() );
|
||||
|
||||
eraseDatabase( cl, path );
|
||||
dbHolder.erase( cl, path );
|
||||
delete database; // closes files
|
||||
cc().clearns();
|
||||
}
|
||||
|
@ -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
14
jstests/dbadmin.js
Normal 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 );
|
Loading…
Reference in New Issue
Block a user