diff options
author | David Hatch <david.hatch@mongodb.com> | 2016-07-15 17:17:26 -0400 |
---|---|---|
committer | David Hatch <david.hatch@mongodb.com> | 2016-07-20 17:25:21 -0400 |
commit | 5ecb390a5ec416b995f2049c1fdc25c84d2c885a (patch) | |
tree | 3c8908a571c5638f66c3dc901632f0497d5b97f2 | |
parent | 4f763e1509ab88aef9c9e7db45d9699f94382bf2 (diff) | |
download | mongo-5ecb390a5ec416b995f2049c1fdc25c84d2c885a.tar.gz |
SERVER-24063 Add collation to logs, profile and currentOp.
-rw-r--r-- | jstests/core/profile_agg.js | 5 | ||||
-rw-r--r-- | jstests/core/profile_count.js | 3 | ||||
-rw-r--r-- | jstests/core/profile_delete.js | 8 | ||||
-rw-r--r-- | jstests/core/profile_distinct.js | 3 | ||||
-rw-r--r-- | jstests/core/profile_find.js | 12 | ||||
-rw-r--r-- | jstests/core/profile_findandmodify.js | 7 | ||||
-rw-r--r-- | jstests/core/profile_geonear.js | 11 | ||||
-rw-r--r-- | jstests/core/profile_group.js | 11 | ||||
-rw-r--r-- | jstests/core/profile_mapreduce.js | 5 | ||||
-rw-r--r-- | jstests/core/profile_update.js | 8 | ||||
-rw-r--r-- | jstests/noPassthrough/currentop_query.js | 96 | ||||
-rw-r--r-- | src/mongo/db/curop.cpp | 15 | ||||
-rw-r--r-- | src/mongo/db/curop.h | 17 | ||||
-rw-r--r-- | src/mongo/db/ops/write_ops_exec.cpp | 2 |
14 files changed, 161 insertions, 42 deletions
diff --git a/jstests/core/profile_agg.js b/jstests/core/profile_agg.js index 096e33c9fe4..ede6f20f85d 100644 --- a/jstests/core/profile_agg.js +++ b/jstests/core/profile_agg.js @@ -22,7 +22,7 @@ } assert.commandWorked(coll.createIndex({a: 1})); - assert.eq(8, coll.aggregate([{$match: {a: {$gte: 2}}}]).itcount()); + assert.eq(8, coll.aggregate([{$match: {a: {$gte: 2}}}], {collation: {locale: "fr"}}).itcount()); var profileObj = getLatestProfilerEntry(testDB); assert.eq(profileObj.ns, coll.getFullName(), tojson(profileObj)); @@ -33,6 +33,7 @@ assert.eq(profileObj.planSummary, "IXSCAN { a: 1.0 }", tojson(profileObj)); assert.eq(profileObj.protocol, getProfilerProtocolStringForCommand(conn), tojson(profileObj)); assert.eq(profileObj.command.aggregate, coll.getName(), tojson(profileObj)); + assert.eq(profileObj.command.collation, {locale: "fr"}, tojson(profileObj)); assert(profileObj.hasOwnProperty("responseLength"), tojson(profileObj)); assert(profileObj.hasOwnProperty("millis"), tojson(profileObj)); assert(profileObj.hasOwnProperty("numYield"), tojson(profileObj)); @@ -66,4 +67,4 @@ profileObj = getLatestProfilerEntry(testDB); assert.eq(profileObj.fromMultiPlanner, true, tojson(profileObj)); -})();
\ No newline at end of file +})(); diff --git a/jstests/core/profile_count.js b/jstests/core/profile_count.js index d79fb94df85..0b04dca01ea 100644 --- a/jstests/core/profile_count.js +++ b/jstests/core/profile_count.js @@ -21,7 +21,7 @@ assert.writeOK(coll.insert({a: i})); } - assert.eq(10, coll.count()); + assert.eq(10, coll.count({}, {collation: {locale: "fr"}})); var profileObj = getLatestProfilerEntry(testDB); @@ -29,6 +29,7 @@ assert.eq(profileObj.op, "command", tojson(profileObj)); assert.eq(profileObj.protocol, getProfilerProtocolStringForCommand(conn), tojson(profileObj)); assert.eq(profileObj.command.count, coll.getName(), tojson(profileObj)); + assert.eq(profileObj.command.collation, {locale: "fr"}, tojson(profileObj)); assert.eq(profileObj.planSummary, "COUNT", tojson(profileObj)); assert(profileObj.execStats.hasOwnProperty("stage"), tojson(profileObj)); assert(profileObj.hasOwnProperty("responseLength"), tojson(profileObj)); diff --git a/jstests/core/profile_delete.js b/jstests/core/profile_delete.js index b5906addd9b..5ff39cb026e 100644 --- a/jstests/core/profile_delete.js +++ b/jstests/core/profile_delete.js @@ -21,12 +21,18 @@ } assert.commandWorked(coll.createIndex({a: 1})); - assert.writeOK(coll.remove({a: {$gte: 2}, b: {$gte: 2}}, {justOne: true})); + assert.writeOK(coll.remove({a: {$gte: 2}, b: {$gte: 2}}, + db.getMongo().writeMode() === "commands" + ? {justOne: true, collation: {locale: "fr"}} + : {justOne: true})); var profileObj = getLatestProfilerEntry(testDB); assert.eq(profileObj.ns, coll.getFullName(), tojson(profileObj)); assert.eq(profileObj.op, "remove", tojson(profileObj)); + if (db.getMongo().writeMode() === "commands") { + assert.eq(profileObj.collation, {locale: "fr"}, tojson(profileObj)); + } assert.eq(profileObj.ndeleted, 1, tojson(profileObj)); assert.eq(profileObj.keysExamined, 1, tojson(profileObj)); assert.eq(profileObj.docsExamined, 1, tojson(profileObj)); diff --git a/jstests/core/profile_distinct.js b/jstests/core/profile_distinct.js index 0549b181b7a..878c681df0a 100644 --- a/jstests/core/profile_distinct.js +++ b/jstests/core/profile_distinct.js @@ -22,7 +22,7 @@ } assert.commandWorked(coll.createIndex({b: 1})); - coll.distinct("a", {b: {$gte: 5}}); + coll.distinct("a", {b: {$gte: 5}}, {collation: {locale: "fr"}}); var profileObj = getLatestProfilerEntry(testDB); assert.eq(profileObj.ns, coll.getFullName(), tojson(profileObj)); @@ -33,6 +33,7 @@ assert(profileObj.execStats.hasOwnProperty("stage"), tojson(profileObj)); assert.eq(profileObj.protocol, getProfilerProtocolStringForCommand(conn), tojson(profileObj)); assert.eq(coll.getName(), profileObj.command.distinct, tojson(profileObj)); + assert.eq(profileObj.command.collation, {locale: "fr"}, tojson(profileObj)); assert(profileObj.hasOwnProperty("responseLength"), tojson(profileObj)); assert(profileObj.hasOwnProperty("millis"), tojson(profileObj)); assert(profileObj.hasOwnProperty("numYield"), tojson(profileObj)); diff --git a/jstests/core/profile_find.js b/jstests/core/profile_find.js index c9a6d7bed8c..af042f44378 100644 --- a/jstests/core/profile_find.js +++ b/jstests/core/profile_find.js @@ -21,9 +21,13 @@ for (i = 0; i < 3; ++i) { assert.writeOK(coll.insert({a: i, b: i})); } - assert.commandWorked(coll.createIndex({a: 1})); + assert.commandWorked(coll.createIndex({a: 1}, {collation: {locale: "fr"}})); - assert.neq(coll.findOne({a: 1}), null); + if (!isLegacyReadMode) { + assert.eq(coll.find({a: 1}).collation({locale: "fr"}).limit(1).itcount(), 1); + } else { + assert.neq(coll.findOne({a: 1}), null); + } var profileObj = getLatestProfilerEntry(testDB); @@ -42,6 +46,10 @@ assert.eq( profileObj.protocol, getProfilerProtocolStringForCommand(conn), tojson(profileObj)); } + + if (!isLegacyReadMode) { + assert.eq(profileObj.query.collation, {locale: "fr"}); + } assert.eq(profileObj.cursorExhausted, true, tojson(profileObj)); assert(!profileObj.hasOwnProperty("cursorid"), tojson(profileObj)); assert(profileObj.hasOwnProperty("responseLength"), tojson(profileObj)); diff --git a/jstests/core/profile_findandmodify.js b/jstests/core/profile_findandmodify.js index 91ea534cf6d..1a51bd527ec 100644 --- a/jstests/core/profile_findandmodify.js +++ b/jstests/core/profile_findandmodify.js @@ -20,7 +20,9 @@ } assert.commandWorked(coll.createIndex({b: 1})); - assert.eq({_id: 2, a: 2, b: 2}, coll.findAndModify({query: {a: 2}, update: {$inc: {b: 1}}})); + assert.eq( + {_id: 2, a: 2, b: 2}, + coll.findAndModify({query: {a: 2}, update: {$inc: {b: 1}}, collation: {locale: "fr"}})); var profileObj = getLatestProfilerEntry(testDB); @@ -28,6 +30,7 @@ assert.eq(profileObj.ns, coll.getFullName(), tojson(profileObj)); assert.eq(profileObj.command.query, {a: 2}, tojson(profileObj)); assert.eq(profileObj.command.update, {$inc: {b: 1}}, tojson(profileObj)); + assert.eq(profileObj.command.collation, {locale: "fr"}, tojson(profileObj)); assert.eq(profileObj.updateobj, {$inc: {b: 1}}, tojson(profileObj)); assert.eq(profileObj.keysExamined, 0, tojson(profileObj)); assert.eq(profileObj.docsExamined, 3, tojson(profileObj)); @@ -173,4 +176,4 @@ profileObj = getLatestProfilerEntry(testDB); assert.eq(profileObj.fromMultiPlanner, true, tojson(profileObj)); -})();
\ No newline at end of file +})(); diff --git a/jstests/core/profile_geonear.js b/jstests/core/profile_geonear.js index d9c53487e8c..dd348e4c645 100644 --- a/jstests/core/profile_geonear.js +++ b/jstests/core/profile_geonear.js @@ -22,8 +22,12 @@ } assert.commandWorked(coll.createIndex({loc: "2dsphere"})); - assert.commandWorked(testDB.runCommand( - {geoNear: "test", near: {type: "Point", coordinates: [1, 1]}, spherical: true})); + assert.commandWorked(testDB.runCommand({ + geoNear: "test", + near: {type: "Point", coordinates: [1, 1]}, + spherical: true, + collation: {locale: "fr"} + })); var profileObj = getLatestProfilerEntry(testDB); @@ -36,6 +40,7 @@ assert(profileObj.hasOwnProperty("execStats"), tojson(profileObj)); assert.eq(profileObj.protocol, getProfilerProtocolStringForCommand(conn), tojson(profileObj)); assert.eq(coll.getName(), profileObj.command.geoNear, tojson(profileObj)); + assert.eq({locale: "fr"}, profileObj.command.collation, tojson(profileObj)); assert(profileObj.hasOwnProperty("responseLength"), tojson(profileObj)); assert(profileObj.hasOwnProperty("millis"), tojson(profileObj)); assert(profileObj.hasOwnProperty("numYield"), tojson(profileObj)); @@ -46,4 +51,4 @@ // - geoNear requires at least one "2d" or "2dsphere" index // - geoNear requires there be at most one 2dsphere and at most one 2d index // - geoNear will always prefer a 2d index over a 2dsphere index if both are defined -})();
\ No newline at end of file +})(); diff --git a/jstests/core/profile_group.js b/jstests/core/profile_group.js index a6942f05886..dcbf4c8611f 100644 --- a/jstests/core/profile_group.js +++ b/jstests/core/profile_group.js @@ -22,7 +22,13 @@ } assert.commandWorked(coll.createIndex({b: 1})); - coll.group({key: {a: 1, b: 1}, cond: {b: 3}, reduce: function() {}, initial: {}}); + coll.group({ + key: {a: 1, b: 1}, + cond: {b: 3}, + reduce: function() {}, + initial: {}, + collation: {locale: "fr"} + }); var profileObj = getLatestProfilerEntry(testDB); assert.eq(profileObj.ns, coll.getFullName(), tojson(profileObj)); @@ -33,6 +39,7 @@ assert(profileObj.execStats.hasOwnProperty("stage"), tojson(profileObj)); assert.eq(profileObj.protocol, getProfilerProtocolStringForCommand(conn), tojson(profileObj)); assert.eq(profileObj.command.group.key, {a: 1, b: 1}, tojson(profileObj)); + assert.eq(profileObj.command.group.collation, {locale: "fr"}, tojson(profileObj)); assert(profileObj.hasOwnProperty("responseLength"), tojson(profileObj)); assert(profileObj.command.hasOwnProperty("group"), tojson(profileObj)); assert(profileObj.hasOwnProperty("millis"), tojson(profileObj)); @@ -53,4 +60,4 @@ profileObj = getLatestProfilerEntry(testDB); assert.eq(profileObj.fromMultiPlanner, true, tojson(profileObj)); -})();
\ No newline at end of file +})(); diff --git a/jstests/core/profile_mapreduce.js b/jstests/core/profile_mapreduce.js index 2538862ebba..20e3b2e8fbf 100644 --- a/jstests/core/profile_mapreduce.js +++ b/jstests/core/profile_mapreduce.js @@ -30,7 +30,9 @@ } assert.commandWorked(coll.createIndex({a: 1})); - coll.mapReduce(mapFunction, reduceFunction, {query: {a: {$gte: 0}}, out: {inline: 1}}); + coll.mapReduce(mapFunction, + reduceFunction, + {query: {a: {$gte: 0}}, out: {inline: 1}, collation: {locale: "fr"}}); var profileObj = getLatestProfilerEntry(testDB); @@ -42,6 +44,7 @@ assert(profileObj.execStats.hasOwnProperty("stage"), tojson(profileObj)); assert.eq(profileObj.protocol, getProfilerProtocolStringForCommand(conn), tojson(profileObj)); assert.eq(coll.getName(), profileObj.command.mapreduce, tojson(profileObj)); + assert.eq({locale: "fr"}, profileObj.command.collation, tojson(profileObj)); assert(profileObj.hasOwnProperty("responseLength"), tojson(profileObj)); assert(profileObj.hasOwnProperty("millis"), tojson(profileObj)); assert(profileObj.hasOwnProperty("numYield"), tojson(profileObj)); diff --git a/jstests/core/profile_update.js b/jstests/core/profile_update.js index 215a8942d9c..1132e63a57f 100644 --- a/jstests/core/profile_update.js +++ b/jstests/core/profile_update.js @@ -21,12 +21,18 @@ } assert.commandWorked(coll.createIndex({a: 1})); - assert.writeOK(coll.update({a: {$gte: 2}}, {$set: {c: 1}, $inc: {a: -10}})); + assert.writeOK( + coll.update({a: {$gte: 2}}, + {$set: {c: 1}, $inc: {a: -10}}, + db.getMongo().writeMode() === "commands" ? {collation: {locale: "fr"}} : {})); var profileObj = getLatestProfilerEntry(testDB); assert.eq(profileObj.ns, coll.getFullName(), tojson(profileObj)); assert.eq(profileObj.op, "update", tojson(profileObj)); + if (db.getMongo().writeMode() === "commands") { + assert.eq(profileObj.collation, {locale: "fr"}, tojson(profileObj)); + } assert.eq(profileObj.keysExamined, 1, tojson(profileObj)); assert.eq(profileObj.docsExamined, 1, tojson(profileObj)); assert.eq(profileObj.keysInserted, 1, tojson(profileObj)); diff --git a/jstests/noPassthrough/currentop_query.js b/jstests/noPassthrough/currentop_query.js index 7b607d03966..287678b4eab 100644 --- a/jstests/noPassthrough/currentop_query.js +++ b/jstests/noPassthrough/currentop_query.js @@ -96,32 +96,42 @@ var testList = [ { test: function() { - assert.eq( - db.currentop_query.aggregate([{$match: {a: 1, $comment: "currentop_query"}}]) - .itcount(), - 1); + assert.eq(db.currentop_query + .aggregate([{$match: {a: 1, $comment: "currentop_query"}}], + {collation: {locale: "fr"}}) + .itcount(), + 1); }, command: "aggregate", planSummary: "COLLSCAN", - currentOpFilter: {"query.pipeline.0.$match.$comment": "currentop_query"} + currentOpFilter: { + "query.pipeline.0.$match.$comment": "currentop_query", + "query.collation": {locale: "fr"} + } }, { test: function() { - assert.eq(db.currentop_query.find({a: 1, $comment: "currentop_query"}).count(), + assert.eq(db.currentop_query.find({a: 1, $comment: "currentop_query"}) + .collation({locale: "fr"}) + .count(), 1); }, command: "count", planSummary: "COLLSCAN", - currentOpFilter: {"query.query.$comment": "currentop_query"} + currentOpFilter: + {"query.query.$comment": "currentop_query", "query.collation": {locale: "fr"}} }, { test: function() { - assert.eq(db.currentop_query.distinct("a", {a: 1, $comment: "currentop_query"}), - [1]); + assert.eq( + db.currentop_query.distinct( + "a", {a: 1, $comment: "currentop_query"}, {collation: {locale: "fr"}}), + [1]); }, command: "distinct", planSummary: "COLLSCAN", - currentOpFilter: {"query.query.$comment": "currentop_query"} + currentOpFilter: + {"query.query.$comment": "currentop_query", "query.collation": {locale: "fr"}} }, { test: function() { @@ -134,14 +144,17 @@ }, { test: function() { - assert.eq( - db.currentop_query.findAndModify( - {query: {a: 1, $comment: "currentop_query"}, update: {$inc: {b: 1}}}), - {"_id": 1, "a": 1}); + assert.eq(db.currentop_query.findAndModify({ + query: {a: 1, $comment: "currentop_query"}, + update: {$inc: {b: 1}}, + collation: {locale: "fr"} + }), + {"_id": 1, "a": 1}); }, command: "findandmodify", planSummary: "COLLSCAN", - currentOpFilter: {"query.query.$comment": "currentop_query"} + currentOpFilter: + {"query.query.$comment": "currentop_query", "query.collation": {locale: "fr"}} }, { test: function() { @@ -149,13 +162,17 @@ key: {a: 1}, cond: {a: 1, $comment: "currentop_query"}, reduce: function() {}, - initial: {} + initial: {}, + collation: {locale: "fr"} }), [{"a": 1}]); }, command: "group", planSummary: "COLLSCAN", - currentOpFilter: {"query.group.cond.$comment": "currentop_query"} + currentOpFilter: { + "query.group.cond.$comment": "currentop_query", + "query.group.collation": {locale: "fr"} + } }, { test: function() { @@ -166,28 +183,35 @@ function(a, b) { return Array.sum(b); }, - {query: {a: 1, $comment: "currentop_query"}, out: {inline: 1}})); + { + query: {a: 1, $comment: "currentop_query"}, + out: {inline: 1}, + collation: {locale: "fr"} + })); }, command: "mapreduce", planSummary: "COLLSCAN", - currentOpFilter: {"query.query.$comment": "currentop_query"} + currentOpFilter: + {"query.query.$comment": "currentop_query", "query.collation": {locale: "fr"}} }, { test: function() { - assert.writeOK(db.currentop_query.remove({a: 2, $comment: "currentop_query"})); + assert.writeOK(db.currentop_query.remove({a: 2, $comment: "currentop_query"}, + {collation: {locale: "fr"}})); }, operation: "remove", planSummary: "COLLSCAN", - currentOpFilter: {"query.$comment": "currentop_query"} + currentOpFilter: {"query.$comment": "currentop_query", "collation": {locale: "fr"}} }, { test: function() { assert.writeOK(db.currentop_query.update({a: 1, $comment: "currentop_query"}, - {$inc: {b: 1}})); + {$inc: {b: 1}}, + {collation: {locale: "fr"}})); }, operation: "update", planSummary: "COLLSCAN", - currentOpFilter: {"query.$comment": "currentop_query"} + currentOpFilter: {"query.$comment": "currentop_query", "collation": {locale: "fr"}} } ]; @@ -200,6 +224,25 @@ testList.forEach(confirmCurrentOpContents); // + // Confirm currentOp contains collation for find command. + // + if (params.readMode === "commands") { + confirmCurrentOpContents({ + test: function() { + assert.eq(db.currentop_query.find({a: 1}) + .comment("currentop_query") + .collation({locale: "fr"}) + .itcount(), + 1); + }, + command: "find", + planSummary: "COLLSCAN", + currentOpFilter: + {"query.comment": "currentop_query", "query.collation": {locale: "fr"}} + }); + } + + // // Confirm currentOp content for geoNear. // coll.drop(); @@ -214,12 +257,14 @@ geoNear: "currentop_query", near: {type: "Point", coordinates: [1, 1]}, spherical: true, - query: {$comment: "currentop_query"} + query: {$comment: "currentop_query"}, + collation: {locale: "fr"} })); }, command: "geoNear", planSummary: "GEO_NEAR_2DSPHERE { loc: \"2dsphere\" }", - currentOpFilter: {"query.query.$comment": "currentop_query"} + currentOpFilter: + {"query.query.$comment": "currentop_query", "query.collation": {locale: "fr"}} }); // @@ -294,5 +339,4 @@ runTest({readMode: "commands"}); runTest({readMode: "legacy"}); - })(); diff --git a/src/mongo/db/curop.cpp b/src/mongo/db/curop.cpp index 5c4e4ce118e..9368fe7290f 100644 --- a/src/mongo/db/curop.cpp +++ b/src/mongo/db/curop.cpp @@ -361,6 +361,10 @@ void CurOp::reportState(BSONObjBuilder* builder) { appendAsObjOrString("query", _query, maxQuerySize, builder); } + if (!_collation.isEmpty()) { + appendAsObjOrString("collation", _collation, maxQuerySize, builder); + } + if (!_originatingCommand.isEmpty()) { appendAsObjOrString("originatingCommand", _originatingCommand, maxQuerySize, builder); } @@ -448,6 +452,12 @@ string OpDebug::report(const CurOp& curop, const SingleThreadedLockStats& lockSt updateobj.toString(s); } + auto collation = curop.collation(); + if (!collation.isEmpty()) { + s << " collation: "; + collation.toString(s); + } + OPDEBUG_TOSTRING_HELP(cursorid); OPDEBUG_TOSTRING_HELP(ntoreturn); OPDEBUG_TOSTRING_HELP(ntoskip); @@ -549,6 +559,11 @@ void OpDebug::append(const CurOp& curop, appendAsObjOrString("updateobj", updateobj, maxElementSize, &b); } + auto collation = curop.collation(); + if (!collation.isEmpty()) { + appendAsObjOrString("collation", collation, maxElementSize, &b); + } + OPDEBUG_APPEND_NUMBER(cursorid); OPDEBUG_APPEND_BOOL(exhaust); diff --git a/src/mongo/db/curop.h b/src/mongo/db/curop.h index d362fb0345d..0e487632e86 100644 --- a/src/mongo/db/curop.h +++ b/src/mongo/db/curop.h @@ -174,6 +174,14 @@ public: } /** + * The BSONObj returned may not be owned by CurOp. Callers should call getOwned() if they plan + * to reference beyond the lifetime of this CurOp instance. + */ + BSONObj collation() const { + return _collation; + } + + /** * Returns an owned BSONObj representing the original command. Used only by the getMore * command. */ @@ -302,6 +310,14 @@ public: } /** + * 'collation' must be either an owned BSONObj or guaranteed to outlive the OperationContext it + * is associated with. + */ + void setCollation_inlock(const BSONObj& collation) { + _collation = collation; + } + + /** * Sets the original command object. Used only by the getMore command. */ void setOriginatingCommand_inlock(const BSONObj& commandObj) { @@ -418,6 +434,7 @@ private: int _dbprofile{0}; // 0=off, 1=slow, 2=all std::string _ns; BSONObj _query; + BSONObj _collation; BSONObj _originatingCommand; // Used by getMore to display original command. OpDebug _debug; std::string _message; diff --git a/src/mongo/db/ops/write_ops_exec.cpp b/src/mongo/db/ops/write_ops_exec.cpp index bd8611c146d..1b24c7274b4 100644 --- a/src/mongo/db/ops/write_ops_exec.cpp +++ b/src/mongo/db/ops/write_ops_exec.cpp @@ -488,6 +488,7 @@ static WriteResult::SingleResult performSingleUpdateOp(OperationContext* txn, curOp.setNetworkOp_inlock(dbUpdate); curOp.setLogicalOp_inlock(LogicalOp::opUpdate); curOp.setQuery_inlock(op.query); + curOp.setCollation_inlock(op.collation); curOp.ensureStarted(); } @@ -604,6 +605,7 @@ static WriteResult::SingleResult performSingleDeleteOp(OperationContext* txn, curOp.setNetworkOp_inlock(dbDelete); curOp.setLogicalOp_inlock(LogicalOp::opDelete); curOp.setQuery_inlock(op.query); + curOp.setCollation_inlock(op.collation); curOp.ensureStarted(); } |