summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorXiangyu Yao <xiangyu.yao@mongodb.com>2019-03-29 11:04:36 -0400
committerXiangyu Yao <xiangyu.yao@mongodb.com>2019-04-01 13:51:13 -0400
commite96547906836a12d76b7a1591a0028b1fff8cb79 (patch)
tree70e975e9591137b03cdb8d8f1ee361537b98aecd /src
parenta3c7bdb31e949cfd11c2c9e24f9a04dfd6c22ba1 (diff)
downloadmongo-e96547906836a12d76b7a1591a0028b1fff8cb79.tar.gz
SERVER-39512 Make Database class thread-safe
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/catalog/database.h27
-rw-r--r--src/mongo/db/catalog/database_impl.cpp59
-rw-r--r--src/mongo/db/catalog/database_impl.h48
-rw-r--r--src/mongo/db/repl/oplog.cpp2
-rw-r--r--src/mongo/db/repl/oplog.h2
-rw-r--r--src/mongo/db/views/view_catalog.cpp2
-rw-r--r--src/mongo/db/views/view_catalog.h2
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)