summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jstests/core/list_databases.js4
-rw-r--r--jstests/core/views/views_all_commands.js2
-rw-r--r--jstests/sharding/logical_time_api.js4
-rw-r--r--jstests/sharding/logical_time_metadata.js6
-rw-r--r--src/mongo/db/commands.h2
-rw-r--r--src/mongo/db/repl/repl_set_request_votes_args.cpp2
-rw-r--r--src/mongo/rpc/metadata.cpp25
-rw-r--r--src/mongo/rpc/metadata/logical_time_metadata.h2
-rw-r--r--src/mongo/rpc/metadata/logical_time_metadata_test.cpp40
-rw-r--r--src/mongo/shell/mongo.js22
10 files changed, 86 insertions, 23 deletions
diff --git a/jstests/core/list_databases.js b/jstests/core/list_databases.js
index cf6dc7aa9c1..80df62f2d1d 100644
--- a/jstests/core/list_databases.js
+++ b/jstests/core/list_databases.js
@@ -18,8 +18,8 @@
function verifyNameOnly(listDatabasesOut) {
for (let field in listDatabasesOut) {
- assert(['databases', 'nameOnly', 'ok', 'operationTime', 'logicalTime'].some((f) => f ==
- field),
+ assert(['databases', 'nameOnly', 'ok', 'operationTime', '$logicalTime'].some((f) => f ==
+ field),
'unexpected field ' + field);
}
listDatabasesOut.databases.forEach((database) => {
diff --git a/jstests/core/views/views_all_commands.js b/jstests/core/views/views_all_commands.js
index 4b3db76e8c6..5e4132eb16b 100644
--- a/jstests/core/views/views_all_commands.js
+++ b/jstests/core/views/views_all_commands.js
@@ -315,7 +315,7 @@
ok: 1
};
delete res.operationTime;
- delete res.logicalTime;
+ delete res.$logicalTime;
assert.eq(expectedRes, res, "unexpected result for: " + tojson(killCursorsCmd));
}
},
diff --git a/jstests/sharding/logical_time_api.js b/jstests/sharding/logical_time_api.js
index fc8a03ceb35..03eb172d11e 100644
--- a/jstests/sharding/logical_time_api.js
+++ b/jstests/sharding/logical_time_api.js
@@ -11,7 +11,7 @@
"use strict";
// Returns true if the given object contains a logicalTime BSON object in the following format:
- // logicalTime: {
+ // $logicalTime: {
// clusterTime: <Timestamp>
// signature: {
// hash: <BinData>
@@ -23,7 +23,7 @@
return false;
}
- var logicalTime = obj.logicalTime;
+ var logicalTime = obj.$logicalTime;
return logicalTime && isType(logicalTime, "BSON") &&
isType(logicalTime.clusterTime, "Timestamp") && isType(logicalTime.signature, "BSON") &&
isType(logicalTime.signature.hash, "BinData") &&
diff --git a/jstests/sharding/logical_time_metadata.js b/jstests/sharding/logical_time_metadata.js
index efb1fcc785c..d62121d584b 100644
--- a/jstests/sharding/logical_time_metadata.js
+++ b/jstests/sharding/logical_time_metadata.js
@@ -11,9 +11,9 @@
// insert on one shard and extract the logical time
var res = assert.commandWorked(db.runCommand({insert: 'user', documents: [{x: 10}]}));
- assert.hasFields(res, ['logicalTime']);
+ assert.hasFields(res, ['$logicalTime']);
- var logicalTimeMetadata = res.logicalTime;
+ var logicalTimeMetadata = res.$logicalTime;
assert.hasFields(logicalTimeMetadata, ['clusterTime', 'signature']);
res = st.rs0.getPrimary().adminCommand({replSetGetStatus: 1});
@@ -24,7 +24,7 @@
'appliedTime: ' + tojson(appliedTime) + ' != clusterTime: ' +
tojson(logicalTimeMetadata.clusterTime));
- assert.commandWorked(db.runCommand({ping: 1, logicalTime: logicalTimeMetadata}));
+ assert.commandWorked(db.runCommand({ping: 1, '$logicalTime': logicalTimeMetadata}));
st.stop();
diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h
index a9bfc682712..e4a4ae30889 100644
--- a/src/mongo/db/commands.h
+++ b/src/mongo/db/commands.h
@@ -383,7 +383,7 @@ public:
arg == "$queryOptions" || //
arg == "$readPreference" || //
arg == "$replData" || //
- arg == "logicalTime" || //
+ arg == "$logicalTime" || //
arg == "maxTimeMS" || //
arg == "readConcern" || //
arg == "shardVersion" || //
diff --git a/src/mongo/db/repl/repl_set_request_votes_args.cpp b/src/mongo/db/repl/repl_set_request_votes_args.cpp
index ee15d31ae7b..f126f9ad7c4 100644
--- a/src/mongo/db/repl/repl_set_request_votes_args.cpp
+++ b/src/mongo/db/repl/repl_set_request_votes_args.cpp
@@ -69,7 +69,7 @@ const std::string kLegalResponseFieldNames[] = {
kVoteGrantedFieldName,
kOperationTime,
"$gleStats",
- "logicalTime",
+ "$logicalTime",
"$configServerState",
};
diff --git a/src/mongo/rpc/metadata.cpp b/src/mongo/rpc/metadata.cpp
index 77545303ff7..80046bdad58 100644
--- a/src/mongo/rpc/metadata.cpp
+++ b/src/mongo/rpc/metadata.cpp
@@ -183,17 +183,32 @@ CommandAndMetadata upconvertRequestMetadata(BSONObj legacyCmdObj, int queryFlags
uassertStatusOK(
AuditMetadata::upconvert(legacyCmdObj, queryFlags, &auditCommandBob, &metadataBob));
- return std::make_tuple(auditCommandBob.obj(), metadataBob.obj());
+ BSONObjBuilder logicalTimeCommandBob;
+ for (auto elem : auditCommandBob.done()) {
+ if (elem.fieldNameStringData() == LogicalTimeMetadata::fieldName()) {
+ metadataBob.append(elem);
+ } else {
+ logicalTimeCommandBob.append(elem);
+ }
+ }
+
+ return std::make_tuple(logicalTimeCommandBob.obj(), metadataBob.obj());
}
LegacyCommandAndFlags downconvertRequestMetadata(BSONObj cmdObj, BSONObj metadata) {
int legacyQueryFlags = 0;
+ BSONObjBuilder logicalTimeCommandBob;
+ logicalTimeCommandBob.appendElements(cmdObj);
+ if (auto logicalTime = metadata[LogicalTimeMetadata::fieldName()]) {
+ logicalTimeCommandBob.append(logicalTime);
+ }
+
+ // Ordering is important here - AuditingMetadata must be downconverted before ReadPreference.
BSONObjBuilder auditCommandBob;
- // Ordering is important here - AuditingMetadata must be downconverted first,
- // then ReadPreference.
- uassertStatusOK(
- AuditMetadata::downconvert(cmdObj, metadata, &auditCommandBob, &legacyQueryFlags));
+ uassertStatusOK(AuditMetadata::downconvert(
+ logicalTimeCommandBob.done(), metadata, &auditCommandBob, &legacyQueryFlags));
+ cmdObj = auditCommandBob.obj();
auto readPref = metadata["$readPreference"];
if (!readPref)
diff --git a/src/mongo/rpc/metadata/logical_time_metadata.h b/src/mongo/rpc/metadata/logical_time_metadata.h
index 2ec6b7f03b5..f47d27fba8c 100644
--- a/src/mongo/rpc/metadata/logical_time_metadata.h
+++ b/src/mongo/rpc/metadata/logical_time_metadata.h
@@ -65,7 +65,7 @@ public:
const SignedLogicalTime& getSignedTime() const;
static StringData fieldName() {
- return "logicalTime";
+ return "$logicalTime";
}
private:
diff --git a/src/mongo/rpc/metadata/logical_time_metadata_test.cpp b/src/mongo/rpc/metadata/logical_time_metadata_test.cpp
index 73e9ad64208..bcc50a392cc 100644
--- a/src/mongo/rpc/metadata/logical_time_metadata_test.cpp
+++ b/src/mongo/rpc/metadata/logical_time_metadata_test.cpp
@@ -31,6 +31,7 @@
#include "mongo/platform/basic.h"
#include "mongo/db/jsobj.h"
+#include "mongo/rpc/metadata.h"
#include "mongo/rpc/metadata/logical_time_metadata.h"
#include "mongo/unittest/unittest.h"
@@ -74,7 +75,7 @@ TEST(LogicalTimeMetadataTest, MissingClusterTimeShouldFailToParse) {
long long keyId = 1;
BSONObjBuilder builder;
- BSONObjBuilder subObjBuilder(builder.subobjStart("logicalTime"));
+ BSONObjBuilder subObjBuilder(builder.subobjStart("$logicalTime"));
BSONObjBuilder signatureObjBuilder(subObjBuilder.subobjStart("signature"));
signatureObjBuilder.append("hash", BSONBinData(proof.data(), proof.size(), BinDataGeneral));
signatureObjBuilder.append("keyId", keyId);
@@ -90,7 +91,7 @@ TEST(LogicalTimeMetadataTest, MissingSignatureShouldFailToParse) {
const auto ts = Timestamp(100, 200);
BSONObjBuilder builder;
- BSONObjBuilder subObjBuilder(builder.subobjStart("logicalTime"));
+ BSONObjBuilder subObjBuilder(builder.subobjStart("$logicalTime"));
ts.append(subObjBuilder.bb(), "clusterTime");
subObjBuilder.doneFast();
@@ -105,7 +106,7 @@ TEST(LogicalTimeMetadataTest, MissingHashShouldFailToParse) {
long long keyId = 1;
BSONObjBuilder builder;
- BSONObjBuilder subObjBuilder(builder.subobjStart("logicalTime"));
+ BSONObjBuilder subObjBuilder(builder.subobjStart("$logicalTime"));
ts.append(subObjBuilder.bb(), "clusterTime");
BSONObjBuilder signatureObjBuilder(subObjBuilder.subobjStart("signature"));
signatureObjBuilder.append("keyId", keyId);
@@ -124,7 +125,7 @@ TEST(LogicalTimeMetadataTest, MissingKeyIdShouldFailToParse) {
proof.fill(0);
BSONObjBuilder builder;
- BSONObjBuilder subObjBuilder(builder.subobjStart("logicalTime"));
+ BSONObjBuilder subObjBuilder(builder.subobjStart("$logicalTime"));
ts.append(subObjBuilder.bb(), "clusterTime");
BSONObjBuilder signatureObjBuilder(subObjBuilder.subobjStart("signature"));
signatureObjBuilder.append("hash", BSONBinData(proof.data(), proof.size(), BinDataGeneral));
@@ -145,7 +146,7 @@ TEST(LogicalTimeMetadataTest, ProofWithWrongLengthShouldFailToParse) {
long long keyId = 1;
BSONObjBuilder builder;
- BSONObjBuilder subObjBuilder(builder.subobjStart("logicalTime"));
+ BSONObjBuilder subObjBuilder(builder.subobjStart("$logicalTime"));
ts.append(subObjBuilder.bb(), "clusterTime");
BSONObjBuilder signatureObjBuilder(subObjBuilder.subobjStart("signature"));
signatureObjBuilder.append("hash", BSONBinData(proof.data(), proof.size(), BinDataGeneral));
@@ -158,6 +159,35 @@ TEST(LogicalTimeMetadataTest, ProofWithWrongLengthShouldFailToParse) {
ASSERT_EQ(ErrorCodes::UnsupportedFormat, status);
}
+TEST(LogicalTimeMetadataTest, UpconvertPass) {
+
+ const auto ts = Timestamp(100, 200);
+
+ std::array<uint8_t, 20> proof;
+ proof.fill(0);
+
+ long long keyId = 1;
+
+ BSONObjBuilder builder;
+ builder.append("aaa", 1);
+ builder.append("bbb", 1);
+ BSONObjBuilder subObjBuilder(builder.subobjStart("$logicalTime"));
+ ts.append(subObjBuilder.bb(), "clusterTime");
+ BSONObjBuilder signatureObjBuilder(subObjBuilder.subobjStart("signature"));
+ signatureObjBuilder.append("hash", BSONBinData(proof.data(), proof.size(), BinDataGeneral));
+ signatureObjBuilder.append("keyId", keyId);
+ signatureObjBuilder.doneFast();
+ auto logicalTimeMetadata = subObjBuilder.asTempObj();
+ subObjBuilder.doneFast();
+
+ auto commandObj = builder.done();
+ BSONObjBuilder metadataBob;
+ BSONObjBuilder commandBob;
+ auto converted = upconvertRequestMetadata(commandObj, 0);
+ ASSERT_BSONOBJ_EQ(BSON("aaa" << 1 << "bbb" << 1), std::get<0>(converted));
+ ASSERT_BSONOBJ_EQ(BSON("$logicalTime" << logicalTimeMetadata), std::get<1>(converted));
+}
+
} // namespace rpc
} // namespace mongo
}
diff --git a/src/mongo/shell/mongo.js b/src/mongo/shell/mongo.js
index 834568dc87a..471a0e3285c 100644
--- a/src/mongo/shell/mongo.js
+++ b/src/mongo/shell/mongo.js
@@ -14,6 +14,9 @@ if (!Mongo.prototype) {
(function(original) {
Mongo.prototype.find = function find(ns, query, fields, limit, skip, batchSize, options) {
const self = this;
+ if (this._isCausal) {
+ query = this._gossipLogicalTime(query);
+ }
const res = original.call(this, ns, query, fields, limit, skip, batchSize, options);
const origNext = res.next;
res.next = function next() {
@@ -145,6 +148,15 @@ Mongo.prototype._injectAfterClusterTime = function(cmdObj) {
return cmdObj;
};
+Mongo.prototype._gossipLogicalTime = function(obj) {
+ obj = Object.assign({}, obj);
+ const clusterTime = this.getClusterTime();
+ if (clusterTime) {
+ obj["$logicalTime"] = clusterTime;
+ }
+ return obj;
+};
+
/**
* Sets logicalTime and operationTime extracted from command reply.
* This is applicable for the protocol starting from version 3.6.
@@ -153,8 +165,8 @@ Mongo.prototype._setLogicalTimeFromReply = function(res) {
if (res.hasOwnProperty("operationTime")) {
this.setOperationTime(res["operationTime"]);
}
- if (res.hasOwnProperty("logicalTime")) {
- this.setClusterTime(res["logicalTime"]);
+ if (res.hasOwnProperty("$logicalTime")) {
+ this.setClusterTime(res["$logicalTime"]);
}
};
@@ -167,6 +179,9 @@ Mongo.prototype._setLogicalTimeFromReply = function(res) {
if (this.isCausalConsistencyEnabled(cmdName, cmdObj) && cmdObj) {
cmdObj = this._injectAfterClusterTime(cmdObj);
}
+ if (this._isCausal) {
+ metadata = this._gossipLogicalTime(metadata);
+ }
const res = original.call(this, dbName, cmdName, metadata, cmdObj);
this._setLogicalTimeFromReply(res);
return res;
@@ -183,6 +198,9 @@ Mongo.prototype._setLogicalTimeFromReply = function(res) {
if (this.isCausalConsistencyEnabled(cmdName, cmdObj) && cmdObj) {
cmdObj = this._injectAfterClusterTime(cmdObj);
}
+ if (this._isCausal) {
+ cmdObj = this._gossipLogicalTime(cmdObj);
+ }
const res = original.call(this, dbName, cmdObj, options);
this._setLogicalTimeFromReply(res);
return res;