|
1 | 1 | #include "blobstorage_syncer_localwriter.h"
|
2 | 2 | #include <ydb/core/blobstorage/vdisk/synclog/blobstorage_synclogmsgreader.h>
|
| 3 | +#include <ydb/core/blobstorage/vdisk/synclog/blobstorage_synclogmsgwriter.h> |
3 | 4 |
|
4 | 5 | namespace NKikimr {
|
5 | 6 |
|
@@ -186,5 +187,121 @@ namespace NKikimr {
|
186 | 187 | return new TLocalSyncDataExtractorActor(vctx, skeletonId, parentId, std::move(ev));
|
187 | 188 | }
|
188 | 189 |
|
| 190 | + /////////////////////////////////////////////////////////////////////////////////////////////// |
| 191 | + // TLocalSyncDataCutterActor -- actor extracts data from TEvLocalSyncData, cuts it into |
| 192 | + // smaller chunks and sends in multiple messages to Skeleton |
| 193 | + /////////////////////////////////////////////////////////////////////////////////////////////// |
| 194 | + class TLocalSyncDataCutterActor : public TActorBootstrapped<TLocalSyncDataCutterActor> { |
| 195 | + TIntrusivePtr<TVDiskConfig> VConfig; |
| 196 | + TIntrusivePtr<TVDiskContext> VCtx; |
| 197 | + TActorId SkeletonId; |
| 198 | + TActorId ParentId; |
| 199 | + std::unique_ptr<TEvLocalSyncData> Ev; |
| 200 | + std::vector<TString> Chunks; |
| 201 | + |
| 202 | + ui32 ChunksInFlight = 0; |
| 203 | + bool CompressChunks; |
| 204 | + ui32 MaxChunksInFlight; |
| 205 | + ui32 MaxChunksSize; |
| 206 | + |
| 207 | + public: |
| 208 | + void Bootstrap(const TActorContext &ctx) { |
| 209 | + TInstant startTime = TAppData::TimeProvider->Now(); |
| 210 | + std::unique_ptr<NSyncLog::TNaiveFragmentWriter> fragmentWriter; |
| 211 | + |
| 212 | + if (CompressChunks) { |
| 213 | + fragmentWriter.reset(new NSyncLog::TLz4FragmentWriter); |
| 214 | + } else { |
| 215 | + fragmentWriter.reset(new NSyncLog::TNaiveFragmentWriter); |
| 216 | + } |
| 217 | + |
| 218 | + auto addChunk = [&]() { |
| 219 | + if (fragmentWriter->GetSize()) { |
| 220 | + TString chunk; |
| 221 | + fragmentWriter->Finish(&chunk); |
| 222 | + Chunks.emplace_back(std::move(chunk)); |
| 223 | + fragmentWriter->Clear(); |
| 224 | + } |
| 225 | + }; |
| 226 | + |
| 227 | + auto copy = [&] (const void* ptr) { |
| 228 | + const NSyncLog::TRecordHdr* rec = (const NSyncLog::TRecordHdr*)((char*)ptr - sizeof(NSyncLog::TRecordHdr)); |
| 229 | + if (fragmentWriter->GetSize() + rec->GetSize() > MaxChunksSize) { |
| 230 | + addChunk(); |
| 231 | + } |
| 232 | + fragmentWriter->Push(rec, rec->GetSize()); |
| 233 | + }; |
| 234 | + |
| 235 | + NSyncLog::TFragmentReader fragmentReader(Ev->Data); |
| 236 | + fragmentReader.ForEach(copy, copy, copy, copy); |
| 237 | + |
| 238 | + addChunk(); |
| 239 | + |
| 240 | + TInstant finishTime = TAppData::TimeProvider->Now(); |
| 241 | + LOG_DEBUG_S(ctx, NKikimrServices::BS_SYNCER, VCtx->VDiskLogPrefix |
| 242 | + << "TLocalSyncDataCutterActor: VDiskId# " << Ev->VDiskID.ToString() |
| 243 | + << " dataSize# " << Ev->Data.size() |
| 244 | + << " duration# %s" << (finishTime - startTime)); |
| 245 | + |
| 246 | + Become(&TThis::StateFunc); |
| 247 | + } |
| 248 | + |
| 249 | + void Finish(const TActorContext& ctx, const NKikimrProto::EReplyStatus& status) { |
| 250 | + ctx.Send(ParentId, new TEvLocalSyncDataResult(status, TAppData::TimeProvider->Now(), nullptr, nullptr)); |
| 251 | + PassAway(); |
| 252 | + } |
| 253 | + |
| 254 | + void Handle(const TEvLocalSyncDataResult::TPtr& ev, const TActorContext& ctx) { |
| 255 | + if (ev->Get()->Status == NKikimrProto::OK) { |
| 256 | + --ChunksInFlight; |
| 257 | + if (Chunks.empty() && ChunksInFlight == 0) { |
| 258 | + Finish(ctx, NKikimrProto::OK); |
| 259 | + } else { |
| 260 | + SendChunks(ctx); |
| 261 | + } |
| 262 | + } else { |
| 263 | + Finish(ctx, ev->Get()->Status); |
| 264 | + } |
| 265 | + } |
| 266 | + |
| 267 | + void SendChunks(const TActorContext& ctx) { |
| 268 | + while (ChunksInFlight < MaxChunksInFlight && !Chunks.empty()) { |
| 269 | + ctx.Send(SkeletonId, new TEvLocalSyncData(Ev->VDiskID, Ev->SyncState, std::move(Chunks.back()))); |
| 270 | + Chunks.pop_back(); |
| 271 | + ++ChunksInFlight; |
| 272 | + } |
| 273 | + } |
| 274 | + |
| 275 | + public: |
| 276 | + static constexpr NKikimrServices::TActivity::EType ActorActivityType() { |
| 277 | + return NKikimrServices::TActivity::VDISK_LOCALSYNCDATA_CUTTER; |
| 278 | + } |
| 279 | + |
| 280 | + TLocalSyncDataCutterActor( |
| 281 | + const TIntrusivePtr<TVDiskConfig>& vconfig, |
| 282 | + const TIntrusivePtr<TVDiskContext>& vctx, |
| 283 | + const TActorId& skeletonId, |
| 284 | + const TActorId& parentId, |
| 285 | + std::unique_ptr<TEvLocalSyncData> ev) |
| 286 | + : VCtx(vctx) |
| 287 | + , SkeletonId(skeletonId) |
| 288 | + , ParentId(parentId) |
| 289 | + , Ev(std::move(ev)) |
| 290 | + , CompressChunks(vconfig->MaxSyncLogChunksInFlight) |
| 291 | + , MaxChunksInFlight(vconfig->MaxSyncLogChunksInFlight) |
| 292 | + , MaxChunksSize(vconfig->MaxSyncLogChunkSize) |
| 293 | + {} |
| 294 | + |
| 295 | + STRICT_STFUNC(StateFunc, { |
| 296 | + HFunc(TEvLocalSyncDataResult, Handle); |
| 297 | + }) |
| 298 | + |
| 299 | + }; |
| 300 | + |
| 301 | + IActor* CreateLocalSyncDataCutter(const TIntrusivePtr<TVDiskConfig>& vconfig, const TIntrusivePtr<TVDiskContext>& vctx, |
| 302 | + const TActorId& skeletonId, const TActorId& parentId, std::unique_ptr<TEvLocalSyncData> ev) { |
| 303 | + return new TLocalSyncDataCutterActor(vconfig, vctx, skeletonId, parentId, std::move(ev)); |
| 304 | + } |
| 305 | + |
189 | 306 |
|
190 | 307 | } // NKikimr
|
0 commit comments