@@ -16,64 +16,130 @@ void Test() {
16
16
17
17
TString data = TString::Uninitialized (8_MB);
18
18
memset (data.Detach (), ' X' , data.size ());
19
- TLogoBlobID id (1 , 1 , 1 , 0 , data.size (), 0 );
20
-
21
- { // write data to group
22
- TActorId sender = runtime->AllocateEdgeActor (1 );
23
- runtime->WrapInActorContext (sender, [&] {
24
- SendToBSProxy (sender, info->GroupID , new TEvBlobStorage::TEvPut (id, data, TInstant::Max ()));
25
- });
26
- auto res = env.WaitForEdgeActorEvent <TEvBlobStorage::TEvPutResult>(sender);
27
- UNIT_ASSERT_VALUES_EQUAL (res->Get ()->Status , NKikimrProto::OK);
28
- }
29
19
30
- auto checkReadable = [&](NKikimrProto::EReplyStatus status) {
31
- TActorId sender = runtime->AllocateEdgeActor (1 );
32
- runtime->WrapInActorContext (sender, [&] {
33
- SendToBSProxy (sender, info->GroupID , new TEvBlobStorage::TEvGet (id, 0 , 0 , TInstant::Max (),
34
- NKikimrBlobStorage::EGetHandleClass::FastRead));
35
- });
36
- auto res = env.WaitForEdgeActorEvent <TEvBlobStorage::TEvGetResult>(sender);
37
- UNIT_ASSERT_VALUES_EQUAL (res->Get ()->Status , NKikimrProto::OK);
38
- UNIT_ASSERT_VALUES_EQUAL (res->Get ()->ResponseSz , 1 );
39
- auto & r = res->Get ()->Responses [0 ];
40
- UNIT_ASSERT_VALUES_EQUAL (r.Status , status);
41
- if (status == NKikimrProto::OK) {
42
- UNIT_ASSERT_VALUES_EQUAL (r.Buffer .ConvertToString (), data);
20
+ for (ui32 step = 1 ; step < 100 ; ++step) {
21
+ TLogoBlobID id (1 , 1 , step, 0 , data.size (), 0 );
22
+
23
+ { // write data to group
24
+ TActorId sender = runtime->AllocateEdgeActor (1 );
25
+ runtime->WrapInActorContext (sender, [&] {
26
+ SendToBSProxy (sender, info->GroupID , new TEvBlobStorage::TEvPut (id, data, TInstant::Max ()));
27
+ });
28
+ auto res = env.WaitForEdgeActorEvent <TEvBlobStorage::TEvPutResult>(sender);
29
+ UNIT_ASSERT_VALUES_EQUAL (res->Get ()->Status , NKikimrProto::OK);
43
30
}
44
- };
45
31
46
- checkReadable (NKikimrProto::OK);
32
+ auto checkReadable = [&] {
33
+ TActorId sender = runtime->AllocateEdgeActor (1 );
34
+ runtime->WrapInActorContext (sender, [&] {
35
+ SendToBSProxy (sender, info->GroupID , new TEvBlobStorage::TEvGet (id, 0 , 0 , TInstant::Max (),
36
+ NKikimrBlobStorage::EGetHandleClass::FastRead));
37
+ });
38
+ auto res = env.WaitForEdgeActorEvent <TEvBlobStorage::TEvGetResult>(sender);
39
+ UNIT_ASSERT_VALUES_EQUAL (res->Get ()->Status , NKikimrProto::OK);
40
+ UNIT_ASSERT_VALUES_EQUAL (res->Get ()->ResponseSz , 1 );
41
+ auto & r = res->Get ()->Responses [0 ];
42
+ UNIT_ASSERT_VALUES_EQUAL (r.Status , NKikimrProto::OK);
43
+ UNIT_ASSERT_VALUES_EQUAL (r.Buffer .ConvertToString (), data);
44
+
45
+ ui32 partsMask = 0 ;
46
+ for (ui32 i = 0 ; i < info->GetTotalVDisksNum (); ++i) {
47
+ const TVDiskID& vdiskId = info->GetVDiskId (i);
48
+ env.WithQueueId (vdiskId, NKikimrBlobStorage::EVDiskQueueId::GetFastRead, [&](TActorId queueId) {
49
+ const TActorId sender = runtime->AllocateEdgeActor (1 );
50
+ auto ev = TEvBlobStorage::TEvVGet::CreateExtremeDataQuery (vdiskId, TInstant::Max (),
51
+ NKikimrBlobStorage::EGetHandleClass::FastRead);
52
+ ev->AddExtremeQuery (id, 0 , 0 );
53
+ runtime->Send (new IEventHandle (queueId, sender, ev.release ()), sender.NodeId ());
54
+ auto reply = env.WaitForEdgeActorEvent <TEvBlobStorage::TEvVGetResult>(sender);
55
+ auto & record = reply->Get ()->Record ;
56
+ UNIT_ASSERT_VALUES_EQUAL (record.GetStatus (), NKikimrProto::OK);
57
+ UNIT_ASSERT_VALUES_EQUAL (record.ResultSize (), 1 );
58
+ for (const auto & result : record.GetResult ()) {
59
+ if (result.GetStatus () == NKikimrProto::OK) {
60
+ const TLogoBlobID& id = LogoBlobIDFromLogoBlobID (result.GetBlobID ());
61
+ UNIT_ASSERT (id.PartId ());
62
+ const ui32 partIdx = id.PartId () - 1 ;
63
+ const ui32 mask = 1 << partIdx;
64
+ UNIT_ASSERT (!(partsMask & mask));
65
+ partsMask |= mask;
66
+ } else {
67
+ UNIT_ASSERT_VALUES_EQUAL (result.GetStatus (), NKikimrProto::NODATA);
68
+ }
69
+ }
70
+ });
71
+ }
72
+ UNIT_ASSERT_VALUES_EQUAL (partsMask, (1 << info->Type .TotalPartCount ()) - 1 );
73
+ };
47
74
48
- for (ui32 i = 0 ; i < info->GetTotalVDisksNum (); ++i) {
49
- const TActorId vdiskActorId = info->GetActorId (i);
75
+ checkReadable ();
50
76
51
- ui32 nodeId, pdiskId;
52
- std::tie (nodeId, pdiskId, std::ignore) = DecomposeVDiskServiceId (vdiskActorId);
53
- auto it = env.PDiskMockStates .find (std::make_pair (nodeId, pdiskId));
54
- Y_ABORT_UNLESS (it != env.PDiskMockStates .end ());
77
+ ui32 mask = 0 ;
55
78
56
- const TActorId sender = runtime->AllocateEdgeActor (vdiskActorId.NodeId ());
57
- env.Runtime ->Send (new IEventHandle (vdiskActorId, sender, new TEvBlobStorage::TEvCaptureVDiskLayout), sender.NodeId ());
58
- auto res = env.WaitForEdgeActorEvent <TEvBlobStorage::TEvCaptureVDiskLayoutResult>(sender);
79
+ for (ui32 i = 0 ; i < info->GetTotalVDisksNum (); ++i) {
80
+ const TActorId vdiskActorId = info->GetActorId (i);
59
81
60
- for (auto & item : res->Get ()->Layout ) {
61
- using T = TEvBlobStorage::TEvCaptureVDiskLayoutResult;
62
- if (item.Database == T::EDatabase::LogoBlobs && item.RecordType == T::ERecordType::HugeBlob) {
63
- const TDiskPart& part = item.Location ;
64
- it->second ->SetCorruptedArea (part.ChunkIdx , part.Offset , part.Offset + part.Size , true );
65
- break ;
82
+ ui32 nodeId, pdiskId;
83
+ std::tie (nodeId, pdiskId, std::ignore) = DecomposeVDiskServiceId (vdiskActorId);
84
+ auto it = env.PDiskMockStates .find (std::make_pair (nodeId, pdiskId));
85
+ Y_ABORT_UNLESS (it != env.PDiskMockStates .end ());
86
+
87
+ const TActorId sender = runtime->AllocateEdgeActor (vdiskActorId.NodeId ());
88
+ env.Runtime ->Send (new IEventHandle (vdiskActorId, sender, new TEvBlobStorage::TEvCaptureVDiskLayout), sender.NodeId ());
89
+ auto res = env.WaitForEdgeActorEvent <TEvBlobStorage::TEvCaptureVDiskLayoutResult>(sender);
90
+
91
+ for (auto & item : res->Get ()->Layout ) {
92
+ using T = TEvBlobStorage::TEvCaptureVDiskLayoutResult;
93
+ if (item.Database == T::EDatabase::LogoBlobs && item.RecordType == T::ERecordType::HugeBlob && item.BlobId .FullID () == id) {
94
+ const TDiskPart& part = item.Location ;
95
+ mask |= 1 << i;
96
+ it->second ->SetCorruptedArea (part.ChunkIdx , part.Offset , part.Offset + 1 + RandomNumber (part.Size ), true );
97
+ break ;
98
+ }
66
99
}
100
+
101
+ checkReadable ();
67
102
}
68
103
69
- checkReadable (NKikimrProto::OK);
70
- }
104
+ env.Sim (TDuration::Seconds (60 ));
71
105
72
- env.Sim (TDuration::Seconds (60 ));
106
+ for (ui32 i = 0 ; i < info->GetTotalVDisksNum (); ++i) {
107
+ if (~mask >> i & 1 ) {
108
+ continue ;
109
+ }
110
+
111
+ const TActorId vdiskActorId = info->GetActorId (i);
112
+
113
+ ui32 nodeId, pdiskId;
114
+ std::tie (nodeId, pdiskId, std::ignore) = DecomposeVDiskServiceId (vdiskActorId);
115
+ auto it = env.PDiskMockStates .find (std::make_pair (nodeId, pdiskId));
116
+ Y_ABORT_UNLESS (it != env.PDiskMockStates .end ());
117
+
118
+ const TActorId sender = runtime->AllocateEdgeActor (vdiskActorId.NodeId ());
119
+ env.Runtime ->Send (new IEventHandle (vdiskActorId, sender, new TEvBlobStorage::TEvCaptureVDiskLayout), sender.NodeId ());
120
+ auto res = env.WaitForEdgeActorEvent <TEvBlobStorage::TEvCaptureVDiskLayoutResult>(sender);
121
+
122
+ bool anyPartReadable = false ;
123
+
124
+ for (auto & item : res->Get ()->Layout ) {
125
+ using T = TEvBlobStorage::TEvCaptureVDiskLayoutResult;
126
+ if (item.Database == T::EDatabase::LogoBlobs && item.RecordType == T::ERecordType::HugeBlob && item.BlobId .FullID () == id) {
127
+ const TDiskPart& part = item.Location ;
128
+ anyPartReadable = !it->second ->HasCorruptedArea (part.ChunkIdx , part.Offset , part.Offset + part.Size );
129
+ if (anyPartReadable) {
130
+ break ;
131
+ }
132
+ }
133
+ }
134
+
135
+ UNIT_ASSERT (anyPartReadable);
136
+ }
137
+ }
73
138
}
74
139
75
140
Y_UNIT_TEST_SUITE (ScrubFast) {
76
141
Y_UNIT_TEST (SingleBlob) {
77
142
Test ();
78
143
}
79
144
}
145
+
0 commit comments