diff options
author | Pierlauro Sciarelli <pierlauro.sciarelli@mongodb.com> | 2023-04-21 09:30:22 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-04-21 10:00:12 +0000 |
commit | 4e904003697033ae1876838df3a3a81c5e390423 (patch) | |
tree | ad8f30a85a2d4431ddb50817bfe28d53577d3346 | |
parent | 6320d8fc17d90d563bdd8c879c080a81b083fd55 (diff) | |
download | mongo-4e904003697033ae1876838df3a3a81c5e390423.tar.gz |
SERVER-71792 Log list of cursors a range deletion is going to wait on
-rw-r--r-- | src/mongo/db/cursor_manager.cpp | 18 | ||||
-rw-r--r-- | src/mongo/db/cursor_manager.h | 11 | ||||
-rw-r--r-- | src/mongo/db/s/metadata_manager.cpp | 18 | ||||
-rw-r--r-- | src/mongo/dbtests/cursor_manager_test.cpp | 39 |
4 files changed, 78 insertions, 8 deletions
diff --git a/src/mongo/db/cursor_manager.cpp b/src/mongo/db/cursor_manager.cpp index 8d8164b8e11..f26f77ab50d 100644 --- a/src/mongo/db/cursor_manager.cpp +++ b/src/mongo/db/cursor_manager.cpp @@ -206,6 +206,24 @@ std::size_t CursorManager::timeoutCursors(OperationContext* opCtx, Date_t now) { return toDisposeWithoutMutex.size(); } +std::vector<CursorId> CursorManager::getCursorIdsForNamespace(const NamespaceString& nss) { + std::vector<CursorId> cursorIds; + + // Lock and inspect one partition at a time in order to avoid contention. It is acceptable for + // the output not to include info about cursors opened/closed while iterating. + for (size_t partitionId = 0; partitionId < kNumPartitions; ++partitionId) { + auto lockedPartition = _cursorMap->lockOnePartitionById(partitionId); + for (auto it = lockedPartition->begin(); it != lockedPartition->end(); ++it) { + auto* cursor = it->second; + if (cursor->nss() == nss) { + cursorIds.push_back(cursor->cursorid()); + } + } + } + + return cursorIds; +} + StatusWith<ClientCursorPin> CursorManager::pinCursor( OperationContext* opCtx, CursorId id, diff --git a/src/mongo/db/cursor_manager.h b/src/mongo/db/cursor_manager.h index 9d0b5a710a8..05854c7e17d 100644 --- a/src/mongo/db/cursor_manager.h +++ b/src/mongo/db/cursor_manager.h @@ -194,6 +194,17 @@ public: const SessionKiller::Matcher& matcher); /** + * Returns a vector of open cursor ids registered on the `nss`. The result doesn't include + * cursors registered for a different namespace but also acting on `nss` (e.g. in presence of + * sub-pipelines). + * + * Locks/inspects one partition at a time, hence the result might not include new cursors being + * opened on the namespace. The only guarantee is that the result will include any cursor opened + * before calling this method and not closed before iterating the partition holding it. + */ + std::vector<CursorId> getCursorIdsForNamespace(const NamespaceString& nss); + + /** * Set the CursorManager's ClockSource*. */ void setPreciseClockSource(ClockSource* preciseClockSource) { diff --git a/src/mongo/db/s/metadata_manager.cpp b/src/mongo/db/s/metadata_manager.cpp index 6bb87b819b8..1dd525d704d 100644 --- a/src/mongo/db/s/metadata_manager.cpp +++ b/src/mongo/db/s/metadata_manager.cpp @@ -36,6 +36,7 @@ #include "mongo/base/string_data.h" #include "mongo/bson/simple_bsonobj_comparator.h" #include "mongo/bson/util/builder.h" +#include "mongo/db/cursor_manager.h" #include "mongo/db/query/internal_plans.h" #include "mongo/db/range_arithmetic.h" #include "mongo/db/s/migration_util.h" @@ -276,14 +277,15 @@ SharedSemiFuture<void> MetadataManager::cleanUpRange(ChunkRange const& range, shouldDelayBeforeDeletion ? Seconds(orphanCleanupDelaySecs.load()) : Seconds(0); if (overlapMetadata) { - LOGV2_OPTIONS(21989, - {logv2::LogComponent::kShardingMigration}, - "Deletion of {namespace} range {range} will be scheduled after all possibly " - "dependent queries finish", - "Deletion of the collection's specified range will be scheduled after all " - "possibly dependent queries finish", - "namespace"_attr = _nss.ns(), - "range"_attr = redact(range.toString())); + const auto openCursorsIds = + CursorManager::get(_serviceContext)->getCursorIdsForNamespace(_nss); + LOGV2_INFO_OPTIONS( + 7179200, + {logv2::LogComponent::kShardingRangeDeleter}, + "Range deletion will be scheduled after all possibly dependent queries finish", + "namespace"_attr = _nss, + "range"_attr = range.toString(), + "cursorsDirectlyReferringTheNamespace"_attr = openCursorsIds); ++overlapMetadata->numContingentRangeDeletionTasks; // Schedule the range for deletion once the overlapping metadata object is destroyed // (meaning no more queries can be using the range) and obtain a future which will be diff --git a/src/mongo/dbtests/cursor_manager_test.cpp b/src/mongo/dbtests/cursor_manager_test.cpp index 1cc8ee1f535..f71e45fe2ec 100644 --- a/src/mongo/dbtests/cursor_manager_test.cpp +++ b/src/mongo/dbtests/cursor_manager_test.cpp @@ -753,5 +753,44 @@ TEST_F(CursorManagerTestCustomOpCtx, CursorsMarkedAsKilledAreReturnedForOpKeyLoo auto cursors = useCursorManager()->getCursorsForOpKeys({opKey}); ASSERT_EQ(cursors.size(), size_t(1)); } + +TEST_F(CursorManagerTestCustomOpCtx, + GetCursorIdsForNamespaceReturnsSingleEntryForMatchingNamespace) { + auto opCtx = _queryServiceContext->makeOperationContext(); + auto pinned = makeCursor(opCtx.get()); + auto cursorId = pinned.getCursor()->cursorid(); + auto cursorsForNamespace = useCursorManager()->getCursorIdsForNamespace(kTestNss); + ASSERT_EQUALS(cursorsForNamespace.size(), 1ull); + ASSERT_EQUALS(cursorsForNamespace[0], cursorId); +} + +TEST_F(CursorManagerTestCustomOpCtx, + GetCursorIdsForNamespaceReturnsMultipleEntriesForMatchingNamespace) { + auto opCtx = _queryServiceContext->makeOperationContext(); + auto pinned1 = makeCursor(opCtx.get()); + auto pinned2 = makeCursor(opCtx.get()); + auto cursorId1 = pinned1.getCursor()->cursorid(); + auto cursorId2 = pinned2.getCursor()->cursorid(); + auto cursorsForNamespace = useCursorManager()->getCursorIdsForNamespace(kTestNss); + ASSERT_EQUALS(cursorsForNamespace.size(), 2ull); + // The results for cursorsForNamespace won't necessarily be the same as the order of insertion. + std::set<CursorId> cursorsForNamespaceSet(cursorsForNamespace.begin(), + cursorsForNamespace.end()); + + ASSERT_EQUALS(cursorsForNamespaceSet.count(cursorId1), 1ull); + ASSERT_EQUALS(cursorsForNamespaceSet.count(cursorId2), 1ull); +} + +TEST_F(CursorManagerTestCustomOpCtx, + GetCursorIdsForNamespaceDoesNotReturnEntriesForNonMatchingNamespace) { + auto opCtx = _queryServiceContext->makeOperationContext(); + // Add a cursor for kTestNss. + auto pinned = makeCursor(opCtx.get()); + // Get cursors for a different NamespaceString. + auto cursorsForNamespace = + useCursorManager()->getCursorIdsForNamespace(NamespaceString("somerandom.nss")); + ASSERT_EQUALS(cursorsForNamespace.size(), 0ull); +} + } // namespace } // namespace mongo |