summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2015-01-02 18:09:29 -0500
committerKaloian Manassiev <kaloian.manassiev@mongodb.com>2015-01-05 13:59:47 -0500
commit12d82c741061da23a442086465322352f157d094 (patch)
treee71fd0a9e98c94be93b075a7611f51fe1a1f304b /src/mongo
parenta55a7b936ec2f4e935db4de4f4edb4696935a08d (diff)
downloadmongo-12d82c741061da23a442086465322352f157d094.tar.gz
SERVER-16591 Get rid of _collectionsLock in the database catalog
This lock is not needed anymore since any modifications to the set of collections are done with the database X lock held.
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/concurrency/locker_noop.h175
-rw-r--r--src/mongo/db/operation_context.h13
-rw-r--r--src/mongo/db/operation_context_noop.h17
-rw-r--r--src/mongo/db/storage/kv/kv_database_catalog_entry.cpp109
-rw-r--r--src/mongo/db/storage/kv/kv_database_catalog_entry.h9
-rw-r--r--src/mongo/db/storage/mmap_v1/mmap_v1_database_catalog_entry.cpp226
-rw-r--r--src/mongo/db/storage/mmap_v1/mmap_v1_database_catalog_entry.h114
7 files changed, 406 insertions, 257 deletions
diff --git a/src/mongo/db/concurrency/locker_noop.h b/src/mongo/db/concurrency/locker_noop.h
new file mode 100644
index 00000000000..44510c49f9d
--- /dev/null
+++ b/src/mongo/db/concurrency/locker_noop.h
@@ -0,0 +1,175 @@
+/**
+ * Copyright (C) 2014 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+#include "mongo/db/concurrency/locker.h"
+
+namespace mongo {
+
+ /**
+ * Locker, which cannot be used to lock/unlock resources and just returns true for checks for
+ * whether a particular resource is locked. Do not use it for cases where actual locking
+ * behaviour is expected or locking is performed.
+ */
+ class LockerNoop : public Locker {
+ public:
+ LockerNoop() { }
+
+ virtual LockerId getId() const { invariant(false); }
+
+ virtual LockResult lockGlobal(LockMode mode, unsigned timeoutMs) {
+ invariant(false);
+ }
+
+ virtual LockResult lockGlobalBegin(LockMode mode) {
+ invariant(false);
+ }
+
+ virtual LockResult lockGlobalComplete(unsigned timeoutMs) {
+ invariant(false);
+ }
+
+ virtual void lockMMAPV1Flush() {
+ invariant(false);
+ }
+
+ virtual bool unlockAll() {
+ invariant(false);
+ }
+
+ virtual void downgradeGlobalXtoSForMMAPV1() {
+ invariant(false);
+ }
+
+ virtual void beginWriteUnitOfWork() {
+
+ }
+
+ virtual void endWriteUnitOfWork() {
+
+ }
+
+ virtual bool inAWriteUnitOfWork() const {
+ invariant(false);
+ }
+
+ virtual LockResult lock(ResourceId resId,
+ LockMode mode,
+ unsigned timeoutMs,
+ bool checkDeadlock) {
+ invariant(false);
+ }
+
+ virtual void downgrade(ResourceId resId, LockMode newMode) {
+ invariant(false);
+ }
+
+ virtual bool unlock(ResourceId resId) {
+ invariant(false);
+ }
+
+ virtual LockMode getLockMode(ResourceId resId) const {
+ invariant(false);
+ }
+
+ virtual bool isLockHeldForMode(ResourceId resId, LockMode mode) const {
+ return true;
+ }
+
+ virtual bool isDbLockedForMode(const StringData& dbName, LockMode mode) const {
+ return true;
+ }
+
+ virtual bool isCollectionLockedForMode(const StringData& ns, LockMode mode) const {
+ return true;
+ }
+
+ virtual ResourceId getWaitingResource() const {
+ invariant(false);
+ }
+
+ virtual void getLockerInfo(LockerInfo* lockerInfo) const {
+ invariant(false);
+ }
+
+ virtual bool saveLockStateAndUnlock(LockSnapshot* stateOut) {
+ invariant(false);
+ }
+
+ virtual void restoreLockState(const LockSnapshot& stateToRestore) {
+ invariant(false);
+ }
+
+ virtual void dump() const {
+ invariant(false);
+ }
+
+ virtual bool isW() const {
+ invariant(false);
+ }
+
+ virtual bool isR() const {
+ invariant(false);
+ }
+
+ virtual bool isLocked() const {
+ invariant(false);
+ }
+
+ virtual bool isWriteLocked() const {
+ invariant(false);
+ }
+
+ virtual bool isReadLocked() const {
+ invariant(false);
+ }
+
+ virtual void assertEmpty() const {
+ invariant(false);
+ }
+
+ virtual bool hasLockPending() const {
+ invariant(false);
+ }
+
+ virtual void setIsBatchWriter(bool newValue) {
+ invariant(false);
+ }
+
+ virtual bool isBatchWriter() const {
+ invariant(false);
+ }
+
+ virtual void setLockPendingParallelWriter(bool newValue) {
+ invariant(false);
+ }
+
+ };
+
+} // namespace mongo
diff --git a/src/mongo/db/operation_context.h b/src/mongo/db/operation_context.h
index 59c190733f8..99bf8361ae6 100644
--- a/src/mongo/db/operation_context.h
+++ b/src/mongo/db/operation_context.h
@@ -148,17 +148,14 @@ namespace mongo {
: _txn(txn),
_ended(false) {
- if ( _txn->lockState() ) {
- _txn->lockState()->beginWriteUnitOfWork();
- }
-
+ _txn->lockState()->beginWriteUnitOfWork();
_txn->recoveryUnit()->beginUnitOfWork();
}
~WriteUnitOfWork() {
_txn->recoveryUnit()->endUnitOfWork();
- if (_txn->lockState() && !_ended) {
+ if (!_ended) {
_txn->lockState()->endWriteUnitOfWork();
}
}
@@ -167,11 +164,9 @@ namespace mongo {
invariant(!_ended);
_txn->recoveryUnit()->commitUnitOfWork();
+ _txn->lockState()->endWriteUnitOfWork();
- if (_txn->lockState()) {
- _txn->lockState()->endWriteUnitOfWork();
- _ended = true;
- }
+ _ended = true;
}
private:
diff --git a/src/mongo/db/operation_context_noop.h b/src/mongo/db/operation_context_noop.h
index 8d946850186..0ebdbceb386 100644
--- a/src/mongo/db/operation_context_noop.h
+++ b/src/mongo/db/operation_context_noop.h
@@ -29,6 +29,7 @@
#include "mongo/db/operation_context.h"
#include "mongo/db/client.h"
+#include "mongo/db/concurrency/locker_noop.h"
#include "mongo/db/curop.h"
#include "mongo/db/storage/recovery_unit_noop.h"
@@ -36,12 +37,16 @@ namespace mongo {
class OperationContextNoop : public OperationContext {
public:
- OperationContextNoop(RecoveryUnit* ru) {
- _recoveryUnit.reset(ru);
+ OperationContextNoop(RecoveryUnit* ru)
+ : _recoveryUnit(ru),
+ _locker(new LockerNoop()) {
+
}
- OperationContextNoop() {
- _recoveryUnit.reset(new RecoveryUnitNoop());
+ OperationContextNoop()
+ : _recoveryUnit(new RecoveryUnitNoop()),
+ _locker(new LockerNoop()) {
+
}
virtual ~OperationContextNoop() { }
@@ -69,8 +74,7 @@ namespace mongo {
}
virtual Locker* lockState() const {
- // TODO: This should return an actual object if necessary for testing.
- return NULL;
+ return _locker.get();
}
virtual ProgressMeter* setMessage(const char * msg,
@@ -103,6 +107,7 @@ namespace mongo {
private:
std::auto_ptr<RecoveryUnit> _recoveryUnit;
+ scoped_ptr<Locker> _locker;
ProgressMeter _pm;
};
diff --git a/src/mongo/db/storage/kv/kv_database_catalog_entry.cpp b/src/mongo/db/storage/kv/kv_database_catalog_entry.cpp
index 51fde7efb9c..abde589c5a3 100644
--- a/src/mongo/db/storage/kv/kv_database_catalog_entry.cpp
+++ b/src/mongo/db/storage/kv/kv_database_catalog_entry.cpp
@@ -56,7 +56,6 @@ namespace mongo {
_dce->_engine->getEngine()->dropIdent(_opCtx, _ident);
}
- boost::mutex::scoped_lock lk(_dce->_collectionsLock);
const CollectionMap::iterator it = _dce->_collections.find(_collection);
if (it != _dce->_collections.end()) {
delete it->second;
@@ -94,7 +93,6 @@ namespace mongo {
}
virtual void rollback() {
- boost::mutex::scoped_lock lk(_dce->_collectionsLock);
_dce->_collections[_collection] = _entry;
}
@@ -123,7 +121,6 @@ namespace mongo {
}
bool KVDatabaseCatalogEntry::isEmpty() const {
- boost::mutex::scoped_lock lk( _collectionsLock );
return _collections.empty();
}
@@ -134,7 +131,6 @@ namespace mongo {
int64_t KVDatabaseCatalogEntry::sizeOnDisk( OperationContext* opCtx ) const {
int64_t size = 0;
- boost::mutex::scoped_lock lk( _collectionsLock );
for ( CollectionMap::const_iterator it = _collections.begin(); it != _collections.end(); ++it ) {
const KVCollectionCatalogEntry* coll = it->second;
if ( !coll )
@@ -166,26 +162,31 @@ namespace mongo {
}
void KVDatabaseCatalogEntry::getCollectionNamespaces( std::list<std::string>* out ) const {
- boost::mutex::scoped_lock lk( _collectionsLock );
- for ( CollectionMap::const_iterator it = _collections.begin(); it != _collections.end(); ++it ) {
+ for (CollectionMap::const_iterator it = _collections.begin();
+ it != _collections.end();
+ ++it) {
+
out->push_back( it->first );
}
}
CollectionCatalogEntry* KVDatabaseCatalogEntry::getCollectionCatalogEntry(
const StringData& ns ) const {
- boost::mutex::scoped_lock lk( _collectionsLock );
+
CollectionMap::const_iterator it = _collections.find( ns.toString() );
- if ( it == _collections.end() )
+ if (it == _collections.end()) {
return NULL;
+ }
+
return it->second;
}
RecordStore* KVDatabaseCatalogEntry::getRecordStore( const StringData& ns ) const {
- boost::mutex::scoped_lock lk( _collectionsLock );
CollectionMap::const_iterator it = _collections.find( ns.toString() );
- if ( it == _collections.end() )
+ if (it == _collections.end()) {
return NULL;
+ }
+
return it->second->getRecordStore();
}
@@ -193,19 +194,16 @@ namespace mongo {
const StringData& ns,
const CollectionOptions& options,
bool allocateDefaultSpace ) {
+
+ invariant(txn->lockState()->isDbLockedForMode(name(), MODE_X));
+
if (ns.empty()) {
return Status(ErrorCodes::BadValue, "Collection namespace cannot be empty");
}
- // we assume there is a logical lock on the collection name above
-
- {
- boost::mutex::scoped_lock lk( _collectionsLock );
- if (_collections.count(ns.toString())) {
- invariant(_collections[ns.toString()]);
- return Status( ErrorCodes::NamespaceExists,
- "collection already exists" );
- }
+ if (_collections.count(ns.toString())) {
+ invariant(_collections[ns.toString()]);
+ return Status(ErrorCodes::NamespaceExists, "collection already exists");
}
// need to create it
@@ -221,7 +219,7 @@ namespace mongo {
RecordStore* rs = _engine->getEngine()->getRecordStore( txn, ns, ident, options );
invariant( rs );
- boost::mutex::scoped_lock lk( _collectionsLock );
+
txn->recoveryUnit()->registerChange(new AddCollectionChange(txn, this, ns, ident, true));
_collections[ns.toString()] =
new KVCollectionCatalogEntry( _engine->getEngine(), _engine->getCatalog(),
@@ -238,8 +236,8 @@ namespace mongo {
RecordStore* rs = _engine->getEngine()->getRecordStore( opCtx, ns, ident, md.options );
invariant( rs );
- boost::mutex::scoped_lock lk( _collectionsLock );
invariant(!_collections.count(ns));
+
// No change registration since this is only for committed collections
_collections[ns] = new KVCollectionCatalogEntry( _engine->getEngine(),
_engine->getCatalog(),
@@ -252,19 +250,21 @@ namespace mongo {
const StringData& fromNS,
const StringData& toNS,
bool stayTemp ) {
+
+ invariant(txn->lockState()->isDbLockedForMode(name(), MODE_X));
+
RecordStore* originalRS = NULL;
- // Note: assuming that both fromNS and toNS (or whole db) are X-locked from above.
- {
- boost::mutex::scoped_lock lk( _collectionsLock );
- CollectionMap::const_iterator it = _collections.find( fromNS.toString() );
- if ( it == _collections.end() )
- return Status( ErrorCodes::NamespaceNotFound, "rename cannot find collection" );
- originalRS = it->second->getRecordStore();
- it = _collections.find( toNS.toString() );
- if ( it != _collections.end() )
- return Status( ErrorCodes::NamespaceExists, "for rename to already exists" );
+ CollectionMap::const_iterator it = _collections.find( fromNS.toString() );
+ if (it == _collections.end()) {
+ return Status(ErrorCodes::NamespaceNotFound, "rename cannot find collection");
+ }
+
+ originalRS = it->second->getRecordStore();
+ it = _collections.find( toNS.toString() );
+ if (it != _collections.end()) {
+ return Status(ErrorCodes::NamespaceExists, "for rename to already exists");
}
const std::string identFrom = _engine->getCatalog()->getCollectionIdent( fromNS );
@@ -284,7 +284,6 @@ namespace mongo {
BSONCollectionCatalogEntry::MetaData md = _engine->getCatalog()->getMetaData( txn, toNS );
RecordStore* rs = _engine->getEngine()->getRecordStore( txn, toNS, identTo, md.options );
- boost::mutex::scoped_lock lk( _collectionsLock );
const CollectionMap::iterator itFrom = _collections.find(fromNS.toString());
invariant(itFrom != _collections.end());
txn->recoveryUnit()->registerChange(new RemoveCollectionChange(txn, this, fromNS, identFrom,
@@ -300,18 +299,18 @@ namespace mongo {
return Status::OK();
}
- Status KVDatabaseCatalogEntry::dropCollection( OperationContext* opCtx,
- const StringData& ns ) {
- KVCollectionCatalogEntry* entry;
- {
- boost::mutex::scoped_lock lk( _collectionsLock );
- CollectionMap::const_iterator it = _collections.find( ns.toString() );
- if ( it == _collections.end() )
- return Status( ErrorCodes::NamespaceNotFound, "cannnot find collection to drop" );
- entry = it->second;
+ Status KVDatabaseCatalogEntry::dropCollection(OperationContext* opCtx, const StringData& ns) {
+ invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_X));
+
+ CollectionMap::const_iterator it = _collections.find( ns.toString() );
+ if (it == _collections.end()) {
+ return Status(ErrorCodes::NamespaceNotFound, "cannnot find collection to drop");
}
- invariant( entry->getTotalIndexCount( opCtx ) == entry->getCompletedIndexCount( opCtx ) );
+ KVCollectionCatalogEntry* const entry = it->second;
+
+ invariant(entry->getTotalIndexCount(opCtx) == entry->getCompletedIndexCount(opCtx));
+
{
std::vector<std::string> indexNames;
entry->getAllIndexes( opCtx, &indexNames );
@@ -319,24 +318,24 @@ namespace mongo {
entry->removeIndex( opCtx, indexNames[i] );
}
}
- invariant( entry->getTotalIndexCount( opCtx ) == 0 );
- string ident = _engine->getCatalog()->getCollectionIdent( ns );
+ invariant( entry->getTotalIndexCount( opCtx ) == 0 );
- boost::mutex::scoped_lock lk( _collectionsLock );
+ const std::string ident = _engine->getCatalog()->getCollectionIdent(ns);
- Status status = _engine->getCatalog()->dropCollection( opCtx, ns );
- if ( !status.isOK() )
+ Status status = _engine->getCatalog()->dropCollection(opCtx, ns);
+ if (!status.isOK()) {
return status;
+ }
-
- const CollectionMap::iterator it = _collections.find(ns.toString());
- invariant(it != _collections.end());
-
- // This will lazily delete the KVCollectionCatalogEntry and notify the storageEngine to drop
- // the collection only on WUOW::commit().
- opCtx->recoveryUnit()->registerChange(new RemoveCollectionChange(opCtx, this, ns, ident,
- it->second, true));
+ // This will lazily delete the KVCollectionCatalogEntry and notify the storageEngine to
+ // drop the collection only on WUOW::commit().
+ opCtx->recoveryUnit()->registerChange(new RemoveCollectionChange(opCtx,
+ this,
+ ns,
+ ident,
+ it->second,
+ true));
_collections.erase( ns.toString() );
diff --git a/src/mongo/db/storage/kv/kv_database_catalog_entry.h b/src/mongo/db/storage/kv/kv_database_catalog_entry.h
index fb522120491..fc5fb39adbd 100644
--- a/src/mongo/db/storage/kv/kv_database_catalog_entry.h
+++ b/src/mongo/db/storage/kv/kv_database_catalog_entry.h
@@ -33,9 +33,6 @@
#include <map>
#include <string>
-#include <boost/scoped_ptr.hpp>
-#include <boost/thread/mutex.hpp>
-
#include "mongo/db/catalog/database_catalog_entry.h"
namespace mongo {
@@ -95,10 +92,10 @@ namespace mongo {
class AddCollectionChange;
class RemoveCollectionChange;
- KVStorageEngine* _engine; // not owned here
+ typedef std::map<std::string, KVCollectionCatalogEntry*> CollectionMap;
+
- typedef std::map<std::string,KVCollectionCatalogEntry*> CollectionMap;
+ KVStorageEngine* const _engine; // not owned here
CollectionMap _collections;
- mutable boost::mutex _collectionsLock;
};
}
diff --git a/src/mongo/db/storage/mmap_v1/mmap_v1_database_catalog_entry.cpp b/src/mongo/db/storage/mmap_v1/mmap_v1_database_catalog_entry.cpp
index 1df0cccb9fa..d9a9e5da8db 100644
--- a/src/mongo/db/storage/mmap_v1/mmap_v1_database_catalog_entry.cpp
+++ b/src/mongo/db/storage/mmap_v1/mmap_v1_database_catalog_entry.cpp
@@ -35,7 +35,6 @@
#include <utility>
#include "mongo/db/catalog/index_catalog_entry.h"
-#include "mongo/db/client.h"
#include "mongo/db/index/2d_access_method.h"
#include "mongo/db/index/btree_access_method.h"
#include "mongo/db/index/btree_based_access_method.h"
@@ -49,7 +48,6 @@
#include "mongo/db/storage/mmap_v1/catalog/namespace_details.h"
#include "mongo/db/storage/mmap_v1/catalog/namespace_details_collection_entry.h"
#include "mongo/db/storage/mmap_v1/catalog/namespace_details_rsv1_metadata.h"
-#include "mongo/db/storage/mmap_v1/dur.h"
#include "mongo/db/storage/mmap_v1/data_file.h"
#include "mongo/db/storage/mmap_v1/record_store_v1_capped.h"
#include "mongo/db/storage/mmap_v1/record_store_v1_simple.h"
@@ -57,39 +55,55 @@
#include "mongo/util/log.h"
namespace mongo {
+namespace {
- namespace {
- bool newCollectionsUsePowerOf2SizesFlag = true; // Unused, needed for server parameter.
-
- /**
- * Declaration for the "newCollectionsUsePowerOf2Sizes" server parameter,
- * which is now deprecated in 2.8.
- * Note that:
- * - setting to true performs a no-op.
- * - setting to false will fail.
- */
- class NewCollectionsUsePowerOf2SizesParameter : public ExportedServerParameter<bool> {
- public:
- NewCollectionsUsePowerOf2SizesParameter() :
- ExportedServerParameter<bool>(ServerParameterSet::getGlobal(),
- "newCollectionsUsePowerOf2Sizes",
- &newCollectionsUsePowerOf2SizesFlag,
- true,
- true) {}
-
- virtual Status validate(const bool& potentialNewValue) {
- if (!potentialNewValue) {
- return Status(ErrorCodes::BadValue,
- "newCollectionsUsePowerOf2Sizes cannot be set to false. "
- "Use noPadding instead during createCollection.");
- }
+ /**
+ * Declaration for the "newCollectionsUsePowerOf2Sizes" server parameter, which is now
+ * deprecated in 2.8.
+ * Note that:
+ * - setting to true performs a no-op.
+ * - setting to false will fail.
+ */
+ class NewCollectionsUsePowerOf2SizesParameter : public ExportedServerParameter<bool> {
+ public:
+ NewCollectionsUsePowerOf2SizesParameter() :
+ ExportedServerParameter<bool>(ServerParameterSet::getGlobal(),
+ "newCollectionsUsePowerOf2Sizes",
+ &newCollectionsUsePowerOf2SizesFlag,
+ true,
+ true) {
+
+ }
- return Status::OK();
+ virtual Status validate(const bool& potentialNewValue) {
+ if (!potentialNewValue) {
+ return Status(ErrorCodes::BadValue,
+ "newCollectionsUsePowerOf2Sizes cannot be set to false. "
+ "Use noPadding instead during createCollection.");
}
- } exportedNewCollectionsUsePowerOf2SizesParameter;
+ return Status::OK();
+ }
+
+ private:
+ // Unused, needed for server parameter.
+ bool newCollectionsUsePowerOf2SizesFlag;
+
+ } exportedNewCollectionsUsePowerOf2SizesParameter;
+
+
+ int _massageExtentSize(const ExtentManager* em, long long size) {
+ if (size < em->minSize())
+ return em->minSize();
+ if (size > em->maxSize())
+ return em->maxSize();
+
+ return static_cast<int>(size);
}
+} // namespace
+
+
/**
* Registers the insertion of a new entry in the _collections cache with the RecoveryUnit,
* allowing for rollback.
@@ -124,7 +138,6 @@ namespace mongo {
: _ns(ns.toString()), _catalogEntry(catalogEntry), _cachedEntry(cachedEntry) { }
void rollback() {
- boost::mutex::scoped_lock lk(_catalogEntry->_collectionsLock);
_catalogEntry->_collections[_ns] = _cachedEntry;
}
@@ -166,7 +179,7 @@ namespace mongo {
// _init. That is ok, since they can't have indexes on them anyway.
if (!entry) {
entry = new Entry();
- _insertInCache_inlock(txn, ns, entry);
+ _insertInCache(txn, ns, entry);
// Add the indexes on this namespace to the list of namespaces to load.
std::vector<std::string> indexNames;
@@ -190,7 +203,7 @@ namespace mongo {
catch(std::exception& e) {
log() << "warning database " << path << " " << name << " could not be opened";
DBException* dbe = dynamic_cast<DBException*>(&e);
- if ( dbe != 0 ) {
+ if (dbe) {
log() << "DBException " << dbe->getCode() << ": " << e.what() << endl;
}
else {
@@ -217,10 +230,10 @@ namespace mongo {
void MMAPV1DatabaseCatalogEntry::_removeFromCache(RecoveryUnit* ru,
const StringData& ns) {
- boost::mutex::scoped_lock lk(_collectionsLock);
CollectionMap::iterator i = _collections.find(ns.toString());
- if ( i == _collections.end() )
+ if (i == _collections.end()) {
return;
+ }
// If there is an operation context, register a rollback to restore the cache entry
if (ru) {
@@ -416,12 +429,11 @@ namespace mongo {
_getNamespaceRecordStore()->deleteRecord( txn, oldSpecLocation );
- boost::mutex::scoped_lock lk( _collectionsLock );
Entry*& entry = _collections[toNS.toString()];
invariant( entry == NULL );
txn->recoveryUnit()->registerChange(new EntryInsertion(toNS, this));
entry = new Entry();
- _insertInCache_inlock(txn, toNS, entry);
+ _insertInCache(txn, toNS, entry);
return Status::OK();
}
@@ -497,20 +509,11 @@ namespace mongo {
_namespaceIndex.getCollectionNamespaces( tofill );
}
- namespace {
- int _massageExtentSize( const ExtentManager* em, long long size ) {
- if ( size < em->minSize() )
- return em->minSize();
- if ( size > em->maxSize() )
- return em->maxSize();
- return static_cast<int>( size );
- }
- }
+ void MMAPV1DatabaseCatalogEntry::_ensureSystemCollection(OperationContext* txn,
+ const StringData& ns) {
- void MMAPV1DatabaseCatalogEntry::_ensureSystemCollection_inlock( OperationContext* txn,
- const StringData& ns ) {
- NamespaceDetails* details = _namespaceIndex.details( ns );
- if ( details ) {
+ NamespaceDetails* details = _namespaceIndex.details(ns);
+ if (details) {
return;
}
_namespaceIndex.add_ns( txn, ns, DiskLoc(), false );
@@ -543,8 +546,8 @@ namespace mongo {
bool isSystemNamespacesGoingToBeNew = _namespaceIndex.details( nsn.toString() ) == NULL;
bool isSystemIndexesGoingToBeNew = _namespaceIndex.details( nsi.toString() ) == NULL;
- _ensureSystemCollection_inlock( txn, nsn.toString() );
- _ensureSystemCollection_inlock( txn, nsi.toString() );
+ _ensureSystemCollection(txn, nsn.toString());
+ _ensureSystemCollection(txn, nsi.toString());
if ( isSystemNamespacesGoingToBeNew ) {
txn->recoveryUnit()->registerChange(new EntryInsertion(nsn.toString(), this));
@@ -597,7 +600,7 @@ namespace mongo {
}
if ( isSystemIndexesGoingToBeNew ) {
- _addNamespaceToNamespaceCollection_inlock( txn, nsi.toString(), NULL );
+ _addNamespaceToNamespaceCollection(txn, nsi.toString(), NULL);
}
if ( !nsEntry->catalogEntry )
@@ -647,14 +650,11 @@ namespace mongo {
options.cappedMaxDocs;
}
- {
- boost::mutex::scoped_lock lk( _collectionsLock );
- Entry*& entry = _collections[ns.toString()];
- invariant( !entry );
- txn->recoveryUnit()->registerChange(new EntryInsertion(ns, this));
- entry = new Entry();
- _insertInCache_inlock(txn, ns, entry);
- }
+ Entry*& entry = _collections[ns.toString()];
+ invariant( !entry );
+ txn->recoveryUnit()->registerChange(new EntryInsertion(ns, this));
+ entry = new Entry();
+ _insertInCache(txn, ns, entry);
if ( allocateDefaultSpace ) {
RecordStoreV1Base* rs = _getRecordStore( ns );
@@ -698,56 +698,59 @@ namespace mongo {
_addNamespaceToNamespaceCollection(txn, name, NULL);
_namespaceIndex.add_ns(txn, name, DiskLoc(), false);
- boost::mutex::scoped_lock lk( _collectionsLock );
Entry*& entry = _collections[name.toString()];
invariant( !entry );
txn->recoveryUnit()->registerChange(new EntryInsertion(name, this));
entry = new Entry();
- _insertInCache_inlock(txn, name, entry);
+ _insertInCache(txn, name, entry);
}
CollectionCatalogEntry* MMAPV1DatabaseCatalogEntry::getCollectionCatalogEntry(
const StringData& ns ) const {
- boost::mutex::scoped_lock lk( _collectionsLock );
+
CollectionMap::const_iterator i = _collections.find( ns.toString() );
- if ( i == _collections.end() )
+ if (i == _collections.end()) {
return NULL;
+ }
invariant( i->second->catalogEntry.get() );
return i->second->catalogEntry.get();
}
- void MMAPV1DatabaseCatalogEntry::_insertInCache_inlock(OperationContext* txn,
- const StringData& ns,
- Entry* entry) {
+ void MMAPV1DatabaseCatalogEntry::_insertInCache(OperationContext* txn,
+ const StringData& ns,
+ Entry* entry) {
+
NamespaceDetails* details = _namespaceIndex.details(ns);
invariant(details);
- entry->catalogEntry.reset( new NamespaceDetailsCollectionCatalogEntry( ns,
- details,
- _getIndexRecordStore_inlock(),
- this ) );
+ entry->catalogEntry.reset(
+ new NamespaceDetailsCollectionCatalogEntry(ns,
+ details,
+ _getIndexRecordStore(),
+ this));
- NamespaceString nss( ns );
+ auto_ptr<NamespaceDetailsRSV1MetaData> md(
+ new NamespaceDetailsRSV1MetaData(ns,
+ details,
+ _getNamespaceRecordStore()));
- auto_ptr<NamespaceDetailsRSV1MetaData> md( new NamespaceDetailsRSV1MetaData( ns,
- details,
- _getNamespaceRecordStore_inlock() ) );
+ const NamespaceString nss(ns);
- if ( details->isCapped ) {
- entry->recordStore.reset( new CappedRecordStoreV1( txn,
- NULL, //TOD(ERH) this will blow up :)
- ns,
- md.release(),
- &_extentManager,
- nss.coll() == "system.indexes" ) );
+ if (details->isCapped) {
+ entry->recordStore.reset(new CappedRecordStoreV1(txn,
+ NULL,
+ ns,
+ md.release(),
+ &_extentManager,
+ nss.coll() == "system.indexes"));
}
else {
- entry->recordStore.reset( new SimpleRecordStoreV1( txn,
- ns,
- md.release(),
- &_extentManager,
- nss.coll() == "system.indexes" ) );
+ entry->recordStore.reset(new SimpleRecordStoreV1(txn,
+ ns,
+ md.release(),
+ &_extentManager,
+ nss.coll() == "system.indexes"));
}
}
@@ -756,10 +759,10 @@ namespace mongo {
}
RecordStoreV1Base* MMAPV1DatabaseCatalogEntry::_getRecordStore( const StringData& ns ) const {
- boost::mutex::scoped_lock lk( _collectionsLock );
CollectionMap::const_iterator i = _collections.find( ns.toString() );
- if ( i == _collections.end() )
+ if (i == _collections.end()) {
return NULL;
+ }
invariant( i->second->recordStore.get() );
return i->second->recordStore.get();
@@ -814,58 +817,49 @@ namespace mongo {
}
RecordStoreV1Base* MMAPV1DatabaseCatalogEntry::_getIndexRecordStore() {
- boost::mutex::scoped_lock lk( _collectionsLock );
- return _getIndexRecordStore_inlock();
- }
-
- RecordStoreV1Base* MMAPV1DatabaseCatalogEntry::_getIndexRecordStore_inlock() {
- NamespaceString nss( name(), "system.indexes" );
+ const NamespaceString nss(name(), "system.indexes");
Entry* entry = _collections[nss.toString()];
invariant( entry );
+
return entry->recordStore.get();
}
RecordStoreV1Base* MMAPV1DatabaseCatalogEntry::_getNamespaceRecordStore() const {
- boost::mutex::scoped_lock lk( _collectionsLock );
- return _getNamespaceRecordStore_inlock();
- }
-
- RecordStoreV1Base* MMAPV1DatabaseCatalogEntry::_getNamespaceRecordStore_inlock() const {
- NamespaceString nss( name(), "system.namespaces" );
+ const NamespaceString nss( name(), "system.namespaces" );
CollectionMap::const_iterator i = _collections.find( nss.toString() );
invariant( i != _collections.end() );
+
return i->second->recordStore.get();
}
- void MMAPV1DatabaseCatalogEntry::_addNamespaceToNamespaceCollection( OperationContext* txn,
- const StringData& ns,
- const BSONObj* options ) {
- boost::mutex::scoped_lock lk( _collectionsLock );
- _addNamespaceToNamespaceCollection_inlock( txn, ns, options );
- }
+ void MMAPV1DatabaseCatalogEntry::_addNamespaceToNamespaceCollection(OperationContext* txn,
+ const StringData& ns,
+ const BSONObj* options) {
- void MMAPV1DatabaseCatalogEntry::_addNamespaceToNamespaceCollection_inlock( OperationContext* txn,
- const StringData& ns,
- const BSONObj* options ) {
- if ( nsToCollectionSubstring( ns ) == "system.namespaces" ) {
+ if (nsToCollectionSubstring(ns) == "system.namespaces") {
// system.namespaces holds all the others, so it is not explicitly listed in the catalog.
return;
}
BSONObjBuilder b;
b.append("name", ns);
- if ( options && !options->isEmpty() )
+ if (options && !options->isEmpty()) {
b.append("options", *options);
- BSONObj obj = b.done();
+ }
+
+ const BSONObj obj = b.done();
- RecordStoreV1Base* rs = _getNamespaceRecordStore_inlock();
+ RecordStoreV1Base* rs = _getNamespaceRecordStore();
invariant( rs );
+
StatusWith<RecordId> loc = rs->insertRecord( txn, obj.objdata(), obj.objsize(), false );
massertStatusOK( loc.getStatus() );
}
- void MMAPV1DatabaseCatalogEntry::_removeNamespaceFromNamespaceCollection( OperationContext* txn,
- const StringData& ns ) {
+ void MMAPV1DatabaseCatalogEntry::_removeNamespaceFromNamespaceCollection(
+ OperationContext* txn,
+ const StringData& ns ) {
+
if ( nsToCollectionSubstring( ns ) == "system.namespaces" ) {
// system.namespaces holds all the others, so it is not explicitly listed in the catalog.
return;
diff --git a/src/mongo/db/storage/mmap_v1/mmap_v1_database_catalog_entry.h b/src/mongo/db/storage/mmap_v1/mmap_v1_database_catalog_entry.h
index 9eb1ef53b47..6a597e85dc3 100644
--- a/src/mongo/db/storage/mmap_v1/mmap_v1_database_catalog_entry.h
+++ b/src/mongo/db/storage/mmap_v1/mmap_v1_database_catalog_entry.h
@@ -1,32 +1,30 @@
-// mmap_v1_database_catalog_entry.h
-
/**
-* Copyright (C) 2014 MongoDB Inc.
-*
-* This program is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Affero General Public License, version 3,
-* as published by the Free Software Foundation.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU Affero General Public License for more details.
-*
-* You should have received a copy of the GNU Affero General Public License
-* along with this program. If not, see <http://www.gnu.org/licenses/>.
-*
-* As a special exception, the copyright holders give permission to link the
-* code of portions of this program with the OpenSSL library under certain
-* conditions as described in each individual source file and distribute
-* linked combinations including the program with the OpenSSL library. You
-* must comply with the GNU Affero General Public License in all respects for
-* all of the code used other than as permitted herein. If you modify file(s)
-* with this exception, you may extend this exception to your version of the
-* file(s), but you are not obligated to do so. If you do not wish to do so,
-* delete this exception statement from your version. If you delete this
-* exception statement from all source files in the program, then also delete
-* it in the license file.
-*/
+ * Copyright (C) 2014 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
#pragma once
@@ -63,16 +61,15 @@ namespace mongo {
// these two seem the same and yet different
// TODO(ERH): consolidate into one ideally
- bool exists() const { return _namespaceIndex.pathExists(); }
- bool isEmpty() const { return !_namespaceIndex.allocated(); }
- bool hasUserData() const {
+ virtual bool exists() const { return _namespaceIndex.pathExists(); }
+ virtual bool isEmpty() const { return !_namespaceIndex.allocated(); }
+ virtual bool hasUserData() const {
// The two collections which exist and can't be removed are:
// system.indexes
// system.namespaces
return _collections.size() > 2;
}
-
virtual int64_t sizeOnDisk( OperationContext* opCtx ) const;
virtual bool isOlderThan24( OperationContext* opCtx ) const;
@@ -98,7 +95,7 @@ namespace mongo {
void getCollectionNamespaces( std::list<std::string>* tofill ) const;
- /*
+ /**
* will return NULL if ns does not exist
*/
CollectionCatalogEntry* getCollectionCatalogEntry( const StringData& ns ) const;
@@ -115,11 +112,6 @@ namespace mongo {
CollectionOptions getCollectionOptions( OperationContext* txn,
const StringData& ns ) const;
-
- //
- // Remaining methods are MMAPv1 specific
- //
-
/**
* Creates a CollectionCatalogEntry in the for an index rather than a collection. MMAPv1
* puts both indexes and collections into CCEs. A namespace named 'name' must not exist.
@@ -127,17 +119,21 @@ namespace mongo {
void createNamespaceForIndex(OperationContext* txn, const StringData& name);
private:
-
class EntryInsertion;
class EntryRemoval;
friend class NamespaceDetailsCollectionCatalogEntry;
- // The _collections map is a cache for efficiently looking up namespace information.
- // Access to the cache is protected by the _collectionsLock mutex.
- // Once initialized, the cache must remain consistent with the data in the memory-mapped
- // database files through _removeFromCache and _insertInCache_inlock. These methods
- // use the RecoveryUnit to ensure correct handling of rollback.
+ // The _collections map is a cache for efficiently looking up namespace information. Access
+ // to the cache is protected by holding the appropriate DB lock. Regular operations
+ // (insert/update/delete/query) hold intent locks on the database and they access the cache
+ // directly. Metadata operations, such as create db/collection, etc acquire exclusive lock
+ // on the database, which protects against concurrent readers of the cache.
+ //
+ // Once initialized, the cache must remain consistent with the data in the memory-mapped
+ // database files through _removeFromCache and _insertInCache. These methods use the
+ // RecoveryUnit to ensure correct handling of rollback.
+
struct Entry {
scoped_ptr<CollectionCatalogEntry> catalogEntry;
scoped_ptr<RecordStoreV1Base> recordStore;
@@ -146,39 +142,29 @@ namespace mongo {
typedef std::map<std::string, Entry*> CollectionMap;
- RecordStoreV1Base* _getIndexRecordStore_inlock();
RecordStoreV1Base* _getIndexRecordStore();
- RecordStoreV1Base* _getNamespaceRecordStore_inlock() const;
RecordStoreV1Base* _getNamespaceRecordStore() const;
- RecordStoreV1Base* _getRecordStore( const StringData& ns ) const;
-
- void _addNamespaceToNamespaceCollection( OperationContext* txn,
- const StringData& ns,
- const BSONObj* options );
-
- void _addNamespaceToNamespaceCollection_inlock( OperationContext* txn,
- const StringData& ns,
- const BSONObj* options );
+ RecordStoreV1Base* _getRecordStore(const StringData& ns) const;
+ void _addNamespaceToNamespaceCollection(OperationContext* txn,
+ const StringData& ns,
+ const BSONObj* options);
- void _removeNamespaceFromNamespaceCollection( OperationContext* txn,
- const StringData& ns );
+ void _removeNamespaceFromNamespaceCollection(OperationContext* txn, const StringData& ns);
Status _renameSingleNamespace( OperationContext* txn,
const StringData& fromNS,
const StringData& toNS,
bool stayTemp );
- void _ensureSystemCollection_inlock( OperationContext* txn,
- const StringData& ns );
- void _init( OperationContext* txn );
+ void _ensureSystemCollection(OperationContext* txn, const StringData& ns);
- void _lazyInit( OperationContext* txn );
+ void _init( OperationContext* txn );
/**
* Populate the _collections cache.
*/
- void _insertInCache_inlock(OperationContext* opCtx, const StringData& ns, Entry* entry);
+ void _insertInCache(OperationContext* opCtx, const StringData& ns, Entry* entry);
/**
* Drop cached information for specified namespace. If a RecoveryUnit is specified,
@@ -187,12 +173,10 @@ namespace mongo {
void _removeFromCache(RecoveryUnit* ru, const StringData& ns);
- std::string _path;
+ const std::string _path;
MmapV1ExtentManager _extentManager;
NamespaceIndex _namespaceIndex;
-
- mutable boost::mutex _collectionsLock;
CollectionMap _collections;
};
}