summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/SConscript1
-rw-r--r--src/mongo/db/clientcursor.cpp16
-rw-r--r--src/mongo/db/clientcursor.h6
-rw-r--r--src/mongo/db/commands/getmore_cmd.cpp3
-rw-r--r--src/mongo/db/curop.cpp8
-rw-r--r--src/mongo/db/curop.h9
-rw-r--r--src/mongo/db/cursor_manager.cpp13
-rw-r--r--src/mongo/db/cursor_manager.h4
-rw-r--r--src/mongo/db/query/find.cpp10
-rw-r--r--src/mongo/s/query/cluster_cursor_manager.cpp12
-rw-r--r--src/mongo/s/query/cluster_cursor_manager.h5
-rw-r--r--src/mongo/s/query/cluster_find.cpp1
12 files changed, 74 insertions, 14 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index fc5a3a6e872..27e96498768 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -211,6 +211,7 @@ env.Library(
'$BUILD_DIR/mongo/util/net/network',
'$BUILD_DIR/mongo/util/progress_meter',
'server_options',
+ 'generic_cursor',
],
)
diff --git a/src/mongo/db/clientcursor.cpp b/src/mongo/db/clientcursor.cpp
index fca4761b28c..1c747d07998 100644
--- a/src/mongo/db/clientcursor.cpp
+++ b/src/mongo/db/clientcursor.cpp
@@ -129,6 +129,22 @@ void ClientCursor::dispose(OperationContext* opCtx) {
_disposed = true;
}
+GenericCursor ClientCursor::toGenericCursor() const {
+ GenericCursor gc;
+ gc.setCursorId(cursorid());
+ gc.setNs(nss());
+ gc.setNDocsReturned(pos());
+ gc.setTailable(isTailable());
+ gc.setAwaitData(isAwaitData());
+ gc.setNoCursorTimeout(isNoTimeout());
+ gc.setOriginatingCommand(getOriginatingCommandObj());
+ gc.setLsid(getSessionId());
+ if (auto opCtx = _operationUsingCursor) {
+ gc.setOperationUsingCursorId(opCtx->getOpID());
+ }
+ return gc;
+}
+
//
// Pin methods
//
diff --git a/src/mongo/db/clientcursor.h b/src/mongo/db/clientcursor.h
index cc698e12bfd..7602af622d0 100644
--- a/src/mongo/db/clientcursor.h
+++ b/src/mongo/db/clientcursor.h
@@ -186,6 +186,12 @@ public:
_pos = n;
}
+ /**
+ * Returns a generic cursor containing diagnostics about this cursor.
+ * The caller must either have this cursor pinned or hold a mutex from the cursor manager.
+ */
+ GenericCursor toGenericCursor() const;
+
//
// Timing.
//
diff --git a/src/mongo/db/commands/getmore_cmd.cpp b/src/mongo/db/commands/getmore_cmd.cpp
index a6fa17ab2d6..257e340b6b6 100644
--- a/src/mongo/db/commands/getmore_cmd.cpp
+++ b/src/mongo/db/commands/getmore_cmd.cpp
@@ -424,6 +424,9 @@ public:
if (!originatingCommand.isEmpty()) {
curOp->setOriginatingCommand_inlock(originatingCommand);
}
+
+ // Update the genericCursor stored in curOp with the new cursor stats.
+ curOp->setGenericCursor_inlock(cursor->toGenericCursor());
}
CursorId respondWithId = 0;
diff --git a/src/mongo/db/curop.cpp b/src/mongo/db/curop.cpp
index 7fbc23630b7..57e0d04b59f 100644
--- a/src/mongo/db/curop.cpp
+++ b/src/mongo/db/curop.cpp
@@ -292,6 +292,10 @@ void CurOp::reportCurrentOpForClient(OperationContext* opCtx,
}
}
+void CurOp::setGenericCursor_inlock(GenericCursor gc) {
+ _genericCursor = std::move(gc);
+}
+
CurOp::CurOp(OperationContext* opCtx) : CurOp(opCtx, &_curopStack(opCtx)) {
// If this is a sub-operation, we store the snapshot of lock stats as the base lock stats of the
// current operation.
@@ -491,6 +495,10 @@ void CurOp::reportState(BSONObjBuilder* builder, bool truncateOps) {
builder->append("planSummary", _planSummary);
}
+ if (_genericCursor) {
+ builder->append("cursor", _genericCursor->toBSON());
+ }
+
if (!_message.empty()) {
if (_progressMeter.isActive()) {
StringBuilder buf;
diff --git a/src/mongo/db/curop.h b/src/mongo/db/curop.h
index 1c039d8f06c..61824cb3f2f 100644
--- a/src/mongo/db/curop.h
+++ b/src/mongo/db/curop.h
@@ -32,6 +32,7 @@
#pragma once
#include "mongo/base/disallow_copying.h"
+#include "mongo/db/clientcursor.h"
#include "mongo/db/commands.h"
#include "mongo/db/cursor_id.h"
#include "mongo/db/operation_context.h"
@@ -527,6 +528,10 @@ public:
CurOp* parent() const {
return _parent;
}
+ boost::optional<GenericCursor> getGenericCursor_inlock() const {
+ return _genericCursor;
+ }
+
void yielded(int numYields = 1) {
_numYields += numYields;
} // Should be _inlock()?
@@ -558,6 +563,8 @@ public:
_planSummary = std::move(summary);
}
+ void setGenericCursor_inlock(GenericCursor gc);
+
const boost::optional<SingleThreadedLockStats> getLockStatsBase() {
return _lockStatsBase;
}
@@ -602,6 +609,8 @@ private:
std::string _message;
ProgressMeter _progressMeter;
int _numYields{0};
+ // A GenericCursor containing information about the active cursor for a getMore operation.
+ boost::optional<GenericCursor> _genericCursor;
std::string _planSummary;
boost::optional<SingleThreadedLockStats>
diff --git a/src/mongo/db/cursor_manager.cpp b/src/mongo/db/cursor_manager.cpp
index fb7cd6058d4..cb2266920c7 100644
--- a/src/mongo/db/cursor_manager.cpp
+++ b/src/mongo/db/cursor_manager.cpp
@@ -622,19 +622,6 @@ void CursorManager::appendActiveSessions(LogicalSessionIdSet* lsids) const {
}
}
-GenericCursor CursorManager::buildGenericCursor_inlock(const ClientCursor* cursor) const {
- GenericCursor gc;
- gc.setCursorId(cursor->_cursorid);
- gc.setNs(cursor->nss());
- gc.setLsid(cursor->getSessionId());
- gc.setNDocsReturned(cursor->pos());
- gc.setTailable(cursor->isTailable());
- gc.setAwaitData(cursor->isAwaitData());
- gc.setOriginatingCommand(cursor->getOriginatingCommandObj());
- gc.setNoCursorTimeout(cursor->isNoTimeout());
- return gc;
-}
-
void CursorManager::appendIdleCursors(AuthorizationSession* ctxAuth,
MongoProcessInterface::CurrentOpUserMode userMode,
std::vector<GenericCursor>* cursors) const {
diff --git a/src/mongo/db/cursor_manager.h b/src/mongo/db/cursor_manager.h
index 4202afadc65..d75053fa4b5 100644
--- a/src/mongo/db/cursor_manager.h
+++ b/src/mongo/db/cursor_manager.h
@@ -264,7 +264,9 @@ private:
* CursorManager partition lock. This is neccessary to protect concurrent access to the data
* members of 'cursor', as it prevents other threads from pinning this cursor.
*/
- GenericCursor buildGenericCursor_inlock(const ClientCursor* cursor) const;
+ GenericCursor buildGenericCursor_inlock(const ClientCursor* cursor) const {
+ return cursor->toGenericCursor();
+ }
ClientCursorPin _registerCursor(
OperationContext* opCtx, std::unique_ptr<ClientCursor, ClientCursor::Deleter> clientCursor);
diff --git a/src/mongo/db/query/find.cpp b/src/mongo/db/query/find.cpp
index b295df1d5e7..6a43af3c64f 100644
--- a/src/mongo/db/query/find.cpp
+++ b/src/mongo/db/query/find.cpp
@@ -39,6 +39,7 @@
#include "mongo/db/clientcursor.h"
#include "mongo/db/commands.h"
#include "mongo/db/curop.h"
+#include "mongo/db/curop_failpoint_helpers.h"
#include "mongo/db/db_raii.h"
#include "mongo/db/exec/filter.h"
#include "mongo/db/exec/working_set_common.h"
@@ -73,6 +74,9 @@ using stdx::make_unique;
// Failpoint for checking whether we've received a getmore.
MONGO_FAIL_POINT_DEFINE(failReceivedGetmore);
+// Failpoint to keep a cursor pinned.
+MONGO_FAIL_POINT_DEFINE(legacyGetMoreWaitWithCursor)
+
bool shouldSaveCursor(OperationContext* opCtx,
const Collection* collection,
PlanExecutor::ExecState finalState,
@@ -404,6 +408,8 @@ Message getMore(OperationContext* opCtx,
// command or upconverted legacy query in the originatingCommand field.
curOp.setOpDescription_inlock(upconvertGetMoreEntry(nss, cursorid, ntoreturn));
curOp.setOriginatingCommand_inlock(cc->getOriginatingCommandObj());
+ // Update the generic cursor in curOp.
+ curOp.setGenericCursor_inlock(cc->toGenericCursor());
}
PlanExecutor::ExecState state;
@@ -413,6 +419,10 @@ Message getMore(OperationContext* opCtx,
// metrics, as they accumulate over the course of a cursor's lifetime.
PlanSummaryStats preExecutionStats;
Explain::getSummaryStats(*exec, &preExecutionStats);
+ if (MONGO_FAIL_POINT(legacyGetMoreWaitWithCursor)) {
+ CurOpFailpointHelpers::waitWhileFailPointEnabled(
+ &legacyGetMoreWaitWithCursor, opCtx, "legacyGetMoreWaitWithCursor", nullptr);
+ }
generateBatch(ntoreturn, cc, &bb, &numResults, &state);
diff --git a/src/mongo/s/query/cluster_cursor_manager.cpp b/src/mongo/s/query/cluster_cursor_manager.cpp
index 3b1079aabb0..4964991e8bb 100644
--- a/src/mongo/s/query/cluster_cursor_manager.cpp
+++ b/src/mongo/s/query/cluster_cursor_manager.cpp
@@ -171,6 +171,18 @@ bool ClusterCursorManager::PinnedCursor::remotesExhausted() {
return _cursor->remotesExhausted();
}
+GenericCursor ClusterCursorManager::PinnedCursor::toGenericCursor() const {
+ GenericCursor gc;
+ gc.setCursorId(getCursorId());
+ gc.setNs(_nss);
+ gc.setLsid(getLsid());
+ gc.setNDocsReturned(getNumReturnedSoFar());
+ gc.setTailable(isTailable());
+ gc.setAwaitData(isTailableAndAwaitData());
+ gc.setOriginatingCommand(getOriginatingCommand());
+ return gc;
+}
+
Status ClusterCursorManager::PinnedCursor::setAwaitDataTimeout(Milliseconds awaitDataTimeout) {
invariant(_cursor);
return _cursor->setAwaitDataTimeout(awaitDataTimeout);
diff --git a/src/mongo/s/query/cluster_cursor_manager.h b/src/mongo/s/query/cluster_cursor_manager.h
index 37c7d7478b2..6c1b0d10c92 100644
--- a/src/mongo/s/query/cluster_cursor_manager.h
+++ b/src/mongo/s/query/cluster_cursor_manager.h
@@ -213,6 +213,11 @@ public:
long long getNumReturnedSoFar() const;
/**
+ * Returns a GenericCursor version of the pinned cursor.
+ */
+ GenericCursor toGenericCursor() const;
+
+ /**
* Stashes 'obj' to be returned later by this cursor. A cursor must be owned.
*/
void queueResult(const ClusterQueryResult& result);
diff --git a/src/mongo/s/query/cluster_find.cpp b/src/mongo/s/query/cluster_find.cpp
index 5621ba5150e..a805ad35078 100644
--- a/src/mongo/s/query/cluster_find.cpp
+++ b/src/mongo/s/query/cluster_find.cpp
@@ -575,6 +575,7 @@ StatusWith<CursorResponse> ClusterFind::runGetMore(OperationContext* opCtx,
stdx::lock_guard<Client> lk(*opCtx->getClient());
CurOp::get(opCtx)->setOriginatingCommand_inlock(
pinnedCursor.getValue().getOriginatingCommand());
+ CurOp::get(opCtx)->setGenericCursor_inlock(pinnedCursor.getValue().toGenericCursor());
}
// If the 'waitAfterPinningCursorBeforeGetMoreBatch' fail point is enabled, set the 'msg'