summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorHenrik Edin <henrik.edin@mongodb.com>2021-10-21 19:59:30 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-10-21 20:50:41 +0000
commit5a393055b2bcd03c9bf566a250f89c73a5e48387 (patch)
treed6ee76334d743ca8f4cc518b0758b3c7c79438a7 /src/mongo
parentba83473ade3ee39cd9053ed3b2b3bf3e5f64ba28 (diff)
downloadmongo-5a393055b2bcd03c9bf566a250f89c73a5e48387.tar.gz
SERVER-60884 Fix so Simple8bBuilder::flush doesn't leave state for RLE
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/bson/util/simple8b.cpp3
-rw-r--r--src/mongo/bson/util/simple8b.h5
-rw-r--r--src/mongo/bson/util/simple8b_test.cpp36
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