diff options
author | Henrik Edin <henrik.edin@mongodb.com> | 2021-10-21 19:59:30 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-10-21 20:50:41 +0000 |
commit | 5a393055b2bcd03c9bf566a250f89c73a5e48387 (patch) | |
tree | d6ee76334d743ca8f4cc518b0758b3c7c79438a7 /src | |
parent | ba83473ade3ee39cd9053ed3b2b3bf3e5f64ba28 (diff) | |
download | mongo-5a393055b2bcd03c9bf566a250f89c73a5e48387.tar.gz |
SERVER-60884 Fix so Simple8bBuilder::flush doesn't leave state for RLE
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/bson/util/simple8b.cpp | 3 | ||||
-rw-r--r-- | src/mongo/bson/util/simple8b.h | 5 | ||||
-rw-r--r-- | src/mongo/bson/util/simple8b_test.cpp | 36 |
3 files changed, 40 insertions, 4 deletions
diff --git a/src/mongo/bson/util/simple8b.cpp b/src/mongo/bson/util/simple8b.cpp index 5c9f7a68418..ccc9d076e0a 100644 --- a/src/mongo/bson/util/simple8b.cpp +++ b/src/mongo/bson/util/simple8b.cpp @@ -420,7 +420,6 @@ void Simple8bBuilder<T>::flush() { _handleRleTermination(); // Flush buffered values in _pendingValues. if (!_pendingValues.empty()) { - PendingValue lastPendingValue = _pendingValues.back(); // always flush with the most recent valid selector. This value is the baseSelector if we // have not have a valid selector yet. do { @@ -431,7 +430,7 @@ void Simple8bBuilder<T>::flush() { // 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; - _lastValueInPrevWord = lastPendingValue; + _lastValueInPrevWord = {}; } } diff --git a/src/mongo/bson/util/simple8b.h b/src/mongo/bson/util/simple8b.h index 510545bf767..b7d5e323398 100644 --- a/src/mongo/bson/util/simple8b.h +++ b/src/mongo/bson/util/simple8b.h @@ -139,6 +139,7 @@ private: * in the cpp file. */ struct PendingValue { + PendingValue() = default; PendingValue(boost::optional<T> val, std::array<uint8_t, kNumOfSelectorTypes> bitCount, std::array<uint8_t, kNumOfSelectorTypes> trailingZerosCount); @@ -151,7 +152,7 @@ private: return val.value(); } - boost::optional<T> val; + boost::optional<T> val = T{0}; std::array<uint8_t, kNumOfSelectorTypes> bitCount = {0, 0, 0, 0}; // This is not the total number of trailing zeros, but the trailing zeros that will be // stored given the selector chosen. @@ -255,7 +256,7 @@ private: // If RLE is ongoing, the number of consecutive repeats fo lastValueInPrevWord. uint32_t _rleCount = 0; // If RLE is ongoing, the last value in the previous Simple8b word. - PendingValue _lastValueInPrevWord = {boost::optional<T>(0), {0, 0, 0, 0}, {0, 0, 0, 0}}; + PendingValue _lastValueInPrevWord; // These variables hold the max amount of bits for each value in _pendingValues. They are // updated whenever values are added or removed from _pendingValues to always reflect the max diff --git a/src/mongo/bson/util/simple8b_test.cpp b/src/mongo/bson/util/simple8b_test.cpp index 9afb24b5f87..b6ab16c33d4 100644 --- a/src/mongo/bson/util/simple8b_test.cpp +++ b/src/mongo/bson/util/simple8b_test.cpp @@ -1120,6 +1120,42 @@ TEST(Simple8b, RleEightSelectorLarge) { testSimple8b(expectedInts, expectedBinary); } +TEST(Simple8b, RleFlushResetsRle) { + BufBuilder buffer; + Simple8bBuilder<uint64_t> builder([&buffer](uint64_t simple8bBlock) { + buffer.appendNum(simple8bBlock); + return true; + }); + + // Write a single 1 and flush. Then we add 120 more 1s and check that this does not start RLE. + ASSERT_TRUE(builder.append(1)); + builder.flush(); + + for (int i = 0; i < 120; ++i) { + ASSERT_TRUE(builder.append(1)); + } + builder.flush(); + + auto size = buffer.len(); + auto sharedBuffer = buffer.release(); + + std::vector<uint8_t> simple8bBlockOne1 = {0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + std::vector<uint8_t> simple8bBlockThirty1s = {0x52, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}; + + std::vector<uint8_t> expectedBinary; + expectedBinary.insert(expectedBinary.end(), simple8bBlockOne1.begin(), simple8bBlockOne1.end()); + for (int i = 0; i < 4; ++i) { + expectedBinary.insert( + expectedBinary.end(), simple8bBlockThirty1s.begin(), simple8bBlockThirty1s.end()); + } + + ASSERT_EQ(size, expectedBinary.size()); + ASSERT_EQ(memcmp(sharedBuffer.get(), expectedBinary.data(), size), 0); + + Simple8b<uint64_t> s8b(sharedBuffer.get(), size); + assertValuesEqual(s8b, std::vector<boost::optional<uint64_t>>(121, 1)); +} + TEST(Simple8b, EightSelectorLargeMax) { // Selector 8 value // 1111 + 124 zeros |