@@ -45,6 +45,67 @@ namespace NKikimr::NTestShard {
45
45
BytesProcessed += value.size ();
46
46
}
47
47
48
+ void TLoadActor::IssuePatch () {
49
+ Y_ABORT_UNLESS (!ConfirmedKeys.empty ());
50
+ const size_t index = RandomNumber (ConfirmedKeys.size ());
51
+ const TString originalKey = ConfirmedKeys[index ];
52
+
53
+ // extract length from the original key -- it may not change
54
+ ui64 len, seed, id;
55
+ StringSplitter (originalKey).Split (' ,' ).CollectInto (&len, &seed, &id);
56
+ TString originalValue = FastGenDataForLZ4 (len, seed);
57
+
58
+ // generate patched key
59
+ seed = RandomNumber<ui64>();
60
+ id = RandomNumber<ui64>();
61
+ const TString patchedKey = TStringBuilder () << len << ' ,' << seed << ' ,' << id;
62
+
63
+ // generate random value for the new key
64
+ TString patchedValue = FastGenDataForLZ4 (len, seed);
65
+
66
+ auto ev = CreateRequest ();
67
+ auto & r = ev->Record ;
68
+ auto *patch = r.AddCmdPatch ();
69
+ patch->SetOriginalKey (originalKey);
70
+ patch->SetPatchedKey (patchedKey);
71
+
72
+ TRope rope (patchedValue);
73
+ ui64 offset = 0 ;
74
+ for (size_t chunks = 0 ; offset != len; ++chunks) {
75
+ // skip matching parts
76
+ while (offset + 1 < len && originalValue[offset] == patchedValue[offset]) {
77
+ ++offset;
78
+ }
79
+ Y_ABORT_UNLESS (offset < len);
80
+
81
+ // add patched part
82
+ size_t pos = offset + 1 ;
83
+ while (pos < len && originalValue[pos] != patchedValue[pos]) {
84
+ ++pos;
85
+ }
86
+ const size_t size = (chunks < 8 ? pos : len) - offset;
87
+
88
+ auto *diff = patch->AddDiffs ();
89
+ diff->SetOffset (offset);
90
+ if (RandomNumber (2u )) {
91
+ diff->SetPayloadId (ev->AddPayload (TRope (rope.Position (offset), rope.Position (offset + size))));
92
+ } else {
93
+ diff->SetValue (patchedValue.substr (offset, size));
94
+ }
95
+ offset += size;
96
+ }
97
+
98
+ auto [pifIt, pifInserted] = PatchesInFlight.try_emplace (r.GetCookie (), patchedKey);
99
+ Y_ABORT_UNLESS (pifInserted);
100
+
101
+ auto [it, inserted] = Keys.try_emplace (patchedKey, len);
102
+ Y_ABORT_UNLESS (inserted);
103
+ RegisterTransition (*it, ::NTestShard::TStateServer::ABSENT, ::NTestShard::TStateServer::WRITE_PENDING, std::move (ev));
104
+
105
+ ++KeysWritten;
106
+ BytesProcessed += len;
107
+ }
108
+
48
109
void TLoadActor::ProcessWriteResult (ui64 cookie, const google::protobuf::RepeatedPtrField<NKikimrClient::TKeyValueResponse::TWriteResult>& results) {
49
110
if (const auto wifIt = WritesInFlight.find (cookie); wifIt != WritesInFlight.end ()) {
50
111
TWriteInfo& info = wifIt->second ;
@@ -69,4 +130,17 @@ namespace NKikimr::NTestShard {
69
130
}
70
131
}
71
132
133
+ void TLoadActor::ProcessPatchResult (ui64 cookie, const google::protobuf::RepeatedPtrField<NKikimrClient::TKeyValueResponse::TPatchResult>& results) {
134
+ if (auto nh = PatchesInFlight.extract (cookie)) {
135
+ Y_ABORT_UNLESS (results.size () == 1 );
136
+ const auto & res = results[0 ];
137
+ Y_VERIFY_S (res.GetStatus () == NKikimrProto::OK, " TabletId# " << TabletId << " CmdPatch failed Status# "
138
+ << NKikimrProto::EReplyStatus_Name (NKikimrProto::EReplyStatus (res.GetStatus ())));
139
+ const TString& key = nh.mapped ();
140
+ const auto it = Keys.find (key);
141
+ Y_VERIFY_S (it != Keys.end (), " Key# " << key << " not found in Keys dict" );
142
+ RegisterTransition (*it, ::NTestShard::TStateServer::WRITE_PENDING, ::NTestShard::TStateServer::CONFIRMED);
143
+ }
144
+ }
145
+
72
146
} // NKikimr::NTestShard
0 commit comments