aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsnaury <snaury@ydb.tech>2023-06-29 17:56:56 +0300
committersnaury <snaury@ydb.tech>2023-06-29 17:56:56 +0300
commit15ab94c3c74d7eeb15e99fc5ac7c33f8c17bf62f (patch)
tree3ed290eb3d004d0805266280123db58774e3bf7c
parent47548c73c08693b554c78ee16069c628553abb8b (diff)
downloadydb-15ab94c3c74d7eeb15e99fc5ac7c33f8c17bf62f.tar.gz
Use unaligned read/write for page labels, fix ubsan failures
-rw-r--r--ydb/core/tablet_flat/flat_bloom_writer.h7
-rw-r--r--ydb/core/tablet_flat/flat_page_data.h4
-rw-r--r--ydb/core/tablet_flat/flat_page_gstat.h4
-rw-r--r--ydb/core/tablet_flat/flat_page_index.h4
-rw-r--r--ydb/core/tablet_flat/flat_page_label.cpp64
-rw-r--r--ydb/core/tablet_flat/flat_page_label.h40
-rw-r--r--ydb/core/tablet_flat/flat_page_other.h12
-rw-r--r--ydb/core/tablet_flat/flat_page_txidstat.h4
-rw-r--r--ydb/core/tablet_flat/flat_page_txstatus.h4
-rw-r--r--ydb/core/tablet_flat/flat_page_writer.h19
-rw-r--r--ydb/core/tablet_flat/flat_part_dump.cpp13
-rw-r--r--ydb/core/tablet_flat/flat_part_writer.h12
-rw-r--r--ydb/core/tablet_flat/test/libs/table/test_store.h4
-rw-r--r--ydb/core/tablet_flat/ut/ut_comp_gen.cpp2
14 files changed, 101 insertions, 92 deletions
diff --git a/ydb/core/tablet_flat/flat_bloom_writer.h b/ydb/core/tablet_flat/flat_bloom_writer.h
index 9884d602dd6..b0b91f01b6c 100644
--- a/ydb/core/tablet_flat/flat_bloom_writer.h
+++ b/ydb/core/tablet_flat/flat_bloom_writer.h
@@ -81,11 +81,8 @@ namespace NBloom {
NUtil::NBin::TPut out(Raw.mutable_begin());
- if (auto *hdr = out.Skip<NPage::TLabel>()) {
- hdr->Type = NPage::EPage::Bloom;
- hdr->Format = 0;
- hdr->Size = size;
- }
+ WriteUnaligned<NPage::TLabel>(out.Skip<NPage::TLabel>(),
+ NPage::TLabel::Encode(NPage::EPage::Bloom, 0, size));
if (auto *post = out.Skip<THeader>()) {
Zero(*post);
diff --git a/ydb/core/tablet_flat/flat_page_data.h b/ydb/core/tablet_flat/flat_page_data.h
index a37c4bf75ba..cef621b3f2e 100644
--- a/ydb/core/tablet_flat/flat_page_data.h
+++ b/ydb/core/tablet_flat/flat_page_data.h
@@ -175,9 +175,9 @@ namespace NPage {
Set(raw);
}
- const auto* Label() const noexcept
+ NPage::TLabel Label() const noexcept
{
- return TDeref<const NPage::TLabel>::At(Raw.data());
+ return ReadUnaligned<NPage::TLabel>(Raw.data());
}
explicit operator bool() const noexcept
diff --git a/ydb/core/tablet_flat/flat_page_gstat.h b/ydb/core/tablet_flat/flat_page_gstat.h
index d5eff46141c..6890ba3151d 100644
--- a/ydb/core/tablet_flat/flat_page_gstat.h
+++ b/ydb/core/tablet_flat/flat_page_gstat.h
@@ -211,9 +211,7 @@ namespace NPage {
NUtil::NBin::TPut out(buf.mutable_begin());
- if (auto* label = out.Skip<NPage::TLabel>()) {
- label->Init(EPage::GarbageStats, 0, pageSize);
- }
+ WriteUnaligned<TLabel>(out.Skip<TLabel>(), TLabel::Encode(EPage::GarbageStats, 0, pageSize));
if (auto* header = out.Skip<THeader>()) {
Zero(*header);
diff --git a/ydb/core/tablet_flat/flat_page_index.h b/ydb/core/tablet_flat/flat_page_index.h
index c0b50a5843c..49ee1d9aa43 100644
--- a/ydb/core/tablet_flat/flat_page_index.h
+++ b/ydb/core/tablet_flat/flat_page_index.h
@@ -85,9 +85,9 @@ namespace NPage {
return &Page;
}
- const auto* Label() const noexcept
+ NPage::TLabel Label() const noexcept
{
- return TDeref<const NPage::TLabel>::At(Raw.data(), 0);
+ return ReadUnaligned<NPage::TLabel>(Raw.data());
}
TIter Rewind(TRowId to, TIter on, int dir) const
diff --git a/ydb/core/tablet_flat/flat_page_label.cpp b/ydb/core/tablet_flat/flat_page_label.cpp
index 894722e1f3d..9cfe54b64dc 100644
--- a/ydb/core/tablet_flat/flat_page_label.cpp
+++ b/ydb/core/tablet_flat/flat_page_label.cpp
@@ -2,59 +2,47 @@
#include "util_deref.h"
#include <util/system/sanitizers.h>
+#include <util/system/unaligned_mem.h>
namespace NKikimr {
namespace NTable {
namespace NPage {
- void TLabel::Init(EPage type, ui16 format, ui64 size) noexcept {
- Type = type;
- Format = format;
- SetSize(size);
- }
-
- void TLabel::SetSize(ui64 size) noexcept {
- // We use Max<ui32>() as a huge (>=4GB) page marker
- Size = Y_LIKELY(size < Max<ui32>()) ? ui32(size) : Max<ui32>();
- }
-
TLabelWrapper::TResult TLabelWrapper::Read(TArrayRef<const char> raw, EPage type) const noexcept
{
- auto label = TDeref<TLabel>::Copy(raw.begin(), 0);
-
- if (raw.size() < 8) {
- Y_FAIL("NPage blob is too small to hold label");
- } else if (label.Type != type && type != EPage::Undef) {
- Y_FAIL("NPage blob has an unexpected label type");
- } else if (label.Size != raw.size() && label.Size != Max<ui32>()) {
- Y_FAIL("NPage label size doesn't match data size");
- } else if (label.Size == Max<ui32>()) {
- Y_VERIFY(raw.size() >= Max<ui32>(), "NPage label huge page marker doesn't match data size");
+ Y_VERIFY(raw.size() >= sizeof(TLabel), "Page blob is too small to hold label");
+
+ auto label = ReadUnaligned<TLabel>(raw.data());
+
+ Y_VERIFY(label.Type == type || type == EPage::Undef,
+ "Page blob has an unexpected label type");
+
+ if (Y_UNLIKELY(label.IsHuge())) {
+ Y_VERIFY(raw.size() >= Max<ui32>(), "Page label huge page marker doesn't match data size");
+ } else {
+ Y_VERIFY(label.Size == raw.size(), "Page label size doesn't match data size");
}
const ui16 version = label.Format & 0x7fff;
- if (label.Format & 0x8000) {
- /* New style NPage label, has at least extra 8 bytes, the
+ ECodec codec = ECodec::Plain;
+
+ auto* begin = raw.begin() + sizeof(TLabel);
+
+ if (label.IsExtended()) {
+ /* New style NPage label, has at least 8 extra bytes, the
current impl use only 1st byte. Futher is reserved for
in-place crc (may be) or other pages common metadata.
*/
- // this ugly construct is just to get ui8 at raw.begin() + sizeof(TLabel)
- auto codec = ECodec(*TDeref<ui8>::At(TDeref<TLabel>::At(raw.begin(), 0) + 1, 0));
-
- auto *on = raw.begin() + sizeof(TLabel) + 8;
-
- return { label.Type, version, codec, { on, raw.end() } };
+ Y_VERIFY(raw.size() >= sizeof(TLabel) + sizeof(TLabelExt), "Page extended label doesn't match data size");
- } else {
- /* old style NPage label, has no any extra attached data */
-
- auto *on = raw.begin() + sizeof(TLabel);
-
- return
- { label.Type, version, ECodec::Plain, { on, raw.end() } };
+ auto ext = ReadUnaligned<TLabelExt>(begin);
+ codec = ext.Codec;
+ begin += sizeof(TLabelExt);
}
+
+ return { label.Type, version, codec, { begin, raw.end() } };
}
TSharedData TLabelWrapper::Wrap(TArrayRef<const char> plain, EPage page, ui16 version) noexcept
@@ -63,7 +51,7 @@ namespace NPage {
TSharedData blob = TSharedData::Uninitialized(plain.size() + 8);
- TDeref<TLabel>::At(blob.mutable_begin(), 0)->Init(page, version, blob.size());
+ WriteUnaligned<TLabel>(blob.mutable_begin(), TLabel::Encode(page, version, blob.size()));
std::copy(plain.begin(), plain.end(), blob.mutable_begin() + 8);
@@ -78,7 +66,7 @@ namespace NPage {
TString blob = TString::Uninitialized(plain.size() + 8);
- TDeref<TLabel>::At(blob.begin(), 0)->Init(page, version, blob.size());
+ WriteUnaligned<TLabel>(blob.begin(), TLabel::Encode(page, version, blob.size()));
std::copy(plain.begin(), plain.end(), blob.begin() + 8);
diff --git a/ydb/core/tablet_flat/flat_page_label.h b/ydb/core/tablet_flat/flat_page_label.h
index 4a04c1f7c3e..36453fecd18 100644
--- a/ydb/core/tablet_flat/flat_page_label.h
+++ b/ydb/core/tablet_flat/flat_page_label.h
@@ -23,12 +23,48 @@ namespace NPage {
ui16 Format; // most significant bit is format indicator, the rest is version
TSize Size;
- void Init(EPage type, ui16 format, ui64 size) noexcept;
- void SetSize(ui64 size) noexcept;
+ bool IsExtended() const noexcept {
+ return Format & 0x8000;
+ }
+
+ bool IsHuge() const noexcept {
+ return Size == Max<ui32>();
+ }
+
+ static TLabel Encode(EPage type, ui16 format, ui64 size) noexcept {
+ TSize lsize;
+
+ if (Y_UNLIKELY(size >> 32)) {
+ // This size is used as a huge page marker
+ lsize = Max<ui32>();
+ } else {
+ lsize = TSize(size);
+ }
+
+ return TLabel{
+ .Type = type,
+ .Format = format,
+ .Size = lsize,
+ };
+ }
};
static_assert(sizeof(TLabel) == 8, "Invalid page TLabel unit");
+ struct TLabelExt {
+ ECodec Codec;
+ char Reserved[7];
+
+ static TLabelExt Encode(ECodec codec) noexcept {
+ return TLabelExt{
+ .Codec = codec,
+ .Reserved = {},
+ };
+ }
+ };
+
+ static_assert(sizeof(TLabelExt) == 8, "Invalid page TLabelExt size");
+
struct TLabelWrapper {
struct TResult {
bool operator==(NPage::ECodec codec) const noexcept
diff --git a/ydb/core/tablet_flat/flat_page_other.h b/ydb/core/tablet_flat/flat_page_other.h
index 51e5e9f6589..147097957f4 100644
--- a/ydb/core/tablet_flat/flat_page_other.h
+++ b/ydb/core/tablet_flat/flat_page_other.h
@@ -90,11 +90,7 @@ namespace NPage {
NUtil::NBin::TPut out(buf.mutable_begin());
- if (auto *hdr = out.Skip<NPage::TLabel>()) {
- hdr->Type = EPage::Frames;
- hdr->Format = 0;
- hdr->Size = size;
- }
+ WriteUnaligned<TLabel>(out.Skip<TLabel>(), TLabel::Encode(EPage::Frames, 0, size));
if (auto *post = out.Skip<THeader>()) {
Zero(*post);
@@ -183,11 +179,7 @@ namespace NPage {
NUtil::NBin::TPut out(buf.mutable_begin());
- if (auto *hdr = out.Skip<NPage::TLabel>()) {
- hdr->Type = EPage::Globs;
- hdr->Format = 1;
- hdr->Size = size < Max<ui32>() ? ui32(size) : Max<ui32>();
- }
+ WriteUnaligned<TLabel>(out.Skip<TLabel>(), TLabel::Encode(EPage::Globs, 1, size));
if (auto *post = out.Skip<THeader>()) {
Zero(*post);
diff --git a/ydb/core/tablet_flat/flat_page_txidstat.h b/ydb/core/tablet_flat/flat_page_txidstat.h
index e58cda5c48f..05a3d1c5570 100644
--- a/ydb/core/tablet_flat/flat_page_txidstat.h
+++ b/ydb/core/tablet_flat/flat_page_txidstat.h
@@ -114,9 +114,7 @@ namespace NPage {
NUtil::NBin::TPut out(buf.mutable_begin());
- if (auto* label = out.Skip<TLabel>()) {
- label->Init(EPage::TxIdStats, 0, pageSize);
- }
+ WriteUnaligned<TLabel>(out.Skip<TLabel>(), TLabel::Encode(EPage::TxIdStats, 0, pageSize));
if (auto* header = out.Skip<THeader>()) {
header->ItemCount = txIdList.size();
diff --git a/ydb/core/tablet_flat/flat_page_txstatus.h b/ydb/core/tablet_flat/flat_page_txstatus.h
index b7c99392a4b..2e4e7274d06 100644
--- a/ydb/core/tablet_flat/flat_page_txstatus.h
+++ b/ydb/core/tablet_flat/flat_page_txstatus.h
@@ -155,9 +155,7 @@ namespace NPage {
NUtil::NBin::TPut out(buf.mutable_begin());
- if (auto* label = out.Skip<TLabel>()) {
- label->Init(EPage::TxStatus, 0, pageSize);
- }
+ WriteUnaligned<TLabel>(out.Skip<TLabel>(), TLabel::Encode(EPage::TxStatus, 0, pageSize));
if (auto* header = out.Skip<THeader>()) {
header->CommittedCount = CommittedItems.size();
diff --git a/ydb/core/tablet_flat/flat_page_writer.h b/ydb/core/tablet_flat/flat_page_writer.h
index 3c8f02aad63..6e9fcea1f10 100644
--- a/ydb/core/tablet_flat/flat_page_writer.h
+++ b/ydb/core/tablet_flat/flat_page_writer.h
@@ -23,7 +23,7 @@ namespace NPage {
, Version(version)
, V2Label(label)
, Extra(extra)
- , Prefix(sizeof(TLabel) + (label ? 8 : 0) + sizeof(TRecordsHeader) + Extra)
+ , Prefix(sizeof(TLabel) + (label ? sizeof(TLabelExt) : 0) + sizeof(TRecordsHeader) + Extra)
{
Y_VERIFY((version & 0x8000) == 0, "Invalid version value");
}
@@ -82,15 +82,14 @@ namespace NPage {
char *ptr = Blob.mutable_begin();
- if (auto *label = TDeref<NPage::TLabel>::At(ptr, 0)) {
- label->Init(Type, Version, Blob.size());
-
- if (V2Label) {
- label->Format |= 0x8000;
- *TDeref<ui8>::At(label + 1, 0) = 0; /* page as-is */
- }
-
- ptr += sizeof(NPage::TLabel) + (V2Label ? 8 : 0);
+ if (V2Label) {
+ WriteUnaligned<NPage::TLabel>(ptr, TLabel::Encode(Type, Version | 0x8000, Blob.size()));
+ ptr += sizeof(TLabel);
+ WriteUnaligned<NPage::TLabelExt>(ptr, TLabelExt::Encode(ECodec::Plain));
+ ptr += sizeof(TLabelExt);
+ } else {
+ WriteUnaligned<NPage::TLabel>(ptr, TLabel::Encode(Type, Version, Blob.size()));
+ ptr += sizeof(TLabel);
}
if (auto *hdr = TDeref<TRecordsHeader>::At(ptr, 0)) {
diff --git a/ydb/core/tablet_flat/flat_part_dump.cpp b/ydb/core/tablet_flat/flat_part_dump.cpp
index 44f7da969a4..3604dba6991 100644
--- a/ydb/core/tablet_flat/flat_part_dump.cpp
+++ b/ydb/core/tablet_flat/flat_part_dump.cpp
@@ -90,13 +90,13 @@ namespace {
{
Key.reserve(part.Scheme->Groups[0].KeyTypes.size());
- auto *label = part.Index.Label();
+ auto label = part.Index.Label();
const auto items = (part.Index->End() - part.Index->Begin());
Out
- << " + Index{" << (ui16)label->Type << " rev "
- << label->Format << ", " << label->Size << "b}"
+ << " + Index{" << (ui16)label.Type << " rev "
+ << label.Format << ", " << label.Size << "b}"
<< " " << items << " rec" << Endl
<< " | Page Row Bytes (";
@@ -145,10 +145,11 @@ namespace {
// TODO: need to join with other column groups
auto data = NPage::TDataPage(Env->TryGetPage(&part, page));
- if (auto *label = data.Label()) {
+ if (data) {
+ auto label = data.Label();
Out
- << " + Rows{" << page << "} Label{" << page << (ui16)label->Type
- << " rev " << label->Format << ", " << label->Size << "b}"
+ << " + Rows{" << page << "} Label{" << page << (ui16)label.Type
+ << " rev " << label.Format << ", " << label.Size << "b}"
<< ", [" << data.BaseRow() << ", +" << data->Records << ")row"
<< Endl;
diff --git a/ydb/core/tablet_flat/flat_part_writer.h b/ydb/core/tablet_flat/flat_part_writer.h
index bc3bb0e27a4..6239466a2a6 100644
--- a/ydb/core/tablet_flat/flat_part_writer.h
+++ b/ydb/core/tablet_flat/flat_part_writer.h
@@ -829,14 +829,16 @@ namespace NTable {
if (!force && out.size() + (page.size() >> 3) > page.size()) {
return { }; /* Compressed page is almost the same in size */
} else {
- std::copy(page.begin(), page.begin() + 16, out.mutable_begin());
+ auto label = ReadUnaligned<NPage::TLabel>(page.begin());
- auto *label = TDeref<NPage::TLabel>::At(out.mutable_begin(), 0);
- label->SetSize(out.size());
+ Y_VERIFY(label.IsExtended(), "Expected an extended label");
- *TDeref<ui8>::At(label + 1, 0) = ui8(ECodec::LZ4);
+ auto ext = ReadUnaligned<NPage::TLabelExt>(page.begin() + 8);
- Y_VERIFY(label->Format & 0x8000, "Unexpected label version");
+ ext.Codec = ECodec::LZ4;
+
+ WriteUnaligned<NPage::TLabel>(out.mutable_begin(), NPage::TLabel::Encode(label.Type, label.Format, out.size()));
+ WriteUnaligned<NPage::TLabelExt>(out.mutable_begin() + 8, ext);
NSan::CheckMemIsInitialized(out.data(), out.size());
diff --git a/ydb/core/tablet_flat/test/libs/table/test_store.h b/ydb/core/tablet_flat/test/libs/table/test_store.h
index 0ea1c7192bb..2847ecbbd5b 100644
--- a/ydb/core/tablet_flat/test/libs/table/test_store.h
+++ b/ydb/core/tablet_flat/test/libs/table/test_store.h
@@ -160,9 +160,9 @@ namespace NTest {
TSharedData to = TSharedData::Uninitialized(label.Size);
- *TDeref<NPage::TLabel>::At(to.mutable_begin(), 0) = label;
+ WriteUnaligned<NPage::TLabel>(to.mutable_begin(), label);
- auto *begin = TDeref<char>::At(to.mutable_begin(), sizeof(label));
+ auto *begin = to.mutable_begin() + sizeof(NPage::TLabel);
got = in.Load(begin, to.mutable_end() - begin);
diff --git a/ydb/core/tablet_flat/ut/ut_comp_gen.cpp b/ydb/core/tablet_flat/ut/ut_comp_gen.cpp
index d9d5c194a0f..45febc18efe 100644
--- a/ydb/core/tablet_flat/ut/ut_comp_gen.cpp
+++ b/ydb/core/tablet_flat/ut/ut_comp_gen.cpp
@@ -40,7 +40,7 @@ Y_UNIT_TEST_SUITE(TGenCompaction) {
TCompactionPolicy policy;
// almost randome values except forceCountToCompact = 1 and forceSizeToCompact = 100 GB
- TCompactionPolicy::TGenerationPolicy genPolicy(1, 1, 1, 10*1024*1024*1024, "whoknows", true);
+ TCompactionPolicy::TGenerationPolicy genPolicy(1, 1, 1, 10ULL*1024*1024*1024, "whoknows", true);
for (size_t i = 0; i < 5; ++i) {
policy.Generations.push_back(genPolicy);