summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNeil Shweky <neilshweky@gmail.com>2021-10-27 13:52:45 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-10-27 14:22:28 +0000
commit106b96548c5214a8e246a1cf6ac005a3985c16d4 (patch)
tree9d60577e227bd4c34a6d7d156ecc5a61c63ef52e /src
parentdd41a99e2c177d5bd3a38229d85458117480c5d9 (diff)
downloadmongo-106b96548c5214a8e246a1cf6ac005a3985c16d4.tar.gz
SERVER-58352: Remove ClusterCursorManager::getNamespaceForCursorId(), and related simplifications
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/SConscript1
-rw-r--r--src/mongo/db/allocate_cursor_id.cpp65
-rw-r--r--src/mongo/db/allocate_cursor_id.h48
-rw-r--r--src/mongo/db/cursor_manager.cpp43
-rw-r--r--src/mongo/s/commands/cluster_killcursors_cmd.cpp5
-rw-r--r--src/mongo/s/commands/cluster_killoperations_cmd.cpp41
-rw-r--r--src/mongo/s/commands/cluster_map_reduce_agg.cpp2
-rw-r--r--src/mongo/s/query/cluster_cursor_manager.cpp373
-rw-r--r--src/mongo/s/query/cluster_cursor_manager.h91
-rw-r--r--src/mongo/s/query/cluster_cursor_manager_test.cpp362
-rw-r--r--src/mongo/s/query/cluster_find.cpp2
11 files changed, 352 insertions, 681 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index 2864d3b020f..188a9209ef6 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -1964,6 +1964,7 @@ env.Library(
env.Library(
target='generic_cursor',
source=[
+ 'allocate_cursor_id.cpp',
'generic_cursor.idl',
],
LIBDEPS=[
diff --git a/src/mongo/db/allocate_cursor_id.cpp b/src/mongo/db/allocate_cursor_id.cpp
new file mode 100644
index 00000000000..e9b8371aadf
--- /dev/null
+++ b/src/mongo/db/allocate_cursor_id.cpp
@@ -0,0 +1,65 @@
+/**
+ * Copyright (C) 2021-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#include "mongo/db/allocate_cursor_id.h"
+
+#include "mongo/util/assert_util.h"
+
+namespace mongo::generic_cursor {
+
+CursorId allocateCursorId(const std::function<bool(CursorId)>& pred, PseudoRandom& random) {
+ for (int i = 0; i < 10000; i++) {
+ CursorId id = random.nextInt64();
+
+ // A cursor id of zero is reserved to indicate that the cursor has been closed. If the
+ // random number generator gives us zero, then try again.
+ if (id == 0) {
+ continue;
+ }
+
+ // Avoid negative cursor ids by taking the absolute value. If the cursor id is the minimum
+ // representable negative number, then just generate another random id.
+ if (id == std::numeric_limits<CursorId>::min()) {
+ continue;
+ }
+ id = std::abs(id);
+
+ if (pred(id)) {
+ // The cursor id is not already in use, so return it.
+ return id;
+ }
+
+ // The cursor id is already in use. Generate another random id.
+ }
+
+ // We failed to generate a unique cursor id.
+ fassertFailed(17360);
+}
+
+} // namespace mongo::generic_cursor
diff --git a/src/mongo/db/allocate_cursor_id.h b/src/mongo/db/allocate_cursor_id.h
new file mode 100644
index 00000000000..f7a204c5816
--- /dev/null
+++ b/src/mongo/db/allocate_cursor_id.h
@@ -0,0 +1,48 @@
+/**
+ * Copyright (C) 2021-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+#include <functional>
+
+#include "mongo/db/cursor_id.h"
+#include "mongo/platform/random.h"
+
+namespace mongo::generic_cursor {
+
+/**
+ * Allocates a positive Cursor Id that satisfies 'pred', which checks that the CursorId is not
+ * already in use.
+ *
+ * The caller of this function is responsible for synchronization between the check of whether a
+ * cursor is already allocated in 'pred' and the creation of new cursors.
+ */
+CursorId allocateCursorId(const std::function<bool(CursorId)>& pred, PseudoRandom& random);
+
+} // namespace mongo::generic_cursor
diff --git a/src/mongo/db/cursor_manager.cpp b/src/mongo/db/cursor_manager.cpp
index c1728d78586..f9dbab4ad1a 100644
--- a/src/mongo/db/cursor_manager.cpp
+++ b/src/mongo/db/cursor_manager.cpp
@@ -37,6 +37,7 @@
#include "mongo/base/data_cursor.h"
#include "mongo/base/init.h"
+#include "mongo/db/allocate_cursor_id.h"
#include "mongo/db/audit.h"
#include "mongo/db/auth/authorization_checks.h"
#include "mongo/db/auth/authorization_session.h"
@@ -358,38 +359,6 @@ size_t CursorManager::numCursors() const {
return _cursorMap->size();
}
-CursorId CursorManager::allocateCursorId_inlock() {
- for (int i = 0; i < 10000; i++) {
- CursorId id = _random->nextInt64();
-
- // A cursor id of zero is reserved to indicate that the cursor has been closed. If the
- // random number generator gives us zero, then try again.
- if (id == 0) {
- continue;
- }
-
- // Avoid negative cursor ids by taking the absolute value. If the cursor id is the minimum
- // representable negative number, then just generate another random id.
- if (id == std::numeric_limits<CursorId>::min()) {
- continue;
- }
- id = std::abs(id);
-
- auto partition = _cursorMap->lockOnePartition(id);
- if (partition->count(id) == 0) {
- // The cursor id is not already in use, so return it. Even though we drop the lock on
- // the '_cursorMap' partition, another thread cannot register a cursor with the same id
- // because we still hold '_registrationLock'.
- return id;
- }
-
- // The cursor id is already in use. Generate another random id.
- }
-
- // We failed to generate a unique cursor id.
- fassertFailed(17360);
-}
-
ClientCursorPin CursorManager::registerCursor(OperationContext* opCtx,
ClientCursorParams&& cursorParams) {
// Avoid computing the current time within the critical section.
@@ -403,7 +372,15 @@ ClientCursorPin CursorManager::registerCursor(OperationContext* opCtx,
// Note we must hold the registration lock from now until insertion into '_cursorMap' to ensure
// we don't insert two cursors with the same cursor id.
stdx::lock_guard<SimpleMutex> lock(_registrationLock);
- CursorId cursorId = allocateCursorId_inlock();
+ CursorId cursorId = generic_cursor::allocateCursorId(
+ [&](CursorId cursorId) -> bool {
+ // Even though we drop the lock on the '_cursorMap' partition, another thread cannot
+ // register a cursor with the same id because we still hold '_registrationLock'.
+ auto partition = _cursorMap->lockOnePartition(cursorId);
+ return partition->count(cursorId) == 0;
+ },
+ *_random);
+
std::unique_ptr<ClientCursor, ClientCursor::Deleter> clientCursor(
new ClientCursor(std::move(cursorParams), cursorId, opCtx, now));
diff --git a/src/mongo/s/commands/cluster_killcursors_cmd.cpp b/src/mongo/s/commands/cluster_killcursors_cmd.cpp
index c05ac76d7fb..716107f43d1 100644
--- a/src/mongo/s/commands/cluster_killcursors_cmd.cpp
+++ b/src/mongo/s/commands/cluster_killcursors_cmd.cpp
@@ -50,12 +50,13 @@ struct ClusterKillCursorsCmd {
};
return Grid::get(opCtx)->getCursorManager()->checkAuthForKillCursors(
- opCtx, nss, cursorId, authChecker);
+ opCtx, cursorId, authChecker);
}
+
static Status doKillCursor(OperationContext* opCtx,
const NamespaceString& nss,
CursorId cursorId) {
- return Grid::get(opCtx)->getCursorManager()->killCursor(opCtx, nss, cursorId);
+ return Grid::get(opCtx)->getCursorManager()->killCursor(opCtx, cursorId);
}
};
KillCursorsCmdBase<ClusterKillCursorsCmd> clusterKillCursorsCmd;
diff --git a/src/mongo/s/commands/cluster_killoperations_cmd.cpp b/src/mongo/s/commands/cluster_killoperations_cmd.cpp
index d636fc58adc..0dfc1676438 100644
--- a/src/mongo/s/commands/cluster_killoperations_cmd.cpp
+++ b/src/mongo/s/commands/cluster_killoperations_cmd.cpp
@@ -32,6 +32,7 @@
#include "mongo/db/commands/killoperations_common.h"
#include "mongo/s/grid.h"
#include "mongo/s/query/cluster_cursor_manager.h"
+#include "mongo/stdx/unordered_set.h"
namespace mongo {
@@ -39,24 +40,28 @@ class ClusterKillOperationsCmd : public KillOperationsCmdBase<ClusterKillOperati
public:
static void killCursors(OperationContext* opCtx, const std::vector<OperationKey>& opKeys) {
auto clusterCursorManager = Grid::get(opCtx)->getCursorManager();
- for (auto& cursorId : clusterCursorManager->getCursorsForOpKeys(opKeys)) {
- LOGV2(4664805, "Attempting to kill cursor", "cursorId"_attr = cursorId);
- auto cursorNss = clusterCursorManager->getNamespaceForCursorId(cursorId);
- if (!cursorNss) {
- // The cursor must have already been killed.
- continue;
- }
-
- auto status = clusterCursorManager->killCursor(opCtx, cursorNss.get(), cursorId);
-
- if (!status.isOK()) {
- LOGV2(4664806,
- "Failed to kill the cursor ",
- "error"_attr = redact(status.toString()));
- } else {
- LOGV2(4664807, "Killed cursor", "cursorId"_attr = cursorId);
- }
- }
+ stdx::unordered_set<UUID, UUID::Hash> opKeySet(opKeys.begin(), opKeys.end());
+
+ std::size_t numCursorsKilled = clusterCursorManager->killCursorsSatisfying(
+ opCtx,
+ [&opKeySet](CursorId cursorId, const ClusterCursorManager::CursorEntry& entry) -> bool {
+ if (!entry.getOperationKey()) {
+ return false;
+ }
+
+ bool hasOpKey = opKeySet.find(*entry.getOperationKey()) != opKeySet.end();
+ if (hasOpKey) {
+ LOGV2(4664805,
+ "Attempting to kill cursor",
+ "cursorId"_attr = cursorId,
+ "opKey"_attr = entry.getOperationKey());
+ }
+
+ return hasOpKey;
+ });
+
+ LOGV2(
+ 4664806, "_killOperations command killed cursors", "numKilled"_attr = numCursorsKilled);
}
} ClusterKillOperationsCmd;
diff --git a/src/mongo/s/commands/cluster_map_reduce_agg.cpp b/src/mongo/s/commands/cluster_map_reduce_agg.cpp
index 770e490648f..d478ef08d48 100644
--- a/src/mongo/s/commands/cluster_map_reduce_agg.cpp
+++ b/src/mongo/s/commands/cluster_map_reduce_agg.cpp
@@ -253,7 +253,7 @@ bool runAggregationMapReduce(OperationContext* opCtx,
// response.
if (aggResults["cursor"]["id"].Long() != 0) {
uassertStatusOK(Grid::get(opCtx)->getCursorManager()->killCursor(
- opCtx, parsedMr.getNamespace(), aggResults["cursor"]["id"].Long()));
+ opCtx, aggResults["cursor"]["id"].Long()));
uasserted(31301, "MapReduce inline results are greater than the allowed 16MB limit");
}
diff --git a/src/mongo/s/query/cluster_cursor_manager.cpp b/src/mongo/s/query/cluster_cursor_manager.cpp
index 4087d33d74f..1209d709e22 100644
--- a/src/mongo/s/query/cluster_cursor_manager.cpp
+++ b/src/mongo/s/query/cluster_cursor_manager.cpp
@@ -36,6 +36,7 @@
#include <set>
+#include "mongo/db/allocate_cursor_id.h"
#include "mongo/db/curop.h"
#include "mongo/db/kill_sessions_common.h"
#include "mongo/db/logical_session_cache.h"
@@ -49,32 +50,17 @@ namespace mongo {
namespace {
//
-// Helpers to construct a user-friendly error Status from a (nss, cursorId) pair.
+// Helpers to construct a user-friendly error Status from a cursorId.
//
-Status cursorNotFoundStatus(const NamespaceString& nss, CursorId cursorId) {
+Status cursorNotFoundStatus(CursorId cursorId) {
return {ErrorCodes::CursorNotFound,
- str::stream() << "Cursor not found (namespace: '" << nss.ns() << "', id: " << cursorId
- << ")."};
+ str::stream() << "Cursor not found (id: " << cursorId << ")."};
}
-Status cursorInUseStatus(const NamespaceString& nss, CursorId cursorId) {
+Status cursorInUseStatus(CursorId cursorId) {
return {ErrorCodes::CursorInUse,
- str::stream() << "Cursor already in use (namespace: '" << nss.ns()
- << "', id: " << cursorId << ")."};
-}
-
-//
-// CursorId is a 64-bit type, made up of a 32-bit prefix and a 32-bit suffix. The below helpers
-// convert between a CursorId and its prefix/suffix.
-//
-
-CursorId createCursorId(uint32_t prefix, uint32_t suffix) {
- return (static_cast<uint64_t>(prefix) << 32) | suffix;
-}
-
-uint32_t extractPrefixFromCursorId(CursorId cursorId) {
- return static_cast<uint64_t>(cursorId) >> 32;
+ str::stream() << "Cursor already in use (id: " << cursorId << ")."};
}
} // namespace
@@ -118,7 +104,7 @@ void ClusterCursorManager::PinnedCursor::returnCursor(CursorState cursorState) {
invariant(_cursor);
// Note that unpinning a cursor transfers ownership of the underlying ClusterClientCursor object
// back to the manager.
- _manager->checkInCursor(std::move(_cursor), _nss, _cursorId, cursorState);
+ _manager->checkInCursor(std::move(_cursor), _cursorId, cursorState);
*this = PinnedCursor();
}
@@ -157,8 +143,7 @@ ClusterCursorManager::ClusterCursorManager(ClockSource* clockSource)
}
ClusterCursorManager::~ClusterCursorManager() {
- invariant(_cursorIdPrefixToNamespaceMap.empty());
- invariant(_namespaceToContainerMap.empty());
+ invariant(_cursorEntryMap.empty());
}
void ClusterCursorManager::shutdown(OperationContext* opCtx) {
@@ -191,58 +176,26 @@ StatusWith<CursorId> ClusterCursorManager::registerCursor(
invariant(cursor);
cursor->setLeftoverMaxTimeMicros(opCtx->getRemainingMaxTimeMicros());
- // Find the CursorEntryContainer for this namespace. If none exists, create one.
- auto nsToContainerIt = _namespaceToContainerMap.find(nss);
- if (nsToContainerIt == _namespaceToContainerMap.end()) {
- uint32_t containerPrefix = 0;
- do {
- // The server has always generated positive values for CursorId (which is a signed
- // type), so we use std::abs() here on the prefix for consistency with this historical
- // behavior. If the random number generated is INT_MIN, calling std::abs on it is
- // undefined behavior on 2's complement systems so we need to generate a new number.
- int32_t randomNumber = 0;
- do {
- randomNumber = _pseudoRandom.nextInt32();
- } while (randomNumber == std::numeric_limits<int32_t>::min());
- containerPrefix = static_cast<uint32_t>(std::abs(randomNumber));
- } while (_cursorIdPrefixToNamespaceMap.count(containerPrefix) > 0);
- _cursorIdPrefixToNamespaceMap[containerPrefix] = nss;
-
- auto emplaceResult =
- _namespaceToContainerMap.emplace(nss, CursorEntryContainer(containerPrefix));
- invariant(emplaceResult.second);
- invariant(_namespaceToContainerMap.size() == _cursorIdPrefixToNamespaceMap.size());
-
- nsToContainerIt = emplaceResult.first;
- } else {
- invariant(!nsToContainerIt->second.entryMap.empty()); // If exists, shouldn't be empty.
- }
- CursorEntryContainer& container = nsToContainerIt->second;
-
- // Generate a CursorId (which can't be the invalid value zero).
- CursorEntryMap& entryMap = container.entryMap;
- CursorId cursorId = 0;
- do {
- const uint32_t cursorSuffix = static_cast<uint32_t>(_pseudoRandom.nextInt32());
- cursorId = createCursorId(container.containerPrefix, cursorSuffix);
- } while (cursorId == 0 || entryMap.count(cursorId) > 0);
+ auto cursorId = generic_cursor::allocateCursorId(
+ [&](CursorId cursorId) -> bool { return _cursorEntryMap.count(cursorId) == 0; },
+ _pseudoRandom);
// Create a new CursorEntry and register it in the CursorEntryContainer's map.
- auto emplaceResult = entryMap.emplace(cursorId,
- CursorEntry(std::move(cursor),
- cursorType,
- cursorLifetime,
- now,
- authenticatedUsers,
- opCtx->getClient()->getUUID(),
- opCtx->getOperationKey()));
+ auto emplaceResult = _cursorEntryMap.emplace(cursorId,
+ CursorEntry(std::move(cursor),
+ cursorType,
+ cursorLifetime,
+ now,
+ authenticatedUsers,
+ opCtx->getClient()->getUUID(),
+ opCtx->getOperationKey(),
+ nss));
invariant(emplaceResult.second);
return cursorId;
}
StatusWith<ClusterCursorManager::PinnedCursor> ClusterCursorManager::checkOutCursor(
- const NamespaceString& nss,
CursorId cursorId,
OperationContext* opCtx,
AuthzCheckFn authChecker,
@@ -255,9 +208,9 @@ StatusWith<ClusterCursorManager::PinnedCursor> ClusterCursorManager::checkOutCur
"Cannot check out cursor as we are in the process of shutting down");
}
- CursorEntry* entry = _getEntry(lk, nss, cursorId);
+ CursorEntry* entry = _getEntry(lk, cursorId);
if (!entry) {
- return cursorNotFoundStatus(nss, cursorId);
+ return cursorNotFoundStatus(cursorId);
}
// Check if the user is coauthorized to access this cursor.
@@ -276,7 +229,7 @@ StatusWith<ClusterCursorManager::PinnedCursor> ClusterCursorManager::checkOutCur
}
if (entry->getOperationUsingCursor()) {
- return cursorInUseStatus(nss, cursorId);
+ return cursorInUseStatus(cursorId);
}
auto cursorGuard = entry->releaseCursor(opCtx);
@@ -294,11 +247,10 @@ StatusWith<ClusterCursorManager::PinnedCursor> ClusterCursorManager::checkOutCur
CurOp::get(opCtx)->debug().queryHash = cursorGuard->getQueryHash();
- return PinnedCursor(this, std::move(cursorGuard), nss, cursorId);
+ return PinnedCursor(this, std::move(cursorGuard), entry->getNamespace(), cursorId);
}
void ClusterCursorManager::checkInCursor(std::unique_ptr<ClusterClientCursor> cursor,
- const NamespaceString& nss,
CursorId cursorId,
CursorState cursorState) {
invariant(cursor);
@@ -313,7 +265,7 @@ void ClusterCursorManager::checkInCursor(std::unique_ptr<ClusterClientCursor> cu
stdx::unique_lock<Latch> lk(_mutex);
- CursorEntry* entry = _getEntry(lk, nss, cursorId);
+ CursorEntry* entry = _getEntry(lk, cursorId);
invariant(entry);
// killPending will be true if killCursor() was called while the cursor was in use.
@@ -329,18 +281,17 @@ void ClusterCursorManager::checkInCursor(std::unique_ptr<ClusterClientCursor> cu
// After detaching the cursor, the entry will be destroyed.
entry = nullptr;
- detachAndKillCursor(std::move(lk), opCtx, nss, cursorId);
+ detachAndKillCursor(std::move(lk), opCtx, cursorId);
}
Status ClusterCursorManager::checkAuthForKillCursors(OperationContext* opCtx,
- const NamespaceString& nss,
CursorId cursorId,
AuthzCheckFn authChecker) {
stdx::lock_guard<Latch> lk(_mutex);
- auto entry = _getEntry(lk, nss, cursorId);
+ auto entry = _getEntry(lk, cursorId);
if (!entry) {
- return cursorNotFoundStatus(nss, cursorId);
+ return cursorNotFoundStatus(cursorId);
}
// Note that getAuthenticatedUsers() is thread-safe, so it's okay to call even if there's
@@ -359,16 +310,14 @@ void ClusterCursorManager::killOperationUsingCursor(WithLock, CursorEntry* entry
// operation is done.
}
-Status ClusterCursorManager::killCursor(OperationContext* opCtx,
- const NamespaceString& nss,
- CursorId cursorId) {
+Status ClusterCursorManager::killCursor(OperationContext* opCtx, CursorId cursorId) {
invariant(opCtx);
stdx::unique_lock<Latch> lk(_mutex);
- CursorEntry* entry = _getEntry(lk, nss, cursorId);
+ CursorEntry* entry = _getEntry(lk, cursorId);
if (!entry) {
- return cursorNotFoundStatus(nss, cursorId);
+ return cursorNotFoundStatus(cursorId);
}
// Interrupt any operation currently using the cursor, unless if it's the current operation.
@@ -381,7 +330,7 @@ Status ClusterCursorManager::killCursor(OperationContext* opCtx,
}
// No one is using the cursor, so we destroy it.
- detachAndKillCursor(std::move(lk), opCtx, nss, cursorId);
+ detachAndKillCursor(std::move(lk), opCtx, cursorId);
// We no longer hold the lock here.
@@ -390,9 +339,8 @@ Status ClusterCursorManager::killCursor(OperationContext* opCtx,
void ClusterCursorManager::detachAndKillCursor(stdx::unique_lock<Latch> lk,
OperationContext* opCtx,
- const NamespaceString& nss,
CursorId cursorId) {
- auto detachedCursorGuard = _detachCursor(lk, opCtx, nss, cursorId);
+ auto detachedCursorGuard = _detachCursor(lk, opCtx, cursorId);
invariant(detachedCursorGuard.getStatus());
// Deletion of the cursor can happen out of the lock.
@@ -434,39 +382,29 @@ std::size_t ClusterCursorManager::killCursorsSatisfying(
std::size_t nKilled = 0;
std::vector<ClusterClientCursorGuard> cursorsToDestroy;
- auto nsContainerIt = _namespaceToContainerMap.begin();
- while (nsContainerIt != _namespaceToContainerMap.end()) {
- auto&& entryMap = nsContainerIt->second.entryMap;
- auto cursorIdEntryIt = entryMap.begin();
- while (cursorIdEntryIt != entryMap.end()) {
- auto cursorId = cursorIdEntryIt->first;
- auto& entry = cursorIdEntryIt->second;
-
- if (!pred(cursorId, entry)) {
- ++cursorIdEntryIt;
- continue;
- }
-
- ++nKilled;
-
- if (entry.getOperationUsingCursor()) {
- // Mark the OperationContext using the cursor as killed, and move on.
- killOperationUsingCursor(lk, &entry);
- ++cursorIdEntryIt;
- continue;
- }
+ auto cursorIdEntryIt = _cursorEntryMap.begin();
+ while (cursorIdEntryIt != _cursorEntryMap.end()) {
+ auto cursorId = cursorIdEntryIt->first;
+ auto& entry = cursorIdEntryIt->second;
+
+ if (!pred(cursorId, entry)) {
+ ++cursorIdEntryIt;
+ continue;
+ }
- cursorsToDestroy.push_back(entry.releaseCursor(opCtx));
+ ++nKilled;
- // Destroy the entry and set the iterator to the next element.
- entryMap.erase(cursorIdEntryIt++);
+ if (entry.getOperationUsingCursor()) {
+ // Mark the OperationContext using the cursor as killed, and move on.
+ killOperationUsingCursor(lk, &entry);
+ ++cursorIdEntryIt;
+ continue;
}
- if (entryMap.empty()) {
- nsContainerIt = eraseContainer(nsContainerIt);
- } else {
- ++nsContainerIt;
- }
+ cursorsToDestroy.push_back(entry.releaseCursor(opCtx));
+
+ // Destroy the entry and set the iterator to the next element.
+ _cursorEntryMap.erase(cursorIdEntryIt++);
}
// Ensure cursors are killed outside the lock, as killing may require waiting for callbacks to
@@ -486,28 +424,24 @@ ClusterCursorManager::Stats ClusterCursorManager::stats() const {
Stats stats;
- for (auto& nsContainerPair : _namespaceToContainerMap) {
- for (auto& cursorIdEntryPair : nsContainerPair.second.entryMap) {
- const CursorEntry& entry = cursorIdEntryPair.second;
-
- if (entry.isKillPending()) {
- // Killed cursors do not count towards the number of pinned cursors or the number of
- // open cursors.
- continue;
- }
+ for (auto&& [cursorId, entry] : _cursorEntryMap) {
+ if (entry.isKillPending()) {
+ // Killed cursors do not count towards the number of pinned cursors or the number of
+ // open cursors.
+ continue;
+ }
- if (entry.getOperationUsingCursor()) {
- ++stats.cursorsPinned;
- }
+ if (entry.getOperationUsingCursor()) {
+ ++stats.cursorsPinned;
+ }
- switch (entry.getCursorType()) {
- case CursorType::SingleTarget:
- ++stats.cursorsSingleTarget;
- break;
- case CursorType::MultiTarget:
- ++stats.cursorsMultiTarget;
- break;
- }
+ switch (entry.getCursorType()) {
+ case CursorType::SingleTarget:
+ ++stats.cursorsSingleTarget;
+ break;
+ case CursorType::MultiTarget:
+ ++stats.cursorsMultiTarget;
+ break;
}
}
@@ -517,19 +451,15 @@ ClusterCursorManager::Stats ClusterCursorManager::stats() const {
void ClusterCursorManager::appendActiveSessions(LogicalSessionIdSet* lsids) const {
stdx::lock_guard<Latch> lk(_mutex);
- for (const auto& nsContainerPair : _namespaceToContainerMap) {
- for (const auto& cursorIdEntryPair : nsContainerPair.second.entryMap) {
- const CursorEntry& entry = cursorIdEntryPair.second;
-
- if (entry.isKillPending()) {
- // Don't include sessions for killed cursors.
- continue;
- }
+ for (auto&& [cursorId, entry] : _cursorEntryMap) {
+ if (entry.isKillPending()) {
+ // Don't include sessions for killed cursors.
+ continue;
+ }
- auto lsid = entry.getLsid();
- if (lsid) {
- lsids->insert(*lsid);
- }
+ auto lsid = entry.getLsid();
+ if (lsid) {
+ lsids->insert(*lsid);
}
}
}
@@ -560,40 +490,30 @@ std::vector<GenericCursor> ClusterCursorManager::getIdleCursors(
AuthorizationSession* ctxAuth = AuthorizationSession::get(opCtx->getClient());
- for (const auto& nsContainerPair : _namespaceToContainerMap) {
- for (const auto& cursorIdEntryPair : nsContainerPair.second.entryMap) {
-
- const CursorEntry& entry = cursorIdEntryPair.second;
- // If auth is enabled, and userMode is allUsers, check if the current user has
- // permission to see this cursor.
- if (ctxAuth->getAuthorizationManager().isAuthEnabled() &&
- userMode == MongoProcessInterface::CurrentOpUserMode::kExcludeOthers &&
- !ctxAuth->isCoauthorizedWith(entry.getAuthenticatedUsers())) {
- continue;
- }
- if (entry.isKillPending() || entry.getOperationUsingCursor()) {
- // Don't include sessions for killed or pinned cursors.
- continue;
- }
-
- cursors.emplace_back(
- entry.cursorToGenericCursor(cursorIdEntryPair.first, nsContainerPair.first));
+ for (auto&& [cursorId, entry] : _cursorEntryMap) {
+ // If auth is enabled, and userMode is allUsers, check if the current user has
+ // permission to see this cursor.
+ if (ctxAuth->getAuthorizationManager().isAuthEnabled() &&
+ userMode == MongoProcessInterface::CurrentOpUserMode::kExcludeOthers &&
+ !ctxAuth->isCoauthorizedWith(entry.getAuthenticatedUsers())) {
+ continue;
+ }
+ if (entry.isKillPending() || entry.getOperationUsingCursor()) {
+ // Don't include sessions for killed or pinned cursors.
+ continue;
}
+
+ cursors.emplace_back(entry.cursorToGenericCursor(cursorId, entry.getNamespace()));
}
+
return cursors;
}
std::pair<Status, int> ClusterCursorManager::killCursorsWithMatchingSessions(
OperationContext* opCtx, const SessionKiller::Matcher& matcher) {
auto eraser = [&](ClusterCursorManager& mgr, CursorId id) {
- auto cursorNss = getNamespaceForCursorId(id);
- if (!cursorNss) {
- // The cursor manager couldn't find a namespace associated with 'id'. This means the
- // cursor must have already been killed, so we have no more work to do.
- return;
- }
- uassertStatusOK(mgr.killCursor(opCtx, *cursorNss, id));
+ uassertStatusOK(mgr.killCursor(opCtx, id));
LOGV2(22838, "Killing cursor as part of killing session(s)", "cursorId"_attr = id);
};
@@ -609,131 +529,48 @@ stdx::unordered_set<CursorId> ClusterCursorManager::getCursorsForSession(
stdx::unordered_set<CursorId> cursorIds;
- for (auto&& nsContainerPair : _namespaceToContainerMap) {
- for (auto&& [cursorId, entry] : nsContainerPair.second.entryMap) {
- if (entry.isKillPending()) {
- // Don't include sessions for killed cursors.
- continue;
- }
-
- auto cursorLsid = entry.getLsid();
- if (lsid == cursorLsid) {
- cursorIds.insert(cursorId);
- }
+ for (auto&& [cursorId, entry] : _cursorEntryMap) {
+ if (entry.isKillPending()) {
+ // Don't include sessions for killed cursors.
+ continue;
}
- }
-
- return cursorIds;
-}
-
-stdx::unordered_set<CursorId> ClusterCursorManager::getCursorsForOpKeys(
- std::vector<OperationKey> opKeys) const {
- stdx::lock_guard<Latch> lk(_mutex);
-
- stdx::unordered_set<CursorId> cursorIds;
- // While we could maintain a cached mapping of OperationKey to CursorID to increase performance,
- // this approach was chosen given that 1) mongos will not have as many open cursors as a shard
- // and 2) mongos performance has historically not been a bottleneck.
- for (auto&& opKey : opKeys) {
- for (auto&& nsContainerPair : _namespaceToContainerMap) {
- for (auto&& [cursorId, entry] : nsContainerPair.second.entryMap) {
- if (entry.isKillPending()) {
- // Don't include any killed cursors.
- continue;
- }
-
- if (opKey == entry.getOperationKey()) {
- cursorIds.insert(cursorId);
- }
- }
+ auto cursorLsid = entry.getLsid();
+ if (lsid == cursorLsid) {
+ cursorIds.insert(cursorId);
}
}
return cursorIds;
}
-boost::optional<NamespaceString> ClusterCursorManager::getNamespaceForCursorId(
- CursorId cursorId) const {
- stdx::lock_guard<Latch> lk(_mutex);
-
- const auto it = _cursorIdPrefixToNamespaceMap.find(extractPrefixFromCursorId(cursorId));
- if (it == _cursorIdPrefixToNamespaceMap.end()) {
- return boost::none;
- }
- return it->second;
-}
-
-auto ClusterCursorManager::_getEntry(WithLock, NamespaceString const& nss, CursorId cursorId)
- -> CursorEntry* {
-
- auto nsToContainerIt = _namespaceToContainerMap.find(nss);
- if (nsToContainerIt == _namespaceToContainerMap.end()) {
- return nullptr;
- }
- CursorEntryMap& entryMap = nsToContainerIt->second.entryMap;
- auto entryMapIt = entryMap.find(cursorId);
- if (entryMapIt == entryMap.end()) {
+auto ClusterCursorManager::_getEntry(WithLock, CursorId cursorId) -> CursorEntry* {
+ auto entryMapIt = _cursorEntryMap.find(cursorId);
+ if (entryMapIt == _cursorEntryMap.end()) {
return nullptr;
}
return &entryMapIt->second;
}
-auto ClusterCursorManager::eraseContainer(NssToCursorContainerMap::iterator it)
- -> NssToCursorContainerMap::iterator {
- auto&& container = it->second;
- auto&& entryMap = container.entryMap;
- invariant(entryMap.empty());
-
- // This was the last cursor remaining in the given namespace. Erase all state associated
- // with this namespace.
- size_t numDeleted = _cursorIdPrefixToNamespaceMap.erase(container.containerPrefix);
- if (numDeleted != 1) {
- LOGV2_ERROR(
- 4786901,
- "Error attempting to erase CursorEntryContainer for nss {nss} and containerPrefix"
- "{prefix}. Could not find containerPrefix in map from cursor ID prefix to nss. "
- "Expected 'numDeleted' to be 1, but got {actualNumDeleted}",
- "Error attempting to erase CursorEntryContainer. Could not find containerPrefix in map "
- "from cursor id prefix to namespace string.",
- "nss"_attr = it->first,
- "prefix"_attr = container.containerPrefix,
- "actualNumDeleted"_attr = numDeleted);
- MONGO_UNREACHABLE;
- }
- const auto nssRemoved = it->first;
- _namespaceToContainerMap.erase(it++);
-
- invariant(_namespaceToContainerMap.size() == _cursorIdPrefixToNamespaceMap.size());
- return it;
-}
-
StatusWith<ClusterClientCursorGuard> ClusterCursorManager::_detachCursor(WithLock lk,
OperationContext* opCtx,
- const NamespaceString& nss,
CursorId cursorId) {
- CursorEntry* entry = _getEntry(lk, nss, cursorId);
+ CursorEntry* entry = _getEntry(lk, cursorId);
if (!entry) {
- return cursorNotFoundStatus(nss, cursorId);
+ return cursorNotFoundStatus(cursorId);
}
if (entry->getOperationUsingCursor()) {
- return cursorInUseStatus(nss, cursorId);
+ return cursorInUseStatus(cursorId);
}
// Transfer ownership away from the entry.
ClusterClientCursorGuard cursor = entry->releaseCursor(opCtx);
// Destroy the entry.
- auto nsToContainerIt = _namespaceToContainerMap.find(nss);
- invariant(nsToContainerIt != _namespaceToContainerMap.end());
- CursorEntryMap& entryMap = nsToContainerIt->second.entryMap;
- size_t eraseResult = entryMap.erase(cursorId);
+ size_t eraseResult = _cursorEntryMap.erase(cursorId);
invariant(1 == eraseResult);
- if (entryMap.empty()) {
- eraseContainer(nsToContainerIt);
- }
return std::move(cursor);
}
diff --git a/src/mongo/s/query/cluster_cursor_manager.h b/src/mongo/s/query/cluster_cursor_manager.h
index 7df393e3403..be10b0d60bd 100644
--- a/src/mongo/s/query/cluster_cursor_manager.h
+++ b/src/mongo/s/query/cluster_cursor_manager.h
@@ -228,13 +228,15 @@ public:
Date_t lastActive,
UserNameIterator authenticatedUsersIter,
UUID clientUUID,
- boost::optional<OperationKey> opKey)
+ boost::optional<OperationKey> opKey,
+ NamespaceString nss)
: _cursor(std::move(cursor)),
_cursorType(cursorType),
_cursorLifetime(cursorLifetime),
_lastActive(lastActive),
_lsid(_cursor->getLsid()),
_opKey(std::move(opKey)),
+ _nss(std::move(nss)),
_originatingClient(std::move(clientUUID)),
_authenticatedUsers(
userNameIteratorToContainer<std::vector<UserName>>(authenticatedUsersIter)) {
@@ -279,6 +281,10 @@ public:
return _opKey;
}
+ const NamespaceString& getNamespace() const {
+ return _nss;
+ }
+
/**
* Returns a cursor guard holding the cursor owned by this CursorEntry for an operation to
* use. Only one operation may use the cursor at a time, so callers should check that
@@ -344,6 +350,8 @@ public:
*/
boost::optional<OperationKey> _opKey;
+ NamespaceString _nss;
+
/**
* Current operation using the cursor. Non-null if the cursor is checked out.
*/
@@ -429,8 +437,7 @@ public:
* Does not block.
*/
enum AuthCheck { kCheckSession = true, kNoCheckSession = false };
- StatusWith<PinnedCursor> checkOutCursor(const NamespaceString& nss,
- CursorId cursorId,
+ StatusWith<PinnedCursor> checkOutCursor(CursorId cursorId,
OperationContext* opCtx,
AuthzCheckFn authChecker,
AuthCheck checkSessionAuth = kCheckSession);
@@ -440,7 +447,6 @@ public:
* list of users authorized to use the cursor. Will propagate the return value of authChecker.
*/
Status checkAuthForKillCursors(OperationContext* opCtx,
- const NamespaceString& nss,
CursorId cursorId,
AuthzCheckFn authChecker);
@@ -457,7 +463,7 @@ public:
*
* May block waiting for other threads to finish, but does not block on the network.
*/
- Status killCursor(OperationContext* opCtx, const NamespaceString& nss, CursorId cursorId);
+ Status killCursor(OperationContext* opCtx, CursorId cursorId);
/**
* Kill the cursors satisfying the given predicate. Returns the number of cursors killed.
@@ -510,24 +516,6 @@ public:
*/
stdx::unordered_set<CursorId> getCursorsForSession(LogicalSessionId lsid) const;
- /*
- * Returns a list of all open cursors for the given set of OperationKeys.
- */
- stdx::unordered_set<CursorId> getCursorsForOpKeys(std::vector<OperationKey>) const;
-
- /**
- * Returns the namespace associated with the given cursor id, by examining the 'namespace
- * prefix' portion of the cursor id. A cursor with the given cursor id need not actually exist.
- * If no such namespace is associated with the 'namespace prefix' portion of the cursor id,
- * returns boost::none.
- *
- * This method is deprecated. Use only when a cursor needs to be operated on in cases where a
- * namespace is not available (e.g. OP_KILL_CURSORS).
- *
- * Does not block.
- */
- boost::optional<NamespaceString> getNamespaceForCursorId(CursorId cursorId) const;
-
void incrementCursorsTimedOut(size_t inc) {
_cursorsTimedOut += inc;
}
@@ -537,9 +525,7 @@ public:
}
private:
- struct CursorEntryContainer;
using CursorEntryMap = stdx::unordered_map<CursorId, CursorEntry>;
- using NssToCursorContainerMap = stdx::unordered_map<NamespaceString, CursorEntryContainer>;
/**
* Transfers ownership of the given pinned cursor back to the manager, and moves the cursor to
@@ -553,7 +539,6 @@ private:
* back in.
*/
void checkInCursor(std::unique_ptr<ClusterClientCursor> cursor,
- const NamespaceString& nss,
CursorId cursorId,
CursorState cursorState);
@@ -562,7 +547,6 @@ private:
*/
void detachAndKillCursor(stdx::unique_lock<Latch> lk,
OperationContext* opCtx,
- const NamespaceString& nss,
CursorId cursorId);
/**
@@ -571,7 +555,12 @@ private:
*
* Not thread-safe.
*/
- CursorEntry* _getEntry(WithLock, NamespaceString const& nss, CursorId cursorId);
+ CursorEntry* _getEntry(WithLock, CursorId cursorId);
+
+ /**
+ * Allocates a new cursor id (a positive 64 bit number) that is not already in use.
+ */
+ CursorId _allocateCursorId();
/**
* De-registers the given cursor, and returns an owned pointer to the underlying
@@ -584,7 +573,6 @@ private:
*/
StatusWith<ClusterClientCursorGuard> _detachCursor(WithLock,
OperationContext* opCtx,
- const NamespaceString& nss,
CursorId cursorId);
/**
@@ -592,32 +580,6 @@ private:
*/
void killOperationUsingCursor(WithLock, CursorEntry* entry);
- /**
- * CursorEntryContainer is a moveable, non-copyable container for a set of cursors, where all
- * contained cursors share the same 32-bit prefix of their cursor id.
- */
- struct CursorEntryContainer {
- CursorEntryContainer(const CursorEntryContainer&) = delete;
- CursorEntryContainer& operator=(const CursorEntryContainer&) = delete;
-
- CursorEntryContainer(uint32_t containerPrefix) : containerPrefix(containerPrefix) {}
-
- CursorEntryContainer(CursorEntryContainer&& other) = default;
- CursorEntryContainer& operator=(CursorEntryContainer&& other) = default;
-
- // Common cursor id prefix for all cursors in this container.
- uint32_t containerPrefix;
-
- // Map from cursor id to cursor entry.
- CursorEntryMap entryMap;
- };
-
- /**
- * Erase the container that 'it' points to and return an iterator to the next one. Assumes 'it'
- * is an iterator in '_namespaceToContainerMap'.
- */
- NssToCursorContainerMap::iterator eraseContainer(NssToCursorContainerMap::iterator it);
-
// Clock source. Used when the 'last active' time for a cursor needs to be set/updated. May be
// concurrently accessed by multiple threads.
ClockSource* _clockSource;
@@ -631,23 +593,8 @@ private:
const int64_t _randomSeed;
PseudoRandom _pseudoRandom;
- // Map from cursor id prefix to associated namespace. Exists only to provide namespace lookup
- // for (deprecated) getNamespaceForCursorId() method.
- //
- // A CursorId is a 64-bit type, made up of a 32-bit prefix and a 32-bit suffix. When the first
- // cursor on a given namespace is registered, it is given a CursorId with a prefix that is
- // unique to that namespace, and an arbitrary suffix. Cursors subsequently registered on that
- // namespace will all share the same prefix.
- //
- // Entries are added when the first cursor on the given namespace is registered, and removed
- // when the last cursor on the given namespace is destroyed.
- stdx::unordered_map<uint32_t, NamespaceString> _cursorIdPrefixToNamespaceMap;
-
- // Map from namespace to the CursorEntryContainer for that namespace.
- //
- // Entries are added when the first cursor on the given namespace is registered, and removed
- // when the last cursor on the given namespace is destroyed.
- NssToCursorContainerMap _namespaceToContainerMap;
+ // Map from CursorId to CursorEntry.
+ CursorEntryMap _cursorEntryMap;
size_t _cursorsTimedOut = 0;
};
diff --git a/src/mongo/s/query/cluster_cursor_manager_test.cpp b/src/mongo/s/query/cluster_cursor_manager_test.cpp
index e6704bddbd8..0176fe23947 100644
--- a/src/mongo/s/query/cluster_cursor_manager_test.cpp
+++ b/src/mongo/s/query/cluster_cursor_manager_test.cpp
@@ -116,12 +116,12 @@ protected:
return *std::next(_cursorKilledFlags.begin(), i);
}
- void killCursorFromDifferentOpCtx(const NamespaceString& nss, CursorId cursorId) {
+ void killCursorFromDifferentOpCtx(CursorId cursorId) {
// Set up another client to kill the cursor.
auto killCursorClient = getServiceContext()->makeClient("killCursorClient");
auto killCursorOpCtx = killCursorClient->makeOperationContext();
AlternativeClientRegion acr(killCursorClient);
- ASSERT_OK(getManager()->killCursor(killCursorOpCtx.get(), nss, cursorId));
+ ASSERT_OK(getManager()->killCursor(killCursorOpCtx.get(), cursorId));
}
@@ -149,7 +149,7 @@ TEST_F(ClusterCursorManagerTest, RegisterCursor) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto pinnedCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT_OK(pinnedCursor.getStatus());
auto nextResult = pinnedCursor.getValue()->next();
ASSERT_OK(nextResult.getStatus());
@@ -184,7 +184,7 @@ TEST_F(ClusterCursorManagerTest, CheckOutCursorBasic) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto checkedOutCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT_OK(checkedOutCursor.getStatus());
ASSERT_EQ(cursorId, checkedOutCursor.getValue().getCursorId());
auto nextResult = checkedOutCursor.getValue()->next();
@@ -213,8 +213,8 @@ TEST_F(ClusterCursorManagerTest, CheckOutCursorMultipleCursors) {
UserNameIterator()));
}
for (int i = 0; i < numCursors; ++i) {
- auto pinnedCursor = getManager()->checkOutCursor(
- nss, cursorIds[i], getOperationContext(), successAuthChecker);
+ auto pinnedCursor =
+ getManager()->checkOutCursor(cursorIds[i], getOperationContext(), successAuthChecker);
ASSERT_OK(pinnedCursor.getStatus());
auto nextResult = pinnedCursor.getValue()->next();
ASSERT_OK(nextResult.getStatus());
@@ -236,11 +236,11 @@ TEST_F(ClusterCursorManagerTest, CheckOutCursorPinned) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto pinnedCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT_OK(pinnedCursor.getStatus());
ASSERT_EQ(ErrorCodes::CursorInUse,
getManager()
- ->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker)
+ ->checkOutCursor(cursorId, getOperationContext(), successAuthChecker)
.getStatus());
}
@@ -253,35 +253,17 @@ TEST_F(ClusterCursorManagerTest, CheckOutCursorKilled) {
ClusterCursorManager::CursorType::SingleTarget,
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
- killCursorFromDifferentOpCtx(nss, cursorId);
+ killCursorFromDifferentOpCtx(cursorId);
ASSERT_EQ(ErrorCodes::CursorNotFound,
getManager()
- ->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker)
+ ->checkOutCursor(cursorId, getOperationContext(), successAuthChecker)
.getStatus());
}
// Test that checking out an unknown cursor returns an error with code ErrorCodes::CursorNotFound.
TEST_F(ClusterCursorManagerTest, CheckOutCursorUnknown) {
ASSERT_EQ(ErrorCodes::CursorNotFound,
- getManager()->checkOutCursor(nss, 5, nullptr, successAuthChecker).getStatus());
-}
-
-// Test that checking out a unknown cursor returns an error with code ErrorCodes::CursorNotFound,
-// even if there is an existing cursor with the same cursor id but a different namespace.
-TEST_F(ClusterCursorManagerTest, CheckOutCursorWrongNamespace) {
- const NamespaceString correctNamespace("test.correct");
- const NamespaceString incorrectNamespace("test.incorrect");
- auto cursorId =
- assertGet(getManager()->registerCursor(getOperationContext(),
- allocateMockCursor(),
- correctNamespace,
- ClusterCursorManager::CursorType::SingleTarget,
- ClusterCursorManager::CursorLifetime::Mortal,
- UserNameIterator()));
- ASSERT_EQ(ErrorCodes::CursorNotFound,
- getManager()
- ->checkOutCursor(incorrectNamespace, cursorId, nullptr, successAuthChecker)
- .getStatus());
+ getManager()->checkOutCursor(5, nullptr, successAuthChecker).getStatus());
}
// Test that checking out a unknown cursor returns an error with code ErrorCodes::CursorNotFound,
@@ -296,7 +278,7 @@ TEST_F(ClusterCursorManagerTest, CheckOutCursorWrongCursorId) {
UserNameIterator()));
ASSERT_EQ(ErrorCodes::CursorNotFound,
getManager()
- ->checkOutCursor(nss, cursorId + 1, getOperationContext(), successAuthChecker)
+ ->checkOutCursor(cursorId + 1, getOperationContext(), successAuthChecker)
.getStatus());
}
@@ -313,7 +295,7 @@ TEST_F(ClusterCursorManagerTest, CheckOutCursorUpdateActiveTime) {
Date_t cursorRegistrationTime = getClockSource()->now();
getClockSource()->advance(Milliseconds(1));
auto checkedOutCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT_OK(checkedOutCursor.getStatus());
checkedOutCursor.getValue().returnCursor(ClusterCursorManager::CursorState::NotExhausted);
getManager()->killMortalCursorsInactiveSince(getOperationContext(), cursorRegistrationTime);
@@ -329,7 +311,7 @@ TEST_F(ClusterCursorManagerTest, CheckOutCursorAuthFails) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto checkedOutCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), failAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), failAuthChecker);
ASSERT_EQ(checkedOutCursor.getStatus(), ErrorCodes::Unauthorized);
}
@@ -346,7 +328,7 @@ TEST_F(ClusterCursorManagerTest, ReturnCursorUpdateActiveTime) {
UserNameIterator()));
Date_t cursorCheckOutTime = getClockSource()->now();
auto checkedOutCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT_OK(checkedOutCursor.getStatus());
getClockSource()->advance(Milliseconds(1));
checkedOutCursor.getValue().returnCursor(ClusterCursorManager::CursorState::NotExhausted);
@@ -363,7 +345,7 @@ TEST_F(ClusterCursorManagerTest, KillUnpinnedCursorBasic) {
ClusterCursorManager::CursorType::SingleTarget,
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
- killCursorFromDifferentOpCtx(nss, cursorId);
+ killCursorFromDifferentOpCtx(cursorId);
ASSERT(isMockCursorKilled(0));
}
@@ -377,9 +359,9 @@ TEST_F(ClusterCursorManagerTest, KillPinnedCursorBasic) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto pinnedCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT_OK(pinnedCursor.getStatus());
- killCursorFromDifferentOpCtx(nss, pinnedCursor.getValue().getCursorId());
+ killCursorFromDifferentOpCtx(pinnedCursor.getValue().getCursorId());
// When the cursor is pinned the operation which checked out the cursor should be interrupted.
ASSERT_EQ(getOperationContext()->checkForInterruptNoAssert(), ErrorCodes::CursorKilled);
@@ -406,31 +388,14 @@ TEST_F(ClusterCursorManagerTest, KillCursorMultipleCursors) {
}
// Kill each cursor and verify that it was successfully killed.
for (size_t i = 0; i < numCursors; ++i) {
- ASSERT_OK(getManager()->killCursor(getOperationContext(), nss, cursorIds[i]));
+ ASSERT_OK(getManager()->killCursor(getOperationContext(), cursorIds[i]));
ASSERT(isMockCursorKilled(i));
}
}
// Test that killing an unknown cursor returns an error with code ErrorCodes::CursorNotFound.
TEST_F(ClusterCursorManagerTest, KillCursorUnknown) {
- Status killResult = getManager()->killCursor(getOperationContext(), nss, 5);
- ASSERT_EQ(ErrorCodes::CursorNotFound, killResult);
-}
-
-// Test that killing an unknown cursor returns an error with code ErrorCodes::CursorNotFound,
-// even if there is an existing cursor with the same cursor id but a different namespace.
-TEST_F(ClusterCursorManagerTest, KillCursorWrongNamespace) {
- const NamespaceString correctNamespace("test.correct");
- const NamespaceString incorrectNamespace("test.incorrect");
- auto cursorId =
- assertGet(getManager()->registerCursor(getOperationContext(),
- allocateMockCursor(),
- correctNamespace,
- ClusterCursorManager::CursorType::SingleTarget,
- ClusterCursorManager::CursorLifetime::Mortal,
- UserNameIterator()));
- Status killResult =
- getManager()->killCursor(getOperationContext(), incorrectNamespace, cursorId);
+ Status killResult = getManager()->killCursor(getOperationContext(), 5);
ASSERT_EQ(ErrorCodes::CursorNotFound, killResult);
}
@@ -444,7 +409,7 @@ TEST_F(ClusterCursorManagerTest, KillCursorWrongCursorId) {
ClusterCursorManager::CursorType::SingleTarget,
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
- Status killResult = getManager()->killCursor(getOperationContext(), nss, cursorId + 1);
+ Status killResult = getManager()->killCursor(getOperationContext(), cursorId + 1);
ASSERT_EQ(ErrorCodes::CursorNotFound, killResult);
}
@@ -497,7 +462,7 @@ TEST_F(ClusterCursorManagerTest, ShouldNotKillPinnedCursors) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto pin = assertGet(
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker));
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker));
getManager()->killMortalCursorsInactiveSince(getOperationContext(), getClockSource()->now());
ASSERT(!isMockCursorKilled(0));
pin.returnCursor(ClusterCursorManager::CursorState::NotExhausted);
@@ -615,6 +580,27 @@ TEST_F(ClusterCursorManagerTest, KillCursorsSatisfyingOnlyKillsMatchingSubset) {
}
}
+// Tests that we can kill cusors based on their opkey.
+TEST_F(ClusterCursorManagerTest, KillCursorsSatisfyingBasedOnOpKey) {
+ const size_t numCursors = 10;
+ for (size_t i = 0; i < numCursors; ++i) {
+ ASSERT_OK(getManager()->registerCursor(getOperationContext(),
+ allocateMockCursor(),
+ nss,
+ ClusterCursorManager::CursorType::SingleTarget,
+ ClusterCursorManager::CursorLifetime::Mortal,
+ UserNameIterator()));
+ }
+ auto pred = [&](CursorId id, const ClusterCursorManager::CursorEntry& entry) {
+ return entry.getOperationKey() == getOperationContext()->getOperationKey();
+ };
+ auto nKilled = getManager()->killCursorsSatisfying(getOperationContext(), std::move(pred));
+ ASSERT_EQ(nKilled, numCursors);
+ for (size_t i = 0; i < numCursors; ++i) {
+ ASSERT(isMockCursorKilled(i));
+ }
+}
+
// Test that the Client that registered a cursor is correctly recorded.
TEST_F(ClusterCursorManagerTest, CorrectlyRecordsOriginatingClient) {
ASSERT_OK(getManager()->registerCursor(getOperationContext(),
@@ -691,7 +677,7 @@ TEST_F(ClusterCursorManagerTest, StatsPinCursor) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto pinnedCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT_EQ(1U, getManager()->stats().cursorsPinned);
}
@@ -732,7 +718,7 @@ TEST_F(ClusterCursorManagerTest, StatsKillShardedCursor) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
ASSERT_EQ(1U, getManager()->stats().cursorsMultiTarget);
- ASSERT_OK(getManager()->killCursor(getOperationContext(), nss, cursorId));
+ ASSERT_OK(getManager()->killCursor(getOperationContext(), cursorId));
ASSERT_EQ(0U, getManager()->stats().cursorsMultiTarget);
}
@@ -746,7 +732,7 @@ TEST_F(ClusterCursorManagerTest, StatsKillNotShardedCursor) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
ASSERT_EQ(1U, getManager()->stats().cursorsSingleTarget);
- ASSERT_OK(getManager()->killCursor(getOperationContext(), nss, cursorId));
+ ASSERT_OK(getManager()->killCursor(getOperationContext(), cursorId));
ASSERT_EQ(0U, getManager()->stats().cursorsSingleTarget);
}
@@ -760,10 +746,10 @@ TEST_F(ClusterCursorManagerTest, StatsKillPinnedCursor) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto pinnedCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT_EQ(1U, getManager()->stats().cursorsPinned);
- killCursorFromDifferentOpCtx(nss, cursorId);
+ killCursorFromDifferentOpCtx(cursorId);
ASSERT_EQ(getOperationContext()->checkForInterruptNoAssert(), ErrorCodes::CursorKilled);
ASSERT_EQ(0U, getManager()->stats().cursorsPinned);
@@ -779,7 +765,7 @@ TEST_F(ClusterCursorManagerTest, StatsExhaustShardedCursor) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto pinnedCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT_OK(pinnedCursor.getStatus());
ASSERT_OK(pinnedCursor.getValue()->next().getStatus());
ASSERT_EQ(1U, getManager()->stats().cursorsMultiTarget);
@@ -797,7 +783,7 @@ TEST_F(ClusterCursorManagerTest, StatsExhaustNotShardedCursor) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto pinnedCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT_OK(pinnedCursor.getStatus());
ASSERT_OK(pinnedCursor.getValue()->next().getStatus());
ASSERT_EQ(1U, getManager()->stats().cursorsSingleTarget);
@@ -816,7 +802,7 @@ TEST_F(ClusterCursorManagerTest, StatsExhaustPinnedCursor) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto pinnedCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT_OK(pinnedCursor.getStatus());
ASSERT_OK(pinnedCursor.getValue()->next().getStatus());
ASSERT_EQ(1U, getManager()->stats().cursorsPinned);
@@ -835,7 +821,7 @@ TEST_F(ClusterCursorManagerTest, StatsCheckInWithoutExhaustingPinnedCursor) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto pinnedCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT_OK(pinnedCursor.getStatus());
ASSERT_OK(pinnedCursor.getValue()->next().getStatus());
ASSERT_EQ(1U, getManager()->stats().cursorsPinned);
@@ -843,73 +829,6 @@ TEST_F(ClusterCursorManagerTest, StatsCheckInWithoutExhaustingPinnedCursor) {
ASSERT_EQ(0U, getManager()->stats().cursorsPinned);
}
-// Test that getting the namespace for a cursor returns the correct namespace.
-TEST_F(ClusterCursorManagerTest, GetNamespaceForCursorIdBasic) {
- auto cursorId =
- assertGet(getManager()->registerCursor(getOperationContext(),
- allocateMockCursor(),
- nss,
- ClusterCursorManager::CursorType::SingleTarget,
- ClusterCursorManager::CursorLifetime::Mortal,
- UserNameIterator()));
- boost::optional<NamespaceString> cursorNamespace =
- getManager()->getNamespaceForCursorId(cursorId);
- ASSERT(cursorNamespace);
- ASSERT_EQ(nss.ns(), cursorNamespace->ns());
-}
-
-// Test that getting the namespace for a cursor returns the correct namespace, when there are
-// multiple cursors registered on that namespace.
-TEST_F(ClusterCursorManagerTest, GetNamespaceForCursorIdMultipleCursorsSameNamespace) {
- const size_t numCursors = 10;
- std::vector<CursorId> cursorIds(numCursors);
- for (size_t i = 0; i < numCursors; ++i) {
- cursorIds[i] =
- assertGet(getManager()->registerCursor(getOperationContext(),
- allocateMockCursor(),
- nss,
- ClusterCursorManager::CursorType::SingleTarget,
- ClusterCursorManager::CursorLifetime::Mortal,
- UserNameIterator()));
- }
- for (size_t i = 0; i < numCursors; ++i) {
- boost::optional<NamespaceString> cursorNamespace =
- getManager()->getNamespaceForCursorId(cursorIds[i]);
- ASSERT(cursorNamespace);
- ASSERT_EQ(nss.ns(), cursorNamespace->ns());
- }
-}
-
-// Test that getting the namespace for a cursor returns the correct namespace, when there are
-// multiple cursors registered on different namespaces.
-TEST_F(ClusterCursorManagerTest, GetNamespaceForCursorIdMultipleCursorsDifferentNamespaces) {
- const size_t numCursors = 10;
- std::vector<std::pair<NamespaceString, CursorId>> cursors(numCursors);
- for (size_t i = 0; i < numCursors; ++i) {
- NamespaceString cursorNamespace(std::string(str::stream() << "test.collection" << i));
- auto cursorId =
- assertGet(getManager()->registerCursor(getOperationContext(),
- allocateMockCursor(),
- cursorNamespace,
- ClusterCursorManager::CursorType::SingleTarget,
- ClusterCursorManager::CursorLifetime::Mortal,
- UserNameIterator()));
- cursors[i] = {cursorNamespace, cursorId};
- }
- for (size_t i = 0; i < numCursors; ++i) {
- boost::optional<NamespaceString> cursorNamespace =
- getManager()->getNamespaceForCursorId(cursors[i].second);
- ASSERT(cursorNamespace);
- ASSERT_EQ(cursors[i].first.ns(), cursorNamespace->ns());
- }
-}
-
-// Test that getting the namespace for an unknown cursor returns boost::none.
-TEST_F(ClusterCursorManagerTest, GetNamespaceForCursorIdUnknown) {
- boost::optional<NamespaceString> cursorNamespace = getManager()->getNamespaceForCursorId(5);
- ASSERT_FALSE(cursorNamespace);
-}
-
// Test that the PinnedCursor default constructor creates a pin that owns no cursor.
TEST_F(ClusterCursorManagerTest, PinnedCursorDefaultConstructor) {
ClusterCursorManager::PinnedCursor pinnedCursor;
@@ -927,14 +846,14 @@ TEST_F(ClusterCursorManagerTest, PinnedCursorReturnCursorNotExhausted) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto registeredCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT_OK(registeredCursor.getStatus());
ASSERT_EQ(cursorId, registeredCursor.getValue().getCursorId());
ASSERT_NE(0, cursorId);
registeredCursor.getValue().returnCursor(ClusterCursorManager::CursorState::NotExhausted);
ASSERT_EQ(0, registeredCursor.getValue().getCursorId());
auto checkedOutCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT_OK(checkedOutCursor.getStatus());
}
@@ -949,7 +868,7 @@ TEST_F(ClusterCursorManagerTest, PinnedCursorReturnCursorExhausted) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto registeredCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT_OK(registeredCursor.getStatus());
ASSERT_EQ(cursorId, registeredCursor.getValue().getCursorId());
ASSERT_NE(0, cursorId);
@@ -959,7 +878,7 @@ TEST_F(ClusterCursorManagerTest, PinnedCursorReturnCursorExhausted) {
// Cursor should have been killed and destroyed.
ASSERT_NOT_OK(getManager()
- ->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker)
+ ->checkOutCursor(cursorId, getOperationContext(), successAuthChecker)
.getStatus());
ASSERT(isMockCursorKilled(0));
}
@@ -977,7 +896,7 @@ TEST_F(ClusterCursorManagerTest, PinnedCursorReturnCursorExhaustedWithNonExhaust
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto registeredCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT_OK(registeredCursor.getStatus());
ASSERT_EQ(cursorId, registeredCursor.getValue().getCursorId());
ASSERT_NE(0, cursorId);
@@ -988,7 +907,7 @@ TEST_F(ClusterCursorManagerTest, PinnedCursorReturnCursorExhaustedWithNonExhaust
// Cursor should be killed as soon as it's checked in.
ASSERT(isMockCursorKilled(0));
ASSERT_NOT_OK(getManager()
- ->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker)
+ ->checkOutCursor(cursorId, getOperationContext(), successAuthChecker)
.getStatus());
}
@@ -1003,7 +922,7 @@ TEST_F(ClusterCursorManagerTest, PinnedCursorMoveAssignmentKill) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto pinnedCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
pinnedCursor = ClusterCursorManager::PinnedCursor();
ASSERT(isMockCursorKilled(0));
}
@@ -1019,7 +938,7 @@ TEST_F(ClusterCursorManagerTest, PinnedCursorDestructorKill) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto pinnedCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
}
ASSERT(isMockCursorKilled(0));
}
@@ -1037,7 +956,7 @@ TEST_F(ClusterCursorManagerTest, RemotesExhausted) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto pinnedCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT_OK(pinnedCursor.getStatus());
ASSERT_FALSE(pinnedCursor.getValue()->remotesExhausted());
}
@@ -1053,10 +972,10 @@ TEST_F(ClusterCursorManagerTest, DoNotDestroyKilledPinnedCursors) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto pinnedCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT_OK(pinnedCursor.getStatus());
- killCursorFromDifferentOpCtx(nss, cursorId);
+ killCursorFromDifferentOpCtx(cursorId);
ASSERT_EQ(getOperationContext()->checkForInterruptNoAssert(), ErrorCodes::CursorKilled);
ASSERT(!isMockCursorKilled(0));
@@ -1091,7 +1010,7 @@ TEST_F(ClusterCursorManagerTest, CursorStoresAPIParameters) {
ClusterCursorManager::CursorLifetime::Mortal,
UserNameIterator()));
auto pinnedCursor = assertGet(
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker));
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker));
auto storedAPIParams = pinnedCursor->getAPIParameters();
ASSERT_EQ("2", *storedAPIParams.getAPIVersion());
@@ -1131,7 +1050,7 @@ TEST_F(ClusterCursorManagerTest, PinnedCursorNotKilledOnShutdown) {
UserNameIterator()));
auto pinnedCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
getManager()->shutdown(getOperationContext());
ASSERT_EQ(getOperationContext()->checkForInterruptNoAssert(), ErrorCodes::CursorKilled);
@@ -1159,7 +1078,7 @@ TEST_F(ClusterCursorManagerTest, CannotCheckoutCursorDuringShutdown) {
ASSERT_EQUALS(ErrorCodes::ShutdownInProgress,
getManager()
- ->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker)
+ ->checkOutCursor(cursorId, getOperationContext(), successAuthChecker)
.getStatus());
}
@@ -1207,7 +1126,7 @@ TEST_F(ClusterCursorManagerTest, OneCursorWithASession) {
ASSERT(cursors.find(cursorId) != cursors.end());
// Remove the cursor from the manager.
- ASSERT_OK(getManager()->killCursor(getOperationContext(), nss, cursorId));
+ ASSERT_OK(getManager()->killCursor(getOperationContext(), cursorId));
// There should be no more cursor entries by session id.
LogicalSessionIdSet sessions;
@@ -1231,8 +1150,7 @@ TEST_F(ClusterCursorManagerTest, GetSessionIdsWhileCheckedOut) {
UserNameIterator()));
// Check the cursor out, then try to append cursors, see that we get one.
- auto res =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ auto res = getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT(res.isOK());
auto cursors = getManager()->getCursorsForSession(lsid);
@@ -1273,7 +1191,7 @@ TEST_F(ClusterCursorManagerTest, MultipleCursorsWithSameSession) {
ASSERT(cursors.find(cursorId2) != cursors.end());
// Remove one cursor from the manager.
- ASSERT_OK(getManager()->killCursor(getOperationContext(), nss, cursorId1));
+ ASSERT_OK(getManager()->killCursor(getOperationContext(), cursorId1));
// Should still be able to retrieve the session.
lsids.clear();
@@ -1367,12 +1285,12 @@ TEST_F(ClusterCursorManagerTest, CheckAuthForKillCursors) {
ASSERT_EQ(ErrorCodes::CursorNotFound,
getManager()->checkAuthForKillCursors(
- getOperationContext(), nss, cursorId + 1, successAuthChecker));
- ASSERT_EQ(ErrorCodes::Unauthorized,
- getManager()->checkAuthForKillCursors(
- getOperationContext(), nss, cursorId, failAuthChecker));
- ASSERT_OK(getManager()->checkAuthForKillCursors(
- getOperationContext(), nss, cursorId, successAuthChecker));
+ getOperationContext(), cursorId + 1, successAuthChecker));
+ ASSERT_EQ(
+ ErrorCodes::Unauthorized,
+ getManager()->checkAuthForKillCursors(getOperationContext(), cursorId, failAuthChecker));
+ ASSERT_OK(
+ getManager()->checkAuthForKillCursors(getOperationContext(), cursorId, successAuthChecker));
}
TEST_F(ClusterCursorManagerTest, PinnedCursorReturnsUnderlyingCursorTxnNumber) {
@@ -1386,7 +1304,7 @@ TEST_F(ClusterCursorManagerTest, PinnedCursorReturnsUnderlyingCursorTxnNumber) {
UserNameIterator()));
auto pinnedCursor =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
+ getManager()->checkOutCursor(cursorId, getOperationContext(), successAuthChecker);
ASSERT_OK(pinnedCursor.getStatus());
// The underlying cursor's txnNumber should be returned.
@@ -1394,134 +1312,6 @@ TEST_F(ClusterCursorManagerTest, PinnedCursorReturnsUnderlyingCursorTxnNumber) {
ASSERT_EQ(txnNumber, *pinnedCursor.getValue()->getTxnNumber());
}
-TEST_F(ClusterCursorManagerTest, CursorsWithoutOperationKeys) {
- ASSERT_OK(getManager()->registerCursor(getOperationContext(),
- allocateMockCursor(),
- nss,
- ClusterCursorManager::CursorType::SingleTarget,
- ClusterCursorManager::CursorLifetime::Mortal,
- UserNameIterator()));
-
- ASSERT_EQ(getManager()->getCursorsForOpKeys({UUID::gen()}).size(), size_t(0));
-}
-
-TEST_F(ClusterCursorManagerTest, OneCursorWithAnOperationKey) {
- auto opKey = UUID::gen();
- getOperationContext()->setOperationKey(opKey);
- auto cursorId =
- assertGet(getManager()->registerCursor(getOperationContext(),
- allocateMockCursor(),
- nss,
- ClusterCursorManager::CursorType::SingleTarget,
- ClusterCursorManager::CursorLifetime::Mortal,
- UserNameIterator()));
-
- // Retrieve all cursors for this operation key - should be just ours.
- auto cursors = getManager()->getCursorsForOpKeys({opKey});
- ASSERT_EQ(cursors.size(), size_t(1));
- ASSERT(cursors.find(cursorId) != cursors.end());
-
- // Remove the cursor from the manager.
- ASSERT_OK(getManager()->killCursor(getOperationContext(), nss, cursorId));
-
- // There should be no more cursor entries for this operation key.
- ASSERT(getManager()->getCursorsForOpKeys({opKey}).empty());
-}
-
-TEST_F(ClusterCursorManagerTest, GetCursorByOpKeyWhileCheckedOut) {
- auto opKey = UUID::gen();
- getOperationContext()->setOperationKey(opKey);
- auto cursorId =
- assertGet(getManager()->registerCursor(getOperationContext(),
- allocateMockCursor(),
- nss,
- ClusterCursorManager::CursorType::SingleTarget,
- ClusterCursorManager::CursorLifetime::Mortal,
- UserNameIterator()));
-
- // Check the cursor out then look it up by operation key.
- auto res =
- getManager()->checkOutCursor(nss, cursorId, getOperationContext(), successAuthChecker);
- ASSERT(res.isOK());
-
- auto cursors = getManager()->getCursorsForOpKeys({opKey});
- ASSERT_EQ(cursors.size(), size_t(1));
-}
-
-TEST_F(ClusterCursorManagerTest, MultipleCursorsWithSameOperationKey) {
- auto opKey = UUID::gen();
- getOperationContext()->setOperationKey(opKey);
- auto cursorId1 =
- assertGet(getManager()->registerCursor(getOperationContext(),
- allocateMockCursor(),
- nss,
- ClusterCursorManager::CursorType::SingleTarget,
- ClusterCursorManager::CursorLifetime::Mortal,
- UserNameIterator()));
- auto cursorId2 =
- assertGet(getManager()->registerCursor(getOperationContext(),
- allocateMockCursor(),
- nss,
- ClusterCursorManager::CursorType::SingleTarget,
- ClusterCursorManager::CursorLifetime::Mortal,
- UserNameIterator()));
-
- // Retrieve all cursors for the operation key - should be both cursors.
- auto cursors = getManager()->getCursorsForOpKeys({opKey});
- ASSERT_EQ(cursors.size(), size_t(2));
- ASSERT(cursors.find(cursorId1) != cursors.end());
- ASSERT(cursors.find(cursorId2) != cursors.end());
-
- // Remove one cursor from the manager.
- ASSERT_OK(getManager()->killCursor(getOperationContext(), nss, cursorId1));
-
- // Should still be able to retrieve remaining cursor by session.
- cursors = getManager()->getCursorsForOpKeys({opKey});
- ASSERT_EQ(cursors.size(), size_t(1));
- ASSERT(cursors.find(cursorId2) != cursors.end());
-}
-
-TEST_F(ClusterCursorManagerTest, MultipleCursorsMultipleOperationKeys) {
- auto opKey1 = UUID::gen();
- auto opKey2 = UUID::gen();
- getOperationContext()->setOperationKey(opKey1);
-
- auto client2 = getServiceContext()->makeClient("client2");
- auto opCtx2 = client2->makeOperationContext();
- opCtx2->setOperationKey(opKey2);
-
- // Register two cursors with different operation keys.
- CursorId cursor1 =
- assertGet(getManager()->registerCursor(getOperationContext(),
- allocateMockCursor(),
- nss,
- ClusterCursorManager::CursorType::SingleTarget,
- ClusterCursorManager::CursorLifetime::Mortal,
- UserNameIterator()));
-
- CursorId cursor2 =
- assertGet(getManager()->registerCursor(opCtx2.get(),
- allocateMockCursor(),
- nss,
- ClusterCursorManager::CursorType::SingleTarget,
- ClusterCursorManager::CursorLifetime::Mortal,
- UserNameIterator()));
-
- // Retrieve cursors for each operation key.
- auto cursors1 = getManager()->getCursorsForOpKeys({opKey1});
- ASSERT_EQ(cursors1.size(), size_t(1));
- ASSERT(cursors1.find(cursor1) != cursors1.end());
-
- auto cursors2 = getManager()->getCursorsForOpKeys({opKey2});
- ASSERT_EQ(cursors2.size(), size_t(1));
-
- // Retrieve cursors for both operation keys.
- auto cursors = getManager()->getCursorsForOpKeys({opKey1, opKey2});
- ASSERT_EQ(cursors.size(), size_t(2));
- ASSERT(cursors.find(cursor1) != cursors.end());
- ASSERT(cursors.find(cursor2) != cursors.end());
-}
-
} // namespace
} // namespace mongo
diff --git a/src/mongo/s/query/cluster_find.cpp b/src/mongo/s/query/cluster_find.cpp
index 148a17f89b6..0bafa7b0fc2 100644
--- a/src/mongo/s/query/cluster_find.cpp
+++ b/src/mongo/s/query/cluster_find.cpp
@@ -681,7 +681,7 @@ StatusWith<CursorResponse> ClusterFind::runGetMore(OperationContext* opCtx,
NamespaceString nss(cmd.getDbName(), cmd.getCollection());
int64_t cursorId = cmd.getCommandParameter();
- auto pinnedCursor = cursorManager->checkOutCursor(nss, cursorId, opCtx, authChecker);
+ auto pinnedCursor = cursorManager->checkOutCursor(cursorId, opCtx, authChecker);
if (!pinnedCursor.isOK()) {
return pinnedCursor.getStatus();
}