diff --git a/.clang-tidy.in b/.clang-tidy.in index 48904483f56..d26e7fe3412 100644 --- a/.clang-tidy.in +++ b/.clang-tidy.in @@ -49,6 +49,7 @@ Checks: '-*, hicpp-static-assert, hicpp-undelegated-constructor, misc-definitions-in-headers, + misc-header-include-cycle, misc-new-delete-overloads, misc-static-assert, misc-unconventional-assign-operator, @@ -137,7 +138,7 @@ Checks: '-*, -readability-simplify-subscript-expr, -readability-static-accessed-through-instance, -readability-string-compare, - -readability-uniqueptr-delete-release + -readability-uniqueptr-delete-release, ' HeaderFilterRegex: 'mongo/[-A-Za-z0-9_/]*\.(h|hpp|ipp|inl|cstruct.h|defs|def.h)' CheckOptions: diff --git a/src/mongo/BUILD.bazel b/src/mongo/BUILD.bazel index d8c89f9b1f0..d865ec9e62d 100644 --- a/src/mongo/BUILD.bazel +++ b/src/mongo/BUILD.bazel @@ -210,7 +210,6 @@ mongo_cc_library( "//src/mongo/base:data_range_cursor.h", "//src/mongo/base:data_type.h", "//src/mongo/base:data_type_endian.h", - "//src/mongo/base:data_type_string_data.h", "//src/mongo/base:data_type_terminated.h", "//src/mongo/base:data_view.h", "//src/mongo/base:dependency_graph.h", diff --git a/src/mongo/base/data_type.h b/src/mongo/base/data_type.h index 84105dc1da5..0c91bb98a4c 100644 --- a/src/mongo/base/data_type.h +++ b/src/mongo/base/data_type.h @@ -166,10 +166,24 @@ struct DataType { static Status makeTrivialLoadStatus(size_t sizeOfT, size_t length, size_t debug_offset); }; +template <> +struct DataType::Handler { + // Consumes all available data, producing + // a `StringData(ptr,length)`. + static Status load(StringData* sdata, + const char* ptr, + size_t length, + size_t* advanced, + std::ptrdiff_t debug_offset); + + // Copies `sdata` fully into the [ptr,ptr+length) range. + // Does nothing and returns an Overflow status if + // `sdata` doesn't fit. + static Status store( + StringData sdata, char* ptr, size_t length, size_t* advanced, std::ptrdiff_t debug_offset); + + static StringData defaultConstruct() { + return StringData(); + } +}; } // namespace mongo - -// Force the visibility of the DataType::Handler specializations. -#define MONGO_BASE_DATA_TYPE_H_INCLUDE_HANDSHAKE_ -#include "mongo/base/data_type_string_data.h" - -#undef MONGO_BASE_DATA_TYPE_H_INCLUDE_HANDSHAKE_ diff --git a/src/mongo/base/data_type_string_data.h b/src/mongo/base/data_type_string_data.h deleted file mode 100644 index 3efdde87378..00000000000 --- a/src/mongo/base/data_type_string_data.h +++ /dev/null @@ -1,68 +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 - * . - * - * 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 -#include - -#include "mongo/base/data_type.h" -#include "mongo/base/status.h" -#include "mongo/base/string_data.h" - -#ifndef MONGO_BASE_DATA_TYPE_H_INCLUDE_HANDSHAKE_ -#error "do not include directly. Use mongo/base/data_type.h" -#endif // MONGO_BASE_DATA_TYPE_H_INCLUDE_HANDSHAKE_ - -// Provides a DataType::Handler specialization for StringData. - -namespace mongo { - -template <> -struct DataType::Handler { - // Consumes all available data, producing - // a `StringData(ptr,length)`. - static Status load(StringData* sdata, - const char* ptr, - size_t length, - size_t* advanced, - std::ptrdiff_t debug_offset); - - // Copies `sdata` fully into the [ptr,ptr+length) range. - // Does nothing and returns an Overflow status if - // `sdata` doesn't fit. - static Status store( - StringData sdata, char* ptr, size_t length, size_t* advanced, std::ptrdiff_t debug_offset); - - static StringData defaultConstruct() { - return StringData(); - } -}; - -} // namespace mongo diff --git a/src/mongo/bson/column/BUILD.bazel b/src/mongo/bson/column/BUILD.bazel index 183b11a5506..d44618713fa 100644 --- a/src/mongo/bson/column/BUILD.bazel +++ b/src/mongo/bson/column/BUILD.bazel @@ -27,7 +27,6 @@ mongo_cc_library( "simple8b.h", "simple8b.inl", "simple8b_builder.h", - "simple8b_builder.inl", "simple8b_helpers.h", "simple8b_type_util.h", "//src/mongo/util:overloaded_visitor.h", diff --git a/src/mongo/bson/column/simple8b_builder.h b/src/mongo/bson/column/simple8b_builder.h index b9d50e82d33..f1663124ec5 100644 --- a/src/mongo/bson/column/simple8b_builder.h +++ b/src/mongo/bson/column/simple8b_builder.h @@ -30,15 +30,22 @@ #pragma once #include +#include #include +#include #include +#include +#include #include #include #include #include #include +#include #include +#include "mongo/bson/column/simple8b_helpers.h" + namespace mongo { /** * Concept for writing 64bit simple8b blocks via a callback. @@ -349,6 +356,625 @@ private: std::vector _pendingValues; }; -} // namespace mongo +// This is called in _encode while iterating through _pendingValues. For the base selector, we just +// return val. Contains unsed vars in order to seamlessly integrate with seven and eight selector +// extensions. +template +struct Simple8bBuilder::BaseSelectorEncodeFunctor { + uint64_t operator()(const PendingValue& value) { + return static_cast(value.value()); + }; +}; -#include "mongo/bson/column/simple8b_builder.inl" +// This is called in _encode while iterating through _pendingValues. It creates part of a simple8b +// word according to the specifications of the sevenSelector extension. This value is then appended +// to the full simple8b word in _encode. +template +struct Simple8bBuilder::SevenSelectorEncodeFunctor { + uint64_t operator()(const PendingValue& value) { + using namespace simple8b_internal; + + uint8_t trailingZeros = value.trailingZerosCount[kSevenSelector]; + uint64_t currWord = trailingZeros; + // We do two shifts here to account for the case where trailingZeros is > kTrailingZero bit + // size. If we subtracted this could lead to shift by a negative value which is undefined. + currWord |= static_cast((value.value() >> trailingZeros) + << kTrailingZeroBitSize[kSevenSelector]); + return currWord; + }; +}; + +// This is a helper functor that is extended by the EightSelectorSmall and EightSelectorLarge encode +// functors. It provides the logic for encoding with the eight selector where the extension type is +// designated by the inheritance in the EightSelectorSmall and EightSelectorLarge functors. +template +template +struct Simple8bBuilder::EightSelectorEncodeFunctor { + uint64_t operator()(const PendingValue& value) { + using namespace simple8b_internal; + + // integer division. We have a nibble shift of size 4 + uint8_t trailingZeros = value.trailingZerosCount[ExtensionType] / kNibbleShiftSize; + uint64_t currWord = trailingZeros; + // Shift to remove trailing zeros * 4 and then shift over for the 4 bits to hold + // the trailingZerosCount + currWord |= static_cast((value.value() >> (trailingZeros * kNibbleShiftSize)) + << kTrailingZeroBitSize[ExtensionType]); + return currWord; + } +}; + +// This is called in _encode while iterating through _pendingValues. It creates part of a simple8b +// word according to the specifications of the eightSelectorSmall extension. This value is then +// appended to the full simple8b word in _encode. +template +struct Simple8bBuilder::EightSelectorSmallEncodeFunctor + : public EightSelectorEncodeFunctor {}; + +// This is called in _encode while iterating through _pendingValues. It creates part of a simple8b +// word according to the specifications of the eightSelectorLarge extension. This value is then +// appended to the full simple8b word in _encode. +template +struct Simple8bBuilder::EightSelectorLargeEncodeFunctor + : public EightSelectorEncodeFunctor {}; + +// Base Constructor for PendingValue +template +Simple8bBuilder::PendingValue::PendingValue( + boost::optional val, + std::array bitCount, + std::array trailingZerosCount) + : val(val), bitCount(bitCount), trailingZerosCount(trailingZerosCount){}; + +template +Simple8bBuilder::PendingIterator::PendingIterator( + typename std::vector::const_iterator beginning, + typename std::vector::const_iterator it, + reference rleValue, + uint32_t rleCount) + : _begin(beginning), _it(it), _rleValue(rleValue), _rleCount(rleCount) {} + +template +auto Simple8bBuilder::PendingIterator::operator->() const -> pointer { + return &operator*(); +} + +template +auto Simple8bBuilder::PendingIterator::operator*() const -> reference { + if (_rleCount > 0) + return _rleValue; + + return _it->val; +} + +template +auto Simple8bBuilder::PendingIterator::operator++() -> PendingIterator& { + if (_rleCount > 0) { + --_rleCount; + return *this; + } + + ++_it; + return *this; +} + +template +auto Simple8bBuilder::PendingIterator::operator++(int) -> PendingIterator { + auto ret = *this; + ++(*this); + return ret; +} + +template +auto Simple8bBuilder::PendingIterator::operator--() -> PendingIterator& { + if (_rleCount > 0 || _it == _begin) { + ++_rleCount; + return *this; + } + + --_it; + return *this; +} + +template +auto Simple8bBuilder::PendingIterator::operator--(int) -> PendingIterator { + auto ret = *this; + --(*this); + return ret; +} + +template +bool Simple8bBuilder::PendingIterator::operator==( + const Simple8bBuilder::PendingIterator& rhs) const { + return _it == rhs._it && _rleCount == rhs._rleCount; +} + +template +bool Simple8bBuilder::PendingIterator::operator!=( + const Simple8bBuilder::PendingIterator& rhs) const { + return !operator==(rhs); +} + +template +Simple8bBuilder::Simple8bBuilder(Allocator allocator) : _pendingValues(allocator) {} + +template +Simple8bBuilder::~Simple8bBuilder() = default; + +template +template +requires Simple8bBlockWriter +void Simple8bBuilder::prefillWithSkips(size_t numSkips, F&& writeFn) { + constexpr size_t kMaxSkipsInBlock = 60; + constexpr uint64_t kAllSkipsBlock = + 0xFFFFFFFFFFFFFFF1; // A simple8b block that contains 60 skips + + // Do checks once, and then process all skips in bulk + uassert(8575002, + "prefillWithSkips() called after other appends", + _rleCount == 0 && _pendingValues.empty() && _lastValidExtensionType == 0); + + if (numSkips > kMaxSkipsInBlock) { + // Handle case with initialized _rleCount (this should be the common case) + writeFn(kAllSkipsBlock); + _rleCount = numSkips - kMaxSkipsInBlock; + _lastValueInPrevWord = boost::none; + } else { + // Insufficient skips to start an _rleCount, just default to appending them + // individually (we can skip rle checks) + for (size_t i = 0; i < numSkips; ++i) + _appendSkip(true, writeFn); + } +} + +template +template +requires Simple8bBlockWriter +bool Simple8bBuilder::append(T value, F&& writeFn) { + if (rlePossible()) { + if (_lastValueInPrevWord == value) { + ++_rleCount; + // RLE does not use selectors, make sure they are reset. + _lastValidExtensionType = 0; + isSelectorPossible.fill(true); + return true; + } + _handleRleTermination(writeFn); + } + + return _appendValue(value, true, writeFn); +} + +template +template +requires Simple8bBlockWriter +void Simple8bBuilder::skip(F&& writeFn) { + if (rlePossible()) { + if (!_lastValueInPrevWord.has_value()) { + ++_rleCount; + // RLE does not use selectors, make sure they are reset. + _lastValidExtensionType = 0; + isSelectorPossible.fill(true); + return; + } + _handleRleTermination(writeFn); + } + _appendSkip(true /* tryRle */, writeFn); +} + +template +template +requires Simple8bBlockWriter +void Simple8bBuilder::flush(F&& writeFn) { + // Flush repeating integers that have been kept for RLE. + _handleRleTermination(writeFn); + // Flush buffered values in _pendingValues. + if (!_pendingValues.empty()) { + // always flush with the most recent valid selector. This value is the baseSelector if we + // have not have a valid selector yet. + do { + uint64_t simple8bWord = _encodeLargestPossibleWord(_lastValidExtensionType); + writeFn(simple8bWord); + } while (!_pendingValues.empty()); + + // There are no more words in _pendingValues and RLE is possible. + // However the _rleCount is 0 because we have not read any of the values in the next word. + _rleCount = 0; + } +} + +template +void Simple8bBuilder::setLastForRLE(boost::optional val) { + _lastValueInPrevWord = val; + if (val) { + auto pendingValue = _calculatePendingValue(*val); + invariant(pendingValue); + invariant(_doesIntegerFitInCurrentWord(*pendingValue)); + } +} + +template +void Simple8bBuilder::resetLastForRLEIfNeeded() { + if (!rlePossible()) { + _lastValueInPrevWord = 0; + } +} + +template +void Simple8bBuilder::initializeRLEFrom(const Simple8bBuilder& other) { + if (other.rlePossible()) { + _lastValueInPrevWord = other._lastValueInPrevWord; + } +} + +template +boost::optional::PendingValue> +Simple8bBuilder::_calculatePendingValue(T value) { + using namespace simple8b_internal; + + // Early exit if we try to store max value. They are not handled when counting zeros. + if (value == std::numeric_limits::max()) + return boost::none; + + uint8_t trailingZerosCount = countTrailingZerosWithZero(value); + // Initially set every selector as invalid. + uint8_t bitCountWithoutLeadingZeros = countBitsWithoutLeadingZeros(value); + uint8_t trailingZerosStoredInCountSeven = + (std::min(trailingZerosCount, kTrailingZerosMaxCount[kSevenSelector])); + uint8_t meaningfulValueBitsStoredWithSeven = + bitCountWithoutLeadingZeros - trailingZerosStoredInCountSeven; + // We use integer division to ensure that a multiple of 4 is stored in + // trailingZerosStoredInCount when we have the nibble shift. + uint8_t trailingZerosStoredInCountEightSmall = + (std::min(trailingZerosCount, kTrailingZerosMaxCount[kEightSelectorSmall]) / + kNibbleShiftSize) * + kNibbleShiftSize; + uint8_t meaningfulValueBitsStoredWithEightSmall = + bitCountWithoutLeadingZeros - trailingZerosStoredInCountEightSmall; + // We use integer division to ensure that a multiple of 4 is stored in + // trailingZerosStoredInCount when we have the nibble shift. + uint8_t trailingZerosStoredInCountEightLarge = + (std::min(trailingZerosCount, kTrailingZerosMaxCount[kEightSelectorLarge]) / + kNibbleShiftSize) * + kNibbleShiftSize; + uint8_t meaningfulValueBitsStoredWithEightLarge = + bitCountWithoutLeadingZeros - trailingZerosStoredInCountEightLarge; + + // Edge cases where we have the number of trailing zeros bits as all ones and we need to add a + // padded zero to the meaningful bits to avoid confilicts with skip storage. Otherwise, we can + // reuse the bitCountWithoutLeadingZeros already calculated above. + if (trailingZerosCount == kTrailingZerosMaxCount[kSevenSelector]) { + meaningfulValueBitsStoredWithSeven = + countBitsWithoutLeadingZeros(value >> trailingZerosCount); + } else if (trailingZerosCount == kTrailingZerosMaxCount[kEightSelectorSmall]) { + meaningfulValueBitsStoredWithEightSmall = + countBitsWithoutLeadingZeros(value >> trailingZerosCount); + } + + // This case is specifically for 128 bit types where we have 124 zeros or max zeros + // count. We do not need to even check this for 64 bit types + if constexpr (std::is_same::value) { + if (trailingZerosCount == kTrailingZerosMaxCount[kEightSelectorLarge]) { + meaningfulValueBitsStoredWithEightLarge = + countBitsWithoutLeadingZeros(value >> trailingZerosCount); + } + } + + std::array zeroCount = {0, + trailingZerosStoredInCountSeven, + trailingZerosStoredInCountEightSmall, + trailingZerosStoredInCountEightLarge}; + + // Check if the amount of bits needed is more than we can store using all selector combinations. + if ((bitCountWithoutLeadingZeros > kDataBits[kBaseSelector]) && + (meaningfulValueBitsStoredWithSeven + kTrailingZeroBitSize[kSevenSelector] > + kDataBits[kSevenSelector]) && + (meaningfulValueBitsStoredWithEightSmall + kTrailingZeroBitSize[kEightSelectorSmall] > + kDataBits[kEightSelectorSmall]) && + (meaningfulValueBitsStoredWithEightLarge + kTrailingZeroBitSize[kEightSelectorLarge] > + kDataBits[kEightSelectorLarge])) { + return boost::none; + } + + return PendingValue{value, + {bitCountWithoutLeadingZeros, + meaningfulValueBitsStoredWithSeven, + meaningfulValueBitsStoredWithEightSmall, + meaningfulValueBitsStoredWithEightLarge}, + zeroCount}; +} + +template +template +bool Simple8bBuilder::_appendValue(T value, bool tryRle, F&& writeFn) { + auto pendingValue = _calculatePendingValue(value); + if (!pendingValue) { + return false; + } + + // Check if we have a valid selector for the current word. This method update the global + // isSelectorValid to avoid redundant computation. + if (_doesIntegerFitInCurrentWord(*pendingValue)) { + // If the integer fits in the current word, add it. + _pendingValues.push_back(*pendingValue); + _updateSimple8bCurrentState(*pendingValue); + } else { + // If the integer does not fit in the current word, convert the integers into simple8b + // word(s) with no unused buckets until the new value can be added to _pendingValues. Then + // add the Simple8b word(s) to the buffer. Finally add the new integer and update any global + // variables. We add based on the lastSelector that was valid where priority ordering is the + // following: base, seven, eightSmall, eightLarge. Store pending last value for RLE. + PendingValue lastPendingValue = _pendingValues.back(); + do { + uint64_t simple8bWord = _encodeLargestPossibleWord(_lastValidExtensionType); + writeFn(simple8bWord); + } while (!(_doesIntegerFitInCurrentWord(*pendingValue))); + + if (tryRle && _pendingValues.empty() && lastPendingValue.val == value) { + // There are no more words in _pendingValues and the last element of the last Simple8b + // word is the same as the new value. Therefore, start RLE. + _rleCount = 1; + _lastValueInPrevWord = lastPendingValue.val; + // RLE does not use selectors, make sure they are reset. + _lastValidExtensionType = 0; + isSelectorPossible.fill(true); + } else { + _pendingValues.push_back(*pendingValue); + _updateSimple8bCurrentState(*pendingValue); + } + } + return true; +} + +template +template +void Simple8bBuilder::_appendSkip(bool tryRle, F&& writeFn) { + using namespace simple8b_internal; + + if (!_pendingValues.empty()) { + bool isLastValueSkip = _pendingValues.back().isSkip(); + + // There is never a case where we need to write more than one Simple8b wrod + // because we only need 1 bit for skip + if (!_doesIntegerFitInCurrentWord({boost::none, kMinDataBits, {0, 0, 0, 0}})) { + // Form simple8b word if skip can not fit with last selector + uint64_t simple8bWord = _encodeLargestPossibleWord(_lastValidExtensionType); + writeFn(simple8bWord); + _lastValidExtensionType = kBaseSelector; + } + + if (_pendingValues.empty() && isLastValueSkip && tryRle) { + // It is possible to start rle + _rleCount = 1; + _lastValueInPrevWord = boost::none; + return; + } + } + // Push true into skip and the dummy value, 0, into currNum. We use the dummy value, 0 because + // it takes 1 bit and it will not affect our global curr bit length calculations. + _pendingValues.push_back({boost::none, {0, 0, 0, 0}, {0, 0, 0, 0}}); +} + +template +template +void Simple8bBuilder::_handleRleTermination(F&& writeFn) { + // Try to create a RLE Simple8b word. + _appendRleEncoding(writeFn); + // Add any values that could not be encoded in RLE. + while (_rleCount > 0) { + if (!_lastValueInPrevWord.has_value()) { + _appendSkip(false /* tryRle */, writeFn); + } else { + _appendValue(_lastValueInPrevWord.value(), false, writeFn); + } + --_rleCount; + } + + // Reset last for RLE and which selectors are possible to use for next word + _lastValueInPrevWord = 0; + // Ensure that selector state is reset if we have nothing in pending. This will happen when RLE + // has been setup but nothing compatible was added later. + if (_pendingValues.empty()) { + _lastValidExtensionType = 0; + isSelectorPossible.fill(true); + } +} + +template +template +void Simple8bBuilder::_appendRleEncoding(F&& writeFn) { + using namespace simple8b_internal; + + // This encodes a value using rle. The selector is set as 15 and the count is added in the next + // 4 bits. The value is the previous value stored by simple8b or 0 if no previous value was + // stored. + auto createRleEncoding = [this, &writeFn](uint8_t count) { + uint64_t rleEncoding = kRleSelector; + // We will store (count - 1) during encoding and execute (count + 1) during decoding. + rleEncoding |= (count - 1) << kSelectorBits; + _rleCount -= kRleMultiplier * count; + writeFn(rleEncoding); + }; + + uint32_t count = _rleCount / kRleMultiplier; + // Check to make sure count is big enough for RLE encoding + if (count >= 1) { + while (count > kMaxRleCount) { + // If one RLE word is insufficient use multiple RLE words. + createRleEncoding(kMaxRleCount); + count -= kMaxRleCount; + } + createRleEncoding(count); + } +} + +template +bool Simple8bBuilder::rlePossible() const { + return _pendingValues.empty() || _rleCount != 0; +} + + +template +bool Simple8bBuilder::_doesIntegerFitInCurrentWord(const PendingValue& value) { + bool fitsInCurrentWord = false; + for (uint8_t i = 0; i < kNumOfSelectorTypes; ++i) { + if (isSelectorPossible[i]) { + fitsInCurrentWord = + fitsInCurrentWord || _doesIntegerFitInCurrentWordWithGivenSelectorType(value, i); + } + // Stop loop early if we find a valid selector. + if (fitsInCurrentWord) + return fitsInCurrentWord; + } + return false; +} + +template +bool Simple8bBuilder::_doesIntegerFitInCurrentWordWithGivenSelectorType( + const PendingValue& value, uint8_t extensionType) { + using namespace simple8b_internal; + + uint64_t numBitsWithValue = + (std::max(_currMaxBitLen[extensionType], value.bitCount[extensionType]) + + kTrailingZeroBitSize[extensionType]) * + (_pendingValues.size() + 1); + // If the numBitswithValue is greater than max bits or we cannot fit the trailingZeros we update + // this selector as false and return false. Special case for baseSelector where we never add + // trailingZeros so we always pass the zeros comparison. + if (kDataBits[extensionType] < numBitsWithValue) { + isSelectorPossible[extensionType] = false; + return false; + } + // Update so we remember the last validExtensionType when its time to encode a word + _lastValidExtensionType = extensionType; + return true; +} + +template +int64_t Simple8bBuilder::_encodeLargestPossibleWord(uint8_t extensionType) { + using namespace simple8b_internal; + + // Since this is always called right after _doesIntegerFitInCurrentWord fails for the first + // time, we know all values in _pendingValues fits in the slots for the selector that can store + // this many values. Find the smallest selector that doesn't leave any unused slots. + uint8_t selector = getSelectorIndex(_pendingValues.size(), extensionType); + uint8_t integersCoded = kIntsStoreForSelector[extensionType][selector]; + uint64_t encodedWord; + switch (extensionType) { + case kEightSelectorSmall: + encodedWord = _encode(EightSelectorSmallEncodeFunctor(), selector, extensionType); + break; + case kEightSelectorLarge: + encodedWord = _encode(EightSelectorLargeEncodeFunctor(), selector, extensionType); + break; + case kSevenSelector: + encodedWord = _encode(SevenSelectorEncodeFunctor(), selector, extensionType); + break; + default: + encodedWord = _encode(BaseSelectorEncodeFunctor(), selector, extensionType); + } + + // While we erase from the front of a vector the number of remaining elements is normally small. + // Vector is a less complex data structure than a deque and normally has better performance when + // the number of elements in it is low. + _pendingValues.erase(_pendingValues.begin(), _pendingValues.begin() + integersCoded); + _currMaxBitLen = kMinDataBits; + for (const auto& val : _pendingValues) { + _updateSimple8bCurrentState(val); + } + // Reset which selectors are possible to use for next word + isSelectorPossible.fill(true); + return encodedWord; +} + +template +template +uint64_t Simple8bBuilder::_encode(Func func, + uint8_t selectorIdx, + uint8_t extensionType) { + using namespace simple8b_internal; + + uint8_t baseSelector = kExtensionToBaseSelector[extensionType][selectorIdx]; + uint8_t bitShiftExtension = kBaseSelectorToShiftSize[baseSelector]; + uint64_t encodedWord = baseSelector; + uint8_t bitsPerInteger = kBitsPerIntForSelector[extensionType][selectorIdx]; + uint8_t integersCoded = kIntsStoreForSelector[extensionType][selectorIdx]; + uint64_t unshiftedMask = kDecodeMask[extensionType][selectorIdx]; + uint8_t bitsForTrailingZeros = kTrailingZeroBitSize[extensionType]; + for (uint8_t i = 0; i < integersCoded; ++i) { + uint8_t shiftSize = + (bitsPerInteger + bitsForTrailingZeros) * i + kSelectorBits + bitShiftExtension; + uint64_t currEncodedWord; + if (_pendingValues[i].isSkip()) { + currEncodedWord = unshiftedMask; + } else { + currEncodedWord = func(_pendingValues[i]); + } + encodedWord |= currEncodedWord << shiftSize; + } + if (extensionType != kBaseSelector) { + encodedWord |= (uint64_t(selectorIdx) << kSelectorBits); + } + return encodedWord; +} + +template +void Simple8bBuilder::_updateSimple8bCurrentState(const PendingValue& val) { + using namespace simple8b_internal; + + for (uint8_t i = 0; i < kNumOfSelectorTypes; ++i) { + _currMaxBitLen[i] = std::max(_currMaxBitLen[i], val.bitCount[i]); + } +} + +template +typename Simple8bBuilder::PendingIterator Simple8bBuilder::begin() + const { + return {_pendingValues.begin(), _pendingValues.begin(), _lastValueInPrevWord, _rleCount}; +} + +template +typename Simple8bBuilder::PendingIterator Simple8bBuilder::end() const { + return {_pendingValues.begin(), _pendingValues.end(), _lastValueInPrevWord, 0}; +} + +template +std::reverse_iterator::PendingIterator> +Simple8bBuilder::rbegin() const { + return std::reverse_iterator::PendingIterator>(end()); +} + +template +std::reverse_iterator::PendingIterator> +Simple8bBuilder::rend() const { + return std::reverse_iterator::PendingIterator>(begin()); +} + +template +bool Simple8bBuilder::isInternalStateIdentical( + const Simple8bBuilder& other) const { + // Verifies the pending values + if (!std::equal(begin(), end(), other.begin(), other.end())) { + return false; + } + if (_rleCount != other._rleCount) { + return false; + } + if (_lastValueInPrevWord != other._lastValueInPrevWord) { + return false; + } + if (_currMaxBitLen != other._currMaxBitLen) { + return false; + } + if (_currTrailingZerosCount != other._currTrailingZerosCount) { + return false; + } + if (_lastValidExtensionType != other._lastValidExtensionType) { + return false; + } + if (isSelectorPossible != other.isSelectorPossible) { + return false; + } + return true; +} +} // namespace mongo diff --git a/src/mongo/bson/column/simple8b_builder.inl b/src/mongo/bson/column/simple8b_builder.inl deleted file mode 100644 index aee9fdc3699..00000000000 --- a/src/mongo/bson/column/simple8b_builder.inl +++ /dev/null @@ -1,665 +0,0 @@ -/** - * 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 - * . - * - * 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/bson/column/simple8b_builder.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "mongo/bson/column/simple8b_helpers.h" - -namespace mongo { -// This is called in _encode while iterating through _pendingValues. For the base selector, we just -// return val. Contains unsed vars in order to seamlessly integrate with seven and eight selector -// extensions. -template -struct Simple8bBuilder::BaseSelectorEncodeFunctor { - uint64_t operator()(const PendingValue& value) { - return static_cast(value.value()); - }; -}; - -// This is called in _encode while iterating through _pendingValues. It creates part of a simple8b -// word according to the specifications of the sevenSelector extension. This value is then appended -// to the full simple8b word in _encode. -template -struct Simple8bBuilder::SevenSelectorEncodeFunctor { - uint64_t operator()(const PendingValue& value) { - using namespace simple8b_internal; - - uint8_t trailingZeros = value.trailingZerosCount[kSevenSelector]; - uint64_t currWord = trailingZeros; - // We do two shifts here to account for the case where trailingZeros is > kTrailingZero bit - // size. If we subtracted this could lead to shift by a negative value which is undefined. - currWord |= static_cast((value.value() >> trailingZeros) - << kTrailingZeroBitSize[kSevenSelector]); - return currWord; - }; -}; - -// This is a helper functor that is extended by the EightSelectorSmall and EightSelectorLarge encode -// functors. It provides the logic for encoding with the eight selector where the extension type is -// designated by the inheritance in the EightSelectorSmall and EightSelectorLarge functors. -template -template -struct Simple8bBuilder::EightSelectorEncodeFunctor { - uint64_t operator()(const PendingValue& value) { - using namespace simple8b_internal; - - // integer division. We have a nibble shift of size 4 - uint8_t trailingZeros = value.trailingZerosCount[ExtensionType] / kNibbleShiftSize; - uint64_t currWord = trailingZeros; - // Shift to remove trailing zeros * 4 and then shift over for the 4 bits to hold - // the trailingZerosCount - currWord |= static_cast((value.value() >> (trailingZeros * kNibbleShiftSize)) - << kTrailingZeroBitSize[ExtensionType]); - return currWord; - } -}; - -// This is called in _encode while iterating through _pendingValues. It creates part of a simple8b -// word according to the specifications of the eightSelectorSmall extension. This value is then -// appended to the full simple8b word in _encode. -template -struct Simple8bBuilder::EightSelectorSmallEncodeFunctor - : public EightSelectorEncodeFunctor {}; - -// This is called in _encode while iterating through _pendingValues. It creates part of a simple8b -// word according to the specifications of the eightSelectorLarge extension. This value is then -// appended to the full simple8b word in _encode. -template -struct Simple8bBuilder::EightSelectorLargeEncodeFunctor - : public EightSelectorEncodeFunctor {}; - -// Base Constructor for PendingValue -template -Simple8bBuilder::PendingValue::PendingValue( - boost::optional val, - std::array bitCount, - std::array trailingZerosCount) - : val(val), bitCount(bitCount), trailingZerosCount(trailingZerosCount){}; - -template -Simple8bBuilder::PendingIterator::PendingIterator( - typename std::vector::const_iterator beginning, - typename std::vector::const_iterator it, - reference rleValue, - uint32_t rleCount) - : _begin(beginning), _it(it), _rleValue(rleValue), _rleCount(rleCount) {} - -template -auto Simple8bBuilder::PendingIterator::operator->() const -> pointer { - return &operator*(); -} - -template -auto Simple8bBuilder::PendingIterator::operator*() const -> reference { - if (_rleCount > 0) - return _rleValue; - - return _it->val; -} - -template -auto Simple8bBuilder::PendingIterator::operator++() -> PendingIterator& { - if (_rleCount > 0) { - --_rleCount; - return *this; - } - - ++_it; - return *this; -} - -template -auto Simple8bBuilder::PendingIterator::operator++(int) -> PendingIterator { - auto ret = *this; - ++(*this); - return ret; -} - -template -auto Simple8bBuilder::PendingIterator::operator--() -> PendingIterator& { - if (_rleCount > 0 || _it == _begin) { - ++_rleCount; - return *this; - } - - --_it; - return *this; -} - -template -auto Simple8bBuilder::PendingIterator::operator--(int) -> PendingIterator { - auto ret = *this; - --(*this); - return ret; -} - -template -bool Simple8bBuilder::PendingIterator::operator==( - const Simple8bBuilder::PendingIterator& rhs) const { - return _it == rhs._it && _rleCount == rhs._rleCount; -} - -template -bool Simple8bBuilder::PendingIterator::operator!=( - const Simple8bBuilder::PendingIterator& rhs) const { - return !operator==(rhs); -} - -template -Simple8bBuilder::Simple8bBuilder(Allocator allocator) : _pendingValues(allocator) {} - -template -Simple8bBuilder::~Simple8bBuilder() = default; - -template -template -requires Simple8bBlockWriter -void Simple8bBuilder::prefillWithSkips(size_t numSkips, F &&writeFn) { - constexpr size_t kMaxSkipsInBlock = 60; - constexpr uint64_t kAllSkipsBlock = 0xFFFFFFFFFFFFFFF1; // A simple8b block that contains 60 skips - - // Do checks once, and then process all skips in bulk - uassert(8575002, "prefillWithSkips() called after other appends", _rleCount == 0 && _pendingValues.empty() && _lastValidExtensionType == 0); - - if (numSkips > kMaxSkipsInBlock) { - // Handle case with initialized _rleCount (this should be the common case) - writeFn(kAllSkipsBlock); - _rleCount = numSkips - kMaxSkipsInBlock; - _lastValueInPrevWord = boost::none; - } else { - // Insufficient skips to start an _rleCount, just default to appending them - // individually (we can skip rle checks) - for (size_t i = 0; i < numSkips; ++i) - _appendSkip(true, writeFn); - } -} - -template -template -requires Simple8bBlockWriter -bool Simple8bBuilder::append(T value, F&& writeFn) { - if (rlePossible()) { - if (_lastValueInPrevWord == value) { - ++_rleCount; - // RLE does not use selectors, make sure they are reset. - _lastValidExtensionType = 0; - isSelectorPossible.fill(true); - return true; - } - _handleRleTermination(writeFn); - } - - return _appendValue(value, true, writeFn); -} - -template -template -requires Simple8bBlockWriter -void Simple8bBuilder::skip(F&& writeFn) { - if (rlePossible()) { - if (!_lastValueInPrevWord.has_value()) { - ++_rleCount; - // RLE does not use selectors, make sure they are reset. - _lastValidExtensionType = 0; - isSelectorPossible.fill(true); - return; - } - _handleRleTermination(writeFn); - } - _appendSkip(true /* tryRle */, writeFn); -} - -template -template -requires Simple8bBlockWriter -void Simple8bBuilder::flush(F&& writeFn) { - // Flush repeating integers that have been kept for RLE. - _handleRleTermination(writeFn); - // Flush buffered values in _pendingValues. - if (!_pendingValues.empty()) { - // always flush with the most recent valid selector. This value is the baseSelector if we - // have not have a valid selector yet. - do { - uint64_t simple8bWord = _encodeLargestPossibleWord(_lastValidExtensionType); - writeFn(simple8bWord); - } while (!_pendingValues.empty()); - - // There are no more words in _pendingValues and RLE is possible. - // However the _rleCount is 0 because we have not read any of the values in the next word. - _rleCount = 0; - } -} - -template -void Simple8bBuilder::setLastForRLE(boost::optional val) { - _lastValueInPrevWord = val; - if (val) { - auto pendingValue = _calculatePendingValue(*val); - invariant(pendingValue); - invariant(_doesIntegerFitInCurrentWord(*pendingValue)); - } -} - -template -void Simple8bBuilder::resetLastForRLEIfNeeded() { - if (!rlePossible()) { - _lastValueInPrevWord = 0; - } -} - -template -void Simple8bBuilder::initializeRLEFrom(const Simple8bBuilder& other) { - if (other.rlePossible()) { - _lastValueInPrevWord = other._lastValueInPrevWord; - } -} - -template -boost::optional::PendingValue> -Simple8bBuilder::_calculatePendingValue(T value) { - using namespace simple8b_internal; - - // Early exit if we try to store max value. They are not handled when counting zeros. - if (value == std::numeric_limits::max()) - return boost::none; - - uint8_t trailingZerosCount = countTrailingZerosWithZero(value); - // Initially set every selector as invalid. - uint8_t bitCountWithoutLeadingZeros = countBitsWithoutLeadingZeros(value); - uint8_t trailingZerosStoredInCountSeven = - (std::min(trailingZerosCount, kTrailingZerosMaxCount[kSevenSelector])); - uint8_t meaningfulValueBitsStoredWithSeven = - bitCountWithoutLeadingZeros - trailingZerosStoredInCountSeven; - // We use integer division to ensure that a multiple of 4 is stored in - // trailingZerosStoredInCount when we have the nibble shift. - uint8_t trailingZerosStoredInCountEightSmall = - (std::min(trailingZerosCount, kTrailingZerosMaxCount[kEightSelectorSmall]) / - kNibbleShiftSize) * - kNibbleShiftSize; - uint8_t meaningfulValueBitsStoredWithEightSmall = - bitCountWithoutLeadingZeros - trailingZerosStoredInCountEightSmall; - // We use integer division to ensure that a multiple of 4 is stored in - // trailingZerosStoredInCount when we have the nibble shift. - uint8_t trailingZerosStoredInCountEightLarge = - (std::min(trailingZerosCount, kTrailingZerosMaxCount[kEightSelectorLarge]) / - kNibbleShiftSize) * - kNibbleShiftSize; - uint8_t meaningfulValueBitsStoredWithEightLarge = - bitCountWithoutLeadingZeros - trailingZerosStoredInCountEightLarge; - - // Edge cases where we have the number of trailing zeros bits as all ones and we need to add a - // padded zero to the meaningful bits to avoid confilicts with skip storage. Otherwise, we can - // reuse the bitCountWithoutLeadingZeros already calculated above. - if (trailingZerosCount == kTrailingZerosMaxCount[kSevenSelector]) { - meaningfulValueBitsStoredWithSeven = - countBitsWithoutLeadingZeros(value >> trailingZerosCount); - } else if (trailingZerosCount == kTrailingZerosMaxCount[kEightSelectorSmall]) { - meaningfulValueBitsStoredWithEightSmall = - countBitsWithoutLeadingZeros(value >> trailingZerosCount); - } - - // This case is specifically for 128 bit types where we have 124 zeros or max zeros - // count. We do not need to even check this for 64 bit types - if constexpr (std::is_same::value) { - if (trailingZerosCount == kTrailingZerosMaxCount[kEightSelectorLarge]) { - meaningfulValueBitsStoredWithEightLarge = - countBitsWithoutLeadingZeros(value >> trailingZerosCount); - } - } - - std::array zeroCount = {0, - trailingZerosStoredInCountSeven, - trailingZerosStoredInCountEightSmall, - trailingZerosStoredInCountEightLarge}; - - // Check if the amount of bits needed is more than we can store using all selector combinations. - if ((bitCountWithoutLeadingZeros > kDataBits[kBaseSelector]) && - (meaningfulValueBitsStoredWithSeven + kTrailingZeroBitSize[kSevenSelector] > - kDataBits[kSevenSelector]) && - (meaningfulValueBitsStoredWithEightSmall + kTrailingZeroBitSize[kEightSelectorSmall] > - kDataBits[kEightSelectorSmall]) && - (meaningfulValueBitsStoredWithEightLarge + kTrailingZeroBitSize[kEightSelectorLarge] > - kDataBits[kEightSelectorLarge])) { - return boost::none; - } - - return PendingValue{value, - {bitCountWithoutLeadingZeros, - meaningfulValueBitsStoredWithSeven, - meaningfulValueBitsStoredWithEightSmall, - meaningfulValueBitsStoredWithEightLarge}, - zeroCount}; -} - -template -template -bool Simple8bBuilder::_appendValue(T value, bool tryRle, F&& writeFn) { - auto pendingValue = _calculatePendingValue(value); - if (!pendingValue) { - return false; - } - - // Check if we have a valid selector for the current word. This method update the global - // isSelectorValid to avoid redundant computation. - if (_doesIntegerFitInCurrentWord(*pendingValue)) { - // If the integer fits in the current word, add it. - _pendingValues.push_back(*pendingValue); - _updateSimple8bCurrentState(*pendingValue); - } else { - // If the integer does not fit in the current word, convert the integers into simple8b - // word(s) with no unused buckets until the new value can be added to _pendingValues. Then - // add the Simple8b word(s) to the buffer. Finally add the new integer and update any global - // variables. We add based on the lastSelector that was valid where priority ordering is the - // following: base, seven, eightSmall, eightLarge. Store pending last value for RLE. - PendingValue lastPendingValue = _pendingValues.back(); - do { - uint64_t simple8bWord = _encodeLargestPossibleWord(_lastValidExtensionType); - writeFn(simple8bWord); - } while (!(_doesIntegerFitInCurrentWord(*pendingValue))); - - if (tryRle && _pendingValues.empty() && lastPendingValue.val == value) { - // There are no more words in _pendingValues and the last element of the last Simple8b - // word is the same as the new value. Therefore, start RLE. - _rleCount = 1; - _lastValueInPrevWord = lastPendingValue.val; - // RLE does not use selectors, make sure they are reset. - _lastValidExtensionType = 0; - isSelectorPossible.fill(true); - } else { - _pendingValues.push_back(*pendingValue); - _updateSimple8bCurrentState(*pendingValue); - } - } - return true; -} - -template -template -void Simple8bBuilder::_appendSkip(bool tryRle, F&& writeFn) { - using namespace simple8b_internal; - - if (!_pendingValues.empty()) { - bool isLastValueSkip = _pendingValues.back().isSkip(); - - // There is never a case where we need to write more than one Simple8b wrod - // because we only need 1 bit for skip - if (!_doesIntegerFitInCurrentWord({boost::none, kMinDataBits, {0, 0, 0, 0}})) { - // Form simple8b word if skip can not fit with last selector - uint64_t simple8bWord = _encodeLargestPossibleWord(_lastValidExtensionType); - writeFn(simple8bWord); - _lastValidExtensionType = kBaseSelector; - } - - if (_pendingValues.empty() && isLastValueSkip && tryRle) { - // It is possible to start rle - _rleCount = 1; - _lastValueInPrevWord = boost::none; - return; - } - } - // Push true into skip and the dummy value, 0, into currNum. We use the dummy value, 0 because - // it takes 1 bit and it will not affect our global curr bit length calculations. - _pendingValues.push_back({boost::none, {0, 0, 0, 0}, {0, 0, 0, 0}}); -} - -template -template -void Simple8bBuilder::_handleRleTermination(F&& writeFn) { - // Try to create a RLE Simple8b word. - _appendRleEncoding(writeFn); - // Add any values that could not be encoded in RLE. - while (_rleCount > 0) { - if (!_lastValueInPrevWord.has_value()) { - _appendSkip(false /* tryRle */, writeFn); - } else { - _appendValue(_lastValueInPrevWord.value(), false, writeFn); - } - --_rleCount; - } - - // Reset last for RLE and which selectors are possible to use for next word - _lastValueInPrevWord = 0; - // Ensure that selector state is reset if we have nothing in pending. This will happen when RLE - // has been setup but nothing compatible was added later. - if (_pendingValues.empty()) { - _lastValidExtensionType = 0; - isSelectorPossible.fill(true); - } -} - -template -template -void Simple8bBuilder::_appendRleEncoding(F&& writeFn) { - using namespace simple8b_internal; - - // This encodes a value using rle. The selector is set as 15 and the count is added in the next - // 4 bits. The value is the previous value stored by simple8b or 0 if no previous value was - // stored. - auto createRleEncoding = [this, &writeFn](uint8_t count) { - uint64_t rleEncoding = kRleSelector; - // We will store (count - 1) during encoding and execute (count + 1) during decoding. - rleEncoding |= (count - 1) << kSelectorBits; - _rleCount -= kRleMultiplier * count; - writeFn(rleEncoding); - }; - - uint32_t count = _rleCount / kRleMultiplier; - // Check to make sure count is big enough for RLE encoding - if (count >= 1) { - while (count > kMaxRleCount) { - // If one RLE word is insufficient use multiple RLE words. - createRleEncoding(kMaxRleCount); - count -= kMaxRleCount; - } - createRleEncoding(count); - } -} - -template -bool Simple8bBuilder::rlePossible() const { - return _pendingValues.empty() || _rleCount != 0; -} - - -template -bool Simple8bBuilder::_doesIntegerFitInCurrentWord(const PendingValue& value) { - bool fitsInCurrentWord = false; - for (uint8_t i = 0; i < kNumOfSelectorTypes; ++i) { - if (isSelectorPossible[i]) { - fitsInCurrentWord = - fitsInCurrentWord || _doesIntegerFitInCurrentWordWithGivenSelectorType(value, i); - } - // Stop loop early if we find a valid selector. - if (fitsInCurrentWord) - return fitsInCurrentWord; - } - return false; -} - -template -bool Simple8bBuilder::_doesIntegerFitInCurrentWordWithGivenSelectorType( - const PendingValue& value, uint8_t extensionType) { - using namespace simple8b_internal; - - uint64_t numBitsWithValue = - (std::max(_currMaxBitLen[extensionType], value.bitCount[extensionType]) + - kTrailingZeroBitSize[extensionType]) * - (_pendingValues.size() + 1); - // If the numBitswithValue is greater than max bits or we cannot fit the trailingZeros we update - // this selector as false and return false. Special case for baseSelector where we never add - // trailingZeros so we always pass the zeros comparison. - if (kDataBits[extensionType] < numBitsWithValue) { - isSelectorPossible[extensionType] = false; - return false; - } - // Update so we remember the last validExtensionType when its time to encode a word - _lastValidExtensionType = extensionType; - return true; -} - -template -int64_t Simple8bBuilder::_encodeLargestPossibleWord(uint8_t extensionType) { - using namespace simple8b_internal; - - // Since this is always called right after _doesIntegerFitInCurrentWord fails for the first - // time, we know all values in _pendingValues fits in the slots for the selector that can store - // this many values. Find the smallest selector that doesn't leave any unused slots. - uint8_t selector = getSelectorIndex(_pendingValues.size(), extensionType); - uint8_t integersCoded = kIntsStoreForSelector[extensionType][selector]; - uint64_t encodedWord; - switch (extensionType) { - case kEightSelectorSmall: - encodedWord = _encode(EightSelectorSmallEncodeFunctor(), selector, extensionType); - break; - case kEightSelectorLarge: - encodedWord = _encode(EightSelectorLargeEncodeFunctor(), selector, extensionType); - break; - case kSevenSelector: - encodedWord = _encode(SevenSelectorEncodeFunctor(), selector, extensionType); - break; - default: - encodedWord = _encode(BaseSelectorEncodeFunctor(), selector, extensionType); - } - - // While we erase from the front of a vector the number of remaining elements is normally small. - // Vector is a less complex data structure than a deque and normally has better performance when - // the number of elements in it is low. - _pendingValues.erase(_pendingValues.begin(), _pendingValues.begin() + integersCoded); - _currMaxBitLen = kMinDataBits; - for (const auto& val : _pendingValues) { - _updateSimple8bCurrentState(val); - } - // Reset which selectors are possible to use for next word - isSelectorPossible.fill(true); - return encodedWord; -} - -template -template -uint64_t Simple8bBuilder::_encode(Func func, - uint8_t selectorIdx, - uint8_t extensionType) { - using namespace simple8b_internal; - - uint8_t baseSelector = kExtensionToBaseSelector[extensionType][selectorIdx]; - uint8_t bitShiftExtension = kBaseSelectorToShiftSize[baseSelector]; - uint64_t encodedWord = baseSelector; - uint8_t bitsPerInteger = kBitsPerIntForSelector[extensionType][selectorIdx]; - uint8_t integersCoded = kIntsStoreForSelector[extensionType][selectorIdx]; - uint64_t unshiftedMask = kDecodeMask[extensionType][selectorIdx]; - uint8_t bitsForTrailingZeros = kTrailingZeroBitSize[extensionType]; - for (uint8_t i = 0; i < integersCoded; ++i) { - uint8_t shiftSize = - (bitsPerInteger + bitsForTrailingZeros) * i + kSelectorBits + bitShiftExtension; - uint64_t currEncodedWord; - if (_pendingValues[i].isSkip()) { - currEncodedWord = unshiftedMask; - } else { - currEncodedWord = func(_pendingValues[i]); - } - encodedWord |= currEncodedWord << shiftSize; - } - if (extensionType != kBaseSelector) { - encodedWord |= (uint64_t(selectorIdx) << kSelectorBits); - } - return encodedWord; -} - -template -void Simple8bBuilder::_updateSimple8bCurrentState(const PendingValue& val) { - using namespace simple8b_internal; - - for (uint8_t i = 0; i < kNumOfSelectorTypes; ++i) { - _currMaxBitLen[i] = std::max(_currMaxBitLen[i], val.bitCount[i]); - } -} - -template -typename Simple8bBuilder::PendingIterator Simple8bBuilder::begin() - const { - return {_pendingValues.begin(), _pendingValues.begin(), _lastValueInPrevWord, _rleCount}; -} - -template -typename Simple8bBuilder::PendingIterator Simple8bBuilder::end() const { - return {_pendingValues.begin(), _pendingValues.end(), _lastValueInPrevWord, 0}; -} - -template -std::reverse_iterator::PendingIterator> -Simple8bBuilder::rbegin() const { - return std::reverse_iterator::PendingIterator>(end()); -} - -template -std::reverse_iterator::PendingIterator> -Simple8bBuilder::rend() const { - return std::reverse_iterator::PendingIterator>(begin()); -} - -template -bool Simple8bBuilder::isInternalStateIdentical( - const Simple8bBuilder& other) const { - // Verifies the pending values - if (!std::equal(begin(), end(), other.begin(), other.end())) { - return false; - } - if (_rleCount != other._rleCount) { - return false; - } - if (_lastValueInPrevWord != other._lastValueInPrevWord) { - return false; - } - if (_currMaxBitLen != other._currMaxBitLen) { - return false; - } - if (_currTrailingZerosCount != other._currTrailingZerosCount) { - return false; - } - if (_lastValidExtensionType != other._lastValidExtensionType) { - return false; - } - if (isSelectorPossible != other.isSelectorPossible) { - return false; - } - return true; -} - -} // namespace mongo diff --git a/src/mongo/client/sdam/sdam.h b/src/mongo/client/sdam/sdam.h index 16645e2418a..a49d12f2019 100644 --- a/src/mongo/client/sdam/sdam.h +++ b/src/mongo/client/sdam/sdam.h @@ -28,7 +28,6 @@ */ #pragma once -#include "mongo/client/sdam/sdam.h" #include "mongo/client/sdam/sdam_datatypes.h" #include "mongo/client/sdam/server_description.h" #include "mongo/client/sdam/server_selector.h" diff --git a/src/mongo/db/catalog/index_catalog_entry_impl.h b/src/mongo/db/catalog/index_catalog_entry_impl.h index e5aa3f6d769..8648da233bd 100644 --- a/src/mongo/db/catalog/index_catalog_entry_impl.h +++ b/src/mongo/db/catalog/index_catalog_entry_impl.h @@ -42,6 +42,7 @@ #include "mongo/db/index/index_descriptor.h" #include "mongo/db/index/multikey_paths.h" #include "mongo/db/namespace_string.h" +#include "mongo/db/pipeline/expression_context.h" #include "mongo/db/query/collation/collator_interface.h" #include "mongo/db/record_id.h" #include "mongo/db/storage/ident.h" diff --git a/src/mongo/db/commands/query_cmd/external_data_source_commands_test.cpp b/src/mongo/db/commands/query_cmd/external_data_source_commands_test.cpp index e743dd436d6..4288812b207 100644 --- a/src/mongo/db/commands/query_cmd/external_data_source_commands_test.cpp +++ b/src/mongo/db/commands/query_cmd/external_data_source_commands_test.cpp @@ -51,6 +51,7 @@ #include "mongo/db/database_name.h" #include "mongo/db/dbdirectclient.h" #include "mongo/db/operation_context.h" +#include "mongo/db/pipeline/aggregate_command_gen.h" #include "mongo/db/pipeline/aggregation_request_helper.h" #include "mongo/db/query/query_knobs_gen.h" #include "mongo/db/repl/member_state.h" diff --git a/src/mongo/db/exec/multi_plan_bucket.h b/src/mongo/db/exec/multi_plan_bucket.h index c86267246e0..d39847b49ad 100644 --- a/src/mongo/db/exec/multi_plan_bucket.h +++ b/src/mongo/db/exec/multi_plan_bucket.h @@ -44,23 +44,7 @@ namespace mongo { -class MultiPlanBucket; - -/** - * This class defines tokens that each thread must obtain to attempt multiplanning, provided that - * the MultiPlan rate limiting is enabled. If not enough tokens are available, the thread must wait - * until either the plan is cached or tokens become available. - */ -class MultiPlanTokens { -public: - MultiPlanTokens(size_t tokensCount, boost::intrusive_ptr bucket) - : _tokensCount(tokensCount), _bucket(bucket) {} - ~MultiPlanTokens(); - -private: - size_t _tokensCount; - boost::intrusive_ptr _bucket; -}; +class MultiPlanTokens; /** * This class defines a bucket in the Multi Plan rate limiting algorithm. It controls number of @@ -109,4 +93,20 @@ private: stdx::mutex _mutex; stdx::condition_variable_any _cv; }; + +/** + * This class defines tokens that each thread must obtain to attempt multiplanning, provided that + * the MultiPlan rate limiting is enabled. If not enough tokens are available, the thread must wait + * until either the plan is cached or tokens become available. + */ +class MultiPlanTokens { +public: + MultiPlanTokens(size_t tokensCount, boost::intrusive_ptr bucket) + : _tokensCount(tokensCount), _bucket(std::move(bucket)) {} + ~MultiPlanTokens(); + +private: + size_t _tokensCount; + boost::intrusive_ptr _bucket; +}; } // namespace mongo diff --git a/src/mongo/db/exec/sbe/expressions/sbe_block_expr_test.cpp b/src/mongo/db/exec/sbe/expressions/sbe_block_expr_test.cpp index cf4e8156ab8..ff551ed744e 100644 --- a/src/mongo/db/exec/sbe/expressions/sbe_block_expr_test.cpp +++ b/src/mongo/db/exec/sbe/expressions/sbe_block_expr_test.cpp @@ -37,6 +37,7 @@ #include "mongo/db/exec/sbe/sbe_block_test_helpers.h" #include "mongo/db/exec/sbe/sbe_unittest.h" #include "mongo/db/exec/sbe/values/block_interface.h" +#include "mongo/db/exec/sbe/values/cell_interface.h" #include "mongo/db/exec/sbe/values/slot.h" #include "mongo/db/exec/sbe/values/value.h" #include "mongo/db/query/collation/collator_interface_mock.h" diff --git a/src/mongo/db/exec/sbe/stages/stages.h b/src/mongo/db/exec/sbe/stages/stages.h index a1c792b229b..e50ca92444b 100644 --- a/src/mongo/db/exec/sbe/stages/stages.h +++ b/src/mongo/db/exec/sbe/stages/stages.h @@ -34,6 +34,7 @@ #include "mongo/db/exec/sbe/util/debug_print.h" #include "mongo/db/exec/sbe/values/slot.h" #include "mongo/db/exec/sbe/values/value.h" +#include "mongo/db/exec/sbe/vm/code_fragment.h" #include "mongo/db/exec/scoped_timer.h" #include "mongo/db/exec/trial_run_tracker.h" #include "mongo/db/operation_context.h" diff --git a/src/mongo/db/exec/sbe/values/block_interface.h b/src/mongo/db/exec/sbe/values/block_interface.h index e81d4a8bb07..863e6e0ee21 100644 --- a/src/mongo/db/exec/sbe/values/block_interface.h +++ b/src/mongo/db/exec/sbe/values/block_interface.h @@ -35,7 +35,6 @@ #include #include "mongo/base/compare_numbers.h" -#include "mongo/db/exec/sbe/values/cell_interface.h" #include "mongo/db/exec/sbe/values/column_op.h" #include "mongo/db/exec/sbe/values/value.h" #include "mongo/util/assert_util.h" diff --git a/src/mongo/db/exec/sbe/values/cell_interface.h b/src/mongo/db/exec/sbe/values/cell_interface.h index d3a832fd11a..9e936fb1811 100644 --- a/src/mongo/db/exec/sbe/values/cell_interface.h +++ b/src/mongo/db/exec/sbe/values/cell_interface.h @@ -32,7 +32,6 @@ #include #include "mongo/db/exec/sbe/values/block_interface.h" -#include "mongo/db/exec/sbe/values/value.h" namespace mongo::sbe::value { /** diff --git a/src/mongo/db/exec/sbe/values/value_printer.cpp b/src/mongo/db/exec/sbe/values/value_printer.cpp index 8713577fe96..f706e6dfa78 100644 --- a/src/mongo/db/exec/sbe/values/value_printer.cpp +++ b/src/mongo/db/exec/sbe/values/value_printer.cpp @@ -42,6 +42,7 @@ #include "mongo/db/exec/sbe/makeobj_spec.h" #include "mongo/db/exec/sbe/sort_spec.h" #include "mongo/db/exec/sbe/values/block_interface.h" +#include "mongo/db/exec/sbe/values/cell_interface.h" #include "mongo/db/exec/sbe/values/value.h" #include "mongo/db/exec/sbe/values/value_printer.h" #include "mongo/db/fts/fts_matcher.h" diff --git a/src/mongo/db/exec/sbe/vm/code_fragment.h b/src/mongo/db/exec/sbe/vm/code_fragment.h index 825b026900f..1524c6b3fa7 100644 --- a/src/mongo/db/exec/sbe/vm/code_fragment.h +++ b/src/mongo/db/exec/sbe/vm/code_fragment.h @@ -32,7 +32,6 @@ #include #include "mongo/db/exec/sbe/values/slot.h" -#include "mongo/db/exec/sbe/vm/vm.h" #include "mongo/db/exec/sbe/vm/vm_builtin.h" #include "mongo/db/exec/sbe/vm/vm_instruction.h" #include "mongo/db/exec/sbe/vm/vm_types.h" diff --git a/src/mongo/db/exec/sbe/vm/vm_block.cpp b/src/mongo/db/exec/sbe/vm/vm_block.cpp index 00f9f998798..d1a6e4d2b95 100644 --- a/src/mongo/db/exec/sbe/vm/vm_block.cpp +++ b/src/mongo/db/exec/sbe/vm/vm_block.cpp @@ -36,6 +36,7 @@ #include "mongo/db/exec/sbe/in_list.h" #include "mongo/db/exec/sbe/values/arith_common.h" #include "mongo/db/exec/sbe/values/block_interface.h" +#include "mongo/db/exec/sbe/values/cell_interface.h" #include "mongo/db/exec/sbe/values/generic_compare.h" #include "mongo/db/exec/sbe/values/util.h" #include "mongo/db/exec/sbe/values/value.h" diff --git a/src/mongo/db/exec/sbe/vm/vm_instruction.cpp b/src/mongo/db/exec/sbe/vm/vm_instruction.cpp index 6e003ff6078..59abea5343d 100644 --- a/src/mongo/db/exec/sbe/vm/vm_instruction.cpp +++ b/src/mongo/db/exec/sbe/vm/vm_instruction.cpp @@ -33,6 +33,7 @@ #include "mongo/db/exec/sbe/values/arith_common.h" #include "mongo/db/exec/sbe/values/bson.h" #include "mongo/db/exec/sbe/vm/code_fragment.h" +#include "mongo/db/exec/sbe/vm/vm.h" #include "mongo/db/query/collation/collation_index_key.h" #define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kQuery diff --git a/src/mongo/db/pipeline/aggregation_request_helper.h b/src/mongo/db/pipeline/aggregation_request_helper.h index 2dd5189655b..05d27945b4e 100644 --- a/src/mongo/db/pipeline/aggregation_request_helper.h +++ b/src/mongo/db/pipeline/aggregation_request_helper.h @@ -47,7 +47,6 @@ #include "mongo/db/exec/document_value/document.h" #include "mongo/db/namespace_string.h" #include "mongo/db/operation_context.h" -#include "mongo/db/pipeline/aggregate_command_gen.h" #include "mongo/db/pipeline/exchange_spec_gen.h" #include "mongo/db/pipeline/legacy_runtime_constants_gen.h" #include "mongo/db/pipeline/plan_executor_pipeline.h" diff --git a/src/mongo/db/pipeline/document_source_group_base.h b/src/mongo/db/pipeline/document_source_group_base.h index df780bada78..a23c0f001a1 100644 --- a/src/mongo/db/pipeline/document_source_group_base.h +++ b/src/mongo/db/pipeline/document_source_group_base.h @@ -59,6 +59,7 @@ #include "mongo/db/pipeline/stage_constraints.h" #include "mongo/db/pipeline/variables.h" #include "mongo/db/query/query_shape/serialization_options.h" +#include "mongo/db/query/sort_pattern.h" #include "mongo/util/string_map.h" namespace mongo { diff --git a/src/mongo/db/pipeline/document_source_hybrid_scoring_input_util.h b/src/mongo/db/pipeline/document_source_hybrid_scoring_input_util.h index fb29f417d75..bf610f6b17a 100644 --- a/src/mongo/db/pipeline/document_source_hybrid_scoring_input_util.h +++ b/src/mongo/db/pipeline/document_source_hybrid_scoring_input_util.h @@ -30,8 +30,6 @@ #pragma once #include "mongo/base/status.h" -#include "mongo/db/pipeline/document_source_rank_fusion_inputs_gen.h" -#include "mongo/db/pipeline/document_source_score_fusion_inputs_gen.h" namespace mongo { diff --git a/src/mongo/db/pipeline/expression.h b/src/mongo/db/pipeline/expression.h index ceab78ef287..161ce206889 100644 --- a/src/mongo/db/pipeline/expression.h +++ b/src/mongo/db/pipeline/expression.h @@ -72,7 +72,6 @@ #include "mongo/db/query/allowed_contexts.h" #include "mongo/db/query/datetime/date_time_support.h" #include "mongo/db/query/query_shape/serialization_options.h" -#include "mongo/db/query/sort_pattern.h" #include "mongo/db/query/util/named_enum.h" #include "mongo/db/update/pattern_cmp.h" #include "mongo/db/version_context.h" diff --git a/src/mongo/db/pipeline/expression_from_accumulator_quantile.h b/src/mongo/db/pipeline/expression_from_accumulator_quantile.h index 726f09f39eb..7c7009e056e 100644 --- a/src/mongo/db/pipeline/expression_from_accumulator_quantile.h +++ b/src/mongo/db/pipeline/expression_from_accumulator_quantile.h @@ -42,7 +42,6 @@ #include "mongo/db/exec/document_value/document.h" #include "mongo/db/exec/document_value/value.h" #include "mongo/db/pipeline/expression_context.h" -#include "mongo/db/pipeline/expression_from_accumulator_quantile.h" #include "mongo/db/pipeline/expression_visitor.h" #include "mongo/db/pipeline/percentile_algo.h" #include "mongo/db/pipeline/percentile_algo_continuous.h" diff --git a/src/mongo/db/pipeline/expression_visitor.h b/src/mongo/db/pipeline/expression_visitor.h index 0034744465f..796c2ff341d 100644 --- a/src/mongo/db/pipeline/expression_visitor.h +++ b/src/mongo/db/pipeline/expression_visitor.h @@ -29,7 +29,6 @@ #pragma once -#include "mongo/db/pipeline/expression.h" #include "mongo/platform/basic.h" #include "mongo/db/pipeline/expression_walker.h" diff --git a/src/mongo/db/pipeline/match_processor.cpp b/src/mongo/db/pipeline/match_processor.cpp index 89f990a9e39..9dce372a5c0 100644 --- a/src/mongo/db/pipeline/match_processor.cpp +++ b/src/mongo/db/pipeline/match_processor.cpp @@ -35,6 +35,7 @@ #include "mongo/db/matcher/expression_algo.h" #include "mongo/db/matcher/expression_parser.h" #include "mongo/db/matcher/match_expression_dependencies.h" +#include "mongo/db/pipeline/document_path_support.h" #include "mongo/db/pipeline/expression.h" namespace mongo { diff --git a/src/mongo/db/pipeline/search/document_source_list_search_indexes.cpp b/src/mongo/db/pipeline/search/document_source_list_search_indexes.cpp index 5c131fd0415..28110a51cd6 100644 --- a/src/mongo/db/pipeline/search/document_source_list_search_indexes.cpp +++ b/src/mongo/db/pipeline/search/document_source_list_search_indexes.cpp @@ -28,6 +28,7 @@ */ #include "mongo/db/pipeline/search/document_source_list_search_indexes.h" +#include "mongo/db/pipeline/search/document_source_list_search_indexes_gen.h" #include "mongo/db/query/search/search_index_common.h" #include "mongo/db/query/search/search_index_process_interface.h" diff --git a/src/mongo/db/pipeline/search/document_source_list_search_indexes.h b/src/mongo/db/pipeline/search/document_source_list_search_indexes.h index 0df710f56ef..4c1b2dd3bf1 100644 --- a/src/mongo/db/pipeline/search/document_source_list_search_indexes.h +++ b/src/mongo/db/pipeline/search/document_source_list_search_indexes.h @@ -34,7 +34,6 @@ #include "mongo/bson/bsonobj.h" #include "mongo/db/pipeline/document_source.h" -#include "mongo/db/pipeline/search/document_source_list_search_indexes_gen.h" #include "mongo/db/query/search/search_query_view_spec_gen.h" namespace mongo { diff --git a/src/mongo/db/pipeline/window_function/window_bounds.h b/src/mongo/db/pipeline/window_function/window_bounds.h index f953e353f09..635d6401ca5 100644 --- a/src/mongo/db/pipeline/window_function/window_bounds.h +++ b/src/mongo/db/pipeline/window_function/window_bounds.h @@ -29,6 +29,8 @@ #pragma once +#include "mongo/db/query/sort_pattern.h" + namespace mongo { /** diff --git a/src/mongo/db/pipeline/window_function/window_function_exec_derivative.h b/src/mongo/db/pipeline/window_function/window_function_exec_derivative.h index 5f17b4a52ec..5791cfab5e4 100644 --- a/src/mongo/db/pipeline/window_function/window_function_exec_derivative.h +++ b/src/mongo/db/pipeline/window_function/window_function_exec_derivative.h @@ -43,6 +43,7 @@ #include "mongo/db/pipeline/window_function/window_bounds.h" #include "mongo/db/pipeline/window_function/window_function_exec.h" #include "mongo/db/query/datetime/date_time_support.h" +#include "mongo/db/query/sort_pattern.h" #include "mongo/util/assert_util.h" namespace mongo { diff --git a/src/mongo/db/pipeline/window_function/window_function_statement.h b/src/mongo/db/pipeline/window_function/window_function_statement.h index ad99f9c54ef..47e64f8b21d 100644 --- a/src/mongo/db/pipeline/window_function/window_function_statement.h +++ b/src/mongo/db/pipeline/window_function/window_function_statement.h @@ -30,6 +30,7 @@ #pragma once #include "mongo/db/pipeline/window_function/window_function_expression.h" +#include "mongo/db/query/sort_pattern.h" namespace mongo { diff --git a/src/mongo/db/pipeline/window_function/window_function_top_bottom_n.h b/src/mongo/db/pipeline/window_function/window_function_top_bottom_n.h index 60eb98336af..7cc319b9752 100644 --- a/src/mongo/db/pipeline/window_function/window_function_top_bottom_n.h +++ b/src/mongo/db/pipeline/window_function/window_function_top_bottom_n.h @@ -31,6 +31,7 @@ #include "mongo/db/pipeline/accumulator_multi.h" #include "mongo/db/pipeline/window_function/window_function.h" +#include "mongo/db/query/sort_pattern.h" namespace mongo { diff --git a/src/mongo/db/query/canonical_distinct.h b/src/mongo/db/query/canonical_distinct.h index b1e9d71605c..eb9256da602 100644 --- a/src/mongo/db/query/canonical_distinct.h +++ b/src/mongo/db/query/canonical_distinct.h @@ -36,6 +36,7 @@ #include #include "mongo/db/pipeline/group_from_first_document_transformation.h" +#include "mongo/db/query/sort_pattern.h" #include "mongo/util/uuid.h" namespace mongo { diff --git a/src/mongo/db/query/client_cursor/cursor_idl_validator.h b/src/mongo/db/query/client_cursor/cursor_idl_validator.h index a733373c4be..f6d6a666bbc 100644 --- a/src/mongo/db/query/client_cursor/cursor_idl_validator.h +++ b/src/mongo/db/query/client_cursor/cursor_idl_validator.h @@ -28,7 +28,6 @@ */ #pragma once -#include "mongo/db/query/client_cursor/cursor_response_gen.h" namespace mongo { diff --git a/src/mongo/db/query/plan_enumerator/plan_enumerator.h b/src/mongo/db/query/plan_enumerator/plan_enumerator.h index 861c280702e..87781ef4f42 100644 --- a/src/mongo/db/query/plan_enumerator/plan_enumerator.h +++ b/src/mongo/db/query/plan_enumerator/plan_enumerator.h @@ -48,6 +48,7 @@ #include "mongo/db/query/plan_enumerator/enumerator_memo.h" #include "mongo/db/query/plan_enumerator/plan_enumerator_explain_info.h" #include "mongo/db/query/query_knobs_gen.h" +#include "mongo/db/query/sort_pattern.h" #include "mongo/platform/atomic_word.h" #include "mongo/stdx/unordered_map.h" #include "mongo/util/fail_point.h" diff --git a/src/mongo/db/query/query_solution.h b/src/mongo/db/query/query_solution.h index ffdb84697e0..fd2f1565498 100644 --- a/src/mongo/db/query/query_solution.h +++ b/src/mongo/db/query/query_solution.h @@ -71,6 +71,7 @@ #include "mongo/db/query/projection.h" #include "mongo/db/query/query_knobs_gen.h" #include "mongo/db/query/record_id_bound.h" +#include "mongo/db/query/sort_pattern.h" #include "mongo/db/query/stage_types.h" #include "mongo/db/query/timeseries/bucket_spec.h" #include "mongo/platform/atomic_word.h" diff --git a/src/mongo/db/query/stage_builder/sbe/gen_helpers.h b/src/mongo/db/query/stage_builder/sbe/gen_helpers.h index 4e393b8fb86..97d860a6975 100644 --- a/src/mongo/db/query/stage_builder/sbe/gen_helpers.h +++ b/src/mongo/db/query/stage_builder/sbe/gen_helpers.h @@ -55,6 +55,7 @@ #include "mongo/db/pipeline/expression.h" #include "mongo/db/pipeline/variables.h" #include "mongo/db/query/projection_ast.h" +#include "mongo/db/query/sort_pattern.h" #include "mongo/db/query/stage_builder/sbe/abt/comparison_op.h" #include "mongo/db/query/stage_builder/sbe/builder_state.h" #include "mongo/db/query/stage_builder/sbe/sbexpr.h" diff --git a/src/mongo/db/s/migration_blocking_operation/multi_update_coordinator.h b/src/mongo/db/s/migration_blocking_operation/multi_update_coordinator.h index 8fc42bfb84c..513b2a0618c 100644 --- a/src/mongo/db/s/migration_blocking_operation/multi_update_coordinator.h +++ b/src/mongo/db/s/migration_blocking_operation/multi_update_coordinator.h @@ -30,7 +30,6 @@ #pragma once #include "mongo/db/repl/primary_only_service.h" -#include "mongo/db/s/migration_blocking_operation/multi_update_coordinator.h" #include "mongo/db/s/migration_blocking_operation/multi_update_coordinator_external_state.h" #include "mongo/db/s/migration_blocking_operation/multi_update_coordinator_gen.h" #include "mongo/db/s/primary_only_service_helpers/retry_until_majority_commit.h" diff --git a/src/mongo/db/s/migration_chunk_cloner_source.h b/src/mongo/db/s/migration_chunk_cloner_source.h index f30768bc922..59e16bf153c 100644 --- a/src/mongo/db/s/migration_chunk_cloner_source.h +++ b/src/mongo/db/s/migration_chunk_cloner_source.h @@ -57,7 +57,6 @@ #include "mongo/db/record_id.h" #include "mongo/db/repl/oplog_entry.h" #include "mongo/db/repl/optime.h" -#include "mongo/db/s/migration_chunk_cloner_source.h" #include "mongo/db/s/migration_session_id.h" #include "mongo/db/s/session_catalog_migration_source.h" #include "mongo/db/session/logical_session_id.h" diff --git a/src/mongo/db/s/resharding/resharding_change_streams_monitor.cpp b/src/mongo/db/s/resharding/resharding_change_streams_monitor.cpp index b6b0c20688a..bedc2b1d13e 100644 --- a/src/mongo/db/s/resharding/resharding_change_streams_monitor.cpp +++ b/src/mongo/db/s/resharding/resharding_change_streams_monitor.cpp @@ -29,6 +29,7 @@ #include "mongo/db/s/resharding/resharding_change_streams_monitor.h" +#include "mongo/db/pipeline/aggregate_command_gen.h" #include "mongo/db/pipeline/aggregation_request_helper.h" #include "mongo/db/pipeline/document_source_change_stream.h" #include "mongo/db/pipeline/document_source_change_stream_gen.h" diff --git a/src/mongo/db/update_index_data.h b/src/mongo/db/update_index_data.h index 5cf3f3f28ff..9ab937207d9 100644 --- a/src/mongo/db/update_index_data.h +++ b/src/mongo/db/update_index_data.h @@ -34,7 +34,6 @@ #include "mongo/base/string_data.h" #include "mongo/db/field_ref.h" -#include "mongo/db/update_index_data.h" namespace mongo { diff --git a/src/mongo/s/query_analysis_sampler.cpp b/src/mongo/s/query_analysis_sampler.cpp index a6acf1f09e8..afef2c080b7 100644 --- a/src/mongo/s/query_analysis_sampler.cpp +++ b/src/mongo/s/query_analysis_sampler.cpp @@ -56,6 +56,7 @@ #include "mongo/platform/compiler.h" #include "mongo/rpc/get_status_from_command_result.h" #include "mongo/s/analyze_shard_key_role.h" +#include "mongo/s/analyze_shard_key_server_parameters_gen.h" #include "mongo/s/client/shard.h" #include "mongo/s/client/shard_registry.h" #include "mongo/s/grid.h" diff --git a/src/mongo/s/query_analysis_sampler.h b/src/mongo/s/query_analysis_sampler.h index 69a1018c2e8..a09db000441 100644 --- a/src/mongo/s/query_analysis_sampler.h +++ b/src/mongo/s/query_analysis_sampler.h @@ -40,7 +40,6 @@ #include "mongo/db/service_context.h" #include "mongo/s/analyze_shard_key_common_gen.h" #include "mongo/s/analyze_shard_key_role.h" -#include "mongo/s/analyze_shard_key_server_parameters_gen.h" #include "mongo/stdx/mutex.h" #include "mongo/util/assert_util.h" #include "mongo/util/periodic_runner.h" diff --git a/src/mongo/s/query_analysis_sampler_test.cpp b/src/mongo/s/query_analysis_sampler_test.cpp index ad8d05c9eb8..83e3e8b6902 100644 --- a/src/mongo/s/query_analysis_sampler_test.cpp +++ b/src/mongo/s/query_analysis_sampler_test.cpp @@ -55,6 +55,7 @@ #include "mongo/idl/server_parameter_test_util.h" #include "mongo/rpc/op_msg.h" #include "mongo/s/analyze_shard_key_common_gen.h" +#include "mongo/s/analyze_shard_key_server_parameters_gen.h" #include "mongo/s/refresh_query_analyzer_configuration_cmd_gen.h" #include "mongo/s/sharding_mongos_test_fixture.h" #include "mongo/stdx/future.h" diff --git a/src/mongo/unittest/BUILD.bazel b/src/mongo/unittest/BUILD.bazel index 351f9928e6d..8d890f11615 100644 --- a/src/mongo/unittest/BUILD.bazel +++ b/src/mongo/unittest/BUILD.bazel @@ -33,11 +33,9 @@ mongo_cc_library( "assert.h", "assert_that.h", "barrier.h", - "bson_test_util.h", "death_test.h", "framework.h", "golden_test.h", - "inline_auto_update.h", "join_thread.h", "log_test.h", "matcher.h", diff --git a/src/mongo/unittest/assert.h b/src/mongo/unittest/assert.h index 65beba99190..984841f697d 100644 --- a/src/mongo/unittest/assert.h +++ b/src/mongo/unittest/assert.h @@ -48,10 +48,13 @@ #include "mongo/base/status_with.h" #include "mongo/base/string_data.h" +#include "mongo/bson/bsonelement.h" +#include "mongo/bson/bsonobj.h" +#include "mongo/bson/simple_bsonelement_comparator.h" +#include "mongo/bson/simple_bsonobj_comparator.h" #include "mongo/db/exec/mutable_bson/mutable_bson_test_utils.h" #include "mongo/logv2/log_debug.h" #include "mongo/logv2/log_detail.h" -#include "mongo/unittest/bson_test_util.h" #include "mongo/unittest/framework.h" #include "mongo/unittest/stringify.h" #include "mongo/unittest/test_info.h" @@ -551,4 +554,139 @@ T assertGet(StatusWith&& swt) { return std::move(swt.getValue()); } + +/** + * BSON comparison utility macro. Do not use directly. + */ +#define ASSERT_BSON_COMPARISON(NAME, a, b, astr, bstr) \ + ::mongo::unittest::assertComparison_##NAME(__FILE__, __LINE__, astr, bstr, a, b) + +/** + * Use to compare two instances of type BSONObj under the default comparator in unit tests. + */ +#define ASSERT_BSONOBJ_EQ(a, b) ASSERT_BSON_COMPARISON(BSONObjEQ, a, b, #a, #b) +#define ASSERT_BSONOBJ_LT(a, b) ASSERT_BSON_COMPARISON(BSONObjLT, a, b, #a, #b) +#define ASSERT_BSONOBJ_LTE(a, b) ASSERT_BSON_COMPARISON(BSONObjLTE, a, b, #a, #b) +#define ASSERT_BSONOBJ_GT(a, b) ASSERT_BSON_COMPARISON(BSONObjGT, a, b, #a, #b) +#define ASSERT_BSONOBJ_GTE(a, b) ASSERT_BSON_COMPARISON(BSONObjGTE, a, b, #a, #b) +#define ASSERT_BSONOBJ_NE(a, b) ASSERT_BSON_COMPARISON(BSONObjNE, a, b, #a, #b) + +/** + * Use to compare two instances of type BSONObj with unordered fields in unit tests. + */ +#define ASSERT_BSONOBJ_EQ_UNORDERED(a, b) ASSERT_BSON_COMPARISON(BSONObjEQ_UNORDERED, a, b, #a, #b) +#define ASSERT_BSONOBJ_LT_UNORDERED(a, b) ASSERT_BSON_COMPARISON(BSONObjLT_UNORDERED, a, b, #a, #b) +#define ASSERT_BSONOBJ_LTE_UNORDERED(a, b) \ + ASSERT_BSON_COMPARISON(BSONObjLTE_UNORDERED, a, b, #a, #b) +#define ASSERT_BSONOBJ_GT_UNORDERED(a, b) ASSERT_BSON_COMPARISON(BSONObjGT_UNORDERED, a, b, #a, #b) +#define ASSERT_BSONOBJ_GTE_UNORDERED(a, b) \ + ASSERT_BSON_COMPARISON(BSONObjGTE_UNORDERED, a, b, #a, #b) +#define ASSERT_BSONOBJ_NE_UNORDERED(a, b) ASSERT_BSON_COMPARISON(BSONObjNE_UNORDERED, a, b, #a, #b) + +/** + * Use to compare two instances of type BSONElement under the default comparator in unit tests. + */ +#define ASSERT_BSONELT_EQ(a, b) ASSERT_BSON_COMPARISON(BSONElementEQ, a, b, #a, #b) +#define ASSERT_BSONELT_LT(a, b) ASSERT_BSON_COMPARISON(BSONElementLT, a, b, #a, #b) +#define ASSERT_BSONELT_LTE(a, b) ASSERT_BSON_COMPARISON(BSONElementLTE, a, b, #a, #b) +#define ASSERT_BSONELT_GT(a, b) ASSERT_BSON_COMPARISON(BSONElementGT, a, b, #a, #b) +#define ASSERT_BSONELT_GTE(a, b) ASSERT_BSON_COMPARISON(BSONElementGTE, a, b, #a, #b) +#define ASSERT_BSONELT_NE(a, b) ASSERT_BSON_COMPARISON(BSONElementNE, a, b, #a, #b) + +#define ASSERT_BSONOBJ_BINARY_EQ(a, b) \ + ::mongo::unittest::assertComparison_BSONObjBINARY_EQ(__FILE__, __LINE__, #a, #b, a, b) + +#define DECLARE_BSON_CMP_FUNC(BSONTYPE, NAME) \ + void assertComparison_##BSONTYPE##NAME(const std::string& theFile, \ + unsigned theLine, \ + StringData aExpression, \ + StringData bExpression, \ + const BSONTYPE& aValue, \ + const BSONTYPE& bValue); + +DECLARE_BSON_CMP_FUNC(BSONObj, EQ); +DECLARE_BSON_CMP_FUNC(BSONObj, LT); +DECLARE_BSON_CMP_FUNC(BSONObj, LTE); +DECLARE_BSON_CMP_FUNC(BSONObj, GT); +DECLARE_BSON_CMP_FUNC(BSONObj, GTE); +DECLARE_BSON_CMP_FUNC(BSONObj, NE); + +DECLARE_BSON_CMP_FUNC(BSONObj, EQ_UNORDERED); +DECLARE_BSON_CMP_FUNC(BSONObj, LT_UNORDERED); +DECLARE_BSON_CMP_FUNC(BSONObj, LTE_UNORDERED); +DECLARE_BSON_CMP_FUNC(BSONObj, GT_UNORDERED); +DECLARE_BSON_CMP_FUNC(BSONObj, GTE_UNORDERED); +DECLARE_BSON_CMP_FUNC(BSONObj, NE_UNORDERED); + +DECLARE_BSON_CMP_FUNC(BSONObj, BINARY_EQ); + +DECLARE_BSON_CMP_FUNC(BSONElement, EQ); +DECLARE_BSON_CMP_FUNC(BSONElement, LT); +DECLARE_BSON_CMP_FUNC(BSONElement, LTE); +DECLARE_BSON_CMP_FUNC(BSONElement, GT); +DECLARE_BSON_CMP_FUNC(BSONElement, GTE); +DECLARE_BSON_CMP_FUNC(BSONElement, NE); +#undef DECLARE_BSON_CMP_FUNC + +/** + * Given a BSONObj, return a string that wraps the json form of the BSONObj with + * `fromjson(R"(<>)")`. + */ +std::string formatJsonStr(const std::string& obj); + +#define ASSERT_BSONOBJ_EQ_AUTO(expected, actual) \ + ASSERT(AUTO_UPDATE_HELPER(::mongo::unittest::formatJsonStr(expected), \ + ::mongo::unittest::formatJsonStr(actual.jsonString()), \ + false)) + +/** + * Computes a difference between the expected and actual formatted output and outputs it to the + * provide stream instance. Used to display difference between expected and actual format for + * auto-update macros. It is exposed in the header here for testability. + */ +void outputDiff(std::ostream& os, + const std::vector& expFormatted, + const std::vector& actualFormatted, + size_t startLineNumber); + +bool handleAutoUpdate(const std::string& expected, + const std::string& actual, + const std::string& fileName, + size_t lineNumber, + bool needsEscaping); + +bool expandNoPlanMacro(const std::string& fileName, size_t lineNumber); + +void updateDelta(const std::string& fileName, size_t lineNumber, int64_t delta); + +void expandActualPlan(const SourceLocation& location, const std::string& actual); + +// Account for maximum line length after linting. We need to indent, add quotes, etc. +static constexpr size_t kAutoUpdateMaxLineLength = 88; + +/** + * Auto update result back in the source file if the assert fails. + * The expected result must be a multi-line string in the following form: + * + * ASSERT_EXPLAIN_V2_AUTO( // NOLINT + * "BinaryOp [Add]\n" + * "| Const [2]\n" + * "Const [1]\n", + * tree); + * + * Limitations: + * 1. There should not be any comments or other formatting inside the multi-line string + * constant other than 'NOLINT'. If we have a single-line constant, the auto-updating will + * generate a 'NOLINT' at the end of the line. + * 2. The expression which we are explaining ('tree' in the example above) must fit on a single + * line. + * 3. The macro should be indented by 4 spaces. + */ +#define AUTO_UPDATE_HELPER(expected, actual, needsEscaping) \ + ::mongo::unittest::handleAutoUpdate(expected, actual, __FILE__, __LINE__, needsEscaping) + +#define ASSERT_STR_EQ_AUTO(expected, actual) ASSERT(AUTO_UPDATE_HELPER(expected, actual, true)) + +#define ASSERT_NUMBER_EQ_AUTO(expected, actual) \ + ASSERT(AUTO_UPDATE_HELPER(str::stream() << expected, str::stream() << actual, false)) } // namespace mongo::unittest diff --git a/src/mongo/unittest/bson_test_util.cpp b/src/mongo/unittest/bson_test_util.cpp index 03b18ce0bd8..2e04a8c7148 100644 --- a/src/mongo/unittest/bson_test_util.cpp +++ b/src/mongo/unittest/bson_test_util.cpp @@ -37,8 +37,6 @@ #include "mongo/bson/simple_bsonobj_comparator.h" #include "mongo/bson/unordered_fields_bsonobj_comparator.h" #include "mongo/unittest/assert.h" -#include "mongo/unittest/bson_test_util.h" -#include "mongo/unittest/inline_auto_update.h" #include "mongo/util/assert_util.h" #include "mongo/util/str.h" diff --git a/src/mongo/unittest/bson_test_util.h b/src/mongo/unittest/bson_test_util.h deleted file mode 100644 index 55a217f4111..00000000000 --- a/src/mongo/unittest/bson_test_util.h +++ /dev/null @@ -1,132 +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 - * . - * - * 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 - -// IWYU pragma: private, include "mongo/unittest/unittest.h" -// IWYU pragma: friend "mongo/unittest/.*" - -#include - -#include "mongo/base/string_data.h" -#include "mongo/bson/bsonelement.h" -#include "mongo/bson/bsonobj.h" -#include "mongo/bson/simple_bsonelement_comparator.h" -#include "mongo/bson/simple_bsonobj_comparator.h" -#include "mongo/unittest/assert.h" -#include "mongo/unittest/inline_auto_update.h" - -/** - * BSON comparison utility macro. Do not use directly. - */ -#define ASSERT_BSON_COMPARISON(NAME, a, b, astr, bstr) \ - ::mongo::unittest::assertComparison_##NAME(__FILE__, __LINE__, astr, bstr, a, b) - -/** - * Use to compare two instances of type BSONObj under the default comparator in unit tests. - */ -#define ASSERT_BSONOBJ_EQ(a, b) ASSERT_BSON_COMPARISON(BSONObjEQ, a, b, #a, #b) -#define ASSERT_BSONOBJ_LT(a, b) ASSERT_BSON_COMPARISON(BSONObjLT, a, b, #a, #b) -#define ASSERT_BSONOBJ_LTE(a, b) ASSERT_BSON_COMPARISON(BSONObjLTE, a, b, #a, #b) -#define ASSERT_BSONOBJ_GT(a, b) ASSERT_BSON_COMPARISON(BSONObjGT, a, b, #a, #b) -#define ASSERT_BSONOBJ_GTE(a, b) ASSERT_BSON_COMPARISON(BSONObjGTE, a, b, #a, #b) -#define ASSERT_BSONOBJ_NE(a, b) ASSERT_BSON_COMPARISON(BSONObjNE, a, b, #a, #b) - -/** - * Use to compare two instances of type BSONObj with unordered fields in unit tests. - */ -#define ASSERT_BSONOBJ_EQ_UNORDERED(a, b) ASSERT_BSON_COMPARISON(BSONObjEQ_UNORDERED, a, b, #a, #b) -#define ASSERT_BSONOBJ_LT_UNORDERED(a, b) ASSERT_BSON_COMPARISON(BSONObjLT_UNORDERED, a, b, #a, #b) -#define ASSERT_BSONOBJ_LTE_UNORDERED(a, b) \ - ASSERT_BSON_COMPARISON(BSONObjLTE_UNORDERED, a, b, #a, #b) -#define ASSERT_BSONOBJ_GT_UNORDERED(a, b) ASSERT_BSON_COMPARISON(BSONObjGT_UNORDERED, a, b, #a, #b) -#define ASSERT_BSONOBJ_GTE_UNORDERED(a, b) \ - ASSERT_BSON_COMPARISON(BSONObjGTE_UNORDERED, a, b, #a, #b) -#define ASSERT_BSONOBJ_NE_UNORDERED(a, b) ASSERT_BSON_COMPARISON(BSONObjNE_UNORDERED, a, b, #a, #b) - -/** - * Use to compare two instances of type BSONElement under the default comparator in unit tests. - */ -#define ASSERT_BSONELT_EQ(a, b) ASSERT_BSON_COMPARISON(BSONElementEQ, a, b, #a, #b) -#define ASSERT_BSONELT_LT(a, b) ASSERT_BSON_COMPARISON(BSONElementLT, a, b, #a, #b) -#define ASSERT_BSONELT_LTE(a, b) ASSERT_BSON_COMPARISON(BSONElementLTE, a, b, #a, #b) -#define ASSERT_BSONELT_GT(a, b) ASSERT_BSON_COMPARISON(BSONElementGT, a, b, #a, #b) -#define ASSERT_BSONELT_GTE(a, b) ASSERT_BSON_COMPARISON(BSONElementGTE, a, b, #a, #b) -#define ASSERT_BSONELT_NE(a, b) ASSERT_BSON_COMPARISON(BSONElementNE, a, b, #a, #b) - -#define ASSERT_BSONOBJ_BINARY_EQ(a, b) \ - ::mongo::unittest::assertComparison_BSONObjBINARY_EQ(__FILE__, __LINE__, #a, #b, a, b) - -namespace mongo { -namespace unittest { - -#define DECLARE_BSON_CMP_FUNC(BSONTYPE, NAME) \ - void assertComparison_##BSONTYPE##NAME(const std::string& theFile, \ - unsigned theLine, \ - StringData aExpression, \ - StringData bExpression, \ - const BSONTYPE& aValue, \ - const BSONTYPE& bValue); - -DECLARE_BSON_CMP_FUNC(BSONObj, EQ); -DECLARE_BSON_CMP_FUNC(BSONObj, LT); -DECLARE_BSON_CMP_FUNC(BSONObj, LTE); -DECLARE_BSON_CMP_FUNC(BSONObj, GT); -DECLARE_BSON_CMP_FUNC(BSONObj, GTE); -DECLARE_BSON_CMP_FUNC(BSONObj, NE); - -DECLARE_BSON_CMP_FUNC(BSONObj, EQ_UNORDERED); -DECLARE_BSON_CMP_FUNC(BSONObj, LT_UNORDERED); -DECLARE_BSON_CMP_FUNC(BSONObj, LTE_UNORDERED); -DECLARE_BSON_CMP_FUNC(BSONObj, GT_UNORDERED); -DECLARE_BSON_CMP_FUNC(BSONObj, GTE_UNORDERED); -DECLARE_BSON_CMP_FUNC(BSONObj, NE_UNORDERED); - -DECLARE_BSON_CMP_FUNC(BSONObj, BINARY_EQ); - -DECLARE_BSON_CMP_FUNC(BSONElement, EQ); -DECLARE_BSON_CMP_FUNC(BSONElement, LT); -DECLARE_BSON_CMP_FUNC(BSONElement, LTE); -DECLARE_BSON_CMP_FUNC(BSONElement, GT); -DECLARE_BSON_CMP_FUNC(BSONElement, GTE); -DECLARE_BSON_CMP_FUNC(BSONElement, NE); -#undef DECLARE_BSON_CMP_FUNC - -/** - * Given a BSONObj, return a string that wraps the json form of the BSONObj with - * `fromjson(R"(<>)")`. - */ -std::string formatJsonStr(const std::string& obj); - -#define ASSERT_BSONOBJ_EQ_AUTO(expected, actual) \ - ASSERT(AUTO_UPDATE_HELPER(::mongo::unittest::formatJsonStr(expected), \ - ::mongo::unittest::formatJsonStr(actual.jsonString()), \ - false)) -} // namespace unittest -} // namespace mongo diff --git a/src/mongo/unittest/inline_auto_update.cpp b/src/mongo/unittest/inline_auto_update.cpp index dae4f12d753..a4a3dd06e37 100644 --- a/src/mongo/unittest/inline_auto_update.cpp +++ b/src/mongo/unittest/inline_auto_update.cpp @@ -27,7 +27,6 @@ * it in the license file. */ -#include "mongo/unittest/inline_auto_update.h" #include #include @@ -42,6 +41,7 @@ #include #include +#include "mongo/unittest/assert.h" #include "mongo/unittest/framework.h" #include "mongo/util/str_escape.h" diff --git a/src/mongo/unittest/inline_auto_update.h b/src/mongo/unittest/inline_auto_update.h deleted file mode 100644 index 2a8d2954ee1..00000000000 --- a/src/mongo/unittest/inline_auto_update.h +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright (C) 2022-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 - * . - * - * 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 - -// IWYU pragma: private, include "mongo/unittest/unittest.h" -// IWYU pragma: friend "mongo/unittest/.*" - -#include -#include -#include -#include - -#include "mongo/platform/source_location.h" -#include "mongo/unittest/assert.h" - -namespace mongo::unittest { -/** - * Computes a difference between the expected and actual formatted output and outputs it to the - * provide stream instance. Used to display difference between expected and actual format for - * auto-update macros. It is exposed in the header here for testability. - */ -void outputDiff(std::ostream& os, - const std::vector& expFormatted, - const std::vector& actualFormatted, - size_t startLineNumber); - -bool handleAutoUpdate(const std::string& expected, - const std::string& actual, - const std::string& fileName, - size_t lineNumber, - bool needsEscaping); - -bool expandNoPlanMacro(const std::string& fileName, size_t lineNumber); - -void updateDelta(const std::string& fileName, size_t lineNumber, int64_t delta); - -void expandActualPlan(const SourceLocation& location, const std::string& actual); - -// Account for maximum line length after linting. We need to indent, add quotes, etc. -static constexpr size_t kAutoUpdateMaxLineLength = 88; - -/** - * Auto update result back in the source file if the assert fails. - * The expected result must be a multi-line string in the following form: - * - * ASSERT_EXPLAIN_V2_AUTO( // NOLINT - * "BinaryOp [Add]\n" - * "| Const [2]\n" - * "Const [1]\n", - * tree); - * - * Limitations: - * 1. There should not be any comments or other formatting inside the multi-line string - * constant other than 'NOLINT'. If we have a single-line constant, the auto-updating will - * generate a 'NOLINT' at the end of the line. - * 2. The expression which we are explaining ('tree' in the example above) must fit on a single - * line. - * 3. The macro should be indented by 4 spaces. - */ -#define AUTO_UPDATE_HELPER(expected, actual, needsEscaping) \ - ::mongo::unittest::handleAutoUpdate(expected, actual, __FILE__, __LINE__, needsEscaping) - -#define ASSERT_STR_EQ_AUTO(expected, actual) ASSERT(AUTO_UPDATE_HELPER(expected, actual, true)) - -#define ASSERT_NUMBER_EQ_AUTO(expected, actual) \ - ASSERT(AUTO_UPDATE_HELPER(str::stream() << expected, str::stream() << actual, false)) -} // namespace mongo::unittest diff --git a/src/mongo/unittest/inline_auto_update_test.cpp b/src/mongo/unittest/inline_auto_update_test.cpp index 5e894474643..d83a4bb7e42 100644 --- a/src/mongo/unittest/inline_auto_update_test.cpp +++ b/src/mongo/unittest/inline_auto_update_test.cpp @@ -27,7 +27,6 @@ * it in the license file. */ -#include "mongo/unittest/inline_auto_update.h" #include "mongo/base/string_data.h" #include "mongo/unittest/assert.h" diff --git a/src/mongo/unittest/unittest.h b/src/mongo/unittest/unittest.h index c1d801b2dbf..64be7e8b86b 100644 --- a/src/mongo/unittest/unittest.h +++ b/src/mongo/unittest/unittest.h @@ -43,7 +43,6 @@ #pragma once -#include "mongo/unittest/assert.h" // IWYU pragma: export -#include "mongo/unittest/assert_that.h" // IWYU pragma: export -#include "mongo/unittest/bson_test_util.h" // IWYU pragma: export -#include "mongo/unittest/framework.h" // IWYU pragma: export +#include "mongo/unittest/assert.h" // IWYU pragma: export +#include "mongo/unittest/assert_that.h" // IWYU pragma: export +#include "mongo/unittest/framework.h" // IWYU pragma: export diff --git a/src/mongo/unittest/unittest_test.cpp b/src/mongo/unittest/unittest_test.cpp index 06a81839dff..1b19d1abee3 100644 --- a/src/mongo/unittest/unittest_test.cpp +++ b/src/mongo/unittest/unittest_test.cpp @@ -56,7 +56,6 @@ #include "mongo/logv2/log.h" #include "mongo/stdx/type_traits.h" #include "mongo/unittest/assert.h" -#include "mongo/unittest/bson_test_util.h" #include "mongo/unittest/death_test.h" #include "mongo/unittest/framework.h" #include "mongo/unittest/stringify.h"