diff options
author | Bernard Gorman <bernard.gorman@gmail.com> | 2017-03-22 08:21:15 +0000 |
---|---|---|
committer | Bernard Gorman <bernard.gorman@gmail.com> | 2017-03-22 22:30:31 +0000 |
commit | 51d8b9c2f5eafc457f889d9786ebd68e4398ba64 (patch) | |
tree | 5f03f06ee26558803de1f8c7f40a6a6a7e5c09f7 /src | |
parent | 7b4770c1dbbc2a264a10f4fcfc87025ce832b680 (diff) | |
download | mongo-51d8b9c2f5eafc457f889d9786ebd68e4398ba64.tar.gz |
SERVER-27439 Large queries can omit comment in currentOp
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/curop.cpp | 67 |
1 files changed, 54 insertions, 13 deletions
diff --git a/src/mongo/db/curop.cpp b/src/mongo/db/curop.cpp index 2af0907170d..f4c028879c3 100644 --- a/src/mongo/db/curop.cpp +++ b/src/mongo/db/curop.cpp @@ -296,23 +296,30 @@ Command::ReadWriteType CurOp::getReadWriteType() const { } namespace { + +/** + * Used by callers of appendAsObjOrString to indicate whether a comment parameter may be present and + * should be retained upon truncation. + */ +enum class TruncationMode { kNoComment, kIncludeComment }; + /** - * Appends {name: obj} to the provided builder. If obj is greater than maxSize, appends a - * string summary of obj instead of the object itself. + * Appends {<name>: obj} to the provided builder. If obj is greater than maxSize, appends a string + * summary of obj as { <name>: { $truncated: "obj" } }. If a comment parameter is present, add it to + * the truncation object. */ void appendAsObjOrString(StringData name, const BSONObj& obj, size_t maxSize, - BSONObjBuilder* builder) { + BSONObjBuilder* builder, + TruncationMode truncateBehavior = TruncationMode::kNoComment) { if (static_cast<size_t>(obj.objsize()) <= maxSize) { builder->append(name, obj); } else { // Generate an abbreviated serialization for the object, by passing false as the // "full" argument to obj.toString(). std::string objToString = obj.toString(); - if (objToString.size() <= maxSize) { - builder->append(name, objToString); - } else { + if (objToString.size() > maxSize) { // objToString is still too long, so we append to the builder a truncated form // of objToString concatenated with "...". Instead of creating a new string // temporary, mutate objToString to do this (we know that we can mutate @@ -320,8 +327,22 @@ void appendAsObjOrString(StringData name, objToString[maxSize - 3] = '.'; objToString[maxSize - 2] = '.'; objToString[maxSize - 1] = '.'; - builder->append(name, StringData(objToString).substr(0, maxSize)); } + + StringData truncation = StringData(objToString).substr(0, maxSize); + + // Append the truncated representation of the object to the builder. If this is an operation + // which supports a comment parameter and one is present, write it to the object alongside + // the truncated op. This object will appear as {$truncated: "{find: \"collection\", filter: + // {x: 1, ...", comment: "comment text" } + BSONObjBuilder truncatedBuilder(builder->subobjStart(name)); + truncatedBuilder.append("$truncated", truncation); + + if (truncateBehavior == TruncationMode::kIncludeComment && obj["comment"]) { + truncatedBuilder.append(obj["comment"]); + } + + truncatedBuilder.doneFast(); } } } // namespace @@ -354,9 +375,15 @@ void CurOp::reportState(BSONObjBuilder* builder) { appendAsObjOrString("query", upconvertQueryEntry(_query, NamespaceString(_ns), ntoreturn, ntoskip), maxQuerySize, - builder); + builder, + TruncationMode::kIncludeComment); } else { - appendAsObjOrString("query", _query, maxQuerySize, builder); + appendAsObjOrString( + "query", + _query, + maxQuerySize, + builder, + (_isCommand ? TruncationMode::kIncludeComment : TruncationMode::kNoComment)); } if (!_collation.isEmpty()) { @@ -364,7 +391,11 @@ void CurOp::reportState(BSONObjBuilder* builder) { } if (!_originatingCommand.isEmpty()) { - appendAsObjOrString("originatingCommand", _originatingCommand, maxQuerySize, builder); + appendAsObjOrString("originatingCommand", + _originatingCommand, + maxQuerySize, + builder, + TruncationMode::kIncludeComment); } if (!_planSummary.empty()) { @@ -557,15 +588,25 @@ void OpDebug::append(const CurOp& curop, appendAsObjOrString("query", upconvertQueryEntry(curop.query(), nss, ntoreturn, ntoskip), maxElementSize, - &b); + &b, + TruncationMode::kIncludeComment); } else if (curop.haveQuery()) { const char* fieldName = (logicalOp == LogicalOp::opCommand) ? "command" : "query"; - appendAsObjOrString(fieldName, curop.query(), maxElementSize, &b); + appendAsObjOrString( + fieldName, + curop.query(), + maxElementSize, + &b, + (iscommand ? TruncationMode::kIncludeComment : TruncationMode::kNoComment)); } auto originatingCommand = curop.originatingCommand(); if (!originatingCommand.isEmpty()) { - appendAsObjOrString("originatingCommand", originatingCommand, maxElementSize, &b); + appendAsObjOrString("originatingCommand", + originatingCommand, + maxElementSize, + &b, + TruncationMode::kIncludeComment); } if (!updateobj.isEmpty()) { |