diff options
author | snaury <snaury@ydb.tech> | 2023-06-29 17:56:56 +0300 |
---|---|---|
committer | snaury <snaury@ydb.tech> | 2023-06-29 17:56:56 +0300 |
commit | 15ab94c3c74d7eeb15e99fc5ac7c33f8c17bf62f (patch) | |
tree | 3ed290eb3d004d0805266280123db58774e3bf7c | |
parent | 47548c73c08693b554c78ee16069c628553abb8b (diff) | |
download | ydb-15ab94c3c74d7eeb15e99fc5ac7c33f8c17bf62f.tar.gz |
Use unaligned read/write for page labels, fix ubsan failures
-rw-r--r-- | ydb/core/tablet_flat/flat_bloom_writer.h | 7 | ||||
-rw-r--r-- | ydb/core/tablet_flat/flat_page_data.h | 4 | ||||
-rw-r--r-- | ydb/core/tablet_flat/flat_page_gstat.h | 4 | ||||
-rw-r--r-- | ydb/core/tablet_flat/flat_page_index.h | 4 | ||||
-rw-r--r-- | ydb/core/tablet_flat/flat_page_label.cpp | 64 | ||||
-rw-r--r-- | ydb/core/tablet_flat/flat_page_label.h | 40 | ||||
-rw-r--r-- | ydb/core/tablet_flat/flat_page_other.h | 12 | ||||
-rw-r--r-- | ydb/core/tablet_flat/flat_page_txidstat.h | 4 | ||||
-rw-r--r-- | ydb/core/tablet_flat/flat_page_txstatus.h | 4 | ||||
-rw-r--r-- | ydb/core/tablet_flat/flat_page_writer.h | 19 | ||||
-rw-r--r-- | ydb/core/tablet_flat/flat_part_dump.cpp | 13 | ||||
-rw-r--r-- | ydb/core/tablet_flat/flat_part_writer.h | 12 | ||||
-rw-r--r-- | ydb/core/tablet_flat/test/libs/table/test_store.h | 4 | ||||
-rw-r--r-- | ydb/core/tablet_flat/ut/ut_comp_gen.cpp | 2 |
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); |