summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierlauro Sciarelli <pierlauro.sciarelli@mongodb.com>2023-02-09 11:50:46 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-02-09 17:32:40 +0000
commita691dacf5bca2d78714d4abebe18078e1473b485 (patch)
tree94f9808051037d6b364c476db696386da2ae62e5
parent6dad29fa64f0bab3468b18ec784f53027306c8d7 (diff)
downloadmongo-a691dacf5bca2d78714d4abebe18078e1473b485.tar.gz
SERVER-71792 Log list of cursors a range deletion is going to wait on
-rw-r--r--src/mongo/db/cursor_manager.cpp18
-rw-r--r--src/mongo/db/cursor_manager.h11
-rw-r--r--src/mongo/db/s/range_deleter_service_op_observer.cpp11
-rw-r--r--src/mongo/dbtests/cursor_manager_test.cpp39
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 fa85089ff26..61845775695 100644
--- a/src/mongo/dbtests/cursor_manager_test.cpp
+++ b/src/mongo/dbtests/cursor_manager_test.cpp
@@ -754,5 +754,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