diff options
author | Shreyas Kalyan <shreyas.kalyan@mongodb.com> | 2023-04-06 12:39:14 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-04-10 11:10:42 +0000 |
commit | ee6071a0f36b7d2ffb70afe83b9b0cb9364e2ec7 (patch) | |
tree | fc294ea6487d0e1a5785db1f3248e65c0bf7990c | |
parent | c6e5701933a98b4fe91c2409c212fcce2d3d34f0 (diff) | |
download | mongo-ee6071a0f36b7d2ffb70afe83b9b0cb9364e2ec7.tar.gz |
SERVER-75171 Use the GetQueryableEncryptionCountInfo command in compaction
-rw-r--r-- | jstests/auth/lib/commands_lib.js | 2 | ||||
-rw-r--r-- | jstests/sharding/database_versioning_all_commands.js | 2 | ||||
-rw-r--r-- | src/mongo/crypto/fle_crypto.cpp | 61 | ||||
-rw-r--r-- | src/mongo/crypto/fle_crypto.h | 4 | ||||
-rw-r--r-- | src/mongo/crypto/fle_crypto_test.cpp | 4 | ||||
-rw-r--r-- | src/mongo/crypto/fle_crypto_types.h | 16 | ||||
-rw-r--r-- | src/mongo/db/commands/fle2_compact.cpp | 81 | ||||
-rw-r--r-- | src/mongo/db/commands/fle2_get_count_info_command.cpp | 53 | ||||
-rw-r--r-- | src/mongo/db/commands/fle2_get_count_info_command.idl | 28 | ||||
-rw-r--r-- | src/mongo/db/fle_crud.cpp | 54 | ||||
-rw-r--r-- | src/mongo/db/fle_crud.h | 26 | ||||
-rw-r--r-- | src/mongo/db/fle_crud_mongod.cpp | 28 | ||||
-rw-r--r-- | src/mongo/db/fle_crud_test.cpp | 4 |
13 files changed, 244 insertions, 119 deletions
diff --git a/jstests/auth/lib/commands_lib.js b/jstests/auth/lib/commands_lib.js index 2ce51bfd6a0..de2782a5ac2 100644 --- a/jstests/auth/lib/commands_lib.js +++ b/jstests/auth/lib/commands_lib.js @@ -4744,7 +4744,7 @@ export const authCommandsLib = { tokens: [ {tokens: [{"s": BinData(0, "lUBO7Mov5Sb+c/D4cJ9whhhw/+PZFLCk/AQU2+BpumQ=")}]}, ], - "forInsert": true, + "queryType": "insert", }, skipTest: (conn) => { return !TestData.setParameters.featureFlagFLE2ProtocolVersion2; diff --git a/jstests/sharding/database_versioning_all_commands.js b/jstests/sharding/database_versioning_all_commands.js index 8e22f3281a1..7e031d1e990 100644 --- a/jstests/sharding/database_versioning_all_commands.js +++ b/jstests/sharding/database_versioning_all_commands.js @@ -521,7 +521,7 @@ let testCases = { [{"s": BinData(0, "lUBO7Mov5Sb+c/D4cJ9whhhw/+PZFLCk/AQU2+BpumQ=")}] }, ], - "forInsert": true + "queryType": "insert" }; } } diff --git a/src/mongo/crypto/fle_crypto.cpp b/src/mongo/crypto/fle_crypto.cpp index c98541c5877..a30e9951b73 100644 --- a/src/mongo/crypto/fle_crypto.cpp +++ b/src/mongo/crypto/fle_crypto.cpp @@ -1806,6 +1806,61 @@ BSONObj runStateMachineForDecryption(mongocrypt_ctx_t* ctx, FLEKeyVault* keyVaul return result; } +FLEEdgeCountInfo getEdgeCountInfoForCompact(const FLEStateCollectionReader& reader, + ConstDataRange tag, + const boost::optional<PrfBlock>& edc) { + + auto escToken = EDCServerPayloadInfo::getESCToken(tag); + + auto tagToken = FLETwiceDerivedTokenGenerator::generateESCTwiceDerivedTagToken(escToken); + auto valueToken = FLETwiceDerivedTokenGenerator::generateESCTwiceDerivedValueToken(escToken); + + auto positions = ESCCollection::emuBinaryV2(reader, tagToken, valueToken); + + // Handle case where cpos is none. This means that no new non-anchors have been inserted + // since since the last compact/cleanup. + // This could happen if a previous compact inserted an anchor, but the temp ECOC drop + // was interrupted. On restart, the compaction will run emuBinaryV2 again, but since the + // anchor was already inserted for this value, it may return null cpos if there have been no + // new insertions for that value since the first compact attempt. + if (!positions.cpos.has_value()) { + // No new non-anchors since the last compact/cleanup. + // There must be at least one anchor. + uassert(7293602, + "An ESC anchor document is expected but none is found", + !positions.apos.has_value() || positions.apos.value() > 0); + // the anchor with the latest cpos already exists so no more work needed + + return FLEEdgeCountInfo( + 0, tagToken, positions.cpos, positions.apos, reader.getStats(), boost::none); + } + + uint64_t nextAnchorPos = 0; + + if (!positions.apos.has_value()) { + auto r_esc = reader.getById(ESCCollection::generateNullAnchorId(tagToken)); + + uassert(7293601, "ESC null anchor document not found", !r_esc.isEmpty()); + + auto nullAnchorDoc = + uassertStatusOK(ESCCollection::decryptAnchorDocument(valueToken, r_esc)); + nextAnchorPos = nullAnchorDoc.position + 1; + } else { + nextAnchorPos = positions.apos.value() + 1; + } + + return FLEEdgeCountInfo( + nextAnchorPos, + tagToken, + positions.cpos, + positions.apos, + reader.getStats(), + edc.map([](const PrfBlock& prf) { + return FLETokenFromCDR<FLETokenType::EDCDerivedFromDataTokenAndContentionFactorToken>( + prf); + })); +} + FLEEdgeCountInfo getEdgeCountInfo(const FLEStateCollectionReader& reader, ConstDataRange tag, FLETagQueryInterface::TagQueryType type, @@ -2716,7 +2771,11 @@ std::vector<std::vector<FLEEdgeCountInfo>> ESCCollection::getTags( countInfos.reserve(tokens.size()); for (const auto& token : tokens) { - countInfos.push_back(getEdgeCountInfo(reader, token.esc, type, token.edc)); + if (type == FLETagQueryInterface::TagQueryType::kCompact) { + countInfos.push_back(getEdgeCountInfoForCompact(reader, token.esc, token.edc)); + } else { + countInfos.push_back(getEdgeCountInfo(reader, token.esc, type, token.edc)); + } } countInfoSets.emplace_back(countInfos); diff --git a/src/mongo/crypto/fle_crypto.h b/src/mongo/crypto/fle_crypto.h index 7b49241fd54..24ac7425bae 100644 --- a/src/mongo/crypto/fle_crypto.h +++ b/src/mongo/crypto/fle_crypto.h @@ -331,7 +331,7 @@ struct ESCDocument { */ class FLETagQueryInterface { public: - enum class TagQueryType { kInsert, kQuery }; + enum class TagQueryType { kInsert, kQuery, kCompact }; virtual ~FLETagQueryInterface(); @@ -386,6 +386,8 @@ public: virtual bool existsById(PrfBlock block) const { return !getById(block).isEmpty(); } + + virtual ECStats getStats() const = 0; }; class ESCCollection { diff --git a/src/mongo/crypto/fle_crypto_test.cpp b/src/mongo/crypto/fle_crypto_test.cpp index 15acde90f69..94fff514108 100644 --- a/src/mongo/crypto/fle_crypto_test.cpp +++ b/src/mongo/crypto/fle_crypto_test.cpp @@ -606,6 +606,10 @@ public: return _docs.size(); } + ECStats getStats() const override { + return ECStats(); + } + void setOverrideCount(int64_t count) { _overrideCount = count; } diff --git a/src/mongo/crypto/fle_crypto_types.h b/src/mongo/crypto/fle_crypto_types.h index 5affa1a6122..12bb268b294 100644 --- a/src/mongo/crypto/fle_crypto_types.h +++ b/src/mongo/crypto/fle_crypto_types.h @@ -35,6 +35,7 @@ #include "mongo/base/secure_allocator.h" #include "mongo/crypto/aead_encryption.h" +#include "mongo/crypto/fle_stats_gen.h" #include "mongo/util/uuid.h" namespace mongo { @@ -261,11 +262,26 @@ struct FLEEdgeCountInfo { boost::optional<EDCDerivedFromDataTokenAndContentionFactorToken> edcParam) : count(c), tagToken(t), edc(edcParam) {} + FLEEdgeCountInfo(uint64_t c, + ESCTwiceDerivedTagToken t, + boost::optional<uint64_t> cpos, + boost::optional<uint64_t> apos, + boost::optional<ECStats> stats, + boost::optional<EDCDerivedFromDataTokenAndContentionFactorToken> edcParam) + : count(c), tagToken(t), cpos(cpos), apos(apos), stats(stats), edc(edcParam) {} + + // May reflect a value suitable for insert or query. uint64_t count; ESCTwiceDerivedTagToken tagToken; + boost::optional<uint64_t> cpos; + + boost::optional<uint64_t> apos; + + boost::optional<ECStats> stats; + boost::optional<EDCDerivedFromDataTokenAndContentionFactorToken> edc; }; diff --git a/src/mongo/db/commands/fle2_compact.cpp b/src/mongo/db/commands/fle2_compact.cpp index f637e1c8dc8..162103af76f 100644 --- a/src/mongo/db/commands/fle2_compact.cpp +++ b/src/mongo/db/commands/fle2_compact.cpp @@ -105,34 +105,6 @@ void CompactStatsCounter<ECOCStats>::add(const ECOCStats& other) { addDeletes(other.getDeleted()); } -/** - * Implementation of FLEStateCollectionReader for txn_api::TransactionClient - */ -template <typename StatsType> -class TxnCollectionReaderForCompact : public FLEStateCollectionReader { -public: - TxnCollectionReaderForCompact(FLEQueryInterface* queryImpl, - const NamespaceString& nss, - StatsType* stats) - : _queryImpl(queryImpl), _nss(nss), _stats(stats) {} - - uint64_t getDocumentCount() const override { - return _queryImpl->countDocuments(_nss); - } - - BSONObj getById(PrfBlock block) const override { - auto doc = BSON("v" << BSONBinData(block.data(), block.size(), BinDataGeneral)); - BSONElement element = doc.firstElement(); - auto result = _queryImpl->getById(_nss, element); - _stats.addReads(1); - return result; - } - -private: - FLEQueryInterface* _queryImpl; - const NamespaceString& _nss; - mutable CompactStatsCounter<StatsType> _stats; -}; } // namespace @@ -209,47 +181,38 @@ void compactOneFieldValuePairV2(FLEQueryInterface* queryImpl, const ECOCCompactionDocumentV2& ecocDoc, const NamespaceString& escNss, ECStats* escStats) { - auto escTagToken = FLETwiceDerivedTokenGenerator::generateESCTwiceDerivedTagToken(ecocDoc.esc); auto escValueToken = FLETwiceDerivedTokenGenerator::generateESCTwiceDerivedValueToken(ecocDoc.esc); - CompactStatsCounter<ECStats> stats(escStats); - TxnCollectionReaderForCompact reader(queryImpl, escNss, escStats); - - auto positions = ESCCollection::emuBinaryV2(reader, escTagToken, escValueToken); - - // Handle case where cpos is none. This means that no new non-anchors have been inserted - // since since the last compact/cleanup. - // This could happen if a previous compact inserted an anchor, but the temp ECOC drop - // was interrupted. On restart, the compaction will run emuBinaryV2 again, but since the - // anchor was already inserted for this value, it may return null cpos if there have been no - // new insertions for that value since the first compact attempt. - if (!positions.cpos.has_value()) { - // No new non-anchors since the last compact/cleanup. - // There must be at least one anchor. - uassert(7293602, - "An ESC anchor document is expected but none is found", - !positions.apos.has_value() || positions.apos.value() > 0); - // the anchor with the latest cpos already exists so no more work needed - return; + std::vector<std::vector<FLEEdgePrfBlock>> tags; + { + FLEEdgePrfBlock edgeSet{ecocDoc.esc.data, boost::none}; + tags.push_back({edgeSet}); } - uint64_t nextAnchorPos = 0; + auto countInfoSets = + queryImpl->getTags(escNss, tags, FLEQueryInterface::TagQueryType::kCompact); - if (!positions.apos.has_value()) { - auto r_esc = reader.getById(ESCCollection::generateNullAnchorId(escTagToken)); + uassert(7517100, + "CountInfoSets cannot be empty and must have one value.", + countInfoSets.size() == 1 && countInfoSets[0].size() == 1); - uassert(7293601, "ESC null anchor document not found", !r_esc.isEmpty()); + auto& val = countInfoSets[0][0]; + CompactStatsCounter<ECStats> stats(escStats); + + auto& tagToken = val.tagToken; + auto cpos = val.cpos; - auto nullAnchorDoc = - uassertStatusOK(ESCCollection::decryptAnchorDocument(escValueToken, r_esc)); - nextAnchorPos = nullAnchorDoc.position + 1; - } else { - nextAnchorPos = positions.apos.value() + 1; + uassert( + 7517103, "Stats cannot be empty for compacting a field value pair.", val.stats.has_value()); + stats.add(val.stats.get()); + + if (!val.cpos) { + return; } - auto anchorDoc = ESCCollection::generateAnchorDocument( - escTagToken, escValueToken, nextAnchorPos, positions.cpos.value()); + auto anchorDoc = + ESCCollection::generateAnchorDocument(tagToken, escValueToken, val.count, cpos.value()); StmtId stmtId = kUninitializedStmtId; if (MONGO_unlikely(fleCompactHangBeforeESCAnchorInsert.shouldFail())) { diff --git a/src/mongo/db/commands/fle2_get_count_info_command.cpp b/src/mongo/db/commands/fle2_get_count_info_command.cpp index fe5b82fe9b3..b1dd29fd4dd 100644 --- a/src/mongo/db/commands/fle2_get_count_info_command.cpp +++ b/src/mongo/db/commands/fle2_get_count_info_command.cpp @@ -70,6 +70,29 @@ std::vector<std::vector<FLEEdgePrfBlock>> toNestedTokens( return nestedBlocks; } +QECountInfoReplyTokens tokenFromCountInfo(const FLEEdgeCountInfo& countInfo) { + QECountInfoReplyTokens token(FLEUtil::vectorFromCDR(countInfo.tagToken.toCDR()), + countInfo.count); + + if (countInfo.edc) { + token.setEDCDerivedFromDataTokenAndContentionFactorToken(countInfo.edc.value().toCDR()); + } + + if (countInfo.cpos) { + token.setCpos(countInfo.cpos.get()); + } + + if (countInfo.apos) { + token.setApos(countInfo.apos.get()); + } + + if (countInfo.stats) { + token.setStats(countInfo.stats.get()); + } + + return token; +} + std::vector<QECountInfoReplyTokenSet> toGetTagRequestTupleSet( const std::vector<std::vector<FLEEdgeCountInfo>>& countInfoSets) { @@ -82,14 +105,7 @@ std::vector<QECountInfoReplyTokenSet> toGetTagRequestTupleSet( tokens.reserve(countInfos.size()); for (auto& countInfo : countInfos) { - tokens.emplace_back(FLEUtil::vectorFromCDR(countInfo.tagToken.toCDR()), - countInfo.count); - - if (countInfo.edc.has_value()) { - auto& replyTuple = tokens.back(); - replyTuple.setEDCDerivedFromDataTokenAndContentionFactorToken( - countInfo.edc.value().toCDR()); - } + tokens.emplace_back(tokenFromCountInfo(countInfo)); } nestedBlocks.emplace_back(std::move(tokens)); @@ -98,6 +114,19 @@ std::vector<QECountInfoReplyTokenSet> toGetTagRequestTupleSet( return nestedBlocks; } +FLEQueryInterface::TagQueryType queryTypeTranslation(QECountInfoQueryTypeEnum type) { + switch (type) { + case QECountInfoQueryTypeEnum::Insert: + return FLEQueryInterface::TagQueryType::kInsert; + case QECountInfoQueryTypeEnum::Query: + return FLEQueryInterface::TagQueryType::kQuery; + case QECountInfoQueryTypeEnum::Compact: + return FLEQueryInterface::TagQueryType::kCompact; + default: + uasserted(7517102, "Invalid QECountInfoQueryTypeEnum value."); + } +} + QECountInfosReply getTagsLocal(OperationContext* opCtx, const GetQueryableEncryptionCountInfo& request) { @@ -105,12 +134,8 @@ QECountInfosReply getTagsLocal(OperationContext* opCtx, auto nestedTokens = toNestedTokens(request.getTokens()); - auto countInfoSets = - getTagsFromStorage(opCtx, - request.getNamespace(), - nestedTokens, - request.getForInsert() ? FLETagQueryInterface::TagQueryType::kInsert - : FLETagQueryInterface::TagQueryType::kQuery); + auto countInfoSets = getTagsFromStorage( + opCtx, request.getNamespace(), nestedTokens, queryTypeTranslation(request.getQueryType())); QECountInfosReply reply; reply.setCounts(toGetTagRequestTupleSet(countInfoSets)); diff --git a/src/mongo/db/commands/fle2_get_count_info_command.idl b/src/mongo/db/commands/fle2_get_count_info_command.idl index 93a1a6df499..8717fa9e32f 100644 --- a/src/mongo/db/commands/fle2_get_count_info_command.idl +++ b/src/mongo/db/commands/fle2_get_count_info_command.idl @@ -31,6 +31,7 @@ global: imports: - "mongo/db/basic_types.idl" + - "mongo/crypto/fle_stats.idl" structs: QECountInfoReplyTokens: @@ -50,6 +51,18 @@ structs: type: bindata_generic cpp_name: EDCDerivedFromDataTokenAndContentionFactorToken optional: true + cpos: + description: "cpos argument returned from emuBinary" + type: long + optional: true + apos: + description: "cpos argument returned from emuBinary" + type: long + optional: true + stats: + description: "stats returned for compaction algorithm" + type: ECStats + optional: true QECountInfoReplyTokenSet: description: "Array of tokens sets" @@ -87,6 +100,14 @@ structs: fields: counts: array<QECountInfoReplyTokenSet> +enums: + QECountInfoQueryType: + description: "query types" + type: string + values: + Insert: "insert" + Query: "query" + Compact: "compact" commands: getQueryableEncryptionCountInfo: @@ -100,6 +121,7 @@ commands: tokens: description: "Array of tokens to fetch" type: array<QECountInfoRequestTokenSet> - forInsert: - description: Whether to return a count for insert or query - type: bool + queryType: + description: "Purpose of command, either for insert, query, or compact" + type: QECountInfoQueryType + diff --git a/src/mongo/db/fle_crud.cpp b/src/mongo/db/fle_crud.cpp index db64687f09f..0868141218c 100644 --- a/src/mongo/db/fle_crud.cpp +++ b/src/mongo/db/fle_crud.cpp @@ -186,6 +186,30 @@ std::vector<QECountInfoRequestTokenSet> toTagSets( return nestedBlocks; } +FLEEdgeCountInfo convertTokensToEdgeCount(const QECountInfoReplyTokens& token) { + + boost::optional<EDCDerivedFromDataTokenAndContentionFactorToken> edc; + if (token.getEDCDerivedFromDataTokenAndContentionFactorToken()) { + edc = FLETokenFromCDR<FLETokenType::EDCDerivedFromDataTokenAndContentionFactorToken>( + token.getEDCDerivedFromDataTokenAndContentionFactorToken().value()); + } + + boost::optional<uint64_t> cpos; + if (token.getCpos()) { + cpos = token.getCpos(); + } + + boost::optional<uint64_t> apos; + if (token.getApos()) { + apos = token.getApos(); + } + + auto esc = + FLETokenFromCDR<FLETokenType::ESCTwiceDerivedTagToken>(token.getESCTwiceDerivedTagToken()); + + return FLEEdgeCountInfo(token.getCount(), esc, cpos, apos, token.getStats(), edc); +} + std::vector<std::vector<FLEEdgeCountInfo>> toEdgeCounts( const std::vector<QECountInfoReplyTokenSet>& tupleSet) { @@ -200,16 +224,7 @@ std::vector<std::vector<FLEEdgeCountInfo>> toEdgeCounts( blocks.reserve(tuples.size()); for (auto& tuple : tuples) { - blocks.emplace_back(tuple.getCount(), - FLETokenFromCDR<FLETokenType::ESCTwiceDerivedTagToken>( - tuple.getESCTwiceDerivedTagToken())); - auto& p = blocks.back(); - - if (tuple.getEDCDerivedFromDataTokenAndContentionFactorToken().has_value()) { - p.edc = - FLETokenFromCDR<FLETokenType::EDCDerivedFromDataTokenAndContentionFactorToken>( - tuple.getEDCDerivedFromDataTokenAndContentionFactorToken().value()); - } + blocks.emplace_back(convertTokensToEdgeCount(tuple)); } nestedBlocks.emplace_back(std::move(blocks)); @@ -1467,6 +1482,19 @@ uint64_t FLEQueryInterfaceImpl::countDocuments(const NamespaceString& nss) { return static_cast<uint64_t>(signedDocCount); } +QECountInfoQueryTypeEnum queryTypeTranslation(FLEQueryInterface::TagQueryType type) { + switch (type) { + case FLEQueryInterface::TagQueryType::kInsert: + return QECountInfoQueryTypeEnum::Insert; + case FLEQueryInterface::TagQueryType::kQuery: + return QECountInfoQueryTypeEnum::Query; + case FLEQueryInterface::TagQueryType::kCompact: + return QECountInfoQueryTypeEnum::Compact; + default: + uasserted(7517101, "Invalid TagQueryType value."); + } +} + std::vector<std::vector<FLEEdgeCountInfo>> FLEQueryInterfaceImpl::getTags( const NamespaceString& nss, const std::vector<std::vector<FLEEdgePrfBlock>>& tokensSets, @@ -1480,7 +1508,7 @@ std::vector<std::vector<FLEEdgeCountInfo>> FLEQueryInterfaceImpl::getTags( } getCountsCmd.setTokens(toTagSets(tokensSets)); - getCountsCmd.setForInsert(type == FLEQueryInterface::TagQueryType::kInsert); + getCountsCmd.setQueryType(queryTypeTranslation(type)); auto response = _txnClient.runCommandSync(nss.db(), getCountsCmd.toBSON({})); @@ -1756,7 +1784,7 @@ uint64_t FLETagNoTXNQuery::countDocuments(const NamespaceString& nss) { std::vector<std::vector<FLEEdgeCountInfo>> FLETagNoTXNQuery::getTags( const NamespaceString& nss, const std::vector<std::vector<FLEEdgePrfBlock>>& tokensSets, - TagQueryType type) { + FLEQueryInterface::TagQueryType type) { invariant(!_opCtx->inMultiDocumentTransaction()); @@ -1775,7 +1803,7 @@ std::vector<std::vector<FLEEdgeCountInfo>> FLETagNoTXNQuery::getTags( } getCountsCmd.setTokens(toTagSets(tokensSets)); - getCountsCmd.setForInsert(type == FLEQueryInterface::TagQueryType::kInsert); + getCountsCmd.setQueryType(queryTypeTranslation(type)); DBDirectClient directClient(opCtx.get()); diff --git a/src/mongo/db/fle_crud.h b/src/mongo/db/fle_crud.h index 30c30c90cb2..a2c5fe051a7 100644 --- a/src/mongo/db/fle_crud.h +++ b/src/mongo/db/fle_crud.h @@ -378,32 +378,6 @@ private: }; /** - * Implementation of FLEStateCollectionReader for txn_api::TransactionClient - * - * Document count is cached since we only need it once per esc or ecc collection. - */ -class TxnCollectionReader : public FLEStateCollectionReader { -public: - TxnCollectionReader(uint64_t count, FLETagQueryInterface* queryImpl, const NamespaceString& nss) - : _count(count), _queryImpl(queryImpl), _nss(nss) {} - - uint64_t getDocumentCount() const override { - return _count; - } - - BSONObj getById(PrfBlock block) const override { - auto doc = BSON("v" << BSONBinData(block.data(), block.size(), BinDataGeneral)); - BSONElement element = doc.firstElement(); - return _queryImpl->getById(_nss, element); - } - -private: - uint64_t _count; - FLETagQueryInterface* _queryImpl; - NamespaceString _nss; -}; - -/** * Creates a new SyncTransactionWithRetries object that runs a transaction on the * sharding fixed task executor. */ diff --git a/src/mongo/db/fle_crud_mongod.cpp b/src/mongo/db/fle_crud_mongod.cpp index 19650224271..a13e25c6685 100644 --- a/src/mongo/db/fle_crud_mongod.cpp +++ b/src/mongo/db/fle_crud_mongod.cpp @@ -27,6 +27,7 @@ * it in the license file. */ +#include "mongo/base/status.h" #include "mongo/db/fle_crud.h" #include <string> @@ -169,6 +170,10 @@ public: return BSONObj(); } + + ECStats getStats() const override { + return ECStats(); + } }; @@ -189,8 +194,17 @@ public: return _count; } + void incrementRead() const { + _stats.setRead(_stats.getRead() + 1); + } + + ECStats getStats() const override { + return _stats; + } + BSONObj getById(PrfBlock block) const override { auto record = getRecordById(block); + if (record.has_value()) { return record->data.releaseToBson(); } @@ -211,6 +225,7 @@ private: builder.appendBinData(BSONBinData(block.data(), block.size(), BinDataType::BinDataGeneral)); auto recordId = RecordId(builder.getBuffer(), builder.getSize()); + incrementRead(); return _cursor->seekExact(recordId); } @@ -219,6 +234,7 @@ private: const uint64_t _count; const NamespaceStringOrUUID& _nssOrUUID; SeekableRecordCursor* _cursor; + mutable ECStats _stats; }; /** @@ -246,8 +262,17 @@ public: return _count; } + void incrementRead() const { + _stats.setRead(_stats.getRead() + 1); + } + + ECStats getStats() const override { + return _stats; + } + BSONObj getById(PrfBlock block) const override { auto record = getRecordById(block); + if (record.has_value()) { return record->data.releaseToBson(); } @@ -270,6 +295,8 @@ private: kb.appendBinData(BSONBinData(block.data(), block.size(), BinDataGeneral)); KeyString::Value id(kb.getValueCopy()); + incrementRead(); + auto ksEntry = _indexCursor->seekForKeyString(id); if (!ksEntry) { return boost::none; @@ -299,6 +326,7 @@ private: SortedDataInterface* _sdi; SortedDataInterface::Cursor* _indexCursor; SeekableRecordCursor* _cursor; + mutable ECStats _stats; }; const auto kIdIndexName = "_id_"_sd; diff --git a/src/mongo/db/fle_crud_test.cpp b/src/mongo/db/fle_crud_test.cpp index 65739ebba8d..e025da89572 100644 --- a/src/mongo/db/fle_crud_test.cpp +++ b/src/mongo/db/fle_crud_test.cpp @@ -745,6 +745,10 @@ public: return _queryImpl.getById(_coll, doc.firstElement()); } + ECStats getStats() const override { + return ECStats(); + } + private: NamespaceString _coll; FLEQueryInterfaceMock& _queryImpl; |