summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDianna Hohensee <dianna.hohensee@mongodb.com>2020-05-07 15:17:35 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-05-12 02:53:39 +0000
commit3de4762514cee3507f77efd7b46b20c4362c041a (patch)
tree36f13877f42be887f124de6c4c4e305a654657e0
parentab9233d37298a13752ebed493c2c2f973b087adf (diff)
downloadmongo-3de4762514cee3507f77efd7b46b20c4362c041a.tar.gz
SERVER-47872 Move the Database class' epoch into the CollectionCatalog
-rw-r--r--src/mongo/db/catalog/collection_catalog.cpp5
-rw-r--r--src/mongo/db/catalog/collection_catalog.h23
-rw-r--r--src/mongo/db/catalog/collection_catalog_test.cpp9
-rw-r--r--src/mongo/db/catalog/database.h13
-rw-r--r--src/mongo/db/catalog/database_holder_impl.cpp2
-rw-r--r--src/mongo/db/catalog/database_holder_impl.h10
-rw-r--r--src/mongo/db/catalog/database_impl.cpp3
-rw-r--r--src/mongo/db/catalog/database_impl.h8
-rw-r--r--src/mongo/db/exec/requires_collection_stage.cpp6
-rw-r--r--src/mongo/db/exec/requires_collection_stage.h16
10 files changed, 48 insertions, 47 deletions
diff --git a/src/mongo/db/catalog/collection_catalog.cpp b/src/mongo/db/catalog/collection_catalog.cpp
index 8b1de565c47..c6e4973f259 100644
--- a/src/mongo/db/catalog/collection_catalog.cpp
+++ b/src/mongo/db/catalog/collection_catalog.cpp
@@ -249,6 +249,11 @@ void CollectionCatalog::onOpenCatalog(OperationContext* opCtx) {
stdx::lock_guard<Latch> lock(_catalogLock);
invariant(_shadowCatalog);
_shadowCatalog.reset();
+ ++_epoch;
+}
+
+uint64_t CollectionCatalog::getEpoch() const {
+ return _epoch;
}
Collection* CollectionCatalog::lookupCollectionByUUID(OperationContext* opCtx,
diff --git a/src/mongo/db/catalog/collection_catalog.h b/src/mongo/db/catalog/collection_catalog.h
index 23d0bf88b25..1a57e6f55f5 100644
--- a/src/mongo/db/catalog/collection_catalog.h
+++ b/src/mongo/db/catalog/collection_catalog.h
@@ -235,6 +235,17 @@ public:
*/
void onOpenCatalog(OperationContext* opCtx);
+ /**
+ * The epoch is incremented whenever the catalog is closed and re-opened.
+ *
+ * Callers of this method must hold the global lock in at least MODE_IS.
+ *
+ * This allows callers to detect an intervening catalog close. For example, closing the catalog
+ * must kill all active queries. This is implemented by checking that the epoch has not changed
+ * during query yield recovery.
+ */
+ uint64_t getEpoch() const;
+
iterator begin(StringData db) const;
iterator end() const;
@@ -285,6 +296,18 @@ private:
*/
uint64_t _generationNumber;
+ // Incremented whenever the CollectionCatalog gets closed and reopened (onCloseCatalog and
+ // onOpenCatalog).
+ //
+ // Catalog objects are destroyed and recreated when the catalog is closed and re-opened. We
+ // increment this counter to track when the catalog is reopened. This permits callers to detect
+ // after yielding whether their catalog pointers are still valid. Collection UUIDs are not
+ // sufficient, since they remain stable across catalog re-opening.
+ //
+ // A thread must hold the global exclusive lock to write to this variable, and must hold the
+ // global lock in at least MODE_IS to read it.
+ uint64_t _epoch = 0;
+
// Protects _resourceInformation.
mutable Mutex _resourceLock = MONGO_MAKE_LATCH("CollectionCatalog::_resourceLock");
diff --git a/src/mongo/db/catalog/collection_catalog_test.cpp b/src/mongo/db/catalog/collection_catalog_test.cpp
index 573ee9f5b3e..4cf75ec7962 100644
--- a/src/mongo/db/catalog/collection_catalog_test.cpp
+++ b/src/mongo/db/catalog/collection_catalog_test.cpp
@@ -576,6 +576,15 @@ TEST_F(CollectionCatalogTest, LookupNSSByUUIDForClosedCatalogReturnsFreshestNSS)
ASSERT_EQUALS(*catalog.lookupNSSByUUID(&opCtx, colUUID), newNss);
}
+// Re-opening the catalog should increment the CollectionCatalog's epoch.
+TEST_F(CollectionCatalogTest, CollectionCatalogEpoch) {
+ auto originalEpoch = catalog.getEpoch();
+ catalog.onCloseCatalog(&opCtx);
+ catalog.onOpenCatalog(&opCtx);
+ auto incrementedEpoch = catalog.getEpoch();
+ ASSERT_EQ(originalEpoch + 1, incrementedEpoch);
+}
+
DEATH_TEST_F(CollectionCatalogResourceTest, AddInvalidResourceType, "invariant") {
auto rid = ResourceId(RESOURCE_GLOBAL, 0);
catalog.addResource(rid, "");
diff --git a/src/mongo/db/catalog/database.h b/src/mongo/db/catalog/database.h
index f0ae23db785..bf8c12638d2 100644
--- a/src/mongo/db/catalog/database.h
+++ b/src/mongo/db/catalog/database.h
@@ -172,19 +172,6 @@ public:
* DropPendingCollectionReaper to clean up eventually.
*/
virtual void checkForIdIndexesAndDropPendingCollections(OperationContext* opCtx) const = 0;
-
- /**
- * A database is assigned a new epoch whenever it is closed and re-opened. This involves
- * deleting and reallocating a new Database object, so the epoch for a particular Database
- * instance is immutable.
- *
- * Callers of this method must hold the global lock in at least MODE_IS.
- *
- * This allows callers which drop and reacquire locks to detect an intervening database close.
- * For example, closing a database must kill all active queries against the database. This is
- * implemented by checking that the epoch has not changed during query yield recovery.
- */
- virtual uint64_t epoch() const = 0;
};
} // namespace mongo
diff --git a/src/mongo/db/catalog/database_holder_impl.cpp b/src/mongo/db/catalog/database_holder_impl.cpp
index 93e1a98b0fa..7d72ed98cef 100644
--- a/src/mongo/db/catalog/database_holder_impl.cpp
+++ b/src/mongo/db/catalog/database_holder_impl.cpp
@@ -147,7 +147,7 @@ Database* DatabaseHolderImpl::openDb(OperationContext* opCtx, StringData ns, boo
*justCreated = true;
}
- auto newDb = std::make_unique<DatabaseImpl>(dbname, ++_epoch);
+ auto newDb = std::make_unique<DatabaseImpl>(dbname);
newDb->init(opCtx);
// Finally replace our nullptr entry with the new Database pointer.
diff --git a/src/mongo/db/catalog/database_holder_impl.h b/src/mongo/db/catalog/database_holder_impl.h
index cede54eab55..8b200c22a51 100644
--- a/src/mongo/db/catalog/database_holder_impl.h
+++ b/src/mongo/db/catalog/database_holder_impl.h
@@ -60,16 +60,6 @@ private:
typedef StringMap<Database*> DBs;
mutable SimpleMutex _m;
DBs _dbs;
-
- // Databases objects and their constituent collections are destroyed and recreated when
- // databases are closed and opened. We use this counter to assign a new epoch to a database when
- // it is reopened. This permits callers to detect after yielding and reacquiring locks whether
- // their catalog pointers are still valid. Collection UUIDs are not sufficient, since they
- // remain stable when databases are closed and reopened.
- //
- // A thread must hold the global exclusive lock to write to this variable, and must hold the
- // global lock in at least MODE_IS to read it.
- uint64_t _epoch = 0;
};
} // namespace mongo
diff --git a/src/mongo/db/catalog/database_impl.cpp b/src/mongo/db/catalog/database_impl.cpp
index 4258a66dab5..bfc4ff75ca0 100644
--- a/src/mongo/db/catalog/database_impl.cpp
+++ b/src/mongo/db/catalog/database_impl.cpp
@@ -129,9 +129,8 @@ Status DatabaseImpl::validateDBName(StringData dbname) {
return Status::OK();
}
-DatabaseImpl::DatabaseImpl(const StringData name, uint64_t epoch)
+DatabaseImpl::DatabaseImpl(const StringData name)
: _name(name.toString()),
- _epoch(epoch),
_viewsName(_name + "." + DurableViewCatalog::viewsCollectionName().toString()) {
auto durableViewCatalog = std::make_unique<DurableViewCatalogImpl>(this);
auto viewCatalog = std::make_unique<ViewCatalog>(std::move(durableViewCatalog));
diff --git a/src/mongo/db/catalog/database_impl.h b/src/mongo/db/catalog/database_impl.h
index c9ab3b210f1..3992a645e04 100644
--- a/src/mongo/db/catalog/database_impl.h
+++ b/src/mongo/db/catalog/database_impl.h
@@ -35,7 +35,7 @@ namespace mongo {
class DatabaseImpl final : public Database {
public:
- explicit DatabaseImpl(StringData name, uint64_t epoch);
+ explicit DatabaseImpl(StringData name);
void init(OperationContext*) const final;
@@ -132,10 +132,6 @@ public:
return CollectionCatalog::get(opCtx).end();
}
- uint64_t epoch() const {
- return _epoch;
- }
-
private:
/**
* Throws if there is a reason 'ns' cannot be created as a user collection.
@@ -163,8 +159,6 @@ private:
const std::string _name; // "dbname"
- const uint64_t _epoch;
-
const NamespaceString _viewsName; // "dbname.system.views"
AtomicWord<int> _profile{0}; // 0=off
diff --git a/src/mongo/db/exec/requires_collection_stage.cpp b/src/mongo/db/exec/requires_collection_stage.cpp
index 0d120e413cc..59f41a27e53 100644
--- a/src/mongo/db/exec/requires_collection_stage.cpp
+++ b/src/mongo/db/exec/requires_collection_stage.cpp
@@ -31,8 +31,6 @@
#include "mongo/db/exec/requires_collection_stage.h"
-#include "mongo/db/catalog/collection_catalog.h"
-
namespace mongo {
template <typename CollectionT>
@@ -72,8 +70,8 @@ void RequiresCollectionStageBase<CollectionT>::doRestoreState() {
invariant(_collection);
uassert(ErrorCodes::QueryPlanKilled,
- str::stream() << "Database epoch changed due to a database-level event.",
- getDatabaseEpoch(_collection) == _databaseEpoch);
+ str::stream() << "The catalog was closed and reopened",
+ getCatalogEpoch() == _catalogEpoch);
doRestoreStateRequiresCollection();
}
diff --git a/src/mongo/db/exec/requires_collection_stage.h b/src/mongo/db/exec/requires_collection_stage.h
index 3b0520281e1..648cd0aa927 100644
--- a/src/mongo/db/exec/requires_collection_stage.h
+++ b/src/mongo/db/exec/requires_collection_stage.h
@@ -30,6 +30,7 @@
#pragma once
#include "mongo/db/catalog/collection.h"
+#include "mongo/db/catalog/collection_catalog.h"
#include "mongo/db/catalog/database.h"
#include "mongo/db/catalog/database_holder.h"
#include "mongo/db/exec/plan_stage.h"
@@ -59,7 +60,7 @@ public:
: PlanStage(stageType, expCtx),
_collection(coll),
_collectionUUID(_collection->uuid()),
- _databaseEpoch(getDatabaseEpoch(_collection)),
+ _catalogEpoch(getCatalogEpoch()),
_nss(_collection->ns()) {
invariant(_collection);
}
@@ -90,19 +91,14 @@ protected:
}
private:
- // This can only be called when the plan stage is attached to an operation context. The
- // collection pointer 'coll' must be non-null and must point to a valid collection.
- uint64_t getDatabaseEpoch(CollectionT coll) const {
- invariant(coll);
- auto databaseHolder = DatabaseHolder::get(opCtx());
- auto db = databaseHolder->getDb(opCtx(), coll->ns().ns());
- invariant(db);
- return db->epoch();
+ // This can only be called when the plan stage is attached to an operation context.
+ uint64_t getCatalogEpoch() const {
+ return CollectionCatalog::get(opCtx()).getEpoch();
}
CollectionT _collection;
const UUID _collectionUUID;
- const uint64_t _databaseEpoch;
+ const uint64_t _catalogEpoch;
// TODO SERVER-31695: The namespace will no longer be needed once queries can survive collection
// renames.