summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCheahuychou Mao <mao.cheahuychou@gmail.com>2021-01-06 19:39:39 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-01-13 02:05:27 +0000
commit5c1c3e6930a5acefe1a1fbe2763db8e435167e26 (patch)
treebc5fe2aadf4c5fa76e55ec393967910a7102297a
parent34e32be7b869deea3fc100d4e60b08986fdc4528 (diff)
downloadmongo-5c1c3e6930a5acefe1a1fbe2763db8e435167e26.tar.gz
SERVER-53680 Use IDL for KeysCollectionDocument
-rw-r--r--src/mongo/db/SConscript3
-rw-r--r--src/mongo/db/key_generator.cpp1
-rw-r--r--src/mongo/db/key_generator_update_test.cpp17
-rw-r--r--src/mongo/db/keys_collection_cache.cpp2
-rw-r--r--src/mongo/db/keys_collection_cache.h2
-rw-r--r--src/mongo/db/keys_collection_cache_test.cpp23
-rw-r--r--src/mongo/db/keys_collection_client.h2
-rw-r--r--src/mongo/db/keys_collection_client_direct.cpp21
-rw-r--r--src/mongo/db/keys_collection_client_sharded.cpp6
-rw-r--r--src/mongo/db/keys_collection_document.cpp118
-rw-r--r--src/mongo/db/keys_collection_document.h88
-rw-r--r--src/mongo/db/keys_collection_document.idl64
-rw-r--r--src/mongo/db/keys_collection_document_test.cpp38
-rw-r--r--src/mongo/db/keys_collection_manager.h2
-rw-r--r--src/mongo/db/keys_collection_manager_sharding_test.cpp23
-rw-r--r--src/mongo/db/logical_time.cpp11
-rw-r--r--src/mongo/db/logical_time.h6
-rw-r--r--src/mongo/db/namespace_string.cpp3
-rw-r--r--src/mongo/db/namespace_string.h3
-rw-r--r--src/mongo/db/s/config/config_server_test_fixture.cpp7
-rw-r--r--src/mongo/s/catalog/sharding_catalog_client.h2
-rw-r--r--src/mongo/s/catalog/sharding_catalog_client_impl.cpp13
-rw-r--r--src/mongo/s/catalog/sharding_catalog_client_test.cpp5
23 files changed, 178 insertions, 282 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index 6b70018a274..cac09b14c61 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -1640,7 +1640,7 @@ env.Library(
env.Library(
target='keys_collection_document',
source=[
- 'keys_collection_document.cpp',
+ 'keys_collection_document.idl',
],
LIBDEPS=[
'logical_time',
@@ -1673,6 +1673,7 @@ env.Library(
'$BUILD_DIR/mongo/s/catalog/sharding_catalog_client',
'keys_collection_document',
'logical_time',
+ 'namespace_string',
],
)
diff --git a/src/mongo/db/key_generator.cpp b/src/mongo/db/key_generator.cpp
index 3e899fd888b..eac600c5fd1 100644
--- a/src/mongo/db/key_generator.cpp
+++ b/src/mongo/db/key_generator.cpp
@@ -34,6 +34,7 @@
#include "mongo/client/read_preference.h"
#include "mongo/db/keys_collection_client.h"
#include "mongo/db/operation_context.h"
+#include "mongo/db/time_proof_service.h"
#include "mongo/db/vector_clock.h"
#include "mongo/s/client/shard_registry.h"
#include "mongo/util/fail_point.h"
diff --git a/src/mongo/db/key_generator_update_test.cpp b/src/mongo/db/key_generator_update_test.cpp
index 9590d3fda9a..d794e0caab6 100644
--- a/src/mongo/db/key_generator_update_test.cpp
+++ b/src/mongo/db/key_generator_update_test.cpp
@@ -36,8 +36,9 @@
#include "mongo/db/jsobj.h"
#include "mongo/db/key_generator.h"
#include "mongo/db/keys_collection_client_sharded.h"
-#include "mongo/db/keys_collection_document.h"
+#include "mongo/db/keys_collection_document_gen.h"
#include "mongo/db/s/config/config_server_test_fixture.h"
+#include "mongo/db/time_proof_service.h"
#include "mongo/db/vector_clock_mutable.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/clock_source_mock.h"
@@ -111,7 +112,7 @@ TEST_F(KeyGeneratorUpdateTest, ShouldCreateAnotherKeyIfOnlyOneKeyExists) {
KeysCollectionDocument origKey1(
1, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey1.toBSON()));
{
auto allKeys = getKeys(operationContext());
@@ -158,12 +159,12 @@ TEST_F(KeyGeneratorUpdateTest, ShouldCreateAnotherKeyIfNoValidKeyAfterCurrent) {
KeysCollectionDocument origKey1(
1, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey1.toBSON()));
KeysCollectionDocument origKey2(
2, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(110, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey2.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey2.toBSON()));
{
auto allKeys = getKeys(operationContext());
@@ -241,12 +242,12 @@ TEST_F(KeyGeneratorUpdateTest, ShouldCreate2KeysIfAllKeysAreExpired) {
KeysCollectionDocument origKey1(
1, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey1.toBSON()));
KeysCollectionDocument origKey2(
2, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(110, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey2.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey2.toBSON()));
{
auto allKeys = getKeys(operationContext());
@@ -339,12 +340,12 @@ TEST_F(KeyGeneratorUpdateTest, ShouldNotCreateNewKeyIfThereAre2UnexpiredKeys) {
KeysCollectionDocument origKey1(
1, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey1.toBSON()));
KeysCollectionDocument origKey2(
2, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(110, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey2.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey2.toBSON()));
{
auto allKeys = getKeys(operationContext());
diff --git a/src/mongo/db/keys_collection_cache.cpp b/src/mongo/db/keys_collection_cache.cpp
index 0e57d6b091a..5cf62f8da12 100644
--- a/src/mongo/db/keys_collection_cache.cpp
+++ b/src/mongo/db/keys_collection_cache.cpp
@@ -32,7 +32,7 @@
#include "mongo/db/keys_collection_cache.h"
#include "mongo/db/keys_collection_client.h"
-#include "mongo/db/keys_collection_document.h"
+#include "mongo/db/keys_collection_document_gen.h"
#include "mongo/db/repl/replication_coordinator.h"
#include "mongo/util/str.h"
diff --git a/src/mongo/db/keys_collection_cache.h b/src/mongo/db/keys_collection_cache.h
index 61989d6ae5b..17c532b72fa 100644
--- a/src/mongo/db/keys_collection_cache.h
+++ b/src/mongo/db/keys_collection_cache.h
@@ -32,7 +32,7 @@
#include <map>
#include "mongo/base/status_with.h"
-#include "mongo/db/keys_collection_document.h"
+#include "mongo/db/keys_collection_document_gen.h"
#include "mongo/db/operation_context.h"
#include "mongo/platform/mutex.h"
diff --git a/src/mongo/db/keys_collection_cache_test.cpp b/src/mongo/db/keys_collection_cache_test.cpp
index 51ada59e365..da649b06c70 100644
--- a/src/mongo/db/keys_collection_cache_test.cpp
+++ b/src/mongo/db/keys_collection_cache_test.cpp
@@ -32,9 +32,10 @@
#include "mongo/db/jsobj.h"
#include "mongo/db/keys_collection_cache.h"
#include "mongo/db/keys_collection_client_sharded.h"
-#include "mongo/db/keys_collection_document.h"
+#include "mongo/db/keys_collection_document_gen.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/s/config/config_server_test_fixture.h"
+#include "mongo/db/time_proof_service.h"
#include "mongo/s/grid.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/clock_source_mock.h"
@@ -79,7 +80,7 @@ TEST_F(CacheTest, GetKeyShouldReturnCorrectKeyAfterRefresh) {
KeysCollectionDocument origKey1(
1, "test", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey1.toBSON()));
auto refreshStatus = cache.refresh(operationContext());
ASSERT_OK(refreshStatus.getStatus());
@@ -110,7 +111,7 @@ TEST_F(CacheTest, GetKeyShouldReturnErrorIfNoKeyIsValidForGivenTime) {
KeysCollectionDocument origKey1(
1, "test", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey1.toBSON()));
auto refreshStatus = cache.refresh(operationContext());
ASSERT_OK(refreshStatus.getStatus());
@@ -133,17 +134,17 @@ TEST_F(CacheTest, GetKeyShouldReturnOldestKeyPossible) {
KeysCollectionDocument origKey0(
0, "test", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(100, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey0.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey0.toBSON()));
KeysCollectionDocument origKey1(
1, "test", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey1.toBSON()));
KeysCollectionDocument origKey2(
2, "test", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(110, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey2.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey2.toBSON()));
auto refreshStatus = cache.refresh(operationContext());
ASSERT_OK(refreshStatus.getStatus());
@@ -174,7 +175,7 @@ TEST_F(CacheTest, RefreshShouldNotGetKeysForOtherPurpose) {
KeysCollectionDocument origKey0(
0, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(100, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey0.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey0.toBSON()));
{
auto refreshStatus = cache.refresh(operationContext());
@@ -187,7 +188,7 @@ TEST_F(CacheTest, RefreshShouldNotGetKeysForOtherPurpose) {
KeysCollectionDocument origKey1(
1, "test", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey1.toBSON()));
{
auto refreshStatus = cache.refresh(operationContext());
@@ -218,7 +219,7 @@ TEST_F(CacheTest, RefreshCanIncrementallyGetNewKeys) {
KeysCollectionDocument origKey0(
0, "test", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(100, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey0.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey0.toBSON()));
{
auto refreshStatus = cache.refresh(operationContext());
@@ -238,12 +239,12 @@ TEST_F(CacheTest, RefreshCanIncrementallyGetNewKeys) {
KeysCollectionDocument origKey1(
1, "test", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey1.toBSON()));
KeysCollectionDocument origKey2(
2, "test", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(110, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey2.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey2.toBSON()));
{
auto refreshStatus = cache.refresh(operationContext());
diff --git a/src/mongo/db/keys_collection_client.h b/src/mongo/db/keys_collection_client.h
index debff147f53..a805300da2b 100644
--- a/src/mongo/db/keys_collection_client.h
+++ b/src/mongo/db/keys_collection_client.h
@@ -33,7 +33,7 @@
#include "mongo/base/status_with.h"
#include "mongo/base/string_data.h"
-#include "mongo/db/keys_collection_document.h"
+#include "mongo/db/keys_collection_document_gen.h"
namespace mongo {
diff --git a/src/mongo/db/keys_collection_client_direct.cpp b/src/mongo/db/keys_collection_client_direct.cpp
index 9fa9c6a3560..4b90c8bb23f 100644
--- a/src/mongo/db/keys_collection_client_direct.cpp
+++ b/src/mongo/db/keys_collection_client_direct.cpp
@@ -40,7 +40,7 @@
#include "mongo/bson/util/bson_extract.h"
#include "mongo/client/read_preference.h"
#include "mongo/db/dbdirectclient.h"
-#include "mongo/db/keys_collection_document.h"
+#include "mongo/db/keys_collection_document_gen.h"
#include "mongo/db/logical_time.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/service_context.h"
@@ -91,7 +91,7 @@ StatusWith<std::vector<KeysCollectionDocument>> KeysCollectionClientDirect::getN
auto findStatus = _query(opCtx,
ReadPreferenceSetting(ReadPreference::Nearest, TagSet{}),
readConcern,
- KeysCollectionDocument::ConfigNS,
+ NamespaceString::kKeysCollectionNamespace,
queryBuilder.obj(),
BSON("expiresAt" << 1),
boost::none);
@@ -103,12 +103,13 @@ StatusWith<std::vector<KeysCollectionDocument>> KeysCollectionClientDirect::getN
const auto& keyDocs = findStatus.getValue().docs;
std::vector<KeysCollectionDocument> keys;
for (auto&& keyDoc : keyDocs) {
- auto parseStatus = KeysCollectionDocument::fromBSON(keyDoc);
- if (!parseStatus.isOK()) {
- return parseStatus.getStatus();
+ KeysCollectionDocument key;
+ try {
+ key = KeysCollectionDocument::parse(IDLParserErrorContext("keyDoc"), keyDoc);
+ } catch (...) {
+ return exceptionToStatus();
}
-
- keys.push_back(std::move(parseStatus.getValue()));
+ keys.push_back(std::move(key));
}
return keys;
@@ -173,8 +174,10 @@ Status KeysCollectionClientDirect::_insert(OperationContext* opCtx,
}
Status KeysCollectionClientDirect::insertNewKey(OperationContext* opCtx, const BSONObj& doc) {
- return _insert(
- opCtx, KeysCollectionDocument::ConfigNS, doc, ShardingCatalogClient::kMajorityWriteConcern);
+ return _insert(opCtx,
+ NamespaceString::kKeysCollectionNamespace,
+ doc,
+ ShardingCatalogClient::kMajorityWriteConcern);
}
} // namespace mongo
diff --git a/src/mongo/db/keys_collection_client_sharded.cpp b/src/mongo/db/keys_collection_client_sharded.cpp
index 5a6a37bd210..08f56481b19 100644
--- a/src/mongo/db/keys_collection_client_sharded.cpp
+++ b/src/mongo/db/keys_collection_client_sharded.cpp
@@ -50,8 +50,10 @@ StatusWith<std::vector<KeysCollectionDocument>> KeysCollectionClientSharded::get
}
Status KeysCollectionClientSharded::insertNewKey(OperationContext* opCtx, const BSONObj& doc) {
- return _catalogClient->insertConfigDocument(
- opCtx, KeysCollectionDocument::ConfigNS, doc, ShardingCatalogClient::kMajorityWriteConcern);
+ return _catalogClient->insertConfigDocument(opCtx,
+ NamespaceString::kKeysCollectionNamespace,
+ doc,
+ ShardingCatalogClient::kMajorityWriteConcern);
}
} // namespace mongo
diff --git a/src/mongo/db/keys_collection_document.cpp b/src/mongo/db/keys_collection_document.cpp
deleted file mode 100644
index d8a83ea22cc..00000000000
--- a/src/mongo/db/keys_collection_document.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- * Copyright (C) 2018-present MongoDB, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the Server Side Public License, version 1,
- * as published by MongoDB, Inc.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * Server Side Public License for more details.
- *
- * You should have received a copy of the Server Side Public License
- * along with this program. If not, see
- * <http://www.mongodb.com/licensing/server-side-public-license>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the Server Side Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#include "mongo/platform/basic.h"
-
-#include "mongo/db/keys_collection_document.h"
-
-#include "mongo/base/status.h"
-#include "mongo/bson/bsonobjbuilder.h"
-#include "mongo/bson/util/bson_extract.h"
-#include "mongo/db/logical_time.h"
-#include "mongo/db/time_proof_service.h"
-
-namespace mongo {
-
-namespace {
-
-const char kKeyIdFieldName[] = "_id";
-const char kPurposeFieldName[] = "purpose";
-const char kKeyFieldName[] = "key";
-const char kExpiresAtFieldName[] = "expiresAt";
-
-} // namespace
-
-const NamespaceString KeysCollectionDocument::ConfigNS("admin.system.keys");
-
-StatusWith<KeysCollectionDocument> KeysCollectionDocument::fromBSON(const BSONObj& source) {
- long long keyId;
- Status status = bsonExtractIntegerField(source, kKeyIdFieldName, &keyId);
- if (!status.isOK()) {
- return status;
- }
-
- std::string purpose;
- status = bsonExtractStringField(source, kPurposeFieldName, &purpose);
- if (!status.isOK()) {
- return status;
- }
-
- // Extract BinData type signature hash and construct a SHA1Block instance from it.
- BSONElement keyElem;
- status = bsonExtractTypedField(source, kKeyFieldName, BinData, &keyElem);
- if (!status.isOK()) {
- return status;
- }
-
- int hashLength = 0;
- auto rawBinSignature = keyElem.binData(hashLength);
- BSONBinData proofBinData(rawBinSignature, hashLength, keyElem.binDataType());
- auto keyStatus = SHA1Block::fromBinData(proofBinData);
- if (!keyStatus.isOK()) {
- return keyStatus.getStatus();
- }
-
- Timestamp ts;
- status = bsonExtractTimestampField(source, kExpiresAtFieldName, &ts);
- if (!status.isOK()) {
- return status;
- }
-
- return KeysCollectionDocument(
- keyId, std::move(purpose), std::move(keyStatus.getValue()), LogicalTime(ts));
-}
-
-BSONObj KeysCollectionDocument::toBSON() const {
- BSONObjBuilder builder;
-
- builder.append(kKeyIdFieldName, _keyId);
- builder.append(kPurposeFieldName, _purpose);
- _key.appendAsBinData(builder, kKeyFieldName);
- _expiresAt.asTimestamp().append(builder.bb(), kExpiresAtFieldName);
-
- return builder.obj();
-}
-
-long long KeysCollectionDocument::getKeyId() const {
- return _keyId;
-}
-
-const std::string& KeysCollectionDocument::getPurpose() const {
- return _purpose;
-}
-
-const TimeProofService::Key& KeysCollectionDocument::getKey() const {
- return _key;
-}
-
-const LogicalTime& KeysCollectionDocument::getExpiresAt() const {
- return _expiresAt;
-}
-
-} // namespace mongo
diff --git a/src/mongo/db/keys_collection_document.h b/src/mongo/db/keys_collection_document.h
deleted file mode 100644
index 802d131d939..00000000000
--- a/src/mongo/db/keys_collection_document.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * Copyright (C) 2018-present MongoDB, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the Server Side Public License, version 1,
- * as published by MongoDB, Inc.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * Server Side Public License for more details.
- *
- * You should have received a copy of the Server Side Public License
- * along with this program. If not, see
- * <http://www.mongodb.com/licensing/server-side-public-license>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the Server Side Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#pragma once
-
-#include "mongo/base/status.h"
-#include "mongo/db/logical_time.h"
-#include "mongo/db/namespace_string.h"
-#include "mongo/db/time_proof_service.h"
-
-namespace mongo {
-
-/**
- * Class for parsing and serializing a key document stored in admin.system.keys.
- *
- * Format:
- * {
- * _id: <long long>,
- * purpose: 'signLogicalTime',
- * key: <20 byte key generated with secure PRNG in BinData>,
- * expiresAt: <LogicalTime, currently in Timestamp format>
- * }
- */
-class KeysCollectionDocument {
-public:
- static const NamespaceString ConfigNS;
-
- KeysCollectionDocument(long long keyId,
- std::string purpose,
- TimeProofService::Key key,
- LogicalTime expiresAt)
- : _keyId(keyId),
- _purpose(std::move(purpose)),
- _key(std::move(key)),
- _expiresAt(std::move(expiresAt)) {}
-
- /**
- * Parses the key document from BSON.
- */
- static StatusWith<KeysCollectionDocument> fromBSON(const BSONObj& source);
-
- /**
- * Serialize the key document as BSON.
- */
- BSONObj toBSON() const;
-
- long long getKeyId() const;
-
- const std::string& getPurpose() const;
-
- const TimeProofService::Key& getKey() const;
-
- const LogicalTime& getExpiresAt() const;
-
-private:
- long long _keyId = 0;
- std::string _purpose;
- TimeProofService::Key _key;
- LogicalTime _expiresAt;
-};
-
-} // namespace mongo
diff --git a/src/mongo/db/keys_collection_document.idl b/src/mongo/db/keys_collection_document.idl
new file mode 100644
index 00000000000..dbffd8168a7
--- /dev/null
+++ b/src/mongo/db/keys_collection_document.idl
@@ -0,0 +1,64 @@
+# Copyright (C) 2021-present MongoDB, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the Server Side Public License, version 1,
+# as published by MongoDB, Inc.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# Server Side Public License for more details.
+#
+# You should have received a copy of the Server Side Public License
+# along with this program. If not, see
+# <http://www.mongodb.com/licensing/server-side-public-license>.
+#
+# As a special exception, the copyright holders give permission to link the
+# code of portions of this program with the OpenSSL library under certain
+# conditions as described in each individual source file and distribute
+# linked combinations including the program with the OpenSSL library. You
+# must comply with the Server Side Public License in all respects for
+# all of the code used other than as permitted herein. If you modify file(s)
+# with this exception, you may extend this exception to your version of the
+# file(s), but you are not obligated to do so. If you do not wish to do so,
+# delete this exception statement from your version. If you delete this
+# exception statement from all source files in the program, then also delete
+# it in the license file.
+#
+global:
+ cpp_namespace: "mongo"
+ cpp_includes:
+ - "mongo/db/logical_time.h"
+
+imports:
+ - "mongo/crypto/sha1_block.idl"
+ - "mongo/idl/basic_types.idl"
+
+types:
+ logicalTime:
+ description: "A MongoDB LogicalTime."
+ bson_serialization_type: any
+ cpp_type: LogicalTime
+ serializer: LogicalTime::serializeToBSON
+ deserializer: LogicalTime::parseFromBSON
+
+structs:
+ keysCollectionDocument:
+ description: >-
+ Represents a key document stored in admin.system.keys.
+ strict: true
+ fields:
+ _id:
+ type: safeInt64
+ description: >-
+ NumberLong representation of the cluster time at which the key was created.
+ cpp_name: keyId
+ purpose:
+ type: string
+ description: "The purpose of the key."
+ key:
+ type: sha1Block
+ description: "20 byte key generated with secure PRNG in BinData."
+ expiresAt:
+ type: logicalTime
+ description: "The logical time at which the key will expire."
diff --git a/src/mongo/db/keys_collection_document_test.cpp b/src/mongo/db/keys_collection_document_test.cpp
index dfa6124a212..6be5e268507 100644
--- a/src/mongo/db/keys_collection_document_test.cpp
+++ b/src/mongo/db/keys_collection_document_test.cpp
@@ -30,7 +30,8 @@
#include "mongo/platform/basic.h"
#include "mongo/db/jsobj.h"
-#include "mongo/db/keys_collection_document.h"
+#include "mongo/db/keys_collection_document_gen.h"
+#include "mongo/db/time_proof_service.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
@@ -52,10 +53,7 @@ TEST(KeysCollectionDocument, Roundtrip) {
KeysCollectionDocument keysCollectionDoc(keyId, purpose, key, expiresAt);
auto serializedObj = keysCollectionDoc.toBSON();
-
- auto parseStatus = KeysCollectionDocument::fromBSON(serializedObj);
- ASSERT_OK(parseStatus.getStatus());
- const auto& parsedKey = parseStatus.getValue();
+ auto parsedKey = KeysCollectionDocument::parse(IDLParserErrorContext("keyDoc"), serializedObj);
ASSERT_EQ(keyId, parsedKey.getKeyId());
ASSERT_EQ(purpose, parsedKey.getPurpose());
@@ -78,8 +76,10 @@ TEST(KeysCollectionDocument, MissingKeyIdShouldFailToParse) {
expiresAt.asTimestamp().append(builder.bb(), "expiresAt");
auto serializedObj = builder.done();
- auto status = KeysCollectionDocument::fromBSON(serializedObj).getStatus();
- ASSERT_EQ(ErrorCodes::NoSuchKey, status);
+ ASSERT_THROWS_CODE(
+ KeysCollectionDocument::parse(IDLParserErrorContext("keyDoc"), serializedObj),
+ AssertionException,
+ 40414);
}
TEST(KeysCollectionDocument, MissingPurposeShouldFailToParse) {
@@ -92,13 +92,15 @@ TEST(KeysCollectionDocument, MissingPurposeShouldFailToParse) {
const auto expiresAt = LogicalTime(Timestamp(100, 200));
BSONObjBuilder builder;
- builder.append("keyId", keyId);
+ builder.append("_id", keyId);
builder.append("key", BSONBinData(key.data(), key.size(), BinDataGeneral));
expiresAt.asTimestamp().append(builder.bb(), "expiresAt");
auto serializedObj = builder.done();
- auto status = KeysCollectionDocument::fromBSON(serializedObj).getStatus();
- ASSERT_EQ(ErrorCodes::NoSuchKey, status);
+ ASSERT_THROWS_CODE(
+ KeysCollectionDocument::parse(IDLParserErrorContext("keyDoc"), serializedObj),
+ AssertionException,
+ 40414);
}
TEST(KeysCollectionDocument, MissingKeyShouldFailToParse) {
@@ -109,13 +111,15 @@ TEST(KeysCollectionDocument, MissingKeyShouldFailToParse) {
const auto expiresAt = LogicalTime(Timestamp(100, 200));
BSONObjBuilder builder;
- builder.append("keyId", keyId);
+ builder.append("_id", keyId);
builder.append("purpose", purpose);
expiresAt.asTimestamp().append(builder.bb(), "expiresAt");
auto serializedObj = builder.done();
- auto status = KeysCollectionDocument::fromBSON(serializedObj).getStatus();
- ASSERT_EQ(ErrorCodes::NoSuchKey, status);
+ ASSERT_THROWS_CODE(
+ KeysCollectionDocument::parse(IDLParserErrorContext("keyDoc"), serializedObj),
+ AssertionException,
+ 40414);
}
TEST(KeysCollectionDocument, MissingExpiresAtShouldFailToParse) {
@@ -128,13 +132,15 @@ TEST(KeysCollectionDocument, MissingExpiresAtShouldFailToParse) {
TimeProofService::Key key(keyHash);
BSONObjBuilder builder;
- builder.append("keyId", keyId);
+ builder.append("_id", keyId);
builder.append("purpose", purpose);
builder.append("key", BSONBinData(key.data(), key.size(), BinDataGeneral));
auto serializedObj = builder.done();
- auto status = KeysCollectionDocument::fromBSON(serializedObj).getStatus();
- ASSERT_EQ(ErrorCodes::NoSuchKey, status);
+ ASSERT_THROWS_CODE(
+ KeysCollectionDocument::parse(IDLParserErrorContext("keyDoc"), serializedObj),
+ AssertionException,
+ 40414);
}
} // namespace
diff --git a/src/mongo/db/keys_collection_manager.h b/src/mongo/db/keys_collection_manager.h
index 0fe5ee6f732..2bb3ca00744 100644
--- a/src/mongo/db/keys_collection_manager.h
+++ b/src/mongo/db/keys_collection_manager.h
@@ -35,7 +35,7 @@
#include "mongo/base/status_with.h"
#include "mongo/db/key_generator.h"
#include "mongo/db/keys_collection_cache.h"
-#include "mongo/db/keys_collection_document.h"
+#include "mongo/db/keys_collection_document_gen.h"
#include "mongo/db/keys_collection_manager_gen.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/platform/mutex.h"
diff --git a/src/mongo/db/keys_collection_manager_sharding_test.cpp b/src/mongo/db/keys_collection_manager_sharding_test.cpp
index fb2cf3d98e0..a1c829b263b 100644
--- a/src/mongo/db/keys_collection_manager_sharding_test.cpp
+++ b/src/mongo/db/keys_collection_manager_sharding_test.cpp
@@ -31,9 +31,10 @@
#include "mongo/db/jsobj.h"
#include "mongo/db/keys_collection_client_sharded.h"
-#include "mongo/db/keys_collection_document.h"
+#include "mongo/db/keys_collection_document_gen.h"
#include "mongo/db/keys_collection_manager.h"
#include "mongo/db/s/config/config_server_test_fixture.h"
+#include "mongo/db/time_proof_service.h"
#include "mongo/db/vector_clock_mutable.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/clock_source_mock.h"
@@ -97,7 +98,7 @@ TEST_F(KeysManagerShardedTest, GetKeyWithSingleKey) {
KeysCollectionDocument origKey1(
1, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey1.toBSON()));
auto keyStatus =
keyManager()->getKeyForValidation(operationContext(), 1, LogicalTime(Timestamp(100, 0)));
@@ -115,12 +116,12 @@ TEST_F(KeysManagerShardedTest, GetKeyWithMultipleKeys) {
KeysCollectionDocument origKey1(
1, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey1.toBSON()));
KeysCollectionDocument origKey2(
2, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(205, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey2.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey2.toBSON()));
auto keyStatus =
keyManager()->getKeyForValidation(operationContext(), 1, LogicalTime(Timestamp(100, 0)));
@@ -147,7 +148,7 @@ TEST_F(KeysManagerShardedTest, GetKeyShouldErrorIfKeyIdMismatchKey) {
KeysCollectionDocument origKey1(
1, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey1.toBSON()));
auto keyStatus =
keyManager()->getKeyForValidation(operationContext(), 2, LogicalTime(Timestamp(100, 0)));
@@ -160,11 +161,11 @@ TEST_F(KeysManagerShardedTest, GetKeyWithoutRefreshShouldReturnRightKey) {
KeysCollectionDocument origKey1(
1, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey1.toBSON()));
KeysCollectionDocument origKey2(
2, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(110, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey2.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey2.toBSON()));
{
auto keyStatus = keyManager()->getKeyForValidation(
@@ -195,7 +196,7 @@ TEST_F(KeysManagerShardedTest, GetKeyForSigningShouldReturnRightKey) {
KeysCollectionDocument origKey1(
1, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey1.toBSON()));
keyManager()->refreshNow(operationContext());
@@ -214,11 +215,11 @@ TEST_F(KeysManagerShardedTest, GetKeyForSigningShouldReturnRightOldKey) {
KeysCollectionDocument origKey1(
1, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey1.toBSON()));
KeysCollectionDocument origKey2(
2, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(110, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey2.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey2.toBSON()));
keyManager()->refreshNow(operationContext());
@@ -285,7 +286,7 @@ TEST_F(KeysManagerShardedTest, ShouldStillBeAbleToUpdateCacheEvenIfItCantCreateK
KeysCollectionDocument origKey1(
1, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0)));
ASSERT_OK(insertToConfigCollection(
- operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON()));
+ operationContext(), NamespaceString::kKeysCollectionNamespace, origKey1.toBSON()));
// Set the time to be very ahead so the updater will be forced to create new keys.
const LogicalTime fakeTime(Timestamp(20000, 0));
diff --git a/src/mongo/db/logical_time.cpp b/src/mongo/db/logical_time.cpp
index ae80b8b8c40..bdc8d9f040f 100644
--- a/src/mongo/db/logical_time.cpp
+++ b/src/mongo/db/logical_time.cpp
@@ -46,7 +46,8 @@ LogicalTime LogicalTime::fromOperationTime(const BSONObj& obj) {
const auto opTimeElem(obj[kOperationTimeFieldName]);
uassert(ErrorCodes::FailedToParse, "No operationTime found", !opTimeElem.eoo());
uassert(ErrorCodes::BadValue,
- "Operation time is of the wrong value",
+ str::stream() << kOperationTimeFieldName << " is of the wrong type '"
+ << typeName(opTimeElem.type()) << "'",
opTimeElem.type() == bsonTimestamp);
return LogicalTime(opTimeElem.timestamp());
}
@@ -79,4 +80,12 @@ BSONObj LogicalTime::toBSON() const {
return bldr.obj();
}
+void LogicalTime::serializeToBSON(StringData fieldName, BSONObjBuilder* bob) const {
+ bob->appendElements(BSON(fieldName << asTimestamp()));
+}
+
+LogicalTime LogicalTime::parseFromBSON(const BSONElement& elem) {
+ return LogicalTime(elem.timestamp());
+}
+
} // namespace mongo
diff --git a/src/mongo/db/logical_time.h b/src/mongo/db/logical_time.h
index 2e6b135329e..68b5c143316 100644
--- a/src/mongo/db/logical_time.h
+++ b/src/mongo/db/logical_time.h
@@ -85,6 +85,12 @@ public:
*/
BSONObj toBSON() const;
+ /*
+ * These methods support IDL parsing of logical times.
+ */
+ static LogicalTime parseFromBSON(const BSONElement& elem);
+ void serializeToBSON(StringData fieldName, BSONObjBuilder* bob) const;
+
/**
* An uninitialized value of LogicalTime. Default constructed.
*/
diff --git a/src/mongo/db/namespace_string.cpp b/src/mongo/db/namespace_string.cpp
index 3b28b021c50..169339c4c57 100644
--- a/src/mongo/db/namespace_string.cpp
+++ b/src/mongo/db/namespace_string.cpp
@@ -108,6 +108,9 @@ const NamespaceString NamespaceString::kReshardingApplierProgressNamespace(
const NamespaceString NamespaceString::kReshardingTxnClonerProgressNamespace(
NamespaceString::kConfigDb, "localReshardingOperations.recipient.progress_txn_cloner");
+const NamespaceString NamespaceString::kKeysCollectionNamespace(NamespaceString::kAdminDb,
+ "system.keys");
+
bool NamespaceString::isListCollectionsCursorNS() const {
return coll() == listCollectionsCursorCol;
}
diff --git a/src/mongo/db/namespace_string.h b/src/mongo/db/namespace_string.h
index 029d9c7e18c..f702eaa2044 100644
--- a/src/mongo/db/namespace_string.h
+++ b/src/mongo/db/namespace_string.h
@@ -148,6 +148,9 @@ public:
// Namespace for storing config.transactions cloner progress for resharding.
static const NamespaceString kReshardingTxnClonerProgressNamespace;
+ // Namespace for storing keys for signing and validating cluster times.
+ static const NamespaceString kKeysCollectionNamespace;
+
/**
* Constructs an empty NamespaceString.
*/
diff --git a/src/mongo/db/s/config/config_server_test_fixture.cpp b/src/mongo/db/s/config/config_server_test_fixture.cpp
index 6013e807143..25092ea133c 100644
--- a/src/mongo/db/s/config/config_server_test_fixture.cpp
+++ b/src/mongo/db/s/config/config_server_test_fixture.cpp
@@ -369,7 +369,7 @@ std::vector<KeysCollectionDocument> ConfigServerTestFixture::getKeys(OperationCo
auto findStatus = config->exhaustiveFindOnConfig(opCtx,
kReadPref,
repl::ReadConcernLevel::kMajorityReadConcern,
- KeysCollectionDocument::ConfigNS,
+ NamespaceString::kKeysCollectionNamespace,
BSONObj(),
BSON("expiresAt" << 1),
boost::none);
@@ -378,9 +378,8 @@ std::vector<KeysCollectionDocument> ConfigServerTestFixture::getKeys(OperationCo
std::vector<KeysCollectionDocument> keys;
const auto& docs = findStatus.getValue().docs;
for (const auto& doc : docs) {
- auto keyStatus = KeysCollectionDocument::fromBSON(doc);
- ASSERT_OK(keyStatus.getStatus());
- keys.push_back(keyStatus.getValue());
+ auto key = KeysCollectionDocument::parse(IDLParserErrorContext("keyDoc"), doc);
+ keys.push_back(std::move(key));
}
return keys;
diff --git a/src/mongo/s/catalog/sharding_catalog_client.h b/src/mongo/s/catalog/sharding_catalog_client.h
index a8918a2ed36..43c2c160a18 100644
--- a/src/mongo/s/catalog/sharding_catalog_client.h
+++ b/src/mongo/s/catalog/sharding_catalog_client.h
@@ -34,7 +34,7 @@
#include <string>
#include <vector>
-#include "mongo/db/keys_collection_document.h"
+#include "mongo/db/keys_collection_document_gen.h"
#include "mongo/db/repl/optime_with.h"
#include "mongo/db/write_concern_options.h"
#include "mongo/s/client/shard.h"
diff --git a/src/mongo/s/catalog/sharding_catalog_client_impl.cpp b/src/mongo/s/catalog/sharding_catalog_client_impl.cpp
index a0dadf7de00..ff7053ab8ee 100644
--- a/src/mongo/s/catalog/sharding_catalog_client_impl.cpp
+++ b/src/mongo/s/catalog/sharding_catalog_client_impl.cpp
@@ -902,7 +902,7 @@ StatusWith<std::vector<KeysCollectionDocument>> ShardingCatalogClientImpl::getNe
auto findStatus = config->exhaustiveFindOnConfig(opCtx,
kConfigReadSelector,
readConcernLevel,
- KeysCollectionDocument::ConfigNS,
+ NamespaceString::kKeysCollectionNamespace,
queryBuilder.obj(),
BSON("expiresAt" << 1),
boost::none);
@@ -914,12 +914,13 @@ StatusWith<std::vector<KeysCollectionDocument>> ShardingCatalogClientImpl::getNe
const auto& keyDocs = findStatus.getValue().docs;
std::vector<KeysCollectionDocument> keys;
for (auto&& keyDoc : keyDocs) {
- auto parseStatus = KeysCollectionDocument::fromBSON(keyDoc);
- if (!parseStatus.isOK()) {
- return parseStatus.getStatus();
+ KeysCollectionDocument key;
+ try {
+ key = KeysCollectionDocument::parse(IDLParserErrorContext("keyDoc"), keyDoc);
+ } catch (...) {
+ return exceptionToStatus();
}
-
- keys.push_back(std::move(parseStatus.getValue()));
+ keys.push_back(std::move(key));
}
return keys;
diff --git a/src/mongo/s/catalog/sharding_catalog_client_test.cpp b/src/mongo/s/catalog/sharding_catalog_client_test.cpp
index 85ec4605657..6166fb43926 100644
--- a/src/mongo/s/catalog/sharding_catalog_client_test.cpp
+++ b/src/mongo/s/catalog/sharding_catalog_client_test.cpp
@@ -39,6 +39,7 @@
#include "mongo/db/ops/write_ops.h"
#include "mongo/db/query/query_request.h"
#include "mongo/db/repl/read_concern_args.h"
+#include "mongo/db/time_proof_service.h"
#include "mongo/executor/task_executor.h"
#include "mongo/rpc/get_status_from_command_result.h"
#include "mongo/rpc/metadata/repl_set_metadata.h"
@@ -1305,7 +1306,7 @@ TEST_F(ShardingCatalogClientTest, GetNewKeys) {
fromjson("{purpose: 'none',"
"expiresAt: {$gt: {$timestamp: {t: 1234, i: 5678}}}}"));
- ASSERT_EQ(KeysCollectionDocument::ConfigNS, query->nss());
+ ASSERT_EQ(NamespaceString::kKeysCollectionNamespace, query->nss());
ASSERT_BSONOBJ_EQ(expectedQuery, query->getFilter());
ASSERT_BSONOBJ_EQ(BSON("expiresAt" << 1), query->getSort());
ASSERT_FALSE(query->getLimit().is_initialized());
@@ -1356,7 +1357,7 @@ TEST_F(ShardingCatalogClientTest, GetNewKeysWithEmptyCollection) {
fromjson("{purpose: 'none',"
"expiresAt: {$gt: {$timestamp: {t: 1234, i: 5678}}}}"));
- ASSERT_EQ(KeysCollectionDocument::ConfigNS, query->nss());
+ ASSERT_EQ(NamespaceString::kKeysCollectionNamespace, query->nss());
ASSERT_BSONOBJ_EQ(expectedQuery, query->getFilter());
ASSERT_BSONOBJ_EQ(BSON("expiresAt" << 1), query->getSort());
ASSERT_FALSE(query->getLimit().is_initialized());