summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierlauro Sciarelli <pierlauro.sciarelli@mongodb.com>2023-04-21 09:30:22 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-04-21 10:00:12 +0000
commit4e904003697033ae1876838df3a3a81c5e390423 (patch)
treead8f30a85a2d4431ddb50817bfe28d53577d3346
parent6320d8fc17d90d563bdd8c879c080a81b083fd55 (diff)
downloadmongo-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.cpp18
-rw-r--r--src/mongo/db/cursor_manager.h11
-rw-r--r--src/mongo/db/s/metadata_manager.cpp18
-rw-r--r--src/mongo/dbtests/cursor_manager_test.cpp39
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