diff options
author | Pierlauro Sciarelli <pierlauro.sciarelli@mongodb.com> | 2023-02-20 16:25:33 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-02-20 18:07:31 +0000 |
commit | 314825e8dfbbe246bc2e4ad0531f3ccdf73b2608 (patch) | |
tree | 3f9b183131050a39af3678e34360a92ef1bf51fb | |
parent | 89b0377ea5c62e5a72469d6072aaa146a700b2b6 (diff) | |
download | mongo-314825e8dfbbe246bc2e4ad0531f3ccdf73b2608.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/range_deleter_service_op_observer.cpp | 11 | ||||
-rw-r--r-- | src/mongo/dbtests/cursor_manager_test.cpp | 39 |
4 files changed, 79 insertions, 0 deletions
diff --git a/src/mongo/db/cursor_manager.cpp b/src/mongo/db/cursor_manager.cpp index 214c1c2bf3f..eb2e3dad8bb 100644 --- a/src/mongo/db/cursor_manager.cpp +++ b/src/mongo/db/cursor_manager.cpp @@ -186,6 +186,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 bce3b05fdea..ed5cdb4e876 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/range_deleter_service_op_observer.cpp b/src/mongo/db/s/range_deleter_service_op_observer.cpp index 7c0d0084963..93de39a2377 100644 --- a/src/mongo/db/s/range_deleter_service_op_observer.cpp +++ b/src/mongo/db/s/range_deleter_service_op_observer.cpp @@ -30,6 +30,7 @@ #include "mongo/db/s/range_deleter_service_op_observer.h" #include "mongo/db/catalog_raii.h" +#include "mongo/db/cursor_manager.h" #include "mongo/db/persistent_task_store.h" #include "mongo/db/s/collection_sharding_runtime.h" #include "mongo/db/s/range_deleter_service.h" @@ -54,6 +55,16 @@ void registerTaskWithOngoingQueriesOnOpLogEntryCommit(OperationContext* opCtx, rdt.getNss()) ->getOngoingQueriesCompletionFuture(rdt.getCollectionUuid(), rdt.getRange()) .semi(); + if (!waitForActiveQueriesToComplete.isReady()) { + const auto openCursorsIds = + CursorManager::get(opCtx)->getCursorIdsForNamespace(rdt.getNss()); + LOGV2_INFO( + 7179200, + "Range deletion will be scheduled after all possibly dependent queries finish", + "namespace"_attr = rdt.getNss(), + "range"_attr = rdt.getRange(), + "cursorsDirectlyReferringTheNamespace"_attr = openCursorsIds); + } (void)RangeDeleterService::get(opCtx)->registerTask( rdt, std::move(waitForActiveQueriesToComplete)); } catch (const DBException& ex) { diff --git a/src/mongo/dbtests/cursor_manager_test.cpp b/src/mongo/dbtests/cursor_manager_test.cpp index 4b634dc2db3..4eb9e1c12a2 100644 --- a/src/mongo/dbtests/cursor_manager_test.cpp +++ b/src/mongo/dbtests/cursor_manager_test.cpp @@ -752,5 +752,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 |