summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ydb/core/blobstorage/pdisk/blobstorage_pdisk_ut.cpp132
1 files changed, 132 insertions, 0 deletions
diff --git a/ydb/core/blobstorage/pdisk/blobstorage_pdisk_ut.cpp b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_ut.cpp
index 4513bb2b2f0..d1219e1aa33 100644
--- a/ydb/core/blobstorage/pdisk/blobstorage_pdisk_ut.cpp
+++ b/ydb/core/blobstorage/pdisk/blobstorage_pdisk_ut.cpp
@@ -6,6 +6,8 @@
#include <ydb/core/blobstorage/crypto/default.h>
#include <ydb/core/testlib/actors/test_runtime.h>
+#include <util/system/hp_timer.h>
+
namespace NKikimr {
Y_UNIT_TEST_SUITE(TPDiskTest) {
@@ -1021,5 +1023,135 @@ std::atomic<ui64> TVDiskMock::OwnerRound = 2;
new NPDisk::TEvCheckSpace(evInitRes->PDiskParams->Owner, evInitRes->PDiskParams->OwnerRound),
NKikimrProto::CORRUPTED);
}
+
+ Y_UNIT_TEST(KillOwnerWhileDeletingChunk) {
+ THPTimer timer;
+ ui32 timeLimit = 20;
+ while (timer.Passed() < timeLimit) {
+ TActorTestContext testCtx(false);
+
+ auto logNoTest = [&](TVDiskMock& mock, NPDisk::TCommitRecord rec) {
+ auto evLog = MakeHolder<NPDisk::TEvLog>(mock.PDiskParams->Owner, mock.PDiskParams->OwnerRound, 0, PrepareData(1),
+ mock.GetLsnSeg(), nullptr);
+ evLog->Signature.SetCommitRecord();
+ evLog->CommitRecord = std::move(rec);
+ testCtx.Send(evLog.Release());
+ };
+
+ TVDiskMock mock(&testCtx);
+ mock.Init();
+
+
+ ui32 vdisksNum = 100;
+ std::vector<TVDiskMock> mocks;
+ for (ui32 i = 0; i < vdisksNum; ++i) {
+ mocks.push_back(TVDiskMock(&testCtx));
+ mocks[i].Init();
+ }
+
+ ui32 reservedChunks = 10;
+
+ for (ui32 i = 0; i < reservedChunks; ++i) {
+ mock.ReserveChunk();
+ }
+ mock.CommitReservedChunks();
+
+ while (mock.Chunks[EChunkState::COMMITTED].size() > 0) {
+ auto it = mock.Chunks[EChunkState::COMMITTED].begin();
+ NPDisk::TCommitRecord rec;
+ rec.DeleteChunks.push_back(*it);
+ logNoTest(mock, rec);
+ mock.Chunks[EChunkState::COMMITTED].erase(it);
+ }
+
+ testCtx.Send(new NPDisk::TEvHarakiri(mock.PDiskParams->Owner, mock.PDiskParams->OwnerRound));
+
+ for (ui32 c = 0; ; c = (c + 1) % mocks.size()) {
+ testCtx.Send(new NPDisk::TEvChunkReserve(mocks[c].PDiskParams->Owner, mocks[c].PDiskParams->OwnerRound, 1));
+ THolder<NPDisk::TEvChunkReserveResult> evRes = testCtx.Recv<NPDisk::TEvChunkReserveResult>();
+ if (!evRes || evRes->Status != NKikimrProto::OK) {
+ break;
+ }
+ const ui32 reservedChunk = evRes->ChunkIds.front();
+ auto& reservedChunks = mocks[c].Chunks[EChunkState::RESERVED];
+ reservedChunks.emplace(reservedChunk);
+
+ NPDisk::TCommitRecord rec;
+ rec.CommitChunks.push_back(*reservedChunks.begin());
+ logNoTest(mocks[c], rec);
+ reservedChunks.clear();
+ }
+ testCtx.Recv<NPDisk::TEvHarakiriResult>();
+ }
+ }
+
+ Y_UNIT_TEST(KillOwnerWhileDeletingChunkWithInflight) {
+ THPTimer timer;
+ ui32 timeLimit = 20;
+ while (timer.Passed() < timeLimit) {
+ TActorTestContext testCtx(false);
+
+ auto logNoTest = [&](TVDiskMock& mock, NPDisk::TCommitRecord rec) {
+ auto evLog = MakeHolder<NPDisk::TEvLog>(mock.PDiskParams->Owner, mock.PDiskParams->OwnerRound, 0, PrepareData(1),
+ mock.GetLsnSeg(), nullptr);
+ evLog->Signature.SetCommitRecord();
+ evLog->CommitRecord = std::move(rec);
+ testCtx.Send(evLog.Release());
+ };
+
+ TVDiskMock mock(&testCtx);
+ mock.Init();
+
+
+ ui32 vdisksNum = 100;
+ std::vector<TVDiskMock> mocks;
+ for (ui32 i = 0; i < vdisksNum; ++i) {
+ mocks.push_back(TVDiskMock(&testCtx));
+ mocks[i].Init();
+ }
+
+ ui32 reservedChunks = 10;
+ for (ui32 i = 0; i < reservedChunks; ++i) {
+ mock.ReserveChunk();
+ }
+ mock.CommitReservedChunks();
+ TVector<TChunkIdx> chunkIds(mock.Chunks[EChunkState::COMMITTED].begin(), mock.Chunks[EChunkState::COMMITTED].end());
+
+ ui32 inflight = 300;
+
+ while (mock.Chunks[EChunkState::COMMITTED].size() > 0) {
+ auto it = mock.Chunks[EChunkState::COMMITTED].begin();
+ for (ui32 i = 0; i < inflight; ++i) {
+ TString data = "HATE. LET ME TELL YOU HOW MUCH I'VE COME TO HATE YOU SINCE I BEGAN TO LIVE...";
+ testCtx.Send(new NPDisk::TEvChunkWrite(mock.PDiskParams->Owner, mock.PDiskParams->OwnerRound,
+ *it, 0, new NPDisk::TEvChunkWrite::TStrokaBackedUpParts(data), nullptr, false, 0));
+ }
+ NPDisk::TCommitRecord rec;
+ rec.DeleteChunks.push_back(*it);
+ logNoTest(mock, rec);
+ mock.Chunks[EChunkState::COMMITTED].erase(it);
+ }
+ mock.Chunks[EChunkState::COMMITTED].clear();
+
+ testCtx.Send(new NPDisk::TEvHarakiri(mock.PDiskParams->Owner, mock.PDiskParams->OwnerRound));
+
+ for (ui32 c = 0; ; c = (c + 1) % mocks.size()) {
+ testCtx.Send(new NPDisk::TEvChunkReserve(mocks[c].PDiskParams->Owner, mocks[c].PDiskParams->OwnerRound, 1));
+ THolder<NPDisk::TEvChunkReserveResult> evRes = testCtx.Recv<NPDisk::TEvChunkReserveResult>();
+ if (!evRes || evRes->Status != NKikimrProto::OK) {
+ break;
+ }
+ const ui32 reservedChunk = evRes->ChunkIds.front();
+ auto& reservedChunks = mocks[c].Chunks[EChunkState::RESERVED];
+ reservedChunks.emplace(reservedChunk);
+
+ NPDisk::TCommitRecord rec;
+ rec.CommitChunks.push_back(*reservedChunks.begin());
+ logNoTest(mocks[c], rec);
+ reservedChunks.clear();
+ }
+ testCtx.Recv<NPDisk::TEvHarakiriResult>();
+ }
+ }
}
} // namespace NKikimr