Skip to content

Commit 4451984

Browse files
Sriram Ganesandaverigby
authored andcommitted
MB-30097: Use valueSize() instead of using size directly
The higher order bit of the size of a Blob will be set if the value if uncompressible. The valueSize() function will clear the bit and return the actual size of the value. The valueSize() function needs to be used in the copy contructor of the Blob to use a memcpy instead of using the size variable directly. Change-Id: I7745190e83c1ee97c4fdefc3ac06473627159549 Reviewed-on: http://review.couchbase.org/95566 Well-Formed: Build Bot <[email protected]> Tested-by: Build Bot <[email protected]> Reviewed-by: Dave Rigby <[email protected]>
1 parent 3c15b33 commit 4451984

File tree

4 files changed

+25
-5
lines changed

4 files changed

+25
-5
lines changed

engines/ep/src/blob.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@ Blob::Blob(const size_t len) : Blob(nullptr, len) {
5555
}
5656

5757
Blob::Blob(const Blob& other)
58-
: size(other.size),
58+
: size(other.size.load()),
5959
// While this is a copy, it is a new allocation therefore reset age.
6060
age(0) {
61-
std::memcpy(data, other.data, size);
61+
std::memcpy(data, other.data, other.valueSize());
6262
ObjectRegistry::onCreateBlob(this);
6363
}
6464

engines/ep/src/blob.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,10 @@ class Blob : public RCValue {
161161

162162
// Size of the value. The highest bit is used to represent if the
163163
// value is compressible or not. If set, then the value is not
164-
// compressible.
165-
uint32_t size;
164+
// compressible. This needs to be an atomic variable as there could
165+
// be a data race between threads that update the size
166+
// (e.g, the setUncompressible API) and the ones that read the size
167+
std::atomic<uint32_t> size;
166168

167169
// The age of this Blob, in terms of some unspecified units of time.
168170
uint8_t age;

engines/ep/src/item.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ std::ostream& operator<<(std::ostream& os, const Blob& b) {
205205
<< " age:" << int(b.age)
206206
<< " data: <" << std::hex;
207207
// Print at most 40 bytes of the body.
208-
auto bytes_to_print = std::min(uint32_t(40), b.size);
208+
auto bytes_to_print = std::min(uint32_t(40), b.size.load());
209209
for (size_t ii = 0; ii < bytes_to_print; ii++) {
210210
if (ii != 0) {
211211
os << ' ';

engines/ep/tests/module_tests/stored_value_test.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,24 @@ TYPED_TEST(ValueTest, DISABLED_StoredValueReallocateGivesSameSize) {
135135
}
136136
}
137137

138+
/* MB-30097: Set the stored value as uncompressible and ensure that
139+
* the size of the Blob doesn't change on a reallocation
140+
*/
141+
TYPED_TEST(ValueTest, StoredValueUncompressibleReallocateGivesSameSize) {
142+
auto sv = this->factory(
143+
make_item(0,
144+
makeStoredDocKey(std::string(10, 'k').c_str()),
145+
std::string(182, 'v').c_str()),
146+
{});
147+
148+
auto blob = sv->getValue();
149+
int beforeValueSize = blob->valueSize();
150+
sv->setUncompressible();
151+
sv->reallocate();
152+
blob = sv->getValue();
153+
EXPECT_EQ(beforeValueSize, blob->valueSize());
154+
}
155+
138156
TYPED_TEST(ValueTest, metaDataSize) {
139157
// Check metadata size reports correctly.
140158
EXPECT_EQ(this->getFixedSize() + /*key*/ 3 + /*len*/ 1 +

0 commit comments

Comments
 (0)