diff options
author | Xiangyu Yao <xiangyu.yao@mongodb.com> | 2019-03-29 11:04:36 -0400 |
---|---|---|
committer | Xiangyu Yao <xiangyu.yao@mongodb.com> | 2019-04-01 13:51:13 -0400 |
commit | e96547906836a12d76b7a1591a0028b1fff8cb79 (patch) | |
tree | 70e975e9591137b03cdb8d8f1ee361537b98aecd /src | |
parent | a3c7bdb31e949cfd11c2c9e24f9a04dfd6c22ba1 (diff) | |
download | mongo-e96547906836a12d76b7a1591a0028b1fff8cb79.tar.gz |
SERVER-39512 Make Database class thread-safe
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/catalog/database.h | 27 | ||||
-rw-r--r-- | src/mongo/db/catalog/database_impl.cpp | 59 | ||||
-rw-r--r-- | src/mongo/db/catalog/database_impl.h | 48 | ||||
-rw-r--r-- | src/mongo/db/repl/oplog.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/repl/oplog.h | 2 | ||||
-rw-r--r-- | src/mongo/db/views/view_catalog.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/views/view_catalog.h | 2 |
7 files changed, 66 insertions, 76 deletions
diff --git a/src/mongo/db/catalog/database.h b/src/mongo/db/catalog/database.h index 69b9975bb67..512e6e040ea 100644 --- a/src/mongo/db/catalog/database.h +++ b/src/mongo/db/catalog/database.h @@ -65,7 +65,7 @@ public: const NamespaceString& fullns, CollectionOptions collectionOptions, bool createDefaultIndexes = true, - const BSONObj& idIndex = BSONObj()) = 0; + const BSONObj& idIndex = BSONObj()) const = 0; Database() = default; @@ -81,14 +81,14 @@ public: /** * Sets up internal memory structures. */ - virtual void init(OperationContext* opCtx) = 0; + virtual void init(OperationContext* opCtx) const = 0; // closes files and other cleanup see below. - virtual void close(OperationContext* const opCtx) = 0; + virtual void close(OperationContext* const opCtx) const = 0; virtual const std::string& name() const = 0; - virtual void clearTmpCollections(OperationContext* const opCtx) = 0; + virtual void clearTmpCollections(OperationContext* const opCtx) const = 0; /** * Sets a new profiling level for the database and returns the outcome. @@ -118,7 +118,7 @@ public: virtual void getStats(OperationContext* const opCtx, BSONObjBuilder* const output, - const double scale = 1) = 0; + const double scale = 1) const = 0; virtual const DatabaseCatalogEntry* getDatabaseCatalogEntry() const = 0; @@ -134,22 +134,23 @@ public: */ virtual Status dropCollection(OperationContext* const opCtx, const StringData fullns, - repl::OpTime dropOpTime = {}) = 0; + repl::OpTime dropOpTime = {}) const = 0; virtual Status dropCollectionEvenIfSystem(OperationContext* const opCtx, const NamespaceString& fullns, - repl::OpTime dropOpTime = {}) = 0; + repl::OpTime dropOpTime = {}) const = 0; - virtual Status dropView(OperationContext* const opCtx, const NamespaceString& viewName) = 0; + virtual Status dropView(OperationContext* const opCtx, + const NamespaceString& viewName) const = 0; virtual Collection* createCollection(OperationContext* const opCtx, StringData ns, const CollectionOptions& options = CollectionOptions(), const bool createDefaultIndexes = true, - const BSONObj& idIndex = BSONObj()) = 0; + const BSONObj& idIndex = BSONObj()) const = 0; virtual Status createView(OperationContext* const opCtx, const NamespaceString& viewName, - const CollectionOptions& options) = 0; + const CollectionOptions& options) const = 0; /** * @param ns - this is fully qualified, which is maybe not ideal ??? @@ -159,12 +160,12 @@ public: virtual Collection* getCollection(OperationContext* opCtx, const NamespaceString& ns) const = 0; virtual Collection* getOrCreateCollection(OperationContext* const opCtx, - const NamespaceString& nss) = 0; + const NamespaceString& nss) const = 0; virtual Status renameCollection(OperationContext* const opCtx, const StringData fromNS, const StringData toNS, - const bool stayTemp) = 0; + const bool stayTemp) const = 0; virtual const std::string& getSystemViewsName() const = 0; @@ -186,7 +187,7 @@ public: * database, we also gather a list of drop-pending collection namespaces for the * DropPendingCollectionReaper to clean up eventually. */ - virtual void checkForIdIndexesAndDropPendingCollections(OperationContext* opCtx) = 0; + virtual void checkForIdIndexesAndDropPendingCollections(OperationContext* opCtx) const = 0; /** * A database is assigned a new epoch whenever it is closed and re-opened. This involves diff --git a/src/mongo/db/catalog/database_impl.cpp b/src/mongo/db/catalog/database_impl.cpp index b15efab21aa..49dadda173c 100644 --- a/src/mongo/db/catalog/database_impl.cpp +++ b/src/mongo/db/catalog/database_impl.cpp @@ -124,7 +124,7 @@ void uassertNamespaceNotIndex(StringData ns, StringData caller) { NamespaceString::normal(ns)); } -void DatabaseImpl::close(OperationContext* opCtx) { +void DatabaseImpl::close(OperationContext* opCtx) const { invariant(opCtx->lockState()->isW()); // Clear cache of oplog Collection pointer. @@ -161,9 +161,10 @@ DatabaseImpl::DatabaseImpl(const StringData name, DatabaseCatalogEntry* dbEntry, auto viewCatalog = std::make_unique<ViewCatalog>(std::move(durableViewCatalog)); ViewCatalog::set(this, std::move(viewCatalog)); + _profile.store(serverGlobalParams.defaultProfile); } -void DatabaseImpl::init(OperationContext* const opCtx) { +void DatabaseImpl::init(OperationContext* const opCtx) const { Status status = validateDBName(_name); if (!status.isOK()) { @@ -171,8 +172,6 @@ void DatabaseImpl::init(OperationContext* const opCtx) { uasserted(10028, status.toString()); } - _profile = serverGlobalParams.defaultProfile; - std::list<std::string> collections; _dbEntry->getCollectionNamespaces(&collections); @@ -205,7 +204,7 @@ void DatabaseImpl::init(OperationContext* const opCtx) { } } -void DatabaseImpl::clearTmpCollections(OperationContext* opCtx) { +void DatabaseImpl::clearTmpCollections(OperationContext* opCtx) const { invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_X)); std::list<std::string> collections; @@ -239,12 +238,14 @@ void DatabaseImpl::clearTmpCollections(OperationContext* opCtx) { } Status DatabaseImpl::setProfilingLevel(OperationContext* opCtx, int newLevel) { - if (_profile == newLevel) { + auto currLevel = _profile.load(); + + if (currLevel == newLevel) { return Status::OK(); } if (newLevel == 0) { - _profile = 0; + _profile.store(0); return Status::OK(); } @@ -264,27 +265,23 @@ Status DatabaseImpl::setProfilingLevel(OperationContext* opCtx, int newLevel) { return status; } - _profile = newLevel; + _profile.store(newLevel); return Status::OK(); } void DatabaseImpl::setDropPending(OperationContext* opCtx, bool dropPending) { - if (dropPending) { - invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_X)); - _dropPending = true; - } else { - invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_IX)); - _dropPending = false; - } + auto mode = dropPending ? MODE_X : MODE_IX; + invariant(opCtx->lockState()->isDbLockedForMode(name(), mode)); + _dropPending.store(dropPending); } bool DatabaseImpl::isDropPending(OperationContext* opCtx) const { invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_X)); - return _dropPending; + return _dropPending.load(); } -void DatabaseImpl::getStats(OperationContext* opCtx, BSONObjBuilder* output, double scale) { +void DatabaseImpl::getStats(OperationContext* opCtx, BSONObjBuilder* output, double scale) const { long long nCollections = 0; long long nViews = 0; @@ -350,7 +347,7 @@ void DatabaseImpl::getStats(OperationContext* opCtx, BSONObjBuilder* output, dou } } -Status DatabaseImpl::dropView(OperationContext* opCtx, const NamespaceString& viewName) { +Status DatabaseImpl::dropView(OperationContext* opCtx, const NamespaceString& viewName) const { dassert(opCtx->lockState()->isDbLockedForMode(name(), MODE_IX)); dassert(opCtx->lockState()->isCollectionLockedForMode(viewName, MODE_IX)); dassert(opCtx->lockState()->isCollectionLockedForMode(NamespaceString(_viewsName), MODE_X)); @@ -363,7 +360,7 @@ Status DatabaseImpl::dropView(OperationContext* opCtx, const NamespaceString& vi Status DatabaseImpl::dropCollection(OperationContext* opCtx, StringData fullns, - repl::OpTime dropOpTime) { + repl::OpTime dropOpTime) const { if (!getCollection(opCtx, fullns)) { // Collection doesn't exist so don't bother validating if it can be dropped. return Status::OK(); @@ -375,7 +372,7 @@ Status DatabaseImpl::dropCollection(OperationContext* opCtx, if (nss.isSystem()) { if (nss.isSystemDotProfile()) { - if (_profile != 0) + if (_profile.load() != 0) return Status(ErrorCodes::IllegalOperation, "turn off profiling before dropping system.profile collection"); } else if (!(nss.isSystemDotViews() || nss.isHealthlog() || @@ -392,7 +389,7 @@ Status DatabaseImpl::dropCollection(OperationContext* opCtx, Status DatabaseImpl::dropCollectionEvenIfSystem(OperationContext* opCtx, const NamespaceString& fullns, - repl::OpTime dropOpTime) { + repl::OpTime dropOpTime) const { invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_X)); LOG(1) << "dropCollection: " << fullns; @@ -506,7 +503,7 @@ Status DatabaseImpl::dropCollectionEvenIfSystem(OperationContext* opCtx, void DatabaseImpl::_dropCollectionIndexes(OperationContext* opCtx, const NamespaceString& fullns, - Collection* collection) { + Collection* collection) const { invariant(_name == fullns.db()); LOG(1) << "dropCollection: " << fullns << " - dropAllIndexes start"; collection->getIndexCatalog()->dropAllIndexes(opCtx, true); @@ -517,7 +514,7 @@ void DatabaseImpl::_dropCollectionIndexes(OperationContext* opCtx, Status DatabaseImpl::_finishDropCollection(OperationContext* opCtx, const NamespaceString& fullns, - Collection* collection) { + Collection* collection) const { auto uuid = collection->uuid(); auto uuidString = uuid ? uuid.get().toString() : "no UUID"; log() << "Finishing collection drop for " << fullns << " (" << uuidString << ")."; @@ -548,7 +545,7 @@ Collection* DatabaseImpl::getCollection(OperationContext* opCtx, const Namespace Status DatabaseImpl::renameCollection(OperationContext* opCtx, StringData fromNS, StringData toNS, - bool stayTemp) { + bool stayTemp) const { audit::logRenameCollection(&cc(), fromNS, toNS); invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_X)); @@ -605,7 +602,7 @@ Status DatabaseImpl::renameCollection(OperationContext* opCtx, } Collection* DatabaseImpl::getOrCreateCollection(OperationContext* opCtx, - const NamespaceString& nss) { + const NamespaceString& nss) const { Collection* c = getCollection(opCtx, nss); if (!c) { @@ -616,7 +613,7 @@ Collection* DatabaseImpl::getOrCreateCollection(OperationContext* opCtx, void DatabaseImpl::_checkCanCreateCollection(OperationContext* opCtx, const NamespaceString& nss, - const CollectionOptions& options) { + const CollectionOptions& options) const { massert(17399, str::stream() << "Cannot create collection " << nss << " - collection already exists.", getCollection(opCtx, nss) == nullptr); @@ -639,12 +636,12 @@ void DatabaseImpl::_checkCanCreateCollection(OperationContext* opCtx, uassert(ErrorCodes::DatabaseDropPending, str::stream() << "Cannot create collection " << nss << " - database is in the process of being dropped.", - !_dropPending); + !_dropPending.load()); } Status DatabaseImpl::createView(OperationContext* opCtx, const NamespaceString& viewName, - const CollectionOptions& options) { + const CollectionOptions& options) const { dassert(opCtx->lockState()->isDbLockedForMode(name(), MODE_IX)); dassert(opCtx->lockState()->isCollectionLockedForMode(viewName, MODE_IX)); dassert(opCtx->lockState()->isCollectionLockedForMode(NamespaceString(_viewsName), MODE_X)); @@ -667,7 +664,7 @@ Collection* DatabaseImpl::createCollection(OperationContext* opCtx, StringData ns, const CollectionOptions& options, bool createIdIndex, - const BSONObj& idIndex) { + const BSONObj& idIndex) const { invariant(!options.isView()); NamespaceString nss(ns); @@ -847,7 +844,7 @@ StatusWith<NamespaceString> DatabaseImpl::makeUniqueCollectionNamespace( << " attempts due to namespace conflicts with existing collections."); } -void DatabaseImpl::checkForIdIndexesAndDropPendingCollections(OperationContext* opCtx) { +void DatabaseImpl::checkForIdIndexesAndDropPendingCollections(OperationContext* opCtx) const { if (name() == "local") { // Collections in the local database are not replicated, so we do not need an _id index on // any collection. For the same reason, it is not possible for the local database to contain @@ -889,7 +886,7 @@ Status DatabaseImpl::userCreateNS(OperationContext* opCtx, const NamespaceString& fullns, CollectionOptions collectionOptions, bool createDefaultIndexes, - const BSONObj& idIndex) { + const BSONObj& idIndex) const { LOG(1) << "create collection " << fullns << ' ' << collectionOptions.toBSON(); if (!NamespaceString::validCollectionComponent(fullns.ns())) diff --git a/src/mongo/db/catalog/database_impl.h b/src/mongo/db/catalog/database_impl.h index dfd66ebbb1c..68987713798 100644 --- a/src/mongo/db/catalog/database_impl.h +++ b/src/mongo/db/catalog/database_impl.h @@ -39,17 +39,17 @@ class DatabaseImpl final : public Database { public: explicit DatabaseImpl(StringData name, DatabaseCatalogEntry* dbEntry, uint64_t epoch); - void init(OperationContext*) final; + void init(OperationContext*) const final; // closes files and other cleanup see below. - void close(OperationContext* opCtx) final; + void close(OperationContext* opCtx) const final; const std::string& name() const final { return _name; } - void clearTmpCollections(OperationContext* opCtx) final; + void clearTmpCollections(OperationContext* opCtx) const final; /** * Sets a new profiling level for the database and returns the outcome. @@ -60,7 +60,7 @@ public: Status setProfilingLevel(OperationContext* opCtx, int newLevel) final; int getProfilingLevel() const final { - return _profile; + return _profile.load(); } const char* getProfilingNS() const final { return _profileName.c_str(); @@ -70,7 +70,7 @@ public: bool isDropPending(OperationContext* opCtx) const final; - void getStats(OperationContext* opCtx, BSONObjBuilder* output, double scale = 1) final; + void getStats(OperationContext* opCtx, BSONObjBuilder* output, double scale = 1) const final; const DatabaseCatalogEntry* getDatabaseCatalogEntry() const final; @@ -86,28 +86,28 @@ public: */ Status dropCollection(OperationContext* opCtx, StringData fullns, - repl::OpTime dropOpTime) final; + repl::OpTime dropOpTime) const final; Status dropCollectionEvenIfSystem(OperationContext* opCtx, const NamespaceString& fullns, - repl::OpTime dropOpTime) final; + repl::OpTime dropOpTime) const final; - Status dropView(OperationContext* opCtx, const NamespaceString& viewName) final; + Status dropView(OperationContext* opCtx, const NamespaceString& viewName) const final; Status userCreateNS(OperationContext* opCtx, const NamespaceString& fullns, CollectionOptions collectionOptions, bool createDefaultIndexes, - const BSONObj& idIndex) final; + const BSONObj& idIndex) const final; Collection* createCollection(OperationContext* opCtx, StringData ns, const CollectionOptions& options = CollectionOptions(), bool createDefaultIndexes = true, - const BSONObj& idIndex = BSONObj()) final; + const BSONObj& idIndex = BSONObj()) const final; Status createView(OperationContext* opCtx, const NamespaceString& viewName, - const CollectionOptions& options) final; + const CollectionOptions& options) const final; /** * @param ns - this is fully qualified, which is maybe not ideal ??? @@ -116,7 +116,8 @@ public: Collection* getCollection(OperationContext* opCtx, const NamespaceString& ns) const; - Collection* getOrCreateCollection(OperationContext* opCtx, const NamespaceString& nss) final; + Collection* getOrCreateCollection(OperationContext* opCtx, + const NamespaceString& nss) const final; /** * Renames the fully qualified namespace 'fromNS' to the fully qualified namespace 'toNS'. @@ -129,16 +130,7 @@ public: Status renameCollection(OperationContext* opCtx, StringData fromNS, StringData toNS, - bool stayTemp) final; - - /** - * Physically drops the specified opened database and removes it from the server's metadata. It - * doesn't notify the replication subsystem or do any other consistency checks, so it should - * not be used directly from user commands. - * - * Must be called with the specified database locked in X mode. - */ - static void dropDatabase(OperationContext* opCtx, Database* db); + bool stayTemp) const final; static Status validateDBName(StringData dbname); @@ -149,7 +141,7 @@ public: StatusWith<NamespaceString> makeUniqueCollectionNamespace(OperationContext* opCtx, StringData collectionNameModel) final; - void checkForIdIndexesAndDropPendingCollections(OperationContext* opCtx) final; + void checkForIdIndexesAndDropPendingCollections(OperationContext* opCtx) const final; UUIDCatalog::iterator begin(OperationContext* opCtx) const final { return UUIDCatalog::get(opCtx).begin(_name); @@ -169,7 +161,7 @@ private: */ void _checkCanCreateCollection(OperationContext* opCtx, const NamespaceString& nss, - const CollectionOptions& options); + const CollectionOptions& options) const; /** * Completes a collection drop by removing the collection itself from the storage engine. @@ -179,14 +171,14 @@ private: */ Status _finishDropCollection(OperationContext* opCtx, const NamespaceString& fullns, - Collection* collection); + Collection* collection) const; /** * Removes all indexes for a collection. */ void _dropCollectionIndexes(OperationContext* opCtx, const NamespaceString& fullns, - Collection* collection); + Collection* collection) const; const std::string _name; // "dbname" @@ -197,12 +189,12 @@ private: const std::string _profileName; // "dbname.system.profile" const std::string _viewsName; // "dbname.system.views" - int _profile; // 0=off. + AtomicWord<int> _profile{0}; // 0=off // If '_dropPending' is true, this Database is in the midst of a two-phase drop. No new // collections may be created in this Database. // This variable may only be read/written while the database is locked in MODE_X. - bool _dropPending = false; + AtomicWord<bool> _dropPending{false}; // Random number generator used to create unique collection namespaces suitable for temporary // collections. Lazily created on first call to makeUniqueCollectionNamespace(). diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp index 0aa23a1a07c..0c86e4449bd 100644 --- a/src/mongo/db/repl/oplog.cpp +++ b/src/mongo/db/repl/oplog.cpp @@ -2093,7 +2093,7 @@ void initTimestampFromOplog(OperationContext* opCtx, const std::string& oplogNS) } } -void oplogCheckCloseDatabase(OperationContext* opCtx, Database* db) { +void oplogCheckCloseDatabase(OperationContext* opCtx, const Database* db) { invariant(opCtx->lockState()->isW()); if (db->name() == "local") { localOplogInfo(opCtx->getServiceContext()).oplog = nullptr; diff --git a/src/mongo/db/repl/oplog.h b/src/mongo/db/repl/oplog.h index 86be44cc30d..5879fc0297d 100644 --- a/src/mongo/db/repl/oplog.h +++ b/src/mongo/db/repl/oplog.h @@ -151,7 +151,7 @@ OpTime logOp(OperationContext* opCtx, // Flush out the cached pointer to the oplog. // Used by the closeDatabase command to ensure we don't cache closed things. -void oplogCheckCloseDatabase(OperationContext* opCtx, Database* db); +void oplogCheckCloseDatabase(OperationContext* opCtx, const Database* db); /** * Establish the cached pointer to the local oplog. diff --git a/src/mongo/db/views/view_catalog.cpp b/src/mongo/db/views/view_catalog.cpp index c932c365983..f77f6991b59 100644 --- a/src/mongo/db/views/view_catalog.cpp +++ b/src/mongo/db/views/view_catalog.cpp @@ -73,7 +73,7 @@ StatusWith<std::unique_ptr<CollatorInterface>> parseCollator(OperationContext* o } } // namespace -ViewCatalog* ViewCatalog::get(Database* db) { +ViewCatalog* ViewCatalog::get(const Database* db) { return getViewCatalog(db).get(); } diff --git a/src/mongo/db/views/view_catalog.h b/src/mongo/db/views/view_catalog.h index 08ed7c72422..7e92ea3afad 100644 --- a/src/mongo/db/views/view_catalog.h +++ b/src/mongo/db/views/view_catalog.h @@ -67,7 +67,7 @@ public: using ViewMap = StringMap<std::shared_ptr<ViewDefinition>>; using ViewIteratorCallback = stdx::function<void(const ViewDefinition& view)>; - static ViewCatalog* get(Database* db); + static ViewCatalog* get(const Database* db); static void set(Database* db, std::unique_ptr<ViewCatalog> catalog); explicit ViewCatalog(std::unique_ptr<DurableViewCatalog> durable) |