diff options
author | a-sumin <a-sumin@yandex-team.com> | 2023-05-16 18:00:55 +0300 |
---|---|---|
committer | a-sumin <a-sumin@yandex-team.com> | 2023-05-16 18:00:55 +0300 |
commit | bb8a7d33d7bcc9d3bdd0c640d6c007f0e6610f57 (patch) | |
tree | 7849a87d62849c1e3f12a898d366a02973c1b9b0 | |
parent | 60f98737b9ee6b8fc0db0144b24ed03867a81135 (diff) | |
download | ydb-bb8a7d33d7bcc9d3bdd0c640d6c007f0e6610f57.tar.gz |
Introduce dedicated NPDisk::TLogCache
17 files changed, 339 insertions, 54 deletions
diff --git a/ydb/core/blobstorage/pdisk/CMakeLists.darwin-x86_64.txt b/ydb/core/blobstorage/pdisk/CMakeLists.darwin-x86_64.txt index 378ee761763..69594119e22 100644 --- a/ydb/core/blobstorage/pdisk/CMakeLists.darwin-x86_64.txt +++ b/ydb/core/blobstorage/pdisk/CMakeLists.darwin-x86_64.txt @@ -56,6 +56,7 @@ target_sources(core-blobstorage-pdisk PRIVATE ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_impl_http.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_impl_log.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_internal_interface.cpp + ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_log_cache.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_logreader.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_mon.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_params.cpp diff --git a/ydb/core/blobstorage/pdisk/CMakeLists.linux-aarch64.txt b/ydb/core/blobstorage/pdisk/CMakeLists.linux-aarch64.txt index 1fd378a19b2..14483b3155f 100644 --- a/ydb/core/blobstorage/pdisk/CMakeLists.linux-aarch64.txt +++ b/ydb/core/blobstorage/pdisk/CMakeLists.linux-aarch64.txt @@ -57,6 +57,7 @@ target_sources(core-blobstorage-pdisk PRIVATE ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_impl_http.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_impl_log.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_internal_interface.cpp + ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_log_cache.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_logreader.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_mon.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_params.cpp diff --git a/ydb/core/blobstorage/pdisk/CMakeLists.linux-x86_64.txt b/ydb/core/blobstorage/pdisk/CMakeLists.linux-x86_64.txt index 1fd378a19b2..14483b3155f 100644 --- a/ydb/core/blobstorage/pdisk/CMakeLists.linux-x86_64.txt +++ b/ydb/core/blobstorage/pdisk/CMakeLists.linux-x86_64.txt @@ -57,6 +57,7 @@ target_sources(core-blobstorage-pdisk PRIVATE ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_impl_http.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_impl_log.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_internal_interface.cpp + ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_log_cache.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_logreader.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_mon.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_params.cpp diff --git a/ydb/core/blobstorage/pdisk/CMakeLists.windows-x86_64.txt b/ydb/core/blobstorage/pdisk/CMakeLists.windows-x86_64.txt index 378ee761763..69594119e22 100644 --- a/ydb/core/blobstorage/pdisk/CMakeLists.windows-x86_64.txt +++ b/ydb/core/blobstorage/pdisk/CMakeLists.windows-x86_64.txt @@ -56,6 +56,7 @@ target_sources(core-blobstorage-pdisk PRIVATE ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_impl_http.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_impl_log.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_internal_interface.cpp + ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_log_cache.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_logreader.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_mon.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_params.cpp diff --git a/ydb/core/blobstorage/pdisk/blobstorage_pdisk_blockdevice.h b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_blockdevice.h index 7469ec76d8a..1388ec92fa4 100644 --- a/ydb/core/blobstorage/pdisk/blobstorage_pdisk_blockdevice.h +++ b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_blockdevice.h @@ -47,6 +47,7 @@ public: virtual void CachedPreadAsync(void *data, ui32 size, ui64 offset, TCompletionAction *completionAction, TReqId reqId, NWilson::TTraceId *traceId) = 0; virtual void ClearCache() = 0; + virtual void EraseCacheRange(ui64 begin, ui64 end) = 0; // erases offsets range [begin, end) virtual void FlushAsync(TCompletionAction *completionAction, TReqId reqId) = 0; virtual void NoopAsync(TCompletionAction *completionAction, TReqId reqId) = 0; virtual void NoopAsyncHackForLogReader(TCompletionAction *completionAction, TReqId reqId) = 0; @@ -61,11 +62,13 @@ public: virtual TString DebugInfo() = 0; }; +class TPDisk; + IBlockDevice* CreateRealBlockDevice(const TString &path, ui32 pDiskId, TPDiskMon &mon, ui64 reorderingCycles, ui64 seekCostNs, ui64 deviceInFlight, TDeviceMode::TFlags flags, - ui32 maxQueuedCompletionActions, TIntrusivePtr<TSectorMap> sectorMap); + ui32 maxQueuedCompletionActions, TIntrusivePtr<TSectorMap> sectorMap, TPDisk * const pdisk = nullptr); IBlockDevice* CreateRealBlockDeviceWithDefaults(const TString &path, TPDiskMon &mon, TDeviceMode::TFlags flags, - TIntrusivePtr<TSectorMap> sectorMap, TActorSystem *actorSystem); + TIntrusivePtr<TSectorMap> sectorMap, TActorSystem *actorSystem, TPDisk * const pdisk = nullptr); } // NPDisk } // NKikimr diff --git a/ydb/core/blobstorage/pdisk/blobstorage_pdisk_blockdevice_async.cpp b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_blockdevice_async.cpp index a66a3f911e1..6a53d162b12 100644 --- a/ydb/core/blobstorage/pdisk/blobstorage_pdisk_blockdevice_async.cpp +++ b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_blockdevice_async.cpp @@ -1,6 +1,8 @@ #include "blobstorage_pdisk_blockdevice.h" #include <ydb/library/pdisk_io/buffers.h> #include "blobstorage_pdisk_completion_impl.h" +#include "blobstorage_pdisk_impl.h" +#include "blobstorage_pdisk_log_cache.h" #include "blobstorage_pdisk_mon.h" #include "blobstorage_pdisk_util_atomicblockcounter.h" #include "blobstorage_pdisk_util_countedqueuemanyone.h" @@ -11,7 +13,6 @@ #include <ydb/core/base/appdata.h> #include <ydb/core/blobstorage/lwtrace_probes/blobstorage_probes.h> #include <ydb/core/protos/services.pb.h> -#include <ydb/core/util/cache.h> #include <ydb/core/util/yverify_stream.h> #include <ydb/library/pdisk_io/aio.h> #include <ydb/library/pdisk_io/spdk_state.h> @@ -1198,48 +1199,29 @@ class TCachedBlockDevice : public TRealBlockDevice { } }; - struct TCacheRecord : public TThrRefBase { - char *Data; - ui64 Size; - TVector<ui64> BadOffsets; - - TCacheRecord(TCachedReadCompletion *source) - : Data(static_cast<char*>(malloc(source->GetSize()))) - , Size(source->GetSize()) - , BadOffsets(std::move(source->GetBadOffsets())) - { - memcpy(Data, source->GetData(), source->GetSize()); - } - - ~TCacheRecord() { - free(Data); - } - }; - static constexpr ui64 MaxCount = 500ull; static constexpr ui64 MaxReadsInFly = 2; TMutex CacheMutex; - NCache::TLruCache<ui64, TIntrusivePtr<TCacheRecord>> Cache; + TLogCache Cache; // cache records MUST NOT cross chunk boundaries TMultiMap<ui64, TRead> ReadsForOffset; TMap<ui64, TCachedReadCompletion*> CurrentReads; ui64 ReadsInFly; + TPDisk * const PDisk; void UpdateReads() { auto nextIt = ReadsForOffset.begin(); for (auto it = ReadsForOffset.begin(); it != ReadsForOffset.end(); it = nextIt) { nextIt++; TRead &read = it->second; - TIntrusivePtr<TCacheRecord> *found; - bool isFound = Cache.Find(read.Offset, found); - if (isFound) { - TCacheRecord &cached = *found->Get(); - if (read.Size <= cached.Size) { - memcpy(read.Data, cached.Data, read.Size); + const TLogCache::TCacheRecord* cached = Cache.Find(read.Offset); + if (cached) { + if (read.Size <= cached->Data.Size()) { + memcpy(read.Data, cached->Data.GetData(), read.Size); Mon.DeviceReadCacheHits->Inc(); Y_VERIFY(read.CompletionAction); - for (size_t i = 0; i < cached.BadOffsets.size(); ++i) { - read.CompletionAction->RegisterBadOffset(cached.BadOffsets[i]); + for (size_t i = 0; i < cached->BadOffsets.size(); ++i) { + read.CompletionAction->RegisterBadOffset(cached->BadOffsets[i]); } NoopAsyncHackForLogReader(read.CompletionAction, read.ReqId); ReadsForOffset.erase(it); @@ -1270,13 +1252,14 @@ class TCachedBlockDevice : public TRealBlockDevice { public: TCachedBlockDevice(const TString &path, ui32 pDiskId, TPDiskMon &mon, ui64 reorderingCycles, ui64 seekCostNs, ui64 deviceInFlight, TDeviceMode::TFlags flags, ui32 maxQueuedCompletionActions, - TIntrusivePtr<TSectorMap> sectorMap) + TIntrusivePtr<TSectorMap> sectorMap, TPDisk * const pdisk) : TRealBlockDevice(path, pDiskId, mon, reorderingCycles, seekCostNs, deviceInFlight, flags, maxQueuedCompletionActions, sectorMap) - , ReadsInFly(0) + , ReadsInFly(0), PDisk(pdisk) {} void ExecRead(TCachedReadCompletion *completion, TActorSystem *actorSystem) { + Y_ASSERT(PDisk); TStackVec<TCompletionAction*, 32> pendingActions; { TGuard<TMutex> guard(CacheMutex); @@ -1284,28 +1267,42 @@ public: auto currentReadIt = CurrentReads.find(offset); Y_VERIFY(currentReadIt != CurrentReads.end()); auto range = ReadsForOffset.equal_range(offset); - if (Cache.GetCount() >= MaxCount) { - Cache.Pop(); + + ui64 chunkIdx = offset / PDisk->Format.ChunkSize; + Y_VERIFY(chunkIdx < PDisk->ChunkState.size()); + if (TChunkState::DATA_COMMITTED == PDisk->ChunkState[chunkIdx].CommitState) { + if ((offset % PDisk->Format.ChunkSize) + completion->GetSize() > PDisk->Format.ChunkSize) { + // TODO: split buffer if crossing chunk boundary instead of completely discarding it + LOG_INFO_S( + *ActorSystem, NKikimrServices::BS_DEVICE, + "Skip caching log read due to chunk boundary crossing"); + } else { + if (Cache.Size() >= MaxCount) { + Cache.Pop(); + } + const char* dataPtr = static_cast<const char*>(completion->GetData()); + Cache.Insert( + TLogCache::TCacheRecord( + completion->GetOffset(), + TRcBuf(TString(dataPtr, dataPtr + completion->GetSize())), + completion->GetBadOffsets())); + } } - TIntrusivePtr<TCacheRecord> cacheRecord(new TCacheRecord(completion)); - TIntrusivePtr<TCacheRecord> *junk; - Cache.Erase(offset); - bool isOk = Cache.Insert(offset, cacheRecord, junk); - Y_VERIFY(isOk); + auto nextIt = range.first; for (auto it = range.first; it != range.second; it = nextIt) { nextIt++; TRead &read = it->second; if (read.Size <= completion->GetSize()) { if (read.Data != completion->GetData()) { - memcpy(read.Data, cacheRecord->Data, read.Size); + memcpy(read.Data, completion->GetData(), read.Size); Mon.DeviceReadCacheHits->Inc(); } else { Mon.DeviceReadCacheMisses->Inc(); } Y_VERIFY(read.CompletionAction); - for (size_t i = 0; i < cacheRecord->BadOffsets.size(); ++i) { - read.CompletionAction->RegisterBadOffset(cacheRecord->BadOffsets[i]); + for (ui64 badOffset : completion->GetBadOffsets()) { + read.CompletionAction->RegisterBadOffset(badOffset); } pendingActions.push_back(read.CompletionAction); ReadsForOffset.erase(it); @@ -1360,6 +1357,11 @@ public: Cache.Clear(); } + virtual void EraseCacheRange(ui64 begin, ui64 end) override { + TGuard<TMutex> guard(CacheMutex); + Cache.EraseRange(begin, end); + } + void Stop() override { TRealBlockDevice::Stop(); for (auto it = CurrentReads.begin(); it != CurrentReads.end(); ++it) { @@ -1377,14 +1379,14 @@ public: IBlockDevice* CreateRealBlockDevice(const TString &path, ui32 pDiskId, TPDiskMon &mon, ui64 reorderingCycles, ui64 seekCostNs, ui64 deviceInFlight, TDeviceMode::TFlags flags, ui32 maxQueuedCompletionActions, - TIntrusivePtr<TSectorMap> sectorMap) { + TIntrusivePtr<TSectorMap> sectorMap, TPDisk * const pdisk) { return new TCachedBlockDevice(path, pDiskId, mon, reorderingCycles, seekCostNs, deviceInFlight, flags, - maxQueuedCompletionActions, sectorMap); + maxQueuedCompletionActions, sectorMap, pdisk); } IBlockDevice* CreateRealBlockDeviceWithDefaults(const TString &path, TPDiskMon &mon, TDeviceMode::TFlags flags, - TIntrusivePtr<TSectorMap> sectorMap, TActorSystem *actorSystem) { - IBlockDevice *device = CreateRealBlockDevice(path, 0, mon, 0, 0, 4, flags, 8, sectorMap); + TIntrusivePtr<TSectorMap> sectorMap, TActorSystem *actorSystem, TPDisk * const pdisk) { + IBlockDevice *device = CreateRealBlockDevice(path, 0, mon, 0, 0, 4, flags, 8, sectorMap, pdisk); device->Initialize(actorSystem, {}); return device; } diff --git a/ydb/core/blobstorage/pdisk/blobstorage_pdisk_driveestimator.cpp b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_driveestimator.cpp index d4e7f0e2231..2ea7e9e61cc 100644 --- a/ydb/core/blobstorage/pdisk/blobstorage_pdisk_driveestimator.cpp +++ b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_driveestimator.cpp @@ -236,7 +236,7 @@ TDriveEstimator::TDriveEstimator(const TString filename) , ActorSystemCreator(new TActorSystemCreator) , ActorSystem(ActorSystemCreator->GetActorSystem()) , QueueDepth(4) - , Device(CreateRealBlockDevice(filename, 0, PDiskMon, 50, 0, QueueDepth, TDeviceMode::LockFile, 128, nullptr)) + , Device(CreateRealBlockDevice(filename, 0, PDiskMon, 50, 0, QueueDepth, TDeviceMode::LockFile, 128, nullptr, nullptr)) , BufferPool(CreateBufferPool(BufferSize, 1, false, {})) , Buffer(BufferPool->Pop()) { diff --git a/ydb/core/blobstorage/pdisk/blobstorage_pdisk_impl.cpp b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_impl.cpp index 748c7105280..5c3027d21ac 100644 --- a/ydb/core/blobstorage/pdisk/blobstorage_pdisk_impl.cpp +++ b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_impl.cpp @@ -45,7 +45,7 @@ TPDisk::TPDisk(const TIntrusivePtr<TPDiskConfig> cfg, const TIntrusivePtr<::NMon , BlockDevice(CreateRealBlockDevice(cfg->GetDevicePath(), cfg->PDiskId, Mon, HPCyclesMs(ReorderingMs), DriveModel.SeekTimeNs(), cfg->DeviceInFlight, TDeviceMode::LockFile | (cfg->UseSpdkNvmeDriver ? TDeviceMode::UseSpdk : 0), - cfg->MaxQueuedCompletionActions, cfg->SectorMap)) + cfg->MaxQueuedCompletionActions, cfg->SectorMap, this)) , Cfg(cfg) , CreationTime(TInstant::Now()) , ExpectedSlotCount(cfg->ExpectedSlotCount) diff --git a/ydb/core/blobstorage/pdisk/blobstorage_pdisk_impl_log.cpp b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_impl_log.cpp index 392776190c6..74951e1676d 100644 --- a/ydb/core/blobstorage/pdisk/blobstorage_pdisk_impl_log.cpp +++ b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_impl_log.cpp @@ -1137,6 +1137,12 @@ void TPDisk::OnLogCommitDone(TLogCommitDone &req) { void TPDisk::MarkChunksAsReleased(TReleaseChunks& req) { TGuard<TMutex> guard(StateMutex); + for (const auto& chunkIdx : req.ChunksToRelease) { + BlockDevice->EraseCacheRange( + Format.Offset(chunkIdx, 0), + Format.Offset(chunkIdx + 1, 0)); + } + if (req.IsChunksFromLogSplice) { auto *releaseReq = ReqCreator.CreateFromArgs<TReleaseChunks>(std::move(req.ChunksToRelease)); diff --git a/ydb/core/blobstorage/pdisk/blobstorage_pdisk_log_cache.cpp b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_log_cache.cpp new file mode 100644 index 00000000000..7d225c2efa9 --- /dev/null +++ b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_log_cache.cpp @@ -0,0 +1,82 @@ +#include "blobstorage_pdisk_log_cache.h" + +namespace NKikimr { +namespace NPDisk { + +TLogCache::TCacheRecord::TCacheRecord(ui64 offset, TRcBuf data, TVector<ui64> badOffsets) + : Offset(offset) + , Data(std::move(data)) + , BadOffsets(std::move(badOffsets)) +{} + +TLogCache::TCacheRecord::TCacheRecord(TCacheRecord&& other) + : Offset(other.Offset) + , Data(std::move(other.Data)) + , BadOffsets(std::move(other.BadOffsets)) +{} + +TLogCache::TItem::TItem(TItem&& other) + : Value(std::move(other.Value)) +{} + +TLogCache::TItem::TItem(TCacheRecord&& value) + : Value(std::move(value)) +{} + +size_t TLogCache::Size() const { + return Index.size(); +} + +const TLogCache::TCacheRecord* TLogCache::Find(ui64 offset) { + auto indexIt = Index.find(offset); + if (indexIt == Index.end()) { + return nullptr; + } + + List.PushFront(&indexIt->second); + return &indexIt->second.Value; +} + +const TLogCache::TCacheRecord* TLogCache::FindWithoutPromote(ui64 offset) const { + auto indexIt = Index.find(offset); + if (indexIt == Index.end()) { + return nullptr; + } + + return &indexIt->second.Value; +} + +bool TLogCache::Pop() { + if (Index.empty()) + return false; + + TItem* item = List.PopBack(); + Index.erase(item->Value.Offset); + return true; +} + +bool TLogCache::Insert(TCacheRecord&& value) { + auto [it, inserted] = Index.try_emplace(value.Offset, std::move(value)); + List.PushFront(&it->second); + return inserted; +} + +size_t TLogCache::Erase(ui64 offset) { + return Index.erase(offset); +} + +size_t TLogCache::EraseRange(ui64 begin, ui64 end) { + Y_VERIFY_DEBUG(begin <= end); + auto beginIt = Index.lower_bound(begin); + auto endIt = Index.lower_bound(end); + size_t dist = std::distance(beginIt, endIt); + Index.erase(beginIt, endIt); + return dist; +} + +void TLogCache::Clear() { + Index.clear(); +} + +} // NPDisk +} // NKikimr diff --git a/ydb/core/blobstorage/pdisk/blobstorage_pdisk_log_cache.h b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_log_cache.h new file mode 100644 index 00000000000..c3d91dcdd2c --- /dev/null +++ b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_log_cache.h @@ -0,0 +1,54 @@ +#pragma once +#include "defs.h" +#include <library/cpp/actors/util/rc_buf.h> +#include <util/generic/intrlist.h> +#include <util/generic/hash.h> + +namespace NKikimr { +namespace NPDisk { + +/** + * Key-value LRU cache without automatic eviction, but able to erase range of keys. + **/ +class TLogCache { +public: + struct TCacheRecord { + ui64 Offset = 0; + TRcBuf Data; + TVector<ui64> BadOffsets; + + TCacheRecord() = default; + TCacheRecord(TCacheRecord&&); + TCacheRecord(ui64 offset, TRcBuf data, TVector<ui64> badOffsets); + }; + +private: + struct TItem : public TIntrusiveListItem<TItem> { + TCacheRecord Value; + + // custom constructors ignoring TIntrusiveListItem + TItem(TItem&& other); + explicit TItem(TCacheRecord&& value); + }; + + using TListType = TIntrusiveList<TItem>; + using TIndex = TMap<ui64, TItem>; + +public: + size_t Size() const; + const TCacheRecord* Find(ui64 offset); + const TCacheRecord* FindWithoutPromote(ui64 offset) const; + + bool Pop(); + bool Insert(TCacheRecord&& value); + size_t Erase(ui64 offset); + size_t EraseRange(ui64 begin, ui64 end); // erases range [begin, end) + void Clear(); + +private: + TListType List; + TIndex Index; +}; + +} // NPDisk +} // NKikimr diff --git a/ydb/core/blobstorage/pdisk/blobstorage_pdisk_log_cache_ut.cpp b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_log_cache_ut.cpp new file mode 100644 index 00000000000..ba0d99e641a --- /dev/null +++ b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_log_cache_ut.cpp @@ -0,0 +1,126 @@ +#include "blobstorage_pdisk_log_cache.h" + +#include <library/cpp/testing/unittest/registar.h> + +namespace NKikimr { +namespace NPDisk { + +Y_UNIT_TEST_SUITE(TLogCache) { + TLogCache::TCacheRecord MakeRecord(ui64 offset, TString str) { + return TLogCache::TCacheRecord( + offset, + TRcBuf(TString(str.c_str(), str.c_str() + str.size() + 1)), + {}); + } + + Y_UNIT_TEST(Simple) { + TLogCache cache; + + UNIT_ASSERT(cache.Insert(MakeRecord(1, "a"))); + UNIT_ASSERT(cache.Insert(MakeRecord(2, "b"))); + UNIT_ASSERT_EQUAL(cache.Size(), 2); + UNIT_ASSERT_STRINGS_EQUAL(cache.Find(1)->Data.GetData(), "a"); + + UNIT_ASSERT(cache.Insert(MakeRecord(3, "c"))); + UNIT_ASSERT(cache.Pop()); // 2 must be evicted + UNIT_ASSERT_EQUAL(cache.Size(), 2); + UNIT_ASSERT_EQUAL(nullptr, cache.Find(2)); + UNIT_ASSERT_STRINGS_EQUAL(cache.Find(3)->Data.GetData(), "c"); + + UNIT_ASSERT(cache.Pop()); // 1 must be evicted + UNIT_ASSERT(cache.Insert(MakeRecord(4, "d"))); + + UNIT_ASSERT_EQUAL(cache.Size(), 2); + UNIT_ASSERT_EQUAL(nullptr, cache.Find(1)); + UNIT_ASSERT_STRINGS_EQUAL(cache.Find(4)->Data.GetData(), "d"); + + UNIT_ASSERT(cache.Pop()); // 3 must be evicted + UNIT_ASSERT_EQUAL(cache.Size(), 1); + UNIT_ASSERT_EQUAL(nullptr, cache.Find(3)); + UNIT_ASSERT_STRINGS_EQUAL(cache.Find(4)->Data.GetData(), "d"); + + UNIT_ASSERT_EQUAL(0, cache.Erase(3)); + UNIT_ASSERT_EQUAL(1, cache.Erase(4)); + UNIT_ASSERT_EQUAL(cache.Size(), 0); + UNIT_ASSERT(!cache.Pop()); + UNIT_ASSERT_EQUAL(cache.Size(), 0); + } + + TLogCache SetupCache(const TVector<std::pair<ui64, TString>>& content = {{5, "x"}, {1, "y"}, {10, "z"}}) { + TLogCache cache; + for (auto pair : content) { + cache.Insert(MakeRecord(pair.first, pair.second)); + } + return cache; + }; + + void AssertCacheContains(TLogCache& cache, const TVector<std::pair<ui64, TString>>& content = {{5, "x"}, {1, "y"}, {10, "z"}}) { + UNIT_ASSERT_VALUES_EQUAL(content.size(), cache.Size()); + for (auto pair : content) { + UNIT_ASSERT_STRINGS_EQUAL( + pair.second, + cache.FindWithoutPromote(pair.first)->Data.GetData()); + } + for (auto pair : content) { + UNIT_ASSERT(cache.Pop()); + UNIT_ASSERT_EQUAL(nullptr, cache.FindWithoutPromote(pair.first)); + } + } + + Y_UNIT_TEST(EraseRangeOnEmpty) { + TLogCache cache; + UNIT_ASSERT_EQUAL(0, cache.EraseRange(0, 0)); + UNIT_ASSERT_EQUAL(0, cache.EraseRange(0, 10)); + UNIT_ASSERT_EQUAL(0, cache.EraseRange(10, 10)); + } + + Y_UNIT_TEST(EraseRangeOutsideOfData) { + TLogCache cache = SetupCache(); + UNIT_ASSERT_EQUAL(3, cache.Size()); + UNIT_ASSERT_EQUAL(0, cache.EraseRange(0, 1)); + UNIT_ASSERT_EQUAL(3, cache.Size()); + UNIT_ASSERT_EQUAL(0, cache.EraseRange(11, 12)); + UNIT_ASSERT_EQUAL(3, cache.Size()); + UNIT_ASSERT_EQUAL(0, cache.EraseRange(11, 100)); + UNIT_ASSERT_EQUAL(3, cache.Size()); + } + + Y_UNIT_TEST(EraseRangeSingleMinElement) { + TLogCache cache = SetupCache(); + UNIT_ASSERT_EQUAL(1, cache.EraseRange(1, 2)); + AssertCacheContains(cache, {{5, "x"}, {10, "z"}}); + } + + Y_UNIT_TEST(EraseRangeSingleMidElement) { + TLogCache cache = SetupCache(); + UNIT_ASSERT_EQUAL(1, cache.EraseRange(5, 6)); + AssertCacheContains(cache, {{1, "y"}, {10, "z"}}); + } + + Y_UNIT_TEST(EraseRangeSingleMaxElement) { + TLogCache cache = SetupCache(); + UNIT_ASSERT_EQUAL(1, cache.EraseRange(10, 11)); + AssertCacheContains(cache, {{5, "x"}, {1, "y"}}); + } + + Y_UNIT_TEST(EraseRangeSample) { + TLogCache cache = SetupCache(); + UNIT_ASSERT_EQUAL(2, cache.EraseRange(2, 100)); + AssertCacheContains(cache, {{1, "y"}}); + } + + Y_UNIT_TEST(EraseRangeAllExact) { + TLogCache cache = SetupCache(); + UNIT_ASSERT_EQUAL(3, cache.EraseRange(1, 11)); + UNIT_ASSERT_EQUAL(0, cache.Size()); + } + + Y_UNIT_TEST(EraseRangeAllAmple) { + TLogCache cache = SetupCache(); + UNIT_ASSERT_EQUAL(3, cache.EraseRange(0, 100)); + UNIT_ASSERT_EQUAL(0, cache.Size()); + } +} + +} // NPDisk +} // NKikimr diff --git a/ydb/core/blobstorage/pdisk/blobstorage_pdisk_logreader.cpp b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_logreader.cpp index 532ad750833..add4a820ac2 100644 --- a/ydb/core/blobstorage/pdisk/blobstorage_pdisk_logreader.cpp +++ b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_logreader.cpp @@ -793,11 +793,11 @@ bool TLogReader::ProcessSectorSet(TSectorData *sector) { << " LastGoodToWriteLogPosition# " << LastGoodToWriteLogPosition << " Marker# LR018"); } else { -// Y_VERIFY_S(ChunkIdx == LogEndChunkIdx && SectorIdx >= LogEndSectorIdx, SelfInfo() -// << " File# " << __FILE__ -// << " Line# " << __LINE__ -// << " LogEndChunkIdx# " << LogEndChunkIdx -// << " LogEndSectorIdx# " << LogEndSectorIdx); + Y_VERIFY_S(ChunkIdx == LogEndChunkIdx && SectorIdx >= LogEndSectorIdx, SelfInfo() + << " File# " << __FILE__ + << " Line# " << __LINE__ + << " LogEndChunkIdx# " << LogEndChunkIdx + << " LogEndSectorIdx# " << LogEndSectorIdx); if (!(ChunkIdx == LogEndChunkIdx && SectorIdx >= LogEndSectorIdx)) { LOG_WARN_S(*PDisk->ActorSystem, NKikimrServices::BS_PDISK, SelfInfo() << " In ProcessSectorSet got !restorator.GoodSectorFlags outside the LogEndSector." @@ -1147,6 +1147,11 @@ void TLogReader::Reply() { if (IsInitial) { PDisk->ProcessChunkOwnerMap(*ChunkOwnerMap.Get()); ChunkOwnerMap.Destroy(); + + PDisk->BlockDevice->EraseCacheRange( + PDisk->Format.Offset(ChunkIdx, 0), + PDisk->Format.Offset(ChunkIdx + 1, 0) + ); } LOG_DEBUG(*PDisk->ActorSystem, NKikimrServices::BS_PDISK, "PDiskId# %" PRIu32 " To ownerId# %" PRIu32 " %s", (ui32)PDisk->PDiskId, (ui32)Owner, Result->ToString().c_str()); @@ -1387,4 +1392,3 @@ void TLogReader::ReleaseUsedBadOffsets() { } // NPDisk } // NKikimr - diff --git a/ydb/core/blobstorage/pdisk/ut/CMakeLists.darwin-x86_64.txt b/ydb/core/blobstorage/pdisk/ut/CMakeLists.darwin-x86_64.txt index 5472736fd16..95f69321e94 100644 --- a/ydb/core/blobstorage/pdisk/ut/CMakeLists.darwin-x86_64.txt +++ b/ydb/core/blobstorage/pdisk/ut/CMakeLists.darwin-x86_64.txt @@ -32,6 +32,7 @@ target_link_options(ydb-core-blobstorage-pdisk-ut PRIVATE target_sources(ydb-core-blobstorage-pdisk-ut PRIVATE ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_blockdevice_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_crypto_ut.cpp + ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_log_cache_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_util_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_ut_env.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_ut_races.cpp diff --git a/ydb/core/blobstorage/pdisk/ut/CMakeLists.linux-aarch64.txt b/ydb/core/blobstorage/pdisk/ut/CMakeLists.linux-aarch64.txt index eb05ab2715d..faef05f81f8 100644 --- a/ydb/core/blobstorage/pdisk/ut/CMakeLists.linux-aarch64.txt +++ b/ydb/core/blobstorage/pdisk/ut/CMakeLists.linux-aarch64.txt @@ -35,6 +35,7 @@ target_link_options(ydb-core-blobstorage-pdisk-ut PRIVATE target_sources(ydb-core-blobstorage-pdisk-ut PRIVATE ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_blockdevice_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_crypto_ut.cpp + ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_log_cache_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_util_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_ut_env.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_ut_races.cpp diff --git a/ydb/core/blobstorage/pdisk/ut/CMakeLists.linux-x86_64.txt b/ydb/core/blobstorage/pdisk/ut/CMakeLists.linux-x86_64.txt index 8ad3a8a33fb..268016dec16 100644 --- a/ydb/core/blobstorage/pdisk/ut/CMakeLists.linux-x86_64.txt +++ b/ydb/core/blobstorage/pdisk/ut/CMakeLists.linux-x86_64.txt @@ -36,6 +36,7 @@ target_link_options(ydb-core-blobstorage-pdisk-ut PRIVATE target_sources(ydb-core-blobstorage-pdisk-ut PRIVATE ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_blockdevice_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_crypto_ut.cpp + ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_log_cache_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_util_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_ut_env.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_ut_races.cpp diff --git a/ydb/core/blobstorage/pdisk/ut/CMakeLists.windows-x86_64.txt b/ydb/core/blobstorage/pdisk/ut/CMakeLists.windows-x86_64.txt index 83968ce047d..0533f6adb7d 100644 --- a/ydb/core/blobstorage/pdisk/ut/CMakeLists.windows-x86_64.txt +++ b/ydb/core/blobstorage/pdisk/ut/CMakeLists.windows-x86_64.txt @@ -25,6 +25,7 @@ target_link_libraries(ydb-core-blobstorage-pdisk-ut PUBLIC target_sources(ydb-core-blobstorage-pdisk-ut PRIVATE ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_blockdevice_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_crypto_ut.cpp + ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_log_cache_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_util_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_ut_env.cpp ${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/pdisk/blobstorage_pdisk_ut_races.cpp |