diff --git a/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/page_store.cpp b/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/page_store.cpp index a551aa73a47..b41d7cc5889 100644 --- a/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/page_store.cpp +++ b/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/page_store.cpp @@ -26,7 +26,7 @@ class TPageStore: public IPageStore private: struct TPage { - TString Content; + TBuffer Content; ui64 Lsn = 0; bool Dirty = false; }; @@ -52,10 +52,10 @@ class TPageStore: public IPageStore NProto::TError WritePage( ui64 lsn, ui64 pageNo, - TString page, + TBuffer page, TVector& logRecord) override; NProto::TError - ReadPage(ui64 lsn, ui64 pageNo, TString* page) const override; + ReadPage(ui64 lsn, ui64 pageNo, TBuffer* page) const override; }; //////////////////////////////////////////////////////////////////////////////// @@ -89,7 +89,7 @@ void TPageStore::RollbackPages(const TVector& pages) NProto::TError TPageStore::WritePage( ui64 lsn, ui64 pageNo, - TString page, + TBuffer page, TVector& logRecord) { std::lock_guard g(Mutex); @@ -126,7 +126,7 @@ NProto::TError TPageStore::WritePage( if (!found) { logRecord.push_back( - {.FirstPageNo = pageNo, .Content = TVector({page})}); + {.FirstPageNo = pageNo, .Content = TVector({page})}); } // @@ -147,9 +147,9 @@ NProto::TError TPageStore::WritePage( return {}; } -NProto::TError TPageStore::ReadPage(ui64 lsn, ui64 pageNo, TString* page) const +NProto::TError TPageStore::ReadPage(ui64 lsn, ui64 pageNo, TBuffer* page) const { - page->clear(); + page->Clear(); TPageCache::iterator cachedPage; { @@ -185,7 +185,7 @@ NProto::TError TPageStore::ReadPage(ui64 lsn, ui64 pageNo, TString* page) const { std::lock_guard g(Mutex); - if (page->empty()) { + if (page->Empty()) { PageCache.erase(cachedPage); } else { cachedPage->second.Content = *page; @@ -231,11 +231,11 @@ NProto::TError TPageStore::ReadPage(ui64 lsn, ui64 pageNo, TString* page) const << "unexpected page count: " << rpg.Content.size()); } - if (rpg.Content[0].size() < PageSize) { + if (rpg.Content[0].Size() < PageSize) { return MakeError( E_BADMSG, TStringBuilder() - << "unexpected page size: " << rpg.Content[0].size()); + << "unexpected page size: " << rpg.Content[0].Size()); } *page = std::move(rpg.Content[0]); @@ -251,11 +251,12 @@ class TMemPageStore: public TPageStore : TPageStore(nullptr /* storage */, pageSize) {} - NProto::TError ReadPage(ui64 lsn, ui64 pageNo, TString* page) const override + NProto::TError ReadPage(ui64 lsn, ui64 pageNo, TBuffer* page) const override { auto error = TPageStore::ReadPage(lsn, pageNo, page); if (error.GetCode() == E_NOT_FOUND) { - *page = TString(PageSize, 0); + page->Clear(); + page->Fill(0, PageSize); return {}; } diff --git a/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/page_store.h b/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/page_store.h index a4fb334d3ae..2cd6942961c 100644 --- a/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/page_store.h +++ b/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/page_store.h @@ -3,6 +3,8 @@ #include #include +#include + #include namespace NCloud::NFileStore::NStorage::NFastShard { @@ -20,10 +22,10 @@ class IPageStore [[nodiscard]] virtual NProto::TError WritePage( ui64 lsn, ui64 pageNo, - TString page, + TBuffer page, TVector& logRecord) = 0; [[nodiscard]] virtual NProto::TError - ReadPage(ui64 lsn, ui64 pageNo, TString* page) const = 0; + ReadPage(ui64 lsn, ui64 pageNo, TBuffer* page) const = 0; }; using IPageStorePtr = std::shared_ptr; diff --git a/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/persistent_bitmap.cpp b/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/persistent_bitmap.cpp index f129af95c0b..9448a0432e0 100644 --- a/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/persistent_bitmap.cpp +++ b/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/persistent_bitmap.cpp @@ -11,12 +11,12 @@ namespace { constexpr ui64 InvalidBitNo = Max(); constexpr ui64 BitsPerWord = 64; -bool IsFull(const TString& bitmapPage) +bool IsFull(const TBuffer& bitmapPage) { - Y_ABORT_UNLESS(bitmapPage.size() % sizeof(ui64) == 0); + Y_ABORT_UNLESS(bitmapPage.Size() % sizeof(ui64) == 0); - for (ui64 i = 0; i < bitmapPage.size(); i += sizeof(ui64)) { - const ui64* word = reinterpret_cast(bitmapPage.data() + i); + for (ui64 i = 0; i < bitmapPage.Size(); i += sizeof(ui64)) { + const ui64* word = reinterpret_cast(bitmapPage.Data() + i); if (~*word != 0) { return false; } @@ -37,34 +37,34 @@ static ui16 PopCount(ui64 x) return byteSums * 0x0101010101010101ULL >> 56; } -ui64 PopCount(const TString& bitmapPage) +ui64 PopCount(const TBuffer& bitmapPage) { - Y_ABORT_UNLESS(bitmapPage.size() % sizeof(ui64) == 0); + Y_ABORT_UNLESS(bitmapPage.Size() % sizeof(ui64) == 0); ui64 c = 0; - for (ui64 i = 0; i < bitmapPage.size(); i += sizeof(ui64)) { - const ui64* word = reinterpret_cast(bitmapPage.data() + i); + for (ui64 i = 0; i < bitmapPage.Size(); i += sizeof(ui64)) { + const ui64* word = reinterpret_cast(bitmapPage.Data() + i); c += PopCount(*word); } return c; } -bool GetBit(TString& bitmapPage, ui64 bit) +bool GetBit(TBuffer& bitmapPage, ui64 bit) { - Y_ABORT_UNLESS(bitmapPage.size() % sizeof(ui64) == 0); + Y_ABORT_UNLESS(bitmapPage.Size() % sizeof(ui64) == 0); ui64* word = - reinterpret_cast(bitmapPage.begin()) + bit / BitsPerWord; + reinterpret_cast(bitmapPage.Data()) + bit / BitsPerWord; return (*word & (1ULL << (bit % BitsPerWord))) != 0; } -void SetBit(TString& bitmapPage, ui64 bit, bool isReset) +void SetBit(TBuffer& bitmapPage, ui64 bit, bool isReset) { - Y_ABORT_UNLESS(bitmapPage.size() % sizeof(ui64) == 0); + Y_ABORT_UNLESS(bitmapPage.Size() % sizeof(ui64) == 0); ui64* word = - reinterpret_cast(bitmapPage.begin()) + bit / BitsPerWord; + reinterpret_cast(bitmapPage.Data()) + bit / BitsPerWord; if (isReset) { *word &= ~(1ULL << (bit % BitsPerWord)); } else { @@ -72,12 +72,12 @@ void SetBit(TString& bitmapPage, ui64 bit, bool isReset) } } -ui64 FindFirstFreeBit(const TString& bitmapPage) +ui64 FindFirstFreeBit(const TBuffer& bitmapPage) { - Y_ABORT_UNLESS(bitmapPage.size() % sizeof(ui64) == 0); + Y_ABORT_UNLESS(bitmapPage.Size() % sizeof(ui64) == 0); - for (ui64 i = 0; i < bitmapPage.size(); i += sizeof(ui64)) { - const ui64* word = reinterpret_cast(bitmapPage.data() + i); + for (ui64 i = 0; i < bitmapPage.Size(); i += sizeof(ui64)) { + const ui64* word = reinterpret_cast(bitmapPage.Data() + i); if (~*word != 0) { return i * 8 + std::countr_one(*word); } @@ -237,7 +237,7 @@ NProto::TError TPersistentBitmap::InitIfNeeded() const return error; } - Y_ABORT_UNLESS(BitmapPages[i].size() == PageSize); + Y_ABORT_UNLESS(BitmapPages[i].Size() == PageSize); if (!IsFull(BitmapPages[i])) { BitmapPagesWithFreeBits.push(i); diff --git a/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/persistent_bitmap.h b/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/persistent_bitmap.h index 1e6ad85f996..a185705a864 100644 --- a/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/persistent_bitmap.h +++ b/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/persistent_bitmap.h @@ -4,6 +4,7 @@ #include +#include #include namespace NCloud::NFileStore::NStorage::NFastShard { @@ -19,7 +20,7 @@ class TPersistentBitmap const ui64 BitsPerPage; IPageStorePtr PageStore; - mutable TVector BitmapPages; + mutable TVector BitmapPages; mutable TStack BitmapPagesWithFreeBits; public: diff --git a/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/persistent_hash_table.h b/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/persistent_hash_table.h index 5244cb9368b..978f8869294 100644 --- a/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/persistent_hash_table.h +++ b/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/persistent_hash_table.h @@ -9,6 +9,7 @@ #include #include +#include #include namespace NCloud::NFileStore::NStorage::NFastShard { @@ -58,13 +59,13 @@ class TPersistentHashTable const ui64 SlotSize; const ui64 SlotCount; const ui64 SlotsPerPage; - TString Page; + TBuffer Page; bool Dirty = false; ui64 SlotNo; struct TDirtyPage { - TString Content; + TBuffer Content; ui64 PageNo = 0; }; @@ -140,7 +141,7 @@ class TPersistentHashTable [[nodiscard]] const char* GetRaw() const { const ui64 offsetInPage = (SlotNo % SlotsPerPage) * SlotSize; - return Page.data() + offsetInPage; + return Page.Data() + offsetInPage; } [[nodiscard]] const TValue& Get() const @@ -151,7 +152,7 @@ class TPersistentHashTable void Write(const char* data) { const ui64 offsetInPage = (SlotNo % SlotsPerPage) * SlotSize; - char* dst = Page.begin() + offsetInPage; + char* dst = Page.Data() + offsetInPage; memcpy(dst, data, sizeof(TValue)); dst += sizeof(TValue); const ui64 tail = SlotSize - sizeof(TValue); @@ -164,7 +165,7 @@ class TPersistentHashTable void Clear() { const ui64 offsetInPage = (SlotNo % SlotsPerPage) * SlotSize; - memset(Page.begin() + offsetInPage, 0, SlotSize); + memset(Page.Data() + offsetInPage, 0, SlotSize); Dirty = true; } @@ -310,7 +311,7 @@ class TPersistentHashTable [[nodiscard]] NProto::TError WritePage( ui64 lsn, ui64 slotNo, - TString page, + TBuffer page, TVector& pageGroups) { const ui64 pageNo = FirstPageNo + slotNo / SlotsPerPage; @@ -318,7 +319,7 @@ class TPersistentHashTable } [[nodiscard]] NProto::TError - ReadPage(ui64 lsn, ui64 slotNo, TString* page) const + ReadPage(ui64 lsn, ui64 slotNo, TBuffer* page) const { const ui64 pageNo = FirstPageNo + slotNo / SlotsPerPage; return PageStore->ReadPage(lsn, pageNo, page); @@ -337,14 +338,14 @@ class TPersistentHashTable [[nodiscard]] NProto::TError LookupSlot(ui64 lsn, ui64 slotNo, TValue* v) const { - TString page; + TBuffer page; auto error = ReadPage(lsn, slotNo, &page); if (HasError(error)) { return error; } const ui32 relSlotNo = slotNo % SlotsPerPage; - const char* ptr = page.data() + relSlotNo * SlotSize; + const char* ptr = page.Data() + relSlotNo * SlotSize; return LookupSlot(ptr, v) ? MakeError(S_OK) : MakeError(S_FALSE); } @@ -466,14 +467,14 @@ class TPersistentHashTable ui64 slotNo, TVector& pageGroups) { - TString page; + TBuffer page; auto error = ReadPage(lsn, slotNo, &page); if (HasError(error)) { return error; } const ui32 relSlotNo = slotNo % SlotsPerPage; - char* ptr = page.begin() + relSlotNo * SlotSize; + char* ptr = page.Data() + relSlotNo * SlotSize; memcpy(ptr, &v, sizeof(TValue)); error = WritePage(lsn, slotNo, std::move(page), pageGroups); diff --git a/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/shard.cpp b/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/shard.cpp index 584eac48eaa..b1c520745f0 100644 --- a/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/shard.cpp +++ b/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/shard.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -1832,7 +1833,7 @@ class TFiberShardImpl break; } - TString page; + TBuffer page; if (isUnalignedHead || isUnalignedTail) { error = PageStore->ReadPage( writeContext.Lsn, @@ -1846,7 +1847,7 @@ class TFiberShardImpl break; } } else { - page.ReserveAndResize(PageSize); + page.Resize(PageSize); } const ui64 offsetInPage = @@ -1856,7 +1857,7 @@ class TFiberShardImpl const ui64 toCopy = Min(pageEnd, endOffset) - (pageStart + offsetInPage); memcpy( - page.begin() + offsetInPage, + page.Data() + offsetInPage, request.GetBuffer().data() + bufferOffset, toCopy); @@ -2034,7 +2035,7 @@ class TFiberShardImpl break; } - TString page; + TBuffer page; error = PageStore->ReadPage(0 /* lsn */, storagePageNo, &page); if (HasError(error)) { @@ -2052,7 +2053,7 @@ class TFiberShardImpl Min(pageEnd, endOffset) - (pageStart + offsetInPage); memcpy( buffer.begin() + bufferOffset, - page.begin() + offsetInPage, + page.Data() + offsetInPage, toCopy); bufferOffset += toCopy; diff --git a/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/shard_ut_error.cpp b/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/shard_ut_error.cpp index d7c43717c3c..568ee0dab67 100644 --- a/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/shard_ut_error.cpp +++ b/cloud/filestore/libs/storage/fastshard/impl/naive_mirrored/shard_ut_error.cpp @@ -51,7 +51,13 @@ struct TTempError struct TTestStorageGroup: IStorageGroup { - TVector Pages{PageCount}; + // + // Deliberately not brace-initialized: TBuffer(size_t) is implicit, so + // {PageCount} would create a single buffer instead of PageCount empty + // pages. + // + + TVector Pages = TVector(PageCount); TTempError ReadError; TTempError WriteError; @@ -102,8 +108,8 @@ struct TTestStorageGroup: IStorageGroup pg.FirstPageNo = pgr.FirstPageNo; for (ui64 i = 0; i < pgr.PageCount; ++i) { pg.Content.push_back(Pages[pgr.FirstPageNo + i]); - if (pg.Content.back().empty()) { - pg.Content.back().resize(PageSize, 0); + if (pg.Content.back().Empty()) { + pg.Content.back().Fill(0, PageSize); } } } diff --git a/cloud/filestore/libs/storage/fastshard/sn/impl/storage_node.cpp b/cloud/filestore/libs/storage/fastshard/sn/impl/storage_node.cpp index 4c61771b60f..1fbdb09a5ca 100644 --- a/cloud/filestore/libs/storage/fastshard/sn/impl/storage_node.cpp +++ b/cloud/filestore/libs/storage/fastshard/sn/impl/storage_node.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -221,7 +222,7 @@ class TNaiveFileStorageNode: public IStorageNode ui64 FirstPageNo = 0; ui64 PageCount = 0; ui32 PageSize = 0; - TString Buffer; + TBuffer Buffer; iovec Iov{}; ui64 BytesRead = 0; FiberScheduler::IoFuture Future; @@ -242,9 +243,9 @@ class TNaiveFileStorageNode: public IStorageNode op.FirstPageNo = ref.GetFirstPageNo(); op.PageCount = ref.GetPageCount(); op.PageSize = ref.GetPageSize(); - op.Buffer.ReserveAndResize(op.PageCount * op.PageSize); - op.Iov.iov_base = op.Buffer.begin(); - op.Iov.iov_len = op.Buffer.size(); + op.Buffer.Resize(op.PageCount * op.PageSize); + op.Iov.iov_base = op.Buffer.Data(); + op.Iov.iov_len = op.Buffer.Size(); const ui64 offset = op.FirstPageNo * op.PageSize; FiberScheduler::read( fd, @@ -303,9 +304,9 @@ class TNaiveFileStorageNode: public IStorageNode auto* pg = resp.AddPageGroups(); pg->SetFirstPageNo(op.FirstPageNo); for (ui64 i = 0; i < op.PageCount; ++i) { - pg->AddContent(op.Buffer.substr( - static_cast(i) * op.PageSize, - op.PageSize)); + pg->AddContent()->assign( + op.Buffer.Data() + static_cast(i) * op.PageSize, + op.PageSize); } } return resp; diff --git a/cloud/filestore/libs/storage/fastshard/sn/quorum/storage_group.cpp b/cloud/filestore/libs/storage/fastshard/sn/quorum/storage_group.cpp index 5818a0d1014..73ea0009e91 100644 --- a/cloud/filestore/libs/storage/fastshard/sn/quorum/storage_group.cpp +++ b/cloud/filestore/libs/storage/fastshard/sn/quorum/storage_group.cpp @@ -104,8 +104,10 @@ class TStorageGroupImpl: public IStorageGroup auto* w = request.AddPageGroups(); w->SetFirstPageNo(pg.FirstPageNo); w->MutableContent()->Reserve(pg.Content.size()); - for (auto& c: pg.Content) { - *w->AddContent() = std::move(c); + for (const auto& c: pg.Content) { + // proto content is TString - the copy stays until the + // protocol itself switches away from TString + w->AddContent()->assign(c.Data(), c.Size()); } } SILK_DEBUG("sg write: %s", DebugMessage(request).c_str()); @@ -146,8 +148,8 @@ class TStorageGroupImpl: public IStorageGroup auto& r = pageGroups->emplace_back(); r.FirstPageNo = pg.GetFirstPageNo(); r.Content.reserve(pg.ContentSize()); - for (auto& c: *pg.MutableContent()) { - r.Content.emplace_back(std::move(c)); + for (const auto& c: pg.GetContent()) { + r.Content.emplace_back(c.data(), c.size()); } } } diff --git a/cloud/filestore/libs/storage/fastshard/sn/quorum/storage_group.h b/cloud/filestore/libs/storage/fastshard/sn/quorum/storage_group.h index 48f9d30a1d2..1829e896dd3 100644 --- a/cloud/filestore/libs/storage/fastshard/sn/quorum/storage_group.h +++ b/cloud/filestore/libs/storage/fastshard/sn/quorum/storage_group.h @@ -2,6 +2,7 @@ #include +#include #include #include @@ -20,7 +21,7 @@ struct TPageGroupRef struct TPageGroup { ui64 FirstPageNo = 0; - TVector Content; + TVector Content; }; /** diff --git a/cloud/filestore/libs/storage/fastshard/sn/quorum/storage_group_ut.cpp b/cloud/filestore/libs/storage/fastshard/sn/quorum/storage_group_ut.cpp index df565253d3a..76041442f66 100644 --- a/cloud/filestore/libs/storage/fastshard/sn/quorum/storage_group_ut.cpp +++ b/cloud/filestore/libs/storage/fastshard/sn/quorum/storage_group_ut.cpp @@ -120,10 +120,11 @@ TEST(NaiveGroupTest, MirrorsWrites) TStorageFixture fx; { - TVector pageGroups = {{ - .FirstPageNo = 111, - .Content = {"page1", "page2"}, - }}; + TPageGroup pageGroup{.FirstPageNo = 111}; + pageGroup.Content.emplace_back("page1", 5U /* len */); + pageGroup.Content.emplace_back("page2", 5U /* len */); + TVector pageGroups; + pageGroups.push_back(std::move(pageGroup)); auto error = fx.Group->WriteLogRecord( defaultHeaders, @@ -196,9 +197,10 @@ TEST(NaiveGroupTest, RoundRobinsRead) pageGroups[j].Content.size()); for (ui64 k = 0; k < pageGroups[j].Content.size(); ++k) { - EXPECT_STREQ( - epg.GetContent(k).c_str(), - pageGroups[j].Content[k].c_str()); + const auto& c = pageGroups[j].Content[k]; + EXPECT_EQ( + epg.GetContent(k), + TString(c.Data(), c.Size())); } } }