summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/catalog/multi_index_block.cpp4
-rw-r--r--src/mongo/db/storage/durable_catalog.h5
-rw-r--r--src/mongo/db/storage/durable_catalog_impl.cpp15
-rw-r--r--src/mongo/db/storage/durable_catalog_impl.h5
-rw-r--r--src/mongo/db/storage/storage_engine.h8
-rw-r--r--src/mongo/db/storage/storage_engine_impl.cpp82
-rw-r--r--src/mongo/db/storage/storage_engine_impl.h15
-rw-r--r--src/mongo/db/storage/storage_engine_mock.h4
8 files changed, 94 insertions, 44 deletions
diff --git a/src/mongo/db/catalog/multi_index_block.cpp b/src/mongo/db/catalog/multi_index_block.cpp
index 617145e3abc..63a304a1f30 100644
--- a/src/mongo/db/catalog/multi_index_block.cpp
+++ b/src/mongo/db/catalog/multi_index_block.cpp
@@ -872,7 +872,9 @@ boost::optional<ResumeIndexInfo> MultiIndexBlock::_abortWithoutCleanup(Operation
void MultiIndexBlock::_writeStateToDisk(OperationContext* opCtx) const {
auto obj = _constructStateObject();
- auto rs = opCtx->getServiceContext()->getStorageEngine()->makeTemporaryRecordStore(opCtx);
+ auto rs = opCtx->getServiceContext()
+ ->getStorageEngine()
+ ->makeTemporaryRecordStoreForResumableIndexBuild(opCtx);
WriteUnitOfWork wuow(opCtx);
diff --git a/src/mongo/db/storage/durable_catalog.h b/src/mongo/db/storage/durable_catalog.h
index 2d9aecb32ee..b782b144f0b 100644
--- a/src/mongo/db/storage/durable_catalog.h
+++ b/src/mongo/db/storage/durable_catalog.h
@@ -128,6 +128,11 @@ public:
virtual std::string newInternalIdent() = 0;
/**
+ * Generate an internal resumable index build ident name.
+ */
+ virtual std::string newInternalResumableIndexBuildIdent() = 0;
+
+ /**
* On success, returns the RecordId which identifies the new record store in the durable catalog
* in addition to ownership of the new RecordStore.
*/
diff --git a/src/mongo/db/storage/durable_catalog_impl.cpp b/src/mongo/db/storage/durable_catalog_impl.cpp
index b991c213bc3..de8b719918b 100644
--- a/src/mongo/db/storage/durable_catalog_impl.cpp
+++ b/src/mongo/db/storage/durable_catalog_impl.cpp
@@ -65,6 +65,7 @@ const char kNamespaceFieldName[] = "ns";
const char kNonRepairableFeaturesFieldName[] = "nonRepairable";
const char kRepairableFeaturesFieldName[] = "repairable";
const char kInternalIdentPrefix[] = "internal-";
+const char kResumableIndexBuildIdentStem[] = "resumable-index-build-";
void appendPositionsOfBitsSet(uint64_t value, StringBuilder* sb) {
invariant(sb);
@@ -427,8 +428,17 @@ bool DurableCatalogImpl::_hasEntryCollidingWithRand() const {
}
std::string DurableCatalogImpl::newInternalIdent() {
+ return _newInternalIdent("");
+}
+
+std::string DurableCatalogImpl::newInternalResumableIndexBuildIdent() {
+ return _newInternalIdent(kResumableIndexBuildIdentStem);
+}
+
+std::string DurableCatalogImpl::_newInternalIdent(StringData identStem) {
StringBuilder buf;
buf << kInternalIdentPrefix;
+ buf << identStem;
buf << _next.fetchAndAdd(1) << '-' << _rand;
return buf.str();
}
@@ -765,6 +775,11 @@ bool DurableCatalogImpl::isInternalIdent(StringData ident) const {
return ident.find(kInternalIdentPrefix) != std::string::npos;
}
+bool DurableCatalogImpl::isResumableIndexBuildIdent(StringData ident) const {
+ invariant(isInternalIdent(ident), ident.toString());
+ return ident.find(kResumableIndexBuildIdentStem) != std::string::npos;
+}
+
bool DurableCatalogImpl::isCollectionIdent(StringData ident) const {
// Internal idents prefixed "internal-" should not be considered collections, because
// they are not eligible for orphan recovery through repair.
diff --git a/src/mongo/db/storage/durable_catalog_impl.h b/src/mongo/db/storage/durable_catalog_impl.h
index b24816d333d..9b8fad96825 100644
--- a/src/mongo/db/storage/durable_catalog_impl.h
+++ b/src/mongo/db/storage/durable_catalog_impl.h
@@ -92,6 +92,8 @@ public:
bool isInternalIdent(StringData ident) const;
+ bool isResumableIndexBuildIdent(StringData ident) const;
+
bool isCollectionIdent(StringData ident) const;
FeatureTracker* getFeatureTracker() const {
@@ -108,6 +110,7 @@ public:
std::string getFilesystemPathForDb(const std::string& dbName) const;
std::string newInternalIdent();
+ std::string newInternalResumableIndexBuildIdent();
StatusWith<std::pair<RecordId, std::unique_ptr<RecordStore>>> createCollection(
OperationContext* opCtx,
@@ -229,6 +232,8 @@ private:
*/
std::string _newUniqueIdent(NamespaceString nss, const char* kind);
+ std::string _newInternalIdent(StringData identStem);
+
// Helpers only used by constructor and init(). Don't call from elsewhere.
static std::string _newRand();
bool _hasEntryCollidingWithRand() const;
diff --git a/src/mongo/db/storage/storage_engine.h b/src/mongo/db/storage/storage_engine.h
index aa06d951c9f..72c09e125b6 100644
--- a/src/mongo/db/storage/storage_engine.h
+++ b/src/mongo/db/storage/storage_engine.h
@@ -376,6 +376,14 @@ public:
OperationContext* opCtx) = 0;
/**
+ * Creates a temporary RecordStore on the storage engine for a resumable index build. On
+ * startup after an unclean shutdown, the storage engine will drop any un-dropped temporary
+ * record stores.
+ */
+ virtual std::unique_ptr<TemporaryRecordStore> makeTemporaryRecordStoreForResumableIndexBuild(
+ OperationContext* opCtx) = 0;
+
+ /**
* Creates a temporary RecordStore on the storage engine from an existing ident on disk. On
* startup after an unclean shutdown, the storage engine will drop any un-dropped temporary
* record stores.
diff --git a/src/mongo/db/storage/storage_engine_impl.cpp b/src/mongo/db/storage/storage_engine_impl.cpp
index 88c183919e1..e8efa8ce88d 100644
--- a/src/mongo/db/storage/storage_engine_impl.cpp
+++ b/src/mongo/db/storage/storage_engine_impl.cpp
@@ -326,7 +326,7 @@ Status StorageEngineImpl::_recoverOrphanedCollection(OperationContext* opCtx,
return Status::OK();
}
-bool StorageEngineImpl::_handleInternalIdents(
+bool StorageEngineImpl::_handleInternalIdent(
OperationContext* opCtx,
const std::string& ident,
InternalIdentReconcilePolicy internalIdentReconcilePolicy,
@@ -345,14 +345,15 @@ bool StorageEngineImpl::_handleInternalIdents(
return true;
}
+ if (!_catalog->isResumableIndexBuildIdent(ident)) {
+ return false;
+ }
+
// When starting up after a clean shutdown and resumable index builds are supported, find the
// internal idents that contain the relevant information to resume each index build and recover
// the state.
auto rs = _engine->getRecordStore(opCtx, "", ident, CollectionOptions());
- // Look at the contents to determine whether this ident will contain information for
- // resuming an index build.
- // TODO SERVER-49215: differentiate the internal idents without looking at the contents.
auto cursor = rs->getCursor(opCtx);
auto record = cursor->next();
if (record) {
@@ -360,36 +361,35 @@ bool StorageEngineImpl::_handleInternalIdents(
// Parse the documents here so that we can restart the build if the document doesn't
// contain all the necessary information to be able to resume building the index.
- if (doc.hasField("phase")) {
- ResumeIndexInfo resumeInfo;
- try {
- if (MONGO_unlikely(failToParseResumeIndexInfo.shouldFail())) {
- uasserted(ErrorCodes::FailPointEnabled,
- "failToParseResumeIndexInfo fail point is enabled");
- }
-
- resumeInfo = ResumeIndexInfo::parse(IDLParserErrorContext("ResumeIndexInfo"), doc);
- } catch (const DBException& e) {
- LOGV2(4916300, "Failed to parse resumable index info", "error"_attr = e.toStatus());
-
- // Ignore the error so that we can restart the index build instead of resume it. We
- // should drop the internal ident if we failed to parse.
- internalIdentsToDrop->insert(ident);
- return true;
+ ResumeIndexInfo resumeInfo;
+ try {
+ if (MONGO_unlikely(failToParseResumeIndexInfo.shouldFail())) {
+ uasserted(ErrorCodes::FailPointEnabled,
+ "failToParseResumeIndexInfo fail point is enabled");
}
- reconcileResult->indexBuildsToResume.push_back(resumeInfo);
+ resumeInfo = ResumeIndexInfo::parse(IDLParserErrorContext("ResumeIndexInfo"), doc);
+ } catch (const DBException& e) {
+ LOGV2(4916300, "Failed to parse resumable index info", "error"_attr = e.toStatus());
- // Once we have parsed the resume info, we can safely drop the internal ident.
+ // Ignore the error so that we can restart the index build instead of resume it. We
+ // should drop the internal ident if we failed to parse.
internalIdentsToDrop->insert(ident);
-
- LOGV2(4916301,
- "Found unfinished index build to resume",
- "buildUUID"_attr = resumeInfo.getBuildUUID(),
- "collectionUUID"_attr = resumeInfo.getCollectionUUID(),
- "phase"_attr = IndexBuildPhase_serializer(resumeInfo.getPhase()));
return true;
}
+
+ reconcileResult->indexBuildsToResume.push_back(resumeInfo);
+
+ // Once we have parsed the resume info, we can safely drop the internal ident.
+ internalIdentsToDrop->insert(ident);
+
+ LOGV2(4916301,
+ "Found unfinished index build to resume",
+ "buildUUID"_attr = resumeInfo.getBuildUUID(),
+ "collectionUUID"_attr = resumeInfo.getCollectionUUID(),
+ "phase"_attr = IndexBuildPhase_serializer(resumeInfo.getPhase()));
+
+ return true;
}
return false;
@@ -448,12 +448,12 @@ StatusWith<StorageEngine::ReconcileResult> StorageEngineImpl::reconcileCatalogAn
continue;
}
- if (_handleInternalIdents(opCtx,
- it,
- internalIdentReconcilePolicy,
- &reconcileResult,
- &internalIdentsToDrop,
- &allInternalIdents)) {
+ if (_handleInternalIdent(opCtx,
+ it,
+ internalIdentReconcilePolicy,
+ &reconcileResult,
+ &internalIdentsToDrop,
+ &allInternalIdents)) {
continue;
}
@@ -864,10 +864,18 @@ std::unique_ptr<TemporaryRecordStore> StorageEngineImpl::makeTemporaryRecordStor
OperationContext* opCtx) {
std::unique_ptr<RecordStore> rs =
_engine->makeTemporaryRecordStore(opCtx, _catalog->newInternalIdent());
- LOGV2_DEBUG(22258,
+ LOGV2_DEBUG(22258, 1, "Created temporary record store", "ident"_attr = rs->getIdent());
+ return std::make_unique<TemporaryKVRecordStore>(getEngine(), std::move(rs));
+}
+
+std::unique_ptr<TemporaryRecordStore>
+StorageEngineImpl::makeTemporaryRecordStoreForResumableIndexBuild(OperationContext* opCtx) {
+ std::unique_ptr<RecordStore> rs =
+ _engine->makeTemporaryRecordStore(opCtx, _catalog->newInternalResumableIndexBuildIdent());
+ LOGV2_DEBUG(4921500,
1,
- "created temporary record store: {rs_getIdent}",
- "rs_getIdent"_attr = rs->getIdent());
+ "Created temporary record store for resumable index build",
+ "ident"_attr = rs->getIdent());
return std::make_unique<TemporaryKVRecordStore>(getEngine(), std::move(rs));
}
diff --git a/src/mongo/db/storage/storage_engine_impl.h b/src/mongo/db/storage/storage_engine_impl.h
index 4761e1f3a38..7d71e5de128 100644
--- a/src/mongo/db/storage/storage_engine_impl.h
+++ b/src/mongo/db/storage/storage_engine_impl.h
@@ -113,6 +113,9 @@ public:
virtual std::unique_ptr<TemporaryRecordStore> makeTemporaryRecordStore(
OperationContext* opCtx) override;
+ virtual std::unique_ptr<TemporaryRecordStore> makeTemporaryRecordStoreForResumableIndexBuild(
+ OperationContext* opCtx) override;
+
virtual std::unique_ptr<TemporaryRecordStore> makeTemporaryRecordStoreFromExistingIdent(
OperationContext* opCtx, StringData ident) override;
@@ -386,12 +389,12 @@ private:
* Returns whether the given ident is an internal ident and if it should be dropped or used to
* resume an index build.
*/
- bool _handleInternalIdents(OperationContext* opCtx,
- const std::string& ident,
- InternalIdentReconcilePolicy internalIdentReconcilePolicy,
- ReconcileResult* reconcileResult,
- std::set<std::string>* internalIdentsToDrop,
- std::set<std::string>* allInternalIdents);
+ bool _handleInternalIdent(OperationContext* opCtx,
+ const std::string& ident,
+ InternalIdentReconcilePolicy internalIdentReconcilePolicy,
+ ReconcileResult* reconcileResult,
+ std::set<std::string>* internalIdentsToDrop,
+ std::set<std::string>* allInternalIdents);
class RemoveDBChange;
diff --git a/src/mongo/db/storage/storage_engine_mock.h b/src/mongo/db/storage/storage_engine_mock.h
index 3a4a14bd9e6..5c7078e2a2d 100644
--- a/src/mongo/db/storage/storage_engine_mock.h
+++ b/src/mongo/db/storage/storage_engine_mock.h
@@ -93,6 +93,10 @@ public:
std::unique_ptr<TemporaryRecordStore> makeTemporaryRecordStore(OperationContext* opCtx) final {
return {};
}
+ std::unique_ptr<TemporaryRecordStore> makeTemporaryRecordStoreForResumableIndexBuild(
+ OperationContext* opCtx) final {
+ return {};
+ }
std::unique_ptr<TemporaryRecordStore> makeTemporaryRecordStoreFromExistingIdent(
OperationContext* opCtx, StringData ident) final {
return {};