mirror of https://github.com/mongodb/mongo
SERVER-102295 Simplify DatabaseName storage flags implementation (#34512)
GitOrigin-RevId: e4a57ab232b840be280419ad7a5cc301a1c5c60b
This commit is contained in:
parent
cf879d2ede
commit
336b6bbc8d
|
|
@ -367,11 +367,7 @@ class DatabaseNamePrinter(object):
|
||||||
def _get_storage_data(self):
|
def _get_storage_data(self):
|
||||||
"""Return the data pointer from the _data Storage class."""
|
"""Return the data pointer from the _data Storage class."""
|
||||||
data = self.val["_data"]
|
data = self.val["_data"]
|
||||||
footer = data["_footer"]
|
flags = data["_flags"]
|
||||||
f_size = footer.type.sizeof
|
|
||||||
|
|
||||||
# The last byte of _footer contain the flags (and the size when using small string).
|
|
||||||
flags = footer.cast(gdb.lookup_type("char").array(f_size))[f_size - 1]
|
|
||||||
|
|
||||||
data_ptr = data["_data"]
|
data_ptr = data["_data"]
|
||||||
if is_small_string(flags):
|
if is_small_string(flags):
|
||||||
|
|
|
||||||
|
|
@ -429,8 +429,8 @@
|
||||||
</Type>
|
</Type>
|
||||||
|
|
||||||
<Type Name="mongo::DatabaseName">
|
<Type Name="mongo::DatabaseName">
|
||||||
<!-- (((const char *)&_footer)[sizeof(size_t) - 1]) & 2 -->
|
<!-- _data._flags & 2 -->
|
||||||
<DisplayString Condition="(((const char*)& _data._footer)[sizeof(size_t) - 1]) & 2">{ ((const char *)&(_data._data)),[(((const char*)& _data._footer)[sizeof(size_t) - 1]) >> 2]s8 }</DisplayString>
|
<DisplayString Condition="_data._flags & 2">{ ((const char *)&(_data._data)),[_data._flags >> 2]s8 }</DisplayString>
|
||||||
<DisplayString>{_data._data,[_data._length]s8}</DisplayString>
|
<DisplayString>{_data._data,[_data._length]s8}</DisplayString>
|
||||||
</Type>
|
</Type>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -108,8 +108,7 @@ public:
|
||||||
_data = Storage(dbName._data, dbName.sizeWithTenant() + kDataOffset);
|
_data = Storage(dbName._data, dbName.sizeWithTenant() + kDataOffset);
|
||||||
} else if (dbName._data.isSmallString()) {
|
} else if (dbName._data.isSmallString()) {
|
||||||
_data = dbName._data;
|
_data = dbName._data;
|
||||||
_data.updateFooter(database_name::kSmallStringFlag,
|
_data.setFlags(database_name::kSmallStringFlag, dbName.sizeWithTenant() + kDataOffset);
|
||||||
dbName.sizeWithTenant() + kDataOffset);
|
|
||||||
} else {
|
} else {
|
||||||
_data = dbName._data;
|
_data = dbName._data;
|
||||||
}
|
}
|
||||||
|
|
@ -457,20 +456,17 @@ protected:
|
||||||
constexpr Storage(const char* data, size_t length) noexcept
|
constexpr Storage(const char* data, size_t length) noexcept
|
||||||
: _data(data),
|
: _data(data),
|
||||||
_length(length),
|
_length(length),
|
||||||
_footer(createFooter(database_name::kStaticAllocFlag, 0)) {}
|
_flags(createFlags(database_name::kStaticAllocFlag, 0)) {}
|
||||||
|
|
||||||
Storage() noexcept
|
Storage() noexcept
|
||||||
: _data(nullptr),
|
: _data(nullptr),
|
||||||
_length(0),
|
_length(0),
|
||||||
_footer(createFooter(database_name::kSmallStringFlag, kDataOffset)) {}
|
_flags(createFlags(database_name::kSmallStringFlag, kDataOffset)) {}
|
||||||
|
|
||||||
constexpr ~Storage() {
|
constexpr ~Storage() {
|
||||||
if (!std::is_constant_evaluated()) {
|
if (!std::is_constant_evaluated()) {
|
||||||
if (isDynamicAlloc() && _data != nullptr) {
|
if (isDynamicAlloc() && _data != nullptr) {
|
||||||
MONGO_COMPILER_DIAGNOSTIC_PUSH
|
|
||||||
MONGO_COMPILER_DIAGNOSTIC_IGNORED_TRANSITIONAL("-Wfree-nonheap-object")
|
|
||||||
delete[] _data;
|
delete[] _data;
|
||||||
MONGO_COMPILER_DIAGNOSTIC_POP
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -482,14 +478,18 @@ protected:
|
||||||
* a collection and we are only trying to copy the database part from it.
|
* a collection and we are only trying to copy the database part from it.
|
||||||
*/
|
*/
|
||||||
Storage(const Storage& other, const size_t newSize)
|
Storage(const Storage& other, const size_t newSize)
|
||||||
: _data(other._data), _length(other._length), _footer(other._footer) {
|
: _data(other._data),
|
||||||
|
_length(other._length),
|
||||||
|
_padding(other._padding),
|
||||||
|
_flags(other._flags) {
|
||||||
if (other.isStaticAlloc() && other.size() == newSize) {
|
if (other.isStaticAlloc() && other.size() == newSize) {
|
||||||
return;
|
return;
|
||||||
} else if (other.isSmallString()) {
|
} else if (other.isSmallString()) {
|
||||||
updateFooter(database_name::kSmallStringFlag, newSize);
|
setFlags(database_name::kSmallStringFlag, newSize);
|
||||||
} else if (newSize < kSmallStringSize) {
|
} else if (newSize < kSmallStringSize) {
|
||||||
setFooter(database_name::kSmallStringFlag, newSize);
|
setFlags(database_name::kSmallStringFlag, newSize);
|
||||||
memcpy(mutableDataptr(), other._data, newSize);
|
clearPadding();
|
||||||
|
memcpy(smallStringDataptr(), other._data, newSize);
|
||||||
} else if (other.isDynamicAlloc()) {
|
} else if (other.isDynamicAlloc()) {
|
||||||
char* dataptr = new char[newSize];
|
char* dataptr = new char[newSize];
|
||||||
_data = dataptr;
|
_data = dataptr;
|
||||||
|
|
@ -499,7 +499,10 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
Storage(Storage&& other) noexcept
|
Storage(Storage&& other) noexcept
|
||||||
: _data(other._data), _length(other._length), _footer(other._footer) {
|
: _data(other._data),
|
||||||
|
_length(other._length),
|
||||||
|
_padding(other._padding),
|
||||||
|
_flags(other._flags) {
|
||||||
if (other.isDynamicAlloc()) {
|
if (other.isDynamicAlloc()) {
|
||||||
other.reset();
|
other.reset();
|
||||||
}
|
}
|
||||||
|
|
@ -531,39 +534,33 @@ protected:
|
||||||
void copy(const Storage& other) noexcept {
|
void copy(const Storage& other) noexcept {
|
||||||
_data = other._data;
|
_data = other._data;
|
||||||
_length = other._length;
|
_length = other._length;
|
||||||
_footer = other._footer;
|
_padding = other._padding;
|
||||||
|
_flags = other._flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a word with a valid flag byte and the rest of the data cleared.
|
* Returns flagsIn, optionally with the length mixed-in if flagsIn indicate small string
|
||||||
|
* optimization.
|
||||||
*/
|
*/
|
||||||
constexpr size_t createFooter(unsigned char flagsIn, unsigned char length) {
|
constexpr unsigned char createFlags(unsigned char flagsIn, unsigned char length) {
|
||||||
if (flagsIn & database_name::kSmallStringFlag) {
|
if (flagsIn & database_name::kSmallStringFlag) {
|
||||||
flagsIn |= (length << 2);
|
flagsIn |= (length << 2);
|
||||||
}
|
}
|
||||||
|
return flagsIn;
|
||||||
char byteflags[sizeof(size_t)] = {0};
|
|
||||||
byteflags[sizeof(size_t) - 1] = flagsIn;
|
|
||||||
return absl::bit_cast<size_t>(byteflags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the footer field with the correct flags and length. Clear the first sizeof(_footer)
|
* Clear _padding, which might store data when using the small string optimisation.
|
||||||
* - 1 bytes which might store data when using the small string optimisation.
|
|
||||||
*/
|
*/
|
||||||
void setFooter(unsigned char flagsIn, unsigned char length = 0) {
|
void clearPadding() {
|
||||||
_footer = createFooter(flagsIn, length);
|
std::fill(_padding.begin(), _padding.end(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the flag and length of the footer field without changing the first sizeof(_footer) -
|
* Sets the flags and length of the _flags field.
|
||||||
* 1 bytes which might contain data.
|
|
||||||
*/
|
*/
|
||||||
void updateFooter(unsigned char flagsIn, unsigned char length) {
|
void setFlags(unsigned char flagsIn, unsigned char length) {
|
||||||
if (flagsIn & database_name::kSmallStringFlag) {
|
_flags = createFlags(flagsIn, length);
|
||||||
flagsIn |= (length << 2);
|
|
||||||
}
|
|
||||||
reinterpret_cast<unsigned char*>(&_footer)[sizeof(size_t) - 1] = flagsIn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -628,12 +625,13 @@ protected:
|
||||||
dataptr = new char[length];
|
dataptr = new char[length];
|
||||||
data._data = dataptr;
|
data._data = dataptr;
|
||||||
data._length = length;
|
data._length = length;
|
||||||
data._footer = 0;
|
data._flags = 0;
|
||||||
} else {
|
} else {
|
||||||
data.setFooter(database_name::kSmallStringFlag, static_cast<unsigned char>(length));
|
data.setFlags(database_name::kSmallStringFlag, static_cast<unsigned char>(length));
|
||||||
dataptr = data.mutableDataptr();
|
data.clearPadding();
|
||||||
|
dataptr = data.smallStringDataptr();
|
||||||
}
|
}
|
||||||
invariant(dataptr == data.mutableDataptr());
|
invariant(dataptr == data.data());
|
||||||
|
|
||||||
*dataptr = details;
|
*dataptr = details;
|
||||||
if (hasTenant) {
|
if (hasTenant) {
|
||||||
|
|
@ -688,17 +686,12 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
|
||||||
* Extracts the flags's byte from the _footer field.
|
|
||||||
*/
|
|
||||||
constexpr unsigned char getFlags() const {
|
constexpr unsigned char getFlags() const {
|
||||||
return absl::bit_cast<std::array<char, sizeof(size_t)>>(_footer)[sizeof(size_t) - 1];
|
return _flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* mutableDataptr() {
|
char* smallStringDataptr() {
|
||||||
if (isSmallString())
|
return reinterpret_cast<char*>(&_data);
|
||||||
return reinterpret_cast<char*>(&_data);
|
|
||||||
return const_cast<char*>(_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -707,23 +700,22 @@ protected:
|
||||||
void reset() {
|
void reset() {
|
||||||
_data = nullptr;
|
_data = nullptr;
|
||||||
_length = 0;
|
_length = 0;
|
||||||
setFooter(database_name::kSmallStringFlag, kDataOffset);
|
setFlags(database_name::kSmallStringFlag, kDataOffset);
|
||||||
|
clearPadding();
|
||||||
}
|
}
|
||||||
|
|
||||||
void deallocate() {
|
void deallocate() {
|
||||||
if (isDynamicAlloc() && _data != nullptr) {
|
if (isDynamicAlloc() && _data != nullptr) {
|
||||||
MONGO_COMPILER_DIAGNOSTIC_PUSH
|
|
||||||
MONGO_COMPILER_DIAGNOSTIC_IGNORED_TRANSITIONAL("-Wfree-nonheap-object")
|
|
||||||
delete[] _data;
|
delete[] _data;
|
||||||
MONGO_COMPILER_DIAGNOSTIC_POP
|
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Storage can work in three different mode (dynamic allocation, static allocation or
|
* Storage can work in three different modes (dynamic allocation, static allocation or
|
||||||
* small-string optimisation) depending on the flag bits (the last two bits of _footer) :
|
* small-string optimisation) depending on the flag bits (the two least significant bits of
|
||||||
* Flags value given by _footer[sizeof(_footer) - 1] & 0x00000011:
|
* _flags):
|
||||||
|
* Flags value given by _flags & 0b11:
|
||||||
* 0: the data is dynamically allocated.
|
* 0: the data is dynamically allocated.
|
||||||
* 1: the data is statically allocated.
|
* 1: the data is statically allocated.
|
||||||
* 2: the data is packed using the small string optimisation
|
* 2: the data is packed using the small string optimisation
|
||||||
|
|
@ -731,13 +723,13 @@ protected:
|
||||||
* When using static of dynamic allocation, _data is a pointer to the actual data and
|
* When using static of dynamic allocation, _data is a pointer to the actual data and
|
||||||
* _length contains its size.
|
* _length contains its size.
|
||||||
*
|
*
|
||||||
* When using the small string optimisation the data is packed in _data, _length and the
|
* When using the small string optimisation the data is packed in _data, _length and
|
||||||
* first sizeof(_footer)-1 bytes of _footer. The size of the data is contained in the first
|
* _padding. The size of the data is contained in 6 most significant bits of _flags.
|
||||||
* 6 bits of the last byte of _footer :
|
|
||||||
*/
|
*/
|
||||||
const char* _data;
|
const char* _data;
|
||||||
size_t _length;
|
size_t _length;
|
||||||
size_t _footer;
|
std::array<char, sizeof(size_t) - 1> _padding{};
|
||||||
|
unsigned char _flags;
|
||||||
};
|
};
|
||||||
Storage _data;
|
Storage _data;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue