Skip to content

Commit

Permalink
SERVER-37090 Add idleCursors to currentOp output for mongos
Browse files Browse the repository at this point in the history
  • Loading branch information
TedTuckman committed Sep 18, 2018
1 parent cd441ed commit 157691e
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 14 deletions.
18 changes: 11 additions & 7 deletions jstests/core/currentop_cursors.js
Expand Up @@ -2,10 +2,7 @@
* Tests that an idle cursor will appear in the $currentOp output if the idleCursors option is
* set to true.
*
* The work to make this feature available on mongos is deferred to SERVER-37004
* and SERVER-37005. Those tickets will make the idleCursor fields available to curOp.
* @tags: [assumes_against_mongod_not_mongos, assumes_read_concern_unchanged]
*
* @tags: [assumes_read_concern_unchanged]
*/

(function() {
Expand All @@ -20,12 +17,19 @@
assert.commandWorked(db.runCommand({find: "jstests_currentop", batchSize: 2})).cursor.id;
const result = adminDB
.aggregate([
{$currentOp: {allUsers: false, idleCursors: true}},
{$currentOp: {localOps: true, allUsers: false, idleCursors: true}},
{$match: {$and: [{type: "idleCursor"}, {"cursor.cursorId": findOut}]}}
])
.toArray();
assert.eq(result.length, 1, tojson(result));
assert.eq(result[0].cursor.nDocsReturned, 2, tojson(result));
assert.eq(result.length, 1, result);
assert.eq(result[0].cursor.nDocsReturned, 2, result);
assert.eq(result[0].cursor.tailable, false, result);
assert.eq(result[0].cursor.awaitData, false, result);
assert.eq(result[0].cursor.noCursorTimeout, false, result);
assert.eq(result[0].cursor.ns, coll.getFullName(), result);
assert.eq(result[0].cursor.originatingCommand.find, "jstests_currentop", result);
assert.eq(result[0].cursor.originatingCommand.batchSize, 2, result);

const noIdle = adminDB
.aggregate([
{$currentOp: {allUsers: false, idleCursors: false}},
Expand Down
2 changes: 0 additions & 2 deletions src/mongo/db/pipeline/mongos_process_interface.h
Expand Up @@ -52,8 +52,6 @@ class MongoSInterface final : public MongoProcessCommon {
const Document& documentKey,
boost::optional<BSONObj> readConcern) final;

// TODO: SERVER-37090 bring mongos getIdleCursors to match mongod and pass back GenericCursors
// with all available fields.
std::vector<GenericCursor> getIdleCursors(const boost::intrusive_ptr<ExpressionContext>& expCtx,
CurrentOpUserMode userMode) const final;

Expand Down
22 changes: 17 additions & 5 deletions src/mongo/s/query/cluster_cursor_manager.cpp
Expand Up @@ -572,6 +572,21 @@ void ClusterCursorManager::appendActiveSessions(LogicalSessionIdSet* lsids) cons
}
}

GenericCursor ClusterCursorManager::CursorEntry::cursorToGenericCursor(
CursorId cursorId, const NamespaceString& ns) const {
invariant(_cursor);
GenericCursor gc;
gc.setCursorId(cursorId);
gc.setNs(ns);
gc.setLsid(_cursor->getLsid());
gc.setNDocsReturned(_cursor->getNumReturnedSoFar());
gc.setTailable(_cursor->isTailable());
gc.setAwaitData(_cursor->isTailableAndAwaitData());
gc.setOriginatingCommand(_cursor->getOriginatingCommand());
gc.setNoCursorTimeout(getLifetimeType() == CursorLifetime::Immortal);
return gc;
}

std::vector<GenericCursor> ClusterCursorManager::getIdleCursors() const {
std::vector<GenericCursor> cursors;

Expand All @@ -586,11 +601,8 @@ std::vector<GenericCursor> ClusterCursorManager::getIdleCursors() const {
continue;
}

cursors.emplace_back();
auto& gc = cursors.back();
gc.setCursorId(cursorIdEntryPair.first);
gc.setNs(nsContainerPair.first);
gc.setLsid(entry.getLsid());
cursors.emplace_back(
entry.cursorToGenericCursor(cursorIdEntryPair.first, nsContainerPair.first));
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/mongo/s/query/cluster_cursor_manager.h
Expand Up @@ -553,6 +553,14 @@ class ClusterCursorManager {
return _lsid;
}

/**
* Creates a generic cursor from the cursor inside this entry. Should only be called on
* idle cursors. The caller must supply the cursorId and namespace because the CursorEntry
* does not have access to them. Cannot be called if this CursorEntry does not own an
* underlying ClusterClientCursor.
*/
GenericCursor cursorToGenericCursor(CursorId cursorId, const NamespaceString& ns) const;

/**
* Returns 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 getOperationUsingCursor()
Expand Down

0 comments on commit 157691e

Please sign in to comment.