diff options
Diffstat (limited to 'src/mongo/db/catalog/database_holder.cpp')
-rw-r--r-- | src/mongo/db/catalog/database_holder.cpp | 228 |
1 files changed, 109 insertions, 119 deletions
diff --git a/src/mongo/db/catalog/database_holder.cpp b/src/mongo/db/catalog/database_holder.cpp index bf1238db95f..f4a2cf62970 100644 --- a/src/mongo/db/catalog/database_holder.cpp +++ b/src/mongo/db/catalog/database_holder.cpp @@ -46,169 +46,159 @@ namespace mongo { - using std::set; - using std::string; - using std::stringstream; +using std::set; +using std::string; +using std::stringstream; namespace { - StringData _todb(StringData ns) { - size_t i = ns.find('.'); - if (i == std::string::npos) { - uassert(13074, "db name can't be empty", ns.size()); - return ns; - } +StringData _todb(StringData ns) { + size_t i = ns.find('.'); + if (i == std::string::npos) { + uassert(13074, "db name can't be empty", ns.size()); + return ns; + } - uassert(13075, "db name can't be empty", i > 0); + uassert(13075, "db name can't be empty", i > 0); - const StringData d = ns.substr(0, i); - uassert(13280, "invalid db name: " + ns.toString(), NamespaceString::validDBName(d)); + const StringData d = ns.substr(0, i); + uassert(13280, "invalid db name: " + ns.toString(), NamespaceString::validDBName(d)); - return d; - } + return d; +} - DatabaseHolder _dbHolder; +DatabaseHolder _dbHolder; -} // namespace +} // namespace - DatabaseHolder& dbHolder() { - return _dbHolder; - } +DatabaseHolder& dbHolder() { + return _dbHolder; +} + +Database* DatabaseHolder::get(OperationContext* txn, StringData ns) const { + const StringData db = _todb(ns); + invariant(txn->lockState()->isDbLockedForMode(db, MODE_IS)); - Database* DatabaseHolder::get(OperationContext* txn, - StringData ns) const { + stdx::lock_guard<SimpleMutex> lk(_m); + DBs::const_iterator it = _dbs.find(db); + if (it != _dbs.end()) { + return it->second; + } - const StringData db = _todb(ns); - invariant(txn->lockState()->isDbLockedForMode(db, MODE_IS)); + return NULL; +} - stdx::lock_guard<SimpleMutex> lk(_m); - DBs::const_iterator it = _dbs.find(db); - if (it != _dbs.end()) { - return it->second; +Database* DatabaseHolder::openDb(OperationContext* txn, StringData ns, bool* justCreated) { + const StringData dbname = _todb(ns); + invariant(txn->lockState()->isDbLockedForMode(dbname, MODE_X)); + + Database* db = get(txn, ns); + if (db) { + if (justCreated) { + *justCreated = false; } - return NULL; + return db; } - Database* DatabaseHolder::openDb(OperationContext* txn, - StringData ns, - bool* justCreated) { + // Check casing + const string duplicate = Database::duplicateUncasedName(dbname.toString()); + if (!duplicate.empty()) { + stringstream ss; + ss << "db already exists with different case already have: [" << duplicate + << "] trying to create [" << dbname.toString() << "]"; + uasserted(ErrorCodes::DatabaseDifferCase, ss.str()); + } - const StringData dbname = _todb(ns); - invariant(txn->lockState()->isDbLockedForMode(dbname, MODE_X)); + StorageEngine* storageEngine = getGlobalServiceContext()->getGlobalStorageEngine(); + invariant(storageEngine); - Database* db = get(txn, ns); - if (db) { - if (justCreated) { - *justCreated = false; - } + DatabaseCatalogEntry* entry = storageEngine->getDatabaseCatalogEntry(txn, dbname); + invariant(entry); + const bool exists = entry->exists(); + if (!exists) { + audit::logCreateDatabase(&cc(), dbname); + } - return db; - } + if (justCreated) { + *justCreated = !exists; + } - // Check casing - const string duplicate = Database::duplicateUncasedName(dbname.toString()); - if (!duplicate.empty()) { - stringstream ss; - ss << "db already exists with different case already have: [" - << duplicate - << "] trying to create [" - << dbname.toString() - << "]"; - uasserted(ErrorCodes::DatabaseDifferCase, ss.str()); - } + // Do this outside of the scoped lock, because database creation does transactional + // operations which may block. Only one thread can be inside this method for the same DB + // name, because of the requirement for X-lock on the database when we enter. So there is + // no way we can insert two different databases for the same name. + db = new Database(txn, dbname, entry); - StorageEngine* storageEngine = getGlobalServiceContext()->getGlobalStorageEngine(); - invariant(storageEngine); + stdx::lock_guard<SimpleMutex> lk(_m); + _dbs[dbname] = db; - DatabaseCatalogEntry* entry = storageEngine->getDatabaseCatalogEntry(txn, dbname); - invariant(entry); - const bool exists = entry->exists(); - if (!exists) { - audit::logCreateDatabase(&cc(), dbname); - } + return db; +} - if (justCreated) { - *justCreated = !exists; - } +void DatabaseHolder::close(OperationContext* txn, StringData ns) { + // TODO: This should be fine if only a DB X-lock + invariant(txn->lockState()->isW()); - // Do this outside of the scoped lock, because database creation does transactional - // operations which may block. Only one thread can be inside this method for the same DB - // name, because of the requirement for X-lock on the database when we enter. So there is - // no way we can insert two different databases for the same name. - db = new Database(txn, dbname, entry); + const StringData dbName = _todb(ns); - stdx::lock_guard<SimpleMutex> lk(_m); - _dbs[dbname] = db; + stdx::lock_guard<SimpleMutex> lk(_m); - return db; + DBs::const_iterator it = _dbs.find(dbName); + if (it == _dbs.end()) { + return; } - void DatabaseHolder::close(OperationContext* txn, - StringData ns) { - // TODO: This should be fine if only a DB X-lock - invariant(txn->lockState()->isW()); + it->second->close(txn); + delete it->second; + _dbs.erase(it); - const StringData dbName = _todb(ns); - - stdx::lock_guard<SimpleMutex> lk(_m); + getGlobalServiceContext()->getGlobalStorageEngine()->closeDatabase(txn, dbName.toString()); +} - DBs::const_iterator it = _dbs.find(dbName); - if (it == _dbs.end()) { - return; - } +bool DatabaseHolder::closeAll(OperationContext* txn, BSONObjBuilder& result, bool force) { + invariant(txn->lockState()->isW()); - it->second->close( txn ); - delete it->second; - _dbs.erase(it); + stdx::lock_guard<SimpleMutex> lk(_m); - getGlobalServiceContext()->getGlobalStorageEngine()->closeDatabase(txn, dbName.toString()); + set<string> dbs; + for (DBs::const_iterator i = _dbs.begin(); i != _dbs.end(); ++i) { + dbs.insert(i->first); } - bool DatabaseHolder::closeAll(OperationContext* txn, BSONObjBuilder& result, bool force) { - invariant(txn->lockState()->isW()); + BSONArrayBuilder bb(result.subarrayStart("dbs")); + int nNotClosed = 0; + for (set<string>::iterator i = dbs.begin(); i != dbs.end(); ++i) { + string name = *i; - stdx::lock_guard<SimpleMutex> lk(_m); + LOG(2) << "DatabaseHolder::closeAll name:" << name; - set< string > dbs; - for ( DBs::const_iterator i = _dbs.begin(); i != _dbs.end(); ++i ) { - dbs.insert( i->first ); + if (!force && BackgroundOperation::inProgForDb(name)) { + log() << "WARNING: can't close database " << name + << " because a bg job is in progress - try killOp command"; + nNotClosed++; + continue; } - BSONArrayBuilder bb( result.subarrayStart( "dbs" ) ); - int nNotClosed = 0; - for( set< string >::iterator i = dbs.begin(); i != dbs.end(); ++i ) { - string name = *i; - - LOG(2) << "DatabaseHolder::closeAll name:" << name; + Database* db = _dbs[name]; + db->close(txn); + delete db; - if( !force && BackgroundOperation::inProgForDb(name) ) { - log() << "WARNING: can't close database " - << name - << " because a bg job is in progress - try killOp command"; - nNotClosed++; - continue; - } + _dbs.erase(name); - Database* db = _dbs[name]; - db->close( txn ); - delete db; + getGlobalServiceContext()->getGlobalStorageEngine()->closeDatabase(txn, name); - _dbs.erase( name ); - - getGlobalServiceContext()->getGlobalStorageEngine()->closeDatabase( txn, name ); - - bb.append( name ); - } - - bb.done(); - if( nNotClosed ) { - result.append("nNotClosed", nNotClosed); - } + bb.append(name); + } - return true; + bb.done(); + if (nNotClosed) { + result.append("nNotClosed", nNotClosed); } + + return true; +} } |