diff --git a/cloud/storage/core/libs/common/persistent_table.h b/cloud/storage/core/libs/common/persistent_table.h index ea7c28fbae..b749fb72aa 100644 --- a/cloud/storage/core/libs/common/persistent_table.h +++ b/cloud/storage/core/libs/common/persistent_table.h @@ -145,48 +145,7 @@ class TPersistentTable : FileName(fileName) , RecordCount(initialRecordCount) { - // if file doesn't exist create file with zeroed header - TFile file(FileName, OpenAlways | WrOnly); - if (file.GetLength() == 0) { - file.Resize(CalcFileSize(0)); - } - file.Close(); - - FileMap = std::make_unique(FileName, TMemoryMapCommon::oRdWr); - FileMap->Map(0, sizeof(THeader)); - - auto* header = reinterpret_cast(FileMap->Ptr()); - if (header->RecordCount == 0) { - header->Version = Version; - header->RecordCount = RecordCount; - header->HeaderSize = sizeof(THeader); - header->RecordSize = sizeof(TRecord); - header->CompactedRecordSrcIndex = InvalidIndex; - header->CompactedRecordDstIndex = InvalidIndex; - } - - Y_ABORT_UNLESS( - header->Version == Version, - "Invalid header version %d", - header->Version); - Y_ABORT_UNLESS( - header->HeaderSize == sizeof(THeader), - "Invalid header size %lu != %lu", - header->HeaderSize, - sizeof(THeader)); - Y_ABORT_UNLESS( - header->RecordSize == sizeof(TRecord), - "Invalid record size %lu != %lu", - header->RecordSize, - sizeof(TRecord)); - - RecordCount = header->RecordCount; - - FileMap->ResizeAndRemap(0, CalcFileSize(RecordCount)); - HeaderPtr = reinterpret_cast(FileMap->Ptr()); - RecordsPtr = reinterpret_cast(HeaderPtr + 1); - - CompactRecords(); + Init(); } H* HeaderData() @@ -240,7 +199,61 @@ class TPersistentTable return NextFreeRecord - FreeRecords.size(); } + void Clear() + { + NextFreeRecord = 0; + FileMap.reset(); + FreeRecords.clear(); + Init(); + } + private: + void Init() + { + // if file doesn't exist create file with zeroed header + TFile file(FileName, OpenAlways | WrOnly); + if (file.GetLength() == 0) { + file.Resize(CalcFileSize(0)); + } + file.Close(); + + FileMap = std::make_unique(FileName, TMemoryMapCommon::oRdWr); + FileMap->Map(0, sizeof(THeader)); + + auto* header = reinterpret_cast(FileMap->Ptr()); + if (header->RecordCount == 0) { + header->Version = Version; + header->RecordCount = RecordCount; + header->HeaderSize = sizeof(THeader); + header->RecordSize = sizeof(TRecord); + header->CompactedRecordSrcIndex = InvalidIndex; + header->CompactedRecordDstIndex = InvalidIndex; + } + + Y_ABORT_UNLESS( + header->Version == Version, + "Invalid header version %d", + header->Version); + Y_ABORT_UNLESS( + header->HeaderSize == sizeof(THeader), + "Invalid header size %lu != %lu", + header->HeaderSize, + sizeof(THeader)); + Y_ABORT_UNLESS( + header->RecordSize == sizeof(TRecord), + "Invalid record size %lu != %lu", + header->RecordSize, + sizeof(TRecord)); + + RecordCount = header->RecordCount; + + FileMap->ResizeAndRemap(0, CalcFileSize(RecordCount)); + HeaderPtr = reinterpret_cast(FileMap->Ptr()); + RecordsPtr = reinterpret_cast(HeaderPtr + 1); + + CompactRecords(); + } + size_t CalcFileSize(size_t recordCount) { return sizeof(THeader) + recordCount * sizeof(TRecord); diff --git a/cloud/storage/core/libs/common/persistent_table_ut.cpp b/cloud/storage/core/libs/common/persistent_table_ut.cpp index cdeb8f51f7..8f8585f7a3 100644 --- a/cloud/storage/core/libs/common/persistent_table_ut.cpp +++ b/cloud/storage/core/libs/common/persistent_table_ut.cpp @@ -423,6 +423,32 @@ Y_UNIT_TEST_SUITE(TPersistentTableTest) UNIT_ASSERT_VALUES_EQUAL(ri.CountRecords(), table->CountRecords()); } } + + Y_UNIT_TEST(ShouldClearRecords) + { + TTempDir dir; + auto tablePath = dir.Path() / "table"; + + auto tableSize = 32; + + TPersistentTable table(tablePath, tableSize); + UNIT_ASSERT_VALUES_EQUAL(table.CountRecords(), 0); + + for (auto i = 0; i < tableSize; ++i) { + auto index = table.AllocRecord(); + UNIT_ASSERT_VALUES_UNEQUAL(table.InvalidIndex, index); + UNIT_ASSERT_VALUES_EQUAL(table.CountRecords(), index + 1); + } + + table.Clear(); + UNIT_ASSERT_VALUES_EQUAL(table.CountRecords(), 0); + + for (auto i = 0; i < tableSize; ++i) { + auto index = table.AllocRecord(); + UNIT_ASSERT_VALUES_UNEQUAL(table.InvalidIndex, index); + UNIT_ASSERT_VALUES_EQUAL(table.CountRecords(), index + 1); + } + } } } // namespace NCloud