Skip to content

Commit fd5a3c7

Browse files
authored
feat(core): External representation enum (#5912)
1 parent 5bbaa0d commit fd5a3c7

File tree

4 files changed

+51
-19
lines changed

4 files changed

+51
-19
lines changed

src/core/compact_object.cc

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -875,9 +875,18 @@ uint64_t CompactObj::HashCode(string_view str) {
875875
}
876876

877877
CompactObjType CompactObj::ObjType() const {
878-
if (IsInline() || taglen_ == INT_TAG || taglen_ == SMALL_TAG || taglen_ == EXTERNAL_TAG)
878+
if (IsInline() || taglen_ == INT_TAG || taglen_ == SMALL_TAG)
879879
return OBJ_STRING;
880880

881+
if (taglen_ == EXTERNAL_TAG) {
882+
switch (static_cast<ExternalRep>(u_.ext_ptr.representation)) {
883+
case ExternalRep::STRING:
884+
return OBJ_STRING;
885+
case ExternalRep::SERIALIZED_MAP:
886+
return OBJ_HASH;
887+
};
888+
}
889+
881890
if (taglen_ == ROBJ_TAG)
882891
return u_.r_obj.type();
883892

@@ -1192,15 +1201,21 @@ void CompactObj::GetString(char* dest) const {
11921201
LOG(FATAL) << "Bad tag " << int(taglen_);
11931202
}
11941203

1195-
void CompactObj::SetExternal(size_t offset, uint32_t sz) {
1204+
void CompactObj::SetExternal(size_t offset, uint32_t sz, ExternalRep rep) {
11961205
SetMeta(EXTERNAL_TAG, mask_);
11971206

11981207
u_.ext_ptr.is_cool = 0;
1208+
u_.ext_ptr.representation = static_cast<uint8_t>(rep);
11991209
u_.ext_ptr.page_offset = offset % 4096;
12001210
u_.ext_ptr.serialized_size = sz;
12011211
u_.ext_ptr.offload.page_index = offset / 4096;
12021212
}
12031213

1214+
CompactObj::ExternalRep CompactObj::GetExternalRep() const {
1215+
DCHECK(IsExternal());
1216+
return static_cast<CompactObj::ExternalRep>(u_.ext_ptr.representation);
1217+
}
1218+
12041219
void CompactObj::SetCool(size_t offset, uint32_t sz, detail::TieredColdRecord* record) {
12051220
// We copy the mask of the "cooled" referenced object because it contains the encoding info.
12061221
SetMeta(EXTERNAL_TAG, record->value.mask_);
@@ -1221,24 +1236,17 @@ auto CompactObj::GetCool() const -> CoolItem {
12211236
return res;
12221237
}
12231238

1224-
void CompactObj::ImportExternal(const CompactObj& src) {
1225-
DCHECK(src.IsExternal());
1226-
uint8_t encoding = src.mask_bits_.encoding;
1227-
SetMeta(EXTERNAL_TAG, 0);
1228-
mask_bits_.encoding = encoding;
1229-
u_.ext_ptr = src.u_.ext_ptr;
1230-
}
1231-
12321239
std::pair<size_t, size_t> CompactObj::GetExternalSlice() const {
12331240
DCHECK_EQ(EXTERNAL_TAG, taglen_);
12341241
auto& ext = u_.ext_ptr;
12351242
size_t offset = ext.page_offset;
12361243
offset += size_t(ext.is_cool ? ext.cool_record->page_index : ext.offload.page_index) * 4096;
1237-
return pair<size_t, size_t>(offset, size_t(u_.ext_ptr.serialized_size));
1244+
return {offset, size_t(u_.ext_ptr.serialized_size)};
12381245
}
12391246

12401247
void CompactObj::Materialize(std::string_view blob, bool is_raw) {
12411248
CHECK(IsExternal()) << int(taglen_);
1249+
DCHECK_EQ(u_.ext_ptr.representation, static_cast<uint8_t>(ExternalRep::STRING));
12421250

12431251
DCHECK_GT(blob.size(), kInlineLen);
12441252

src/core/compact_object.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,12 @@ class CompactObj {
160160
using PrefixArray = std::vector<std::string_view>;
161161
using MemoryResource = detail::RobjWrapper::MemoryResource;
162162

163+
// Different representations of external values
164+
enum class ExternalRep : uint8_t {
165+
STRING, // OBJ_STRING, Basic representation with various string encodings
166+
SERIALIZED_MAP // OBJ_HASH, Serialized map
167+
};
168+
163169
CompactObj() { // By default - empty string.
164170
}
165171

@@ -348,7 +354,8 @@ class CompactObj {
348354
return u_.ext_ptr.is_cool;
349355
}
350356

351-
void SetExternal(size_t offset, uint32_t sz);
357+
void SetExternal(size_t offset, uint32_t sz, ExternalRep rep);
358+
ExternalRep GetExternalRep() const;
352359

353360
// Switches to empty, non-external string.
354361
// Preserves all the attributes.
@@ -369,8 +376,6 @@ class CompactObj {
369376
// Returns the external data of the object incuding its ColdRecord.
370377
CoolItem GetCool() const;
371378

372-
void ImportExternal(const CompactObj& src);
373-
374379
std::pair<size_t, size_t> GetExternalSlice() const;
375380

376381
// Injects either the the raw string (extracted with GetRawString()) or the usual string
@@ -466,8 +471,9 @@ class CompactObj {
466471
struct ExternalPtr {
467472
uint32_t serialized_size;
468473
uint16_t page_offset; // 0 for multi-page blobs. != 0 for small blobs.
469-
uint16_t is_cool : 1;
470-
uint16_t is_reserved : 15;
474+
uint8_t is_cool : 1;
475+
uint8_t representation : 2; // See ExternalRep
476+
uint16_t is_reserved : 13;
471477

472478
// We do not have enough space in the common area to store page_index together with
473479
// cool_record pointer. Therefore, we moved this field into TieredColdRecord itself.

src/core/compact_object_test.cc

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "core/huff_coder.h"
1818
#include "core/mi_memory_resource.h"
1919
#include "core/page_usage_stats.h"
20+
#include "core/string_map.h"
2021
#include "core/string_or_view.h"
2122
#include "core/string_set.h"
2223

@@ -616,13 +617,29 @@ TEST_F(CompactObjectTest, StrEncodingAndMaterialize) {
616617
EXPECT_EQ(test_str, enc.Decode(raw_str).Take());
617618

618619
// Test Materialize
619-
obj.SetExternal(0, 0); // dummy values
620+
obj.SetExternal(0, 0, CompactObj::ExternalRep::STRING); // dummy values
620621
obj.Materialize(raw_str, true);
621622
EXPECT_EQ(test_str, obj.ToString());
622623
}
623624
}
624625
}
625626

627+
TEST_F(CompactObjectTest, ExternalRepresentation) {
628+
{
629+
CompactObj obj;
630+
obj.SetString("test", false);
631+
obj.SetExternal(0, 4, CompactObj::ExternalRep::STRING);
632+
EXPECT_EQ(obj.ObjType(), OBJ_STRING);
633+
}
634+
{
635+
StringMap sm{};
636+
CompactObj obj;
637+
obj.SetRObjPtr(&sm);
638+
obj.SetExternal(0, 4, CompactObj::ExternalRep::SERIALIZED_MAP);
639+
EXPECT_EQ(obj.ObjType(), OBJ_HASH);
640+
}
641+
}
642+
626643
TEST_F(CompactObjectTest, AsanTriggerReadOverflow) {
627644
cobj_.SetString(string(32, 'a'), false);
628645
auto dest = make_unique<char[]>(32);

src/server/tiered_storage.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ class TieredStorage::ShardOpManager : public tiering::OpManager {
134134
// Set value to be an in-memory type again. Update memory stats.
135135
void Upload(DbIndex dbid, string_view value, bool is_raw, size_t serialized_len, PrimeValue* pv) {
136136
DCHECK(!value.empty());
137+
DCHECK_EQ(uint8_t(pv->GetExternalRep()), uint8_t(CompactObj::ExternalRep::STRING));
137138

138139
pv->Materialize(value, is_raw);
139140
RecordDeleted(*pv, serialized_len, GetDbTableStats(dbid));
@@ -155,7 +156,7 @@ class TieredStorage::ShardOpManager : public tiering::OpManager {
155156
ts_->CoolDown(key.first, key.second, segment, pv);
156157
} else {
157158
stats->AddTypeMemoryUsage(pv->ObjType(), -pv->MallocUsed());
158-
pv->SetExternal(segment.offset, segment.length);
159+
pv->SetExternal(segment.offset, segment.length, CompactObj::ExternalRep::STRING);
159160
}
160161
} else {
161162
LOG(DFATAL) << "Should not reach here";
@@ -542,7 +543,7 @@ size_t TieredStorage::ReclaimMemory(size_t goal) {
542543
tiering::DiskSegment segment = FromCoolItem(pv.GetCool());
543544

544545
// Now the item is only in storage.
545-
pv.SetExternal(segment.offset, segment.length);
546+
pv.SetExternal(segment.offset, segment.length, CompactObj::ExternalRep::STRING);
546547

547548
auto* stats = op_manager_->GetDbTableStats(record->db_index);
548549
stats->AddTypeMemoryUsage(record->value.ObjType(), -record->value.MallocUsed());

0 commit comments

Comments
 (0)