summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorA. Jesse Jiryu Davis <jesse@mongodb.com>2021-03-05 19:42:22 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-03-06 01:19:47 +0000
commitbd5693121fbe12bee14a83b4527df73c881a2052 (patch)
tree23a0b17b3daba1be8b4bbde56f7d2a85a6907ae1
parentf0a5b6384340c7b4b06c0e0e0edb32a5c007ae38 (diff)
downloadmongo-bd5693121fbe12bee14a83b4527df73c881a2052.tar.gz
SERVER-53149 Finish converting getMore to IDL
-rw-r--r--src/mongo/db/api_parameters.cpp11
-rw-r--r--src/mongo/db/api_parameters.h4
-rw-r--r--src/mongo/db/commands/SConscript1
-rw-r--r--src/mongo/db/commands/getmore_cmd.cpp125
-rw-r--r--src/mongo/db/query/getmore_command.idl1
-rw-r--r--src/mongo/db/query/getmore_request.cpp68
-rw-r--r--src/mongo/db/query/getmore_request.h6
-rw-r--r--src/mongo/db/query/getmore_request_test.cpp176
-rw-r--r--src/mongo/s/commands/SConscript1
-rw-r--r--src/mongo/s/commands/cluster_getmore_cmd.cpp29
-rw-r--r--src/mongo/s/commands/strategy.cpp13
-rw-r--r--src/mongo/s/query/async_results_merger_test.cpp15
-rw-r--r--src/mongo/s/query/cluster_find.cpp58
-rw-r--r--src/mongo/s/query/cluster_find.h6
14 files changed, 180 insertions, 334 deletions
diff --git a/src/mongo/db/api_parameters.cpp b/src/mongo/db/api_parameters.cpp
index 51e424637db..fbe130ee4de 100644
--- a/src/mongo/db/api_parameters.cpp
+++ b/src/mongo/db/api_parameters.cpp
@@ -64,6 +64,17 @@ APIParameters APIParameters::fromBSON(const BSONObj& cmdObj) {
APIParametersFromClient::parse("APIParametersFromClient"_sd, cmdObj));
}
+void APIParameters::uassertNoApiParameters(const BSONObj& bsonObject) {
+ for (const auto& fieldName :
+ std::vector<StringData>{APIParametersFromClient::kApiVersionFieldName,
+ APIParametersFromClient::kApiStrictFieldName,
+ APIParametersFromClient::kApiDeprecationErrorsFieldName}) {
+ uassert(4937600,
+ str::stream() << "Cannot pass in API parameter field " << fieldName,
+ !bsonObject.hasField(fieldName));
+ }
+}
+
void APIParameters::appendInfo(BSONObjBuilder* builder) const {
if (_apiVersion) {
builder->append(kAPIVersionFieldName, *_apiVersion);
diff --git a/src/mongo/db/api_parameters.h b/src/mongo/db/api_parameters.h
index 34c129bca15..809cb49a902 100644
--- a/src/mongo/db/api_parameters.h
+++ b/src/mongo/db/api_parameters.h
@@ -48,6 +48,10 @@ public:
static const OperationContext::Decoration<APIParameters> get;
static APIParameters fromClient(const APIParametersFromClient& apiParamsFromClient);
static APIParameters fromBSON(const BSONObj& cmdObj);
+ /*
+ * Throw if bsonObject includes any API parameters.
+ */
+ static void uassertNoApiParameters(const BSONObj& bsonObject);
// For use with unordered_map.
struct Hash {
diff --git a/src/mongo/db/commands/SConscript b/src/mongo/db/commands/SConscript
index 53dbaa6d788..1e9cabe5e18 100644
--- a/src/mongo/db/commands/SConscript
+++ b/src/mongo/db/commands/SConscript
@@ -333,6 +333,7 @@ env.Library(
],
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/base',
+ '$BUILD_DIR/mongo/db/api_parameters',
'$BUILD_DIR/mongo/db/catalog/catalog_helpers',
'$BUILD_DIR/mongo/db/catalog/collection_catalog_helper',
'$BUILD_DIR/mongo/db/catalog/collection_query_info',
diff --git a/src/mongo/db/commands/getmore_cmd.cpp b/src/mongo/db/commands/getmore_cmd.cpp
index 50242d38565..fd8ad91c234 100644
--- a/src/mongo/db/commands/getmore_cmd.cpp
+++ b/src/mongo/db/commands/getmore_cmd.cpp
@@ -34,6 +34,7 @@
#include <memory>
#include <string>
+#include "mongo/db/api_parameters.h"
#include "mongo/db/auth/authorization_checks.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/catalog/collection.h"
@@ -48,7 +49,7 @@
#include "mongo/db/query/cursor_response.h"
#include "mongo/db/query/find.h"
#include "mongo/db/query/find_common.h"
-#include "mongo/db/query/getmore_request.h"
+#include "mongo/db/query/getmore_command_gen.h"
#include "mongo/db/query/plan_executor.h"
#include "mongo/db/query/plan_summary_stats.h"
#include "mongo/db/read_concern.h"
@@ -88,21 +89,21 @@ static const ReadConcernSupportResult kSupportsReadConcernResult{
* Validates that the lsid of 'opCtx' matches that of 'cursor'. This must be called after
* authenticating, so that it is safe to report the lsid of 'cursor'.
*/
-void validateLSID(OperationContext* opCtx, const GetMoreRequest& request, ClientCursor* cursor) {
+void validateLSID(OperationContext* opCtx, int64_t cursorId, ClientCursor* cursor) {
uassert(50736,
- str::stream() << "Cannot run getMore on cursor " << request.cursorid
+ str::stream() << "Cannot run getMore on cursor " << cursorId
<< ", which was not created in a session, in session "
<< *opCtx->getLogicalSessionId(),
!opCtx->getLogicalSessionId() || cursor->getSessionId());
uassert(50737,
- str::stream() << "Cannot run getMore on cursor " << request.cursorid
+ str::stream() << "Cannot run getMore on cursor " << cursorId
<< ", which was created in session " << *cursor->getSessionId()
<< ", without an lsid",
opCtx->getLogicalSessionId() || !cursor->getSessionId());
uassert(50738,
- str::stream() << "Cannot run getMore on cursor " << request.cursorid
+ str::stream() << "Cannot run getMore on cursor " << cursorId
<< ", which was created in session " << *cursor->getSessionId()
<< ", in session " << *opCtx->getLogicalSessionId(),
!opCtx->getLogicalSessionId() || !cursor->getSessionId() ||
@@ -113,23 +114,21 @@ void validateLSID(OperationContext* opCtx, const GetMoreRequest& request, Client
* Validates that the txnNumber of 'opCtx' matches that of 'cursor'. This must be called after
* authenticating, so that it is safe to report the txnNumber of 'cursor'.
*/
-void validateTxnNumber(OperationContext* opCtx,
- const GetMoreRequest& request,
- ClientCursor* cursor) {
+void validateTxnNumber(OperationContext* opCtx, int64_t cursorId, ClientCursor* cursor) {
uassert(50739,
- str::stream() << "Cannot run getMore on cursor " << request.cursorid
+ str::stream() << "Cannot run getMore on cursor " << cursorId
<< ", which was not created in a transaction, in transaction "
<< *opCtx->getTxnNumber(),
!opCtx->getTxnNumber() || cursor->getTxnNumber());
uassert(50740,
- str::stream() << "Cannot run getMore on cursor " << request.cursorid
+ str::stream() << "Cannot run getMore on cursor " << cursorId
<< ", which was created in transaction " << *cursor->getTxnNumber()
<< ", without a txnNumber",
opCtx->getTxnNumber() || !cursor->getTxnNumber());
uassert(50741,
- str::stream() << "Cannot run getMore on cursor " << request.cursorid
+ str::stream() << "Cannot run getMore on cursor " << cursorId
<< ", which was created in transaction " << *cursor->getTxnNumber()
<< ", in transaction " << *opCtx->getTxnNumber(),
!opCtx->getTxnNumber() || !cursor->getTxnNumber() ||
@@ -192,7 +191,7 @@ void applyCursorReadConcern(OperationContext* opCtx, repl::ReadConcernArgs rcArg
*/
void setUpOperationDeadline(OperationContext* opCtx,
const ClientCursor& cursor,
- const GetMoreRequest& request,
+ const GetMoreCommand& cmd,
bool disableAwaitDataFailpointActive) {
// We assume that cursors created through a DBDirectClient are always used from their
@@ -205,7 +204,7 @@ void setUpOperationDeadline(OperationContext* opCtx,
if (cursor.isAwaitData() && !disableAwaitDataFailpointActive) {
awaitDataState(opCtx).waitForInsertsDeadline =
opCtx->getServiceContext()->getPreciseClockSource()->now() +
- request.awaitDataTimeout.value_or(Seconds{1});
+ Milliseconds{cmd.getMaxTimeMS().value_or(1000)};
} else if (cursor.getLeftoverMaxTimeMicros() < Microseconds::max()) {
opCtx->setDeadlineAfterNowBy(cursor.getLeftoverMaxTimeMicros(),
ErrorCodes::MaxTimeMSExpired);
@@ -218,12 +217,12 @@ void setUpOperationDeadline(OperationContext* opCtx,
*/
void setUpOperationContextStateForGetMore(OperationContext* opCtx,
const ClientCursor& cursor,
- const GetMoreRequest& request,
+ const GetMoreCommand& cmd,
bool disableAwaitDataFailpointActive) {
applyCursorReadConcern(opCtx, cursor.getReadConcernArgs());
opCtx->setWriteConcern(cursor.getWriteConcernOptions());
APIParameters::get(opCtx) = cursor.getAPIParameters();
- setUpOperationDeadline(opCtx, cursor, request, disableAwaitDataFailpointActive);
+ setUpOperationDeadline(opCtx, cursor, cmd, disableAwaitDataFailpointActive);
// If the originating command had a 'comment' field, we extract it and set it on opCtx. Note
// that if the 'getMore' command itself has a 'comment' field, we give precedence to it.
@@ -258,9 +257,14 @@ public:
class Invocation final : public CommandInvocation {
public:
Invocation(Command* cmd, const OpMsgRequest& request)
- : CommandInvocation(cmd),
- _request(uassertStatusOK(
- GetMoreRequest::parseFromBSON(request.getDatabase().toString(), request.body))) {}
+ : CommandInvocation(cmd), _cmd(GetMoreCommand::parse({"getMore"}, request.body)) {
+ NamespaceString nss(_cmd.getDbName(), _cmd.getCollection());
+ uassert(ErrorCodes::InvalidNamespace,
+ str::stream() << "Invalid namespace for getMore: " << nss.ns(),
+ nss.isValid());
+
+ APIParameters::uassertNoApiParameters(request.body);
+ }
private:
bool supportsWriteConcern() const override {
@@ -280,14 +284,14 @@ public:
}
NamespaceString ns() const override {
- return _request.nss;
+ return NamespaceString(_cmd.getDbName(), _cmd.getCollection());
}
void doCheckAuthorization(OperationContext* opCtx) const override {
uassertStatusOK(auth::checkAuthForGetMore(AuthorizationSession::get(opCtx->getClient()),
- _request.nss,
- _request.cursorid,
- _request.term.is_initialized()));
+ ns(),
+ _cmd.getCommandParameter(),
+ _cmd.getTerm().is_initialized()));
}
/**
@@ -302,7 +306,7 @@ public:
*/
bool generateBatch(OperationContext* opCtx,
ClientCursor* cursor,
- const GetMoreRequest& request,
+ const GetMoreCommand& cmd,
const bool isTailable,
CursorResponseBuilder* nextBatch,
std::uint64_t* numResults,
@@ -315,7 +319,7 @@ public:
BSONObj obj;
PlanExecutor::ExecState state;
try {
- while (!FindCommon::enoughForGetMore(request.batchSize.value_or(0), *numResults) &&
+ while (!FindCommon::enoughForGetMore(cmd.getBatchSize().value_or(0), *numResults) &&
PlanExecutor::ADVANCED == (state = exec->getNext(&obj, nullptr))) {
// If adding this object will cause us to exceed the message size limit, then we
// stash it for later.
@@ -348,7 +352,7 @@ public:
"getMore command executor error",
"error"_attr = exception.toStatus(),
"stats"_attr = redact(stats),
- "cmd"_attr = request.toBSON());
+ "cmd"_attr = cmd.toBSON({}));
exception.addContext("Executor error during getMore");
throw;
@@ -390,16 +394,18 @@ public:
// the stats twice.
boost::optional<AutoGetCollectionForReadMaybeLockFree> readLock;
boost::optional<AutoStatsTracker> statsTracker;
+ NamespaceString nss(_cmd.getDbName(), _cmd.getCollection());
+ int64_t cursorId = _cmd.getCommandParameter();
if (cursorPin->getExecutor()->lockPolicy() ==
PlanExecutor::LockPolicy::kLocksInternally) {
- if (!_request.nss.isCollectionlessCursorNamespace()) {
+ if (!nss.isCollectionlessCursorNamespace()) {
statsTracker.emplace(
opCtx,
- _request.nss,
+ nss,
Top::LockType::NotLocked,
AutoStatsTracker::LogMode::kUpdateTopAndCurOp,
- CollectionCatalog::get(opCtx)->getDatabaseProfileLevel(_request.nss.db()));
+ CollectionCatalog::get(opCtx)->getDatabaseProfileLevel(nss.db()));
}
} else {
invariant(cursorPin->getExecutor()->lockPolicy() ==
@@ -426,14 +432,14 @@ public:
statsTracker.emplace(
opCtx,
- _request.nss,
+ nss,
Top::LockType::ReadLocked,
AutoStatsTracker::LogMode::kUpdateTopAndCurOp,
- CollectionCatalog::get(opCtx)->getDatabaseProfileLevel(_request.nss.db()));
+ CollectionCatalog::get(opCtx)->getDatabaseProfileLevel(nss.db()));
// Check whether we are allowed to read from this node after acquiring our locks.
uassertStatusOK(repl::ReplicationCoordinator::get(opCtx)->checkCanServeReadsFor(
- opCtx, _request.nss, true));
+ opCtx, nss, true));
}
// A user can only call getMore on their own cursor. If there were multiple users
@@ -442,7 +448,7 @@ public:
auto authzSession = AuthorizationSession::get(opCtx->getClient());
if (!authzSession->isCoauthorizedWith(cursorPin->getAuthenticatedUsers())) {
uasserted(ErrorCodes::Unauthorized,
- str::stream() << "cursor id " << _request.cursorid
+ str::stream() << "cursor id " << cursorId
<< " was not created by the authenticated user");
}
@@ -450,23 +456,23 @@ public:
if (!authzSession->isAuthorizedForPrivileges(cursorPin->getOriginatingPrivileges())) {
uasserted(ErrorCodes::Unauthorized,
str::stream()
- << "not authorized for getMore with cursor id " << _request.cursorid);
+ << "not authorized for getMore with cursor id " << cursorId);
}
- if (_request.nss != cursorPin->nss()) {
+ if (nss != cursorPin->nss()) {
uasserted(ErrorCodes::Unauthorized,
- str::stream() << "Requested getMore on namespace '" << _request.nss.ns()
+ str::stream() << "Requested getMore on namespace '" << nss.ns()
<< "', but cursor belongs to a different namespace "
<< cursorPin->nss().ns());
}
// Ensure the lsid and txnNumber of the getMore match that of the originating command.
- validateLSID(opCtx, _request, cursorPin.getCursor());
- validateTxnNumber(opCtx, _request, cursorPin.getCursor());
+ validateLSID(opCtx, cursorId, cursorPin.getCursor());
+ validateTxnNumber(opCtx, cursorId, cursorPin.getCursor());
- if (_request.nss.isOplog() && MONGO_unlikely(rsStopGetMoreCmd.shouldFail())) {
+ if (nss.isOplog() && MONGO_unlikely(rsStopGetMoreCmd.shouldFail())) {
uasserted(ErrorCodes::CommandFailed,
- str::stream() << "getMore on " << _request.nss.ns()
+ str::stream() << "getMore on " << nss.ns()
<< " rejected due to active fail point rsStopGetMoreCmd");
}
@@ -475,7 +481,7 @@ public:
invariant(cursorPin->isTailable());
}
- if (_request.awaitDataTimeout && !cursorPin->isAwaitData()) {
+ if (_cmd.getMaxTimeMS() && !cursorPin->isAwaitData()) {
uasserted(ErrorCodes::BadValue,
"cannot set maxTimeMS on getMore command for a non-awaitData cursor");
}
@@ -488,7 +494,7 @@ public:
// repeatedly release and re-acquire the collection readLock at regular intervals until
// the failpoint is released. This is done in order to avoid deadlocks caused by the
// pinned-cursor failpoints in this file (see SERVER-21997).
- std::function<void()> dropAndReacquireReadLockIfLocked = [&readLock, opCtx, this]() {
+ std::function<void()> dropAndReacquireReadLockIfLocked = [&readLock, opCtx, nss]() {
if (!readLock) {
// This function is a no-op if 'readLock' is not held in the first place.
return;
@@ -497,7 +503,7 @@ public:
// Make sure an interrupted operation does not prevent us from reacquiring the lock.
UninterruptibleLockGuard noInterrupt(opCtx->lockState());
readLock.reset();
- readLock.emplace(opCtx, _request.nss);
+ readLock.emplace(opCtx, nss);
};
if (MONGO_unlikely(waitAfterPinningCursorBeforeGetMoreBatch.shouldFail())) {
CurOpFailpointHelpers::waitWhileFailPointEnabled(
@@ -505,7 +511,7 @@ public:
opCtx,
"waitAfterPinningCursorBeforeGetMoreBatch",
dropAndReacquireReadLockIfLocked,
- _request.nss);
+ nss);
}
const bool disableAwaitDataFailpointActive =
@@ -513,7 +519,7 @@ public:
// Inherit properties like readConcern and maxTimeMS from our originating cursor.
setUpOperationContextStateForGetMore(
- opCtx, *cursorPin.getCursor(), _request, disableAwaitDataFailpointActive);
+ opCtx, *cursorPin.getCursor(), _cmd, disableAwaitDataFailpointActive);
if (!cursorPin->isAwaitData()) {
opCtx->checkForInterrupt(); // May trigger maxTimeAlwaysTimeOut fail point.
@@ -579,7 +585,7 @@ public:
// Mark this as an AwaitData operation if appropriate.
if (cursorPin->isAwaitData() && !disableAwaitDataFailpointActive) {
- auto lastKnownCommittedOpTime = _request.lastKnownCommittedOpTime;
+ auto lastKnownCommittedOpTime = _cmd.getLastKnownCommittedOpTime();
if (opCtx->isExhaust() && cursorPin->getLastKnownCommittedOpTime()) {
// Use the commit point of the last batch for exhaust cursors.
lastKnownCommittedOpTime = cursorPin->getLastKnownCommittedOpTime();
@@ -610,12 +616,12 @@ public:
data["shouldNotdropLock"].booleanSafe()
? []() {} /*empty function*/
: saveAndRestoreStateWithReadLockReacquisition,
- _request.nss);
+ nss);
});
const auto shouldSaveCursor = generateBatch(opCtx,
cursorPin.getCursor(),
- _request,
+ _cmd,
cursorPin->isTailable(),
&nextBatch,
&numResults,
@@ -642,7 +648,7 @@ public:
}
if (shouldSaveCursor) {
- respondWithId = _request.cursorid;
+ respondWithId = cursorId;
exec->saveState();
exec->detachFromOperationContext();
@@ -658,7 +664,7 @@ public:
curOp->debug().cursorExhausted = true;
}
- nextBatch.done(respondWithId, _request.nss.ns());
+ nextBatch.done(respondWithId, nss.ns());
// Increment this metric once we have generated a response and we know it will return
// documents.
@@ -686,15 +692,17 @@ public:
// Counted as a getMore, not as a command.
globalOpCounters.gotGetMore();
auto curOp = CurOp::get(opCtx);
- curOp->debug().cursorid = _request.cursorid;
+ NamespaceString nss(_cmd.getDbName(), _cmd.getCollection());
+ int64_t cursorId = _cmd.getCommandParameter();
+ curOp->debug().cursorid = cursorId;
// The presence of a term in the request indicates that this is an internal replication
// oplog read request.
- if (_request.term && _request.nss == NamespaceString::kRsOplogNamespace) {
+ if (_cmd.getTerm() && nss == NamespaceString::kRsOplogNamespace) {
// Validate term before acquiring locks.
auto replCoord = repl::ReplicationCoordinator::get(opCtx);
// Note: updateTerm returns ok if term stayed the same.
- uassertStatusOK(replCoord->updateTerm(opCtx, *_request.term));
+ uassertStatusOK(replCoord->updateTerm(opCtx, *_cmd.getTerm()));
// If the term field is present in an oplog request, it means this is an oplog
// getMore for replication oplog fetching because the term field is only allowed for
@@ -709,7 +717,7 @@ public:
}
auto cursorManager = CursorManager::get(opCtx);
- auto cursorPin = uassertStatusOK(cursorManager->pinCursor(opCtx, _request.cursorid));
+ auto cursorPin = uassertStatusOK(cursorManager->pinCursor(opCtx, cursorId));
// Get the read concern level here in case the cursor is exhausted while iterating.
const auto isLinearizableReadConcern = cursorPin->getReadConcernArgs().getLevel() ==
@@ -737,9 +745,18 @@ public:
opCtx,
"waitBeforeUnpinningOrDeletingCursorAfterGetMoreBatch");
}
+
+ if (getTestCommandsEnabled()) {
+ validateResult(reply);
+ }
+ }
+
+ void validateResult(rpc::ReplyBuilderInterface* reply) {
+ auto ret = reply->getBodyBuilder().asTempObj();
+ CursorGetMoreReply::parse({"CursorGetMoreReply"}, ret.removeField("ok"));
}
- const GetMoreRequest _request;
+ const GetMoreCommand _cmd;
};
bool maintenanceOk() const override {
diff --git a/src/mongo/db/query/getmore_command.idl b/src/mongo/db/query/getmore_command.idl
index 9e4626d546a..91fdd7e283f 100644
--- a/src/mongo/db/query/getmore_command.idl
+++ b/src/mongo/db/query/getmore_command.idl
@@ -50,6 +50,7 @@ commands:
batchSize:
type: safeInt64
optional: true
+ validator: {gte: 0}
maxTimeMS:
description: "The awaitData timeout."
type: safeInt64
diff --git a/src/mongo/db/query/getmore_request.cpp b/src/mongo/db/query/getmore_request.cpp
index 30d8c59337b..669c9587213 100644
--- a/src/mongo/db/query/getmore_request.cpp
+++ b/src/mongo/db/query/getmore_request.cpp
@@ -38,7 +38,6 @@
#include "mongo/db/api_parameters_gen.h"
#include "mongo/db/commands.h"
#include "mongo/db/namespace_string.h"
-#include "mongo/db/query/getmore_command_gen.h"
#include "mongo/db/repl/bson_extract_optime.h"
#include "mongo/idl/command_generic_argument.h"
#include "mongo/util/assert_util.h"
@@ -46,6 +45,18 @@
namespace mongo {
+namespace {
+
+const char kCollectionField[] = "collection";
+const char kBatchSizeField[] = "batchSize";
+const char kAwaitDataTimeoutField[] = "maxTimeMS";
+const char kTermField[] = "term";
+const char kLastKnownCommittedOpTimeField[] = "lastKnownCommittedOpTime";
+
+} // namespace
+
+const char GetMoreRequest::kGetMoreCommandName[] = "getMore";
+
GetMoreRequest::GetMoreRequest() : cursorid(0), batchSize(0) {}
GetMoreRequest::GetMoreRequest(NamespaceString namespaceString,
@@ -80,54 +91,29 @@ Status GetMoreRequest::isValid() const {
return Status::OK();
}
-// static
-StatusWith<GetMoreRequest> GetMoreRequest::parseFromBSON(const std::string& dbname,
- const BSONObj& cmdObj) try {
- for (const auto& fieldName :
- std::vector<StringData>{APIParametersFromClient::kApiVersionFieldName,
- APIParametersFromClient::kApiStrictFieldName,
- APIParametersFromClient::kApiDeprecationErrorsFieldName}) {
- uassert(4937600,
- str::stream() << "Cannot pass in API parameter field " << fieldName,
- !cmdObj.hasField(fieldName));
- }
+BSONObj GetMoreRequest::toBSON() const {
+ BSONObjBuilder builder;
+
+ builder.append(kGetMoreCommandName, cursorid);
+ builder.append(kCollectionField, nss.coll());
- auto parsed = GetMoreCommand::parse({"getMore"}, cmdObj);
- auto maxTimeMS = parsed.getMaxTimeMS();
-
- GetMoreRequest request(
- NamespaceString(dbname, parsed.getCollection()),
- parsed.getCommandParameter(),
- parsed.getBatchSize(),
- // Treat maxTimeMS=0 the same as none.
- (maxTimeMS && *maxTimeMS) ? boost::optional<Milliseconds>(*maxTimeMS) : boost::none,
- parsed.getTerm() ? boost::optional<long long>(*parsed.getTerm()) : boost::none,
- parsed.getLastKnownCommittedOpTime());
-
- Status validStatus = request.isValid();
- if (!validStatus.isOK()) {
- return validStatus;
+ if (batchSize) {
+ builder.append(kBatchSizeField, *batchSize);
}
- return request;
-} catch (const DBException& exc) {
- return exc.toStatus();
-}
+ if (awaitDataTimeout) {
+ builder.append(kAwaitDataTimeoutField, durationCount<Milliseconds>(*awaitDataTimeout));
+ }
-BSONObj GetMoreRequest::toBSON() const {
- auto cmd = GetMoreCommand(cursorid);
- cmd.setDbName(nss.db());
- cmd.setCollection(nss.coll());
- cmd.setBatchSize(batchSize);
- cmd.setLastKnownCommittedOpTime(lastKnownCommittedOpTime);
if (term) {
- cmd.setTerm(static_cast<int64_t>(*term));
+ builder.append(kTermField, *term);
}
- if (awaitDataTimeout) {
- cmd.setMaxTimeMS(durationCount<Milliseconds>(*awaitDataTimeout));
+
+ if (lastKnownCommittedOpTime) {
+ lastKnownCommittedOpTime->append(&builder, kLastKnownCommittedOpTimeField);
}
- return cmd.toBSON({});
+ return builder.obj();
}
} // namespace mongo
diff --git a/src/mongo/db/query/getmore_request.h b/src/mongo/db/query/getmore_request.h
index 4c15af6c74b..61efdfcd187 100644
--- a/src/mongo/db/query/getmore_request.h
+++ b/src/mongo/db/query/getmore_request.h
@@ -59,12 +59,6 @@ struct GetMoreRequest {
boost::optional<repl::OpTime> lastKnownCommittedOpTime);
/**
- * Construct a GetMoreRequest from the command specification and db name.
- */
- static StatusWith<GetMoreRequest> parseFromBSON(const std::string& dbname,
- const BSONObj& cmdObj);
-
- /**
* Serializes this object into a BSON representation. Fields that are not set will not be
* part of the the serialized object.
*/
diff --git a/src/mongo/db/query/getmore_request_test.cpp b/src/mongo/db/query/getmore_request_test.cpp
index 4273838b88c..e698fa9c07f 100644
--- a/src/mongo/db/query/getmore_request_test.cpp
+++ b/src/mongo/db/query/getmore_request_test.cpp
@@ -41,182 +41,6 @@ namespace {
using namespace mongo;
-TEST(GetMoreRequestTest, parseFromBSONEmptyCommandObject) {
- StatusWith<GetMoreRequest> result = GetMoreRequest::parseFromBSON("db", BSONObj());
- ASSERT_NOT_OK(result.getStatus());
-}
-
-TEST(GetMoreRequestTest, parseFromBSONCursorIdNotNumeric) {
- StatusWith<GetMoreRequest> result = GetMoreRequest::parseFromBSON("db",
- BSON("getMore"
- << "not a number"
- << "collection"
- << "coll"
- << "$db"
- << "db"));
- ASSERT_NOT_OK(result.getStatus());
-}
-
-TEST(GetMoreRequestTest, parseFromBSONCursorIdNotLongLong) {
- StatusWith<GetMoreRequest> result =
- GetMoreRequest::parseFromBSON("db",
- BSON("getMore"
- << "not a number"
- << "collection" << 123 << "$db"
- << "db"));
- ASSERT_NOT_OK(result.getStatus());
-}
-
-TEST(GetMoreRequestTest, parseFromBSONMissingCollection) {
- StatusWith<GetMoreRequest> result =
- GetMoreRequest::parseFromBSON("db",
- BSON("getMore" << CursorId(123) << "$db"
- << "db"));
- ASSERT_NOT_OK(result.getStatus());
-}
-
-TEST(GetMoreRequestTest, parseFromBSONCollectionNotString) {
- StatusWith<GetMoreRequest> result = GetMoreRequest::parseFromBSON(
- "db",
- BSON("getMore" << CursorId(123) << "collection" << 456 << "$db"
- << "db"));
- ASSERT_NOT_OK(result.getStatus());
-}
-
-TEST(GetMoreRequestTest, parseFromBSONBatchSizeNotInteger) {
- StatusWith<GetMoreRequest> result =
- GetMoreRequest::parseFromBSON("db",
- BSON("getMore" << CursorId(123) << "collection"
- << "coll"
- << "batchSize"
- << "not a number"
- << "$db"
- << "db"));
- ASSERT_NOT_OK(result.getStatus());
-}
-
-TEST(GetMoreRequestTest, parseFromBSONInvalidCursorId) {
- StatusWith<GetMoreRequest> result =
- GetMoreRequest::parseFromBSON("db",
- BSON("getMore" << CursorId(0) << "collection"
- << "coll"
- << "$db"
- << "db"));
- ASSERT_NOT_OK(result.getStatus());
-}
-
-TEST(GetMoreRequestTest, parseFromBSONNegativeCursorId) {
- StatusWith<GetMoreRequest> result =
- GetMoreRequest::parseFromBSON("db",
- BSON("getMore" << CursorId(-123) << "collection"
- << "coll"
- << "$db"
- << "db"));
- ASSERT_OK(result.getStatus());
- ASSERT_EQUALS("db.coll", result.getValue().nss.toString());
- ASSERT_EQUALS(CursorId(-123), result.getValue().cursorid);
- ASSERT_FALSE(result.getValue().batchSize);
-}
-
-TEST(GetMoreRequestTest, parseFromBSONUnrecognizedFieldName) {
- StatusWith<GetMoreRequest> result =
- GetMoreRequest::parseFromBSON("db",
- BSON("getMore" << CursorId(123) << "collection"
- << "coll"
- << "unknown_field" << 1 << "$db"
- << "db"));
- ASSERT_NOT_OK(result.getStatus());
-}
-
-TEST(GetMoreRequestTest, parseFromBSONInvalidBatchSize) {
- StatusWith<GetMoreRequest> result =
- GetMoreRequest::parseFromBSON("db",
- BSON("getMore" << CursorId(123) << "collection"
- << "coll"
- << "batchSize" << -1 << "$db"
- << "db"));
- ASSERT_NOT_OK(result.getStatus());
-}
-
-TEST(GetMoreRequestTest, parseFromBSONInvalidBatchSizeOfZero) {
- StatusWith<GetMoreRequest> result =
- GetMoreRequest::parseFromBSON("db",
- BSON("getMore" << CursorId(123) << "collection"
- << "coll"
- << "batchSize" << 0 << "$db"
- << "db"));
- ASSERT_NOT_OK(result.getStatus());
-}
-
-TEST(GetMoreRequestTest, parseFromBSONNoBatchSize) {
- StatusWith<GetMoreRequest> result =
- GetMoreRequest::parseFromBSON("db",
- BSON("getMore" << CursorId(123) << "collection"
- << "coll"
- << "$db"
- << "db"));
- ASSERT_OK(result.getStatus());
- ASSERT_EQUALS("db.coll", result.getValue().nss.toString());
- ASSERT_EQUALS(CursorId(123), result.getValue().cursorid);
- ASSERT_FALSE(result.getValue().batchSize);
-}
-
-TEST(GetMoreRequestTest, parseFromBSONBatchSizeProvided) {
- StatusWith<GetMoreRequest> result =
- GetMoreRequest::parseFromBSON("db",
- BSON("getMore" << CursorId(123) << "collection"
- << "coll"
- << "batchSize" << 200 << "$db"
- << "db"));
- ASSERT_EQUALS("db.coll", result.getValue().nss.toString());
- ASSERT_EQUALS(CursorId(123), result.getValue().cursorid);
- ASSERT(result.getValue().batchSize);
- ASSERT_EQUALS(200, *result.getValue().batchSize);
-}
-
-TEST(GetMoreRequestTest, parseFromBSONIgnoreQueryOptions) {
- StatusWith<GetMoreRequest> result =
- GetMoreRequest::parseFromBSON("db",
- BSON("getMore" << CursorId(123) << "collection"
- << "coll"
- << "$queryOptions"
- << "bar"
- << "$db"
- << "db"));
- ASSERT_OK(result.getStatus());
- ASSERT_EQUALS("db.coll", result.getValue().nss.toString());
- ASSERT_EQUALS(CursorId(123), result.getValue().cursorid);
-}
-
-TEST(GetMoreRequestTest, parseFromBSONHasMaxTimeMS) {
- StatusWith<GetMoreRequest> result =
- GetMoreRequest::parseFromBSON("db",
- BSON("getMore" << CursorId(123) << "collection"
- << "coll"
- << "maxTimeMS" << 100 << "$db"
- << "db"));
- ASSERT_OK(result.getStatus());
- ASSERT_EQUALS("db.coll", result.getValue().nss.toString());
- ASSERT(result.getValue().awaitDataTimeout);
- ASSERT_EQUALS(100, durationCount<Milliseconds>(*result.getValue().awaitDataTimeout));
- ASSERT_EQUALS(CursorId(123), result.getValue().cursorid);
-}
-
-TEST(GetMoreRequestTest, parseFromBSONHasMaxTimeMSOfZero) {
- StatusWith<GetMoreRequest> result =
- GetMoreRequest::parseFromBSON("db",
- BSON("getMore" << CursorId(123) << "collection"
- << "coll"
- << "maxTimeMS" << 0 << "$db"
- << "db"));
- ASSERT_OK(result.getStatus());
- ASSERT_EQUALS("db.coll", result.getValue().nss.toString());
- ASSERT_EQUALS(CursorId(123), result.getValue().cursorid);
-
- // Max time of 0 means the same thing as no max time.
- ASSERT(!result.getValue().awaitDataTimeout);
-}
-
TEST(GetMoreRequestTest, toBSONHasBatchSize) {
GetMoreRequest request(
NamespaceString("testdb.testcoll"), 123, 99, boost::none, boost::none, boost::none);
diff --git a/src/mongo/s/commands/SConscript b/src/mongo/s/commands/SConscript
index 176468bf315..2b13e640112 100644
--- a/src/mongo/s/commands/SConscript
+++ b/src/mongo/s/commands/SConscript
@@ -103,6 +103,7 @@ env.Library(
'cluster_commands.idl',
],
LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/db/api_parameters',
'$BUILD_DIR/mongo/db/audit',
'$BUILD_DIR/mongo/db/auth/address_restriction',
'$BUILD_DIR/mongo/db/auth/auth',
diff --git a/src/mongo/s/commands/cluster_getmore_cmd.cpp b/src/mongo/s/commands/cluster_getmore_cmd.cpp
index a08fd0d3e0a..25bec22c1e4 100644
--- a/src/mongo/s/commands/cluster_getmore_cmd.cpp
+++ b/src/mongo/s/commands/cluster_getmore_cmd.cpp
@@ -29,11 +29,12 @@
#include "mongo/platform/basic.h"
+#include "mongo/db/api_parameters.h"
#include "mongo/db/auth/authorization_checks.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/commands.h"
#include "mongo/db/query/cursor_response.h"
-#include "mongo/db/query/getmore_request.h"
+#include "mongo/db/query/getmore_command_gen.h"
#include "mongo/db/stats/counters.h"
#include "mongo/s/query/cluster_cursor_manager.h"
#include "mongo/s/query/cluster_find.h"
@@ -73,13 +74,13 @@ public:
class Invocation final : public CommandInvocation {
public:
Invocation(Command* cmd, const OpMsgRequest& request)
- : CommandInvocation(cmd),
- _request(uassertStatusOK(
- GetMoreRequest::parseFromBSON(request.getDatabase().toString(), request.body))) {}
+ : CommandInvocation(cmd), _cmd(GetMoreCommand::parse({"getMore"}, request.body)) {
+ APIParameters::uassertNoApiParameters(request.body);
+ }
private:
NamespaceString ns() const override {
- return _request.nss;
+ return NamespaceString(_cmd.getDbName(), _cmd.getCollection());
}
bool supportsWriteConcern() const override {
@@ -92,20 +93,28 @@ public:
void doCheckAuthorization(OperationContext* opCtx) const override {
uassertStatusOK(auth::checkAuthForGetMore(AuthorizationSession::get(opCtx->getClient()),
- _request.nss,
- _request.cursorid,
- _request.term.is_initialized()));
+ ns(),
+ _cmd.getCommandParameter(),
+ _cmd.getTerm().is_initialized()));
}
void run(OperationContext* opCtx, rpc::ReplyBuilderInterface* reply) override {
// Counted as a getMore, not as a command.
globalOpCounters.gotGetMore();
auto bob = reply->getBodyBuilder();
- auto response = uassertStatusOK(ClusterFind::runGetMore(opCtx, _request));
+ auto response = uassertStatusOK(ClusterFind::runGetMore(opCtx, _cmd));
response.addToBSON(CursorResponse::ResponseType::SubsequentResponse, &bob);
+
+ if (getTestCommandsEnabled()) {
+ validateResult(bob.asTempObj());
+ }
+ }
+
+ void validateResult(const BSONObj& replyObj) {
+ CursorGetMoreReply::parse({"CursorGetMoreReply"}, replyObj.removeField("ok"));
}
- const GetMoreRequest _request;
+ const GetMoreCommand _cmd;
};
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
diff --git a/src/mongo/s/commands/strategy.cpp b/src/mongo/s/commands/strategy.cpp
index fcbcb89cd9e..2bb1d973b16 100644
--- a/src/mongo/s/commands/strategy.cpp
+++ b/src/mongo/s/commands/strategy.cpp
@@ -57,7 +57,7 @@
#include "mongo/db/operation_time_tracker.h"
#include "mongo/db/ops/write_ops.h"
#include "mongo/db/query/find_common.h"
-#include "mongo/db/query/getmore_request.h"
+#include "mongo/db/query/getmore_command_gen.h"
#include "mongo/db/query/query_request_helper.h"
#include "mongo/db/read_write_concern_defaults.h"
#include "mongo/db/stats/api_version_metrics.h"
@@ -1331,18 +1331,17 @@ DbResponse Strategy::getMore(OperationContext* opCtx, const NamespaceString& nss
}
uassertStatusOK(statusGetDb);
- boost::optional<std::int64_t> batchSize;
+ GetMoreCommand getMoreCmd(cursorId, nss.coll().toString());
+ getMoreCmd.setDbName(nss.db());
if (ntoreturn) {
- batchSize = ntoreturn;
+ getMoreCmd.setBatchSize(ntoreturn);
}
- GetMoreRequest getMoreRequest(nss, cursorId, batchSize, boost::none, boost::none, boost::none);
-
// Set the upconverted getMore as the CurOp command object.
CurOp::get(opCtx)->setGenericOpRequestDetails(
- opCtx, nss, nullptr, getMoreRequest.toBSON(), dbm->msg().operation());
+ opCtx, nss, nullptr, getMoreCmd.toBSON({}), dbm->msg().operation());
- auto cursorResponse = ClusterFind::runGetMore(opCtx, getMoreRequest);
+ auto cursorResponse = ClusterFind::runGetMore(opCtx, getMoreCmd);
if (cursorResponse == ErrorCodes::CursorNotFound) {
return replyToQuery(ResultFlag_CursorNotFound, nullptr, 0, 0);
}
diff --git a/src/mongo/s/query/async_results_merger_test.cpp b/src/mongo/s/query/async_results_merger_test.cpp
index ec41e728f68..a4bca4cafeb 100644
--- a/src/mongo/s/query/async_results_merger_test.cpp
+++ b/src/mongo/s/query/async_results_merger_test.cpp
@@ -37,7 +37,7 @@
#include "mongo/db/pipeline/change_stream_constants.h"
#include "mongo/db/pipeline/resume_token.h"
#include "mongo/db/query/cursor_response.h"
-#include "mongo/db/query/getmore_request.h"
+#include "mongo/db/query/getmore_command_gen.h"
#include "mongo/db/query/query_request_helper.h"
#include "mongo/executor/task_executor.h"
#include "mongo/s/catalog/type_shard.h"
@@ -1094,13 +1094,12 @@ TEST_F(AsyncResultsMergerTest, GetMoreBatchSizes) {
readyEvent = unittest::assertGet(arm->nextEvent());
BSONObj scheduledCmd = getNthPendingRequest(0).cmdObj;
- auto request = GetMoreRequest::parseFromBSON("anydbname",
- scheduledCmd.addField(BSON("$db"
- << "anydbname")
- .firstElement()));
- ASSERT_OK(request.getStatus());
- ASSERT_EQ(*request.getValue().batchSize, 1LL);
- ASSERT_EQ(request.getValue().cursorid, 1LL);
+ auto cmd = GetMoreCommand::parse({"getMore"},
+ scheduledCmd.addField(BSON("$db"
+ << "anydbname")
+ .firstElement()));
+ ASSERT_EQ(*cmd.getBatchSize(), 1LL);
+ ASSERT_EQ(cmd.getCommandParameter(), 1LL);
scheduleNetworkResponses(std::move(responses));
executor()->waitForEvent(readyEvent);
diff --git a/src/mongo/s/query/cluster_find.cpp b/src/mongo/s/query/cluster_find.cpp
index 02c4b570ac9..8997ee6746b 100644
--- a/src/mongo/s/query/cluster_find.cpp
+++ b/src/mongo/s/query/cluster_find.cpp
@@ -438,7 +438,7 @@ CursorId runQueryWithoutRetrying(OperationContext* opCtx,
* and/or what's specified on the request.
*/
Status setUpOperationContextStateForGetMore(OperationContext* opCtx,
- const GetMoreRequest& request,
+ const GetMoreCommand& cmd,
const ClusterCursorManager::PinnedCursor& cursor) {
if (auto readPref = cursor->getReadPreference()) {
ReadPreferenceSetting::get(opCtx) = *readPref;
@@ -461,12 +461,12 @@ Status setUpOperationContextStateForGetMore(OperationContext* opCtx,
// For tailable + awaitData cursors, the request may have indicated a maximum amount of time
// to wait for new data. If not, default it to 1 second. We track the deadline instead via
// the 'waitForInsertsDeadline' decoration.
- auto timeout = request.awaitDataTimeout.value_or(Milliseconds{1000});
+ auto timeout = Milliseconds{cmd.getMaxTimeMS().value_or(1000)};
awaitDataState(opCtx).waitForInsertsDeadline =
opCtx->getServiceContext()->getPreciseClockSource()->now() + timeout;
invariant(cursor->setAwaitDataTimeout(timeout).isOK());
- } else if (request.awaitDataTimeout) {
+ } else if (cmd.getMaxTimeMS()) {
return {ErrorCodes::BadValue,
"maxTimeMS can only be used with getMore for tailable, awaitData cursors"};
} else if (cursor->getLeftoverMaxTimeMicros() < Microseconds::max()) {
@@ -619,18 +619,18 @@ CursorId ClusterFind::runQuery(OperationContext* opCtx,
* ClusterClusterCursor manager if it does not.
*/
void validateLSID(OperationContext* opCtx,
- const GetMoreRequest& request,
+ int64_t cursorId,
const ClusterCursorManager::PinnedCursor& cursor) {
if (opCtx->getLogicalSessionId() && !cursor->getLsid()) {
uasserted(50799,
- str::stream() << "Cannot run getMore on cursor " << request.cursorid
+ str::stream() << "Cannot run getMore on cursor " << cursorId
<< ", which was not created in a session, in session "
<< *opCtx->getLogicalSessionId());
}
if (!opCtx->getLogicalSessionId() && cursor->getLsid()) {
uasserted(50800,
- str::stream() << "Cannot run getMore on cursor " << request.cursorid
+ str::stream() << "Cannot run getMore on cursor " << cursorId
<< ", which was created in session " << *cursor->getLsid()
<< ", without an lsid");
}
@@ -638,7 +638,7 @@ void validateLSID(OperationContext* opCtx,
if (opCtx->getLogicalSessionId() && cursor->getLsid() &&
(*opCtx->getLogicalSessionId() != *cursor->getLsid())) {
uasserted(50801,
- str::stream() << "Cannot run getMore on cursor " << request.cursorid
+ str::stream() << "Cannot run getMore on cursor " << cursorId
<< ", which was created in session " << *cursor->getLsid()
<< ", in session " << *opCtx->getLogicalSessionId());
}
@@ -649,18 +649,18 @@ void validateLSID(OperationContext* opCtx,
* the ClusterClusterCursor manager if it does not.
*/
void validateTxnNumber(OperationContext* opCtx,
- const GetMoreRequest& request,
+ int64_t cursorId,
const ClusterCursorManager::PinnedCursor& cursor) {
if (opCtx->getTxnNumber() && !cursor->getTxnNumber()) {
uasserted(50802,
- str::stream() << "Cannot run getMore on cursor " << request.cursorid
+ str::stream() << "Cannot run getMore on cursor " << cursorId
<< ", which was not created in a transaction, in transaction "
<< *opCtx->getTxnNumber());
}
if (!opCtx->getTxnNumber() && cursor->getTxnNumber()) {
uasserted(50803,
- str::stream() << "Cannot run getMore on cursor " << request.cursorid
+ str::stream() << "Cannot run getMore on cursor " << cursorId
<< ", which was created in transaction " << *cursor->getTxnNumber()
<< ", without a txnNumber");
}
@@ -668,7 +668,7 @@ void validateTxnNumber(OperationContext* opCtx,
if (opCtx->getTxnNumber() && cursor->getTxnNumber() &&
(*opCtx->getTxnNumber() != *cursor->getTxnNumber())) {
uasserted(50804,
- str::stream() << "Cannot run getMore on cursor " << request.cursorid
+ str::stream() << "Cannot run getMore on cursor " << cursorId
<< ", which was created in transaction " << *cursor->getTxnNumber()
<< ", in transaction " << *opCtx->getTxnNumber());
}
@@ -679,17 +679,17 @@ void validateTxnNumber(OperationContext* opCtx,
* that stored on the cursor. The cursor is returned to the ClusterCursorManager if it does not.
*/
void validateOperationSessionInfo(OperationContext* opCtx,
- const GetMoreRequest& request,
+ int64_t cursorId,
ClusterCursorManager::PinnedCursor* cursor) {
auto returnCursorGuard = makeGuard(
[cursor] { cursor->returnCursor(ClusterCursorManager::CursorState::NotExhausted); });
- validateLSID(opCtx, request, *cursor);
- validateTxnNumber(opCtx, request, *cursor);
+ validateLSID(opCtx, cursorId, *cursor);
+ validateTxnNumber(opCtx, cursorId, *cursor);
returnCursorGuard.dismiss();
}
StatusWith<CursorResponse> ClusterFind::runGetMore(OperationContext* opCtx,
- const GetMoreRequest& request) {
+ const GetMoreCommand& cmd) {
auto cursorManager = Grid::get(opCtx)->getCursorManager();
auto authzSession = AuthorizationSession::get(opCtx->getClient());
@@ -699,27 +699,28 @@ StatusWith<CursorResponse> ClusterFind::runGetMore(OperationContext* opCtx,
: Status(ErrorCodes::Unauthorized, "User not authorized to access cursor");
};
- auto pinnedCursor =
- cursorManager->checkOutCursor(request.nss, request.cursorid, opCtx, authChecker);
+ NamespaceString nss(cmd.getDbName(), cmd.getCollection());
+ int64_t cursorId = cmd.getCommandParameter();
+
+ auto pinnedCursor = cursorManager->checkOutCursor(nss, cursorId, opCtx, authChecker);
if (!pinnedCursor.isOK()) {
return pinnedCursor.getStatus();
}
- invariant(request.cursorid == pinnedCursor.getValue().getCursorId());
+ invariant(cursorId == pinnedCursor.getValue().getCursorId());
- validateOperationSessionInfo(opCtx, request, &pinnedCursor.getValue());
+ validateOperationSessionInfo(opCtx, cursorId, &pinnedCursor.getValue());
// Ensure that the client still has the privileges to run the originating command.
if (!authzSession->isAuthorizedForPrivileges(
pinnedCursor.getValue()->getOriginatingPrivileges())) {
uasserted(ErrorCodes::Unauthorized,
- str::stream() << "not authorized for getMore with cursor id "
- << request.cursorid);
+ str::stream() << "not authorized for getMore with cursor id " << cursorId);
}
// Set the originatingCommand object and the cursorID in CurOp.
{
CurOp::get(opCtx)->debug().nShards = pinnedCursor.getValue()->getNumRemotes();
- CurOp::get(opCtx)->debug().cursorid = request.cursorid;
+ CurOp::get(opCtx)->debug().cursorid = cursorId;
stdx::lock_guard<Client> lk(*opCtx->getClient());
CurOp::get(opCtx)->setOriginatingCommand_inlock(
pinnedCursor.getValue()->getOriginatingCommand());
@@ -734,12 +735,12 @@ StatusWith<CursorResponse> ClusterFind::runGetMore(OperationContext* opCtx,
: ErrorCodes::InternalError);
uasserted(errorCode, "Hit the 'failGetMoreAfterCursorCheckout' failpoint");
},
- [&opCtx, &request](const BSONObj& data) {
+ [&opCtx, nss](const BSONObj& data) {
auto dataForFailCommand =
data.addField(BSON("failCommands" << BSON_ARRAY("getMore")).firstElement());
auto* getMoreCommand = CommandHelpers::findCommand("getMore");
return CommandHelpers::shouldActivateFailCommandFailPoint(
- dataForFailCommand, request.nss, getMoreCommand, opCtx->getClient());
+ dataForFailCommand, nss, getMoreCommand, opCtx->getClient());
});
// If the 'waitAfterPinningCursorBeforeGetMoreBatch' fail point is enabled, set the 'msg'
@@ -752,14 +753,14 @@ StatusWith<CursorResponse> ClusterFind::runGetMore(OperationContext* opCtx,
}
auto opCtxSetupStatus =
- setUpOperationContextStateForGetMore(opCtx, request, pinnedCursor.getValue());
+ setUpOperationContextStateForGetMore(opCtx, cmd, pinnedCursor.getValue());
if (!opCtxSetupStatus.isOK()) {
return opCtxSetupStatus;
}
std::vector<BSONObj> batch;
int bytesBuffered = 0;
- long long batchSize = request.batchSize.value_or(0);
+ long long batchSize = cmd.getBatchSize().value_or(0);
long long startingFrom = pinnedCursor.getValue()->getNumReturnedSoFar();
auto cursorState = ClusterCursorManager::CursorState::NotExhausted;
BSONObj postBatchResumeToken;
@@ -826,8 +827,7 @@ StatusWith<CursorResponse> ClusterFind::runGetMore(OperationContext* opCtx,
// If the cursor has been exhausted, we will communicate this by returning a CursorId of zero.
auto idToReturn =
- (cursorState == ClusterCursorManager::CursorState::Exhausted ? CursorId(0)
- : request.cursorid);
+ (cursorState == ClusterCursorManager::CursorState::Exhausted ? CursorId(0) : cursorId);
// For empty batches, or in the case where the final result was added to the batch rather than
// being stashed, we update the PBRT here to ensure that it is the most recent available.
@@ -856,7 +856,7 @@ StatusWith<CursorResponse> ClusterFind::runGetMore(OperationContext* opCtx,
auto atClusterTime = !opCtx->inMultiDocumentTransaction()
? repl::ReadConcernArgs::get(opCtx).getArgsAtClusterTime()
: boost::none;
- return CursorResponse(request.nss,
+ return CursorResponse(nss,
idToReturn,
std::move(batch),
atClusterTime ? atClusterTime->asTimestamp()
diff --git a/src/mongo/s/query/cluster_find.h b/src/mongo/s/query/cluster_find.h
index 89ab0d24731..fe5907c0153 100644
--- a/src/mongo/s/query/cluster_find.h
+++ b/src/mongo/s/query/cluster_find.h
@@ -35,6 +35,7 @@
#include "mongo/db/cursor_id.h"
#include "mongo/db/query/cursor_response.h"
#include "mongo/db/query/explain_options.h"
+#include "mongo/db/query/getmore_command_gen.h"
namespace mongo {
@@ -42,7 +43,6 @@ template <typename T>
class StatusWith;
class CanonicalQuery;
class OperationContext;
-struct GetMoreRequest;
struct ReadPreferenceSetting;
/**
@@ -68,10 +68,10 @@ public:
bool* partialResultsReturned = nullptr);
/**
- * Executes the getMore request 'request', and on success returns a CursorResponse.
+ * Executes the getMore command 'cmd', and on success returns a CursorResponse.
*/
static StatusWith<CursorResponse> runGetMore(OperationContext* opCtx,
- const GetMoreRequest& request);
+ const GetMoreCommand& cmd);
};
} // namespace mongo