diff options
author | James Wahlin <james.wahlin@10gen.com> | 2016-05-20 16:42:09 -0400 |
---|---|---|
committer | James Wahlin <james.wahlin@10gen.com> | 2016-06-03 20:58:42 -0400 |
commit | 94b2682abc46a7739e52bba12b3ecdae16b5f8e8 (patch) | |
tree | 9b95d30ba9966b119fa18175c26d95ff548a2c19 | |
parent | bd5ef88fd884a2cc95eab6d4b66ce09d5efacb81 (diff) | |
download | mongo-94b2682abc46a7739e52bba12b3ecdae16b5f8e8.tar.gz |
SERVER-23260 Report original query with getMore
-rw-r--r-- | jstests/core/profile_getmore.js | 41 | ||||
-rw-r--r-- | jstests/noPassthrough/currentop_query.js | 5 | ||||
-rw-r--r-- | src/mongo/db/commands/find_cmd.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/commands/getmore_cmd.cpp | 10 | ||||
-rw-r--r-- | src/mongo/db/curop.cpp | 14 | ||||
-rw-r--r-- | src/mongo/db/curop.h | 16 | ||||
-rw-r--r-- | src/mongo/db/query/find.cpp | 14 |
7 files changed, 89 insertions, 13 deletions
diff --git a/jstests/core/profile_getmore.js b/jstests/core/profile_getmore.js index 7a6e9902d26..c82fb35b3a9 100644 --- a/jstests/core/profile_getmore.js +++ b/jstests/core/profile_getmore.js @@ -8,6 +8,7 @@ var testDB = db.getSiblingDB("profile_getmore"); assert.commandWorked(testDB.dropDatabase()); var coll = testDB.getCollection("test"); + var isLegacyReadMode = (db.getMongo().readMode() === "legacy"); testDB.setProfilingLevel(2); @@ -20,7 +21,7 @@ } assert.commandWorked(coll.createIndex({a: 1})); - var cursor = coll.find({a: {$gt: 0}}).batchSize(2); + var cursor = coll.find({a: {$gt: 0}}).sort({a: 1}).batchSize(2); cursor.next(); // Perform initial query and consume first of 2 docs returned. var cursorId = getLatestProfilerEntry(testDB).cursorid; // Save cursorid from find. @@ -37,6 +38,10 @@ assert.eq(profileObj.cursorid, cursorId, tojson(profileObj)); assert.eq(profileObj.nreturned, 2, tojson(profileObj)); assert.eq(profileObj.query.batchSize, 2, tojson(profileObj)); + if (!isLegacyReadMode) { + assert.eq(profileObj.originatingCommand.filter, {a: {$gt: 0}}); + assert.eq(profileObj.originatingCommand.sort, {a: 1}); + } assert.eq(profileObj.planSummary, "IXSCAN { a: 1.0 }", tojson(profileObj)); assert(profileObj.execStats.hasOwnProperty("stage"), tojson(profileObj)); assert(profileObj.hasOwnProperty("responseLength"), tojson(profileObj)); @@ -83,4 +88,36 @@ tojson(profileObj)); // cursorid should always be present on getMore. assert.neq(0, profileObj.cursorid, tojson(profileObj)); assert.eq(profileObj.cursorExhausted, true, tojson(profileObj)); -})();
\ No newline at end of file + + // + // Confirm getMore on aggregation. + // + coll.drop(); + for (i = 0; i < 10; ++i) { + assert.writeOK(coll.insert({a: i})); + } + assert.commandWorked(coll.createIndex({a: 1})); + + var cursor = coll.aggregate([{$match: {a: {$gt: 0}}}], {cursor: {batchSize: 2}}); + cursor.next(); // Perform initial query and consume first of 2 docs returned. + + var cursorId = getLatestProfilerEntry(testDB).cursorid; // Save cursorid from find. + + cursor.next(); // Consume second of 2 docs from initial query. + cursor.next(); // getMore performed, leaving open cursor. + + var profileObj = getLatestProfilerEntry(testDB); + + assert.eq(profileObj.ns, coll.getFullName(), tojson(profileObj)); + assert.eq(profileObj.op, "getmore", tojson(profileObj)); + if (!isLegacyReadMode) { + assert.eq( + profileObj.originatingCommand.pipeline[0], {$match: {a: {$gt: 0}}}, tojson(profileObj)); + } + assert.eq(profileObj.cursorid, cursorId, tojson(profileObj)); + + // TODO SERVER-23265 - The following values are incorrect. Fix to report correct values. + assert.eq(profileObj.keysExamined, 0, tojson(profileObj)); + assert.eq(profileObj.docsExamined, 0, tojson(profileObj)); + assert.eq(profileObj.nreturned, 7, tojson(profileObj)); +})(); diff --git a/jstests/noPassthrough/currentop_query.js b/jstests/noPassthrough/currentop_query.js index b72da385564..5847ff7015e 100644 --- a/jstests/noPassthrough/currentop_query.js +++ b/jstests/noPassthrough/currentop_query.js @@ -222,7 +222,10 @@ db.runCommand({getMore: TestData.cursorId, collection: "currentop_query"})); }, planSummary: "COLLSCAN", - currentOpFilter: {"query.getMore": TestData.cursorId} + currentOpFilter: { + "query.getMore": TestData.cursorId, + "originatingCommand.filter.$comment": "currentop_query" + } }); delete TestData.cursorId; diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp index 15b512b5d71..dc536e838b6 100644 --- a/src/mongo/db/commands/find_cmd.cpp +++ b/src/mongo/db/commands/find_cmd.cpp @@ -321,7 +321,7 @@ public: nss.ns(), txn->recoveryUnit()->isReadingFromMajorityCommittedSnapshot(), originalQR.getOptions(), - originalQR.getFilter()); + cmdObj.getOwned()); cursorId = cursor->cursorid(); invariant(!exec); diff --git a/src/mongo/db/commands/getmore_cmd.cpp b/src/mongo/db/commands/getmore_cmd.cpp index c2d4bd0da2f..6edd1b7bea2 100644 --- a/src/mongo/db/commands/getmore_cmd.cpp +++ b/src/mongo/db/commands/getmore_cmd.cpp @@ -307,9 +307,17 @@ public: exec->reattachToOperationContext(txn); exec->restoreState(); + auto planSummary = Explain::getPlanSummary(exec); { stdx::lock_guard<Client>(*txn->getClient()); - curOp->setPlanSummary_inlock(Explain::getPlanSummary(exec)); + curOp->setPlanSummary_inlock(planSummary); + + // Ensure that the original query or command object is available in the slow query log, + // profiler and currentOp. + auto originatingCommand = cursor->getQuery(); + if (!originatingCommand.isEmpty()) { + curOp->setOriginatingCommand_inlock(originatingCommand); + } } uint64_t notifierVersion = 0; diff --git a/src/mongo/db/curop.cpp b/src/mongo/db/curop.cpp index e3906d29de9..9562f3dff0e 100644 --- a/src/mongo/db/curop.cpp +++ b/src/mongo/db/curop.cpp @@ -346,6 +346,10 @@ void CurOp::reportState(BSONObjBuilder* builder) { appendAsObjOrString("query", _query, maxQuerySize, builder); } + if (!_originatingCommand.isEmpty()) { + appendAsObjOrString("originatingCommand", _originatingCommand, maxQuerySize, builder); + } + if (!_planSummary.empty()) { builder->append("planSummary", _planSummary); } @@ -415,6 +419,11 @@ string OpDebug::report(const CurOp& curop, const SingleThreadedLockStats& lockSt } } + auto originatingCommand = curop.originatingCommand(); + if (!originatingCommand.isEmpty()) { + s << " originatingCommand: " << originatingCommand; + } + if (!curop.getPlanSummary().empty()) { s << " planSummary: " << curop.getPlanSummary(); } @@ -516,6 +525,11 @@ void OpDebug::append(const CurOp& curop, appendAsObjOrString(fieldName, curop.query(), maxElementSize, &b); } + auto originatingCommand = curop.originatingCommand(); + if (!originatingCommand.isEmpty()) { + appendAsObjOrString("originatingCommand", originatingCommand, maxElementSize, &b); + } + if (!updateobj.isEmpty()) { appendAsObjOrString("updateobj", updateobj, maxElementSize, &b); } diff --git a/src/mongo/db/curop.h b/src/mongo/db/curop.h index eee95967b96..fc8612f7acc 100644 --- a/src/mongo/db/curop.h +++ b/src/mongo/db/curop.h @@ -173,6 +173,14 @@ public: return _query; } + /** + * Returns an owned BSONObj representing the original command. Used only by the getMore + * command. + */ + BSONObj originatingCommand() const { + return _originatingCommand; + } + void enter_inlock(const char* ns, int dbProfileLevel); /** @@ -293,6 +301,13 @@ public: _query = query; } + /** + * Sets the original command object. Used only by the getMore command. + */ + void setOriginatingCommand_inlock(const BSONObj& commandObj) { + _originatingCommand = commandObj.getOwned(); + } + Command* getCommand() const { return _command; } @@ -398,6 +413,7 @@ private: int _dbprofile{0}; // 0=off, 1=slow, 2=all std::string _ns; BSONObj _query; + BSONObj _originatingCommand; // Used by getMore to display original command. OpDebug _debug; std::string _message; ProgressMeter _progressMeter; diff --git a/src/mongo/db/query/find.cpp b/src/mongo/db/query/find.cpp index 5b365500e16..fa4f0e53834 100644 --- a/src/mongo/db/query/find.cpp +++ b/src/mongo/db/query/find.cpp @@ -333,13 +333,6 @@ QueryResult::View getMore(OperationContext* txn, } txn->checkForInterrupt(); // May trigger maxTimeAlwaysTimeOut fail point. - // Ensure that the original query or command object is available in the slow query log, - // profiler, and currentOp. - { - stdx::lock_guard<Client> lk(*txn->getClient()); - curOp.setQuery_inlock(cc->getQuery()); - } - cc->updateSlaveLocation(txn); if (cc->isAggCursor()) { @@ -372,9 +365,14 @@ QueryResult::View getMore(OperationContext* txn, exec->reattachToOperationContext(txn); exec->restoreState(); + auto planSummary = Explain::getPlanSummary(exec); { stdx::lock_guard<Client>(*txn->getClient()); - CurOp::get(txn)->setPlanSummary_inlock(Explain::getPlanSummary(exec)); + curOp.setPlanSummary_inlock(planSummary); + + // Ensure that the original query or command object is available in the slow query log, + // profiler and currentOp. + curOp.setQuery_inlock(cc->getQuery()); } PlanExecutor::ExecState state; |