summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Wahlin <james.wahlin@10gen.com>2016-05-20 16:42:09 -0400
committerJames Wahlin <james.wahlin@10gen.com>2016-06-03 20:58:42 -0400
commit94b2682abc46a7739e52bba12b3ecdae16b5f8e8 (patch)
tree9b95d30ba9966b119fa18175c26d95ff548a2c19
parentbd5ef88fd884a2cc95eab6d4b66ce09d5efacb81 (diff)
downloadmongo-94b2682abc46a7739e52bba12b3ecdae16b5f8e8.tar.gz
SERVER-23260 Report original query with getMore
-rw-r--r--jstests/core/profile_getmore.js41
-rw-r--r--jstests/noPassthrough/currentop_query.js5
-rw-r--r--src/mongo/db/commands/find_cmd.cpp2
-rw-r--r--src/mongo/db/commands/getmore_cmd.cpp10
-rw-r--r--src/mongo/db/curop.cpp14
-rw-r--r--src/mongo/db/curop.h16
-rw-r--r--src/mongo/db/query/find.cpp14
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;