diff options
author | single <single@yandex-team.ru> | 2022-02-10 16:50:29 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:50:29 +0300 |
commit | 8ae96df130bbede609c3504aa9af1bc6ff5361b3 (patch) | |
tree | 4751832974bd75ca721269aa54faa15d76032dfb | |
parent | 5d4e7b7c923852e0f6398791ec98a60cf9faab46 (diff) | |
download | ydb-8ae96df130bbede609c3504aa9af1bc6ff5361b3.tar.gz |
Restoring authorship annotation for <single@yandex-team.ru>. Commit 1 of 2.
445 files changed, 27974 insertions, 27974 deletions
diff --git a/library/cpp/actors/core/actor.cpp b/library/cpp/actors/core/actor.cpp index 6f9ba6a42b..243a3e1a86 100644 --- a/library/cpp/actors/core/actor.cpp +++ b/library/cpp/actors/core/actor.cpp @@ -16,15 +16,15 @@ namespace NActors { } void IActor::Registered(TActorSystem* sys, const TActorId& owner) { - // fallback to legacy method, do not use it anymore - if (auto eh = AfterRegister(SelfId(), owner)) - sys->Send(eh); - } - - void IActor::Describe(IOutputStream &out) const noexcept { - SelfActorId.Out(out); - } - + // fallback to legacy method, do not use it anymore + if (auto eh = AfterRegister(SelfId(), owner)) + sys->Send(eh); + } + + void IActor::Describe(IOutputStream &out) const noexcept { + SelfActorId.Out(out); + } + bool IActor::Send(const TActorId& recipient, IEventBase* ev, ui32 flags, ui64 cookie, NWilson::TTraceId traceId) const noexcept { return SelfActorId.Send(recipient, ev, flags, cookie, std::move(traceId)); } @@ -123,7 +123,7 @@ namespace NActors { TlsActivationContext->ExecutorThread.Schedule(deadline, new IEventHandle(SelfActorId, TActorId(), ev), cookie); } - void IActor::Schedule(TDuration delta, IEventBase* ev, ISchedulerCookie* cookie) const noexcept { + void IActor::Schedule(TDuration delta, IEventBase* ev, ISchedulerCookie* cookie) const noexcept { TlsActivationContext->ExecutorThread.Schedule(delta, new IEventHandle(SelfActorId, TActorId(), ev), cookie); } diff --git a/library/cpp/actors/core/actor.h b/library/cpp/actors/core/actor.h index ed29bd14b9..7a414bad1c 100644 --- a/library/cpp/actors/core/actor.h +++ b/library/cpp/actors/core/actor.h @@ -6,7 +6,7 @@ #include <library/cpp/actors/util/local_process_key.h> namespace NActors { - class TActorSystem; + class TActorSystem; class TMailboxTable; struct TMailboxHeader; @@ -169,11 +169,11 @@ namespace NActors { void Schedule(TDuration delta, IEventBase* ev, ISchedulerCookie* cookie = nullptr) const; }; - class IActor; - - class IActorOps : TNonCopyable { + class IActor; + + class IActorOps : TNonCopyable { public: - virtual void Describe(IOutputStream&) const noexcept = 0; + virtual void Describe(IOutputStream&) const noexcept = 0; virtual bool Send(const TActorId& recipient, IEventBase*, ui32 flags = 0, ui64 cookie = 0, NWilson::TTraceId traceId = {}) const noexcept = 0; /** @@ -205,12 +205,12 @@ namespace NActors { virtual TActorId Register(IActor*, TMailboxType::EType mailboxType = TMailboxType::HTSwap, ui32 poolId = Max<ui32>()) const noexcept = 0; virtual TActorId RegisterWithSameMailbox(IActor*) const noexcept = 0; - }; - + }; + class TDecorator; - class IActor : protected IActorOps { - public: + class IActor : protected IActorOps { + public: typedef void (IActor::*TReceiveFunc)(TAutoPtr<IEventHandle>& ev, const TActorContext& ctx); private: @@ -324,7 +324,7 @@ namespace NActors { } virtual void Registered(TActorSystem* sys, const TActorId& owner); - + virtual TAutoPtr<IEventHandle> AfterRegister(const TActorId& self, const TActorId& parentId) { Y_UNUSED(self); Y_UNUSED(parentId); @@ -349,7 +349,7 @@ namespace NActors { } protected: - void Describe(IOutputStream&) const noexcept override; + void Describe(IOutputStream&) const noexcept override; bool Send(const TActorId& recipient, IEventBase* ev, ui32 flags = 0, ui64 cookie = 0, NWilson::TTraceId traceId = {}) const noexcept final; template <typename TEvent> bool Send(const TActorId& recipient, THolder<TEvent> ev, ui32 flags = 0, ui64 cookie = 0, NWilson::TTraceId traceId = {}) const{ @@ -363,7 +363,7 @@ namespace NActors { void Schedule(TInstant deadline, IEventBase* ev, ISchedulerCookie* cookie = nullptr) const noexcept final; void Schedule(TMonotonic deadline, IEventBase* ev, ISchedulerCookie* cookie = nullptr) const noexcept final; - void Schedule(TDuration delta, IEventBase* ev, ISchedulerCookie* cookie = nullptr) const noexcept final; + void Schedule(TDuration delta, IEventBase* ev, ISchedulerCookie* cookie = nullptr) const noexcept final; // register new actor in ActorSystem on new fresh mailbox. TActorId Register(IActor* actor, TMailboxType::EType mailboxType = TMailboxType::HTSwap, ui32 poolId = Max<ui32>()) const noexcept final; diff --git a/library/cpp/actors/core/event.h b/library/cpp/actors/core/event.h index 6ff02aaf94..745bbd28f4 100644 --- a/library/cpp/actors/core/event.h +++ b/library/cpp/actors/core/event.h @@ -59,11 +59,11 @@ namespace NActors { public: template <typename TEv> inline TEv* CastAsLocal() const noexcept { - auto fits = GetTypeRewrite() == TEv::EventType; - - return fits ? static_cast<TEv*>(Event.Get()) : nullptr; - } - + auto fits = GetTypeRewrite() == TEv::EventType; + + return fits ? static_cast<TEv*>(Event.Get()) : nullptr; + } + template <typename TEventType> TEventType* Get() { if (Type != TEventType::EventType) diff --git a/library/cpp/actors/core/events.h b/library/cpp/actors/core/events.h index 702cf50fad..984cb51523 100644 --- a/library/cpp/actors/core/events.h +++ b/library/cpp/actors/core/events.h @@ -85,23 +85,23 @@ namespace NActors { Unsubscribe, // generic unsubscribe from something Delivered, // event delivered Undelivered, // event undelivered - Poison, // request actor to shutdown + Poison, // request actor to shutdown Completed, // generic async job result event - PoisonTaken, // generic Poison taken (reply to PoisonPill event, i.e. died completely) + PoisonTaken, // generic Poison taken (reply to PoisonPill event, i.e. died completely) FlushLog, CallbackCompletion, CallbackException, - Gone, // Generic notification of actor death + Gone, // Generic notification of actor death TrackActor, UntrackActor, InvokeResult, CoroTimeout, InvokeQuery, - End, - + End, + // Compatibility section - PoisonPill = Poison, - ActorDied = Gone, + PoisonPill = Poison, + ActorDied = Gone, }; static_assert(End < EventSpaceEnd(ES_SYSTEM), "expect End < EventSpaceEnd(ES_SYSTEM)"); @@ -111,16 +111,16 @@ namespace NActors { DEFINE_SIMPLE_LOCAL_EVENT(TEvBootstrap, "System: TEvBootstrap") }; - struct TEvPoison : public TEventBase<TEvPoison, TSystem::Poison> { - DEFINE_SIMPLE_NONLOCAL_EVENT(TEvPoison, "System: TEvPoison") + struct TEvPoison : public TEventBase<TEvPoison, TSystem::Poison> { + DEFINE_SIMPLE_NONLOCAL_EVENT(TEvPoison, "System: TEvPoison") }; struct TEvWakeup: public TEventBase<TEvWakeup, TSystem::Wakeup> { DEFINE_SIMPLE_LOCAL_EVENT(TEvWakeup, "System: TEvWakeup") - - TEvWakeup(ui64 tag = 0) : Tag(tag) { } - - const ui64 Tag = 0; + + TEvWakeup(ui64 tag = 0) : Tag(tag) { } + + const ui64 Tag = 0; }; struct TEvSubscribe: public TEventBase<TEvSubscribe, TSystem::Subscribe> { @@ -205,14 +205,14 @@ namespace NActors { } }; - struct TEvGone: public TEventBase<TEvGone, TSystem::Gone> { - DEFINE_SIMPLE_LOCAL_EVENT(TEvGone, "System: TEvGone") + struct TEvGone: public TEventBase<TEvGone, TSystem::Gone> { + DEFINE_SIMPLE_LOCAL_EVENT(TEvGone, "System: TEvGone") }; - + struct TEvInvokeResult; - using TEvPoisonPill = TEvPoison; // Legacy name, deprecated - using TEvActorDied = TEvGone; + using TEvPoisonPill = TEvPoison; // Legacy name, deprecated + using TEvActorDied = TEvGone; }; } diff --git a/library/cpp/actors/core/executor_pool_base.cpp b/library/cpp/actors/core/executor_pool_base.cpp index c3b9999168..1fb66adc61 100644 --- a/library/cpp/actors/core/executor_pool_base.cpp +++ b/library/cpp/actors/core/executor_pool_base.cpp @@ -8,8 +8,8 @@ namespace NActors { LWTRACE_USING(ACTORLIB_PROVIDER); void DoActorInit(TActorSystem* sys, IActor* actor, const TActorId& self, const TActorId& owner) { - actor->SelfActorId = self; - actor->Registered(sys, owner); + actor->SelfActorId = self; + actor->Registered(sys, owner); } TExecutorPoolBaseMailboxed::TExecutorPoolBaseMailboxed(ui32 poolId, ui32 maxActivityType) @@ -98,7 +98,7 @@ namespace NActors { // do init const TActorId actorId(ActorSystem->NodeId, PoolId, localActorId, hint); - DoActorInit(ActorSystem, actor, actorId, parentId); + DoActorInit(ActorSystem, actor, actorId, parentId); // Once we unlock the mailbox the actor starts running and we cannot use the pointer any more actor = nullptr; @@ -145,7 +145,7 @@ namespace NActors { mailbox->AttachActor(localActorId, actor); const TActorId actorId(ActorSystem->NodeId, PoolId, localActorId, hint); - DoActorInit(ActorSystem, actor, actorId, parentId); + DoActorInit(ActorSystem, actor, actorId, parentId); NHPTimer::STime elapsed = GetCycleCountFast() - hpstart; if (elapsed > 1000000) { LWPROBE(SlowRegisterAdd, PoolId, NHPTimer::GetSeconds(elapsed) * 1000.0); diff --git a/library/cpp/actors/core/executor_thread.cpp b/library/cpp/actors/core/executor_thread.cpp index 446b651efd..7a34944ae2 100644 --- a/library/cpp/actors/core/executor_thread.cpp +++ b/library/cpp/actors/core/executor_thread.cpp @@ -67,10 +67,10 @@ namespace NActors { DyingActors.push_back(THolder(actor)); } - void TExecutorThread::DropUnregistered() { - DyingActors.clear(); // here is actual destruction of actors - } - + void TExecutorThread::DropUnregistered() { + DyingActors.clear(); // here is actual destruction of actors + } + void TExecutorThread::Schedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie) { ++CurrentActorScheduledEventsCounter; Ctx.Executor->Schedule(deadline, ev, cookie, Ctx.WorkerId); @@ -181,7 +181,7 @@ namespace NActors { size_t dyingActorsCnt = DyingActors.size(); Ctx.UpdateActorsStats(dyingActorsCnt); if (dyingActorsCnt) { - DropUnregistered(); + DropUnregistered(); actor = nullptr; } diff --git a/library/cpp/actors/core/executor_thread.h b/library/cpp/actors/core/executor_thread.h index 9d3c573f0d..a1ef9786f6 100644 --- a/library/cpp/actors/core/executor_thread.h +++ b/library/cpp/actors/core/executor_thread.h @@ -43,7 +43,7 @@ namespace NActors { const TActorId& parentId = TActorId()); TActorId RegisterActor(IActor* actor, TMailboxHeader* mailbox, ui32 hint, const TActorId& parentId = TActorId()); void UnregisterActor(TMailboxHeader* mailbox, ui64 localActorId); - void DropUnregistered(); + void DropUnregistered(); const std::vector<THolder<IActor>>& GetUnregistered() const { return DyingActors; } void Schedule(TInstant deadline, TAutoPtr<IEventHandle> ev, ISchedulerCookie* cookie = nullptr); diff --git a/library/cpp/actors/core/log.cpp b/library/cpp/actors/core/log.cpp index 5f63b5af58..ca0c6e60ea 100644 --- a/library/cpp/actors/core/log.cpp +++ b/library/cpp/actors/core/log.cpp @@ -251,11 +251,11 @@ namespace NActors { const auto prio = ev.Level.ToPrio(); - switch (prio) { - case ::NActors::NLog::EPrio::Alert: + switch (prio) { + case ::NActors::NLog::EPrio::Alert: Metrics->IncAlertMsgs(); break; - case ::NActors::NLog::EPrio::Emerg: + case ::NActors::NLog::EPrio::Emerg: Metrics->IncEmergMsgs(); break; default: @@ -344,10 +344,10 @@ namespace NActors { str << "<a href='logger?c=" << i << "'>" << name << "</a>"; } TABLED() { - str << PriorityToString(EPrio(componentSettings.Raw.X.Level)); + str << PriorityToString(EPrio(componentSettings.Raw.X.Level)); } TABLED() { - str << PriorityToString(EPrio(componentSettings.Raw.X.SamplingLevel)); + str << PriorityToString(EPrio(componentSettings.Raw.X.SamplingLevel)); } TABLED() { str << componentSettings.Raw.X.SamplingRate; @@ -421,11 +421,11 @@ namespace NActors { UL() { LI() { str << "Priority: " - << NLog::PriorityToString(NLog::EPrio(componentSettings.Raw.X.Level)); + << NLog::PriorityToString(NLog::EPrio(componentSettings.Raw.X.Level)); } LI() { str << "Sampling priority: " - << NLog::PriorityToString(NLog::EPrio(componentSettings.Raw.X.SamplingLevel)); + << NLog::PriorityToString(NLog::EPrio(componentSettings.Raw.X.SamplingLevel)); } LI() { str << "Sampling rate: " @@ -444,7 +444,7 @@ namespace NActors { for (int p = NLog::PRI_EMERG; p <= NLog::PRI_TRACE; ++p) { LI() { str << "<a href='logger?c=" << component << "&p=" << p << "'>" - << NLog::PriorityToString(NLog::EPrio(p)) << "</a>"; + << NLog::PriorityToString(NLog::EPrio(p)) << "</a>"; } } } @@ -455,7 +455,7 @@ namespace NActors { for (int p = NLog::PRI_EMERG; p <= NLog::PRI_TRACE; ++p) { LI() { str << "<a href='logger?c=" << component << "&sp=" << p << "'>" - << NLog::PriorityToString(NLog::EPrio(p)) << "</a>"; + << NLog::PriorityToString(NLog::EPrio(p)) << "</a>"; } } } @@ -519,7 +519,7 @@ namespace NActors { TABLER() { TABLED() { str << "<a href = 'logger?c=-1&p=" << p << "'>" - << NLog::PriorityToString(NLog::EPrio(p)) << "</a>"; + << NLog::PriorityToString(NLog::EPrio(p)) << "</a>"; } } } @@ -541,7 +541,7 @@ namespace NActors { TABLER() { TABLED() { str << "<a href = 'logger?c=-1&sp=" << p << "'>" - << NLog::PriorityToString(NLog::EPrio(p)) << "</a>"; + << NLog::PriorityToString(NLog::EPrio(p)) << "</a>"; } } } @@ -576,8 +576,8 @@ namespace NActors { bool TLoggerActor::OutputRecord(TInstant time, NLog::EPrio priority, NLog::EComponent component, const TString& formatted) noexcept try { - const auto logPrio = ::ELogPriority(ui16(priority)); - + const auto logPrio = ::ELogPriority(ui16(priority)); + char buf[TimeBufSize]; switch (Settings->Format) { case NActors::NLog::TSettings::PLAIN_FULL_FORMAT: { diff --git a/library/cpp/actors/core/log.h b/library/cpp/actors/core/log.h index c11a7cf3c1..65e75b9909 100644 --- a/library/cpp/actors/core/log.h +++ b/library/cpp/actors/core/log.h @@ -2,7 +2,7 @@ #include "defs.h" -#include "log_iface.h" +#include "log_iface.h" #include "log_settings.h" #include "actorsystem.h" #include "events.h" @@ -122,7 +122,7 @@ namespace NActors { //////////////////////////////////////////////////////////////////////////////// // SET LOG LEVEL FOR A COMPONENT //////////////////////////////////////////////////////////////////////////////// - class TLogComponentLevelRequest: public TEventLocal<TLogComponentLevelRequest, int(NLog::EEv::LevelReq)> { + class TLogComponentLevelRequest: public TEventLocal<TLogComponentLevelRequest, int(NLog::EEv::LevelReq)> { public: // set given priority for the component TLogComponentLevelRequest(NLog::EPriority priority, NLog::EComponent component) @@ -145,7 +145,7 @@ namespace NActors { friend class TLoggerActor; }; - class TLogComponentLevelResponse: public TEventLocal<TLogComponentLevelResponse, int(NLog::EEv::LevelResp)> { + class TLogComponentLevelResponse: public TEventLocal<TLogComponentLevelResponse, int(NLog::EEv::LevelResp)> { public: TLogComponentLevelResponse(int code, const TString& explanation) : Code(code) @@ -166,7 +166,7 @@ namespace NActors { TString Explanation; }; - class TLogIgnored: public TEventLocal<TLogIgnored, int(NLog::EEv::Ignored)> { + class TLogIgnored: public TEventLocal<TLogIgnored, int(NLog::EEv::Ignored)> { public: TLogIgnored() { } @@ -213,7 +213,7 @@ namespace NActors { void StateFunc(TAutoPtr<IEventHandle>& ev, const TActorContext& ctx) { switch (ev->GetTypeRewrite()) { HFunc(TLogIgnored, HandleIgnoredEvent); - HFunc(NLog::TEvLog, HandleLogEvent); + HFunc(NLog::TEvLog, HandleLogEvent); HFunc(TLogComponentLevelRequest, HandleLogComponentLevelRequest); HFunc(NMon::TEvHttpInfo, HandleMonInfo); } @@ -246,7 +246,7 @@ namespace NActors { void BecomeDefunct(); void HandleIgnoredEvent(TLogIgnored::TPtr& ev, const NActors::TActorContext& ctx); void HandleIgnoredEventDrop(); - void HandleLogEvent(NLog::TEvLog::TPtr& ev, const TActorContext& ctx); + void HandleLogEvent(NLog::TEvLog::TPtr& ev, const TActorContext& ctx); void HandleLogEventDrop(const NLog::TEvLog::TPtr& ev); void HandleLogComponentLevelRequest(TLogComponentLevelRequest::TPtr& ev, const TActorContext& ctx); void HandleMonInfo(NMon::TEvHttpInfo::TPtr& ev, const TActorContext& ctx); diff --git a/library/cpp/actors/core/log_iface.h b/library/cpp/actors/core/log_iface.h index b331db9ca8..0ca9c14b91 100644 --- a/library/cpp/actors/core/log_iface.h +++ b/library/cpp/actors/core/log_iface.h @@ -1,12 +1,12 @@ -#pragma once - -#include "events.h" -#include "event_local.h" - -namespace NActors { +#pragma once + +#include "events.h" +#include "event_local.h" + +namespace NActors { namespace NLog { using EComponent = int; - + enum EPriority : ui16 { // migrate it to EPrio whenever possible PRI_EMERG, PRI_ALERT, @@ -18,7 +18,7 @@ namespace NActors { PRI_DEBUG, PRI_TRACE }; - + enum class EPrio : ui16 { Emerg = 0, Alert = 1, @@ -30,39 +30,39 @@ namespace NActors { Debug = 7, Trace = 8, }; - + struct TLevel { TLevel(ui32 raw) : Raw(raw) { } - + TLevel(EPrio prio) : Raw((ui16(prio) + 1) << 8) { } - + EPrio ToPrio() const noexcept { const auto major = Raw >> 8; - + return major > 0 ? EPrio(major - 1) : EPrio::Emerg; } - + bool IsUrgentAbortion() const noexcept { return (Raw >> 8) == 0; } - + /* Generalized monotonic level value composed with major and minor - levels. Minor is used for verbosity within major, basic EPrio - mapped to (EPrio + 1, 0) and Major = 0 is reserved as special - space with meaning like EPrio::Emerg but with extened actions. - Thus logger should map Major = 0 to EPrio::Emerg if it have no - idea how to handle special emergency actions. - */ - + levels. Minor is used for verbosity within major, basic EPrio + mapped to (EPrio + 1, 0) and Major = 0 is reserved as special + space with meaning like EPrio::Emerg but with extened actions. + Thus logger should map Major = 0 to EPrio::Emerg if it have no + idea how to handle special emergency actions. + */ + ui32 Raw = 0; // ((ui16(EPrio) + 1) << 8) | ui8(minor) }; - + enum class EEv { Log = EventSpaceBegin(TEvents::ES_LOGGER), LevelReq, @@ -70,9 +70,9 @@ namespace NActors { Ignored, End }; - + static_assert(int(EEv::End) < EventSpaceEnd(TEvents::ES_LOGGER), ""); - + class TEvLog: public TEventLocal<TEvLog, int(EEv::Log)> { public: TEvLog(TInstant stamp, TLevel level, EComponent comp, const TString &line) @@ -90,7 +90,7 @@ namespace NActors { , Line(std::move(line)) { } - + TEvLog(EPriority prio, EComponent comp, TString line, TInstant time = TInstant::Now()) : Stamp(time) , Level(EPrio(prio)) @@ -98,12 +98,12 @@ namespace NActors { , Line(std::move(line)) { } - + const TInstant Stamp = TInstant::Max(); const TLevel Level; const EComponent Component = 0; TString Line; }; - + } -} +} diff --git a/library/cpp/actors/core/log_settings.cpp b/library/cpp/actors/core/log_settings.cpp index f52f2fc5d2..5a5b66b4ac 100644 --- a/library/cpp/actors/core/log_settings.cpp +++ b/library/cpp/actors/core/log_settings.cpp @@ -116,7 +116,7 @@ namespace NActors { str << titleName << " for all components has been changed to " - << PriorityToString(EPrio(priority)); + << PriorityToString(EPrio(priority)); explanation = str.Str(); return 0; } else { @@ -136,8 +136,8 @@ namespace NActors { AtomicSet(ComponentInfo[component], settings.Raw.Data); TStringStream str; str << titleName << " for the component " << ComponentNames[component] - << " has been changed from " << PriorityToString(EPrio(oldPriority)) - << " to " << PriorityToString(EPrio(priority)); + << " has been changed from " << PriorityToString(EPrio(oldPriority)) + << " to " << PriorityToString(EPrio(priority)); explanation = str.Str(); return 0; } diff --git a/library/cpp/actors/core/log_settings.h b/library/cpp/actors/core/log_settings.h index 7fe4504edd..7f9ea16553 100644 --- a/library/cpp/actors/core/log_settings.h +++ b/library/cpp/actors/core/log_settings.h @@ -1,32 +1,32 @@ #pragma once #include "actor.h" -#include "log_iface.h" +#include "log_iface.h" #include <util/generic/vector.h> #include <util/digest/murmur.h> #include <util/random/easy.h> namespace NActors { namespace NLog { - inline const char* PriorityToString(EPrio priority) { + inline const char* PriorityToString(EPrio priority) { switch (priority) { - case EPrio::Emerg: + case EPrio::Emerg: return "EMERG"; - case EPrio::Alert: + case EPrio::Alert: return "ALERT"; - case EPrio::Crit: + case EPrio::Crit: return "CRIT"; - case EPrio::Error: + case EPrio::Error: return "ERROR"; - case EPrio::Warn: + case EPrio::Warn: return "WARN"; - case EPrio::Notice: + case EPrio::Notice: return "NOTICE"; - case EPrio::Info: + case EPrio::Info: return "INFO"; - case EPrio::Debug: + case EPrio::Debug: return "DEBUG"; - case EPrio::Trace: + case EPrio::Trace: return "TRACE"; default: return "UNKNOWN"; diff --git a/library/cpp/actors/dnscachelib/dnscache.cpp b/library/cpp/actors/dnscachelib/dnscache.cpp index 649339ddb2..c966fd7b13 100644 --- a/library/cpp/actors/dnscachelib/dnscache.cpp +++ b/library/cpp/actors/dnscachelib/dnscache.cpp @@ -7,7 +7,7 @@ #include <util/datetime/systime.h> const TDnsCache::THost TDnsCache::NullHost; - + LWTRACE_USING(DNSCACHELIB_PROVIDER); static_assert(sizeof(ares_channel) == sizeof(void*), "expect sizeof(ares_channel) == sizeof(void *)"); @@ -22,7 +22,7 @@ TDnsCache::TDnsCache(bool allowIpv4, bool allowIpv6, time_t lifetime, time_t neg , ACacheMisses(0) , PtrCacheHits(0) , PtrCacheMisses(0) -{ +{ #ifdef _win_ if (ares_library_init(ARES_LIB_INIT_WIN32) != ARES_SUCCESS) { LWPROBE(AresInitFailed); @@ -53,97 +53,97 @@ TDnsCache::~TDnsCache(void) { } TString TDnsCache::GetHostByAddr(const NAddr::IRemoteAddr& addr) { - in6_addr key; - - if (addr.Addr()->sa_family == AF_INET6) { + in6_addr key; + + if (addr.Addr()->sa_family == AF_INET6) { const struct sockaddr_in6* s6 = (const struct sockaddr_in6*)(addr.Addr()); - memcpy(&key, &s6->sin6_addr, sizeof(s6->sin6_addr)); - } else if (addr.Addr()->sa_family == AF_INET) { + memcpy(&key, &s6->sin6_addr, sizeof(s6->sin6_addr)); + } else if (addr.Addr()->sa_family == AF_INET) { const struct sockaddr_in* s4 = (const struct sockaddr_in*)(addr.Addr()); - memset(&key, 0, sizeof(key)); - memcpy(&key, &s4->sin_addr, sizeof(s4->sin_addr)); - } else { - return ""; - } + memset(&key, 0, sizeof(key)); + memcpy(&key, &s4->sin_addr, sizeof(s4->sin_addr)); + } else { + return ""; + } const TAddr& host = ResolveAddr(key, addr.Addr()->sa_family); - - return host.Hostname; -} - + + return host.Hostname; +} + TIpHost TDnsCache::Get(const TString& hostname) { - if (!AllowIpV4) - return TIpHost(-1); - + if (!AllowIpV4) + return TIpHost(-1); + const THost& addr = Resolve(hostname, AF_INET); - + TGuard<TMutex> lock(CacheMtx); - if (addr.AddrsV4.empty()) { - return TIpHost(-1); - } - return addr.AddrsV4.front(); -} - -NAddr::IRemoteAddrPtr TDnsCache::GetAddr( + if (addr.AddrsV4.empty()) { + return TIpHost(-1); + } + return addr.AddrsV4.front(); +} + +NAddr::IRemoteAddrPtr TDnsCache::GetAddr( const TString& hostname, int family, TIpPort port, bool cacheOnly) { - if (family != AF_INET && AllowIpV6) { + if (family != AF_INET && AllowIpV6) { const THost& addr = Resolve(hostname, AF_INET6, cacheOnly); - + TGuard<TMutex> lock(CacheMtx); - if (!addr.AddrsV6.empty()) { - struct sockaddr_in6 sin6; - Zero(sin6); - sin6.sin6_family = AF_INET6; - sin6.sin6_addr = addr.AddrsV6.front(); - sin6.sin6_port = HostToInet(port); - + if (!addr.AddrsV6.empty()) { + struct sockaddr_in6 sin6; + Zero(sin6); + sin6.sin6_family = AF_INET6; + sin6.sin6_addr = addr.AddrsV6.front(); + sin6.sin6_port = HostToInet(port); + return MakeHolder<NAddr::TIPv6Addr>(sin6); - } - } - - if (family != AF_INET6 && AllowIpV4) { + } + } + + if (family != AF_INET6 && AllowIpV4) { const THost& addr = Resolve(hostname, AF_INET, cacheOnly); - + TGuard<TMutex> lock(CacheMtx); - if (!addr.AddrsV4.empty()) { + if (!addr.AddrsV4.empty()) { return MakeHolder<NAddr::TIPv4Addr>(TIpAddress(addr.AddrsV4.front(), port)); - } - } - + } + } + LWPROBE(FamilyMismatch, family, AllowIpV4, AllowIpV6); return nullptr; -} - -void TDnsCache::GetAllAddresses( +} + +void TDnsCache::GetAllAddresses( const TString& hostname, TVector<NAddr::IRemoteAddrPtr>& addrs) { - if (AllowIpV4) { + if (AllowIpV4) { const THost& addr4 = Resolve(hostname, AF_INET); TGuard<TMutex> lock(CacheMtx); - for (size_t i = 0; i < addr4.AddrsV4.size(); i++) { + for (size_t i = 0; i < addr4.AddrsV4.size(); i++) { addrs.push_back(MakeHolder<NAddr::TIPv4Addr>(TIpAddress(addr4.AddrsV4[i], 0))); - } - } - - if (AllowIpV6) { + } + } + + if (AllowIpV6) { const THost& addr6 = Resolve(hostname, AF_INET6); - struct sockaddr_in6 sin6; - Zero(sin6); - sin6.sin6_family = AF_INET6; + struct sockaddr_in6 sin6; + Zero(sin6); + sin6.sin6_family = AF_INET6; TGuard<TMutex> lock(CacheMtx); - for (size_t i = 0; i < addr6.AddrsV6.size(); i++) { - sin6.sin6_addr = addr6.AddrsV6[i]; - + for (size_t i = 0; i < addr6.AddrsV6.size(); i++) { + sin6.sin6_addr = addr6.AddrsV6[i]; + addrs.push_back(MakeHolder<NAddr::TIPv6Addr>(sin6)); - } - } -} - + } + } +} + void TDnsCache::GetStats(ui64& a_cache_hits, ui64& a_cache_misses, ui64& ptr_cache_hits, ui64& ptr_cache_misses) { TGuard<TMutex> lock(CacheMtx); @@ -169,11 +169,11 @@ bool TDnsCache::THost::IsStale(int family, const TDnsCache* ctx) const noexcept const TDnsCache::THost& TDnsCache::Resolve(const TString& hostname, int family, bool cacheOnly) { - if (!ValidateHName(hostname)) { + if (!ValidateHName(hostname)) { LWPROBE(ResolveNullHost, hostname, family); - return NullHost; - } - + return NullHost; + } + THostCache::iterator p; Y_ASSERT(family == AF_INET || family == AF_INET6); @@ -232,9 +232,9 @@ TDnsCache::Resolve(const TString& hostname, int family, bool cacheOnly) { } bool TDnsCache::ValidateHName(const TString& name) const noexcept { - return name.size() > 0; -} - + return name.size() > 0; +} + const TDnsCache::TAddr& TDnsCache::ResolveAddr(const in6_addr& addr, int family) { TAddrCache::iterator p; @@ -282,7 +282,7 @@ const TDnsCache::TAddr& TDnsCache::ResolveAddr(const in6_addr& addr, int family) } void TDnsCache::WaitTask(TAtomic& flag) { - const TInstant start = TInstant(TTimeKeeper::GetTimeval()); + const TInstant start = TInstant(TTimeKeeper::GetTimeval()); while (AtomicGet(flag)) { ares_channel chan = static_cast<ares_channel>(Channel); @@ -319,11 +319,11 @@ void TDnsCache::WaitTask(TAtomic& flag) { Y_ASSERT(nfds != 0); - const TDuration left = TInstant(TTimeKeeper::GetTimeval()) - start; - const TDuration wait = Max(Timeout - left, TDuration::Zero()); - - int rv = poll(pfd, nfds, wait.MilliSeconds()); - + const TDuration left = TInstant(TTimeKeeper::GetTimeval()) - start; + const TDuration wait = Max(Timeout - left, TDuration::Zero()); + + int rv = poll(pfd, nfds, wait.MilliSeconds()); + if (rv == -1) { if (errno == EINTR) { continue; @@ -351,10 +351,10 @@ void TDnsCache::WaitTask(TAtomic& flag) { : ARES_SOCKET_BAD); } } - - if (start + Timeout <= TInstant(TTimeKeeper::GetTimeval())) { - break; - } + + if (start + Timeout <= TInstant(TTimeKeeper::GetTimeval())) { + break; + } } } diff --git a/library/cpp/actors/dnscachelib/dnscache.h b/library/cpp/actors/dnscachelib/dnscache.h index 3313a251a1..2d6adb3a36 100644 --- a/library/cpp/actors/dnscachelib/dnscache.h +++ b/library/cpp/actors/dnscachelib/dnscache.h @@ -5,7 +5,7 @@ #include <util/generic/vector.h> #include <util/network/address.h> #include <util/system/mutex.h> -#include <util/datetime/base.h> +#include <util/datetime/base.h> /** Asynchronous DNS resolver. * @@ -19,7 +19,7 @@ class TDnsCache { public: TDnsCache(bool allowIpv4 = true, bool allowIpv6 = true, time_t entry_lifetime = 1800, time_t neg_lifetime = 1, ui32 request_timeout = 500000); - ~TDnsCache(); + ~TDnsCache(); TString GetHostByAddr(const NAddr::IRemoteAddr&); @@ -37,9 +37,9 @@ public: void GetStats(ui64& a_cache_hits, ui64& a_cache_misses, ui64& ptr_cache_hits, ui64& ptr_cache_misses); -protected: +protected: bool ValidateHName(const TString& host) const noexcept; - + private: struct TGHBNContext { TDnsCache* Owner; @@ -52,7 +52,7 @@ private: in6_addr Addr; }; - struct THost { + struct THost { THost() noexcept { } @@ -73,8 +73,8 @@ private: }; typedef TMap<TString, THost> THostCache; - - struct TAddr { + + struct TAddr { TString Hostname; time_t Resolved = 0; time_t NotFound = 0; @@ -112,7 +112,7 @@ private: const time_t EntryLifetime; const time_t NegativeLifetime; - const TDuration Timeout; + const TDuration Timeout; const bool AllowIpV4; const bool AllowIpV6; @@ -124,8 +124,8 @@ private: ui64 PtrCacheHits; ui64 PtrCacheMisses; - const static THost NullHost; - + const static THost NullHost; + TMutex AresMtx; void* Channel; diff --git a/library/cpp/actors/testlib/test_runtime.cpp b/library/cpp/actors/testlib/test_runtime.cpp index 6fa25b9965..7c4871399d 100644 --- a/library/cpp/actors/testlib/test_runtime.cpp +++ b/library/cpp/actors/testlib/test_runtime.cpp @@ -1,4 +1,4 @@ -#include "test_runtime.h" +#include "test_runtime.h" #include <library/cpp/actors/core/actor_bootstrapped.h> #include <library/cpp/actors/core/callstack.h> @@ -22,16 +22,16 @@ bool VERBOSE = false; const bool PRINT_EVENT_BODY = false; -namespace { - - TString MakeClusterId() { - pid_t pid = getpid(); - TStringBuilder uuid; - uuid << "Cluster for process with id: " << pid; - return uuid; - } -} +namespace { + TString MakeClusterId() { + pid_t pid = getpid(); + TStringBuilder uuid; + uuid << "Cluster for process with id: " << pid; + return uuid; + } +} + namespace NActors { ui64 TScheduledEventQueueItem::NextUniqueId = 0; @@ -80,7 +80,7 @@ namespace NActors { TTestActorRuntimeBase::TNodeDataBase::~TNodeDataBase() { Stop(); } - + class TTestActorRuntimeBase::TEdgeActor : public TActor<TEdgeActor> { public: @@ -326,7 +326,7 @@ namespace NActors { } TDuration delay = (deadline - now); - if (Runtime->SingleSysEnv || !Runtime->ScheduledEventFilterFunc(*Runtime, ev, delay, deadline)) { + if (Runtime->SingleSysEnv || !Runtime->ScheduledEventFilterFunc(*Runtime, ev, delay, deadline)) { ui32 mailboxHint = ev->GetRecipientRewrite().Hint(); Runtime->GetMailbox(Runtime->FirstNodeId + NodeIndex, mailboxHint).Schedule(TScheduledEventQueueItem(deadline, ev, cookie)); Runtime->MailboxesHasEvents.Signal(); @@ -365,7 +365,7 @@ namespace NActors { } ui32 mailboxHint = ev->GetRecipientRewrite().Hint(); - if (ev->GetTypeRewrite() == ui32(NActors::NLog::EEv::Log)) { + if (ev->GetTypeRewrite() == ui32(NActors::NLog::EEv::Log)) { const NActors::TActorId loggerActorId = NActors::TActorId(nodeId, "logger"); TActorId logger = node->ActorSystem->LookupLocalService(loggerActorId); if (ev->GetRecipientRewrite() == logger) { @@ -451,15 +451,15 @@ namespace NActors { TTestActorRuntimeBase::TTestActorRuntimeBase(THeSingleSystemEnv) : TTestActorRuntimeBase(1, 1, false) - { - SingleSysEnv = true; - } - + { + SingleSysEnv = true; + } + TTestActorRuntimeBase::TTestActorRuntimeBase(ui32 nodeCount, ui32 dataCenterCount, bool useRealThreads) : ScheduledCount(0) , ScheduledLimit(100000) , MainThreadId(TThread::CurrentThreadId()) - , ClusterUUID(MakeClusterId()) + , ClusterUUID(MakeClusterId()) , FirstNodeId(NextNodeId) , NodeCount(nodeCount) , DataCenterCount(dataCenterCount) @@ -741,7 +741,7 @@ namespace NActors { void TTestActorRuntimeBase::InitNodes() { NextNodeId += NodeCount; Y_VERIFY(NodeCount > 0); - + for (ui32 nodeIndex = 0; nodeIndex < NodeCount; ++nodeIndex) { auto nodeIt = Nodes.emplace(FirstNodeId + nodeIndex, GetNodeFactory().CreateNode()).first; TNodeDataBase* node = nodeIt->second.Get(); @@ -900,7 +900,7 @@ namespace NActors { const TActorId actorId(FirstNodeId + nodeIndex, poolId, localActorId, hint); ActorNames[actorId] = TypeName(*actor); RegistrationObserver(*this, parentId ? parentId : CurrentRecipient, actorId); - DoActorInit(node->ActorSystem.Get(), actor, actorId, parentId ? parentId : CurrentRecipient); + DoActorInit(node->ActorSystem.Get(), actor, actorId, parentId ? parentId : CurrentRecipient); switch (mailboxType) { case TMailboxType::Simple: @@ -944,7 +944,7 @@ namespace NActors { const TActorId actorId(FirstNodeId + nodeIndex, poolId, localActorId, hint); ActorNames[actorId] = TypeName(*actor); RegistrationObserver(*this, parentId ? parentId : CurrentRecipient, actorId); - DoActorInit(node->ActorSystem.Get(), actor, actorId, parentId ? parentId : CurrentRecipient); + DoActorInit(node->ActorSystem.Get(), actor, actorId, parentId ? parentId : CurrentRecipient); return actorId; } @@ -1583,7 +1583,7 @@ namespace NActors { TCallstack::GetTlsCallstack().SetLinesToSkip(); #endif recipientActor->Receive(evHolder, ctx); - node->ExecutorThread->DropUnregistered(); + node->ExecutorThread->DropUnregistered(); } CurrentRecipient = TActorId(); TlsActivationContext = prevTlsActivationContext; @@ -1683,24 +1683,24 @@ namespace NActors { NActors::TMailboxType::Simple, InterconnectPoolId())); } - if (!SingleSysEnv) { // Single system env should do this self - TAutoPtr<TLogBackend> logBackend = LogBackend ? LogBackend : NActors::CreateStderrBackend(); - NActors::TLoggerActor *loggerActor = new NActors::TLoggerActor(node->LogSettings, + if (!SingleSysEnv) { // Single system env should do this self + TAutoPtr<TLogBackend> logBackend = LogBackend ? LogBackend : NActors::CreateStderrBackend(); + NActors::TLoggerActor *loggerActor = new NActors::TLoggerActor(node->LogSettings, logBackend, GetCountersForComponent(node->DynamicCounters, "utils")); NActors::TActorSetupCmd loggerActorCmd(loggerActor, NActors::TMailboxType::Simple, node->GetLoggerPoolId()); std::pair<NActors::TActorId, NActors::TActorSetupCmd> loggerActorPair(node->LogSettings->LoggerActorId, loggerActorCmd); - setup->LocalServices.push_back(loggerActorPair); - } + setup->LocalServices.push_back(loggerActorPair); + } return THolder<TActorSystem>(new TActorSystem(setup, node->GetAppData(), node->LogSettings)); } TActorSystem* TTestActorRuntimeBase::SingleSys() const { - Y_VERIFY(Nodes.size() == 1, "Works only for single system env"); - - return Nodes.begin()->second->ActorSystem.Get(); - } - + Y_VERIFY(Nodes.size() == 1, "Works only for single system env"); + + return Nodes.begin()->second->ActorSystem.Get(); + } + TActorSystem* TTestActorRuntimeBase::GetAnyNodeActorSystem() { for (auto& x : Nodes) { return x.second->ActorSystem.Get(); diff --git a/library/cpp/actors/testlib/test_runtime.h b/library/cpp/actors/testlib/test_runtime.h index 26e3b45c98..38e964835c 100644 --- a/library/cpp/actors/testlib/test_runtime.h +++ b/library/cpp/actors/testlib/test_runtime.h @@ -39,8 +39,8 @@ const TDuration DEFAULT_DISPATCH_TIMEOUT = NSan::PlainOrUnderSanitizer( namespace NActors { - struct THeSingleSystemEnv { }; - + struct THeSingleSystemEnv { }; + struct TEventMailboxId { TEventMailboxId() : NodeId(0) @@ -200,7 +200,7 @@ namespace NActors { typedef std::function<bool(TTestActorRuntimeBase& runtime, TAutoPtr<IEventHandle>& event)> TEventFilter; typedef std::function<bool(TTestActorRuntimeBase& runtime, TAutoPtr<IEventHandle>& event, TDuration delay, TInstant& deadline)> TScheduledEventFilter; typedef std::function<void(TTestActorRuntimeBase& runtime, const TActorId& parentId, const TActorId& actorId)> TRegistrationObserver; - + TTestActorRuntimeBase(THeSingleSystemEnv); TTestActorRuntimeBase(ui32 nodeCount, ui32 dataCenterCount, bool UseRealThreads); @@ -284,7 +284,7 @@ namespace NActors { return Nodes[FirstNodeId + nodeIdx]->LogSettings; } - TActorSystem* SingleSys() const; + TActorSystem* SingleSys() const; TActorSystem* GetAnyNodeActorSystem(); TActorSystem* GetActorSystem(ui32 nodeId); template <typename TEvent> @@ -471,12 +471,12 @@ namespace NActors { UseRealInterconnect = true; } - protected: + protected: struct TNodeDataBase; TNodeDataBase* GetRawNode(ui32 node) const { - return Nodes.at(FirstNodeId + node).Get(); - } - + return Nodes.at(FirstNodeId + node).Get(); + } + static IExecutorPool* CreateExecutorPoolStub(TTestActorRuntimeBase* runtime, ui32 nodeIndex, TNodeDataBase* node, ui32 poolId); virtual TIntrusivePtr<NMonitoring::TDynamicCounters> GetCountersForComponent(TIntrusivePtr<NMonitoring::TDynamicCounters> counters, const char* component) { Y_UNUSED(counters); @@ -492,7 +492,7 @@ namespace NActors { Y_UNUSED(setup); } - private: + private: IActor* FindActor(const TActorId& actorId, TNodeDataBase* node) const; void SendInternal(IEventHandle* ev, ui32 nodeIndex, bool viaActorSystem); TEventMailBox& GetMailbox(ui32 nodeId, ui32 hint); @@ -507,12 +507,12 @@ namespace NActors { THolder<TTempDir> TmpDir; const TThread::TId MainThreadId; - protected: + protected: bool UseRealInterconnect = false; TInterconnectMock InterconnectMock; bool IsInitialized = false; bool SingleSysEnv = false; - const TString ClusterUUID; + const TString ClusterUUID; const ui32 FirstNodeId; const ui32 NodeCount; const ui32 DataCenterCount; @@ -535,7 +535,7 @@ namespace NActors { TIntrusivePtr<IRandomProvider> RandomProvider; TIntrusivePtr<ITimeProvider> TimeProvider; - protected: + protected: struct TNodeDataBase: public TThrRefBase { TNodeDataBase(); void Stop(); @@ -598,7 +598,7 @@ namespace NActors { protected: THolder<INodeFactory> NodeFactory{new TDefaultNodeFactory}; - private: + private: void InitNode(TNodeDataBase* node, size_t idx); struct TDispatchContext { diff --git a/library/cpp/actors/testlib/ya.make b/library/cpp/actors/testlib/ya.make index 1afb3f6059..87dc50175e 100644 --- a/library/cpp/actors/testlib/ya.make +++ b/library/cpp/actors/testlib/ya.make @@ -1,26 +1,26 @@ -LIBRARY() - -OWNER( - g:kikimr -) - -SRCS( - test_runtime.cpp -) - -PEERDIR( +LIBRARY() + +OWNER( + g:kikimr +) + +SRCS( + test_runtime.cpp +) + +PEERDIR( library/cpp/actors/core library/cpp/actors/interconnect/mock library/cpp/actors/protos library/cpp/random_provider library/cpp/time_provider -) - -IF (GCC) - CFLAGS(-fno-devirtualize-speculatively) -ENDIF() - -END() +) + +IF (GCC) + CFLAGS(-fno-devirtualize-speculatively) +ENDIF() + +END() RECURSE_FOR_TESTS( ut diff --git a/library/cpp/lfalloc/lf_allocX64.h b/library/cpp/lfalloc/lf_allocX64.h index fd2a906d6f..588b051815 100644 --- a/library/cpp/lfalloc/lf_allocX64.h +++ b/library/cpp/lfalloc/lf_allocX64.h @@ -390,53 +390,53 @@ static char* AllocWithMMap(uintptr_t sz, EMMapMode mode) { return largeBlock; } -enum class ELarge : ui8 { - Free = 0, // block in free cache - Alloc = 1, // block is allocated - Gone = 2, // block was unmapped -}; - -struct TLargeBlk { - - static TLargeBlk* As(void *raw) { - return reinterpret_cast<TLargeBlk*>((char*)raw - 4096ll); - } - - static const TLargeBlk* As(const void *raw) { - return reinterpret_cast<const TLargeBlk*>((const char*)raw - 4096ll); - } - - void SetSize(size_t bytes, size_t pages) { - Pages = pages; - Bytes = bytes; - } - - void Mark(ELarge state) { - const ui64 marks[] = { - 0x8b38aa5ca4953c98, // ELarge::Free - 0xf916d33584eb5087, // ELarge::Alloc - 0xd33b0eca7651bc3f // ELarge::Gone - }; - - Token = size_t(marks[ui8(state)]); - } - - size_t Pages; // Total pages allocated with mmap like call - size_t Bytes; // Actually requested bytes by user - size_t Token; // Block state token, see ELarge enum. -}; - - -static void LargeBlockUnmap(void* p, size_t pages) { - const auto bytes = (pages + 1) * uintptr_t(4096); - - IncrementCounter(CT_MUNMAP, bytes); +enum class ELarge : ui8 { + Free = 0, // block in free cache + Alloc = 1, // block is allocated + Gone = 2, // block was unmapped +}; + +struct TLargeBlk { + + static TLargeBlk* As(void *raw) { + return reinterpret_cast<TLargeBlk*>((char*)raw - 4096ll); + } + + static const TLargeBlk* As(const void *raw) { + return reinterpret_cast<const TLargeBlk*>((const char*)raw - 4096ll); + } + + void SetSize(size_t bytes, size_t pages) { + Pages = pages; + Bytes = bytes; + } + + void Mark(ELarge state) { + const ui64 marks[] = { + 0x8b38aa5ca4953c98, // ELarge::Free + 0xf916d33584eb5087, // ELarge::Alloc + 0xd33b0eca7651bc3f // ELarge::Gone + }; + + Token = size_t(marks[ui8(state)]); + } + + size_t Pages; // Total pages allocated with mmap like call + size_t Bytes; // Actually requested bytes by user + size_t Token; // Block state token, see ELarge enum. +}; + + +static void LargeBlockUnmap(void* p, size_t pages) { + const auto bytes = (pages + 1) * uintptr_t(4096); + + IncrementCounter(CT_MUNMAP, bytes); IncrementCounter(CT_MUNMAP_CNT, 1); #ifdef _MSC_VER Y_ASSERT_NOBT(0); #else - TLargeBlk::As(p)->Mark(ELarge::Gone); - munmap((char*)p - 4096ll, bytes); + TLargeBlk::As(p)->Mark(ELarge::Gone); + munmap((char*)p - 4096ll, bytes); #endif } @@ -447,7 +447,7 @@ static int LB_LIMIT_TOTAL_SIZE = 500 * 1024 * 1024 / 4096; // do not keep more t static void* volatile lbFreePtrs[LB_BUF_HASH][LB_BUF_SIZE]; static TAtomic lbFreePageCount; - + static void* LargeBlockAlloc(size_t _nSize, ELFAllocCounter counter) { size_t pgCount = (_nSize + 4095) / 4096; #ifdef _MSC_VER @@ -466,16 +466,16 @@ static void* LargeBlockAlloc(size_t _nSize, ELFAllocCounter counter) { if (p == nullptr) continue; if (DoCas(&lbFreePtrs[lbHash][i], (void*)nullptr, p) == p) { - size_t realPageCount = TLargeBlk::As(p)->Pages; + size_t realPageCount = TLargeBlk::As(p)->Pages; if (realPageCount == pgCount) { AtomicAdd(lbFreePageCount, -pgCount); - TLargeBlk::As(p)->Mark(ELarge::Alloc); + TLargeBlk::As(p)->Mark(ELarge::Alloc); return p; } else { if (DoCas(&lbFreePtrs[lbHash][i], p, (void*)nullptr) != (void*)nullptr) { // block was freed while we were busy AtomicAdd(lbFreePageCount, -realPageCount); - LargeBlockUnmap(p, realPageCount); + LargeBlockUnmap(p, realPageCount); --i; } } @@ -484,8 +484,8 @@ static void* LargeBlockAlloc(size_t _nSize, ELFAllocCounter counter) { char* pRes = AllocWithMMap((pgCount + 1) * 4096ll, MM_HUGE); #endif pRes += 4096ll; - TLargeBlk::As(pRes)->SetSize(_nSize, pgCount); - TLargeBlk::As(pRes)->Mark(ELarge::Alloc); + TLargeBlk::As(pRes)->SetSize(_nSize, pgCount); + TLargeBlk::As(pRes)->Mark(ELarge::Alloc); return pRes; } @@ -498,9 +498,9 @@ static void FreeAllLargeBlockMem() { if (p == nullptr) continue; if (DoCas(&lbFreePtr[i], (void*)nullptr, p) == p) { - int pgCount = TLargeBlk::As(p)->Pages; + int pgCount = TLargeBlk::As(p)->Pages; AtomicAdd(lbFreePageCount, -pgCount); - LargeBlockUnmap(p, pgCount); + LargeBlockUnmap(p, pgCount); } } } @@ -513,9 +513,9 @@ static void LargeBlockFree(void* p, ELFAllocCounter counter) { #ifdef _MSC_VER VirtualFree((char*)p - 4096ll, 0, MEM_RELEASE); #else - size_t pgCount = TLargeBlk::As(p)->Pages; + size_t pgCount = TLargeBlk::As(p)->Pages; - TLargeBlk::As(p)->Mark(ELarge::Free); + TLargeBlk::As(p)->Mark(ELarge::Free); IncrementCounter(counter, pgCount * 4096ll); IncrementCounter(CT_SYSTEM_FREE, 4096ll); @@ -531,7 +531,7 @@ static void LargeBlockFree(void* p, ELFAllocCounter counter) { } } - LargeBlockUnmap(p, pgCount); + LargeBlockUnmap(p, pgCount); #endif } @@ -1644,23 +1644,23 @@ static Y_FORCE_INLINE void LFFree(void* p) { } } -static size_t LFGetSize(const void* p) { +static size_t LFGetSize(const void* p) { #if defined(LFALLOC_DBG) if (p == nullptr) return 0; - return GetAllocHeader(const_cast<void*>(p))->Size; + return GetAllocHeader(const_cast<void*>(p))->Size; #endif - uintptr_t chkOffset = ((const char*)p - ALLOC_START); + uintptr_t chkOffset = ((const char*)p - ALLOC_START); if (chkOffset >= N_MAX_WORKSET_SIZE) { if (p == nullptr) return 0; - return TLargeBlk::As(p)->Pages * 4096ll; + return TLargeBlk::As(p)->Pages * 4096ll; } - uintptr_t chunk = ((const char*)p - ALLOC_START) / N_CHUNK_SIZE; + uintptr_t chunk = ((const char*)p - ALLOC_START) / N_CHUNK_SIZE; ptrdiff_t nSizeIdx = chunkSizeIdx[chunk]; if (nSizeIdx <= 0) - return TLargeBlk::As(p)->Pages * 4096ll; + return TLargeBlk::As(p)->Pages * 4096ll; return nSizeIdxToSize[nSizeIdx]; } diff --git a/library/cpp/messagebus/acceptor.cpp b/library/cpp/messagebus/acceptor.cpp index 64a38619c2..de8810d02e 100644 --- a/library/cpp/messagebus/acceptor.cpp +++ b/library/cpp/messagebus/acceptor.cpp @@ -19,7 +19,7 @@ TAcceptor::TAcceptor(TBusSessionImpl* session, ui64 acceptorId, SOCKET socket, c : TActor<TAcceptor>(session->Queue->WorkQueue.Get()) , AcceptorId(acceptorId) , Session(session) - , GranStatus(session->Config.Secret.StatusFlushPeriod) + , GranStatus(session->Config.Secret.StatusFlushPeriod) { SetNonBlock(socket, true); @@ -30,7 +30,7 @@ TAcceptor::TAcceptor(TBusSessionImpl* session, ui64 acceptorId, SOCKET socket, c Stats.Fd = socket; Stats.ListenAddr = addr; - SendStatus(TInstant::Now()); + SendStatus(TInstant::Now()); } void TAcceptor::Act(TDefaultTag) { @@ -40,8 +40,8 @@ void TAcceptor::Act(TDefaultTag) { return; } - TInstant now = TInstant::Now(); - + TInstant now = TInstant::Now(); + if (state == SS_SHUTDOWN_COMMAND) { if (!!Channel) { Channel->Unregister(); @@ -49,7 +49,7 @@ void TAcceptor::Act(TDefaultTag) { Stats.Fd = INVALID_SOCKET; } - SendStatus(now); + SendStatus(now); Session->GetDeadAcceptorStatusQueue()->EnqueueAndSchedule(Stats); Stats.ResetIncremental(); @@ -96,7 +96,7 @@ void TAcceptor::Act(TDefaultTag) { Session->GetOnAcceptQueue()->EnqueueAndSchedule(onAccept); - Stats.LastAcceptSuccessInstant = now; + Stats.LastAcceptSuccessInstant = now; ++Stats.AcceptSuccessCount; } @@ -105,11 +105,11 @@ void TAcceptor::Act(TDefaultTag) { Channel->EnableRead(); - SendStatus(now); + SendStatus(now); } -void TAcceptor::SendStatus(TInstant now) { - GranStatus.Listen.Update(Stats, now); +void TAcceptor::SendStatus(TInstant now) { + GranStatus.Listen.Update(Stats, now); } void TAcceptor::HandleEvent(SOCKET socket, void* cookie) { diff --git a/library/cpp/messagebus/acceptor.h b/library/cpp/messagebus/acceptor.h index 57cb010bf2..8ec2229d63 100644 --- a/library/cpp/messagebus/acceptor.h +++ b/library/cpp/messagebus/acceptor.h @@ -55,6 +55,6 @@ namespace NBus { TGranStatus GranStatus; }; - + } } diff --git a/library/cpp/messagebus/actor/queue_for_actor.h b/library/cpp/messagebus/actor/queue_for_actor.h index 40fa536b82..d26a546296 100644 --- a/library/cpp/messagebus/actor/queue_for_actor.h +++ b/library/cpp/messagebus/actor/queue_for_actor.h @@ -60,15 +60,15 @@ namespace NActor { temp.Shrink(); } } - + template <typename TFunc> void DequeueAllLikelyEmpty(const TFunc& func) { if (Y_LIKELY(IsEmpty())) { return; } - + DequeueAll(func); - } + } }; } diff --git a/library/cpp/messagebus/actor/temp_tls_vector.h b/library/cpp/messagebus/actor/temp_tls_vector.h index 675d92f5b0..407703d702 100644 --- a/library/cpp/messagebus/actor/temp_tls_vector.h +++ b/library/cpp/messagebus/actor/temp_tls_vector.h @@ -23,18 +23,18 @@ public: } ~TTempTlsVector() { - Clear(); - } - - void Clear() { + Clear(); + } + + void Clear() { Vector->clear(); } - + size_t Capacity() const noexcept { - return Vector->capacity(); - } - - void Shrink() { - Vector->shrink_to_fit(); - } + return Vector->capacity(); + } + + void Shrink() { + Vector->shrink_to_fit(); + } }; diff --git a/library/cpp/messagebus/config/netaddr.cpp b/library/cpp/messagebus/config/netaddr.cpp index 962ac538e2..c1cb356840 100644 --- a/library/cpp/messagebus/config/netaddr.cpp +++ b/library/cpp/messagebus/config/netaddr.cpp @@ -129,7 +129,7 @@ namespace NBus { ythrow TNetAddr::TError() << "cannot resolve " << host << ":" << port << " into " << Describe(requireVersion); } } - + TNetAddr::TNetAddr(const TNetworkAddress& na, EIpVersion requireVersion /*= EIP_VERSION_ANY*/, EIpVersion preferVersion /*= EIP_VERSION_ANY*/) : Ptr(MakeAddress(na, requireVersion, preferVersion)) { diff --git a/library/cpp/messagebus/config/netaddr.h b/library/cpp/messagebus/config/netaddr.h index b79c0cc355..ccb4b42810 100644 --- a/library/cpp/messagebus/config/netaddr.h +++ b/library/cpp/messagebus/config/netaddr.h @@ -36,14 +36,14 @@ namespace NBus { public: class TError: public yexception { }; - + TNetAddr(); TNetAddr(TAutoPtr<IRemoteAddr> addr); TNetAddr(const char* hostPort, EIpVersion requireVersion = EIP_VERSION_ANY, EIpVersion preferVersion = EIP_VERSION_ANY); TNetAddr(TStringBuf host, int port, EIpVersion requireVersion = EIP_VERSION_ANY, EIpVersion preferVersion = EIP_VERSION_ANY); TNetAddr(const TNetworkAddress& na, EIpVersion requireVersion = EIP_VERSION_ANY, EIpVersion preferVersion = EIP_VERSION_ANY); TNetAddr(const TNetworkAddress& na, const TAddrInfo& ai); - + bool operator==(const TNetAddr&) const; bool operator!=(const TNetAddr& other) const { return !(*this == other); diff --git a/library/cpp/messagebus/config/session_config.cpp b/library/cpp/messagebus/config/session_config.cpp index fbbbb106c9..17157b3dfa 100644 --- a/library/cpp/messagebus/config/session_config.cpp +++ b/library/cpp/messagebus/config/session_config.cpp @@ -120,7 +120,7 @@ void TBusSessionConfig::ConfigureLastGetopt(NLastGetopt::TOpts& opts, opts.AddLongOption(prefix + "max-message-size") .RequiredArgument("BYTES") .DefaultValue(ToString(MaxMessageSize)) - .StoreMappedResultT<const char*>(&MaxMessageSize, &ParseWithKmgSuffix); + .StoreMappedResultT<const char*>(&MaxMessageSize, &ParseWithKmgSuffix); opts.AddLongOption(prefix + "socket-recv-buffer-size") .RequiredArgument("BYTES") .DefaultValue(ToString(SocketRecvBufferSize)) diff --git a/library/cpp/messagebus/event_loop.cpp b/library/cpp/messagebus/event_loop.cpp index f685135bed..fd2e726d0b 100644 --- a/library/cpp/messagebus/event_loop.cpp +++ b/library/cpp/messagebus/event_loop.cpp @@ -78,7 +78,7 @@ public: const char* Name; - TAtomic RunningState; + TAtomic RunningState; TAtomic StopSignal; TSystemEvent StoppedEvent; TData Data; @@ -143,7 +143,7 @@ void TEventLoop::Stop() { } bool TEventLoop::IsRunning() { - return AtomicGet(Impl->RunningState) == EVENT_LOOP_RUNNING; + return AtomicGet(Impl->RunningState) == EVENT_LOOP_RUNNING; } TChannelPtr TEventLoop::Register(TSocket socket, TEventHandlerPtr eventHandler, void* cookie) { @@ -277,7 +277,7 @@ TEventLoop::TImpl::TImpl(const char* name) } void TEventLoop::TImpl::Run() { - bool res = AtomicCas(&RunningState, EVENT_LOOP_RUNNING, EVENT_LOOP_CREATED); + bool res = AtomicCas(&RunningState, EVENT_LOOP_RUNNING, EVENT_LOOP_CREATED); Y_VERIFY(res, "Invalid mbus event loop state"); if (!!Name) { @@ -320,21 +320,21 @@ void TEventLoop::TImpl::Run() { Data.clear(); } - res = AtomicCas(&RunningState, EVENT_LOOP_STOPPED, EVENT_LOOP_RUNNING); + res = AtomicCas(&RunningState, EVENT_LOOP_STOPPED, EVENT_LOOP_RUNNING); Y_VERIFY(res); - + StoppedEvent.Signal(); } void TEventLoop::TImpl::Stop() { AtomicSet(StopSignal, 1); - if (AtomicGet(RunningState) == EVENT_LOOP_RUNNING) { - Wakeup(); + if (AtomicGet(RunningState) == EVENT_LOOP_RUNNING) { + Wakeup(); - StoppedEvent.WaitI(); - } + StoppedEvent.WaitI(); + } } TChannelPtr TEventLoop::TImpl::Register(TSocket socket, TEventHandlerPtr eventHandler, void* cookie) { diff --git a/library/cpp/messagebus/misc/granup.h b/library/cpp/messagebus/misc/granup.h index 36ecfebc93..8b04aca597 100644 --- a/library/cpp/messagebus/misc/granup.h +++ b/library/cpp/messagebus/misc/granup.h @@ -1,50 +1,50 @@ -#pragma once - +#pragma once + #include <util/datetime/base.h> #include <util/system/guard.h> -#include <util/system/mutex.h> -#include <util/system/spinlock.h> - -namespace NBus { - template <typename TItem, typename TLocker = TSpinLock> - class TGranUp { - public: - TGranUp(TDuration gran) - : Gran(gran) +#include <util/system/mutex.h> +#include <util/system/spinlock.h> + +namespace NBus { + template <typename TItem, typename TLocker = TSpinLock> + class TGranUp { + public: + TGranUp(TDuration gran) + : Gran(gran) , Next(TInstant::MicroSeconds(0)) { } - + template <typename TFunctor> void Update(TFunctor functor, TInstant now, bool force = false) { if (force || now > Next) - Set(functor(), now); - } - + Set(functor(), now); + } + void Update(const TItem& item, TInstant now, bool force = false) { if (force || now > Next) - Set(item, now); - } - + Set(item, now); + } + TItem Get() const noexcept { TGuard<TLocker> guard(Lock); - - return Item; - } - - protected: + + return Item; + } + + protected: void Set(const TItem& item, TInstant now) { TGuard<TLocker> guard(Lock); - - Item = item; - - Next = now + Gran; - } - - private: - const TDuration Gran; + + Item = item; + + Next = now + Gran; + } + + private: + const TDuration Gran; TLocker Lock; TItem Item; TInstant Next; - }; -} + }; +} diff --git a/library/cpp/messagebus/misc/tokenquota.h b/library/cpp/messagebus/misc/tokenquota.h index 190547fa54..954cf0f0d7 100644 --- a/library/cpp/messagebus/misc/tokenquota.h +++ b/library/cpp/messagebus/misc/tokenquota.h @@ -1,83 +1,83 @@ -#pragma once - -#include <util/system/atomic.h> - -namespace NBus { - /* Consumer and feeder quota model impl. - - Consumer thread only calls: - Acquire(), fetches tokens for usage from bucket; - Consume(), eats given amount of tokens, must not - be greater than Value() items; - - Other threads (feeders) calls: - Return(), put used tokens back to bucket; - */ - - class TTokenQuota { - public: - TTokenQuota(bool enabled, size_t tokens, size_t wake) - : Enabled(tokens > 0 ? enabled : false) - , Acquired(0) - , WakeLev(wake < 1 ? Max<size_t>(1, tokens / 2) : 0) - , Tokens_(tokens) +#pragma once + +#include <util/system/atomic.h> + +namespace NBus { + /* Consumer and feeder quota model impl. + + Consumer thread only calls: + Acquire(), fetches tokens for usage from bucket; + Consume(), eats given amount of tokens, must not + be greater than Value() items; + + Other threads (feeders) calls: + Return(), put used tokens back to bucket; + */ + + class TTokenQuota { + public: + TTokenQuota(bool enabled, size_t tokens, size_t wake) + : Enabled(tokens > 0 ? enabled : false) + , Acquired(0) + , WakeLev(wake < 1 ? Max<size_t>(1, tokens / 2) : 0) + , Tokens_(tokens) { Y_UNUSED(padd_); } - + bool Acquire(TAtomic level = 1, bool force = false) { level = Max(TAtomicBase(level), TAtomicBase(1)); - + if (Enabled && (Acquired < level || force)) { Acquired += AtomicSwap(&Tokens_, 0); - } - - return !Enabled || Acquired >= level; - } - + } + + return !Enabled || Acquired >= level; + } + void Consume(size_t items) { if (Enabled) { Y_ASSERT(Acquired >= TAtomicBase(items)); - - Acquired -= items; - } - } - + + Acquired -= items; + } + } + bool Return(size_t items_) noexcept { if (!Enabled || items_ == 0) - return false; - - const TAtomic items = items_; - const TAtomic value = AtomicAdd(Tokens_, items); - - return (value - items < WakeLev && value >= WakeLev); - } - + return false; + + const TAtomic items = items_; + const TAtomic value = AtomicAdd(Tokens_, items); + + return (value - items < WakeLev && value >= WakeLev); + } + bool IsEnabled() const noexcept { - return Enabled; - } - + return Enabled; + } + bool IsAboveWake() const noexcept { - return !Enabled || (WakeLev <= AtomicGet(Tokens_)); - } - + return !Enabled || (WakeLev <= AtomicGet(Tokens_)); + } + size_t Tokens() const noexcept { - return Acquired + AtomicGet(Tokens_); - } - + return Acquired + AtomicGet(Tokens_); + } + size_t Check(const TAtomic level) const noexcept { - return !Enabled || level <= Acquired; - } - - private: + return !Enabled || level <= Acquired; + } + + private: bool Enabled; TAtomicBase Acquired; - const TAtomicBase WakeLev; + const TAtomicBase WakeLev; TAtomic Tokens_; - - /* This padd requires for align Tokens_ member on its own - CPU cacheline. */ - + + /* This padd requires for align Tokens_ member on its own + CPU cacheline. */ + ui64 padd_; - }; -} + }; +} diff --git a/library/cpp/messagebus/remote_connection.cpp b/library/cpp/messagebus/remote_connection.cpp index 22932569db..730fc0f554 100644 --- a/library/cpp/messagebus/remote_connection.cpp +++ b/library/cpp/messagebus/remote_connection.cpp @@ -48,11 +48,11 @@ namespace NBus { const TInstant now = TInstant::Now(); WriterFillStatus(); - + GranStatus.Writer.Update(WriterData.Status, now, true); GranStatus.Reader.Update(ReaderData.Status, now, true); } - + TRemoteConnection::~TRemoteConnection() { Y_VERIFY(ReplyQueue.IsEmpty()); } @@ -73,7 +73,7 @@ namespace NBus { bool TRemoteConnection::TReaderData::HasBytesInBuf(size_t bytes) noexcept { size_t left = Buffer.Size() - Offset; - + return (MoreBytes = left >= bytes ? 0 : bytes - left) == 0; } @@ -83,13 +83,13 @@ namespace NBus { Y_VERIFY(State == WRITER_FILLING, "state must be initial"); Channel = channel; } - + void TRemoteConnection::TReaderData::SetChannel(NEventLoop::TChannelPtr channel) { Y_VERIFY(!Channel, "must not have channel"); Y_VERIFY(Buffer.Empty(), "buffer must be empty"); Channel = channel; } - + void TRemoteConnection::TWriterData::DropChannel() { if (!!Channel) { Channel->Unregister(); @@ -184,7 +184,7 @@ namespace NBus { ReaderData.Status.Fd = INVALID_SOCKET; return; } - + ReaderData.DropChannel(); ReaderData.Status.Fd = readSocket.Socket; @@ -232,10 +232,10 @@ namespace NBus { ReaderData.Status.Acts += 1; ReaderGetSocketQueue()->DequeueAllLikelyEmpty(); - + if (AtomicGet(ReaderData.Down)) { ReaderData.DropChannel(); - + ReaderProcessStatusDown(); ReaderData.ShutdownComplete.Signal(); @@ -262,7 +262,7 @@ namespace NBus { } ReaderFlushMessages(); - } + } ReaderSendStatus(now); } @@ -275,109 +275,109 @@ namespace NBus { else if (!QuotaBytes.Acquire(bytes)) wakeFlags |= WAKE_QUOTA_BYTES; - + if (wakeFlags) { ReaderData.Status.QuotaExhausted++; - + WriterGetWakeQueue()->EnqueueAndSchedule(wakeFlags); } - + return wakeFlags == 0; } - + void TRemoteConnection::QuotaConsume(size_t msg, size_t bytes) { QuotaMsg.Consume(msg); QuotaBytes.Consume(bytes); } - + void TRemoteConnection::QuotaReturnSelf(size_t items, size_t bytes) { if (QuotaReturnValues(items, bytes)) ReadQuotaWakeup(); } - + void TRemoteConnection::QuotaReturnAside(size_t items, size_t bytes) { if (QuotaReturnValues(items, bytes) && !AtomicGet(WriterData.Down)) WriterGetWakeQueue()->EnqueueAndSchedule(0x0); } - + bool TRemoteConnection::QuotaReturnValues(size_t items, size_t bytes) { bool rMsg = QuotaMsg.Return(items); bool rBytes = QuotaBytes.Return(bytes); - + return rMsg || rBytes; } - + void TRemoteConnection::ReadQuotaWakeup() { const ui32 mask = WriterData.AwakeFlags & WriteWakeFlags(); - + if (mask && mask == WriterData.AwakeFlags) { WriterData.Status.ReaderWakeups++; WriterData.AwakeFlags = 0; - + ScheduleRead(); } } - + ui32 TRemoteConnection::WriteWakeFlags() const { ui32 awakeFlags = 0; - + if (QuotaMsg.IsAboveWake()) awakeFlags |= WAKE_QUOTA_MSG; - + if (QuotaBytes.IsAboveWake()) awakeFlags |= WAKE_QUOTA_BYTES; - + return awakeFlags; } - + bool TRemoteConnection::ReaderProcessBuffer() { TInstant now = TInstant::Now(); - + for (;;) { if (!ReaderData.HasBytesInBuf(sizeof(TBusHeader))) { break; } - + TBusHeader header(MakeArrayRef(ReaderData.Buffer.Data() + ReaderData.Offset, ReaderData.Buffer.Size() - ReaderData.Offset)); - + if (header.Size < sizeof(TBusHeader)) { LWPROBE(Error, ToString(MESSAGE_HEADER_CORRUPTED), ToString(PeerAddr), ToString(header.Size)); ReaderData.Status.Incremental.StatusCounter[MESSAGE_HEADER_CORRUPTED] += 1; ScheduleShutdownOnServerOrReconnectOnClient(MESSAGE_HEADER_CORRUPTED, false); return false; } - + if (!IsVersionNegotiation(header) && !IsBusKeyValid(header.Id)) { LWPROBE(Error, ToString(MESSAGE_HEADER_CORRUPTED), ToString(PeerAddr), ToString(header.Size)); ReaderData.Status.Incremental.StatusCounter[MESSAGE_HEADER_CORRUPTED] += 1; ScheduleShutdownOnServerOrReconnectOnClient(MESSAGE_HEADER_CORRUPTED, false); return false; } - + if (header.Size > Config.MaxMessageSize) { LWPROBE(Error, ToString(MESSAGE_MESSAGE_TOO_LARGE), ToString(PeerAddr), ToString(header.Size)); ReaderData.Status.Incremental.StatusCounter[MESSAGE_MESSAGE_TOO_LARGE] += 1; ScheduleShutdownOnServerOrReconnectOnClient(MESSAGE_MESSAGE_TOO_LARGE, false); return false; } - + if (!ReaderData.HasBytesInBuf(header.Size)) { if (ReaderData.Offset == 0) { ReaderData.Buffer.Reserve(header.Size); } break; } - + if (!QuotaAcquire(1, header.Size)) return false; - + if (!MessageRead(MakeArrayRef(ReaderData.Buffer.Data() + ReaderData.Offset, header.Size), now)) { return false; } - + ReaderData.Offset += header.Size; } - + ReaderData.Buffer.ChopHead(ReaderData.Offset); ReaderData.Offset = 0; @@ -408,7 +408,7 @@ namespace NBus { } Y_ASSERT(ReaderData.Buffer.Avail() > 0); - + ssize_t bytes; { TWhatThreadDoesPushPop pp("recv syscall"); @@ -454,7 +454,7 @@ namespace NBus { message != replyQueueTemp.rend(); ++message) { messages.push_back(message->MessagePtr.Release()); } - + WriterErrorMessages(messages, reason); replyQueueTemp.clear(); @@ -535,10 +535,10 @@ namespace NBus { ClearBeforeSendQueue(reasonForQueues); WriterGetReconnectQueue()->Clear(); WriterGetWakeQueue()->Clear(); - + TMessagesPtrs cleared; ClearOutgoingQueue(cleared, false); - + if (!Session->IsSource_) { for (auto& i : cleared) { TBusMessagePtrAndHeader h(i); @@ -548,10 +548,10 @@ namespace NBus { // and this part is not batch } } - + WriterErrorMessages(cleared, reason); } - + void TRemoteConnection::BeforeTryWrite() { } @@ -638,7 +638,7 @@ namespace NBus { WriterData.Status.Incremental.NetworkOps += 1; WriterData.Buffer.LeftProceed(bytes); - } + } WriterData.Buffer.Clear(); if (WriterData.Buffer.Capacity() > MaxBufferSize) { @@ -654,12 +654,12 @@ namespace NBus { WriterGetReconnectQueue()->EnqueueAndSchedule(writer ? WriterData.SocketVersion : ReaderData.SocketVersion); } else { ScheduleShutdown(status); - } + } } void TRemoteConnection::ScheduleShutdown(EMessageStatus status) { ShutdownReason = status; - + AtomicSet(ReaderData.Down, 1); ScheduleRead(); @@ -856,7 +856,7 @@ namespace NBus { } TTempTlsVector<TBusMessagePtrAndHeader, void, TVectorSwaps> writeMessages; - + for (;;) { THolder<TBusMessage> writeMessage(WriterData.SendQueue.PopFront()); if (!writeMessage) { @@ -944,12 +944,12 @@ namespace NBus { WriterErrorMessage(h.MessagePtr.Release(), status); } } - + void TRemoteConnection::WriterErrorMessage(TNonDestroyingAutoPtr<TBusMessage> m, EMessageStatus status) { TBusMessage* released = m.Release(); WriterErrorMessages(MakeArrayRef(&released, 1), status); } - + void TRemoteConnection::WriterErrorMessages(const TArrayRef<TBusMessage*> ms, EMessageStatus status) { ResetOneWayFlag(ms); @@ -958,17 +958,17 @@ namespace NBus { Session->InvokeOnError(m, status); } } - + void TRemoteConnection::FireClientConnectionEvent(TClientConnectionEvent::EType type) { Y_VERIFY(Session->IsSource_, "state check"); TClientConnectionEvent event(type, ConnectionId, PeerAddr); TRemoteClientSession* session = CheckedCast<TRemoteClientSession*>(Session.Get()); session->ClientHandler->OnClientConnectionEvent(event); } - + bool TRemoteConnection::IsAlive() const { return !AtomicGet(WriterData.Down); } - + } } diff --git a/library/cpp/messagebus/remote_connection.h b/library/cpp/messagebus/remote_connection.h index 4538947368..5141a8ea9f 100644 --- a/library/cpp/messagebus/remote_connection.h +++ b/library/cpp/messagebus/remote_connection.h @@ -13,8 +13,8 @@ #include "storage.h" #include "vector_swaps.h" #include "ybus.h" -#include "misc/granup.h" -#include "misc/tokenquota.h" +#include "misc/granup.h" +#include "misc/tokenquota.h" #include <library/cpp/messagebus/actor/actor.h> #include <library/cpp/messagebus/actor/executor.h> @@ -49,7 +49,7 @@ namespace NBus { struct TWriterToReaderSocketMessage { TSocket Socket; ui32 SocketVersion; - + TWriterToReaderSocketMessage(TSocket socket, ui32 socketVersion) : Socket(socket) , SocketVersion(socketVersion) @@ -154,13 +154,13 @@ namespace NBus { virtual void ReaderProcessMessageUnknownVersion(TArrayRef<const char> dataRef) = 0; bool MessageRead(TArrayRef<const char> dataRef, TInstant now); virtual void MessageSent(TArrayRef<TBusMessagePtrAndHeader> messages) = 0; - + void CallSerialize(TBusMessage* msg, TBuffer& buffer) const; void SerializeMessage(TBusMessage* msg, TBuffer* data, TMessageCounter* counter) const; TBusMessage* DeserializeMessage(TArrayRef<const char> dataRef, const TBusHeader* header, TMessageCounter* messageCounter, EMessageStatus* status) const; - + void ResetOneWayFlag(TArrayRef<TBusMessage*>); - + inline ::NActor::TActor<TRemoteConnection, TWriterTag>* GetWriterActor() { return this; } @@ -269,7 +269,7 @@ namespace NBus { TGranUp<TRemoteConnectionWriterStatus> Writer; TGranUp<TRemoteConnectionReaderStatus> Reader; }; - + TWriterData WriterData; TReaderData ReaderData; TGranStatus GranStatus; @@ -280,15 +280,15 @@ namespace NBus { // client connection only TLockFreeQueueBatch<TBusMessagePtrAndHeader, TVectorSwaps> ReplyQueue; - + EMessageStatus ShutdownReason; }; inline const TNetAddr& TRemoteConnection::GetAddr() const noexcept { return PeerAddr; } - + typedef TIntrusivePtr<TRemoteConnection> TRemoteConnectionPtr; - + } } diff --git a/library/cpp/messagebus/remote_connection_status.cpp b/library/cpp/messagebus/remote_connection_status.cpp index 2c48b2a287..05ae84791c 100644 --- a/library/cpp/messagebus/remote_connection_status.cpp +++ b/library/cpp/messagebus/remote_connection_status.cpp @@ -180,15 +180,15 @@ TString TRemoteConnectionStatus::PrintToString() const { p.AddRow("connect syscalls", WriterStatus.ConnectSyscalls); } - p.AddRow("send queue", LeftPad(WriterStatus.SendQueueSize, 6)); - + p.AddRow("send queue", LeftPad(WriterStatus.SendQueueSize, 6)); + if (Server) { - p.AddRow("quota msg", LeftPad(ReaderStatus.QuotaMsg, 6)); - p.AddRow("quota bytes", LeftPad(ReaderStatus.QuotaBytes, 6)); - p.AddRow("quota exhausted", LeftPad(ReaderStatus.QuotaExhausted, 6)); - p.AddRow("reader wakeups", LeftPad(WriterStatus.ReaderWakeups, 6)); - } else { - p.AddRow("ack messages", LeftPad(WriterStatus.AckMessagesSize, 6)); + p.AddRow("quota msg", LeftPad(ReaderStatus.QuotaMsg, 6)); + p.AddRow("quota bytes", LeftPad(ReaderStatus.QuotaBytes, 6)); + p.AddRow("quota exhausted", LeftPad(ReaderStatus.QuotaExhausted, 6)); + p.AddRow("reader wakeups", LeftPad(WriterStatus.ReaderWakeups, 6)); + } else { + p.AddRow("ack messages", LeftPad(WriterStatus.AckMessagesSize, 6)); } p.AddRow("written", WriterStatus.Incremental.MessageCounter.ToString(false)); diff --git a/library/cpp/messagebus/remote_server_session.cpp b/library/cpp/messagebus/remote_server_session.cpp index 6abbf88a60..34dd2153e2 100644 --- a/library/cpp/messagebus/remote_server_session.cpp +++ b/library/cpp/messagebus/remote_server_session.cpp @@ -24,9 +24,9 @@ TRemoteServerSession::TRemoteServerSession(TBusMessageQueue* queue, { if (config.PerConnectionMaxInFlightBySize > 0) { if (config.PerConnectionMaxInFlightBySize < config.MaxMessageSize) - ythrow yexception() - << "too low PerConnectionMaxInFlightBySize value"; - } + ythrow yexception() + << "too low PerConnectionMaxInFlightBySize value"; + } } namespace NBus { @@ -87,7 +87,7 @@ void TRemoteServerSession::OnMessageReceived(TRemoteConnection* c, TVectorSwaps< void TRemoteServerSession::InvokeOnMessage(TBusMessagePtrAndHeader& request, TIntrusivePtr<TRemoteServerConnection>& conn) { if (Y_UNLIKELY(AtomicGet(Down))) { - ReleaseInWorkRequests(*conn.Get(), request.MessagePtr.Get()); + ReleaseInWorkRequests(*conn.Get(), request.MessagePtr.Get()); InvokeOnError(request.MessagePtr.Release(), MESSAGE_SHUTDOWN); } else { TWhatThreadDoesPushPop pp("OnMessage"); @@ -167,19 +167,19 @@ void TRemoteServerSession::ReleaseInWorkResponses(TArrayRef<const TBusMessagePtr void TRemoteServerSession::ReleaseInWorkRequests(TRemoteConnection& con, TBusMessage* request) { Y_ASSERT((request->LocalFlags & MESSAGE_IN_WORK)); - request->LocalFlags &= ~MESSAGE_IN_WORK; - - const size_t size = request->GetHeader()->Size; + request->LocalFlags &= ~MESSAGE_IN_WORK; - con.QuotaReturnAside(1, size); - ServerOwnedMessages.ReleaseMultiple(1, size); + const size_t size = request->GetHeader()->Size; + + con.QuotaReturnAside(1, size); + ServerOwnedMessages.ReleaseMultiple(1, size); } void TRemoteServerSession::ReleaseInWork(TBusIdentity& ident) { - ident.SetInWork(false); - ident.Connection->QuotaReturnAside(1, ident.Size); + ident.SetInWork(false); + ident.Connection->QuotaReturnAside(1, ident.Size); - ServerOwnedMessages.ReleaseMultiple(1, ident.Size); + ServerOwnedMessages.ReleaseMultiple(1, ident.Size); } void TRemoteServerSession::ConvertInWork(TBusIdentity& req, TBusMessage* reply) { diff --git a/library/cpp/messagebus/session_impl.cpp b/library/cpp/messagebus/session_impl.cpp index ddf9f360c4..7adaa1ae6d 100644 --- a/library/cpp/messagebus/session_impl.cpp +++ b/library/cpp/messagebus/session_impl.cpp @@ -389,14 +389,14 @@ void TBusSessionImpl::StatusUpdateCachedDump() { for (TVector<TAcceptorPtr>::const_iterator acceptor = acceptors.begin(); acceptor != acceptors.end(); ++acceptor) { - const TAcceptorStatus status = (*acceptor)->GranStatus.Listen.Get(); - - acceptorStatusSummary += status; - + const TAcceptorStatus status = (*acceptor)->GranStatus.Listen.Get(); + + acceptorStatusSummary += status; + if (acceptor != acceptors.begin()) { ss << "\n"; } - ss << status.PrintToString(); + ss << status.PrintToString(); } r.Acceptors = ss.Str(); @@ -410,19 +410,19 @@ void TBusSessionImpl::StatusUpdateCachedDump() { if (connection != connections.begin()) { ss << "\n"; } - + TRemoteConnectionStatus status; status.Server = !IsSource_; - status.ReaderStatus = (*connection)->GranStatus.Reader.Get(); - status.WriterStatus = (*connection)->GranStatus.Writer.Get(); - + status.ReaderStatus = (*connection)->GranStatus.Reader.Get(); + status.WriterStatus = (*connection)->GranStatus.Writer.Get(); + ss << status.PrintToString(); - - r.ConnectionStatusSummary.ReaderStatus += status.ReaderStatus; - r.ConnectionStatusSummary.WriterStatus += status.WriterStatus; + + r.ConnectionStatusSummary.ReaderStatus += status.ReaderStatus; + r.ConnectionStatusSummary.WriterStatus += status.WriterStatus; } - r.ConnectionsSummary = r.ConnectionStatusSummary.PrintToString(); + r.ConnectionsSummary = r.ConnectionStatusSummary.PrintToString(); r.Connections = ss.Str(); } diff --git a/library/cpp/messagebus/test/ut/messagebus_ut.cpp b/library/cpp/messagebus/test/ut/messagebus_ut.cpp index 040f9b7702..c11d447224 100644 --- a/library/cpp/messagebus/test/ut/messagebus_ut.cpp +++ b/library/cpp/messagebus/test/ut/messagebus_ut.cpp @@ -962,103 +962,103 @@ Y_UNIT_TEST_SUITE(TMessageBusTests) { client.Sync.WaitForAndIncrement(3); } - + struct TServerForQuotaWake: public TExampleServer { TSystemEvent GoOn; TMutex OneLock; - - TOnMessageContext OneMessage; - - static TBusServerSessionConfig Config() { - TBusServerSessionConfig config; - - config.PerConnectionMaxInFlight = 1; - config.PerConnectionMaxInFlightBySize = 1500; - config.MaxMessageSize = 1024; - - return config; - } - - TServerForQuotaWake() - : TExampleServer("TServerForQuotaWake", Config()) + + TOnMessageContext OneMessage; + + static TBusServerSessionConfig Config() { + TBusServerSessionConfig config; + + config.PerConnectionMaxInFlight = 1; + config.PerConnectionMaxInFlightBySize = 1500; + config.MaxMessageSize = 1024; + + return config; + } + + TServerForQuotaWake() + : TExampleServer("TServerForQuotaWake", Config()) { } - + ~TServerForQuotaWake() override { - Session->Shutdown(); - } - + Session->Shutdown(); + } + void OnMessage(TOnMessageContext& req) override { - if (!GoOn.Wait(0)) { + if (!GoOn.Wait(0)) { TGuard<TMutex> guard(OneLock); - - UNIT_ASSERT(!OneMessage); - - OneMessage.Swap(req); - } else - TExampleServer::OnMessage(req); - } - - void WakeOne() { + + UNIT_ASSERT(!OneMessage); + + OneMessage.Swap(req); + } else + TExampleServer::OnMessage(req); + } + + void WakeOne() { TGuard<TMutex> guard(OneLock); - - UNIT_ASSERT(!!OneMessage); - - TExampleServer::OnMessage(OneMessage); - - TOnMessageContext().Swap(OneMessage); - } - }; - + + UNIT_ASSERT(!!OneMessage); + + TExampleServer::OnMessage(OneMessage); + + TOnMessageContext().Swap(OneMessage); + } + }; + Y_UNIT_TEST(WakeReaderOnQuota) { - const size_t test_msg_count = 64; - - TBusClientSessionConfig clientConfig; - - clientConfig.MaxInFlight = test_msg_count; - - TExampleClient client(clientConfig); - TServerForQuotaWake server; - TInstant start; - - client.MessageCount = test_msg_count; - - const NBus::TNetAddr addr = server.GetActualListenAddr(); - - for (unsigned count = 0;;) { - UNIT_ASSERT(count <= test_msg_count); - - TAutoPtr<TBusMessage> message(new TExampleRequest(&client.Proto.RequestCount)); - EMessageStatus status = client.Session->SendMessageAutoPtr(message, &addr); - - if (status == MESSAGE_OK) { - count++; - - } else if (status == MESSAGE_BUSY) { + const size_t test_msg_count = 64; + + TBusClientSessionConfig clientConfig; + + clientConfig.MaxInFlight = test_msg_count; + + TExampleClient client(clientConfig); + TServerForQuotaWake server; + TInstant start; + + client.MessageCount = test_msg_count; + + const NBus::TNetAddr addr = server.GetActualListenAddr(); + + for (unsigned count = 0;;) { + UNIT_ASSERT(count <= test_msg_count); + + TAutoPtr<TBusMessage> message(new TExampleRequest(&client.Proto.RequestCount)); + EMessageStatus status = client.Session->SendMessageAutoPtr(message, &addr); + + if (status == MESSAGE_OK) { + count++; + + } else if (status == MESSAGE_BUSY) { if (count == test_msg_count) { - TInstant now = TInstant::Now(); - + TInstant now = TInstant::Now(); + if (start.GetValue() == 0) { - start = now; - + start = now; + // TODO: properly check that server is blocked } else if (start + TDuration::MilliSeconds(100) < now) { - break; - } - } - - Sleep(TDuration::MilliSeconds(10)); - - } else - UNIT_ASSERT(false); - } - - server.GoOn.Signal(); - server.WakeOne(); - - client.WaitReplies(); - - server.WaitForOnMessageCount(test_msg_count); + break; + } + } + + Sleep(TDuration::MilliSeconds(10)); + + } else + UNIT_ASSERT(false); + } + + server.GoOn.Signal(); + server.WakeOne(); + + client.WaitReplies(); + + server.WaitForOnMessageCount(test_msg_count); }; Y_UNIT_TEST(TestConnectionAttempts) { diff --git a/library/cpp/messagebus/www/www.cpp b/library/cpp/messagebus/www/www.cpp index 62ec241d85..e501cbf4a9 100644 --- a/library/cpp/messagebus/www/www.cpp +++ b/library/cpp/messagebus/www/www.cpp @@ -200,12 +200,12 @@ struct TBusWww::TImpl { Queues.Add(s->GetQueue()); } - void RegisterQueue(TBusMessageQueuePtr q) { + void RegisterQueue(TBusMessageQueuePtr q) { Y_VERIFY(!!q); - TGuard<TMutex> g(Mutex); - Queues.Add(q); - } - + TGuard<TMutex> g(Mutex); + Queues.Add(q); + } + void RegisterModule(TBusModule* module) { Y_VERIFY(!!module); TGuard<TMutex> g(Mutex); @@ -824,10 +824,10 @@ void TBusWww::RegisterServerSession(TBusServerSessionPtr s) { Impl->RegisterServerSession(s); } -void TBusWww::RegisterQueue(TBusMessageQueuePtr q) { - Impl->RegisterQueue(q); -} - +void TBusWww::RegisterQueue(TBusMessageQueuePtr q) { + Impl->RegisterQueue(q); +} + void TBusWww::RegisterModule(TBusModule* module) { Impl->RegisterModule(module); } diff --git a/library/cpp/monlib/messagebus/mon_service_messagebus.h b/library/cpp/monlib/messagebus/mon_service_messagebus.h index fe791e8a9b..ec1890e915 100644 --- a/library/cpp/monlib/messagebus/mon_service_messagebus.h +++ b/library/cpp/monlib/messagebus/mon_service_messagebus.h @@ -42,5 +42,5 @@ namespace NMonitoring { RegisterBusNgMonPage()->RegisterModule(module); } }; - + } diff --git a/ydb/core/actorlib_impl/actor_bootstrapped_ut.cpp b/ydb/core/actorlib_impl/actor_bootstrapped_ut.cpp index 990330b321..5037300374 100644 --- a/ydb/core/actorlib_impl/actor_bootstrapped_ut.cpp +++ b/ydb/core/actorlib_impl/actor_bootstrapped_ut.cpp @@ -37,7 +37,7 @@ Y_UNIT_TEST_SUITE(ActorBootstrapped) { template <typename TDerivedActor> void TestBootrappedActor() { TTestActorRuntime runtime; - runtime.Initialize(NKikimr::TAppPrepare().Unwrap()); + runtime.Initialize(NKikimr::TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(0); auto actor = new TDerivedActor(edge); runtime.Register(actor); diff --git a/ydb/core/actorlib_impl/actor_tracker_ut.cpp b/ydb/core/actorlib_impl/actor_tracker_ut.cpp index d804e3b924..71c8cc6292 100644 --- a/ydb/core/actorlib_impl/actor_tracker_ut.cpp +++ b/ydb/core/actorlib_impl/actor_tracker_ut.cpp @@ -103,8 +103,8 @@ Y_UNIT_TEST_SUITE(TActorTracker) { Y_UNIT_TEST(Basic) { { - TTestBasicRuntime runtime; - runtime.Initialize(NKikimr::TAppPrepare().Unwrap()); + TTestBasicRuntime runtime; + runtime.Initialize(NKikimr::TAppPrepare().Unwrap()); TActorId managerId = runtime.Register(new TManagerActor); TActorId edge = runtime.AllocateEdgeActor(); runtime.Schedule(new IEventHandle(managerId, edge, new TEvents::TEvPoisonPill), TDuration::Seconds(1)); diff --git a/ydb/core/actorlib_impl/http_request_protocol.h b/ydb/core/actorlib_impl/http_request_protocol.h index d5a5b4a0bc..ae22dfb3bb 100644 --- a/ydb/core/actorlib_impl/http_request_protocol.h +++ b/ydb/core/actorlib_impl/http_request_protocol.h @@ -93,14 +93,14 @@ public: ReadHTTPReply<TOrigActor>(orig, ctx, Socket, buf); } - virtual void CatchHTTPRequestError(TString error) noexcept = 0; + virtual void CatchHTTPRequestError(TString error) noexcept = 0; virtual void CatchHTTPContent( const TActorContext& ctx, TVector<char> buf) noexcept = 0; virtual void CatchHTTPWriteComplete(const TActorContext&) noexcept {} - virtual void CatchHTTPConnectionClosed() noexcept = 0; + virtual void CatchHTTPConnectionClosed() noexcept = 0; public: void CatchHostAddress( @@ -156,7 +156,7 @@ public: ctx.SelfID.ToString().data(), error.data()); - CatchHTTPRequestError(std::move(error)); + CatchHTTPRequestError(std::move(error)); } @@ -170,7 +170,7 @@ public: RetryCall = std::function<void(const TActorContext& ctx)>(); } - CatchHTTPRequestError(std::move(error)); + CatchHTTPRequestError(std::move(error)); } @@ -185,14 +185,14 @@ public: ReadHTTPReply<TOrigActor>(OriginalActor, ctx, Socket); } - void CatchSendDataError(TString error) noexcept override + void CatchSendDataError(TString error) noexcept override { - CatchHTTPRequestError(std::move(error)); + CatchHTTPRequestError(std::move(error)); } void CatchReadDataError(TString error) noexcept override { - CatchHTTPRequestError(std::move(error)); + CatchHTTPRequestError(std::move(error)); } void CatchSendDataComplete(const TActorContext& ctx) noexcept override { @@ -224,8 +224,8 @@ public: return true; } - void CatchReadDataClosed() noexcept { - CatchHTTPConnectionClosed(); + void CatchReadDataClosed() noexcept { + CatchHTTPConnectionClosed(); } private: diff --git a/ydb/core/actorlib_impl/read_data_protocol.cpp b/ydb/core/actorlib_impl/read_data_protocol.cpp index 62045309f8..2f225483a7 100644 --- a/ydb/core/actorlib_impl/read_data_protocol.cpp +++ b/ydb/core/actorlib_impl/read_data_protocol.cpp @@ -91,18 +91,18 @@ void TReadDataProtocolImpl::TryAgain(const TActorContext& ctx) noexcept { switch (-recvResult) { case ECONNRESET: - Catcher->CatchReadDataError("Connection reset by peer"); + Catcher->CatchReadDataError("Connection reset by peer"); return; case EPIPE: - Catcher->CatchReadDataError("Connection is closed"); + Catcher->CatchReadDataError("Connection is closed"); return; default: { char buf[1024]; LastSystemErrorText(buf, 1024, -recvResult); - Catcher->CatchReadDataError(TString("Socker error: ") + buf); + Catcher->CatchReadDataError(TString("Socker error: ") + buf); return; } diff --git a/ydb/core/actorlib_impl/read_data_protocol.h b/ydb/core/actorlib_impl/read_data_protocol.h index 7edefab299..391176cc54 100644 --- a/ydb/core/actorlib_impl/read_data_protocol.h +++ b/ydb/core/actorlib_impl/read_data_protocol.h @@ -7,12 +7,12 @@ namespace NActors { struct IReadDataCatch { - virtual void CatchReadDataError(TString error) noexcept = 0; + virtual void CatchReadDataError(TString error) noexcept = 0; /* returns false if the protocol should continue to read data */ virtual bool CatchReadDataComplete( const TActorContext& ctx, size_t amount) noexcept = 0; - virtual void CatchReadDataClosed() noexcept = 0; + virtual void CatchReadDataClosed() noexcept = 0; }; class TReadDataProtocolImpl { @@ -101,9 +101,9 @@ private: struct TCatch: public IReadDataCatch { TDerived* Catcher; - virtual void CatchReadDataError(TString error) noexcept override + virtual void CatchReadDataError(TString error) noexcept override { - Catcher->CatchReadDataError(error); + Catcher->CatchReadDataError(error); } /* returns false if the protocol should continue to read data */ @@ -113,9 +113,9 @@ private: return Catcher->CatchReadDataComplete(ctx, amount); } - virtual void CatchReadDataClosed() noexcept override + virtual void CatchReadDataClosed() noexcept override { - Catcher->CatchReadDataClosed(); + Catcher->CatchReadDataClosed(); } }; diff --git a/ydb/core/actorlib_impl/read_http_reply_protocol.cpp b/ydb/core/actorlib_impl/read_http_reply_protocol.cpp index 63ad2050c1..f3c65ac10e 100644 --- a/ydb/core/actorlib_impl/read_http_reply_protocol.cpp +++ b/ydb/core/actorlib_impl/read_http_reply_protocol.cpp @@ -33,13 +33,13 @@ bool TReadHTTPReplyProtocol::CatchReadDataComplete( /* Check if there no null char in data read from a socket */ if (strlen(Buf.data()) != Filled) { /* got garbage from the socket */ - CatchReadDataError("null char in HTTP reply"); + CatchReadDataError("null char in HTTP reply"); return true; } /* Check maximum size limit */ if (Filled >= HTTPReplySizeLimit) { - CatchReadDataError("HTTP reply is too large"); + CatchReadDataError("HTTP reply is too large"); return true; } @@ -59,9 +59,9 @@ bool TReadHTTPReplyProtocol::CatchReadDataComplete( } -void TReadHTTPReplyProtocol::CatchReadDataClosed() noexcept +void TReadHTTPReplyProtocol::CatchReadDataClosed() noexcept { - CatchReadDataError("Socket closed prematurely"); + CatchReadDataError("Socket closed prematurely"); } } diff --git a/ydb/core/actorlib_impl/read_http_reply_protocol.h b/ydb/core/actorlib_impl/read_http_reply_protocol.h index 6050a3edfe..45760e567d 100644 --- a/ydb/core/actorlib_impl/read_http_reply_protocol.h +++ b/ydb/core/actorlib_impl/read_http_reply_protocol.h @@ -32,7 +32,7 @@ public: Buf.data(), Buf.size() - Filled); } - virtual void CatchReadDataError(TString error) noexcept = 0; + virtual void CatchReadDataError(TString error) noexcept = 0; virtual void CatchHTTPReply( const TActorContext& ctx, @@ -49,7 +49,7 @@ private: bool CatchReadDataComplete( const TActorContext& ctx, size_t amount) noexcept; - void CatchReadDataClosed() noexcept; + void CatchReadDataClosed() noexcept; TIntrusivePtr<NInterconnect::TStreamSocket> Socket; diff --git a/ydb/core/actorlib_impl/send_data_protocol.cpp b/ydb/core/actorlib_impl/send_data_protocol.cpp index 7d79c00039..2c090b2976 100644 --- a/ydb/core/actorlib_impl/send_data_protocol.cpp +++ b/ydb/core/actorlib_impl/send_data_protocol.cpp @@ -67,23 +67,23 @@ void TSendDataProtocol::TryAgain(const TActorContext& ctx) noexcept { switch (-sendResult) { case ECONNRESET: - CatchSendDataError("Connection reset by peer"); + CatchSendDataError("Connection reset by peer"); return; case EPIPE: - CatchSendDataError("Connection is closed"); + CatchSendDataError("Connection is closed"); return; case 0: /* Not realy sure what to do with 0 result, assume socket is closed */ - CatchSendDataError("Connection is closed"); + CatchSendDataError("Connection is closed"); return; default: { char buf[1024]; LastSystemErrorText(buf, 1024, -sendResult); - CatchSendDataError(TString("Socker error: ") + buf); + CatchSendDataError(TString("Socker error: ") + buf); return; } diff --git a/ydb/core/actorlib_impl/send_data_protocol.h b/ydb/core/actorlib_impl/send_data_protocol.h index 2c22936034..7507d27762 100644 --- a/ydb/core/actorlib_impl/send_data_protocol.h +++ b/ydb/core/actorlib_impl/send_data_protocol.h @@ -30,7 +30,7 @@ public: TryAgain(ctx); } - virtual void CatchSendDataError(TString error) noexcept = 0; + virtual void CatchSendDataError(TString error) noexcept = 0; virtual void CatchSendDataComplete( const TActorContext& ctx) noexcept = 0; diff --git a/ydb/core/actorlib_impl/test_interconnect_ut.cpp b/ydb/core/actorlib_impl/test_interconnect_ut.cpp index 0d9d3535ef..601d357129 100644 --- a/ydb/core/actorlib_impl/test_interconnect_ut.cpp +++ b/ydb/core/actorlib_impl/test_interconnect_ut.cpp @@ -118,10 +118,10 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestSimplePingPong) { - TTestBasicRuntime runtime(2); + TTestBasicRuntime runtime(2); runtime.SetLogPriority(NActorsServices::INTERCONNECT, NActors::NLog::PRI_DEBUG); - runtime.Initialize(TAppPrepare().Unwrap()); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(0); const auto wall = runtime.Register(new TWall, 1); @@ -133,8 +133,8 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestManyEvents) { - TTestBasicRuntime runtime(2); - runtime.Initialize(TAppPrepare().Unwrap()); + TTestBasicRuntime runtime(2); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(0); const auto wall = runtime.Register(new TWall, 1); runtime.Register(new TFlooder(wall, edge, 100000), 0); @@ -147,10 +147,10 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { constexpr ui64 iterations = NSan::PlainOrUnderSanitizer(200, 50); for (ui64 i = 0; i < iterations; ++i) { Cerr << "Starting iteration " << i << Endl; - TTestBasicRuntime runtime(2); + TTestBasicRuntime runtime(2); runtime.SetLogPriority(NActorsServices::INTERCONNECT, NActors::NLog::PRI_DEBUG); runtime.SetDispatcherRandomSeed(time, i); - runtime.Initialize(TAppPrepare().Unwrap()); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge0 = runtime.AllocateEdgeActor(0); const auto edge1 = runtime.AllocateEdgeActor(1); const auto wall0 = runtime.Register(new TWall, 0); @@ -166,8 +166,8 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestConnectAndDisconnect) { - TTestBasicRuntime runtime(2); - runtime.Initialize(TAppPrepare().Unwrap()); + TTestBasicRuntime runtime(2); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(0); runtime.Send(new IEventHandle(runtime.GetInterconnectProxy(0, 1), edge, new TEvInterconnect::TEvConnectNode), 0, true); @@ -187,8 +187,8 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestBlobEvent) { - TTestBasicRuntime runtime(2); - runtime.Initialize(TAppPrepare().Unwrap()); + TTestBasicRuntime runtime(2); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(1); TString blob(100000, '@'); @@ -204,9 +204,9 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestBlobEventPreSerialized) { - TTestBasicRuntime runtime(2); + TTestBasicRuntime runtime(2); runtime.SetDispatchTimeout(TDuration::Seconds(1)); - runtime.Initialize(TAppPrepare().Unwrap()); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(1); TString blob(100000, '@'); @@ -230,8 +230,8 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestNotifyUndelivered) { - TTestBasicRuntime runtime(2); - runtime.Initialize(TAppPrepare().Unwrap()); + TTestBasicRuntime runtime(2); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge0 = runtime.AllocateEdgeActor(0); const auto edge1 = runtime.AllocateEdgeActor(1); @@ -251,8 +251,8 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestSubscribeByFlag) { - TTestBasicRuntime runtime(2); - runtime.Initialize(TAppPrepare().Unwrap()); + TTestBasicRuntime runtime(2); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(0); const auto wall = runtime.Register(new TKiller, 1); @@ -270,7 +270,7 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestReconnect) { - TTestBasicRuntime runtime(2); + TTestBasicRuntime runtime(2); runtime.SetUseRealInterconnect(); runtime.SetLogPriority(NActorsServices::INTERCONNECT, NActors::NLog::PRI_DEBUG); runtime.SetLogPriority(NActorsServices::INTERCONNECT_SESSION, NActors::NLog::PRI_DEBUG); @@ -281,7 +281,7 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } return TTestActorRuntime::EEventAction::PROCESS; }); - runtime.Initialize(TAppPrepare().Unwrap()); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(0); const auto wall = runtime.Register(new TWall, 1); @@ -306,8 +306,8 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestSubscribeAndUnsubsribeByEvent) { - TTestBasicRuntime runtime(3); - runtime.Initialize(TAppPrepare().Unwrap()); + TTestBasicRuntime runtime(3); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge0 = runtime.AllocateEdgeActor(0); const auto edge1 = runtime.AllocateEdgeActor(1); @@ -354,7 +354,7 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestManyEventsWithReconnect) { - TTestBasicRuntime runtime(2); + TTestBasicRuntime runtime(2); runtime.SetLogPriority(NActorsServices::INTERCONNECT, NActors::NLog::PRI_DEBUG); SOCKET s = INVALID_SOCKET; runtime.SetObserverFunc([&](TTestActorRuntimeBase&, TAutoPtr<IEventHandle>& ev) { @@ -363,7 +363,7 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } return TTestActorRuntime::EEventAction::PROCESS; }); - runtime.Initialize(TAppPrepare().Unwrap()); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(0); const auto wall = runtime.Register(new TWall, 1); @@ -390,8 +390,8 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestBlobEvent220Bytes) { - TTestBasicRuntime runtime(2); - runtime.Initialize(TAppPrepare().Unwrap()); + TTestBasicRuntime runtime(2); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(1); TString blob(220, '!'); @@ -410,9 +410,9 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestBlobEvent220BytesPreSerialized) { - TTestBasicRuntime runtime(2); + TTestBasicRuntime runtime(2); runtime.SetDispatchTimeout(TDuration::Seconds(1)); - runtime.Initialize(TAppPrepare().Unwrap()); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(1); TString blob(220, '!'); @@ -432,9 +432,9 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestBlobEventDifferentSizes) { - TTestBasicRuntime runtime(2); + TTestBasicRuntime runtime(2); runtime.SetLogPriority(NActorsServices::INTERCONNECT, NActors::NLog::PRI_DEBUG); - runtime.Initialize(TAppPrepare().Unwrap()); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(1); for (size_t s = 1; s <= 1024; ++s) { @@ -453,9 +453,9 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestBlobEventDifferentSizesPreSerialized) { - TTestBasicRuntime runtime(2); + TTestBasicRuntime runtime(2); runtime.SetDispatchTimeout(TDuration::Seconds(1)); - runtime.Initialize(TAppPrepare().Unwrap()); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(1); for (size_t s = 1; s <= 1024; ++s) { @@ -475,9 +475,9 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestBlobEventDifferentSizesPreSerializedAndRaw) { - TTestBasicRuntime runtime(2); + TTestBasicRuntime runtime(2); runtime.SetDispatchTimeout(TDuration::Seconds(1)); - runtime.Initialize(TAppPrepare().Unwrap()); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(1); for (size_t s = 1; s <= 1024; ++s) { @@ -503,8 +503,8 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestNotifyUndeliveredOnMissedActor) { - TTestBasicRuntime runtime(2); - runtime.Initialize(TAppPrepare().Unwrap()); + TTestBasicRuntime runtime(2); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(0); runtime.Send(new IEventHandle(runtime.GetInterconnectProxy(0, 1), @@ -528,8 +528,8 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestBlobEventUpToMebibytes) { - TTestBasicRuntime runtime(2); - runtime.Initialize(TAppPrepare().Unwrap()); + TTestBasicRuntime runtime(2); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(1); for (size_t s = 3; s <= 23; ++s) { @@ -546,9 +546,9 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestPreSerializedBlobEventUpToMebibytes) { - TTestBasicRuntime runtime(2); + TTestBasicRuntime runtime(2); runtime.SetDispatchTimeout(TDuration::Seconds(1)); - runtime.Initialize(TAppPrepare().Unwrap()); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(1); for (size_t s = 3; s <= 23; ++s) { @@ -569,8 +569,8 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestPingPongThroughSubChannel) { - TTestBasicRuntime runtime(2); - runtime.Initialize(TAppPrepare().Unwrap()); + TTestBasicRuntime runtime(2); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(0); const auto wall = runtime.Register(new TWall, 1); @@ -583,8 +583,8 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestBlobEventsThroughSubChannels) { - TTestBasicRuntime runtime(2); - runtime.Initialize(TAppPrepare().Unwrap()); + TTestBasicRuntime runtime(2); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(1); @@ -607,10 +607,10 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestTraceIdPassThrough) { - TTestBasicRuntime runtime(2); + TTestBasicRuntime runtime(2); runtime.SetLogPriority(NActorsServices::INTERCONNECT, NActors::NLog::PRI_DEBUG); - runtime.Initialize(TAppPrepare().Unwrap()); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(1); TString blob(100000, '@'); @@ -634,8 +634,8 @@ Y_UNIT_TEST_SUITE(TInterconnectTest) { } Y_UNIT_TEST(TestAddressResolve) { - TTestBasicRuntime runtime(2); - runtime.Initialize(TAppPrepare().Unwrap()); + TTestBasicRuntime runtime(2); + runtime.Initialize(TAppPrepare().Unwrap()); const auto edge = runtime.AllocateEdgeActor(0); auto event = new TEvResolveAddress; event->Address = "localhost"; diff --git a/ydb/core/actorlib_impl/test_protocols_ut.cpp b/ydb/core/actorlib_impl/test_protocols_ut.cpp index 2e622406a0..d3981fb8c4 100644 --- a/ydb/core/actorlib_impl/test_protocols_ut.cpp +++ b/ydb/core/actorlib_impl/test_protocols_ut.cpp @@ -142,8 +142,8 @@ Y_UNIT_TEST_SUITE(TestProtocols) { Y_UNIT_TEST(TestResolveProtocol) { for (size_t i = 0; i < 10; ++i) { - TTestBasicRuntime runtime(2); - runtime.Initialize(NKikimr::TAppPrepare().Unwrap()); + TTestBasicRuntime runtime(2); + runtime.Initialize(NKikimr::TAppPrepare().Unwrap()); auto tester = new TResolveTester; tester->Edge = runtime.AllocateEdgeActor(0); @@ -231,8 +231,8 @@ Y_UNIT_TEST_SUITE(TestProtocols) { THttpServer server(&serverImpl, mainWorkers, failWorkers, options); UNIT_ASSERT(server.Start()); - TTestBasicRuntime runtime(2); - runtime.Initialize(NKikimr::TAppPrepare().Unwrap()); + TTestBasicRuntime runtime(2); + runtime.Initialize(NKikimr::TAppPrepare().Unwrap()); auto tester = new TConnectTester; tester->Port = port; @@ -309,16 +309,16 @@ Y_UNIT_TEST_SUITE(TestProtocols) { SendData(this, ctx, Socket.Get(), request, strlen(request)); } - void CatchSendDataError(TString error) noexcept override + void CatchSendDataError(TString error) noexcept override { Error = std::move(error); - Send(Edge, new TEvents::TEvWakeup); + Send(Edge, new TEvents::TEvWakeup); } void CatchReadDataError(TString error) noexcept override { Error = std::move(error); - Send(Edge, new TEvents::TEvWakeup); + Send(Edge, new TEvents::TEvWakeup); } void CatchSendDataComplete(const TActorContext& ctx) noexcept override { @@ -360,8 +360,8 @@ Y_UNIT_TEST_SUITE(TestProtocols) { THttpServer server(&serverImpl, mainWorkers, failWorkers, options); UNIT_ASSERT(server.Start()); - TTestBasicRuntime runtime(2); - runtime.Initialize(NKikimr::TAppPrepare().Unwrap()); + TTestBasicRuntime runtime(2); + runtime.Initialize(NKikimr::TAppPrepare().Unwrap()); auto tester = new THTTPTester; tester->Edge = runtime.AllocateEdgeActor(0); @@ -490,7 +490,7 @@ Y_UNIT_TEST_SUITE(TestProtocols) { HTTPWriteContent(this, ctx, msg->Data, msg->Len,msg->Last); } - void CatchHTTPRequestError(TString error) noexcept override + void CatchHTTPRequestError(TString error) noexcept override { Error = std::move(error); exit(1); @@ -666,7 +666,7 @@ Y_UNIT_TEST_SUITE(TestProtocols) { Send(Edge, msg); } - void CatchHTTPConnectionClosed() noexcept override { + void CatchHTTPConnectionClosed() noexcept override { Ctest << "Connection closed prematurely" << Endl; exit(1); } @@ -695,8 +695,8 @@ Y_UNIT_TEST_SUITE(TestProtocols) { THttpServer server(&serverImpl, mainWorkers, failWorkers, options); UNIT_ASSERT(server.Start()); - TTestBasicRuntime runtime(2); - runtime.Initialize(NKikimr::TAppPrepare().Unwrap()); + TTestBasicRuntime runtime(2); + runtime.Initialize(NKikimr::TAppPrepare().Unwrap()); auto tester = new THTTPRequestTester; tester->Edge = runtime.AllocateEdgeActor(0); diff --git a/ydb/core/base/blobstorage.h b/ydb/core/base/blobstorage.h index a2faee326e..80820de5f9 100644 --- a/ydb/core/base/blobstorage.h +++ b/ydb/core/base/blobstorage.h @@ -431,7 +431,7 @@ inline bool SendToBSProxy(const TActorContext &ctx, TActorId recipient, IEventBa NWilson::TTraceId traceId = {}) { return ctx.Send(CreateEventForBSProxy(ctx.SelfID, recipient, ev, cookie, std::move(traceId))); } - + inline bool SendToBSProxy(TActorId sender, ui32 groupId, IEventBase *ev, ui64 cookie = 0, NWilson::TTraceId traceId = {}) { return TActivationContext::Send(CreateEventForBSProxy(sender, groupId, ev, cookie, std::move(traceId))); } @@ -983,7 +983,7 @@ struct TEvBlobStorage { , Size(0) {} - void Set(const TLogoBlobID &id, ui32 sh = 0, ui32 sz = 0) { + void Set(const TLogoBlobID &id, ui32 sh = 0, ui32 sz = 0) { Id = id; Shift = sh; Size = sz; diff --git a/ydb/core/base/resource_profile.h b/ydb/core/base/resource_profile.h index 113b1dd65e..a0b1b65c1f 100644 --- a/ydb/core/base/resource_profile.h +++ b/ydb/core/base/resource_profile.h @@ -15,16 +15,16 @@ namespace NKikimr { class TResourceProfiles : public TThrRefBase { public: using TResourceProfile = NKikimrSchemeOp::TResourceProfile; - using TPtr = std::shared_ptr<TResourceProfile>; + using TPtr = std::shared_ptr<TResourceProfile>; private: using TTabletType = NKikimrTabletBase::TTabletTypes::EType; using TKey = std::pair<TTabletType, TString>; - using TProfiles = THashMap<TKey, TPtr>; + using TProfiles = THashMap<TKey, TPtr>; TProfiles Profiles; - const TPtr DefaultProfile = std::make_shared<TResourceProfile>(); + const TPtr DefaultProfile = std::make_shared<TResourceProfile>(); const TString DefaultProfileName = "default"; const TTabletType DefaultTabletType = NKikimrTabletBase::TTabletTypes::Unknown; @@ -38,7 +38,7 @@ public: Profiles[key] = std::make_shared<TResourceProfile>(profile); } - const TPtr GetProfile(TTabletType type, const TString &name) const + const TPtr GetProfile(TTabletType type, const TString &name) const { auto it = Profiles.find(std::make_pair(type, name)); if (it != Profiles.end()) diff --git a/ydb/core/base/tablet.h b/ydb/core/base/tablet.h index 602e39c600..aaf5d073ee 100644 --- a/ydb/core/base/tablet.h +++ b/ydb/core/base/tablet.h @@ -142,12 +142,12 @@ struct TEvTablet { : Snapshot(snap) {} - void Describe(IOutputStream &out) const noexcept { - out - << "Deps{" << Snapshot.first << ":" << Snapshot.second - << " entries " << Entries.size() << "}"; - } - + void Describe(IOutputStream &out) const noexcept { + out + << "Deps{" << Snapshot.first << ":" << Snapshot.second + << " entries " << Entries.size() << "}"; + } + void AddEntry(const std::pair<ui32, ui32> &id, TVector<TLogoBlobID> &references, bool isSnapshot, TVector<TLogoBlobID> &gcDiscovered, TVector<TLogoBlobID> &gcLeft) { if (isSnapshot) { Snapshot = id; diff --git a/ydb/core/blobstorage/base/blobstorage_vdiskid.h b/ydb/core/blobstorage/base/blobstorage_vdiskid.h index c8d5a818b1..59d8749430 100644 --- a/ydb/core/blobstorage/base/blobstorage_vdiskid.h +++ b/ydb/core/blobstorage/base/blobstorage_vdiskid.h @@ -166,10 +166,10 @@ struct THash<NKikimr::TVDiskIdShort> { } }; -template<> +template<> inline void Out<NKikimr::TVDiskID>(IOutputStream& os, const NKikimr::TVDiskID& vdiskId) { - os << vdiskId.ToString(); -} + os << vdiskId.ToString(); +} template<> inline void Out<NKikimr::TVDiskIdShort>(IOutputStream& os, const NKikimr::TVDiskIdShort& vdiskId) { diff --git a/ydb/core/blobstorage/dsproxy/dsproxy_range.cpp b/ydb/core/blobstorage/dsproxy/dsproxy_range.cpp index e234f8c18e..8b5bc734e8 100644 --- a/ydb/core/blobstorage/dsproxy/dsproxy_range.cpp +++ b/ydb/core/blobstorage/dsproxy/dsproxy_range.cpp @@ -240,7 +240,7 @@ class TBlobStorageGroupRangeRequest : public TBlobStorageGroupRequestActor<TBlob TArrayHolder<TEvBlobStorage::TEvGet::TQuery> queries(new TEvBlobStorage::TEvGet::TQuery[queryCount]); TEvBlobStorage::TEvGet::TQuery *query = queries.Get(); for (const TBlobQueryItem& item : BlobsToGet) { - query->Set(item.BlobId, 0, 0); + query->Set(item.BlobId, 0, 0); ++query; } Y_VERIFY(query == queries.Get() + queryCount); diff --git a/ydb/core/blobstorage/dsproxy/mock/dsproxy_mock.cpp b/ydb/core/blobstorage/dsproxy/mock/dsproxy_mock.cpp index c0e6d8f15c..dcc047aafb 100644 --- a/ydb/core/blobstorage/dsproxy/mock/dsproxy_mock.cpp +++ b/ydb/core/blobstorage/dsproxy/mock/dsproxy_mock.cpp @@ -1,5 +1,5 @@ #include "dsproxy_mock.h" -#include "model.h" +#include "model.h" #include <ydb/core/base/blobstorage.h> #include <ydb/core/blobstorage/vdisk/common/vdisk_events.h> #include <ydb/core/util/stlog.h> @@ -15,43 +15,43 @@ namespace NKikimr { void Handle(TEvBlobStorage::TEvPut::TPtr& ev) { STLOG(PRI_DEBUG, BS_PROXY, BSPM01, "TEvPut", (Msg, ev->Get()->ToString())); - Send(ev->Sender, Model->Handle(ev->Get()),0, ev->Cookie); + Send(ev->Sender, Model->Handle(ev->Get()),0, ev->Cookie); } void Handle(TEvBlobStorage::TEvGet::TPtr& ev) { STLOG(PRI_DEBUG, BS_PROXY, BSPM02, "TEvGet", (Msg, ev->Get()->ToString())); - Send(ev->Sender, Model->Handle(ev->Get()), 0, ev->Cookie); + Send(ev->Sender, Model->Handle(ev->Get()), 0, ev->Cookie); } void Handle(TEvBlobStorage::TEvBlock::TPtr& ev) { STLOG(PRI_DEBUG, BS_PROXY, BSPM03, "TEvBlock", (Msg, ev->Get()->ToString())); - Send(ev->Sender, Model->Handle(ev->Get()), 0, ev->Cookie); + Send(ev->Sender, Model->Handle(ev->Get()), 0, ev->Cookie); } void Handle(TEvBlobStorage::TEvDiscover::TPtr& ev) { STLOG(PRI_DEBUG, BS_PROXY, BSPM04, "TEvDiscover", (Msg, ev->Get()->ToString())); - Send(ev->Sender, Model->Handle(ev->Get()), 0, ev->Cookie); + Send(ev->Sender, Model->Handle(ev->Get()), 0, ev->Cookie); } void Handle(TEvBlobStorage::TEvRange::TPtr& ev) { STLOG(PRI_DEBUG, BS_PROXY, BSPM05, "TEvRange", (Msg, ev->Get()->ToString())); - Send(ev->Sender, Model->Handle(ev->Get()), 0, ev->Cookie); + Send(ev->Sender, Model->Handle(ev->Get()), 0, ev->Cookie); } void Handle(TEvBlobStorage::TEvCollectGarbage::TPtr& ev) { STLOG(PRI_DEBUG, BS_PROXY, BSPM06, "TEvCollectGarbage", (Msg, ev->Get()->ToString())); - Send(ev->Sender, Model->Handle(ev->Get()), 0, ev->Cookie); + Send(ev->Sender, Model->Handle(ev->Get()), 0, ev->Cookie); } void Handle(TEvBlobStorage::TEvStatus::TPtr& ev) { STLOG(PRI_DEBUG, BS_PROXY, BSPM07, "TEvStatus", (Msg, ev->Get()->ToString())); - Send(ev->Sender, new TEvBlobStorage::TEvStatusResult(NKikimrProto::OK, Model->GetStorageStatusFlags()), 0, + Send(ev->Sender, new TEvBlobStorage::TEvStatusResult(NKikimrProto::OK, Model->GetStorageStatusFlags()), 0, ev->Cookie); } void HandlePoison(TEvents::TEvPoisonPill::TPtr& ev) { STLOG(PRI_DEBUG, BS_PROXY, BSPM08, "TEvPoisonPill"); - Send(ev->Sender, new TEvents::TEvPoisonTaken); + Send(ev->Sender, new TEvents::TEvPoisonTaken); PassAway(); } diff --git a/ydb/core/blobstorage/dsproxy/mock/model.h b/ydb/core/blobstorage/dsproxy/mock/model.h index 6161a6b857..c376e06842 100644 --- a/ydb/core/blobstorage/dsproxy/mock/model.h +++ b/ydb/core/blobstorage/dsproxy/mock/model.h @@ -1,361 +1,361 @@ -#pragma once - +#pragma once + #include <ydb/core/base/blobstorage.h> - -namespace NKikimr { -namespace NFake { - + +namespace NKikimr { +namespace NFake { + class TProxyDS : public TThrRefBase { - using TTabletId = ui64; - using TChannel = ui8; - using TGeneration = ui32; - using TStep = ui32; - - struct TBlob { - TBlob(TString buffer) - : Buffer(std::move(buffer)) - {} - - TString Buffer; - bool Keep = false; - bool DoNotKeep = false; - }; - - struct TBarrier { - TGeneration RecordGeneration = 0; - ui32 PerGenerationCounter = 0; - TGeneration CollectGeneration = 0; - TStep CollectStep = 0; - - TBarrier() = default; - TBarrier(const TBarrier& other) = default; - - TBarrier(TGeneration recordGeneration, ui32 perGenerationCounter, TGeneration collectGeneration, - TStep collectStep) - : RecordGeneration(recordGeneration) - , PerGenerationCounter(perGenerationCounter) - , CollectGeneration(collectGeneration) - , CollectStep(collectStep) - {} - - std::pair<TGeneration, TStep> MakeCollectPair() const { - return std::make_pair(CollectGeneration, CollectStep); - } - }; - - THashMap<TTabletId, TGeneration> Blocks; - THashMap<std::pair<TTabletId, TChannel>, TBarrier> Barriers; - THashMap<std::pair<TTabletId, TChannel>, TBarrier> HardBarriers; - TMap<TLogoBlobID, TBlob> Blobs; - - public: // BS events interface : Handle(event) -> event - TEvBlobStorage::TEvPutResult* Handle(TEvBlobStorage::TEvPut *msg) { - // ensure we have full blob id, with PartId set to zero - const TLogoBlobID& id = msg->Id; - Y_VERIFY(id == id.FullID()); - - // validate put against set blocks - if (IsBlocked(id.TabletID(), id.Generation())) { - return new TEvBlobStorage::TEvPutResult(NKikimrProto::BLOCKED, id, + using TTabletId = ui64; + using TChannel = ui8; + using TGeneration = ui32; + using TStep = ui32; + + struct TBlob { + TBlob(TString buffer) + : Buffer(std::move(buffer)) + {} + + TString Buffer; + bool Keep = false; + bool DoNotKeep = false; + }; + + struct TBarrier { + TGeneration RecordGeneration = 0; + ui32 PerGenerationCounter = 0; + TGeneration CollectGeneration = 0; + TStep CollectStep = 0; + + TBarrier() = default; + TBarrier(const TBarrier& other) = default; + + TBarrier(TGeneration recordGeneration, ui32 perGenerationCounter, TGeneration collectGeneration, + TStep collectStep) + : RecordGeneration(recordGeneration) + , PerGenerationCounter(perGenerationCounter) + , CollectGeneration(collectGeneration) + , CollectStep(collectStep) + {} + + std::pair<TGeneration, TStep> MakeCollectPair() const { + return std::make_pair(CollectGeneration, CollectStep); + } + }; + + THashMap<TTabletId, TGeneration> Blocks; + THashMap<std::pair<TTabletId, TChannel>, TBarrier> Barriers; + THashMap<std::pair<TTabletId, TChannel>, TBarrier> HardBarriers; + TMap<TLogoBlobID, TBlob> Blobs; + + public: // BS events interface : Handle(event) -> event + TEvBlobStorage::TEvPutResult* Handle(TEvBlobStorage::TEvPut *msg) { + // ensure we have full blob id, with PartId set to zero + const TLogoBlobID& id = msg->Id; + Y_VERIFY(id == id.FullID()); + + // validate put against set blocks + if (IsBlocked(id.TabletID(), id.Generation())) { + return new TEvBlobStorage::TEvPutResult(NKikimrProto::BLOCKED, id, GetStorageStatusFlags(), 0, 0.f); - } - - // check if this blob is not being collected -- writing such blob is a violation of BS contract + } + + // check if this blob is not being collected -- writing such blob is a violation of BS contract Y_VERIFY(!IsCollectedByBarrier(id), "Id# %s", id.ToString().data()); - - // validate that there are no blobs with the same gen/step, channel, cookie, but with different size - const TLogoBlobID base(id.TabletID(), id.Generation(), id.Step(), id.Channel(), 0, id.Cookie()); - auto iter = Blobs.lower_bound(base); - if (iter != Blobs.end()) { - const TLogoBlobID& existing = iter->first; - Y_VERIFY( - id.TabletID() != existing.TabletID() || - id.Generation() != existing.Generation() || - id.Step() != existing.Step() || - id.Cookie() != existing.Cookie() || - id.Channel() != existing.Channel() || - id == existing, + + // validate that there are no blobs with the same gen/step, channel, cookie, but with different size + const TLogoBlobID base(id.TabletID(), id.Generation(), id.Step(), id.Channel(), 0, id.Cookie()); + auto iter = Blobs.lower_bound(base); + if (iter != Blobs.end()) { + const TLogoBlobID& existing = iter->first; + Y_VERIFY( + id.TabletID() != existing.TabletID() || + id.Generation() != existing.Generation() || + id.Step() != existing.Step() || + id.Cookie() != existing.Cookie() || + id.Channel() != existing.Channel() || + id == existing, "id# %s existing# %s", id.ToString().data(), existing.ToString().data()); - if (id == existing) { - Y_VERIFY(iter->second.Buffer == msg->Buffer); - } - } - - // put an entry into logo blobs database and reply with success - Blobs.emplace(id, std::move(msg->Buffer)); + if (id == existing) { + Y_VERIFY(iter->second.Buffer == msg->Buffer); + } + } + + // put an entry into logo blobs database and reply with success + Blobs.emplace(id, std::move(msg->Buffer)); return new TEvBlobStorage::TEvPutResult(NKikimrProto::OK, id, GetStorageStatusFlags(), 0, 0.f); - } - - TEvBlobStorage::TEvGetResult* Handle(TEvBlobStorage::TEvGet *msg) { - // prepare result structure holding the returned data + } + + TEvBlobStorage::TEvGetResult* Handle(TEvBlobStorage::TEvGet *msg) { + // prepare result structure holding the returned data auto result = std::make_unique<TEvBlobStorage::TEvGetResult>(NKikimrProto::OK, msg->QuerySize, 0u); - - // traverse against requested blobs and process them - for (ui32 i = 0; i < msg->QuerySize; ++i) { - const TEvBlobStorage::TEvGet::TQuery& query = msg->Queries[i]; - - const TLogoBlobID& id = query.Id; - Y_VERIFY(id == id.FullID()); - - TEvBlobStorage::TEvGetResult::TResponse& response = result->Responses[i]; - response.Id = id; - response.Shift = query.Shift; - response.RequestedSize = query.Size; - - auto it = Blobs.find(id); - if (it != Blobs.end()) { - const auto& data = it->second; - - // we have blob and it's not under GC (otherwise it would be already deleted) -- so we reply - // with success and return requested part of blob - response.Status = NKikimrProto::OK; - - // maximum size we can return when seeking to provided Shift - const ui32 maxSize = query.Shift < data.Buffer.size() ? data.Buffer.size() - query.Shift : 0; - - // actual size we are going to return - const ui32 size = Min<ui32>(maxSize, !query.Size ? Max<ui32>() : query.Size); - - // calculate substring; use 0 instead of query.Shift because it may exceed the buffer - response.Buffer = data.Buffer.substr(size ? query.Shift : 0, size); - } else { - // ensure this blob is not under GC + + // traverse against requested blobs and process them + for (ui32 i = 0; i < msg->QuerySize; ++i) { + const TEvBlobStorage::TEvGet::TQuery& query = msg->Queries[i]; + + const TLogoBlobID& id = query.Id; + Y_VERIFY(id == id.FullID()); + + TEvBlobStorage::TEvGetResult::TResponse& response = result->Responses[i]; + response.Id = id; + response.Shift = query.Shift; + response.RequestedSize = query.Size; + + auto it = Blobs.find(id); + if (it != Blobs.end()) { + const auto& data = it->second; + + // we have blob and it's not under GC (otherwise it would be already deleted) -- so we reply + // with success and return requested part of blob + response.Status = NKikimrProto::OK; + + // maximum size we can return when seeking to provided Shift + const ui32 maxSize = query.Shift < data.Buffer.size() ? data.Buffer.size() - query.Shift : 0; + + // actual size we are going to return + const ui32 size = Min<ui32>(maxSize, !query.Size ? Max<ui32>() : query.Size); + + // calculate substring; use 0 instead of query.Shift because it may exceed the buffer + response.Buffer = data.Buffer.substr(size ? query.Shift : 0, size); + } else { + // ensure this blob is not under GC Y_VERIFY(!IsCollectedByBarrier(id), "Id# %s", id.ToString().data()); - - // reply with NODATA -- we haven't got this blob - response.Status = NKikimrProto::NODATA; - } - } - + + // reply with NODATA -- we haven't got this blob + response.Status = NKikimrProto::NODATA; + } + } + return result.release(); - } - - TEvBlobStorage::TEvBlockResult* Handle(TEvBlobStorage::TEvBlock *msg) { - NKikimrProto::EReplyStatus status = NKikimrProto::OK; - - auto it = Blocks.find(msg->TabletId); - if (it == Blocks.end()) { - Blocks.emplace(msg->TabletId, msg->Generation); - } else if (msg->Generation <= it->second) { - status = NKikimrProto::RACE; - } else { - it->second = msg->Generation; - } - - return new TEvBlobStorage::TEvBlockResult(status); - } - - TEvBlobStorage::TEvDiscoverResult* Handle(TEvBlobStorage::TEvDiscover *msg) { - ui32 blockedGeneration = 0; - if (msg->DiscoverBlockedGeneration) { - auto blockit = Blocks.find(msg->TabletId); - if (blockit != Blocks.end()) { - blockedGeneration = blockit->second; - } - } - + } + + TEvBlobStorage::TEvBlockResult* Handle(TEvBlobStorage::TEvBlock *msg) { + NKikimrProto::EReplyStatus status = NKikimrProto::OK; + + auto it = Blocks.find(msg->TabletId); + if (it == Blocks.end()) { + Blocks.emplace(msg->TabletId, msg->Generation); + } else if (msg->Generation <= it->second) { + status = NKikimrProto::RACE; + } else { + it->second = msg->Generation; + } + + return new TEvBlobStorage::TEvBlockResult(status); + } + + TEvBlobStorage::TEvDiscoverResult* Handle(TEvBlobStorage::TEvDiscover *msg) { + ui32 blockedGeneration = 0; + if (msg->DiscoverBlockedGeneration) { + auto blockit = Blocks.find(msg->TabletId); + if (blockit != Blocks.end()) { + blockedGeneration = blockit->second; + } + } + std::unique_ptr<TEvBlobStorage::TEvDiscoverResult> result; - - TLogoBlobID id(msg->TabletId, Max<ui32>(), Max<ui32>(), 0, TLogoBlobID::MaxBlobSize, TLogoBlobID::MaxCookie); - auto it = Blobs.upper_bound(id); - if (it != Blobs.begin()) { - --it; - const TLogoBlobID& lastBlobId = it->first; - if (lastBlobId.TabletID() == msg->TabletId && lastBlobId.Channel() == 0 && - lastBlobId.Generation() >= msg->MinGeneration) { - TString buffer; - if (msg->ReadBody) { - buffer = it->second.Buffer; - } - + + TLogoBlobID id(msg->TabletId, Max<ui32>(), Max<ui32>(), 0, TLogoBlobID::MaxBlobSize, TLogoBlobID::MaxCookie); + auto it = Blobs.upper_bound(id); + if (it != Blobs.begin()) { + --it; + const TLogoBlobID& lastBlobId = it->first; + if (lastBlobId.TabletID() == msg->TabletId && lastBlobId.Channel() == 0 && + lastBlobId.Generation() >= msg->MinGeneration) { + TString buffer; + if (msg->ReadBody) { + buffer = it->second.Buffer; + } + result = std::make_unique<TEvBlobStorage::TEvDiscoverResult>(lastBlobId, msg->MinGeneration, buffer, - blockedGeneration); - } - } - - if (!result) { + blockedGeneration); + } + } + + if (!result) { result = std::make_unique<TEvBlobStorage::TEvDiscoverResult>(NKikimrProto::NODATA, msg->MinGeneration, - blockedGeneration); - } - + blockedGeneration); + } + return result.release(); - } - - TEvBlobStorage::TEvRangeResult* Handle(TEvBlobStorage::TEvRange *msg) { - const TLogoBlobID& from = msg->From; - const TLogoBlobID& to = msg->To; - - Y_VERIFY(from.TabletID() == to.TabletID()); - Y_VERIFY(from.Channel() == to.Channel()); - Y_VERIFY(from.TabletID() == msg->TabletId); - + } + + TEvBlobStorage::TEvRangeResult* Handle(TEvBlobStorage::TEvRange *msg) { + const TLogoBlobID& from = msg->From; + const TLogoBlobID& to = msg->To; + + Y_VERIFY(from.TabletID() == to.TabletID()); + Y_VERIFY(from.Channel() == to.Channel()); + Y_VERIFY(from.TabletID() == msg->TabletId); + auto result = std::make_unique<TEvBlobStorage::TEvRangeResult>(NKikimrProto::OK, from, to, 0u); - - auto process = [&](const TLogoBlobID& id, const TString& buffer) { - result->Responses.emplace_back(id, buffer); - }; - - if (from <= to) { - // forward scan - for (auto it = Blobs.lower_bound(from); it != Blobs.end() && it->first <= to; ++it) { - process(it->first, it->second.Buffer); - } - } else { - // reverse scan - for (auto it = Blobs.upper_bound(from); it != Blobs.begin(); ) { - --it; - if (it->first < to) { - break; - } else { - process(it->first, it->second.Buffer); - } - } - } - + + auto process = [&](const TLogoBlobID& id, const TString& buffer) { + result->Responses.emplace_back(id, buffer); + }; + + if (from <= to) { + // forward scan + for (auto it = Blobs.lower_bound(from); it != Blobs.end() && it->first <= to; ++it) { + process(it->first, it->second.Buffer); + } + } else { + // reverse scan + for (auto it = Blobs.upper_bound(from); it != Blobs.begin(); ) { + --it; + if (it->first < to) { + break; + } else { + process(it->first, it->second.Buffer); + } + } + } + return result.release(); - } - - TEvBlobStorage::TEvCollectGarbageResult* Handle(TEvBlobStorage::TEvCollectGarbage *msg) { + } + + TEvBlobStorage::TEvCollectGarbageResult* Handle(TEvBlobStorage::TEvCollectGarbage *msg) { if (IsBlocked(msg->TabletId, msg->RecordGeneration) && (msg->CollectGeneration != Max<ui32>() || msg->CollectStep != Max<ui32>() || Blocks.at(msg->TabletId) != Max<ui32>())) { - return new TEvBlobStorage::TEvCollectGarbageResult(NKikimrProto::BLOCKED, - msg->TabletId, msg->RecordGeneration, msg->PerGenerationCounter, msg->Channel); - } - - if (msg->Hard) { - Y_VERIFY(!msg->Keep, "Unexpected Keep in HARD collect, msg# %s", msg->ToString().c_str()); - Y_VERIFY(!msg->DoNotKeep, "Unexpected DoNotKeep in HARD collect, msg# %s", msg->ToString().c_str()); - Y_VERIFY(msg->Collect, "Missing Collect in HARD collect, msg# %s", msg->ToString().c_str()); - - std::pair<TTabletId, TChannel> key(msg->TabletId, msg->Channel); - auto it = HardBarriers.find(key); - if (it != HardBarriers.end()) { - const TBarrier& barrier = it->second; - - if (msg->RecordGeneration == barrier.RecordGeneration && - msg->PerGenerationCounter == barrier.PerGenerationCounter) { - // we already have this record; ensure that the data is the same - Y_VERIFY(msg->CollectGeneration == barrier.CollectGeneration && - msg->CollectStep == barrier.CollectStep); - } else { - Y_VERIFY(std::make_pair(msg->RecordGeneration, msg->PerGenerationCounter) > - std::make_pair(barrier.RecordGeneration, barrier.PerGenerationCounter)); - Y_VERIFY(std::make_pair(msg->CollectGeneration, msg->CollectStep) >= - barrier.MakeCollectPair(), - "tabletId %" PRIu64 " requested hard collect %" PRIu32 ":%" PRIu32 - " existing barrier %" PRIu32 ":%" PRIu32 " msg# %s", - msg->TabletId, msg->CollectGeneration, msg->CollectStep, - barrier.CollectGeneration, barrier.CollectStep, msg->ToString().c_str()); - } - } - - // put new hard barrier - HardBarriers[key] = {msg->RecordGeneration, msg->PerGenerationCounter, msg->CollectGeneration, - msg->CollectStep}; - - DoCollection(msg->TabletId, msg->Channel, true, msg->CollectGeneration, msg->CollectStep); - } else { - if (msg->Keep) { - for (const TLogoBlobID& id : *msg->Keep) { - auto it = Blobs.find(id); + return new TEvBlobStorage::TEvCollectGarbageResult(NKikimrProto::BLOCKED, + msg->TabletId, msg->RecordGeneration, msg->PerGenerationCounter, msg->Channel); + } + + if (msg->Hard) { + Y_VERIFY(!msg->Keep, "Unexpected Keep in HARD collect, msg# %s", msg->ToString().c_str()); + Y_VERIFY(!msg->DoNotKeep, "Unexpected DoNotKeep in HARD collect, msg# %s", msg->ToString().c_str()); + Y_VERIFY(msg->Collect, "Missing Collect in HARD collect, msg# %s", msg->ToString().c_str()); + + std::pair<TTabletId, TChannel> key(msg->TabletId, msg->Channel); + auto it = HardBarriers.find(key); + if (it != HardBarriers.end()) { + const TBarrier& barrier = it->second; + + if (msg->RecordGeneration == barrier.RecordGeneration && + msg->PerGenerationCounter == barrier.PerGenerationCounter) { + // we already have this record; ensure that the data is the same + Y_VERIFY(msg->CollectGeneration == barrier.CollectGeneration && + msg->CollectStep == barrier.CollectStep); + } else { + Y_VERIFY(std::make_pair(msg->RecordGeneration, msg->PerGenerationCounter) > + std::make_pair(barrier.RecordGeneration, barrier.PerGenerationCounter)); + Y_VERIFY(std::make_pair(msg->CollectGeneration, msg->CollectStep) >= + barrier.MakeCollectPair(), + "tabletId %" PRIu64 " requested hard collect %" PRIu32 ":%" PRIu32 + " existing barrier %" PRIu32 ":%" PRIu32 " msg# %s", + msg->TabletId, msg->CollectGeneration, msg->CollectStep, + barrier.CollectGeneration, barrier.CollectStep, msg->ToString().c_str()); + } + } + + // put new hard barrier + HardBarriers[key] = {msg->RecordGeneration, msg->PerGenerationCounter, msg->CollectGeneration, + msg->CollectStep}; + + DoCollection(msg->TabletId, msg->Channel, true, msg->CollectGeneration, msg->CollectStep); + } else { + if (msg->Keep) { + for (const TLogoBlobID& id : *msg->Keep) { + auto it = Blobs.find(id); Y_VERIFY(it != Blobs.end(), "Id# %s", id.ToString().data()); - Y_VERIFY(!IsCollectedByBarrier(id) || (it->second.Keep && !it->second.DoNotKeep), + Y_VERIFY(!IsCollectedByBarrier(id) || (it->second.Keep && !it->second.DoNotKeep), "Id# %s Keep# %s DoNotKeep# %s", id.ToString().data(), - it->second.Keep ? "true" : "false", - it->second.DoNotKeep ? "true" : "false"); - Y_VERIFY(!it->second.DoNotKeep); - it->second.Keep = true; - } - } - - if (msg->DoNotKeep) { - for (const TLogoBlobID& id : *msg->DoNotKeep) { - auto it = Blobs.find(id); - if (it != Blobs.end()) { - it->second.DoNotKeep = true; - } - } - } - - if (msg->Collect) { - std::pair<TTabletId, TChannel> key(msg->TabletId, msg->Channel); - auto it = Barriers.find(key); - if (it != Barriers.end()) { - const TBarrier& barrier = it->second; - - if (msg->RecordGeneration == barrier.RecordGeneration && - msg->PerGenerationCounter == barrier.PerGenerationCounter) { - // we already have this record; ensure that the data is the same - Y_VERIFY(msg->CollectGeneration == barrier.CollectGeneration && - msg->CollectStep == barrier.CollectStep); - } else { - Y_VERIFY(std::make_pair(msg->RecordGeneration, msg->PerGenerationCounter) > - std::make_pair(barrier.RecordGeneration, barrier.PerGenerationCounter)); - Y_VERIFY(std::make_pair(msg->CollectGeneration, msg->CollectStep) >= - barrier.MakeCollectPair(), - "tabletId %" PRIu64 " requested collect %" PRIu32 ":%" PRIu32 - " existing barrier %" PRIu32 ":%" PRIu32 " msg# %s", - msg->TabletId, msg->CollectGeneration, msg->CollectStep, - barrier.CollectGeneration, barrier.CollectStep, msg->ToString().c_str()); - } - } - - // put new barrier - Barriers[key] = {msg->RecordGeneration, msg->PerGenerationCounter, msg->CollectGeneration, - msg->CollectStep}; - - DoCollection(msg->TabletId, msg->Channel, false, msg->CollectGeneration, msg->CollectStep); - } - } - - return new TEvBlobStorage::TEvCollectGarbageResult(NKikimrProto::OK, msg->TabletId, - msg->RecordGeneration, msg->PerGenerationCounter, msg->Channel); - } - - public: // Non-event model interaction methods - TStorageStatusFlags GetStorageStatusFlags() const noexcept { - return TStorageStatusFlags(NKikimrBlobStorage::StatusIsValid); - } - - const TMap<TLogoBlobID, TBlob>& AllMyBlobs() const noexcept { - return Blobs; - } - - private: - // check if provided generation is blocked for specific tablet - bool IsBlocked(TTabletId tabletId, TGeneration generation) const noexcept { - auto it = Blocks.find(tabletId); - return it != Blocks.end() && generation <= it->second; - } - - // check if provided blob is under garbage collection by barriers - bool IsCollectedByBarrier(const TLogoBlobID& id) const noexcept { - auto hardIt = HardBarriers.find(std::make_pair(id.TabletID(), id.Channel())); - if (hardIt != HardBarriers.end() && - std::make_pair(id.Generation(), id.Step()) <= hardIt->second.MakeCollectPair()) { - return true; - } - - auto it = Barriers.find(std::make_pair(id.TabletID(), id.Channel())); - return it != Barriers.end() && - std::make_pair(id.Generation(), id.Step()) <= it->second.MakeCollectPair(); - } - - void DoCollection(ui32 tablet, ui32 channel, bool force, ui32 Gen, ui32 Step) { - TLogoBlobID id(tablet, 0, 0, channel, 0, 0); - auto it = Blobs.lower_bound(id); - while (it != Blobs.end() && it->first.TabletID() == tablet && - it->first.Channel() == channel && std::make_pair(it->first.Generation(), - it->first.Step()) <= std::make_pair(Gen, Step)) { - const auto& data = it->second; - if (force || data.DoNotKeep || !data.Keep) { - it = Blobs.erase(it); - } else { - ++it; - } - - } - } - }; -} -} + it->second.Keep ? "true" : "false", + it->second.DoNotKeep ? "true" : "false"); + Y_VERIFY(!it->second.DoNotKeep); + it->second.Keep = true; + } + } + + if (msg->DoNotKeep) { + for (const TLogoBlobID& id : *msg->DoNotKeep) { + auto it = Blobs.find(id); + if (it != Blobs.end()) { + it->second.DoNotKeep = true; + } + } + } + + if (msg->Collect) { + std::pair<TTabletId, TChannel> key(msg->TabletId, msg->Channel); + auto it = Barriers.find(key); + if (it != Barriers.end()) { + const TBarrier& barrier = it->second; + + if (msg->RecordGeneration == barrier.RecordGeneration && + msg->PerGenerationCounter == barrier.PerGenerationCounter) { + // we already have this record; ensure that the data is the same + Y_VERIFY(msg->CollectGeneration == barrier.CollectGeneration && + msg->CollectStep == barrier.CollectStep); + } else { + Y_VERIFY(std::make_pair(msg->RecordGeneration, msg->PerGenerationCounter) > + std::make_pair(barrier.RecordGeneration, barrier.PerGenerationCounter)); + Y_VERIFY(std::make_pair(msg->CollectGeneration, msg->CollectStep) >= + barrier.MakeCollectPair(), + "tabletId %" PRIu64 " requested collect %" PRIu32 ":%" PRIu32 + " existing barrier %" PRIu32 ":%" PRIu32 " msg# %s", + msg->TabletId, msg->CollectGeneration, msg->CollectStep, + barrier.CollectGeneration, barrier.CollectStep, msg->ToString().c_str()); + } + } + + // put new barrier + Barriers[key] = {msg->RecordGeneration, msg->PerGenerationCounter, msg->CollectGeneration, + msg->CollectStep}; + + DoCollection(msg->TabletId, msg->Channel, false, msg->CollectGeneration, msg->CollectStep); + } + } + + return new TEvBlobStorage::TEvCollectGarbageResult(NKikimrProto::OK, msg->TabletId, + msg->RecordGeneration, msg->PerGenerationCounter, msg->Channel); + } + + public: // Non-event model interaction methods + TStorageStatusFlags GetStorageStatusFlags() const noexcept { + return TStorageStatusFlags(NKikimrBlobStorage::StatusIsValid); + } + + const TMap<TLogoBlobID, TBlob>& AllMyBlobs() const noexcept { + return Blobs; + } + + private: + // check if provided generation is blocked for specific tablet + bool IsBlocked(TTabletId tabletId, TGeneration generation) const noexcept { + auto it = Blocks.find(tabletId); + return it != Blocks.end() && generation <= it->second; + } + + // check if provided blob is under garbage collection by barriers + bool IsCollectedByBarrier(const TLogoBlobID& id) const noexcept { + auto hardIt = HardBarriers.find(std::make_pair(id.TabletID(), id.Channel())); + if (hardIt != HardBarriers.end() && + std::make_pair(id.Generation(), id.Step()) <= hardIt->second.MakeCollectPair()) { + return true; + } + + auto it = Barriers.find(std::make_pair(id.TabletID(), id.Channel())); + return it != Barriers.end() && + std::make_pair(id.Generation(), id.Step()) <= it->second.MakeCollectPair(); + } + + void DoCollection(ui32 tablet, ui32 channel, bool force, ui32 Gen, ui32 Step) { + TLogoBlobID id(tablet, 0, 0, channel, 0, 0); + auto it = Blobs.lower_bound(id); + while (it != Blobs.end() && it->first.TabletID() == tablet && + it->first.Channel() == channel && std::make_pair(it->first.Generation(), + it->first.Step()) <= std::make_pair(Gen, Step)) { + const auto& data = it->second; + if (force || data.DoNotKeep || !data.Keep) { + it = Blobs.erase(it); + } else { + ++it; + } + + } + } + }; +} +} diff --git a/ydb/core/blobstorage/dsproxy/ut/dsproxy_sequence_ut.cpp b/ydb/core/blobstorage/dsproxy/ut/dsproxy_sequence_ut.cpp index fdd7a92ea3..0c31b2b5ea 100644 --- a/ydb/core/blobstorage/dsproxy/ut/dsproxy_sequence_ut.cpp +++ b/ydb/core/blobstorage/dsproxy/ut/dsproxy_sequence_ut.cpp @@ -747,7 +747,7 @@ Y_UNIT_TEST(TestGivenMirror3DCGetWithFirstSlowDisk) { } Y_UNIT_TEST(TestGivenBlock42GetThenVGetResponseParts2523Nodata4ThenGetOk) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); TBlobStorageGroupType type = {TErasureType::Erasure4Plus2Block}; Setup(runtime, type); @@ -975,7 +975,7 @@ Y_UNIT_TEST(TestProtobufSizeWithMultiGet) { } Y_UNIT_TEST(TestGivenStripe42GetThenVGetResponsePartsNodata263451ThenGetOk) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); TBlobStorageGroupType type = {TErasureType::Erasure4Plus2Stripe}; Setup(runtime, type); @@ -1021,7 +1021,7 @@ Y_UNIT_TEST(TestGivenStripe42GetThenVGetResponsePartsNodata263451ThenGetOk) { Y_UNIT_TEST(TestGivenStripe42WhenGet2PartsOfBlobThenGetOk) { // Arrange - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); TBlobStorageGroupType type = {TErasureType::Erasure4Plus2Stripe}; Setup(runtime, type); @@ -1086,7 +1086,7 @@ Y_UNIT_TEST(TestGivenStripe42WhenGet2PartsOfBlobThenGetOk) { } Y_UNIT_TEST(TestGivenBlock42IntersectingPutWhenNodataOkThenOk) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); TBlobStorageGroupType type = {TErasureType::Erasure4Plus2Block}; Setup(runtime, type); @@ -1146,7 +1146,7 @@ Y_UNIT_TEST(TestGivenBlock42IntersectingPutWhenNodataOkThenOk) { } Y_UNIT_TEST(TestGivenBlock42PutWhenPartialGetThenSingleDiskRequestOk) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); TBlobStorageGroupType type = {TErasureType::Erasure4Plus2Block}; Setup(runtime, type); @@ -1255,7 +1255,7 @@ Y_UNIT_TEST(TestGivenBlock42PutWhenPartialGetThenSingleDiskRequestOk) { } Y_UNIT_TEST(TestGivenBlock42Put6PartsOnOneVDiskWhenDiscoverThenRecoverFirst) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); TBlobStorageGroupType type = {TErasureType::Erasure4Plus2Block}; Setup(runtime, type); diff --git a/ydb/core/blobstorage/nodewarden/blobstorage_node_warden_ut.cpp b/ydb/core/blobstorage/nodewarden/blobstorage_node_warden_ut.cpp index e3c74cce7b..ab058399b8 100644 --- a/ydb/core/blobstorage/nodewarden/blobstorage_node_warden_ut.cpp +++ b/ydb/core/blobstorage/nodewarden/blobstorage_node_warden_ut.cpp @@ -110,9 +110,9 @@ void SetupServices(TTestActorRuntime &runtime, TString extraPath, TIntrusivePtr< const ui32 domainId = DOMAIN_ID; const ui32 stateStorageGroup = domainId; - - TAppPrepare app; - + + TAppPrepare app; + { TString baseDir = runtime.GetTempDir(); TString keyfile = Sprintf("%s/key.txt", baseDir.data()); @@ -123,7 +123,7 @@ void SetupServices(TTestActorRuntime &runtime, TString extraPath, TIntrusivePtr< } { // setup domain info - app.ClearDomainsAndHive(); + app.ClearDomainsAndHive(); auto domain = TDomainsInfo::TDomain::ConstructDomainWithExplicitTabletIds("dc-1", domainId, 0, domainId, domainId, TVector<ui32>{domainId}, domainId, TVector<ui32>{domainId}, @@ -133,7 +133,7 @@ void SetupServices(TTestActorRuntime &runtime, TString extraPath, TIntrusivePtr< TVector<ui64>{}, DefaultPoolKinds(2)); app.AddDomain(domain.Release()); - app.AddHive(domainId, MakeDefaultHiveID(stateStorageGroup)); + app.AddHive(domainId, MakeDefaultHiveID(stateStorageGroup)); } SetupChannelProfiles(app, domainId); @@ -147,7 +147,7 @@ void SetupServices(TTestActorRuntime &runtime, TString extraPath, TIntrusivePtr< TChannelProfiles::TProfile::TChannel(TBlobStorageGroupType::ErasureMirror3, 0, NKikimrBlobStorage::TVDiskKind::Default)); } - app.SetChannels(std::move(channelProfiles)); + app.SetChannels(std::move(channelProfiles)); } ui32 groupId = TGroupID(GroupConfigurationTypeStatic, DOMAIN_ID, 0).GetRaw(); @@ -240,7 +240,7 @@ void SetupServices(TTestActorRuntime &runtime, TString extraPath, TIntrusivePtr< SetupTabletResolver(runtime, nodeIndex); } - runtime.Initialize(app.Unwrap()); + runtime.Initialize(app.Unwrap()); for (ui32 nodeIndex = 0; nodeIndex < runtime.GetNodeCount(); ++nodeIndex) { TActorId localActor = runtime.GetLocalServiceId( @@ -643,7 +643,7 @@ Y_UNIT_TEST_SUITE(TBlobStorageWardenTest) { CUSTOM_UNIT_TEST(TestGivenPDiskFormatedWithGuid1AndCreatedWithGuid2WhenYardInitThenError) { TTempDir tempDir; - TTestBasicRuntime runtime(2, false); + TTestBasicRuntime runtime(2, false); TIntrusivePtr<NPDisk::TSectorMap> sectorMap(new NPDisk::TSectorMap(32ull << 30ull)); Setup(runtime, "SectorMap:new_pdisk", sectorMap); TActorId sender0 = runtime.AllocateEdgeActor(0); diff --git a/ydb/core/blobstorage/nodewarden/node_warden_impl.cpp b/ydb/core/blobstorage/nodewarden/node_warden_impl.cpp index 47093a108d..8559844415 100644 --- a/ydb/core/blobstorage/nodewarden/node_warden_impl.cpp +++ b/ydb/core/blobstorage/nodewarden/node_warden_impl.cpp @@ -488,5 +488,5 @@ bool NKikimr::ObtainStaticKey(TEncryptionKey *key) { } IActor* NKikimr::CreateBSNodeWarden(const TIntrusivePtr<TNodeWardenConfig> &cfg) { - return new NStorage::TNodeWarden(cfg); + return new NStorage::TNodeWarden(cfg); } diff --git a/ydb/core/blobstorage/nodewarden/ya.make b/ydb/core/blobstorage/nodewarden/ya.make index b43e61e02d..81f1c9455a 100644 --- a/ydb/core/blobstorage/nodewarden/ya.make +++ b/ydb/core/blobstorage/nodewarden/ya.make @@ -1,12 +1,12 @@ -LIBRARY() - -OWNER( +LIBRARY() + +OWNER( alexvru - cthulhu - g:kikimr -) - -SRCS( + cthulhu + g:kikimr +) + +SRCS( group_stat_aggregator.cpp node_warden_cache.cpp node_warden_group.cpp @@ -20,18 +20,18 @@ SRCS( node_warden_scrub.cpp node_warden_stat_aggr.cpp node_warden_vdisk.cpp -) - -PEERDIR( +) + +PEERDIR( library/cpp/json ydb/core/base ydb/core/blobstorage/groupinfo ydb/core/blobstorage/pdisk ydb/core/control ydb/library/pdisk_io -) - -END() +) + +END() RECURSE_FOR_TESTS( ut diff --git a/ydb/core/blobstorage/vdisk/syncer/blobstorage_syncer_scheduler.cpp b/ydb/core/blobstorage/vdisk/syncer/blobstorage_syncer_scheduler.cpp index 92ae94e89f..3494f13d99 100644 --- a/ydb/core/blobstorage/vdisk/syncer/blobstorage_syncer_scheduler.cpp +++ b/ydb/core/blobstorage/vdisk/syncer/blobstorage_syncer_scheduler.cpp @@ -182,8 +182,8 @@ namespace NKikimr { // TSyncerScheduler //////////////////////////////////////////////////////////////////////////// class TSyncerScheduler : public TActorBootstrapped<TSyncerScheduler> { - using IActor::Schedule; // name is used by IActor API - + using IActor::Schedule; // name is used by IActor API + // from protobuf using ESyncStatus = NKikimrVDiskData::TSyncerVDiskEntry::ESyncStatus; using TSyncStatusVal = NKikimrVDiskData::TSyncerVDiskEntry; diff --git a/ydb/core/client/flat_ut.cpp b/ydb/core/client/flat_ut.cpp index 362c052aa1..b21ea7d7ad 100644 --- a/ydb/core/client/flat_ut.cpp +++ b/ydb/core/client/flat_ut.cpp @@ -15,7 +15,7 @@ #include <library/cpp/testing/unittest/registar.h> #include <google/protobuf/text_format.h> #include <util/generic/xrange.h> -#include <util/random/mersenne.h> +#include <util/random/mersenne.h> #include <util/system/sanitizers.h> namespace NKikimr { @@ -1437,7 +1437,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) { TPortManager pm; ui16 port = pm.GetPort(2134); - NFake::TStorage diskParams; + NFake::TStorage diskParams; diskParams.DiskSize = 500ull*1024*1024; diskParams.SectorSize = 512; diskParams.ChunkSize = 50ull*1024*1024; @@ -1728,20 +1728,20 @@ Y_UNIT_TEST_SUITE(TFlatTest) { UNIT_ASSERT_VALUES_EQUAL_C(response.GetExecutionEngineResponseStatus(), (ui32)NMiniKQL::IEngineFlat::EStatus::Complete, "Failed to write row"); } - void WriteRow(TFlatMsgBusClient& annoyingClient, TString table, ui32 key, TString value, TArrayRef<const char> large) { - TString insertRowQuery = "(" - "(let key '('('Key (Uint32 '%u))))" - "(let value '('Value (Utf8 '%s)))" - "(let large '('Large (String '%s)))" - "(let ret_ (AsList" - " (UpdateRow '/dc-1/Dir/%s key '(value large))" - "))" - "(return ret_)" - ")"; - + void WriteRow(TFlatMsgBusClient& annoyingClient, TString table, ui32 key, TString value, TArrayRef<const char> large) { + TString insertRowQuery = "(" + "(let key '('('Key (Uint32 '%u))))" + "(let value '('Value (Utf8 '%s)))" + "(let large '('Large (String '%s)))" + "(let ret_ (AsList" + " (UpdateRow '/dc-1/Dir/%s key '(value large))" + "))" + "(return ret_)" + ")"; + RunWriteQueryRetryOverloads(annoyingClient, Sprintf(insertRowQuery.data(), key, value.data(), large.data(), table.data())); - } - + } + void WriteRow(TFlatMsgBusClient& annoyingClient, TString table, ui32 key, TString value) { TString insertRowQuery = "(" "(let key '('('Key (Uint32 '%u))))" @@ -1755,15 +1755,15 @@ Y_UNIT_TEST_SUITE(TFlatTest) { RunWriteQueryRetryOverloads(annoyingClient, Sprintf(insertRowQuery.data(), key, value.data(), table.data())); } - void WriteRandomRows(TFlatMsgBusClient &client, TString table, ui64 seed, ui32 rows) { - TMersenne<ui64> rnd(seed); - NTable::NTest::TRandomString<decltype(rnd)> blobs(rnd); - - for (auto seq : xrange(rows)) { + void WriteRandomRows(TFlatMsgBusClient &client, TString table, ui64 seed, ui32 rows) { + TMersenne<ui64> rnd(seed); + NTable::NTest::TRandomString<decltype(rnd)> blobs(rnd); + + for (auto seq : xrange(rows)) { WriteRow(client, table, seq, blobs.Do(rnd.Uniform(4, 1600))); - } - } - + } + } + TString ReadRow(TFlatMsgBusClient& annoyingClient, TString table, ui32 key) { TString query = R"( @@ -1793,7 +1793,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) { Name: "TableOld" Columns { Name: "Key" Type: "Uint32"} Columns { Name: "Value" Type: "Utf8"} - Columns { Name: "Large" Type: "String" Family: 0 } + Columns { Name: "Large" Type: "String" Family: 0 } Columns { Name: "unused001" Type: "Bool"} Columns { Name: "unused002" Type: "Uint32"} Columns { Name: "unused003" Type: "Int64"} @@ -1823,12 +1823,12 @@ Y_UNIT_TEST_SUITE(TFlatTest) { KeepInCache: true } } - ColumnFamilies { - Id: 0 - Storage: ColumnStorageTest_1_2_1k - ColumnCache: ColumnCacheNone - } - EnableFilterByKey: true + ColumnFamilies { + Id: 0 + Storage: ColumnStorageTest_1_2_1k + ColumnCache: ColumnCacheNone + } + EnableFilterByKey: true } )___"; @@ -1836,20 +1836,20 @@ Y_UNIT_TEST_SUITE(TFlatTest) { annoyingClient.MkDir("/dc-1", "Dir"); annoyingClient.CreateTable("/dc-1/Dir", Sprintf(table, withFollowers ? 2 : 0)); - TMersenne<ui64> rnd; - NTable::NTest::TRandomString<decltype(rnd)> blobs(rnd); - - for (ui32 i = 0; i < 8; ++i) { - WriteRow(annoyingClient, "TableOld", i, "AAA", blobs.Do(rnd.Uniform(512, 1536))); - WriteRow(annoyingClient, "TableOld", 0x80000000 + i, "BBB", blobs.Do(rnd.Uniform(512, 1536))); + TMersenne<ui64> rnd; + NTable::NTest::TRandomString<decltype(rnd)> blobs(rnd); + + for (ui32 i = 0; i < 8; ++i) { + WriteRow(annoyingClient, "TableOld", i, "AAA", blobs.Do(rnd.Uniform(512, 1536))); + WriteRow(annoyingClient, "TableOld", 0x80000000 + i, "BBB", blobs.Do(rnd.Uniform(512, 1536))); } } TString ReadFromTable(TFlatMsgBusClient& annoyingClient, TString table, ui32 fromKey = 0, bool follower = false) { const char* readQuery = "(" - "(let range1 '('IncFrom '('Key (Uint32 '%d) (Void) )))" - "(let select '('Key 'Value 'Large))" + "(let range1 '('IncFrom '('Key (Uint32 '%d) (Void) )))" + "(let select '('Key 'Value 'Large))" "(let options '())" "(let pgmReturn (AsList" " (SetResult 'range1 (SelectRange '%s range1 select options (Uint32 '%d)))" @@ -1892,8 +1892,8 @@ Y_UNIT_TEST_SUITE(TFlatTest) { TServer cleverServer = TServer(TServerSettings(port)); - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + TFlatMsgBusClient annoyingClient(port); PrepareSourceTable(annoyingClient); @@ -1902,13 +1902,13 @@ Y_UNIT_TEST_SUITE(TFlatTest) { cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::FLAT_TX_SCHEMESHARD, NActors::NLog::PRI_DEBUG); cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::TX_DATASHARD, NActors::NLog::PRI_DEBUG); Cerr << "Copy TableOld to Table" << Endl; - + annoyingClient.CreateTable("/dc-1/Dir", " Name: \"Table\" CopyFromTable: \"/dc-1/Dir/TableOld\""); TString strResultOld = ReadFromTable(annoyingClient, "/dc-1/Dir/TableOld"); TString strResult = ReadFromTable(annoyingClient, "/dc-1/Dir/Table"); - Cout << strResultOld << Endl; + Cout << strResultOld << Endl; UNIT_ASSERT_NO_DIFF(strResult, strResultOld); // Make second copy of the old table @@ -1978,8 +1978,8 @@ Y_UNIT_TEST_SUITE(TFlatTest) { ui16 port = pm.GetPort(2134); TServer cleverServer = TServer(TServerSettings(port)); - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + TFlatMsgBusClient annoyingClient(port); PrepareSourceTable(annoyingClient); @@ -2007,8 +2007,8 @@ Y_UNIT_TEST_SUITE(TFlatTest) { ui16 port = pm.GetPort(2134); TServer cleverServer = TServer(TServerSettings(port)); - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + TFlatMsgBusClient annoyingClient(port); PrepareSourceTable(annoyingClient); @@ -2016,7 +2016,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) { // Copy the table cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::FLAT_TX_SCHEMESHARD, NActors::NLog::PRI_DEBUG); cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::TX_DATASHARD, NActors::NLog::PRI_DEBUG); - + Cerr << "Copy TableOld to Table" << Endl; annoyingClient.CreateTable("/dc-1/Dir", " Name: \"Table\" CopyFromTable: \"/dc-1/Dir/TableOld\"" " PartitionConfig { FollowerCount: 1 }"); @@ -2053,8 +2053,8 @@ Y_UNIT_TEST_SUITE(TFlatTest) { ui16 port = pm.GetPort(2134); TServer cleverServer = TServer(TServerSettings(port)); - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + TFlatMsgBusClient annoyingClient(port); PrepareSourceTable(annoyingClient); @@ -2102,8 +2102,8 @@ Y_UNIT_TEST_SUITE(TFlatTest) { ui16 port = pm.GetPort(2134); TServer cleverServer = TServer(TServerSettings(port)); - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + TFlatMsgBusClient annoyingClient(port); PrepareSourceTable(annoyingClient); @@ -2140,8 +2140,8 @@ Y_UNIT_TEST_SUITE(TFlatTest) { ui16 port = pm.GetPort(2134); TServer cleverServer = TServer(TServerSettings(port)); - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + TFlatMsgBusClient annoyingClient(port); PrepareSourceTable(annoyingClient); @@ -2153,7 +2153,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) { // Copy the table cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::FLAT_TX_SCHEMESHARD, NActors::NLog::PRI_DEBUG); cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::TX_DATASHARD, NActors::NLog::PRI_DEBUG); - + Cerr << "Copy TableOld to Table" << Endl; annoyingClient.CreateTable("/dc-1/Dir", R"___( Name: "Table" @@ -2180,11 +2180,11 @@ Y_UNIT_TEST_SUITE(TFlatTest) { KeepInCache: true } } - ColumnFamilies { - Id: 0 - Storage: ColumnStorageTest_1_2_1k - ColumnCache: ColumnCacheNone - } + ColumnFamilies { + Id: 0 + Storage: ColumnStorageTest_1_2_1k + ColumnCache: ColumnCacheNone + } } )___"); @@ -2192,7 +2192,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) { datashards.insert(partitions.begin(), partitions.end()); // Write new rows to the copy in order to trigger compaction - WriteRandomRows(annoyingClient, "Table", 666, 100); + WriteRandomRows(annoyingClient, "Table", 666, 100); TString strResult = ReadFromTable(annoyingClient, "/dc-1/Dir/Table"); // Delete original table @@ -2212,8 +2212,8 @@ Y_UNIT_TEST_SUITE(TFlatTest) { ui16 port = pm.GetPort(2134); TServer cleverServer = TServer(TServerSettings(port)); - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + TFlatMsgBusClient annoyingClient(port); PrepareSourceTable(annoyingClient); @@ -2225,7 +2225,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) { // Copy the table cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::FLAT_TX_SCHEMESHARD, NActors::NLog::PRI_DEBUG); cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::TX_DATASHARD, NActors::NLog::PRI_DEBUG); - + Cerr << "Copy TableOld to Table" << Endl; annoyingClient.CreateTable("/dc-1/Dir", R"___( Name: "Table" @@ -2257,11 +2257,11 @@ Y_UNIT_TEST_SUITE(TFlatTest) { UpliftPartSize: 0 } } - ColumnFamilies { - Id: 0 - Storage: ColumnStorageTest_1_2_1k - ColumnCache: ColumnCacheNone - } + ColumnFamilies { + Id: 0 + Storage: ColumnStorageTest_1_2_1k + ColumnCache: ColumnCacheNone + } } )___"); @@ -2269,8 +2269,8 @@ Y_UNIT_TEST_SUITE(TFlatTest) { annoyingClient.DeleteTable("/dc-1/Dir", "TableOld"); // Write new rows to the copy in order to trigger compaction - WriteRandomRows(annoyingClient, "Table", 666, 100); - + WriteRandomRows(annoyingClient, "Table", 666, 100); + // Check that first partition of the original table is deleted after part is returned WaitForTabletsToBeDeletedInHive(annoyingClient, cleverServer.GetRuntime(), THashSet<ui64>({partitions[0]})); @@ -2294,8 +2294,8 @@ Y_UNIT_TEST_SUITE(TFlatTest) { ui16 port = pm.GetPort(2134); TServer cleverServer = TServer(TServerSettings(port)); - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + TFlatMsgBusClient annoyingClient(port); PrepareSourceTable(annoyingClient); @@ -2413,8 +2413,8 @@ Y_UNIT_TEST_SUITE(TFlatTest) { TServer cleverServer = TServer(TServerSettings(port)); DisableSplitMergePartCountLimit(cleverServer); - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + TFlatMsgBusClient annoyingClient(port); PrepareSourceTable(annoyingClient); // cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::FLAT_TX_SCHEMESHARD, NActors::NLog::PRI_DEBUG); @@ -2473,9 +2473,9 @@ Y_UNIT_TEST_SUITE(TFlatTest) { ui16 port = pm.GetPort(2134); TServer cleverServer = TServer(TServerSettings(port)); DisableSplitMergePartCountLimit(cleverServer); - - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - + + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + TFlatMsgBusClient annoyingClient(port); PrepareSourceTable(annoyingClient); @@ -2510,9 +2510,9 @@ Y_UNIT_TEST_SUITE(TFlatTest) { ui16 port = pm.GetPort(2134); TServer cleverServer = TServer(TServerSettings(port)); DisableSplitMergePartCountLimit(cleverServer); - - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - + + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + TFlatMsgBusClient annoyingClient(port); PrepareSourceTable(annoyingClient); @@ -2546,9 +2546,9 @@ Y_UNIT_TEST_SUITE(TFlatTest) { ui16 port = pm.GetPort(2134); TServer cleverServer = TServer(TServerSettings(port)); DisableSplitMergePartCountLimit(cleverServer); - - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - + + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + TFlatMsgBusClient annoyingClient(port); PrepareSourceTable(annoyingClient); @@ -2639,9 +2639,9 @@ Y_UNIT_TEST_SUITE(TFlatTest) { ui16 port = pm.GetPort(2134); TServer cleverServer = TServer(TServerSettings(port)); DisableSplitMergePartCountLimit(cleverServer); - - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - + + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + TFlatMsgBusClient annoyingClient(port); PrepareSourceTable(annoyingClient); @@ -2677,9 +2677,9 @@ Y_UNIT_TEST_SUITE(TFlatTest) { ui16 port = pm.GetPort(2134); TServer cleverServer = TServer(TServerSettings(port)); DisableSplitMergePartCountLimit(cleverServer); - - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - + + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + TFlatMsgBusClient annoyingClient(port); PrepareSourceTable(annoyingClient); @@ -2717,9 +2717,9 @@ Y_UNIT_TEST_SUITE(TFlatTest) { ui16 port = pm.GetPort(2134); TServer cleverServer = TServer(TServerSettings(port).SetNodeCount(2)); DisableSplitMergePartCountLimit(cleverServer); - - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - + + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + TFlatMsgBusClient annoyingClient(port); PrepareSourceTable(annoyingClient, true); @@ -2769,61 +2769,61 @@ Y_UNIT_TEST_SUITE(TFlatTest) { } Y_UNIT_TEST(WriteSplitKillRead) { - TPortManager pm; - ui16 port = pm.GetPort(2134); + TPortManager pm; + ui16 port = pm.GetPort(2134); TServer cleverServer = TServer(TServerSettings(port)); DisableSplitMergePartCountLimit(cleverServer); - - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - - TFlatMsgBusClient annoyingClient(port); - PrepareSourceTable(annoyingClient); - - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::FLAT_TX_SCHEMESHARD, NActors::NLog::PRI_DEBUG); - - // Write new rows to the copy in order to trigger compaction + + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + + TFlatMsgBusClient annoyingClient(port); + PrepareSourceTable(annoyingClient); + + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::FLAT_TX_SCHEMESHARD, NActors::NLog::PRI_DEBUG); + + // Write new rows to the copy in order to trigger compaction TMap<ui32, TString> rows1 = { - {1, "AAA"}, - {101, "BBB"}, - {201, "CCC"} - }; - for (const auto& r : rows1) { - WriteRow(annoyingClient, "TableOld", r.first, r.second); - } - - SplitTable(annoyingClient, "/dc-1/Dir/TableOld", 0, {100, 200}); - + {1, "AAA"}, + {101, "BBB"}, + {201, "CCC"} + }; + for (const auto& r : rows1) { + WriteRow(annoyingClient, "TableOld", r.first, r.second); + } + + SplitTable(annoyingClient, "/dc-1/Dir/TableOld", 0, {100, 200}); + TMap<ui32, TString> rows2 = { - {2, "2222AAA"}, - {102, "2222BBB"}, - {202, "2222CCC"} - }; - for (const auto& r : rows2) { - WriteRow(annoyingClient, "TableOld", r.first, r.second); - } - - for (auto tableId: annoyingClient.GetTablePartitions("/dc-1/Dir/TableOld")) - annoyingClient.KillTablet(cleverServer, tableId); - + {2, "2222AAA"}, + {102, "2222BBB"}, + {202, "2222CCC"} + }; + for (const auto& r : rows2) { + WriteRow(annoyingClient, "TableOld", r.first, r.second); + } + + for (auto tableId: annoyingClient.GetTablePartitions("/dc-1/Dir/TableOld")) + annoyingClient.KillTablet(cleverServer, tableId); + TMap<ui32, TString> rows = rows1; - rows.insert(rows2.begin(), rows2.end()); - for (const auto& r : rows) { - TString val = ReadRow(annoyingClient, "TableOld", r.first); - UNIT_ASSERT_VALUES_EQUAL(val, r.second); - } - - annoyingClient.DeleteTable("/dc-1/Dir", "TableOld"); - annoyingClient.Ls("/dc-1/Dir/TableOld"); - } - + rows.insert(rows2.begin(), rows2.end()); + for (const auto& r : rows) { + TString val = ReadRow(annoyingClient, "TableOld", r.first); + UNIT_ASSERT_VALUES_EQUAL(val, r.second); + } + + annoyingClient.DeleteTable("/dc-1/Dir", "TableOld"); + annoyingClient.Ls("/dc-1/Dir/TableOld"); + } + Y_UNIT_TEST(SplitBoundaryRead) { TPortManager pm; ui16 port = pm.GetPort(2134); TServer cleverServer = TServer(TServerSettings(port)); DisableSplitMergePartCountLimit(cleverServer); - - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - + + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + TFlatMsgBusClient annoyingClient(port); PrepareSourceTable(annoyingClient); @@ -2840,9 +2840,9 @@ Y_UNIT_TEST_SUITE(TFlatTest) { ui16 port = pm.GetPort(2134); TServer cleverServer = TServer(TServerSettings(port)); DisableSplitMergePartCountLimit(cleverServer); - - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - + + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + TFlatMsgBusClient annoyingClient(port); PrepareSourceTable(annoyingClient); @@ -2888,9 +2888,9 @@ Y_UNIT_TEST_SUITE(TFlatTest) { ui16 port = pm.GetPort(2134); TServer cleverServer = TServer(TServerSettings(port)); DisableSplitMergePartCountLimit(cleverServer); - - cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - + + cleverServer.GetRuntime()->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + TFlatMsgBusClient annoyingClient(port); const char * tableDescr = R"___( @@ -3259,12 +3259,12 @@ Y_UNIT_TEST_SUITE(TFlatTest) { UNIT_ASSERT(res->Record.HasTabletCounters()); bool found = false; for (const auto& sc : res->Record.GetTabletCounters().GetExecutorCounters().GetSimpleCounters()) { - if (sc.GetName() == "DbDataBytes") { + if (sc.GetName() == "DbDataBytes") { found = true; break; } } - UNIT_ASSERT_C(found, "DbDataBytes counter not found"); + UNIT_ASSERT_C(found, "DbDataBytes counter not found"); } void LargeDatashardReplyRO(TFlatMsgBusClient& client) { @@ -3505,7 +3505,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) { TFlatMsgBusClient annoyingClient(port); - const char * table = R"(Name: "TableWithFilter" + const char * table = R"(Name: "TableWithFilter" Columns { Name: "key1" Type: "Uint32" } Columns { Name: "value" Type: "Uint32" } KeyColumnNames: ["key1"] @@ -3529,13 +3529,13 @@ Y_UNIT_TEST_SUITE(TFlatTest) { KeepInCache: false } } - EnableFilterByKey: true + EnableFilterByKey: true } )"; annoyingClient.InitRoot(); - auto res = annoyingClient.CreateTable("/dc-1", table); - UNIT_ASSERT_VALUES_EQUAL(res, NMsgBusProxy::MSTATUS_OK); + auto res = annoyingClient.CreateTable("/dc-1", table); + UNIT_ASSERT_VALUES_EQUAL(res, NMsgBusProxy::MSTATUS_OK); const ui32 ROW_COUNT = 30; @@ -3545,18 +3545,18 @@ Y_UNIT_TEST_SUITE(TFlatTest) { annoyingClient.FlatQuery(Sprintf(R"(( (let row_ '('('key1 (Uint32 '%u)))) (let cols_ '('('value (Uint32 '%u)))) - (let insert (UpdateRow '/dc-1/TableWithFilter row_ cols_)) + (let insert (UpdateRow '/dc-1/TableWithFilter row_ cols_)) (let ret_ (AsList insert)) (return ret_) ))", i, i)); } - Cout << "SELECT value FROM TableWithFilter WHERE key = i" << Endl; + Cout << "SELECT value FROM TableWithFilter WHERE key = i" << Endl; for (ui32 i = 0; i < ROW_COUNT; ++i) { auto res = annoyingClient.FlatQuery(Sprintf(R"(( (let row_ '('('key1 (Uint32 '%u)))) (let cols_ '('value)) - (let select_ (SelectRow '/dc-1/TableWithFilter row_ cols_)) + (let select_ (SelectRow '/dc-1/TableWithFilter row_ cols_)) (let ret_ (AsList (SetResult 'ret0 select_))) (return ret_) ))", i)); @@ -3570,12 +3570,12 @@ Y_UNIT_TEST_SUITE(TFlatTest) { // Extend the key Cout << "ALTER TABLE Table DROP PRIMARY KEY, ADD COLUMN key2 ADD PRIMARY KEY(key1, key2)" << Endl; - res = annoyingClient.AlterTable("/dc-1", R"( - Name: "TableWithFilter" + res = annoyingClient.AlterTable("/dc-1", R"( + Name: "TableWithFilter" Columns { Name: "key2" Type: "Uint64" } KeyColumnNames: ["key1", "key2"] )"); - UNIT_ASSERT_VALUES_EQUAL(res, NMsgBusProxy::MSTATUS_OK); + UNIT_ASSERT_VALUES_EQUAL(res, NMsgBusProxy::MSTATUS_OK); // Read old rows Cout << "SELECT value FROM Table WHERE key1 = i AND key2 is NULL" << Endl; @@ -3583,7 +3583,7 @@ Y_UNIT_TEST_SUITE(TFlatTest) { auto res = annoyingClient.FlatQuery(Sprintf(R"(( (let row_ '('('key1 (Uint32 '%u)) '('key2 (Null)))) (let cols_ '('value)) - (let select_ (SelectRow '/dc-1/TableWithFilter row_ cols_)) + (let select_ (SelectRow '/dc-1/TableWithFilter row_ cols_)) (let ret_ (AsList (SetResult 'ret0 select_))) (return ret_) ))", i)); diff --git a/ydb/core/client/server/msgbus_server_pq_metarequest_ut.cpp b/ydb/core/client/server/msgbus_server_pq_metarequest_ut.cpp index 237bba147b..07847a61c9 100644 --- a/ydb/core/client/server/msgbus_server_pq_metarequest_ut.cpp +++ b/ydb/core/client/server/msgbus_server_pq_metarequest_ut.cpp @@ -41,7 +41,7 @@ protected: //TTestActorRuntime::SetVerbose(true); // debug events // Initialize runtime - Runtime = MakeHolder<TTestBasicRuntime>(); + Runtime = MakeHolder<TTestBasicRuntime>(); Runtime->SetObserverFunc([this](TTestActorRuntimeBase&, TAutoPtr<IEventHandle>& event) { return EventsObserver(event); }); diff --git a/ydb/core/cms/cms_impl.h b/ydb/core/cms/cms_impl.h index 4813888490..5e155eb322 100644 --- a/ydb/core/cms/cms_impl.h +++ b/ydb/core/cms/cms_impl.h @@ -15,7 +15,7 @@ #include <ydb/core/engine/minikql/flat_local_tx_factory.h> #include <util/generic/stack.h> -#include <util/generic/queue.h> +#include <util/generic/queue.h> namespace NKikimr { namespace NCms { @@ -429,7 +429,7 @@ private: public: TCms(const TActorId &tablet, TTabletStorageInfo *info) : TActor(&TThis::StateInit) - , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) + , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) , State(new TCmsState) , Logger(State) , ConfigSubscriptionId(0) diff --git a/ydb/core/engine/minikql/flat_local_minikql_host.h b/ydb/core/engine/minikql/flat_local_minikql_host.h index edfd182286..a0af57eea0 100644 --- a/ydb/core/engine/minikql/flat_local_minikql_host.h +++ b/ydb/core/engine/minikql/flat_local_minikql_host.h @@ -1,10 +1,10 @@ #pragma once - + #include "flat_local_tx_factory.h" #include "minikql_engine_host.h" namespace NKikimr { -namespace NMiniKQL { +namespace NMiniKQL { class TLocalMiniKQLHost : public TEngineHost { public: @@ -15,15 +15,15 @@ public: const TMiniKQLFactory* factory) : TEngineHost(db, counters, settings) , Factory(factory) - {} - + {} + private: - bool IsMyKey(const TTableId& tableId, const TArrayRef<const TCell>& row) const override - { - Y_UNUSED(row); + bool IsMyKey(const TTableId& tableId, const TArrayRef<const TCell>& row) const override + { + Y_UNUSED(row); return (tableId.PathId.OwnerId == GetShardId()); - } - + } + TRowVersion GetWriteVersion(const TTableId& tableId) const override { return Factory->GetWriteVersion(tableId); diff --git a/ydb/core/engine/minikql/flat_local_minikql_program.h b/ydb/core/engine/minikql/flat_local_minikql_program.h index 2c548f529e..d207903586 100644 --- a/ydb/core/engine/minikql/flat_local_minikql_program.h +++ b/ydb/core/engine/minikql/flat_local_minikql_program.h @@ -1,67 +1,67 @@ -#pragma once - +#pragma once + #include <ydb/core/base/tablet.h> - -namespace NKikimr { -namespace NMiniKQL { - - struct TLocalMiniKQLProgram { - struct TProgramFragment { - TString Binary; - TString Text; - }; - - TProgramFragment Program; - TProgramFragment Params; - - bool CompileOnly; - - static TLocalMiniKQLProgram TextText(const TString &textPgm, const TString &textParams) { - return {{TString(), textPgm}, {TString(), textParams}, false}; - } - static TLocalMiniKQLProgram TextBin(const TString &textPgm, const TString &binParams) { - return {{TString(), textPgm},{binParams, TString()}, false}; - } - static TLocalMiniKQLProgram BinText(const TString &binPgm, const TString &textParams) { - return {{binPgm, TString()},{TString(), textParams}, false}; - } - static TLocalMiniKQLProgram BinBin(const TString &binPgm, const TString &binParams) { - return {{binPgm, TString()},{binParams, TString()}, false}; - } - static TLocalMiniKQLProgram Compile(const TString &textPgm, const TString &textParams) { - return {{TString(), textPgm},{TString(), textParams}, true}; - } - - TLocalMiniKQLProgram() - : CompileOnly(false) - {} - - TLocalMiniKQLProgram(const TProgramFragment &program, const TProgramFragment ¶ms, bool compileOnly) - : Program(program) - , Params(params) - , CompileOnly(compileOnly) - {} - - TLocalMiniKQLProgram(const TEvTablet::TEvLocalMKQL &msg) { - const auto &pgm = msg.Record.GetProgram(); - if (pgm.HasProgram()) { - const auto &x = pgm.GetProgram(); - if (x.HasBin()) - Program.Binary = x.GetBin(); - else if (x.HasText()) - Program.Text = x.GetText(); - } - if (pgm.HasParams()) { - const auto &x = pgm.GetParams(); - if (x.HasBin()) - Params.Binary = x.GetBin(); - else if (x.HasText()) - Params.Text = x.GetText(); - } - - CompileOnly = pgm.HasMode() && (pgm.GetMode() == NKikimrTxUserProxy::TMiniKQLTransaction_EMode_COMPILE); - } - }; - -} -} + +namespace NKikimr { +namespace NMiniKQL { + + struct TLocalMiniKQLProgram { + struct TProgramFragment { + TString Binary; + TString Text; + }; + + TProgramFragment Program; + TProgramFragment Params; + + bool CompileOnly; + + static TLocalMiniKQLProgram TextText(const TString &textPgm, const TString &textParams) { + return {{TString(), textPgm}, {TString(), textParams}, false}; + } + static TLocalMiniKQLProgram TextBin(const TString &textPgm, const TString &binParams) { + return {{TString(), textPgm},{binParams, TString()}, false}; + } + static TLocalMiniKQLProgram BinText(const TString &binPgm, const TString &textParams) { + return {{binPgm, TString()},{TString(), textParams}, false}; + } + static TLocalMiniKQLProgram BinBin(const TString &binPgm, const TString &binParams) { + return {{binPgm, TString()},{binParams, TString()}, false}; + } + static TLocalMiniKQLProgram Compile(const TString &textPgm, const TString &textParams) { + return {{TString(), textPgm},{TString(), textParams}, true}; + } + + TLocalMiniKQLProgram() + : CompileOnly(false) + {} + + TLocalMiniKQLProgram(const TProgramFragment &program, const TProgramFragment ¶ms, bool compileOnly) + : Program(program) + , Params(params) + , CompileOnly(compileOnly) + {} + + TLocalMiniKQLProgram(const TEvTablet::TEvLocalMKQL &msg) { + const auto &pgm = msg.Record.GetProgram(); + if (pgm.HasProgram()) { + const auto &x = pgm.GetProgram(); + if (x.HasBin()) + Program.Binary = x.GetBin(); + else if (x.HasText()) + Program.Text = x.GetText(); + } + if (pgm.HasParams()) { + const auto &x = pgm.GetParams(); + if (x.HasBin()) + Params.Binary = x.GetBin(); + else if (x.HasText()) + Params.Text = x.GetText(); + } + + CompileOnly = pgm.HasMode() && (pgm.GetMode() == NKikimrTxUserProxy::TMiniKQLTransaction_EMode_COMPILE); + } + }; + +} +} diff --git a/ydb/core/engine/minikql/flat_local_tx_factory.cpp b/ydb/core/engine/minikql/flat_local_tx_factory.cpp index d23f4d8bc7..f3859d3452 100644 --- a/ydb/core/engine/minikql/flat_local_tx_factory.cpp +++ b/ydb/core/engine/minikql/flat_local_tx_factory.cpp @@ -1,27 +1,27 @@ #include "flat_local_tx_factory.h" -#include "flat_local_minikql_program.h" -#include "flat_local_tx_minikql.h" +#include "flat_local_minikql_program.h" +#include "flat_local_tx_minikql.h" #include "flat_local_tx_read_columns.h" -#include "flat_local_tx_scheme.h" - -namespace NKikimr { -namespace NMiniKQL { - -using ITransaction = TMiniKQLFactory::ITransaction; - +#include "flat_local_tx_scheme.h" + +namespace NKikimr { +namespace NMiniKQL { + +using ITransaction = TMiniKQLFactory::ITransaction; + TAutoPtr<ITransaction> TMiniKQLFactory::Make(TEvTablet::TEvLocalMKQL::TPtr &ev) -{ - TLocalMiniKQLProgram program(*ev->Get()); - +{ + TLocalMiniKQLProgram program(*ev->Get()); + return new TFlatLocalMiniKQL(ev->Sender, program, this); -} - +} + TAutoPtr<ITransaction> TMiniKQLFactory::Make(TEvTablet::TEvLocalSchemeTx::TPtr &ev) -{ - return new TFlatLocalSchemeTx(ev->Sender, ev); -} - +{ + return new TFlatLocalSchemeTx(ev->Sender, ev); +} + TAutoPtr<ITransaction> TMiniKQLFactory::Make(TEvTablet::TEvLocalReadColumns::TPtr &ev) { return new TFlatLocalReadColumns(ev->Sender, ev); @@ -31,13 +31,13 @@ TRowVersion TMiniKQLFactory::GetWriteVersion(const TTableId& tableId) const { Y_UNUSED(tableId); return TRowVersion::Min(); -} +} TRowVersion TMiniKQLFactory::GetReadVersion(const TTableId& tableId) const { Y_UNUSED(tableId); return TRowVersion::Max(); -} +} IChangeCollector* TMiniKQLFactory::GetChangeCollector(const TTableId& tableId) const { diff --git a/ydb/core/engine/minikql/flat_local_tx_factory.h b/ydb/core/engine/minikql/flat_local_tx_factory.h index 200d21b369..cbf1da0680 100644 --- a/ydb/core/engine/minikql/flat_local_tx_factory.h +++ b/ydb/core/engine/minikql/flat_local_tx_factory.h @@ -1,16 +1,16 @@ -#pragma once - +#pragma once + #include "change_collector_iface.h" #include <ydb/core/scheme/scheme_tabledefs.h> #include <ydb/core/tablet_flat/tablet_flat_executed.h> - -namespace NKikimr { -namespace NMiniKQL { - - struct TMiniKQLFactory : NTabletFlatExecutor::IMiniKQLFactory { + +namespace NKikimr { +namespace NMiniKQL { + + struct TMiniKQLFactory : NTabletFlatExecutor::IMiniKQLFactory { using ITransaction = NTabletFlatExecutor::ITransaction; - + TAutoPtr<ITransaction> Make(TEvTablet::TEvLocalMKQL::TPtr&) override; TAutoPtr<ITransaction> Make(TEvTablet::TEvLocalSchemeTx::TPtr&) override; TAutoPtr<ITransaction> Make(TEvTablet::TEvLocalReadColumns::TPtr &ev) override; @@ -18,7 +18,7 @@ namespace NMiniKQL { virtual TRowVersion GetWriteVersion(const TTableId& tableId) const; virtual TRowVersion GetReadVersion(const TTableId& tableId) const; virtual IChangeCollector* GetChangeCollector(const TTableId& tableId) const; - }; - -} -} + }; + +} +} diff --git a/ydb/core/engine/minikql/flat_local_tx_minikql.h b/ydb/core/engine/minikql/flat_local_tx_minikql.h index 0feabf20e6..c1357eda21 100644 --- a/ydb/core/engine/minikql/flat_local_tx_minikql.h +++ b/ydb/core/engine/minikql/flat_local_tx_minikql.h @@ -1,5 +1,5 @@ -#pragma once - +#pragma once + #include "flat_local_tx_factory.h" #include "flat_local_minikql_host.h" #include <ydb/core/tablet_flat/tablet_flat_executed.h> @@ -12,11 +12,11 @@ #include <ydb/core/base/appdata.h> namespace NKikimr { -namespace NMiniKQL { +namespace NMiniKQL { class TLocalDbSchemeResolver : public NYql::IDbSchemeResolver { public: - TLocalDbSchemeResolver(const NTable::TScheme& scheme, ui64 tabletId) + TLocalDbSchemeResolver(const NTable::TScheme& scheme, ui64 tabletId) : Scheme(scheme) , TabletId(tabletId) {} @@ -31,7 +31,7 @@ public: if (!tableId) { result = TTableResult(TTableResult::Error, "Unknown table " + table.TableName); } else { - const auto *tableInfo = Scheme.Tables.FindPtr(*tableId); + const auto *tableInfo = Scheme.Tables.FindPtr(*tableId); Y_VERIFY(tableInfo); result.KeyColumnCount = tableInfo->KeyColumns.size(); @@ -45,7 +45,7 @@ public: break; } - const auto *columnInfo = tableInfo->Columns.FindPtr(*columnId); + const auto *columnInfo = tableInfo->Columns.FindPtr(*columnId); Y_VERIFY(columnInfo); auto insertResult = result.Columns.insert(std::make_pair(column, IDbSchemeResolver::TTableResult::TColumn @@ -66,12 +66,12 @@ public: Y_FAIL("Not implemented for local resolve."); } private: - const NTable::TScheme& Scheme; + const NTable::TScheme& Scheme; const ui64 TabletId; }; class TFlatLocalMiniKQL : public NTabletFlatExecutor::ITransaction { - ui64 TabletId = Max<ui64>(); + ui64 TabletId = Max<ui64>(); const TActorId Sender; const TLocalMiniKQLProgram SourceProgram; const TMiniKQLFactory* const Factory; @@ -81,8 +81,8 @@ class TFlatLocalMiniKQL : public NTabletFlatExecutor::ITransaction { TAutoPtr<NYql::TMiniKQLCompileResult> ProgramCompileResult; - IEngineFlat::EResult EngineResultStatusCode; - IEngineFlat::EStatus EngineResponseStatus; + IEngineFlat::EResult EngineResultStatusCode; + IEngineFlat::EStatus EngineResponseStatus; TAutoPtr<NKikimrMiniKQL::TResult> EngineEvaluatedResponse; ui64 PageFaultCount = 0; @@ -121,7 +121,7 @@ class TFlatLocalMiniKQL : public NTabletFlatExecutor::ITransaction { TAlignedPagePoolCounters counters(appData->Counters, "local_tx"); TScopedAlloc alloc(counters, appData->FunctionRegistry->SupportsSizedAllocators()); - TTypeEnvironment typeEnv(alloc); + TTypeEnvironment typeEnv(alloc); auto future = ConvertToMiniKQL(expr, appData->FunctionRegistry, &typeEnv, nullptr); future.Wait(); NYql::TConvertResult compileResult = future.GetValue(); @@ -154,8 +154,8 @@ class TFlatLocalMiniKQL : public NTabletFlatExecutor::ITransaction { TAlignedPagePoolCounters counters(appData->Counters, "local_tx"); TScopedAlloc alloc(counters, appData->FunctionRegistry->SupportsSizedAllocators()); - TTypeEnvironment typeEnv(alloc); - TLocalDbSchemeResolver dbResolver(txc.DB.GetScheme(), TabletId); + TTypeEnvironment typeEnv(alloc); + TLocalDbSchemeResolver dbResolver(txc.DB.GetScheme(), TabletId); const auto unguard = Unguard(alloc); auto future = ConvertToMiniKQL(expr, appData->FunctionRegistry, &typeEnv, &dbResolver); future.Wait(); @@ -165,14 +165,14 @@ class TFlatLocalMiniKQL : public NTabletFlatExecutor::ITransaction { return false; } - ProgramCompileResult->CompiledProgram = SerializeRuntimeNode(compileResult.Node, typeEnv); + ProgramCompileResult->CompiledProgram = SerializeRuntimeNode(compileResult.Node, typeEnv); SerializedMiniKQLProgram = ProgramCompileResult->CompiledProgram; return true; } void ClearResponse() { - EngineResultStatusCode = IEngineFlat::EResult::Unknown; - EngineResponseStatus = IEngineFlat::EStatus::Unknown; + EngineResultStatusCode = IEngineFlat::EResult::Unknown; + EngineResponseStatus = IEngineFlat::EStatus::Unknown; EngineEvaluatedResponse.Destroy(); } @@ -198,7 +198,7 @@ class TFlatLocalMiniKQL : public NTabletFlatExecutor::ITransaction { return true; } - bool MakeResponse(IEngineFlat *engine, const TActorContext &ctx) { + bool MakeResponse(IEngineFlat *engine, const TActorContext &ctx) { TAutoPtr<TEvTablet::TEvLocalMKQLResponse> response = new TEvTablet::TEvLocalMKQLResponse(); auto &record = response->Record; record.SetOrigin(TabletId); @@ -224,8 +224,8 @@ class TFlatLocalMiniKQL : public NTabletFlatExecutor::ITransaction { bool Execute(TTransactionContext &txc, const TActorContext &ctx) override { ClearResponse(); - TabletId = txc.Tablet; - + TabletId = txc.Tablet; + const TAppData *appData = AppData(ctx); const auto functionRegistry = appData->FunctionRegistry; @@ -245,7 +245,7 @@ class TFlatLocalMiniKQL : public NTabletFlatExecutor::ITransaction { try { TAlignedPagePoolCounters poolCounters(appData->Counters, "local_tx"); - TEngineFlatSettings proxySettings( + TEngineFlatSettings proxySettings( IEngineFlat::EProtocol::V1, functionRegistry, *TAppData::RandomProvider, *TAppData::TimeProvider, @@ -254,7 +254,7 @@ class TFlatLocalMiniKQL : public NTabletFlatExecutor::ITransaction { proxySettings.EvaluateResultType = true; proxySettings.EvaluateResultValue = true; - TAutoPtr<IEngineFlat> proxyEngine = CreateEngineFlat(proxySettings); + TAutoPtr<IEngineFlat> proxyEngine = CreateEngineFlat(proxySettings); EngineResultStatusCode = proxyEngine->SetProgram(SerializedMiniKQLProgram, SerializedMiniKQLParams); if (EngineResultStatusCode != IEngineFlat::EResult::Ok) return MakeResponse(proxyEngine.Get(), ctx); @@ -289,13 +289,13 @@ class TFlatLocalMiniKQL : public NTabletFlatExecutor::ITransaction { TEngineHostCounters hostCounters; TLocalMiniKQLHost host(txc.DB, hostCounters, TEngineHostSettings(TabletId, false), Factory); - TEngineFlatSettings engineSettings( + TEngineFlatSettings engineSettings( IEngineFlat::EProtocol::V1, functionRegistry, *TAppData::RandomProvider, *TAppData::TimeProvider, &host, poolCounters ); - TAutoPtr<IEngineFlat> engine = CreateEngineFlat(engineSettings); + TAutoPtr<IEngineFlat> engine = CreateEngineFlat(engineSettings); EngineResultStatusCode = engine->AddProgram(TabletId, shardProgram); if (EngineResultStatusCode != IEngineFlat::EResult::Ok) return MakeResponse(engine.Get(), ctx); @@ -351,7 +351,7 @@ class TFlatLocalMiniKQL : public NTabletFlatExecutor::ITransaction { } void Complete(const TActorContext &ctx) override { - if (EngineResultStatusCode != IEngineFlat::EResult::Unknown) + if (EngineResultStatusCode != IEngineFlat::EResult::Unknown) MakeResponse(nullptr, ctx); } @@ -360,7 +360,7 @@ public: TActorId sender, const TLocalMiniKQLProgram &program, const TMiniKQLFactory* factory) - : Sender(sender) + : Sender(sender) , SourceProgram(program) , Factory(factory) {} diff --git a/ydb/core/engine/minikql/flat_local_tx_scheme.h b/ydb/core/engine/minikql/flat_local_tx_scheme.h index c70476a0cd..9e690c94b3 100644 --- a/ydb/core/engine/minikql/flat_local_tx_scheme.h +++ b/ydb/core/engine/minikql/flat_local_tx_scheme.h @@ -1,5 +1,5 @@ -#pragma once - +#pragma once + #include "flat_local_minikql_host.h" #include <ydb/core/tablet_flat/flat_dbase_apply.h> #include <ydb/core/tablet_flat/flat_database.h> @@ -12,33 +12,33 @@ #include <ydb/core/base/appdata.h> namespace NKikimr { -namespace NMiniKQL { +namespace NMiniKQL { class TFlatLocalSchemeTx : public NTabletFlatExecutor::ITransaction { -public: +public: TFlatLocalSchemeTx(TActorId sender, TEvTablet::TEvLocalSchemeTx::TPtr &ev) - : Sender(sender) - , Ev(ev) - {} + : Sender(sender) + , Ev(ev) + {} bool Execute(TTransactionContext &txc, const TActorContext &ctx) override { Y_UNUSED(ctx); Response.Reset(new TEvTablet::TEvLocalSchemeTxResponse); - auto &delta = Ev->Get()->Record.GetSchemeChanges(); - - auto currentScheme = txc.DB.GetScheme(); - NTable::TSchemeModifier(currentScheme).Apply(delta); + auto &delta = Ev->Get()->Record.GetSchemeChanges(); + + auto currentScheme = txc.DB.GetScheme(); + NTable::TSchemeModifier(currentScheme).Apply(delta); // TODO: Validate scheme change - if (!Ev->Get()->Record.GetDryRun()) - txc.DB.Alter().Merge(delta); + if (!Ev->Get()->Record.GetDryRun()) + txc.DB.Alter().Merge(delta); - auto schemeSnapshot = currentScheme.GetSnapshot(); + auto schemeSnapshot = currentScheme.GetSnapshot(); Response->Record.MutableFullScheme()->Swap(schemeSnapshot.Get()); Response->Record.SetStatus(NKikimrProto::OK); - Response->Record.SetOrigin(txc.Tablet); + Response->Record.SetOrigin(txc.Tablet); return true; } @@ -51,10 +51,10 @@ public: ctx.Send(Sender, Response.Release()); } -private: +private: const TActorId Sender; - TEvTablet::TEvLocalSchemeTx::TPtr Ev; - TAutoPtr<TEvTablet::TEvLocalSchemeTxResponse> Response; + TEvTablet::TEvLocalSchemeTx::TPtr Ev; + TAutoPtr<TEvTablet::TEvLocalSchemeTxResponse> Response; }; }} diff --git a/ydb/core/engine/minikql/minikql_engine_host.cpp b/ydb/core/engine/minikql/minikql_engine_host.cpp index 36c35f32cc..270ab32b4e 100644 --- a/ydb/core/engine/minikql/minikql_engine_host.cpp +++ b/ydb/core/engine/minikql/minikql_engine_host.cpp @@ -10,10 +10,10 @@ #include <library/cpp/containers/stack_vector/stack_vec.h> namespace NKikimr { -namespace NMiniKQL { - -using TScheme = NTable::TScheme; +namespace NMiniKQL { +using TScheme = NTable::TScheme; + void ConvertTableKeys(const TScheme& scheme, const TScheme::TTableInfo* tableInfo, const TArrayRef<const TCell>& row, TSmallVec<TRawTypeValue>& key, ui64* keyDataBytes) { @@ -37,7 +37,7 @@ void ConvertTableKeys(const TScheme& scheme, const TScheme::TTableInfo* tableInf TEngineHost::TEngineHost(NTable::TDatabase& db, TEngineHostCounters& counters, const TEngineHostSettings& settings) : Db(db) - , Scheme(db.GetScheme()) + , Scheme(db.GetScheme()) , Settings(settings) , Counters(counters) {} @@ -120,7 +120,7 @@ bool TEngineHost::IsValidKey(TKeyDesc& key, std::pair<ui64, ui64>& maxSnapshotTi } ui64 TEngineHost::CalculateReadSize(const TVector<const TKeyDesc*>& keys) const { - NTable::TSizeEnv env; + NTable::TSizeEnv env; for (const TKeyDesc* ki : keys) { DoCalculateReadSize(*ki, env); @@ -129,7 +129,7 @@ ui64 TEngineHost::CalculateReadSize(const TVector<const TKeyDesc*>& keys) const return env.GetSize(); } -void TEngineHost::DoCalculateReadSize(const TKeyDesc& key, NTable::TSizeEnv& env) const { +void TEngineHost::DoCalculateReadSize(const TKeyDesc& key, NTable::TSizeEnv& env) const { if (TSysTables::IsSystemTable(key.TableId)) return; if (key.RowOperation != TKeyDesc::ERowOperation::Read) @@ -167,7 +167,7 @@ ui64 TEngineHost::CalculateResultSize(const TKeyDesc& key) const { if (key.Range.Point) { return Db.EstimateRowSize(localTid); } else { - NTable::TSizeEnv env; + NTable::TSizeEnv env; DoCalculateReadSize(key, env); ui64 size = env.GetSize(); @@ -244,7 +244,7 @@ void TEngineHost::PinPages(const TVector<THolder<TKeyDesc>>& keys, ui64 pageFaul } bool ready = Db.Precharge(localTid, - keyFrom, + keyFrom, key.Range.Point ? keyFrom : keyTo, tags, Settings.DisableByKeyFilter ? (ui64)NTable::NoByKey : 0, @@ -278,7 +278,7 @@ NUdf::TUnboxedValue TEngineHost::SelectRow(const TTableId& tableId, const TArray TSmallVec<TRawTypeValue> key; ConvertKeys(tableInfo, row, key); - TSmallVec<NTable::TTag> tags; + TSmallVec<NTable::TTag> tags; TSmallVec<NTable::TTag> systemColumnTags; AnalyzeRowType(columnIds, tags, systemColumnTags); @@ -287,9 +287,9 @@ NUdf::TUnboxedValue TEngineHost::SelectRow(const TTableId& tableId, const TArray for (size_t i = 0; i < tags.size(); ++i) cellTypes.emplace_back(tableInfo->Columns.at(tags[i]).PType); - NTable::TRowState dbRow; - - if (key.size() != Db.GetScheme().GetTableInfo(localTid)->KeyColumns.size()) + NTable::TRowState dbRow; + + if (key.size() != Db.GetScheme().GetTableInfo(localTid)->KeyColumns.size()) throw TSchemeErrorTabletException(); Counters.NSelectRow++; @@ -305,7 +305,7 @@ NUdf::TUnboxedValue TEngineHost::SelectRow(const TTableId& tableId, const TArray if (auto collector = GetChangeCollector(tableId)) { collector->Reset(); } - throw TNotReadyTabletException(); + throw TNotReadyTabletException(); } if (NTable::EReady::Gone == ready) { @@ -491,16 +491,16 @@ public: bool Next(NUdf::TUnboxedValue& value) override { bool truncated = false; - Clear(); + Clear(); while (Iter->Next(NTable::ENext::Data) == NTable::EReady::Data) { - TDbTupleRef tuple = Iter->GetKey(); + TDbTupleRef tuple = Iter->GetKey(); ++Iterations; if (Iterations % PeriodicCallbackIterations == 0) { List.EngineHost.ExecPeriodicCallback(); } - + List.EngineHost.GetCounters().SelectRangeDeletedRowSkips += std::exchange(Iter->Stats.DeletedRowSkips, 0); @@ -543,7 +543,7 @@ public: } } - TDbTupleRef rowValues = Iter->GetValues(); + TDbTupleRef rowValues = Iter->GetValues(); ui64 rowSize = 0; for (ui32 i = 0; i < rowValues.ColumnCount; ++i) { rowSize += rowValues.Columns[i].IsNull() ? 1 : rowValues.Columns[i].Size(); @@ -575,9 +575,9 @@ public: if (auto collector = List.EngineHost.GetChangeCollector(List.TableId)) { collector->Reset(); } - throw TNotReadyTabletException(); + throw TNotReadyTabletException(); } - + if (List.Truncated || List.SizeBytes) { Y_VERIFY_DEBUG(List.Truncated && *List.Truncated == truncated); Y_VERIFY_DEBUG(List.SizeBytes && *List.SizeBytes == Bytes); @@ -705,12 +705,12 @@ public: } private: - NTable::TDatabase& Db; + NTable::TDatabase& Db; const TScheme& Scheme; const THolderFactory& HolderFactory; TTableId TableId; ui64 LocalTid; - TSmallVec<NTable::TTag> Tags; + TSmallVec<NTable::TTag> Tags; TSmallVec<NTable::TTag> SystemColumnTags; ui64 ShardId; TSmallVec<bool> SkipNullKeys; @@ -816,7 +816,7 @@ NUdf::TUnboxedValue TEngineHost::SelectRange(const TTableId& tableId, const TTab Y_VERIFY_DEBUG(outerStructType->GetMemberName(1) == "Truncated", "Unexpected type structure of returnType in TEngineHost::SelectRange()"); - TSmallVec<NTable::TTag> tags; + TSmallVec<NTable::TTag> tags; TSmallVec<NTable::TTag> systemColumnTags; AnalyzeRowType(columnIds, tags, systemColumnTags); @@ -859,7 +859,7 @@ void TEngineHost::UpdateRow(const TTableId& tableId, const TArrayRef<const TCell ConvertTableKeys(Scheme, tableInfo, row, key, &keyBytes); ui64 valueBytes = 0; - TSmallVec<NTable::TUpdateOp> ops; + TSmallVec<NTable::TUpdateOp> ops; for (size_t i = 0; i < commands.size(); i++) { const TUpdateCommand& upd = commands[i]; Y_VERIFY(upd.Operation == TKeyDesc::EColumnOperation::Set); // TODO[serxa]: support inplace update in update row diff --git a/ydb/core/engine/minikql/minikql_engine_host.h b/ydb/core/engine/minikql/minikql_engine_host.h index 012ee6891b..33fad2abae 100644 --- a/ydb/core/engine/minikql/minikql_engine_host.h +++ b/ydb/core/engine/minikql/minikql_engine_host.h @@ -10,7 +10,7 @@ #include <ydb/core/engine/mkql_engine_flat_host.h> namespace NKikimr { -namespace NMiniKQL { +namespace NMiniKQL { struct TEngineHostCounters { ui64 NSelectRow = 0; @@ -89,10 +89,10 @@ struct TEngineHostSettings { {} }; -class TEngineHost : public IEngineFlatHost { +class TEngineHost : public IEngineFlatHost { public: - using TScheme = NTable::TScheme; - + using TScheme = NTable::TScheme; + explicit TEngineHost(NTable::TDatabase& db, TEngineHostCounters& counters, const TEngineHostSettings& settings = TEngineHostSettings()); ui64 GetShardId() const override; @@ -104,8 +104,8 @@ public: void PinPages(const TVector<THolder<TKeyDesc>>& keys, ui64 pageFaultCount) override; NUdf::TUnboxedValue SelectRow(const TTableId& tableId, const TArrayRef<const TCell>& row, - TStructLiteral* columnIds, TOptionalType* returnType, const TReadTarget& readTarget, - const THolderFactory& holderFactory) override; + TStructLiteral* columnIds, TOptionalType* returnType, const TReadTarget& readTarget, + const THolderFactory& holderFactory) override; NUdf::TUnboxedValue SelectRange(const TTableId& tableId, const TTableRange& range, TStructLiteral* columnIds, TListLiteral* skipNullKeys, TStructType* returnType, @@ -133,10 +133,10 @@ protected: virtual ui64 LocalTableId(const TTableId& tableId) const; void ConvertKeys(const TScheme::TTableInfo* tableInfo, const TArrayRef<const TCell>& row, TSmallVec<TRawTypeValue>& key) const; - void DoCalculateReadSize(const TKeyDesc& key, NTable::TSizeEnv& env) const; + void DoCalculateReadSize(const TKeyDesc& key, NTable::TSizeEnv& env) const; protected: - NTable::TDatabase& Db; + NTable::TDatabase& Db; const TScheme& Scheme; const TEngineHostSettings Settings; TEngineHostCounters& Counters; diff --git a/ydb/core/engine/minikql/ya.make b/ydb/core/engine/minikql/ya.make index 372282813a..fb6186fb74 100644 --- a/ydb/core/engine/minikql/ya.make +++ b/ydb/core/engine/minikql/ya.make @@ -7,7 +7,7 @@ OWNER( SRCS( flat_local_minikql_host.h - flat_local_tx_factory.cpp + flat_local_tx_factory.cpp minikql_engine_host.cpp minikql_engine_host.h ) diff --git a/ydb/core/engine/mkql_engine_flat_host_ut.cpp b/ydb/core/engine/mkql_engine_flat_host_ut.cpp index 68679f168d..1303d6efb1 100644 --- a/ydb/core/engine/mkql_engine_flat_host_ut.cpp +++ b/ydb/core/engine/mkql_engine_flat_host_ut.cpp @@ -40,21 +40,21 @@ Y_UNIT_TEST_SUITE(TMiniKQLEngineFlatHostTest) { Y_UNIT_TEST(ShardId) { - NTable::TDatabase DB; + NTable::TDatabase DB; TEngineHostCounters hostCounters; TUnversionedEngineHost host(DB, hostCounters, TEngineHostSettings(100)); UNIT_ASSERT_VALUES_EQUAL(host.GetShardId(), 100); } Y_UNIT_TEST(Basic) { - NTable::TDatabase DB; + NTable::TDatabase DB; NIceDb::TNiceDb db(DB); { // Create tables NTable::TDummyEnv env; DB.Begin(1, env); db.Materialize<Schema>(); - DB.Commit(1, true); + DB.Commit(1, true); } { // Fill tables with some stuff @@ -65,7 +65,7 @@ Y_UNIT_TEST_SUITE(TMiniKQLEngineFlatHostTest) { NIceDb::TUpdate<Schema::TestTable::Name>(ToString(i)), NIceDb::TUpdate<Schema::TestTable::BoolValue>(i % 2 == 0)); } - DB.Commit(2, true); + DB.Commit(2, true); } { // Execute some minikql @@ -77,7 +77,7 @@ Y_UNIT_TEST_SUITE(TMiniKQLEngineFlatHostTest) { // TODO: ... MINIKQL ... Y_UNUSED(host); - DB.Commit(3, true); + DB.Commit(3, true); } { // Check data @@ -94,7 +94,7 @@ Y_UNIT_TEST_SUITE(TMiniKQLEngineFlatHostTest) { UNIT_ASSERT(ToString(value) == name); UNIT_ASSERT(boolValue == (i % 2 == 0)); } - DB.Commit(4, true); + DB.Commit(4, true); } } } diff --git a/ydb/core/engine/mkql_engine_flat_ut.cpp b/ydb/core/engine/mkql_engine_flat_ut.cpp index e2b12e2d7a..afce6b0a3f 100644 --- a/ydb/core/engine/mkql_engine_flat_ut.cpp +++ b/ydb/core/engine/mkql_engine_flat_ut.cpp @@ -56,8 +56,8 @@ namespace { template <typename TSchema> void AddShard(ui64 tabletId) { auto& db = Dbs[tabletId]; - - db.Reset(new NTable::TDatabase); + + db.Reset(new NTable::TDatabase); Steps[tabletId] = 0; { // Create tables @@ -73,7 +73,7 @@ namespace { } void CommitTransaction(ui64 tabletId) { - Dbs[tabletId]->Commit(Steps[tabletId], true); + Dbs[tabletId]->Commit(Steps[tabletId], true); Envs.erase(tabletId); } }; diff --git a/ydb/core/kesus/proxy/ut_helpers.cpp b/ydb/core/kesus/proxy/ut_helpers.cpp index 74580d10f7..b5d8d278b0 100644 --- a/ydb/core/kesus/proxy/ut_helpers.cpp +++ b/ydb/core/kesus/proxy/ut_helpers.cpp @@ -11,7 +11,7 @@ TTestContext::TTestContext() void TTestContext::Setup(ui32 nodeCount) { Y_VERIFY(nodeCount >= 2); ProxyActors.clear(); - Runtime.Reset(new TTestBasicRuntime(nodeCount)); + Runtime.Reset(new TTestBasicRuntime(nodeCount)); SetupLogging(); SetupTabletServices(); diff --git a/ydb/core/keyvalue/keyvalue_collector_ut.cpp b/ydb/core/keyvalue/keyvalue_collector_ut.cpp index 4456a82380..268da2bb6c 100644 --- a/ydb/core/keyvalue/keyvalue_collector_ut.cpp +++ b/ydb/core/keyvalue/keyvalue_collector_ut.cpp @@ -31,9 +31,9 @@ public: } void Setup() { - Runtime.Reset(new TTestBasicRuntime(1, false)); + Runtime.Reset(new TTestBasicRuntime(1, false)); //Runtime->SetLogPriority(NKikimrServices::BS_QUEUE, NLog::PRI_CRIT); - Runtime->Initialize(TAppPrepare().Unwrap()); + Runtime->Initialize(TAppPrepare().Unwrap()); TabletInfo.Reset(MakeTabletInfo()); Sender = Runtime->AllocateEdgeActor(NodeIndex); diff --git a/ydb/core/keyvalue/keyvalue_flat_impl.h b/ydb/core/keyvalue/keyvalue_flat_impl.h index 292f2feff9..daff57f1dc 100644 --- a/ydb/core/keyvalue/keyvalue_flat_impl.h +++ b/ydb/core/keyvalue/keyvalue_flat_impl.h @@ -53,17 +53,17 @@ protected: bool Execute(NTabletFlatExecutor::TTransactionContext &txc, const TActorContext &ctx) override { LOG_DEBUG_S(ctx, NKikimrServices::KEYVALUE, "KeyValue# " << txc.Tablet << " TTxInit flat Execute"); TSimpleDbFlat db(txc.DB); - if (txc.DB.GetScheme().GetTableInfo(TABLE_ID) == nullptr) { + if (txc.DB.GetScheme().GetTableInfo(TABLE_ID) == nullptr) { LOG_DEBUG_S(ctx, NKikimrServices::KEYVALUE, "KeyValue# " << txc.Tablet << " TTxInit flat BuildScheme"); // Init the scheme - auto &alter = txc.DB.Alter(); - alter.AddTable("kvtable", TABLE_ID); + auto &alter = txc.DB.Alter(); + alter.AddTable("kvtable", TABLE_ID); alter.AddColumn(TABLE_ID, "key", KEY_TAG, NScheme::TSmallBoundedString::TypeId, false); - alter.AddColumnToKey(TABLE_ID, KEY_TAG); + alter.AddColumnToKey(TABLE_ID, KEY_TAG); alter.AddColumn(TABLE_ID, "value", VALUE_TAG, NScheme::TString::TypeId, false); // Init log batching settings - alter.SetExecutorAllowLogBatching(true); - alter.SetExecutorLogFlushPeriod(TDuration::MicroSeconds(500)); + alter.SetExecutorAllowLogBatching(true); + alter.SetExecutorLogFlushPeriod(TDuration::MicroSeconds(500)); Self.State.Clear(); } else { LOG_DEBUG_S(ctx, NKikimrServices::KEYVALUE, "KeyValue# " << txc.Tablet << " TTxInit flat ReadDb Tree"); @@ -83,29 +83,29 @@ protected: return true; } - static bool LoadStateFromDB(TKeyValueState& state, NTable::TDatabase& db) { + static bool LoadStateFromDB(TKeyValueState& state, NTable::TDatabase& db) { state.Clear(); // Just walk through the DB and read all the keys and values - const std::array<ui32, 2> tags {{ KEY_TAG, VALUE_TAG }}; - auto mode = NTable::ELookup::GreaterOrEqualThan; - auto iter = db.Iterate(TABLE_ID, {}, tags, mode); - - if (!db.Precharge(TABLE_ID, {}, {}, tags, 0, -1, -1)) + const std::array<ui32, 2> tags {{ KEY_TAG, VALUE_TAG }}; + auto mode = NTable::ELookup::GreaterOrEqualThan; + auto iter = db.Iterate(TABLE_ID, {}, tags, mode); + + if (!db.Precharge(TABLE_ID, {}, {}, tags, 0, -1, -1)) return false; while (iter->Next(NTable::ENext::Data) == NTable::EReady::Data) { - const auto &row = iter->Row(); + const auto &row = iter->Row(); - TString key(row.Get(0).AsBuf()); - TString value(row.Get(1).AsBuf()); + TString key(row.Get(0).AsBuf()); + TString value(row.Get(1).AsBuf()); - state.Load(key, value); - if (state.GetIsDamaged()) { - return true; + state.Load(key, value); + if (state.GetIsDamaged()) { + return true; } } - - return iter->Last() != NTable::EReady::Page; + + return iter->Last() != NTable::EReady::Page; } void Complete(const TActorContext &ctx) override { @@ -422,7 +422,7 @@ public: TKeyValueFlat(const TActorId &tablet, TTabletStorageInfo *info) : TActor(&TThis::StateInit) - , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) + , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) { TAutoPtr<TTabletCountersBase> counters( new TProtobufTabletCounters< diff --git a/ydb/core/keyvalue/keyvalue_simple_db_flat.cpp b/ydb/core/keyvalue/keyvalue_simple_db_flat.cpp index 0e2cc43559..74f6e5e05d 100644 --- a/ydb/core/keyvalue/keyvalue_simple_db_flat.cpp +++ b/ydb/core/keyvalue/keyvalue_simple_db_flat.cpp @@ -8,7 +8,7 @@ namespace NKikimr { namespace NKeyValue { -TSimpleDbFlat::TSimpleDbFlat(NTable::TDatabase &db) +TSimpleDbFlat::TSimpleDbFlat(NTable::TDatabase &db) : Db(db) {} diff --git a/ydb/core/keyvalue/keyvalue_simple_db_flat.h b/ydb/core/keyvalue/keyvalue_simple_db_flat.h index 82661a9f15..98b76abec8 100644 --- a/ydb/core/keyvalue/keyvalue_simple_db_flat.h +++ b/ydb/core/keyvalue/keyvalue_simple_db_flat.h @@ -5,7 +5,7 @@ namespace NKikimr { -namespace NTable { +namespace NTable { class TDatabase; } @@ -13,9 +13,9 @@ namespace NKeyValue { class TSimpleDbFlat : public ISimpleDb { protected: - NTable::TDatabase &Db; + NTable::TDatabase &Db; public: - TSimpleDbFlat(NTable::TDatabase &db); + TSimpleDbFlat(NTable::TDatabase &db); void Erase(const TString &key, const TActorContext &ctx) override; void Update(const TString &key, const TString &value, const TActorContext &ctx) override; }; diff --git a/ydb/core/keyvalue/keyvalue_storage_request.cpp b/ydb/core/keyvalue/keyvalue_storage_request.cpp index e9032d2ed3..bf83e2b3ec 100644 --- a/ydb/core/keyvalue/keyvalue_storage_request.cpp +++ b/ydb/core/keyvalue/keyvalue_storage_request.cpp @@ -565,7 +565,7 @@ public: prevGroup = Max<ui32>(); for (const auto& rq : request.ReadQueue) { const auto& readItem = *rq.ReadItem; - readQueries[queryIdx].Set(readItem.LogoBlobId, readItem.BlobOffset, readItem.BlobSize); + readQueries[queryIdx].Set(readItem.LogoBlobId, readItem.BlobOffset, readItem.BlobSize); ++queryIdx; const ui32 group = TabletInfo->GroupFor(readItem.LogoBlobId.Channel(), readItem.LogoBlobId.Generation()); diff --git a/ydb/core/keyvalue/keyvalue_ut.cpp b/ydb/core/keyvalue/keyvalue_ut.cpp index 4ae1fcf56a..b56d222d83 100644 --- a/ydb/core/keyvalue/keyvalue_ut.cpp +++ b/ydb/core/keyvalue/keyvalue_ut.cpp @@ -76,7 +76,7 @@ struct TTestContext { void Prepare(const TString &dispatchName, std::function<void(TTestActorRuntime&)> setup, bool &outActiveZone) { Y_UNUSED(dispatchName); outActiveZone = false; - Runtime.Reset(new TTestBasicRuntime); + Runtime.Reset(new TTestBasicRuntime); Runtime->SetScheduledLimit(100); Runtime->SetLogPriority(NKikimrServices::KEYVALUE, NLog::PRI_DEBUG); SetupLogging(*Runtime); diff --git a/ydb/core/mind/bscontroller/impl.h b/ydb/core/mind/bscontroller/impl.h index ba311a254c..b4a9212887 100644 --- a/ydb/core/mind/bscontroller/impl.h +++ b/ydb/core/mind/bscontroller/impl.h @@ -1661,7 +1661,7 @@ public: TBlobStorageController(const TActorId &tablet, TTabletStorageInfo *info) : TActor(&TThis::StateInit) - , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) + , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) , ResponsivenessPinger(nullptr) , ScrubState(this) { diff --git a/ydb/core/mind/hive/hive_ut.cpp b/ydb/core/mind/hive/hive_ut.cpp index 0383d49a12..ce91de032a 100644 --- a/ydb/core/mind/hive/hive_ut.cpp +++ b/ydb/core/mind/hive/hive_ut.cpp @@ -86,7 +86,7 @@ namespace { THashMap<ui32, TIntrusivePtr<TNodeWardenConfig>> NodeWardenConfigs; void SetupDomainInfo(TTestActorRuntime &runtime, TAppPrepare &app) { - app.ClearDomainsAndHive(); + app.ClearDomainsAndHive(); ui32 domainUid = TTestTxConfig::DomainUid; ui32 ssId = 0; @@ -113,7 +113,7 @@ namespace { static TString STORAGE_POOL = "def"; - void SetupChannels(TAppPrepare &app) { + void SetupChannels(TAppPrepare &app) { TIntrusivePtr<TChannelProfiles> channelProfiles = new TChannelProfiles; channelProfiles->Profiles.emplace_back(); TChannelProfiles::TProfile &profile = channelProfiles->Profiles.back(); @@ -121,7 +121,7 @@ namespace { profile.Channels.push_back( TChannelProfiles::TProfile::TChannel(TBlobStorageGroupType::ErasureNone, 0, NKikimrBlobStorage::TVDiskKind::Default)); } - app.SetChannels(std::move(channelProfiles)); + app.SetChannels(std::move(channelProfiles)); } static TChannelBind GetChannelBind(const TString& storagePool) { @@ -245,10 +245,10 @@ namespace { } void SetupServices(TTestActorRuntime &runtime, bool isLocalEnabled) { - TAppPrepare app; - + TAppPrepare app; + SetupDomainInfo(runtime, app); - SetupChannels(app); + SetupChannels(app); app.SetMinRequestSequenceSize(10); // for smaller sequences and high interaction between root and domain hives app.SetRequestSequenceSize(10); @@ -265,7 +265,7 @@ namespace { SetupNodeWhiteboard(runtime, nodeIndex); } - runtime.Initialize(app.Unwrap()); + runtime.Initialize(app.Unwrap()); for (ui32 nodeIndex = 0; nodeIndex < runtime.GetNodeCount(); ++nodeIndex) { auto it = NodeWardenConfigs.find(nodeIndex); @@ -795,7 +795,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestCreateTablet) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); Setup(runtime, true); const ui64 hiveTablet = MakeDefaultHiveID(0); const ui64 testerTablet = MakeDefaultHiveID(1); @@ -1656,7 +1656,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { if (ENABLE_DETAILED_HIVE_LOG) { Ctest << "At dispatch " << dispatchName << Endl; } - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); Setup(runtime, true); setup(runtime); @@ -1682,7 +1682,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestCreateAndDeleteTabletWithStoragePools) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); Setup(runtime); const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -1883,7 +1883,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestDeleteTablet) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); Setup(runtime, true); TActorId sender = runtime.AllocateEdgeActor(); const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -2000,7 +2000,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(PipeAlivenessOfDeadTablet) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); Setup(runtime, true); TActorId sender = runtime.AllocateEdgeActor(); const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -2025,7 +2025,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestCreateTabletBeforeLocal) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); Setup(runtime, false); TActorId sender = runtime.AllocateEdgeActor(); const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -2067,7 +2067,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestReCreateTablet) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; Setup(runtime, true); TActorId sender = runtime.AllocateEdgeActor(); const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -2106,7 +2106,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestReCreateTabletError) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; Setup(runtime, true); TActorId sender = runtime.AllocateEdgeActor(); const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -2147,7 +2147,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { if (ENABLE_DETAILED_HIVE_LOG) { Ctest << "At dispatch " << dispatchName << Endl; } - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; Setup(runtime, true); setup(runtime); TActorId sender = runtime.AllocateEdgeActor(); @@ -2186,7 +2186,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestLocalDisconnect) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); Setup(runtime, true); TVector<ui64> tabletIds; const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -2205,7 +2205,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestNodeDisconnect) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); Setup(runtime, true); TVector<ui64> tabletIds; TActorId sender = runtime.AllocateEdgeActor(); @@ -2240,7 +2240,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestLocalReplacement) { - TTestBasicRuntime runtime(2, false); + TTestBasicRuntime runtime(2, false); Setup(runtime, true); TVector<ui64> tabletIds; const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -2318,7 +2318,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestLimitedNodeList) { - TTestBasicRuntime runtime(3, false); + TTestBasicRuntime runtime(3, false); Setup(runtime, true); TVector<ui64> tabletIds; const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -2341,7 +2341,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestCreateTabletAndReassignGroups) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); Setup(runtime, true); const ui64 hiveTablet = MakeDefaultHiveID(0); const ui64 testerTablet = MakeDefaultHiveID(1); @@ -2386,7 +2386,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestCreateTabletAndReassignGroups3) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); Setup(runtime, true, 3); const ui64 hiveTablet = MakeDefaultHiveID(0); const ui64 testerTablet = MakeDefaultHiveID(1); @@ -2442,7 +2442,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestReassignGroupsWithRecreateTablet) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); Setup(runtime, true, 3); TActorId sender = runtime.AllocateEdgeActor(); const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -2511,7 +2511,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { if (ENABLE_DETAILED_HIVE_LOG) { Ctest << "At dispatch " << dispatchName << Endl; } - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; Setup(runtime, true); setup(runtime); TActorId sender = runtime.AllocateEdgeActor(); @@ -2558,7 +2558,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } // Y_UNIT_TEST(TestCreateTabletAndChangeProfiles) { -// TTestBasicRuntime runtime(1, false); +// TTestBasicRuntime runtime(1, false); // Setup(runtime, true); // TActorId sender = runtime.AllocateEdgeActor(); // CreatePDiskAndGroup(runtime, sender); @@ -2590,7 +2590,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { // Commented to remove noise from the unit-test logs /* Y_UNIT_TEST(topTablet) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); Setup(runtime, true); TActorId sender = runtime.AllocateEdgeActor(); const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -2610,7 +2610,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { // Commented to remove noise from the unit-test logs /* Y_UNIT_TEST(TestStopAndRestartTablet) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); Setup(runtime, true); TActorId sender = runtime.AllocateEdgeActor(); TVector<ui64> tabletIds; @@ -2634,7 +2634,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { /* Y_UNIT_TEST(TestFailureNotification) { - TTestBasicRuntime runtime(3, false); + TTestBasicRuntime runtime(3, false); Setup(runtime, true); TVector<ui64> tabletIds; TActorId senderA = runtime.AllocateEdgeActor(); @@ -2662,7 +2662,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { */ Y_UNIT_TEST(TestFollowers) { - TTestBasicRuntime runtime(3, false); + TTestBasicRuntime runtime(3, false); Setup(runtime, true); TVector<ui64> tabletIds; const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -2687,7 +2687,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestFollowersReconfiguration) { - TTestBasicRuntime runtime(3, false); + TTestBasicRuntime runtime(3, false); Setup(runtime, true); TVector<ui64> tabletIds; TActorId senderA = runtime.AllocateEdgeActor(); @@ -2735,7 +2735,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { Y_UNIT_TEST(TestFollowerPromotion) { constexpr int NODES = 3; - TTestBasicRuntime runtime(NODES, false); + TTestBasicRuntime runtime(NODES, false); Setup(runtime, true); TVector<ui64> tabletIds; @@ -2805,7 +2805,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestManyFollowersOnOneNode) { - TTestBasicRuntime runtime(2, false); + TTestBasicRuntime runtime(2, false); Setup(runtime, true); const int nodeBase = runtime.GetNodeId(0); TVector<ui64> tabletIds; @@ -2848,7 +2848,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestStartTabletTwiceInARow) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); Setup(runtime, true); const ui64 hiveTablet = MakeDefaultHiveID(0); const ui64 testerTablet = MakeDefaultHiveID(1); @@ -2876,7 +2876,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { Y_UNIT_TEST(TestHiveBalancer) { static const int NUM_NODES = 3; static const int NUM_TABLETS = NUM_NODES * 3; - TTestBasicRuntime runtime(NUM_NODES, false); + TTestBasicRuntime runtime(NUM_NODES, false); Setup(runtime, true); const int nodeBase = runtime.GetNodeId(0); TActorId senderA = runtime.AllocateEdgeActor(); @@ -3374,7 +3374,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestRestartTablets) { - TTestBasicRuntime runtime(3, false); + TTestBasicRuntime runtime(3, false); Setup(runtime, true); TVector<ui64> tabletIds; const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -3437,7 +3437,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestFollowersCrossDC_Easy) { - TTestBasicRuntime runtime((ui32)9, (ui32)3); + TTestBasicRuntime runtime((ui32)9, (ui32)3); Setup(runtime, true); TVector<ui64> tabletIds; const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -3489,7 +3489,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestFollowers_LocalNodeOnly) { - TTestBasicRuntime runtime((ui32)9, (ui32)3); + TTestBasicRuntime runtime((ui32)9, (ui32)3); Setup(runtime, true); TVector<ui64> tabletIds; const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -3845,7 +3845,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestCreateExternalTablet) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); Setup(runtime, true); const ui64 hiveTablet = MakeDefaultHiveID(0); const ui64 testerTablet = MakeDefaultHiveID(1); @@ -3859,7 +3859,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestCreateTabletChangeToExternal) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); Setup(runtime, true); const ui64 hiveTablet = MakeDefaultHiveID(0); const ui64 testerTablet = MakeDefaultHiveID(1); @@ -3882,7 +3882,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestGetStorageInfo) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); Setup(runtime, true); const ui64 hiveTablet = MakeDefaultHiveID(0); const ui64 testerTablet = MakeDefaultHiveID(1); @@ -3902,7 +3902,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestGetStorageInfoDeleteTabletBeforeAssigned) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); Setup(runtime, true); const ui64 hiveTablet = MakeDefaultHiveID(0); const ui64 testerTablet = MakeDefaultHiveID(1); @@ -3979,7 +3979,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestLockTabletExecution) { - TTestBasicRuntime runtime(2, false); + TTestBasicRuntime runtime(2, false); Setup(runtime, false); CreateLocal(runtime, 0); // only the 1st node has local running const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -4003,7 +4003,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestLockTabletExecutionBadOwner) { - TTestBasicRuntime runtime(2, false); + TTestBasicRuntime runtime(2, false); Setup(runtime, false); CreateLocal(runtime, 0); // only the 1st node has local running const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -4022,7 +4022,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestLockTabletExecutionTimeout) { - TTestBasicRuntime runtime(2, false); + TTestBasicRuntime runtime(2, false); Setup(runtime, false); CreateLocal(runtime, 0); // only the 1st node has local running const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -4051,7 +4051,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestLockTabletExecutionRebootTimeout) { - TTestBasicRuntime runtime(2, false); + TTestBasicRuntime runtime(2, false); Setup(runtime, false); CreateLocal(runtime, 0); // only the 1st node has local running const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -4080,7 +4080,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestLockTabletExecutionDelete) { - TTestBasicRuntime runtime(2, false); + TTestBasicRuntime runtime(2, false); Setup(runtime, false); CreateLocal(runtime, 0); // only the 1st node has local running TActorId sender = runtime.AllocateEdgeActor(); @@ -4184,7 +4184,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestLockTabletExecutionReconnect) { - TTestBasicRuntime runtime(2, false); + TTestBasicRuntime runtime(2, false); Setup(runtime, false); CreateLocal(runtime, 0); // only the 1st node has local running const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -4213,7 +4213,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestLockTabletExecutionRebootReconnect) { - TTestBasicRuntime runtime(2, false); + TTestBasicRuntime runtime(2, false); Setup(runtime, false); CreateLocal(runtime, 0); // only the 1st node has local running const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -4239,7 +4239,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestLockTabletExecutionReconnectExpire) { - TTestBasicRuntime runtime(2, false); + TTestBasicRuntime runtime(2, false); Setup(runtime, false); CreateLocal(runtime, 0); // only the 1st node has local running const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -4288,7 +4288,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestLockTabletExecutionBadUnlock) { - TTestBasicRuntime runtime(2, false); + TTestBasicRuntime runtime(2, false); Setup(runtime, false); CreateLocal(runtime, 0); // only the 1st node has local running const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -4309,7 +4309,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestLockTabletExecutionGoodUnlock) { - TTestBasicRuntime runtime(2, false); + TTestBasicRuntime runtime(2, false); Setup(runtime, false); CreateLocal(runtime, 0); // only the 1st node has local running const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -4334,7 +4334,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestLockTabletExecutionStealLock) { - TTestBasicRuntime runtime(2, false); + TTestBasicRuntime runtime(2, false); Setup(runtime, false); CreateLocal(runtime, 0); // only the 1st node has local running const ui64 hiveTablet = MakeDefaultHiveID(0); @@ -4359,7 +4359,7 @@ Y_UNIT_TEST_SUITE(THiveTest) { } Y_UNIT_TEST(TestExternalBoot) { - TTestBasicRuntime runtime(1, false); + TTestBasicRuntime runtime(1, false); Setup(runtime, true); CreateLocal(runtime, 0); // only the 1st node has local running const ui64 hiveTablet = MakeDefaultHiveID(0); diff --git a/ydb/core/mind/node_broker_impl.h b/ydb/core/mind/node_broker_impl.h index e3b68b0587..52fa173704 100644 --- a/ydb/core/mind/node_broker_impl.h +++ b/ydb/core/mind/node_broker_impl.h @@ -319,7 +319,7 @@ private: public: TNodeBroker(const TActorId &tablet, TTabletStorageInfo *info) : TActor(&TThis::StateInit) - , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) + , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) , EpochDuration(TDuration::Hours(1)) , ConfigSubscriptionId(0) , TxProcessor(new TTxProcessor(*this, "root", NKikimrServices::NODE_BROKER)) diff --git a/ydb/core/mind/node_broker_ut.cpp b/ydb/core/mind/node_broker_ut.cpp index 0d9498ddcd..563bc6fe14 100644 --- a/ydb/core/mind/node_broker_ut.cpp +++ b/ydb/core/mind/node_broker_ut.cpp @@ -54,11 +54,11 @@ void SetupServices(TTestActorRuntime &runtime, const ui32 disksInDomain = 1; // setup domain info - TAppPrepare app; - - app.ClearDomainsAndHive(); - app.AddDomain(TDomainsInfo::TDomain::ConstructEmptyDomain("dc-1").Release()); + TAppPrepare app; + app.ClearDomainsAndHive(); + app.AddDomain(TDomainsInfo::TDomain::ConstructEmptyDomain("dc-1").Release()); + { // setup channel profiles TIntrusivePtr<TChannelProfiles> channelProfiles = new TChannelProfiles; channelProfiles->Profiles.emplace_back(); @@ -67,7 +67,7 @@ void SetupServices(TTestActorRuntime &runtime, profile.Channels.push_back( TChannelProfiles::TProfile::TChannel(TBlobStorageGroupType::ErasureNone, 0, NKikimrBlobStorage::TVDiskKind::Default)); } - app.SetChannels(std::move(channelProfiles)); + app.SetChannels(std::move(channelProfiles)); } for (ui32 nodeIndex = 0; nodeIndex < runtime.GetNodeCount(); ++nodeIndex) { @@ -141,7 +141,7 @@ void SetupServices(TTestActorRuntime &runtime, SetupTabletResolver(runtime, nodeIndex); } - runtime.Initialize(app.Unwrap()); + runtime.Initialize(app.Unwrap()); runtime.GetAppData().DynamicNameserviceConfig = new TDynamicNameserviceConfig; auto dnConfig = runtime.GetAppData().DynamicNameserviceConfig; @@ -645,7 +645,7 @@ void RestartNodeBroker(TTestActorRuntime &runtime) Y_UNIT_TEST_SUITE(TNodeBrokerTest) { Y_UNIT_TEST(BasicFunctionality) { - TTestBasicRuntime runtime(8, false); + TTestBasicRuntime runtime(8, false); Setup(runtime, 4); TActorId sender = runtime.AllocateEdgeActor(); @@ -1079,7 +1079,7 @@ Y_UNIT_TEST_SUITE(TNodeBrokerTest) { Y_UNIT_TEST_SUITE(TDynamicNameserverTest) { Y_UNIT_TEST(BasicFunctionality) { - TTestBasicRuntime runtime(8, false); + TTestBasicRuntime runtime(8, false); Setup(runtime); TActorId sender = runtime.AllocateEdgeActor(); diff --git a/ydb/core/mind/table_adapter.h b/ydb/core/mind/table_adapter.h index f0ec8db1e2..df1f3d6876 100644 --- a/ydb/core/mind/table_adapter.h +++ b/ydb/core/mind/table_adapter.h @@ -2,7 +2,7 @@ #include <ydb/core/tablet_flat/tablet_flat_executor.h> #include <ydb/core/tablet_flat/flat_cxx_database.h> - + namespace NKikimr { // inline table specifier diff --git a/ydb/core/mind/ut_fat/blobstorage_node_warden_ut_fat.cpp b/ydb/core/mind/ut_fat/blobstorage_node_warden_ut_fat.cpp index 011f03d93c..535429e429 100644 --- a/ydb/core/mind/ut_fat/blobstorage_node_warden_ut_fat.cpp +++ b/ydb/core/mind/ut_fat/blobstorage_node_warden_ut_fat.cpp @@ -110,7 +110,7 @@ void SetupServices(TTestActorRuntime &runtime) { const ui32 domainId = DOMAIN_ID; const ui32 stateStorageGroup = domainId; - + TString keyfile; { // prepare keyfile TString baseDir = runtime.GetTempDir(); @@ -119,12 +119,12 @@ void SetupServices(TTestActorRuntime &runtime) { file << "some key data"; } - TAppPrepare app; - + TAppPrepare app; + { // setup domain info - app.ClearDomainsAndHive(); - app.AddDomain(TDomainsInfo::TDomain::ConstructEmptyDomain("dc-1", domainId).Release()); - app.AddHive(domainId, MakeDefaultHiveID(stateStorageGroup)); + app.ClearDomainsAndHive(); + app.AddDomain(TDomainsInfo::TDomain::ConstructEmptyDomain("dc-1", domainId).Release()); + app.AddHive(domainId, MakeDefaultHiveID(stateStorageGroup)); } { // setup channel profiles TIntrusivePtr<TChannelProfiles> channelProfiles = new TChannelProfiles; @@ -134,7 +134,7 @@ void SetupServices(TTestActorRuntime &runtime) { profile.Channels.push_back( TChannelProfiles::TProfile::TChannel(TBlobStorageGroupType::ErasureMirror3, 0, NKikimrBlobStorage::TVDiskKind::Default)); } - app.SetChannels(std::move(channelProfiles)); + app.SetChannels(std::move(channelProfiles)); } ui32 groupId = TGroupID(GroupConfigurationTypeStatic, DOMAIN_ID, 0).GetRaw(); @@ -213,7 +213,7 @@ void SetupServices(TTestActorRuntime &runtime) { SetupTabletResolver(runtime, nodeIndex); } - runtime.Initialize(app.Unwrap()); + runtime.Initialize(app.Unwrap()); for (ui32 nodeIndex = 0; nodeIndex < runtime.GetNodeCount(); ++nodeIndex) { TActorId localActor = runtime.GetLocalServiceId( @@ -387,7 +387,7 @@ Y_UNIT_TEST_SUITE(TBlobStorageWardenTest) { CUSTOM_UNIT_TEST(TestCreatePDiskAndGroup) { TTempDir tempDir; - TTestBasicRuntime runtime(2, false); + TTestBasicRuntime runtime(2, false); Setup(runtime); TActorId sender0 = runtime.AllocateEdgeActor(0); TActorId sender1 = runtime.AllocateEdgeActor(1); diff --git a/ydb/core/persqueue/read_balancer.h b/ydb/core/persqueue/read_balancer.h index 6a07edcb78..64e500a503 100644 --- a/ydb/core/persqueue/read_balancer.h +++ b/ydb/core/persqueue/read_balancer.h @@ -438,7 +438,7 @@ public: TPersQueueReadBalancer(const TActorId &tablet, TTabletStorageInfo *info) : TActor(&TThis::StateInit) - , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) + , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) , Inited(false) , PathId(0) , Generation(0) diff --git a/ydb/core/protos/counters.proto b/ydb/core/protos/counters.proto index 05a8c93d90..23a1c5a452 100644 --- a/ydb/core/protos/counters.proto +++ b/ydb/core/protos/counters.proto @@ -69,7 +69,7 @@ enum ETxTypeSimpleCounters { enum ETxTypeCumulativeCounters { COUNTER_TT_CULUMATIVE_IGNORE = 0; - COUNTER_TT_POSTPONED = 1 [(CounterOpts) = {Name: "Postponed"}]; // Total restarts + COUNTER_TT_POSTPONED = 1 [(CounterOpts) = {Name: "Postponed"}]; // Total restarts COUNTER_TT_RO_COMPLETED = 2 [(CounterOpts) = {Name: "RoCompleted"}]; COUNTER_TT_RW_COMPLETED = 3 [(CounterOpts) = {Name: "RwCompleted"}]; COUNTER_TT_WRITES = 4 [(CounterOpts) = {Name: "Writes"}]; diff --git a/ydb/core/protos/flat_scheme_op.proto b/ydb/core/protos/flat_scheme_op.proto index 33e598c1c2..6869b5e10a 100644 --- a/ydb/core/protos/flat_scheme_op.proto +++ b/ydb/core/protos/flat_scheme_op.proto @@ -55,7 +55,7 @@ enum EColumnStorage { ColumnStorage2Ext2 = 5; ColumnStorage1Med2Ext2 = 6; ColumnStorage2Med2Ext2 = 7; - ColumnStorageTest_1_2_1k = 999; + ColumnStorageTest_1_2_1k = 999; } enum EFreezeState { @@ -75,7 +75,7 @@ message TColumnDescription { optional string Type = 2; optional uint32 TypeId = 3; optional uint32 Id = 4; - optional uint32 Family = 5; // On default place column to default(0) family + optional uint32 Family = 5; // On default place column to default(0) family optional string FamilyName = 6; // set Family by name (0 - "default") oneof DefaultValue { string DefaultFromSequence = 7; // Path to sequence for default values @@ -97,8 +97,8 @@ message TStorageConfig { optional uint32 ExternalThreshold = 6; } -message TFamilyDescription { - optional uint32 Id = 1; +message TFamilyDescription { + optional uint32 Id = 1; optional uint32 Room = 2; // Used by datashard, must not be used by users optional uint32 Codec = 3; // DEPRECATED: use ColumnCodec optional bool InMemory = 4; // DEPRECATED: use ColumnCache @@ -107,8 +107,8 @@ message TFamilyDescription { optional EColumnCache ColumnCache = 7; optional EColumnStorage Storage = 8; // DEPRECATED: use StorageConfig optional TStorageConfig StorageConfig = 9; -} - +} + enum ECompactionStrategy { CompactionStrategyUnset = 0; CompactionStrategyGenerational = 1; @@ -196,8 +196,8 @@ message TCompactionPolicy { optional uint32 InMemForceStepsToSnapshot = 3; // OR steps passed optional uint64 InMemForceSizeToSnapshot = 4; // OR size reached optional uint32 InMemCompactionBrokerQueue = 5 [default = 0]; // DEPRECATED - optional uint64 ReadAheadHiThreshold = 6 [default = 67108864]; - optional uint64 ReadAheadLoThreshold = 7 [default = 16777216]; + optional uint64 ReadAheadHiThreshold = 6 [default = 67108864]; + optional uint64 ReadAheadLoThreshold = 7 [default = 16777216]; optional uint32 MinDataPageSize = 8 [default = 7168]; // 7KB is smallest optimal for 512 byte sectors optional uint32 SnapBrokerQueue = 9 [default = 0]; // DEPRECATED optional uint32 BackupBrokerQueue = 11 [default = 1]; // DEPRECATED @@ -262,7 +262,7 @@ message TPartitionConfig { repeated TFamilyDescription ColumnFamilies = 12; optional string ResourceProfile = 13; optional bool DisableStatisticsCalculation = 14; // KIKIMR-3861 hotfix - optional bool EnableFilterByKey = 15 [default = false]; // Build and use per-part bloom filter for fast key non-existence check + optional bool EnableFilterByKey = 15 [default = false]; // Build and use per-part bloom filter for fast key non-existence check optional bool ExecutorFastLogPolicy = 16 [default = true]; // Commit log faster at the expense of bandwidth for cross-DC repeated NKikimrStorageSettings.TStorageRoom StorageRooms = 17; optional bool EnableEraseCache = 18 [default = true]; // Use erase cache for faster iteration over erased rows diff --git a/ydb/core/protos/scheme_log.proto b/ydb/core/protos/scheme_log.proto index fcf4ba52b9..df19040803 100644 --- a/ydb/core/protos/scheme_log.proto +++ b/ydb/core/protos/scheme_log.proto @@ -3,7 +3,7 @@ import "ydb/core/protos/flat_scheme_op.proto"; package NTabletFlatScheme; option java_package = "ru.yandex.kikimr.proto"; -message TAlterRecord { +message TAlterRecord { enum EDeltaType { AddTable = 1; DropTable = 2; @@ -11,55 +11,55 @@ message TAlterRecord { DropColumn = 4; AddColumnToKey = 5; AddColumnToFamily = 6; - AddFamily = 7; + AddFamily = 7; UpdateExecutorInfo = 8; SetCompactionPolicy = 9; - SetRoom = 10; - SetFamily = 11; - SetRedo = 12; - SetTable = 13; + SetRoom = 10; + SetFamily = 11; + SetRedo = 12; + SetTable = 13; }; required EDeltaType DeltaType = 1; optional uint32 TableId = 2; optional string TableName = 3; optional uint32 ColumnId = 4; - optional uint32 FamilyId = 7; - optional uint32 RoomId = 8; + optional uint32 FamilyId = 7; + optional uint32 RoomId = 8; - //_ Global: DB redo log tweaks settings - - optional uint32 Annex = 16; // Same as Large, but for redo log - - //_ Table: Common options - - optional uint32 ByKeyFilter = 17 [default = 0]; // TPart's key filter + //_ Global: DB redo log tweaks settings + + optional uint32 Annex = 16; // Same as Large, but for redo log + + //_ Table: Common options + + optional uint32 ByKeyFilter = 17 [default = 0]; // TPart's key filter optional bool EraseCacheEnabled = 20; optional uint32 EraseCacheMinRows = 21; optional uint32 EraseCacheMaxBytes = 22; optional bool ColdBorrow = 23 [default = false]; - + //_ Table: Attributes of storage (page collection) - - optional uint32 Main = 9; // Default channel for main data - optional uint32 Blobs = 15; // Channel for external blobs - optional uint32 Outer = 19; // Channel for outer packed values - - //_ Table: Attributes of family columns - - optional uint32 Codec = 11; // Read NPage::ECodec for details - optional bool InMemory = 12; // Deprecated, replaced with Cache - optional uint32 Cache = 13; // Read NPage::ECache for details - optional uint32 Large = 14; // When keep values in single blobs - optional uint32 Small = 18; // When pack values to outer blobs - - //_ Table: Attributes of single colimn - - optional string ColumnName = 5; - optional uint32 ColumnType = 6; - optional bytes Default = 10; // Serialized default value for cell + + optional uint32 Main = 9; // Default channel for main data + optional uint32 Blobs = 15; // Channel for external blobs + optional uint32 Outer = 19; // Channel for outer packed values + + //_ Table: Attributes of family columns + + optional uint32 Codec = 11; // Read NPage::ECodec for details + optional bool InMemory = 12; // Deprecated, replaced with Cache + optional uint32 Cache = 13; // Read NPage::ECache for details + optional uint32 Large = 14; // When keep values in single blobs + optional uint32 Small = 18; // When pack values to outer blobs + + //_ Table: Attributes of single colimn + + optional string ColumnName = 5; + optional uint32 ColumnType = 6; + optional bytes Default = 10; // Serialized default value for cell optional bool NotNull = 24 [default = false]; - + optional uint64 ExecutorCacheSize = 100; optional NKikimrSchemeOp.TCompactionPolicy CompactionPolicy = 101; optional bool ExecutorAllowLogBatching = 102; @@ -70,5 +70,5 @@ message TAlterRecord { }; message TSchemeChanges { - repeated TAlterRecord Delta = 1; + repeated TAlterRecord Delta = 1; }; diff --git a/ydb/core/protos/services.proto b/ydb/core/protos/services.proto index c17c8a7dc3..ee19318559 100644 --- a/ydb/core/protos/services.proto +++ b/ydb/core/protos/services.proto @@ -90,12 +90,12 @@ enum EServiceKikimr { TABLET_FLATEX = 315; TABLET_FLATBOOT = 316; TABLET_AGGREGATOR = 317; - TABLET_OPS_HOST = 666; - OPS_COMPACT = 667; - OPS_BACKUP = 668; - SAUSAGE_BIO = 669; - FAKE_ENV = 670; - + TABLET_OPS_HOST = 666; + OPS_COMPACT = 667; + OPS_BACKUP = 668; + SAUSAGE_BIO = 669; + FAKE_ENV = 670; + // PIPE section PIPE_CLIENT = 320; PIPE_SERVER = 321; diff --git a/ydb/core/scheme/scheme_tablecell.cpp b/ydb/core/scheme/scheme_tablecell.cpp index c9ffaccc8e..3c8ed82ce1 100644 --- a/ydb/core/scheme/scheme_tablecell.cpp +++ b/ydb/core/scheme/scheme_tablecell.cpp @@ -60,25 +60,25 @@ TOwnedCellVec::TInit TOwnedCellVec::Allocate(TOwnedCellVec::TCellVec cells) { }; } -TString DbgPrintCell(const TCell& r, NScheme::TTypeId typeId, const NScheme::TTypeRegistry ®) { - NScheme::ITypeSP t = reg.GetType(typeId); +TString DbgPrintCell(const TCell& r, NScheme::TTypeId typeId, const NScheme::TTypeRegistry ®) { + NScheme::ITypeSP t = reg.GetType(typeId); if (!t.IsKnownType()) return Sprintf("Unknow typeId 0x%x", (ui32)typeId); TString res = t->GetName(); res += " : "; - - DbgPrintValue(res, r, typeId); - - return res; -} - -void DbgPrintValue(TString &res, const TCell &r, ui32 type) { - if (r.IsNull()) { + + DbgPrintValue(res, r, typeId); + + return res; +} + +void DbgPrintValue(TString &res, const TCell &r, ui32 type) { + if (r.IsNull()) { res += "NULL"; - } else { - switch (type) { + } else { + switch (type) { case NScheme::NTypeIds::Bool: res += r.AsValue<bool>() ? "true" : "false"; break; diff --git a/ydb/core/scheme/scheme_tablecell.h b/ydb/core/scheme/scheme_tablecell.h index bccfdca97d..d813316182 100644 --- a/ydb/core/scheme/scheme_tablecell.h +++ b/ydb/core/scheme/scheme_tablecell.h @@ -8,7 +8,7 @@ #include <util/generic/hash.h> #include <util/system/unaligned_mem.h> -#include <type_traits> +#include <type_traits> namespace NKikimr { @@ -17,9 +17,9 @@ namespace NKikimr { // Doesn't own the memory buffer that stores the actual value // Small values (<= 8 bytes) are stored inline struct TCell { - template<typename T> - using TStdLayout = std::enable_if_t<std::is_standard_layout<T>::value, T>; - + template<typename T> + using TStdLayout = std::enable_if_t<std::is_standard_layout<T>::value, T>; + private: ui32 DataSize_ : 30; ui32 IsInline_ : 1; @@ -37,12 +37,12 @@ public: : TCell(nullptr, 0) {} - TCell(TArrayRef<const char> ref) - : TCell(ref.begin(), ui32(ref.size())) - { + TCell(TArrayRef<const char> ref) + : TCell(ref.begin(), ui32(ref.size())) + { Y_VERIFY(ref.size() < Max<ui32>(), " Too large blob size for TCell"); - } - + } + TCell(const char* ptr, ui32 sz) : DataSize_(sz) , IsInline_(0) @@ -62,26 +62,26 @@ public: : TCell((const char*)v->Data(), v->Size()) {} - explicit operator bool() const - { - return !IsNull(); - } - + explicit operator bool() const + { + return !IsNull(); + } + bool IsInline() const { return IsInline_; } bool IsNull() const { return IsNull_; } ui32 Size() const { return DataSize_; } - TArrayRef<const char> AsRef() const noexcept - { - return { Data(), Size() }; - } - - TStringBuf AsBuf() const noexcept - { - return { Data(), Size() }; + TArrayRef<const char> AsRef() const noexcept + { + return { Data(), Size() }; } - template<typename T, typename = TStdLayout<T>> + TStringBuf AsBuf() const noexcept + { + return { Data(), Size() }; + } + + template<typename T, typename = TStdLayout<T>> T AsValue() const noexcept { Y_VERIFY(sizeof(T) == Size(), "AsValue<T>() type doesn't match TCell"); @@ -90,16 +90,16 @@ public: } template<typename T, typename = TStdLayout<T>> - static inline TCell Make(const T &val) noexcept - { - auto *ptr = static_cast<const char*>(static_cast<const void*>(&val)); - - return TCell{ ptr, sizeof(val) }; - } - + static inline TCell Make(const T &val) noexcept + { + auto *ptr = static_cast<const char*>(static_cast<const void*>(&val)); + + return TCell{ ptr, sizeof(val) }; + } + #if 1 // Optimization to store small values (<= 8 bytes) inplace - static constexpr bool CanInline(ui32 sz) { return sz <= 8; } + static constexpr bool CanInline(ui32 sz) { return sz <= 8; } static constexpr size_t MaxInlineSize() { return 8; } const char* InlineData() const { Y_VERIFY_DEBUG(IsInline_); return IsNull_ ? nullptr : (char*)&IntVal; } const char* Data() const { return IsNull_ ? nullptr : (IsInline_ ? (char*)&IntVal : Ptr); } @@ -287,10 +287,10 @@ struct TDbTupleRef { const TCell* Columns; ui32 ColumnCount; - TArrayRef<const TCell> Cells() const { - return { Columns, ColumnCount }; - } - + TArrayRef<const TCell> Cells() const { + return { Columns, ColumnCount }; + } + TDbTupleRef(const NScheme::TTypeId* types = nullptr, const TCell* storage = nullptr, ui32 colCnt = 0) : Types(types) , Columns(storage) @@ -523,7 +523,7 @@ private: TVector<TCell> Cells; }; -void DbgPrintValue(TString&, const TCell&, ui32 type); +void DbgPrintValue(TString&, const TCell&, ui32 type); TString DbgPrintCell(const TCell& r, NScheme::TTypeId typeId, const NScheme::TTypeRegistry& typeRegistry); TString DbgPrintTuple(const TDbTupleRef& row, const NScheme::TTypeRegistry& typeRegistry); diff --git a/ydb/core/scheme_types/scheme_raw_type_value.h b/ydb/core/scheme_types/scheme_raw_type_value.h index 1cb0946b6d..5ac40f4e1e 100644 --- a/ydb/core/scheme_types/scheme_raw_type_value.h +++ b/ydb/core/scheme_types/scheme_raw_type_value.h @@ -2,7 +2,7 @@ #include <ydb/public/lib/scheme_types/scheme_type_id.h> -#include <util/generic/array_ref.h> +#include <util/generic/array_ref.h> #include <util/string/builder.h> namespace NKikimr { @@ -17,18 +17,18 @@ public: , ValueType(0) {} - TRawTypeValue(TArrayRef<const char> ref, NScheme::TTypeId vtype) - : TRawTypeValue((void*)ref.data(), ref.size(), vtype) - { - - } - + TRawTypeValue(TArrayRef<const char> ref, NScheme::TTypeId vtype) + : TRawTypeValue((void*)ref.data(), ref.size(), vtype) + { + + } + TRawTypeValue(const void* buf, ui32 bufSize, NScheme::TTypeId vtype) : Buffer(buf) , BufferSize(bufSize) , ValueType(vtype) { - Y_VERIFY_DEBUG(!buf || vtype); + Y_VERIFY_DEBUG(!buf || vtype); } const void* Data() const { return Buffer; } @@ -54,10 +54,10 @@ public: return TStringBuf((const char*)Buffer, BufferSize); } - TArrayRef<const char> AsRef() const noexcept { - return { static_cast<const char*>(Data()), Size() }; - } - + TArrayRef<const char> AsRef() const noexcept { + return { static_cast<const char*>(Data()), Size() }; + } + private: const void* Buffer; ui32 BufferSize; diff --git a/ydb/core/tablet/resource_broker_ut.cpp b/ydb/core/tablet/resource_broker_ut.cpp index 5948509025..ee258b54c6 100644 --- a/ydb/core/tablet/resource_broker_ut.cpp +++ b/ydb/core/tablet/resource_broker_ut.cpp @@ -194,7 +194,7 @@ TIntrusivePtr<IResourceBroker> GetInstantResourceBroker(TTestActorRuntime &runti Y_UNIT_TEST_SUITE(TResourceBroker) { Y_UNIT_TEST(TestErrors) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); SetupLogging(runtime); @@ -275,7 +275,7 @@ Y_UNIT_TEST_SUITE(TResourceBroker) { }; Y_UNIT_TEST(TestOverusage) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); SetupLogging(runtime); @@ -313,7 +313,7 @@ Y_UNIT_TEST_SUITE(TResourceBroker) { } Y_UNIT_TEST(TestExecutionStat) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); SetupLogging(runtime); @@ -403,7 +403,7 @@ Y_UNIT_TEST_SUITE(TResourceBroker) { } Y_UNIT_TEST(TestRealUsage) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); SetupLogging(runtime); @@ -452,7 +452,7 @@ Y_UNIT_TEST_SUITE(TResourceBroker) { } Y_UNIT_TEST(TestCounters) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); SetupLogging(runtime); @@ -547,7 +547,7 @@ Y_UNIT_TEST_SUITE(TResourceBroker) { } Y_UNIT_TEST(TestQueueWithConfigure) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); SetupLogging(runtime); @@ -605,7 +605,7 @@ Y_UNIT_TEST_SUITE(TResourceBroker) { } Y_UNIT_TEST(TestRandomQueue) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); SetupLogging(runtime); @@ -641,7 +641,7 @@ Y_UNIT_TEST_SUITE(TResourceBroker) { } Y_UNIT_TEST(TestNotifyActorDied) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); SetupLogging(runtime); @@ -680,7 +680,7 @@ Y_UNIT_TEST_SUITE(TResourceBroker) { } Y_UNIT_TEST(TestAutoTaskId) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); SetupLogging(runtime); @@ -717,7 +717,7 @@ Y_UNIT_TEST_SUITE(TResourceBroker) { } Y_UNIT_TEST(TestChangeTaskType) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); SetupLogging(runtime); @@ -754,7 +754,7 @@ Y_UNIT_TEST_SUITE(TResourceBroker) { } Y_UNIT_TEST(TestResubmitTask) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); SetupLogging(runtime); @@ -800,7 +800,7 @@ Y_UNIT_TEST_SUITE(TResourceBroker) { } Y_UNIT_TEST(TestUpdateCookie) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); SetupLogging(runtime); diff --git a/ydb/core/tablet/tablet_counters_aggregator_ut.cpp b/ydb/core/tablet/tablet_counters_aggregator_ut.cpp index 707ffb977e..b731c65cc4 100644 --- a/ydb/core/tablet/tablet_counters_aggregator_ut.cpp +++ b/ydb/core/tablet/tablet_counters_aggregator_ut.cpp @@ -90,9 +90,9 @@ Y_UNIT_TEST_SUITE(TTabletCountersAggregator) { TVector<TActorId> cc; TActorId aggregatorId; - TTestBasicRuntime runtime(1); + TTestBasicRuntime runtime(1); - runtime.Initialize(TAppPrepare().Unwrap()); + runtime.Initialize(TAppPrepare().Unwrap()); TActorId edge = runtime.AllocateEdgeActor(); IActor* aggregator = CreateClusterLabeledCountersAggregatorActor(edge, TTabletTypes::PersQueue, 2, TString(), 3); diff --git a/ydb/core/tablet/tablet_metrics.cpp b/ydb/core/tablet/tablet_metrics.cpp index 182c7c566e..4332f42949 100644 --- a/ydb/core/tablet/tablet_metrics.cpp +++ b/ydb/core/tablet/tablet_metrics.cpp @@ -15,7 +15,7 @@ ui64 TDecayingAverageWithSum::GetRawValue() const return RawValue; } -void TResourceMetricsValues::Fill(NKikimrTabletBase::TMetrics& metrics) const { +void TResourceMetricsValues::Fill(NKikimrTabletBase::TMetrics& metrics) const { if (CPU.IsValueReady()) { metrics.SetCPU(CPU.GetValue()); } diff --git a/ydb/core/tablet/tablet_metrics.h b/ydb/core/tablet/tablet_metrics.h index b426284d33..48af4b324e 100644 --- a/ydb/core/tablet/tablet_metrics.h +++ b/ydb/core/tablet/tablet_metrics.h @@ -49,7 +49,7 @@ public: TTabletIopsValue ReadIops; TTabletIopsValue WriteIops; - void Fill(NKikimrTabletBase::TMetrics& metrics) const; + void Fill(NKikimrTabletBase::TMetrics& metrics) const; }; class TResourceMetricsSendState { diff --git a/ydb/core/tablet/tablet_pipe_ut.cpp b/ydb/core/tablet/tablet_pipe_ut.cpp index 2a528070fb..0af97a56d6 100644 --- a/ydb/core/tablet/tablet_pipe_ut.cpp +++ b/ydb/core/tablet/tablet_pipe_ut.cpp @@ -58,7 +58,7 @@ namespace NKikimr { public: TProducerTablet(const TActorId &tablet, TTabletStorageInfo *info) : TActor(&TThis::StateInit) - , TTabletExecutedFlat(info, tablet, nullptr) + , TTabletExecutedFlat(info, tablet, nullptr) , HasData(false) , IsOpened(false) , IsShutdown(false) @@ -67,8 +67,8 @@ namespace NKikimr { } private: - using IActor::Send; // name is used by IActor API - + using IActor::Send; // name is used by IActor API + STFUNC(StateInit) { StateInitImpl(ev, ctx); } @@ -210,7 +210,7 @@ namespace NKikimr { public: TConsumerTablet(const TActorId &tablet, TTabletStorageInfo *info) : TActor(&TThis::StateInit) - , TTabletExecutedFlat(info, tablet, nullptr) + , TTabletExecutedFlat(info, tablet, nullptr) , PipeConnectAcceptor(NTabletPipe::CreateConnectAcceptor(TabletID())) , RejectAll(false) , ServerPipesOpened(0) @@ -337,7 +337,7 @@ namespace NKikimr { public: TConsumerTabletWithoutAcceptor(const TActorId &tablet, TTabletStorageInfo *info) : TActor(&TThis::StateInit) - , TTabletExecutedFlat(info, tablet, nullptr) + , TTabletExecutedFlat(info, tablet, nullptr) { } @@ -401,7 +401,7 @@ namespace NKikimr { Y_UNIT_TEST_SUITE(TTabletPipeTest) { Y_UNIT_TEST(TestOpen) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); TActorId sender = runtime.AllocateEdgeActor(); @@ -441,7 +441,7 @@ Y_UNIT_TEST_SUITE(TTabletPipeTest) { } Y_UNIT_TEST(TestSendWithoutWaitOpen) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); TActorId sender = runtime.AllocateEdgeActor(); @@ -468,7 +468,7 @@ Y_UNIT_TEST_SUITE(TTabletPipeTest) { } Y_UNIT_TEST(TestKillClientBeforServerIdKnown) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); runtime.SetLogPriority(NKikimrServices::PIPE_SERVER, NActors::NLog::PRI_DEBUG); runtime.SetLogPriority(NKikimrServices::PIPE_CLIENT, NActors::NLog::PRI_DEBUG); @@ -512,7 +512,7 @@ Y_UNIT_TEST_SUITE(TTabletPipeTest) { } Y_UNIT_TEST(TestSendWithoutWaitOpenToWrongTablet) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); TActorId sender = runtime.AllocateEdgeActor(); @@ -539,7 +539,7 @@ Y_UNIT_TEST_SUITE(TTabletPipeTest) { } Y_UNIT_TEST(TestSendAfterOpen) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); TActorId sender = runtime.AllocateEdgeActor(); @@ -572,7 +572,7 @@ Y_UNIT_TEST_SUITE(TTabletPipeTest) { } Y_UNIT_TEST(TestSendAfterReboot) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); TActorId sender = runtime.AllocateEdgeActor(); @@ -622,7 +622,7 @@ Y_UNIT_TEST_SUITE(TTabletPipeTest) { } Y_UNIT_TEST(TestConsumerSidePipeReset) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); TActorId sender = runtime.AllocateEdgeActor(); @@ -656,7 +656,7 @@ Y_UNIT_TEST_SUITE(TTabletPipeTest) { } Y_UNIT_TEST(TestConnectReject) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); TActorId sender = runtime.AllocateEdgeActor(); @@ -683,7 +683,7 @@ Y_UNIT_TEST_SUITE(TTabletPipeTest) { } Y_UNIT_TEST(TestSendAfterOpenUsingTabletWithoutAcceptor) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); TActorId sender = runtime.AllocateEdgeActor(); @@ -716,7 +716,7 @@ Y_UNIT_TEST_SUITE(TTabletPipeTest) { } Y_UNIT_TEST(TestRebootUsingTabletWithoutAcceptor) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); TActorId sender = runtime.AllocateEdgeActor(); @@ -767,7 +767,7 @@ Y_UNIT_TEST_SUITE(TTabletPipeTest) { } Y_UNIT_TEST(TestShutdown) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); TActorId sender = runtime.AllocateEdgeActor(); @@ -794,7 +794,7 @@ Y_UNIT_TEST_SUITE(TTabletPipeTest) { } Y_UNIT_TEST(TestTwoNodes) { - TTestBasicRuntime runtime(2); + TTestBasicRuntime runtime(2); SetupTabletServices(runtime); TActorId sender1 = runtime.AllocateEdgeActor(0); @@ -827,7 +827,7 @@ Y_UNIT_TEST_SUITE(TTabletPipeTest) { } Y_UNIT_TEST(TestClientDisconnectAfterPipeOpen) { - TTestBasicRuntime runtime(2); + TTestBasicRuntime runtime(2); SetupTabletServices(runtime); TActorId sender1 = runtime.AllocateEdgeActor(0); @@ -875,7 +875,7 @@ Y_UNIT_TEST_SUITE(TTabletPipeTest) { } Y_UNIT_TEST(TestSendBeforeBootTarget) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; SetupTabletServices(runtime); TActorId sender = runtime.AllocateEdgeActor(); TVector<ui64> tabletIds; @@ -932,7 +932,7 @@ Y_UNIT_TEST_SUITE(TTabletPipeTest) { } Y_UNIT_TEST(TestTwoNodesAndRebootOfProducer) { - TTestBasicRuntime runtime(2); + TTestBasicRuntime runtime(2); SetupTabletServices(runtime); TActorId sender1 = runtime.AllocateEdgeActor(0); @@ -981,7 +981,7 @@ Y_UNIT_TEST_SUITE(TTabletPipeTest) { } Y_UNIT_TEST(TestTwoNodesAndRebootOfConsumer) { - TTestBasicRuntime runtime(2); + TTestBasicRuntime runtime(2); SetupTabletServices(runtime); runtime.SetLogPriority(NActorsServices::INTERCONNECT, NActors::NLog::PRI_DEBUG); diff --git a/ydb/core/tablet/tablet_req_blockbs.cpp b/ydb/core/tablet/tablet_req_blockbs.cpp index 7e2e94ec95..2aa2a4277d 100644 --- a/ydb/core/tablet/tablet_req_blockbs.cpp +++ b/ydb/core/tablet/tablet_req_blockbs.cpp @@ -26,10 +26,10 @@ class TTabletReqBlockBlobStorageGroup : public TActorBootstrapped<TTabletReqBloc SendToBSProxy(TlsActivationContext->AsActorContext(), proxy, event.Release()); } - void Handle(TEvents::TEvUndelivered::TPtr&) { + void Handle(TEvents::TEvUndelivered::TPtr&) { return ReplyAndDie(NKikimrProto::ERROR, "BlobStorage proxy unavailable"); - } - + } + void Handle(TEvBlobStorage::TEvBlockResult::TPtr &ev) { const TEvBlobStorage::TEvBlockResult *msg = ev->Get(); @@ -55,7 +55,7 @@ class TTabletReqBlockBlobStorageGroup : public TActorBootstrapped<TTabletReqBloc switch (ev->GetTypeRewrite()) { hFunc(TEvBlobStorage::TEvBlockResult, Handle); cFunc(TEvents::TEvPoisonPill::EventType, PassAway); - hFunc(TEvents::TEvUndelivered, Handle); + hFunc(TEvents::TEvUndelivered, Handle); } } diff --git a/ydb/core/tablet/tablet_req_delete.cpp b/ydb/core/tablet/tablet_req_delete.cpp index 754c79bb32..1f50fa3e10 100644 --- a/ydb/core/tablet/tablet_req_delete.cpp +++ b/ydb/core/tablet/tablet_req_delete.cpp @@ -69,10 +69,10 @@ class TTabletReqDelete : public TActorBootstrapped<TTabletReqDelete> { SendToBSProxy(ctx, info.GroupId, event.Release(), numRequest); } - void Handle(TEvents::TEvUndelivered::TPtr&, const TActorContext &ctx) { - return ReplyAndDie(NKikimrProto::ERROR, ctx); - } - + void Handle(TEvents::TEvUndelivered::TPtr&, const TActorContext &ctx) { + return ReplyAndDie(NKikimrProto::ERROR, ctx); + } + void Handle(TEvBlobStorage::TEvCollectGarbageResult::TPtr& ev, const TActorContext& ctx) { const TEvBlobStorage::TEvCollectGarbageResult* msg = ev->Get(); switch (msg->Status) { @@ -108,7 +108,7 @@ class TTabletReqDelete : public TActorBootstrapped<TTabletReqDelete> { switch (ev->GetTypeRewrite()) { HFunc(TEvBlobStorage::TEvCollectGarbageResult, Handle); HFunc(TEvStateStorage::TEvDeleteResult, Handle); - HFunc(TEvents::TEvUndelivered, Handle); + HFunc(TEvents::TEvUndelivered, Handle); } } diff --git a/ydb/core/tablet/tablet_req_findlatest.cpp b/ydb/core/tablet/tablet_req_findlatest.cpp index ca3d09aa43..889eb7e1c4 100644 --- a/ydb/core/tablet/tablet_req_findlatest.cpp +++ b/ydb/core/tablet/tablet_req_findlatest.cpp @@ -39,8 +39,8 @@ class TTabletReqFindLatestLogEntry : public TActorBootstrapped<TTabletReqFindLat void Handle(TEvents::TEvUndelivered::TPtr&) { return ReplyAndDie(NKikimrProto::ERROR, "BlobStorage proxy unavailable"); - } - + } + void Handle(TEvBlobStorage::TEvDiscoverResult::TPtr &ev) { TEvBlobStorage::TEvDiscoverResult *msg = ev->Get(); diff --git a/ydb/core/tablet/tablet_req_rebuildhistory.cpp b/ydb/core/tablet/tablet_req_rebuildhistory.cpp index c0b4c0c2bc..fe533a6ad3 100644 --- a/ydb/core/tablet/tablet_req_rebuildhistory.cpp +++ b/ydb/core/tablet/tablet_req_rebuildhistory.cpp @@ -783,8 +783,8 @@ class TTabletReqRebuildHistoryGraph : public TActorBootstrapped<TTabletReqRebuil void Handle(TEvents::TEvUndelivered::TPtr&) { return ReplyAndDie(NKikimrProto::ERROR, "BlobStorage proxy unavailable"); - } - + } + void Handle(TEvTabletBase::TEvFindLatestLogEntryResult::TPtr &ev) { TEvTabletBase::TEvFindLatestLogEntryResult *msg = ev->Get(); diff --git a/ydb/core/tablet/tablet_req_writelog.cpp b/ydb/core/tablet/tablet_req_writelog.cpp index 7c4d02c405..90776c250a 100644 --- a/ydb/core/tablet/tablet_req_writelog.cpp +++ b/ydb/core/tablet/tablet_req_writelog.cpp @@ -26,10 +26,10 @@ class TTabletReqWriteLog : public TActorBootstrapped<TTabletReqWriteLog> { TVector<ui32> YellowMoveChannels; TVector<ui32> YellowStopChannels; - void Handle(TEvents::TEvUndelivered::TPtr&, const TActorContext &ctx) { + void Handle(TEvents::TEvUndelivered::TPtr&, const TActorContext &ctx) { return ReplyAndDie(NKikimrProto::ERROR, "BlobStorage proxy unavailable", ctx); - } - + } + void Handle(TEvBlobStorage::TEvPutResult::TPtr &ev, const TActorContext &ctx) { TEvBlobStorage::TEvPutResult *msg = ev->Get(); @@ -143,7 +143,7 @@ public: STFUNC(StateWait) { switch (ev->GetTypeRewrite()) { HFunc(TEvBlobStorage::TEvPutResult, Handle); - HFunc(TEvents::TEvUndelivered, Handle); + HFunc(TEvents::TEvUndelivered, Handle); } } }; diff --git a/ydb/core/tablet/ya.make b/ydb/core/tablet/ya.make index 25e611b408..d3eecf04bd 100644 --- a/ydb/core/tablet/ya.make +++ b/ydb/core/tablet/ya.make @@ -50,7 +50,7 @@ SRCS( tablet_setup.h tablet_sys.h tablet_sys.cpp - bootstrapper.cpp + bootstrapper.cpp ) PEERDIR( diff --git a/ydb/core/tablet_flat/defs.h b/ydb/core/tablet_flat/defs.h index 166674c3ff..9695bed45c 100644 --- a/ydb/core/tablet_flat/defs.h +++ b/ydb/core/tablet_flat/defs.h @@ -1,16 +1,16 @@ #pragma once // unique tag to fix pragma once gcc glueing: ./ydb/core/tablet_flat/defs.h - -#include "flat_page_iface.h" + +#include "flat_page_iface.h" #include "util_basics.h" - + #include <ydb/core/base/defs.h> #include <ydb/core/base/events.h> #include <ydb/core/base/logoblob.h> #include <ydb/core/scheme_types/scheme_raw_type_value.h> #include <ydb/core/util/type_alias.h> -#include <util/generic/xrange.h> -#include <util/generic/ylimits.h> +#include <util/generic/xrange.h> +#include <util/generic/ylimits.h> namespace NKikimr { @@ -23,15 +23,15 @@ namespace NScheme { } // end of NKikimr::NScheme namespace -namespace NTable { - +namespace NTable { + using TRawVals = TArrayRef<const TRawTypeValue>; - + class TEpoch : public TTypeSafeAlias<TEpoch, i64> { public: // N.B. this catches accidental legacy conversions TEpoch(ui64 value) = delete; - + explicit constexpr TEpoch(i64 value) noexcept : TBase(value) { } @@ -67,55 +67,55 @@ namespace NTable { } }; - enum class ELookup { - ExactMatch = 1, - GreaterOrEqualThan = 2, - GreaterThan = 3, - }; - - struct TTxStamp { - constexpr TTxStamp(ui64 raw = 0) : Raw(raw) { } - TTxStamp(const TLogoBlobID &logo) - : TTxStamp(logo.Generation(), logo.Step()) { } - constexpr TTxStamp(ui32 gen, ui32 step) - : Raw((ui64(gen) << 32) | step) - { - - } - - constexpr bool operator <(ui64 raw) const noexcept - { - return Raw < raw; - } - - constexpr operator ui64() const noexcept { return Raw; } - constexpr ui32 Gen() const noexcept { return Raw >> 32; } - constexpr ui32 Step() const noexcept { return Raw; } - - ui64 Raw = 0; - }; - - struct TSnapEdge { - TSnapEdge() = default; - - TSnapEdge(ui64 txStamp, TEpoch head) - : TxStamp(txStamp) - , Head(head) - { - - } - - ui64 TxStamp = 0; + enum class ELookup { + ExactMatch = 1, + GreaterOrEqualThan = 2, + GreaterThan = 3, + }; + + struct TTxStamp { + constexpr TTxStamp(ui64 raw = 0) : Raw(raw) { } + TTxStamp(const TLogoBlobID &logo) + : TTxStamp(logo.Generation(), logo.Step()) { } + constexpr TTxStamp(ui32 gen, ui32 step) + : Raw((ui64(gen) << 32) | step) + { + + } + + constexpr bool operator <(ui64 raw) const noexcept + { + return Raw < raw; + } + + constexpr operator ui64() const noexcept { return Raw; } + constexpr ui32 Gen() const noexcept { return Raw >> 32; } + constexpr ui32 Step() const noexcept { return Raw; } + + ui64 Raw = 0; + }; + + struct TSnapEdge { + TSnapEdge() = default; + + TSnapEdge(ui64 txStamp, TEpoch head) + : TxStamp(txStamp) + , Head(head) + { + + } + + ui64 TxStamp = 0; TEpoch Head = TEpoch::Zero(); friend bool operator==(const TSnapEdge& a, const TSnapEdge& b) { return a.TxStamp == b.TxStamp && a.Head == b.Head; } - }; -} - -namespace NTabletFlatExecutor { - using TTxStamp = NTable::TTxStamp; - using TRawVals = NTable::TRawVals; -} + }; +} + +namespace NTabletFlatExecutor { + using TTxStamp = NTable::TTxStamp; + using TRawVals = NTable::TRawVals; } +} diff --git a/ydb/core/tablet_flat/flat_abi_check.h b/ydb/core/tablet_flat/flat_abi_check.h index ec1e1eef3d..e3360c55af 100644 --- a/ydb/core/tablet_flat/flat_abi_check.h +++ b/ydb/core/tablet_flat/flat_abi_check.h @@ -1,28 +1,28 @@ -#pragma once - -#include "flat_abi_evol.h" -#include "util_fmt_abort.h" - -namespace NKikimr { -namespace NTable { - - struct TAbi { +#pragma once + +#include "flat_abi_evol.h" +#include "util_fmt_abort.h" + +namespace NKikimr { +namespace NTable { + + struct TAbi { using EVol = ECompatibility; - - void Check(ui32 tail, ui32 head, const char *label) const noexcept - { - if (tail > head) { - Y_Fail(label << " ABI [" << tail << ", " << head << "]" - << " label is invalid"); - } else if (head < ui32(EVol::Tail) || tail > ui32(EVol::Edge)) { - Y_Fail( - "NTable read ABI [" << ui32(EVol::Tail) << ", " - << ui32(EVol::Edge) << "] is incompatible with ABI" - << " [" << tail << ", " << head << "] of " << label - ); - } - } - }; - -} -} + + void Check(ui32 tail, ui32 head, const char *label) const noexcept + { + if (tail > head) { + Y_Fail(label << " ABI [" << tail << ", " << head << "]" + << " label is invalid"); + } else if (head < ui32(EVol::Tail) || tail > ui32(EVol::Edge)) { + Y_Fail( + "NTable read ABI [" << ui32(EVol::Tail) << ", " + << ui32(EVol::Edge) << "] is incompatible with ABI" + << " [" << tail << ", " << head << "] of " << label + ); + } + } + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_abi_evol.h b/ydb/core/tablet_flat/flat_abi_evol.h index ef99020d93..6b1c8aa94b 100644 --- a/ydb/core/tablet_flat/flat_abi_evol.h +++ b/ydb/core/tablet_flat/flat_abi_evol.h @@ -1,97 +1,97 @@ -#pragma once - -#include <util/system/types.h> - -namespace NKikimr { -namespace NTable { - +#pragma once + +#include <util/system/types.h> + +namespace NKikimr { +namespace NTable { + enum class ECompatibility: ui32 { - - /* Evolution of API/ABI changes of executor binary logs, protocols - and table internal data units. Each alteration of these entities - that requires to keep legacy code for compatability for unknown - time period should be recorded in this log with Head increment. - - Each drop of legacy code recorded in this log have to lead to - raising Tail value below which is the lowest supported evolution. - - Tail least supported version for blobs reads, - Head least supported version for produced blobs, - Edge the evolution edge, upper supported version. - - get = [ Tail, Edge ] - can be parsed and interpreted correctly, - put = [ Head, Edge ] - write backward compatibility version span. - */ - - Tail = 1, - Head = 17, + + /* Evolution of API/ABI changes of executor binary logs, protocols + and table internal data units. Each alteration of these entities + that requires to keep legacy code for compatability for unknown + time period should be recorded in this log with Head increment. + + Each drop of legacy code recorded in this log have to lead to + raising Tail value below which is the lowest supported evolution. + + Tail least supported version for blobs reads, + Head least supported version for produced blobs, + Edge the evolution edge, upper supported version. + + get = [ Tail, Edge ] - can be parsed and interpreted correctly, + put = [ Head, Edge ] - write backward compatibility version span. + */ + + Tail = 1, + Head = 17, Edge = 28, - }; - - /* Ev | Desc | Gone - --------------------------------------------------------------------- + }; + + /* Ev | Desc | Gone + --------------------------------------------------------------------- 2 All bundles proto was moved to usage of TLargeGlobId units - --------------------------------------------------------------------- - 3 Support of NPage v2 labels with additional metadata - Page readers adopted to work with relative offsets - --------------------------------------------------------------------- + --------------------------------------------------------------------- + 3 Support of NPage v2 labels with additional metadata + Page readers adopted to work with relative offsets + --------------------------------------------------------------------- 4 EPage::DataPage compression support via NPage v2 labels - --------------------------------------------------------------------- - 5 TPart columns limited to -Min<ui16>, or to 32767 cols - --------------------------------------------------------------------- + --------------------------------------------------------------------- + 5 TPart columns limited to -Min<ui16>, or to 32767 cols + --------------------------------------------------------------------- 6 Complete support of ELargeObj::Extern blobs references - --------------------------------------------------------------------- - 7 Extend NPage::TBlobs with channel mask (version 1) - --------------------------------------------------------------------- + --------------------------------------------------------------------- + 7 Extend NPage::TBlobs with channel mask (version 1) + --------------------------------------------------------------------- 8 ECellOp::{Null,Empty,Reset} cannot have values in redo log - --------------------------------------------------------------------- - 9 Evolution number storages changed from ui64 to ui32 - --------------------------------------------------------------------- - 10 Read suppport of new REDO log chunks + log ABI markers - Key items and updates in REDO log limited to Max<ui16> - --------------------------------------------------------------------- - 11 Complete support of annex in redo log (exnternal blobs) - --------------------------------------------------------------------- - 12 Write redo log in new binary format with generic chunks + --------------------------------------------------------------------- + 9 Evolution number storages changed from ui64 to ui32 + --------------------------------------------------------------------- + 10 Read suppport of new REDO log chunks + log ABI markers + Key items and updates in REDO log limited to Max<ui16> + --------------------------------------------------------------------- + 11 Complete support of annex in redo log (exnternal blobs) + --------------------------------------------------------------------- + 12 Write redo log in new binary format with generic chunks Use only TLargeGlobId in bundles proto (TPageCollectionProtoHelper serializer) - --------------------------------------------------------------------- + --------------------------------------------------------------------- 13 Read/write support for TPart page collection root meta data - Scheme page now has TLabel'ed version EPage::Schem2 + Scheme page now has TLabel'ed version EPage::Schem2 +part metainfo: ABI labels, rows and ERowOp::Erase stats - --------------------------------------------------------------------- - 14 Per-part by key bloom filter support (EPage:ByKey v0) - --------------------------------------------------------------------- + --------------------------------------------------------------------- + 14 Per-part by key bloom filter support (EPage:ByKey v0) + --------------------------------------------------------------------- 15 Complete support ELargeObj::Outer, values packed in page collection --------------------------------------------------------------------- 16 Read and write final key in EPage::Index - --------------------------------------------------------------------- + --------------------------------------------------------------------- 17 Fixed incomplete read support of rooted page collections - --------------------------------------------------------------------- - 18 Durable db change serial numbers with EvBegin v1 - Stamp field in EvFlush is not used anymore + --------------------------------------------------------------------- + 18 Durable db change serial numbers with EvBegin v1 + Stamp field in EvFlush is not used anymore --------------------------------------------------------------------- 19 Generation and serialization of part slices --------------------------------------------------------------------- 20 Support for partial bundle compaction - --------------------------------------------------------------------- - 21 Fix of diverged TxStamp filed in EvBegin, KIKIMR-5323 - --------------------------------------------------------------------- - 22 Fix of unaligned array placement in NPage::TFrames buf - --------------------------------------------------------------------- + --------------------------------------------------------------------- + 21 Fix of diverged TxStamp filed in EvBegin, KIKIMR-5323 + --------------------------------------------------------------------- + 22 Fix of unaligned array placement in NPage::TFrames buf + --------------------------------------------------------------------- 23 Start producing all page collections only with TLabel-ed pages - Resuse unused channels mask in EPage::Blobs for stats - --------------------------------------------------------------------- - 24 Support large NLabel variant in pages and blobs readers - Start write at least small variant of NLabel everywhere - --------------------------------------------------------------------- - 25 Back to evolution 24 and legacy Tiny + Small labels + Resuse unused channels mask in EPage::Blobs for stats + --------------------------------------------------------------------- + 24 Support large NLabel variant in pages and blobs readers + Start write at least small variant of NLabel everywhere + --------------------------------------------------------------------- + 25 Back to evolution 24 and legacy Tiny + Small labels --------------------------------------------------------------------- 26 Parts with column groups --------------------------------------------------------------------- 27 Parts with versioned rows and historic indexes --------------------------------------------------------------------- 28 Parts with uncommitted delta rows - */ - -} -} + */ + +} +} diff --git a/ydb/core/tablet_flat/flat_bio_actor.cpp b/ydb/core/tablet_flat/flat_bio_actor.cpp index 6a866fb395..1f6351e233 100644 --- a/ydb/core/tablet_flat/flat_bio_actor.cpp +++ b/ydb/core/tablet_flat/flat_bio_actor.cpp @@ -1,82 +1,82 @@ -#include "flat_bio_actor.h" -#include "flat_bio_events.h" -#include "flat_bio_stats.h" -#include "util_fmt_logger.h" - +#include "flat_bio_actor.h" +#include "flat_bio_events.h" +#include "flat_bio_stats.h" +#include "util_fmt_logger.h" + #include <ydb/core/base/blobstorage.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { + +namespace NKikimr { +namespace NTabletFlatExecutor { namespace NBlockIO { - -using TEvGet = TEvBlobStorage::TEvGet; - + +using TEvGet = TEvBlobStorage::TEvGet; + struct TBlockIO::TLoaded : public TEvBlobStorage::TEvGetResult::TResponse{ }; - + TBlockIO::TBlockIO(TActorId service, ui64 cookie) : ::NActors::IActor(static_cast<TReceiveFunc>(&TBlockIO::Inbox), NKikimrServices::TActivity::SAUSAGE_BIO_A) - , Service(service) - , Cookie(cookie) -{ -} - -TBlockIO::~TBlockIO() -{ - -} - + , Service(service) + , Cookie(cookie) +{ +} + +TBlockIO::~TBlockIO() +{ + +} + void TBlockIO::Registered(TActorSystem *sys, const TActorId&) -{ - Logger = new NUtil::TLogger(sys, NKikimrServices::SAUSAGE_BIO); -} - +{ + Logger = new NUtil::TLogger(sys, NKikimrServices::SAUSAGE_BIO); +} + void TBlockIO::Inbox(TEventHandlePtr &eh, const ::NActors::TActorContext&) -{ +{ if (auto *ev = eh->CastAsLocal<TEvBlobStorage::TEvGetResult>()) { - if (ev->Status != NKikimrProto::OK) - Terminate(ev->Status); - else { - auto *ptr = reinterpret_cast<TLoaded*>(ev->Responses.Get()); - - Handle(eh->Cookie, { ptr, size_t(ev->ResponseSz) }); - } + if (ev->Status != NKikimrProto::OK) + Terminate(ev->Status); + else { + auto *ptr = reinterpret_cast<TLoaded*>(ev->Responses.Get()); + + Handle(eh->Cookie, { ptr, size_t(ev->ResponseSz) }); + } } else if (auto *ev = eh->CastAsLocal<NBlockIO::TEvFetch>()) { - Y_VERIFY(!Owner, "TBlockIO actor now can hanle only one request"); - - Owner = eh->Sender; + Y_VERIFY(!Owner, "TBlockIO actor now can hanle only one request"); + + Owner = eh->Sender; Bootstrap(ev->Priority, ev->Fetch); - } else if (eh->CastAsLocal<TEvents::TEvUndelivered>()) { - Terminate(NKikimrProto::UNKNOWN); - } else if (eh->CastAsLocal<TEvents::TEvPoison>()) { - PassAway(); - } else { + } else if (eh->CastAsLocal<TEvents::TEvUndelivered>()) { + Terminate(NKikimrProto::UNKNOWN); + } else if (eh->CastAsLocal<TEvents::TEvPoison>()) { + PassAway(); + } else { Y_FAIL("Page collection blocks IO actor got an unexpected event"); - } -} - + } +} + void TBlockIO::Bootstrap(EPriority priority, TAutoPtr<NPageCollection::TFetch> origin) noexcept -{ +{ Origin = origin; Priority = priority; - - Y_VERIFY(Origin->Pages, "Got TFetch request without pages list"); - + + Y_VERIFY(Origin->Pages, "Got TFetch request without pages list"); + PagesToBlobsConverter = new TPagesToBlobsConverter(*Origin->PageCollection, Origin->Pages); - + BlockStates.reserve(Origin->Pages.size()); - - for (auto page: Origin->Pages) { + + for (auto page: Origin->Pages) { ui64 size = Origin->PageCollection->Page(page).Size; BlockStates.emplace_back(size); - } - - Dispatch(); -} - -void TBlockIO::Dispatch() noexcept -{ - const auto ctx = TActivationContext::ActorContextFor(SelfId()); - + } + + Dispatch(); +} + +void TBlockIO::Dispatch() noexcept +{ + const auto ctx = TActivationContext::ActorContextFor(SelfId()); + NKikimrBlobStorage::EGetHandleClass klass; switch (Priority) { case NBlockIO::EPriority::None: @@ -91,74 +91,74 @@ void TBlockIO::Dispatch() noexcept klass = NKikimrBlobStorage::LowRead; break; } - + while (auto more = PagesToBlobsConverter->Grow(NBlockIO::BlockSize)) { auto group = NPageCollection::TLargeGlobId::InvalidGroup; - + TArrayHolder<TEvGet::TQuery> query(new TEvGet::TQuery[+more]); - + ui32 lastBlob = Max<ui32>(); - for (const auto on : xrange(+more)) { + for (const auto on : xrange(+more)) { auto &brick = PagesToBlobsConverter->Queue[more.From + on]; auto glob = Origin->PageCollection->Glob(brick.Blob); - - if ((group = (on ? group : glob.Group)) != glob.Group) - Y_FAIL("Cannot handle different groups in one request"); - - query[on].Id = glob.Logo; - query[on].Shift = brick.Skip; - query[on].Size = brick.Size; - - { - auto skey = std::make_pair(query[on].Id.Channel(), group); - + + if ((group = (on ? group : glob.Group)) != glob.Group) + Y_FAIL("Cannot handle different groups in one request"); + + query[on].Id = glob.Logo; + query[on].Shift = brick.Skip; + query[on].Size = brick.Size; + + { + auto skey = std::make_pair(query[on].Id.Channel(), group); + GroupBytes[skey] += query[on].Size; if (lastBlob != brick.Blob) { lastBlob = brick.Blob; GroupOps[skey] += 1; TotalOps++; } - } - } - - Pending++; - - auto *ev = new TEvGet(query, +more, TInstant::Max(), klass, false); - - SendToBSProxy(ctx, group, ev, more.From /* cookie, request offset */); - } - - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl + } + } + + Pending++; + + auto *ev = new TEvGet(query, +more, TInstant::Max(), klass, false); + + SendToBSProxy(ctx, group, ev, more.From /* cookie, request offset */); + } + + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl << "NBlockIO pageCollection " << Origin->PageCollection->Label() << " cooked flow " << PagesToBlobsConverter->OnHold << "b " << PagesToBlobsConverter->Tail << "p" << " " << PagesToBlobsConverter->Queue.size() << " bricks in " << Pending << " reads, " << BlockStates.size() << "p req"; - } - + } + Y_VERIFY(PagesToBlobsConverter->Complete(), "NPageCollection::TPagesToBlobsConverter cooked incomplete loads"); -} - -void TBlockIO::Handle(ui32 base, TArrayRef<TLoaded> items) noexcept -{ - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl +} + +void TBlockIO::Handle(ui32 base, TArrayRef<TLoaded> items) noexcept +{ + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl << "NBlockIO pageCollection " << Origin->PageCollection->Label() << " got base" << " " << items.size() << " bricks, left " << Pending; - } - - for (auto &piece: items) { - if (piece.Status != NKikimrProto::OK) { - if (auto logl = Logger->Log(ELnLev::Warn)) { - logl + } + + for (auto &piece: items) { + if (piece.Status != NKikimrProto::OK) { + if (auto logl = Logger->Log(ELnLev::Warn)) { + logl << "NBlockIO pageCollection " << Origin->PageCollection->Label() << " get failed" - << ", " << piece.Id << " status " << piece.Status; - } - - return Terminate(piece.Status); - } - + << ", " << piece.Id << " status " << piece.Status; + } + + return Terminate(piece.Status); + } + const auto &brick = PagesToBlobsConverter->Queue[base + (&piece - &items[0])]; - + auto& state = BlockStates.at(brick.Slot); Y_VERIFY(state.Data.size() - state.Offset >= piece.Buffer.size()); ::memcpy( @@ -166,68 +166,68 @@ void TBlockIO::Handle(ui32 base, TArrayRef<TLoaded> items) noexcept piece.Buffer.data(), piece.Buffer.size()); state.Offset += piece.Buffer.size(); - } - - if (--Pending > 0) - return; - + } + + if (--Pending > 0) + return; + size_t index = 0; for (ui32 pageId : Origin->Pages) { auto& state = BlockStates.at(index++); Y_VERIFY(state.Offset == state.Data.size()); if (Origin->PageCollection->Verify(pageId, state.Data)) { - continue; - } else if (auto logl = Logger->Log(ELnLev::Crit)) { + continue; + } else if (auto logl = Logger->Log(ELnLev::Crit)) { const auto bnd = Origin->PageCollection->Bounds(pageId); - - logl + + logl << "NBlockIO pageCollection " << Origin->PageCollection->Label() << " verify failed" << ", page " << pageId << " " << state.Data.size() << "b" - << " spans over {"; - - for (auto one: xrange(bnd.Lo.Blob, bnd.Up.Blob + 1)) { + << " spans over {"; + + for (auto one: xrange(bnd.Lo.Blob, bnd.Up.Blob + 1)) { const auto glob = Origin->PageCollection->Glob(one); - - logl << " " << glob.Group << " " << glob.Logo; - } - - logl << " }"; - } - - return Terminate(NKikimrProto::CORRUPTED); - } - - Terminate(NKikimrProto::OK); -} - -void TBlockIO::Terminate(EStatus code) noexcept -{ - if (auto logl = Logger->Log(code ? ELnLev::Warn : ELnLev::Debug)) { - logl + + logl << " " << glob.Group << " " << glob.Logo; + } + + logl << " }"; + } + + return Terminate(NKikimrProto::CORRUPTED); + } + + Terminate(NKikimrProto::OK); +} + +void TBlockIO::Terminate(EStatus code) noexcept +{ + if (auto logl = Logger->Log(code ? ELnLev::Warn : ELnLev::Debug)) { + logl << "NBlockIO pageCollection " << Origin->PageCollection->Label() << " end, status " << code - << ", cookie {req " << Origin->Cookie << " ev " << Cookie << "}" + << ", cookie {req " << Origin->Cookie << " ev " << Cookie << "}" << ", " << BlockStates.size() << " pages"; - } - + } + auto *ev = new TEvData(std::move(Origin->PageCollection), Origin->Cookie, code); - - if (code == NKikimrProto::OK) { + + if (code == NKikimrProto::OK) { size_t index = 0; ev->Blocks.reserve(Origin->Pages.size()); for (ui32 pageId : Origin->Pages) { auto& state = BlockStates.at(index++); ev->Blocks.emplace_back(pageId, std::move(state.Data)); } - } - - if (Service) + } + + if (Service) Send(Service, new TEvStat(EDir::Read, Priority, PagesToBlobsConverter->OnHold, TotalOps, std::move(GroupBytes), std::move(GroupOps))); - - Send(Owner, ev, 0, Cookie); - - return PassAway(); -} - -} -} -} + + Send(Owner, ev, 0, Cookie); + + return PassAway(); +} + +} +} +} diff --git a/ydb/core/tablet_flat/flat_bio_actor.h b/ydb/core/tablet_flat/flat_bio_actor.h index 6de0926223..3fae5ddfad 100644 --- a/ydb/core/tablet_flat/flat_bio_actor.h +++ b/ydb/core/tablet_flat/flat_bio_actor.h @@ -1,47 +1,47 @@ -#pragma once -#include "defs.h" -#include "flat_sausage_flow.h" -#include "flat_bio_events.h" -#include "util_fmt_line.h" +#pragma once +#include "defs.h" +#include "flat_sausage_flow.h" +#include "flat_bio_events.h" +#include "util_fmt_line.h" #include <ydb/core/tablet/tablet_metrics.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { + +namespace NKikimr { +namespace NTabletFlatExecutor { namespace NBlockIO { - class TBlockIO : public ::NActors::IActor { + class TBlockIO : public ::NActors::IActor { using TEventHandlePtr = TAutoPtr<::NActors::IEventHandle>; - using ELnLev = NUtil::ELnLev; - using EStatus = NKikimrProto::EReplyStatus; + using ELnLev = NUtil::ELnLev; + using EStatus = NKikimrProto::EReplyStatus; using TPagesToBlobsConverter = NPageCollection::TPagesToBlobsConverter<NPageCollection::IPageCollection>; - - struct TLoaded; /* hack for fwd decl of BS interface units */ - - public: + + struct TLoaded; /* hack for fwd decl of BS interface units */ + + public: TBlockIO(TActorId service, ui64 cookie); - ~TBlockIO(); - - private: + ~TBlockIO(); + + private: void Registered(TActorSystem*, const TActorId&) override; void Inbox(TEventHandlePtr &eh, const ::NActors::TActorContext &ctx); void Bootstrap(EPriority priority, TAutoPtr<NPageCollection::TFetch>) noexcept; - void Dispatch() noexcept; - void Handle(ui32 offset, TArrayRef<TLoaded>) noexcept; - void Terminate(EStatus code) noexcept; - - private: + void Dispatch() noexcept; + void Handle(ui32 offset, TArrayRef<TLoaded>) noexcept; + void Terminate(EStatus code) noexcept; + + private: const TActorId Service; - const ui64 Cookie = Max<ui64>(); + const ui64 Cookie = Max<ui64>(); TAutoPtr<NUtil::ILogger> Logger; - - /*_ immutable request settings */ - + + /*_ immutable request settings */ + TActorId Owner; EPriority Priority = EPriority::None; TAutoPtr<NPageCollection::TFetch> Origin; - - /*_ request operational state */ - + + /*_ request operational state */ + struct TLoadState { size_t Offset = 0; TSharedData Data; @@ -53,21 +53,21 @@ namespace NBlockIO { TVector<TLoadState> BlockStates; TAutoPtr<TPagesToBlobsConverter> PagesToBlobsConverter; - ui64 Pending = 0; + ui64 Pending = 0; ui64 TotalOps = 0; NMetrics::TTabletThroughputRawValue GroupBytes; NMetrics::TTabletIopsRawValue GroupOps; - }; - - template<typename ... TArgs> + }; + + template<typename ... TArgs> inline void Once(NActors::IActorOps *ops, TActorId service, - ui64 cookie, TArgs&& ... args) noexcept - { - auto self = ops->Register(new TBlockIO(service, cookie)); - - ops->Send(self, new TEvFetch(std::forward<TArgs>(args)...)); - } - -} -} -} + ui64 cookie, TArgs&& ... args) noexcept + { + auto self = ops->Register(new TBlockIO(service, cookie)); + + ops->Send(self, new TEvFetch(std::forward<TArgs>(args)...)); + } + +} +} +} diff --git a/ydb/core/tablet_flat/flat_bio_eggs.h b/ydb/core/tablet_flat/flat_bio_eggs.h index a71ac8d704..3f8252e773 100644 --- a/ydb/core/tablet_flat/flat_bio_eggs.h +++ b/ydb/core/tablet_flat/flat_bio_eggs.h @@ -1,21 +1,21 @@ -#pragma once - +#pragma once + #include <util/system/types.h> -namespace NKikimr { -namespace NTabletFlatExecutor { +namespace NKikimr { +namespace NTabletFlatExecutor { namespace NBlockIO { - - constexpr static ui64 BlockSize = 8192 * 1024; - + + constexpr static ui64 BlockSize = 8192 * 1024; + enum class EPriority { - None = 0, - Fast = 1, /* Low latency activity */ - Bulk = 2, /* Huge bulk IO reads like scan ops */ - Bkgr = 4, /* System background read activity */ + None = 0, + Fast = 1, /* Low latency activity */ + Bulk = 2, /* Huge bulk IO reads like scan ops */ + Bkgr = 4, /* System background read activity */ Low = 5, /* Low priority read activity */ - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_bio_events.h b/ydb/core/tablet_flat/flat_bio_events.h index dae56ecca0..31ec0bbedc 100644 --- a/ydb/core/tablet_flat/flat_bio_events.h +++ b/ydb/core/tablet_flat/flat_bio_events.h @@ -1,70 +1,70 @@ -#pragma once - -#include "flat_bio_eggs.h" -#include "flat_sausage_packet.h" -#include "flat_sausage_fetch.h" +#pragma once + +#include "flat_bio_eggs.h" +#include "flat_sausage_packet.h" +#include "flat_sausage_fetch.h" #include <ydb/core/protos/base.pb.h> #include <ydb/core/base/events.h> #include <library/cpp/actors/core/event_local.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { + +namespace NKikimr { +namespace NTabletFlatExecutor { namespace NBlockIO { - - enum class EEv : ui32 { - Base_ = EventSpaceBegin(TKikimrEvents::ES_FLAT_EXECUTOR) + 1088, - - Fetch = Base_ + 0, - Data = Base_ + 1, - Stat = Base_ + 8, - }; - - struct TEvFetch : public TEventLocal<TEvFetch, ui32(EEv::Fetch)> { + + enum class EEv : ui32 { + Base_ = EventSpaceBegin(TKikimrEvents::ES_FLAT_EXECUTOR) + 1088, + + Fetch = Base_ + 0, + Data = Base_ + 1, + Stat = Base_ + 8, + }; + + struct TEvFetch : public TEventLocal<TEvFetch, ui32(EEv::Fetch)> { TEvFetch(EPriority priority, TAutoPtr<NPageCollection::TFetch> fetch) : Priority(priority) - , Fetch(fetch) - { - - } - + , Fetch(fetch) + { + + } + const EPriority Priority = EPriority::None; TAutoPtr<NPageCollection::TFetch> Fetch; - }; - - struct TEvData: public TEventLocal<TEvData, ui32(EEv::Data)> { - using EStatus = NKikimrProto::EReplyStatus; - + }; + + struct TEvData: public TEventLocal<TEvData, ui32(EEv::Data)> { + using EStatus = NKikimrProto::EReplyStatus; + TEvData(TIntrusiveConstPtr<NPageCollection::IPageCollection> origin, ui64 cookie, EStatus status) - : Status(status) - , Cookie(cookie) - , Origin(origin) - { - - } - - void Describe(IOutputStream &out) const - { - out - << "Blocks{" << Blocks.size() << " pages" - << " " << Origin->Label() - << " " << (Status == NKikimrProto::OK ? "ok" : "fail") - << " " << NKikimrProto::EReplyStatus_Name(Status) << "}"; - } - - ui64 Bytes() const - { - return - std::accumulate(Blocks.begin(), Blocks.end(), ui64(0), + : Status(status) + , Cookie(cookie) + , Origin(origin) + { + + } + + void Describe(IOutputStream &out) const + { + out + << "Blocks{" << Blocks.size() << " pages" + << " " << Origin->Label() + << " " << (Status == NKikimrProto::OK ? "ok" : "fail") + << " " << NKikimrProto::EReplyStatus_Name(Status) << "}"; + } + + ui64 Bytes() const + { + return + std::accumulate(Blocks.begin(), Blocks.end(), ui64(0), [](ui64 bytes, const NPageCollection::TLoadedPage& block) { return bytes + block.Data.size(); }); - } - - const EStatus Status; - const ui64 Cookie = Max<ui64>(); + } + + const EStatus Status; + const ui64 Cookie = Max<ui64>(); TIntrusiveConstPtr<NPageCollection::IPageCollection> Origin; TVector<NPageCollection::TLoadedPage> Blocks; - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_bio_stats.h b/ydb/core/tablet_flat/flat_bio_stats.h index 565c0e0886..9be41eb72c 100644 --- a/ydb/core/tablet_flat/flat_bio_stats.h +++ b/ydb/core/tablet_flat/flat_bio_stats.h @@ -1,49 +1,49 @@ -#pragma once - -#include "flat_bio_events.h" +#pragma once + +#include "flat_bio_events.h" #include <ydb/core/tablet/tablet_metrics.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { + +namespace NKikimr { +namespace NTabletFlatExecutor { namespace NBlockIO { - + enum class EDir { Read, Write, }; - struct TEvStat: public TEventLocal<TEvStat, ui32(EEv::Stat)> { - using TByCnGr = std::unordered_map<std::pair<ui8, ui32>, ui64>; - + struct TEvStat: public TEventLocal<TEvStat, ui32(EEv::Stat)> { + using TByCnGr = std::unordered_map<std::pair<ui8, ui32>, ui64>; + TEvStat(EDir dir, EPriority priority, ui32 group, const TLogoBlobID& blobId) - : Dir(dir) + : Dir(dir) , Priority(priority) - , Bytes(blobId.BlobSize()) + , Bytes(blobId.BlobSize()) , Ops(1) - { + { GroupBytes.emplace(std::make_pair(blobId.Channel(), group), Bytes); GroupOps.emplace(std::make_pair(blobId.Channel(), group), Ops); - } - + } + TEvStat(EDir dir, EPriority priority, ui64 bytes, ui64 ops, TByCnGr groupBytes, TByCnGr groupOps) - : Dir(dir) + : Dir(dir) , Priority(priority) - , Bytes(bytes) + , Bytes(bytes) , Ops(ops) , GroupBytes(std::move(groupBytes)) , GroupOps(std::move(groupOps)) - { - - } - + { + + } + const EDir Dir; const EPriority Priority; const ui64 Bytes; const ui64 Ops; TByCnGr GroupBytes; TByCnGr GroupOps; - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_bloom_hash.h b/ydb/core/tablet_flat/flat_bloom_hash.h index 93d7060a16..682c7029b6 100644 --- a/ydb/core/tablet_flat/flat_bloom_hash.h +++ b/ydb/core/tablet_flat/flat_bloom_hash.h @@ -1,79 +1,79 @@ -#pragma once - +#pragma once + #include <library/cpp/containers/stack_vector/stack_vec.h> #include <ydb/core/scheme/scheme_tablecell.h> - -#include <util/digest/murmur.h> - -namespace NKikimr { -namespace NTable { -namespace NBloom { - - class TPrefix : TNonCopyable { - public: - explicit TPrefix(TArrayRef<const TCell> row) - { - ui32 size = 0; - - for (const TCell &cell : row) { - /* ui32 is the size of header */ - Offsets.push_back(size += sizeof(ui32) + cell.Size()); - } - - Buffer.reserve(size); - - for (const TCell &cell : row) { - ui32 sz = cell.IsNull() ? Max<ui32>() : cell.Size(); - Buffer.insert(Buffer.end(), (const char*)&sz, ((const char*)&sz) + sizeof(sz)); - Buffer.insert(Buffer.end(), cell.Data(), cell.Data() + cell.Size()); - } - } - - inline TStringBuf Get(ui32 len) const noexcept - { - Y_VERIFY(len > 0 && len <= Offsets.size()); - - return { Buffer.data(), Buffer.data() + Offsets[len - 1] }; - } - - private: - TSmallVec<char> Buffer; - TSmallVec<ui32> Offsets; - }; - + +#include <util/digest/murmur.h> + +namespace NKikimr { +namespace NTable { +namespace NBloom { + + class TPrefix : TNonCopyable { + public: + explicit TPrefix(TArrayRef<const TCell> row) + { + ui32 size = 0; + + for (const TCell &cell : row) { + /* ui32 is the size of header */ + Offsets.push_back(size += sizeof(ui32) + cell.Size()); + } + + Buffer.reserve(size); + + for (const TCell &cell : row) { + ui32 sz = cell.IsNull() ? Max<ui32>() : cell.Size(); + Buffer.insert(Buffer.end(), (const char*)&sz, ((const char*)&sz) + sizeof(sz)); + Buffer.insert(Buffer.end(), cell.Data(), cell.Data() + cell.Size()); + } + } + + inline TStringBuf Get(ui32 len) const noexcept + { + Y_VERIFY(len > 0 && len <= Offsets.size()); + + return { Buffer.data(), Buffer.data() + Offsets[len - 1] }; + } + + private: + TSmallVec<char> Buffer; + TSmallVec<ui32> Offsets; + }; + struct THashRoot { ui64 Value; }; - class THash { - public: + class THash { + public: explicit THash(THashRoot root) - { - // https://github.com/google/leveldb/blob/master/util/bloom.cc#L54 + { + // https://github.com/google/leveldb/blob/master/util/bloom.cc#L54 Hash = root.Value; - Delta = (Hash >> 33) | (Hash << 31); - } - + Delta = (Hash >> 33) | (Hash << 31); + } + explicit THash(TArrayRef<const char> row) : THash(Root(row)) { } - ui64 Next() noexcept - { - return std::exchange(Hash, Hash + Delta); - } - + ui64 Next() noexcept + { + return std::exchange(Hash, Hash + Delta); + } + static THashRoot Root(TArrayRef<const char> row) noexcept { return THashRoot{ MurmurHash<ui64>(row.data(), row.size(), 0x4b7db4c869874dd1ull) }; } - private: - ui64 Hash = 0; - ui64 Delta = 0; - }; - -} -} -} + private: + ui64 Hash = 0; + ui64 Delta = 0; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_bloom_writer.h b/ydb/core/tablet_flat/flat_bloom_writer.h index 625941a77d..89e0604bb1 100644 --- a/ydb/core/tablet_flat/flat_bloom_writer.h +++ b/ydb/core/tablet_flat/flat_bloom_writer.h @@ -1,130 +1,130 @@ -#pragma once - -#include "flat_page_bloom.h" -#include "flat_bloom_hash.h" -#include "flat_util_binary.h" +#pragma once + +#include "flat_page_bloom.h" +#include "flat_bloom_hash.h" +#include "flat_util_binary.h" #include "util_deref.h" - + #include <ydb/core/base/shared_data.h> -#include <util/generic/ymath.h> -#include <util/system/sanitizers.h> - -namespace NKikimr { -namespace NTable { -namespace NBloom { - +#include <util/generic/ymath.h> +#include <util/system/sanitizers.h> + +namespace NKikimr { +namespace NTable { +namespace NBloom { + class IWriter { - public: + public: virtual ~IWriter() = default; - + virtual void Reset() = 0; virtual ui64 EstimateBytesUsed(size_t extraItems) const = 0; virtual void Add(TArrayRef<const TCell> row) = 0; virtual TSharedData Make() = 0; }; - + class TEstimator { public: TEstimator(float error) { Y_VERIFY(error > 0. && error < 1., "Invalid error estimation, should be in (0, 1)"); - + double log2err = Log2(error); - + Amp = -1.44 * log2err; Y_VERIFY(Amp < 256., "Too high rows amplification factor"); - + HashCount = Min(ui64(Max<ui16>()), ui64(ceil(-log2err))); } - - ui64 Bits(ui64 rows) const noexcept + + ui64 Bits(ui64 rows) const noexcept { Y_VERIFY(!(rows >> 54), "Too many rows, probably an invalid value passed"); - + return ((Max(ui64(ceil(Amp * rows)), ui64(1)) + 63) >> 6) << 6; } - - ui16 Hashes() const noexcept + + ui16 Hashes() const noexcept { return HashCount; } - + private: double Amp; ui16 HashCount; }; - - class TWriter final : public IWriter { + + class TWriter final : public IWriter { public: - TWriter(ui64 rows, float error) + TWriter(ui64 rows, float error) { - TEstimator estimator(error); - Hashes = estimator.Hashes(); - Items = estimator.Bits(rows); - Y_VERIFY(Hashes && Items); - + TEstimator estimator(error); + Hashes = estimator.Hashes(); + Items = estimator.Bits(rows); + Y_VERIFY(Hashes && Items); + Reset(); - } - + } + void Reset() override - { - using THeader = NPage::TBloom::THeader; + { + using THeader = NPage::TBloom::THeader; - ui64 array = (Items >> 6) * sizeof(ui64); - - auto size = sizeof(NPage::TLabel) + sizeof(THeader) + array; + ui64 array = (Items >> 6) * sizeof(ui64); + auto size = sizeof(NPage::TLabel) + sizeof(THeader) + array; + Raw = TSharedData::Uninitialized(size); - + NUtil::NBin::TPut out(Raw.mutable_begin()); - - if (auto *hdr = out.Skip<NPage::TLabel>()) { - hdr->Type = NPage::EPage::Bloom; - hdr->Format = 0; - hdr->Size = size; - } - + + if (auto *hdr = out.Skip<NPage::TLabel>()) { + hdr->Type = NPage::EPage::Bloom; + hdr->Format = 0; + hdr->Size = size; + } + if (auto *post = out.Skip<THeader>()) { Zero(*post); - + post->Type = 0; post->Hashes = Hashes; post->Items = Items; } - + Array = { TDeref<ui64>::At(*out, 0), size_t(Items >> 6) }; Y_VERIFY(size_t(*out) % sizeof(ui64) == 0, "Invalid aligment"); Y_VERIFY(TDeref<char>::At(Array.end(), 0) == Raw.mutable_end()); std::fill(Array.begin(), Array.end(), 0); - } - - ui64 EstimateBytesUsed(size_t) const override - { + } + + ui64 EstimateBytesUsed(size_t) const override + { return Raw.size(); - } - + } + void Add(THashRoot root) - { + { THash hash(root); - + for (ui32 seq = 0; seq++ < Hashes; ) { const ui64 num = hash.Next() % Items; - + Array[num >> 6] |= ui64(1) << (num & 0x3f); - } - } - + } + } + void Add(TArrayRef<const TCell> row) override - { + { const TPrefix prefix(row); Add(THash::Root(prefix.Get(row.size()))); - } - + } + TSharedData Make() override { NSan::CheckMemIsInitialized(Raw.data(), Raw.size()); @@ -132,16 +132,16 @@ namespace NBloom { return std::move(Raw); } - private: - ui32 Hashes = 0; - ui64 Items = 0; + private: + ui32 Hashes = 0; + ui64 Items = 0; TSharedData Raw; - TArrayRef<ui64> Array; - }; - - class TQueue final : public IWriter { + TArrayRef<ui64> Array; + }; + + class TQueue final : public IWriter { public: - TQueue(float error) + TQueue(float error) : Estimator(error) , Error(error) { @@ -156,9 +156,9 @@ namespace NBloom { { using THeader = NPage::TBloom::THeader; - ui64 array = (Estimator.Bits(Roots.size() + extraItems) >> 6) * sizeof(ui64); + ui64 array = (Estimator.Bits(Roots.size() + extraItems) >> 6) * sizeof(ui64); - return sizeof(NPage::TLabel) + sizeof(THeader) + array; + return sizeof(NPage::TLabel) + sizeof(THeader) + array; } void Add(TArrayRef<const TCell> row) override @@ -173,7 +173,7 @@ namespace NBloom { return { }; } - TWriter writer(Roots.size(), Error); + TWriter writer(Roots.size(), Error); for (const auto& root : Roots) { writer.Add(root); } @@ -186,6 +186,6 @@ namespace NBloom { float Error; }; -} -} -} +} +} +} diff --git a/ydb/core/tablet_flat/flat_boot_alter.h b/ydb/core/tablet_flat/flat_boot_alter.h index 2b77a0ea76..b6c61e4089 100644 --- a/ydb/core/tablet_flat/flat_boot_alter.h +++ b/ydb/core/tablet_flat/flat_boot_alter.h @@ -1,94 +1,94 @@ -#pragma once - -#include "flat_boot_iface.h" -#include "flat_boot_back.h" -#include "flat_boot_blobs.h" -#include "flat_dbase_apply.h" -#include "logic_alter_main.h" - +#pragma once + +#include "flat_boot_iface.h" +#include "flat_boot_back.h" +#include "flat_boot_blobs.h" +#include "flat_dbase_apply.h" +#include "logic_alter_main.h" + #include <ydb/core/util/pb.h> -#include <util/generic/xrange.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NBoot { - - class TAlter final: public NBoot::IStep { - public: - using TQueue = TDeque<TBody>; - - TAlter(IStep *owner, TQueue queue) - : IStep(owner, NBoot::EStep::Alter) - , Queue(std::move(queue)) - { - - } - - private: /* IStep, boot logic DSL actor interface */ - void Start() noexcept override - { - for (auto slot: xrange(Queue.size())) +#include <util/generic/xrange.h> + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NBoot { + + class TAlter final: public NBoot::IStep { + public: + using TQueue = TDeque<TBody>; + + TAlter(IStep *owner, TQueue queue) + : IStep(owner, NBoot::EStep::Alter) + , Queue(std::move(queue)) + { + + } + + private: /* IStep, boot logic DSL actor interface */ + void Start() noexcept override + { + for (auto slot: xrange(Queue.size())) if (const auto &largeGlobId = Queue.at(slot).LargeGlobId) Pending += Spawn<TLoadBlobs>(largeGlobId, slot); - - Flush(); - } - + + Flush(); + } + void HandleStep(TIntrusivePtr<IStep> step) noexcept override - { - auto *load = step->ConsumeAs<TLoadBlobs>(Pending); - - if (load->Cookie < Skip || load->Cookie - Skip >= Queue.size()) - Y_FAIL("Got TLoadBlobs result cookie out of queue range"); - - Queue.at(load->Cookie - Skip).Body = load->Plain(); - - Flush(); - } - - private: - void Flush() noexcept - { - for (TBody *head = nullptr; Queue && *(head = &Queue[0]); ) { + { + auto *load = step->ConsumeAs<TLoadBlobs>(Pending); + + if (load->Cookie < Skip || load->Cookie - Skip >= Queue.size()) + Y_FAIL("Got TLoadBlobs result cookie out of queue range"); + + Queue.at(load->Cookie - Skip).Body = load->Plain(); + + Flush(); + } + + private: + void Flush() noexcept + { + for (TBody *head = nullptr; Queue && *(head = &Queue[0]); ) { Apply(head->LargeGlobId, head->Body); - - ++Skip, Queue.pop_front(); - } - + + ++Skip, Queue.pop_front(); + } + Y_VERIFY(Queue || !Pending, "TAlter boot actor has lost entries"); - + if (!Queue) { Env->Finish(this); } - } - + } + void Apply(const NPageCollection::TLargeGlobId &largeGlobId, TArrayRef<const char> body) noexcept - { - if (body) { - TProtoBox<NTable::TSchemeChanges> alter(body); - - NTable::TSchemeModifier apply(*Back->Scheme); - - auto changed = apply.Apply(alter); - - if (auto logl = Env->Logger()->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Back) << " alter log " + { + if (body) { + TProtoBox<NTable::TSchemeChanges> alter(body); + + NTable::TSchemeModifier apply(*Back->Scheme); + + auto changed = apply.Apply(alter); + + if (auto logl = Env->Logger()->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Back) << " alter log " << NFmt::TStamp(NTable::TTxStamp(largeGlobId.Lead).Raw) - << ", " << (changed ? "update" : "noop") - << " affects " << NFmt::Arr(apply.Affects); - } - } - - if (auto *logic = Logic->Result().Alter.Get()) + << ", " << (changed ? "update" : "noop") + << " affects " << NFmt::Arr(apply.Affects); + } + } + + if (auto *logic = Logic->Result().Alter.Get()) logic->RestoreLog(largeGlobId); - } - - private: - TLeft Pending; - ui64 Skip = 0; - TQueue Queue; - }; -} -} -} + } + + private: + TLeft Pending; + ui64 Skip = 0; + TQueue Queue; + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_boot_back.h b/ydb/core/tablet_flat/flat_boot_back.h index b97fc38967..604ff7d1c8 100644 --- a/ydb/core/tablet_flat/flat_boot_back.h +++ b/ydb/core/tablet_flat/flat_boot_back.h @@ -1,116 +1,116 @@ -#pragma once - -#include "defs.h" -#include "flat_dbase_naked.h" -#include "flat_dbase_scheme.h" -#include "flat_boot_switch.h" -#include "flat_boot_oven.h" -#include "logic_snap_waste.h" -#include "logic_redo_queue.h" +#pragma once + +#include "defs.h" +#include "flat_dbase_naked.h" +#include "flat_dbase_scheme.h" +#include "flat_boot_switch.h" +#include "flat_boot_oven.h" +#include "logic_snap_waste.h" +#include "logic_redo_queue.h" #include <ydb/core/base/tablet.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NBoot { - - using TDependency = NKikimr::TEvTablet::TDependencyGraph; - - struct TLogEntry { - TLogEntry() = default; - - TLogEntry(NTable::TTxStamp stamp, TString body) - : Stamp(stamp) - , Body(std::move(body)) - { - - } - + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NBoot { + + using TDependency = NKikimr::TEvTablet::TDependencyGraph; + + struct TLogEntry { + TLogEntry() = default; + + TLogEntry(NTable::TTxStamp stamp, TString body) + : Stamp(stamp) + , Body(std::move(body)) + { + + } + TLogEntry(NTable::TTxStamp stamp, NPageCollection::TLargeGlobId largeGlobId) - : Stamp(stamp) + : Stamp(stamp) , LargeGlobId(largeGlobId) - { - - } - - explicit operator bool() const noexcept - { - return bool(Body); - } - - const NTable::TTxStamp Stamp; + { + + } + + explicit operator bool() const noexcept + { + return bool(Body); + } + + const NTable::TTxStamp Stamp; const NPageCollection::TLargeGlobId LargeGlobId; - TString Body; - }; - - struct TBody { - void Describe(IOutputStream &out) const noexcept - { - out + TString Body; + }; + + struct TBody { + void Describe(IOutputStream &out) const noexcept + { + out << "Body{ " << NFmt::Do(LargeGlobId) - << " has " << Body.size() << "b }"; - } - - explicit operator bool() const noexcept - { - return bool(Body); - } - + << " has " << Body.size() << "b }"; + } + + explicit operator bool() const noexcept + { + return bool(Body); + } + const NPageCollection::TLargeGlobId LargeGlobId; - TString Body; - }; - - struct TBack { + TString Body; + }; + + struct TBack { TBack(bool follower, ui64 tablet, ui32 generation) : Follower(follower) - , Tablet(tablet) - , Generation(generation) - { - - } - - void Describe(IOutputStream &out) const noexcept - { - out + , Tablet(tablet) + , Generation(generation) + { + + } + + void Describe(IOutputStream &out) const noexcept + { + out << (Follower ? "Follower" : "Leader") - << "{" << Tablet << ":" << Generation << ":-}"; - } - - void SetTableEdge(const NKikimrExecutorFlat::TLogMemSnap &edge) - { - const ui64 stamp = TTxStamp(edge.GetGeneration(), edge.GetStep()); + << "{" << Tablet << ":" << Generation << ":-}"; + } + + void SetTableEdge(const NKikimrExecutorFlat::TLogMemSnap &edge) + { + const ui64 stamp = TTxStamp(edge.GetGeneration(), edge.GetStep()); const NTable::TEpoch epoch(edge.HasHead() ? edge.GetHead() : 0); - - Y_VERIFY(stamp != Max<ui64>(), "Undefined TxStamp of snapshot"); - - auto &last = Edges[edge.GetTable()]; - - last.TxStamp = Max(last.TxStamp, stamp); + + Y_VERIFY(stamp != Max<ui64>(), "Undefined TxStamp of snapshot"); + + auto &last = Edges[edge.GetTable()]; + + last.TxStamp = Max(last.TxStamp, stamp); last.Head = Max(last.Head, epoch); - } - + } + const bool Follower = false; - const ui64 Tablet = Max<ui64>(); - const ui32 Generation = Max<ui32>(); - - ui64 Serial = 0; - + const ui64 Tablet = Max<ui64>(); + const ui32 Generation = Max<ui32>(); + + ui64 Serial = 0; + TAutoPtr<NBoot::TSteppedCookieAllocatorFactory> SteppedCookieAllocatorFactory; TIntrusivePtr<NSnap::TWaste> Waste; TAutoPtr<NTable::TScheme> Scheme; TAutoPtr<NTable::TDatabaseImpl> DatabaseImpl; TAutoPtr<NRedo::TQueue> Redo; NPageCollection::TLargeGlobId Snap; - TDeque<TLogEntry> RedoLog; - TDeque<TBody> GCELog; - TDeque<TBody> LoansLog; - TDeque<TBody> AlterLog; - TDeque<TBody> TurnsLog; - TDeque<TSwitch> Switches; - THashMap<ui32, NTable::TSnapEdge> Edges; + TDeque<TLogEntry> RedoLog; + TDeque<TBody> GCELog; + TDeque<TBody> LoansLog; + TDeque<TBody> AlterLog; + TDeque<TBody> TurnsLog; + TDeque<TSwitch> Switches; + THashMap<ui32, NTable::TSnapEdge> Edges; THashMap<TLogoBlobID, TIntrusivePtr<TPrivatePageCache::TInfo>> PageCaches; THashMap<TLogoBlobID, TSharedData> TxStatusCaches; - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_boot_blobs.h b/ydb/core/tablet_flat/flat_boot_blobs.h index 098d0fed5d..d5c456047a 100644 --- a/ydb/core/tablet_flat/flat_boot_blobs.h +++ b/ydb/core/tablet_flat/flat_boot_blobs.h @@ -1,61 +1,61 @@ -#pragma once -#include "defs.h" - -#include "flat_boot_iface.h" -#include "flat_sausage_solid.h" +#pragma once +#include "defs.h" + +#include "flat_boot_iface.h" +#include "flat_sausage_solid.h" #include <ydb/core/base/logoblob.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { - - class TExecutorBootLogic; - -namespace NBoot { - - class TLoadBlobs: public NBoot::IStep { - public: + +namespace NKikimr { +namespace NTabletFlatExecutor { + + class TExecutorBootLogic; + +namespace NBoot { + + class TLoadBlobs: public NBoot::IStep { + public: using TBlobIds = TVector<TLogoBlobID>; - - static constexpr NBoot::EStep StepKind = NBoot::EStep::Blobs; - - TLoadBlobs() = default; + + static constexpr NBoot::EStep StepKind = NBoot::EStep::Blobs; + + TLoadBlobs() = default; TLoadBlobs(IStep *owner, NPageCollection::TLargeGlobId largeGlobId, ui64 cookie); - - ~TLoadBlobs() - { - Y_VERIFY(!RefCount(), "TLoadBlobs is still referenced somewhere"); - } - - void Start() noexcept override { } - + + ~TLoadBlobs() + { + Y_VERIFY(!RefCount(), "TLoadBlobs is still referenced somewhere"); + } + + void Start() noexcept override { } + void Feed(TLogoBlobID blobId, TString body) - { + { if (State.Apply(blobId, std::move(body)) && Env) Env->Finish(this); - } - + } + const TVector<TLogoBlobID> Blobs() const - { + { return State.GetBlobs(); - } - + } + TString Plain() - { + { return State.ExtractString(); - } - + } + TSharedData PlainData() { return State.ExtractSharedData(); } - public: - const ui64 Cookie = Max<ui64>(); + public: + const ui64 Cookie = Max<ui64>(); NPageCollection::TLargeGlobId LargeGlobId; /* new method of holding blobs range */ - - private: + + private: NPageCollection::TLargeGlobIdRestoreState State; - }; -} -} -} + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_boot_bundle.h b/ydb/core/tablet_flat/flat_boot_bundle.h index ecdec63649..9417daba05 100644 --- a/ydb/core/tablet_flat/flat_boot_bundle.h +++ b/ydb/core/tablet_flat/flat_boot_bundle.h @@ -1,111 +1,111 @@ -#pragma once - -#include "flat_boot_iface.h" -#include "flat_boot_back.h" -#include "flat_boot_blobs.h" -#include "flat_bio_events.h" -#include "flat_sausage_packet.h" -#include "flat_part_loader.h" -#include "flat_dbase_naked.h" - -#include <util/generic/xrange.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NBoot { - +#pragma once + +#include "flat_boot_iface.h" +#include "flat_boot_back.h" +#include "flat_boot_blobs.h" +#include "flat_bio_events.h" +#include "flat_sausage_packet.h" +#include "flat_part_loader.h" +#include "flat_dbase_naked.h" + +#include <util/generic/xrange.h> + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NBoot { + class TBundleLoadStep final: public NBoot::IStep { - public: + public: using TCache = TPrivatePageCache::TInfo; - - static constexpr NBoot::EStep StepKind = NBoot::EStep::Bundle; - + + static constexpr NBoot::EStep StepKind = NBoot::EStep::Bundle; + TBundleLoadStep() = delete; - + TBundleLoadStep(IStep *owner, ui32 table, TSwitch::TBundle &bundle) - : IStep(owner, NBoot::EStep::Bundle) + : IStep(owner, NBoot::EStep::Bundle) , Table(table) , LargeGlobIds(std::move(bundle.LargeGlobIds)) - , Legacy(std::move(bundle.Legacy)) + , Legacy(std::move(bundle.Legacy)) , Opaque(std::move(bundle.Opaque)) , Deltas(std::move(bundle.Deltas)) , Epoch(bundle.Epoch) - { - - } - - private: /* IStep, boot logic DSL actor interface */ - void Start() noexcept override - { + { + + } + + private: /* IStep, boot logic DSL actor interface */ + void Start() noexcept override + { PageCollections.resize(LargeGlobIds.size()); - + for (auto slot: xrange(LargeGlobIds.size())) { if (auto *info = Back->PageCaches.FindPtr(LargeGlobIds[slot].Lead)) { PageCollections[slot] = *info; - } else { + } else { LeftMetas += Spawn<TLoadBlobs>(LargeGlobIds[slot], slot); - } - } - - TryLoad(); - } - + } + } + + TryLoad(); + } + bool HandleBio(NSharedCache::TEvResult &msg) noexcept override - { + { Y_VERIFY(Loader, "PageCollections loader got un unexpected pages fetch"); - + LeftReads -= 1; - if (msg.Status == NKikimrProto::OK) { + if (msg.Status == NKikimrProto::OK) { Loader->Save(msg.Cookie, msg.Loaded); - - TryFinalize(); - - } else if (auto logl = Env->Logger()->Log(ELnLev::Error)) { - logl - << NFmt::Do(*Back) + + TryFinalize(); + + } else if (auto logl = Env->Logger()->Log(ELnLev::Error)) { + logl + << NFmt::Do(*Back) << " Page collection load failed, " << NFmt::Do(msg); - } - - return msg.Status == NKikimrProto::OK; - } - + } + + return msg.Status == NKikimrProto::OK; + } + void HandleStep(TIntrusivePtr<IStep> step) noexcept override - { - auto *load = step->ConsumeAs<TLoadBlobs>(LeftMetas); - - if (Loader) { - Y_FAIL("Got an unexpected load blobs result"); + { + auto *load = step->ConsumeAs<TLoadBlobs>(LeftMetas); + + if (Loader) { + Y_FAIL("Got an unexpected load blobs result"); } else if (load->Cookie >= PageCollections.size()) { - Y_FAIL("Got blobs load step with an invalid cookie"); + Y_FAIL("Got blobs load step with an invalid cookie"); } else if (PageCollections[load->Cookie]) { Y_FAIL("Page collection is already loaded at room %zu", load->Cookie); - } else { + } else { auto *pack = new NPageCollection::TPageCollection(load->LargeGlobId, load->PlainData()); - + PageCollections[load->Cookie] = new TPrivatePageCache::TInfo(pack); - } - - TryLoad(); - } - - private: - void TryLoad() - { - if (!LeftMetas) { + } + + TryLoad(); + } + + private: + void TryLoad() + { + if (!LeftMetas) { Loader = new NTable::TLoader( std::move(PageCollections), - std::move(Legacy), + std::move(Legacy), std::move(Opaque), std::move(Deltas), Epoch); - - TryFinalize(); - } - } - - void TryFinalize() - { + + TryFinalize(); + } + } + + void TryFinalize() + { if (!LeftReads) { for (auto req : Loader->Run()) { LeftReads += Logic->LoadPages(this, req); @@ -115,47 +115,47 @@ namespace NBoot { if (!LeftReads) { NTable::TPartView partView = Loader->Result(); - if (auto logl = Env->Logger()->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Back) << " table " << Table + if (auto logl = Env->Logger()->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Back) << " table " << Table << " part loaded, page collections ["; - + for (auto &cache : partView.As<NTable::TPartStore>()->PageCollections) - logl << " " << cache->Id; - - logl << " ]"; - } - + logl << " " << cache->Id; + + logl << " ]"; + } + PropagateSideEffects(partView); Back->DatabaseImpl->Merge(Table, std::move(partView)); - + Env->Finish(this); /* return self to owner */ - } - } - + } + } + void PropagateSideEffects(const NTable::TPartView &partView) - { + { for (auto &cache : partView.As<NTable::TPartStore>()->PageCollections) Logic->Result().PageCaches.push_back(cache); - + if (auto &cache = partView.As<NTable::TPartStore>()->Pseudo) Logic->Result().PageCaches.push_back(cache); - } - - private: - const ui32 Table = Max<ui32>(); - + } + + private: + const ui32 Table = Max<ui32>(); + TAutoPtr<NTable::TLoader> Loader; TVector<NPageCollection::TLargeGlobId> LargeGlobIds; TVector<TIntrusivePtr<TCache>> PageCollections; - TString Legacy; + TString Legacy; TString Opaque; TVector<TString> Deltas; NTable::TEpoch Epoch; - - TLeft LeftMetas; - TLeft LeftReads; - }; -} -} -} + + TLeft LeftMetas; + TLeft LeftReads; + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_boot_cookie.h b/ydb/core/tablet_flat/flat_boot_cookie.h index 58e810325a..b8c8bc6ff9 100644 --- a/ydb/core/tablet_flat/flat_boot_cookie.h +++ b/ydb/core/tablet_flat/flat_boot_cookie.h @@ -1,73 +1,73 @@ -#pragma once -#include "flat_sausage_grind.h" - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NBoot { - - struct TCookie { - const static ui32 OffType = 20; - const static ui32 OffIdx = 12; - - const static ui32 MaskType = 0xc00000; - const static ui32 MaskIdx = 0x3ff000; - const static ui32 MaskSub = 0x000fff; - - enum class EType : ui8 { - Log = 0, /* Regular executor blob */ - }; - - enum class EIdx : ui32 { - Snap = 0, /* Legacy, now is unused */ - Redo = 1, /* DBase redo log flow */ - Alter = 2, /* DBase scheme TAlter log */ +#pragma once +#include "flat_sausage_grind.h" + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NBoot { + + struct TCookie { + const static ui32 OffType = 20; + const static ui32 OffIdx = 12; + + const static ui32 MaskType = 0xc00000; + const static ui32 MaskIdx = 0x3ff000; + const static ui32 MaskSub = 0x000fff; + + enum class EType : ui8 { + Log = 0, /* Regular executor blob */ + }; + + enum class EIdx : ui32 { + Snap = 0, /* Legacy, now is unused */ + Redo = 1, /* DBase redo log flow */ + Alter = 2, /* DBase scheme TAlter log */ Pack = 3, /* NPageCollection metablobs */ - Turn = 5, /* Data transmutations log */ - RedoLz4 = 6, - SnapLz4 = 7, /* TExecutor state snapshot */ - TurnLz4 = 8, - Loan = 9, /* Borrow logic changes log */ - GCExt = 10, /* Extended GC logic log */ - - Raw = 17, /* Uniform space [Raw, End] */ - End = 0x3ff - }; - - static_assert(MaskType ^ MaskIdx ^ MaskSub == 0xffffff, ""); - static_assert((MaskIdx >> OffIdx) == ui32(EIdx::End), ""); - - TCookie(ui32 raw) : Raw(raw) { } - - TCookie(EType type, EIdx index, ui32 sub) - : Raw((ui32(type) << OffType) | (ui32(index) << OffIdx) | sub) - { - Y_VERIFY(sub <= MaskSub, "TCookue sub value is out of capacity"); - } - - EType Type() const { return EType((Raw & MaskType) >> OffType); } - EIdx Index() const { return EIdx((Raw & MaskIdx) >> OffIdx); } - ui32 Sub() const { return (Raw & MaskSub); } - + Turn = 5, /* Data transmutations log */ + RedoLz4 = 6, + SnapLz4 = 7, /* TExecutor state snapshot */ + TurnLz4 = 8, + Loan = 9, /* Borrow logic changes log */ + GCExt = 10, /* Extended GC logic log */ + + Raw = 17, /* Uniform space [Raw, End] */ + End = 0x3ff + }; + + static_assert(MaskType ^ MaskIdx ^ MaskSub == 0xffffff, ""); + static_assert((MaskIdx >> OffIdx) == ui32(EIdx::End), ""); + + TCookie(ui32 raw) : Raw(raw) { } + + TCookie(EType type, EIdx index, ui32 sub) + : Raw((ui32(type) << OffType) | (ui32(index) << OffIdx) | sub) + { + Y_VERIFY(sub <= MaskSub, "TCookue sub value is out of capacity"); + } + + EType Type() const { return EType((Raw & MaskType) >> OffType); } + EIdx Index() const { return EIdx((Raw & MaskIdx) >> OffIdx); } + ui32 Sub() const { return (Raw & MaskSub); } + static NPageCollection::TCookieRange CookieRange(EIdx index) noexcept - { - return { RawFor(index, 0), RawFor(index, Max<ui32>()) }; - } - + { + return { RawFor(index, 0), RawFor(index, Max<ui32>()) }; + } + static NPageCollection::TCookieRange CookieRangeRaw() noexcept - { - return { RawFor(EIdx::Raw, 0), RawFor(EIdx::End, Max<ui32>()) }; - } - - static ui32 RawFor(EIdx type, ui32 offset) noexcept - { - offset = Min(offset, ui32(MaskSub)); - - return TCookie(EType::Log, type, offset).Raw; - } - - const ui32 Raw = 0; /* only lower 24 bits are used */ - }; - -} -} -} + { + return { RawFor(EIdx::Raw, 0), RawFor(EIdx::End, Max<ui32>()) }; + } + + static ui32 RawFor(EIdx type, ui32 offset) noexcept + { + offset = Min(offset, ui32(MaskSub)); + + return TCookie(EType::Log, type, offset).Raw; + } + + const ui32 Raw = 0; /* only lower 24 bits are used */ + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_boot_env.h b/ydb/core/tablet_flat/flat_boot_env.h index 48adb0ac6d..f5885a8c11 100644 --- a/ydb/core/tablet_flat/flat_boot_env.h +++ b/ydb/core/tablet_flat/flat_boot_env.h @@ -1,59 +1,59 @@ -#pragma once - -#include "util_fmt_line.h" -#include "flat_boot_iface.h" -#include <util/system/yassert.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NBoot { - - class TRoot : public IEnv, private IStep { - public: +#pragma once + +#include "util_fmt_line.h" +#include "flat_boot_iface.h" +#include <util/system/yassert.h> + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NBoot { + + class TRoot : public IEnv, private IStep { + public: TRoot(TLogic *logic, TBack *state, TAutoPtr<NUtil::ILogger> logger) - : IStep(logic, state) - , Logger_(logger) - { - Ref(); /* Prevent deletion on child IStep-s destruction */ - } - - ~TRoot() - { + : IStep(logic, state) + , Logger_(logger) + { + Ref(); /* Prevent deletion on child IStep-s destruction */ + } + + ~TRoot() + { Y_VERIFY(RefCount() == 1, "Boot env shouldn't be deleted by TIntrusivePtr"); - } - - const NUtil::ILogger* Logger() const noexcept override - { - return Logger_.Get(); - } - - void Describe(IOutputStream &out) const noexcept override - { - out - << "Boot{ " << Queue.size() << " que" - << ", " << RefCount() << " refs }"; - } - - bool Alone() const - { - return RefCount() <= 1 && !Queue; - } - - template<typename TStep, typename ... TArgs> - void Spawn(TArgs&& ... args) - { + } + + const NUtil::ILogger* Logger() const noexcept override + { + return Logger_.Get(); + } + + void Describe(IOutputStream &out) const noexcept override + { + out + << "Boot{ " << Queue.size() << " que" + << ", " << RefCount() << " refs }"; + } + + bool Alone() const + { + return RefCount() <= 1 && !Queue; + } + + template<typename TStep, typename ... TArgs> + void Spawn(TArgs&& ... args) + { Start(new TStep(this, std::forward<TArgs>(args)...)); - } - - void Execute() noexcept - { - for (; Queue; Queue.pop_front()) { + } + + void Execute() noexcept + { + for (; Queue; Queue.pop_front()) { auto order = std::move(Queue.front()); - + switch (order.Op) { case EOp::Start: { *const_cast<IEnv**>(&order.Step->Env) = this; - + order.Step->Start(); break; } @@ -64,50 +64,50 @@ namespace NBoot { owner->HandleStep(std::move(order.Step)); break; } - } - } - } - - protected: - void Start() noexcept override { } - + } + } + } + + protected: + void Start() noexcept override { } + void Start(TIntrusivePtr<IStep> step) noexcept override - { - Y_VERIFY(step->Env == nullptr, "IStep is already fired"); + { + Y_VERIFY(step->Env == nullptr, "IStep is already fired"); Y_VERIFY(step->Owner, "Start called on step without an owner"); - + Queue.emplace_back(EOp::Start, std::move(step)); - } - + } + void Finish(TIntrusivePtr<IStep> step) noexcept override - { + { Y_VERIFY(step, "Finish called without a step"); Y_VERIFY(step->Owner, "Finish called on step without an owner"); Queue.emplace_back(EOp::Finish, std::move(step)); - } - - private: + } + + private: enum class EOp { Start, Finish, }; - struct TOrder { + struct TOrder { TOrder(EOp op, TIntrusivePtr<IStep> step) : Op(op) - , Step(std::move(step)) - { - - } - + , Step(std::move(step)) + { + + } + const EOp Op; TIntrusivePtr<IStep> Step; - }; - + }; + TAutoPtr<NUtil::ILogger> Logger_; - TDeque<TOrder> Queue; - }; -} -} -} + TDeque<TOrder> Queue; + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_boot_gclog.h b/ydb/core/tablet_flat/flat_boot_gclog.h index ced4c72265..d946ab8152 100644 --- a/ydb/core/tablet_flat/flat_boot_gclog.h +++ b/ydb/core/tablet_flat/flat_boot_gclog.h @@ -1,88 +1,88 @@ -#pragma once - -#include "flat_boot_iface.h" -#include "flat_boot_back.h" -#include "flat_boot_blobs.h" -#include "flat_bio_events.h" - +#pragma once + +#include "flat_boot_iface.h" +#include "flat_boot_back.h" +#include "flat_boot_blobs.h" +#include "flat_bio_events.h" + #include <ydb/core/util/pb.h> #include <library/cpp/blockcodecs/codecs.h> -#include <util/generic/xrange.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NBoot { - - class TGCLog final: public NBoot::IStep { - public: - using TQueue = TDeque<TBody>; - - TGCLog(IStep *owner, TQueue queue) - : IStep(owner, NBoot::EStep::GCELog) - , Codec(NBlockCodecs::Codec("lz4fast")) - , Queue(std::move(queue)) - { - - } - - private: /* IStep, boot logic DSL actor interface */ - void Start() noexcept override - { - for (auto slot: xrange(Queue.size())) +#include <util/generic/xrange.h> + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NBoot { + + class TGCLog final: public NBoot::IStep { + public: + using TQueue = TDeque<TBody>; + + TGCLog(IStep *owner, TQueue queue) + : IStep(owner, NBoot::EStep::GCELog) + , Codec(NBlockCodecs::Codec("lz4fast")) + , Queue(std::move(queue)) + { + + } + + private: /* IStep, boot logic DSL actor interface */ + void Start() noexcept override + { + for (auto slot: xrange(Queue.size())) if (const auto &largeGlobId = Queue.at(slot).LargeGlobId) Pending += Spawn<TLoadBlobs>(largeGlobId, slot); - - Flush(); - } - + + Flush(); + } + void HandleStep(TIntrusivePtr<IStep> step) noexcept override - { - auto *load = step->ConsumeAs<TLoadBlobs>(Pending); - - if (load->Cookie < Skip || load->Cookie - Skip >= Queue.size()) - Y_FAIL("Got TLoadBlobs result cookie out of queue range"); - - Queue.at(load->Cookie - Skip).Body = load->Plain(); - - Flush(); - } - - private: - void Flush() noexcept - { - for (TBody *head = nullptr; Queue && *(head = &Queue[0]); ) { + { + auto *load = step->ConsumeAs<TLoadBlobs>(Pending); + + if (load->Cookie < Skip || load->Cookie - Skip >= Queue.size()) + Y_FAIL("Got TLoadBlobs result cookie out of queue range"); + + Queue.at(load->Cookie - Skip).Body = load->Plain(); + + Flush(); + } + + private: + void Flush() noexcept + { + for (TBody *head = nullptr; Queue && *(head = &Queue[0]); ) { auto gen = head->LargeGlobId.Lead.Generation(); auto step = head->LargeGlobId.Lead.Step(); - - Apply(gen, step, Codec->Decode(head->Body)); - - ++Skip, Queue.pop_front(); - } - + + Apply(gen, step, Codec->Decode(head->Body)); + + ++Skip, Queue.pop_front(); + } + Y_VERIFY(Queue || !Pending, "TGCLog boot actor has lost entries"); - + if (!Queue) { Env->Finish(this); } - } - + } + void Apply(ui32 gen, ui32 step, TArrayRef<const char> body) noexcept - { - TProtoBox<NKikimrExecutorFlat::TExternalGcEntry> proto(body); - - TGCLogEntry gcx(TGCTime(gen, step)); - LogoBlobIDVectorFromLogoBlobIDRepeated(&gcx.Delta.Created, proto.GetGcDiscovered()); - LogoBlobIDVectorFromLogoBlobIDRepeated(&gcx.Delta.Deleted, proto.GetGcLeft()); - Back->Waste->Account(gcx.Delta); - Logic->Result().GcLogic->ApplyLogEntry(gcx); - } - - private: - const NBlockCodecs::ICodec *Codec = nullptr; - TLeft Pending; - ui64 Skip = 0; - TQueue Queue; - }; -} -} -} + { + TProtoBox<NKikimrExecutorFlat::TExternalGcEntry> proto(body); + + TGCLogEntry gcx(TGCTime(gen, step)); + LogoBlobIDVectorFromLogoBlobIDRepeated(&gcx.Delta.Created, proto.GetGcDiscovered()); + LogoBlobIDVectorFromLogoBlobIDRepeated(&gcx.Delta.Deleted, proto.GetGcLeft()); + Back->Waste->Account(gcx.Delta); + Logic->Result().GcLogic->ApplyLogEntry(gcx); + } + + private: + const NBlockCodecs::ICodec *Codec = nullptr; + TLeft Pending; + ui64 Skip = 0; + TQueue Queue; + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_boot_iface.h b/ydb/core/tablet_flat/flat_boot_iface.h index 14ecc59e21..a30b6d6728 100644 --- a/ydb/core/tablet_flat/flat_boot_iface.h +++ b/ydb/core/tablet_flat/flat_boot_iface.h @@ -1,31 +1,31 @@ -#pragma once - -#include "flat_boot_util.h" -#include "flat_bio_events.h" +#pragma once + +#include "flat_boot_util.h" +#include "flat_bio_events.h" #include "shared_cache_events.h" -#include "util_fmt_logger.h" -#include "util_fmt_desc.h" +#include "util_fmt_logger.h" +#include "util_fmt_desc.h" #include "util_basics.h" -#include "util_fmt_abort.h" -#include <util/system/yassert.h> - -#include <typeinfo> - -namespace NKikimr { -namespace NTabletFlatExecutor { - class TExecutorBootLogic; - -namespace NBoot { - struct TBack; - class IStep; - class TRoot; - - using ELnLev = NUtil::ELnLev; - - enum class EStep { - None = 0, +#include "util_fmt_abort.h" +#include <util/system/yassert.h> + +#include <typeinfo> + +namespace NKikimr { +namespace NTabletFlatExecutor { + class TExecutorBootLogic; + +namespace NBoot { + struct TBack; + class IStep; + class TRoot; + + using ELnLev = NUtil::ELnLev; + + enum class EStep { + None = 0, Blobs = 1, // Generic blobs loader tool (like NBlockIO) - Stages = 2, + Stages = 2, Bundle = 3, // DB bundles (parts) loader and merger Redo = 4, // DB Redo log queue loader and applier MemTable= 5, // Loader of external TMemTable blobs to cache @@ -35,89 +35,89 @@ namespace NBoot { Turns = 9, // Bundles switch (turns) log processing Snap = 10, // Log snapshot and deps graph processor TxStatus = 11, // TxStatus data loader and merger - }; - - struct IEnv { - virtual const NUtil::ILogger* Logger() const noexcept = 0; - virtual void Describe(IOutputStream&) const noexcept = 0; + }; + + struct IEnv { + virtual const NUtil::ILogger* Logger() const noexcept = 0; + virtual void Describe(IOutputStream&) const noexcept = 0; virtual void Start(TIntrusivePtr<IStep>) noexcept = 0; virtual void Finish(TIntrusivePtr<IStep>) noexcept = 0; - }; - - class IStep : public TSimpleRefCount<IStep> { - friend class TRoot; - - public: - using TLogic = TExecutorBootLogic; - - IStep() = default; - - IStep(TLogic *logic, TBack *state) - : Logic(logic) - , Back(state) - { - - } - - IStep(IStep *owner, EStep kind) - : Kind__(kind) - , Owner(owner) - , Logic(owner->Logic) - , Back(owner->Back) - { - Y_VERIFY(Owner != this, "Boot IStep Cannot be on its own"); - } - - virtual ~IStep() = default; - - virtual void Start() noexcept = 0; - + }; + + class IStep : public TSimpleRefCount<IStep> { + friend class TRoot; + + public: + using TLogic = TExecutorBootLogic; + + IStep() = default; + + IStep(TLogic *logic, TBack *state) + : Logic(logic) + , Back(state) + { + + } + + IStep(IStep *owner, EStep kind) + : Kind__(kind) + , Owner(owner) + , Logic(owner->Logic) + , Back(owner->Back) + { + Y_VERIFY(Owner != this, "Boot IStep Cannot be on its own"); + } + + virtual ~IStep() = default; + + virtual void Start() noexcept = 0; + virtual bool HandleBio(NSharedCache::TEvResult&) noexcept - { + { Y_FAIL("Boot IStep got an unhandled NSharedCache::TEvResult event"); - } - + } + virtual void HandleStep(TIntrusivePtr<IStep>) noexcept - { - Y_FAIL("Boot IStep got an unhandled child step result"); - } - - template<typename TStep, typename ... TArgs> + { + Y_FAIL("Boot IStep got an unhandled child step result"); + } + + template<typename TStep, typename ... TArgs> TSpawned Spawn(TArgs&& ... args) - { + { Env->Start(new TStep(this, std::forward<TArgs>(args)...)); - + return TSpawned(true); - } - - template<typename TStep> - TStep* ConsumeAs(TLeft &left) - { - left -= 1; /* may be it is better to track TLeft in step */ - - return FinalCast<TStep>(true); - } - - template<typename TStep> - TStep* FinalCast(bool require = true) - { - if (typeid(*this) == typeid(TStep)) { - return static_cast<TStep*>(this); - } else if (require) { - Y_FAIL("Cannot cast IStep to particular unit"); - } else { - return nullptr; - } - } - - protected: - const EStep Kind__ = EStep::None; + } + + template<typename TStep> + TStep* ConsumeAs(TLeft &left) + { + left -= 1; /* may be it is better to track TLeft in step */ + + return FinalCast<TStep>(true); + } + + template<typename TStep> + TStep* FinalCast(bool require = true) + { + if (typeid(*this) == typeid(TStep)) { + return static_cast<TStep*>(this); + } else if (require) { + Y_FAIL("Cannot cast IStep to particular unit"); + } else { + return nullptr; + } + } + + protected: + const EStep Kind__ = EStep::None; const TIntrusivePtr<IStep> Owner; - TLogic * const Logic = nullptr; - TBack * const Back = nullptr; - IEnv * const Env = nullptr; - }; - -} -} -} + TLogic * const Logic = nullptr; + TBack * const Back = nullptr; + IEnv * const Env = nullptr; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_boot_loans.h b/ydb/core/tablet_flat/flat_boot_loans.h index d4a98224ac..6cd29ed17a 100644 --- a/ydb/core/tablet_flat/flat_boot_loans.h +++ b/ydb/core/tablet_flat/flat_boot_loans.h @@ -1,81 +1,81 @@ -#pragma once - -#include "flat_boot_iface.h" -#include "flat_boot_back.h" -#include "flat_boot_blobs.h" -#include "flat_executor_borrowlogic.h" - +#pragma once + +#include "flat_boot_iface.h" +#include "flat_boot_back.h" +#include "flat_boot_blobs.h" +#include "flat_executor_borrowlogic.h" + #include <ydb/core/util/pb.h> #include <library/cpp/blockcodecs/codecs.h> -#include <util/generic/xrange.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NBoot { - - class TLoans final: public NBoot::IStep { - public: - using TQueue = TDeque<TBody>; - - TLoans(IStep *owner, TQueue queue) - : IStep(owner, NBoot::EStep::Loans) - , Codec(NBlockCodecs::Codec("lz4fast")) - , Queue(std::move(queue)) - { - - } - - private: /* IStep, boot logic DSL actor interface */ - void Start() noexcept override - { - for (auto slot: xrange(Queue.size())) +#include <util/generic/xrange.h> + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NBoot { + + class TLoans final: public NBoot::IStep { + public: + using TQueue = TDeque<TBody>; + + TLoans(IStep *owner, TQueue queue) + : IStep(owner, NBoot::EStep::Loans) + , Codec(NBlockCodecs::Codec("lz4fast")) + , Queue(std::move(queue)) + { + + } + + private: /* IStep, boot logic DSL actor interface */ + void Start() noexcept override + { + for (auto slot: xrange(Queue.size())) if (const auto &largeGlobId = Queue.at(slot).LargeGlobId) Pending += Spawn<TLoadBlobs>(largeGlobId, slot); - - Flush(); - } - + + Flush(); + } + void HandleStep(TIntrusivePtr<IStep> step) noexcept override - { - auto *load = step->ConsumeAs<TLoadBlobs>(Pending); - - if (load->Cookie < Skip || load->Cookie - Skip >= Queue.size()) - Y_FAIL("Got TLoadBlobs result cookie out of queue range"); - - Queue.at(load->Cookie - Skip).Body = load->Plain(); - - Flush(); - } - - private: - void Flush() noexcept - { - for (TBody *head = nullptr; Queue && *(head = &Queue[0]); ) { + { + auto *load = step->ConsumeAs<TLoadBlobs>(Pending); + + if (load->Cookie < Skip || load->Cookie - Skip >= Queue.size()) + Y_FAIL("Got TLoadBlobs result cookie out of queue range"); + + Queue.at(load->Cookie - Skip).Body = load->Plain(); + + Flush(); + } + + private: + void Flush() noexcept + { + for (TBody *head = nullptr; Queue && *(head = &Queue[0]); ) { Apply(head->LargeGlobId.Lead, Codec->Decode(head->Body)); - - ++Skip, Queue.pop_front(); - } - + + ++Skip, Queue.pop_front(); + } + Y_VERIFY(Queue || !Pending, "TLoans boot actor has lost entries"); - + if (!Queue) { Env->Finish(this); } - } - + } + void Apply(const TLogoBlobID &label, TArrayRef<const char> body) noexcept - { - TProtoBox<NKikimrExecutorFlat::TBorrowedPart> proto(body); - - Logic->Result().Loans->RestoreBorrowedInfo(label, proto); - } - - private: - const NBlockCodecs::ICodec *Codec = nullptr; - TLeft Pending; - ui64 Skip = 0; - TQueue Queue; - }; -} -} -} + { + TProtoBox<NKikimrExecutorFlat::TBorrowedPart> proto(body); + + Logic->Result().Loans->RestoreBorrowedInfo(label, proto); + } + + private: + const NBlockCodecs::ICodec *Codec = nullptr; + TLeft Pending; + ui64 Skip = 0; + TQueue Queue; + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_boot_misc.cpp b/ydb/core/tablet_flat/flat_boot_misc.cpp index e8ca8c203e..803509b3f3 100644 --- a/ydb/core/tablet_flat/flat_boot_misc.cpp +++ b/ydb/core/tablet_flat/flat_boot_misc.cpp @@ -1,25 +1,25 @@ -#include "flat_executor_bootlogic.h" -#include "flat_boot_stages.h" -#include "flat_boot_back.h" +#include "flat_executor_bootlogic.h" +#include "flat_boot_stages.h" +#include "flat_boot_back.h" #include "flat_exec_commit_mgr.h" -#include "logic_snap_main.h" -#include "flat_executor_txloglogic.h" - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NBoot { - +#include "logic_snap_main.h" +#include "flat_executor_txloglogic.h" + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NBoot { + void TStages::FinalizeLeaderLogics(TResult &result, TSteppedCookieAllocatorFactory &steppedCookieAllocatorFactory) noexcept -{ - using EIdx = TCookie::EIdx; - - auto *waste = Back->Waste.Get(); - +{ + using EIdx = TCookie::EIdx; + + auto *waste = Back->Waste.Get(); + result.CommitManager = new TCommitManager(steppedCookieAllocatorFactory, waste, result.GcLogic.Get()); result.Snap = new TLogicSnap(steppedCookieAllocatorFactory.Sys(EIdx::SnapLz4), waste, Back->Snap); result.Redo = new TLogicRedo(steppedCookieAllocatorFactory.Sys(EIdx::RedoLz4), result.CommitManager.Get(), Back->Redo); -} - -} -} -} +} + +} +} +} diff --git a/ydb/core/tablet_flat/flat_boot_oven.h b/ydb/core/tablet_flat/flat_boot_oven.h index 3d3c7b402a..9209db1370 100644 --- a/ydb/core/tablet_flat/flat_boot_oven.h +++ b/ydb/core/tablet_flat/flat_boot_oven.h @@ -1,88 +1,88 @@ -#pragma once - -#include "defs.h" -#include "util_fmt_abort.h" -#include "flat_sausage_grind.h" -#include "flat_boot_cookie.h" +#pragma once + +#include "defs.h" +#include "util_fmt_abort.h" +#include "flat_sausage_grind.h" +#include "flat_boot_cookie.h" #include <ydb/core/base/blobstorage.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NBoot { - + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NBoot { + struct TSteppedCookieAllocatorFactory { - static_assert(unsigned(TCookie::EIdx::Raw) < sizeof(ui64) * 8, ""); - + static_assert(unsigned(TCookie::EIdx::Raw) < sizeof(ui64) * 8, ""); + using TSteppedCookieAllocator = NPageCollection::TSteppedCookieAllocator; - + TSteppedCookieAllocatorFactory() = delete; - + TSteppedCookieAllocatorFactory(const TTabletStorageInfo &info, ui32 gen) - : Tablet(info.TabletID) - , Gen(gen) - , Sys1{ 1, info.GroupFor(1, Gen) } - , Info(info) - { - - } - + : Tablet(info.TabletID) + , Gen(gen) + , Sys1{ 1, info.GroupFor(1, Gen) } + , Info(info) + { + + } + TAutoPtr<TSteppedCookieAllocator> Sys(TCookie::EIdx idx) noexcept - { - Acquire(idx); - - const NTable::TTxStamp stamp(Gen, 0); - + { + Acquire(idx); + + const NTable::TTxStamp stamp(Gen, 0); + return new TSteppedCookieAllocator(Tablet, stamp, TCookie::CookieRange(idx), { Sys1 }); - } - + } + TAutoPtr<TSteppedCookieAllocator> Data() noexcept - { - Acquire(TCookie::EIdx::Raw); - + { + Acquire(TCookie::EIdx::Raw); + TVector<NPageCollection::TSlot> slots; - - for (auto &one: Info.Channels) { - const auto group = one.GroupForGeneration(Gen); - - if (one.Channel == 0) { - /* Zero channel is reserved for system tablet activity */ + + for (auto &one: Info.Channels) { + const auto group = one.GroupForGeneration(Gen); + + if (one.Channel == 0) { + /* Zero channel is reserved for system tablet activity */ } else if (group == NPageCollection::TLargeGlobId::InvalidGroup) { - Y_Fail( + Y_Fail( "Leader{" << Tablet << ":" << Gen << "} got reserved" << " InvalidGroup value for channel " << one.Channel); - - } else if (group == Max<ui32>()) { - /* Channel is disabled for given group on this Gen */ - } else { - slots.emplace_back(one.Channel, group); - } - } - + + } else if (group == Max<ui32>()) { + /* Channel is disabled for given group on this Gen */ + } else { + slots.emplace_back(one.Channel, group); + } + } + const auto cookieRange = TCookie::CookieRangeRaw(); - - return + + return new TSteppedCookieAllocator(Tablet, NTable::TTxStamp{ Gen, 0 }, cookieRange, slots); - } - - private: - void Acquire(TCookie::EIdx idx) noexcept - { - const auto mask = ui64(1) << unsigned(idx); - - if (std::exchange(Issued, Issued | mask) & mask) { + } + + private: + void Acquire(TCookie::EIdx idx) noexcept + { + const auto mask = ui64(1) << unsigned(idx); + + if (std::exchange(Issued, Issued | mask) & mask) { Y_Fail("Cookies cookieRange EIdx" << ui32(idx) << " is resued"); - } - } - - public: - const ui64 Tablet = Max<ui64>(); - const ui32 Gen = Max<ui32>(); + } + } + + public: + const ui64 Tablet = Max<ui64>(); + const ui32 Gen = Max<ui32>(); const NPageCollection::TSlot Sys1; - - private: - const TTabletStorageInfo &Info; - ui64 Issued = 0; - }; -} -} -} + + private: + const TTabletStorageInfo &Info; + ui64 Issued = 0; + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_boot_redo.h b/ydb/core/tablet_flat/flat_boot_redo.h index ec66bfac28..b13e8d4963 100644 --- a/ydb/core/tablet_flat/flat_boot_redo.h +++ b/ydb/core/tablet_flat/flat_boot_redo.h @@ -1,124 +1,124 @@ -#pragma once - -#include "flat_boot_iface.h" -#include "flat_boot_back.h" -#include "flat_boot_blobs.h" -#include "flat_bio_events.h" -#include "flat_dbase_naked.h" -#include "flat_executor_txloglogic.h" -#include "util_fmt_flat.h" - -#include <util/generic/xrange.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NBoot { - - class TRedo final: public NBoot::IStep { - public: - using TQueue = TDeque<TLogEntry>; - - TRedo() = delete; - - TRedo(IStep *owner, TQueue queue) - : IStep(owner, NBoot::EStep::Redo) - , Codec(NBlockCodecs::Codec("lz4fast")) - , Queue(std::move(queue)) - { - - } - - private: /* IStep, boot logic DSL actor interface */ - void Start() noexcept override - { - if (auto logl = Env->Logger()->Log(ELnLev::Info)) { - const auto last = Queue ? Queue.back().Stamp + 1 : 0; - - logl +#pragma once + +#include "flat_boot_iface.h" +#include "flat_boot_back.h" +#include "flat_boot_blobs.h" +#include "flat_bio_events.h" +#include "flat_dbase_naked.h" +#include "flat_executor_txloglogic.h" +#include "util_fmt_flat.h" + +#include <util/generic/xrange.h> + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NBoot { + + class TRedo final: public NBoot::IStep { + public: + using TQueue = TDeque<TLogEntry>; + + TRedo() = delete; + + TRedo(IStep *owner, TQueue queue) + : IStep(owner, NBoot::EStep::Redo) + , Codec(NBlockCodecs::Codec("lz4fast")) + , Queue(std::move(queue)) + { + + } + + private: /* IStep, boot logic DSL actor interface */ + void Start() noexcept override + { + if (auto logl = Env->Logger()->Log(ELnLev::Info)) { + const auto last = Queue ? Queue.back().Stamp + 1 : 0; + + logl << NFmt::Do(*Back) << " redo log has " << Queue.size() - << " records, last before " << NFmt::TStamp(last); - } - - for (auto slot: xrange(Queue.size())) + << " records, last before " << NFmt::TStamp(last); + } + + for (auto slot: xrange(Queue.size())) if (const auto &largeGlobId = Queue.at(slot).LargeGlobId) Pending += Spawn<TLoadBlobs>(largeGlobId, slot); - - Flush(); - } - + + Flush(); + } + void HandleStep(TIntrusivePtr<IStep> step) noexcept override - { - auto *load = step->ConsumeAs<TLoadBlobs>(Pending); - - if (load->Cookie < Skip || load->Cookie - Skip >= Queue.size()) - Y_FAIL("Got TLoadBlobs result cookie out of queue range"); - - Queue.at(load->Cookie - Skip).Body = load->Plain(); - - Flush(); - } - - private: - void Flush() noexcept - { - for (TLogEntry *head = nullptr; Queue && *(head = &Queue[0]); ) { + { + auto *load = step->ConsumeAs<TLoadBlobs>(Pending); + + if (load->Cookie < Skip || load->Cookie - Skip >= Queue.size()) + Y_FAIL("Got TLoadBlobs result cookie out of queue range"); + + Queue.at(load->Cookie - Skip).Body = load->Plain(); + + Flush(); + } + + private: + void Flush() noexcept + { + for (TLogEntry *head = nullptr; Queue && *(head = &Queue[0]); ) { auto index = TCookie(head->LargeGlobId.Lead.Cookie()).Index(); - + if (head->LargeGlobId && index != TCookie::EIdx::RedoLz4) { - Apply(head->Stamp, *head, head->Body); - } else { - Apply(head->Stamp, *head, Codec->Decode(head->Body)); - } - - ++Skip, Queue.pop_front(); - } - + Apply(head->Stamp, *head, head->Body); + } else { + Apply(head->Stamp, *head, Codec->Decode(head->Body)); + } + + ++Skip, Queue.pop_front(); + } + Y_VERIFY(Queue || !Pending, "TRedo boot actor has lost entries"); - + if (!Queue) { Env->Finish(this); } - } - - void Apply(ui64 stamp, const TLogEntry &entry, TString redo) noexcept - { + } + + void Apply(ui64 stamp, const TLogEntry &entry, TString redo) noexcept + { const auto begin_ = Back->DatabaseImpl->Serial(); - + Back->DatabaseImpl->Switch(stamp).ApplyRedo(redo).GrabAnnex(); - + const auto affects = Back->DatabaseImpl->GrabAffects(); - - if (auto logl = Env->Logger()->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Back) << " redo log " << NFmt::TStamp(stamp) + + if (auto logl = Env->Logger()->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Back) << " redo log " << NFmt::TStamp(stamp) << " serial " << begin_ << " -> [" << Back->DatabaseImpl->First_ << ", " << Back->DatabaseImpl->Serial() << "] applied" - << ", affects " << NFmt::Arr(affects); - } - - if (affects) { - if (auto *logic = Back->Redo.Get()) { + << ", affects " << NFmt::Arr(affects); + } + + if (affects) { + if (auto *logic = Back->Redo.Get()) { if (entry.LargeGlobId) { logic->Push(stamp, affects, entry.LargeGlobId); } else { /* has no TLargeGlobId, thus was embedded to entry */ - logic->Push(stamp, affects, std::move(entry.Body)); - } - } - + logic->Push(stamp, affects, std::move(entry.Body)); + } + } + if (auto *compaction = Logic->Result().Comp.Get()) { for (ui32 table: affects) { compaction->Snapshots[table].InMemSteps++; } - } - } - } - - private: - const NBlockCodecs::ICodec *Codec = nullptr; - TLeft Pending; - ui64 Skip = 0; - TQueue Queue; - }; -} -} -} + } + } + } + + private: + const NBlockCodecs::ICodec *Codec = nullptr; + TLeft Pending; + ui64 Skip = 0; + TQueue Queue; + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_boot_snap.h b/ydb/core/tablet_flat/flat_boot_snap.h index 0eae48284f..b9590a1f15 100644 --- a/ydb/core/tablet_flat/flat_boot_snap.h +++ b/ydb/core/tablet_flat/flat_boot_snap.h @@ -1,106 +1,106 @@ -#pragma once - -#include "flat_abi_evol.h" -#include "flat_abi_check.h" -#include "flat_sausage_chop.h" -#include "flat_boot_iface.h" -#include "flat_boot_back.h" -#include "flat_boot_blobs.h" -#include "flat_writer_banks.h" -#include "flat_executor_gclogic.h" -#include "flat_executor_txloglogic.h" - +#pragma once + +#include "flat_abi_evol.h" +#include "flat_abi_check.h" +#include "flat_sausage_chop.h" +#include "flat_boot_iface.h" +#include "flat_boot_back.h" +#include "flat_boot_blobs.h" +#include "flat_writer_banks.h" +#include "flat_executor_gclogic.h" +#include "flat_executor_txloglogic.h" + #include <ydb/core/tablet_flat/flat_executor.pb.h> #include <ydb/core/util/pb.h> -#include <util/generic/xrange.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NBoot { - - class TSnap final: public NBoot::IStep { - using EIdx = TCookie::EIdx; - using TTxStamp = NTable::TTxStamp; - - public: +#include <util/generic/xrange.h> + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NBoot { + + class TSnap final: public NBoot::IStep { + using EIdx = TCookie::EIdx; + using TTxStamp = NTable::TTxStamp; + + public: TSnap(IStep *owner, TIntrusivePtr<TDependency> deps, TAutoPtr<TBody> snap) - : IStep(owner, NBoot::EStep::Snap) - , Codec(NBlockCodecs::Codec("lz4fast")) - , Deps(std::move(deps)) - , Snap(snap) - { - Y_VERIFY(!(Deps && Snap), "Need either deps or raw snap"); - } - - private: /* IStep, boot logic DSL actor interface */ - void Start() noexcept override - { - GrabSnapFromDeps(); - - if (!Snap) { + : IStep(owner, NBoot::EStep::Snap) + , Codec(NBlockCodecs::Codec("lz4fast")) + , Deps(std::move(deps)) + , Snap(snap) + { + Y_VERIFY(!(Deps && Snap), "Need either deps or raw snap"); + } + + private: /* IStep, boot logic DSL actor interface */ + void Start() noexcept override + { + GrabSnapFromDeps(); + + if (!Snap) { ProcessDeps(), Env->Finish(this); } else if (Snap->LargeGlobId.Lead.Step() == 0) { Y_Fail("Invalid TLogoBlobID of snaphot: " << Snap->LargeGlobId.Lead); - } else if (Snap->Body) { + } else if (Snap->Body) { Apply(Snap->LargeGlobId, Snap->Body); - } else { + } else { Pending += Spawn<TLoadBlobs>(Snap->LargeGlobId, 0); - } - } - + } + } + void HandleStep(TIntrusivePtr<IStep> step) noexcept override - { - auto *load = step->ConsumeAs<TLoadBlobs>(Pending); - + { + auto *load = step->ConsumeAs<TLoadBlobs>(Pending); + Apply(load->LargeGlobId, load->Plain()); - } - - private: + } + + private: void Apply(const NPageCollection::TLargeGlobId &snap, TArrayRef<const char> body) noexcept - { - if (EIdx::SnapLz4 == TCookie(snap.Lead.Cookie()).Index()) { - Decode(snap, Codec->Decode(body)); - } else { - Decode(snap, body); - } - + { + if (EIdx::SnapLz4 == TCookie(snap.Lead.Cookie()).Index()) { + Decode(snap, Codec->Decode(body)); + } else { + Decode(snap, body); + } + ProcessSnap(snap), ProcessDeps(), Env->Finish(this); - } - + } + void Decode(const NPageCollection::TLargeGlobId &snap, TArrayRef<const char> body) noexcept - { - bool ok = ParseFromStringNoSizeLimit(Proto, body); - Y_VERIFY(ok); - + { + bool ok = ParseFromStringNoSizeLimit(Proto, body); + Y_VERIFY(ok); + bool huge = (body.size() > 10*1024*1024); - - if (auto logl = Env->Logger()->Log(huge ? ELnLev::Crit : ELnLev::Info)) { - auto edge = Proto.HasVersion() ? Proto.GetVersion().GetHead():1; - auto change = Proto.HasSerial() ? Proto.GetSerial() : 0; - - logl - << NFmt::Do(*Back) << " snap on " - << snap.Lead.Generation() << ":" << snap.Lead.Step() - << " change " << change << ", " << body.size() << "b" - << ", ABI " << edge << " of " + + if (auto logl = Env->Logger()->Log(huge ? ELnLev::Crit : ELnLev::Info)) { + auto edge = Proto.HasVersion() ? Proto.GetVersion().GetHead():1; + auto change = Proto.HasSerial() ? Proto.GetSerial() : 0; + + logl + << NFmt::Do(*Back) << " snap on " + << snap.Lead.Generation() << ":" << snap.Lead.Step() + << " change " << change << ", " << body.size() << "b" + << ", ABI " << edge << " of " << "[" << ui32(NTable::ECompatibility::Tail) << ", " << ui32(NTable::ECompatibility::Edge) << "]" - << ", GC{ +" << Proto.GcSnapDiscoveredSize() - << " -" << Proto.GcSnapLeftSize() << " }"; - } - - if (auto *abi = Proto.HasVersion() ? &Proto.GetVersion() : nullptr) - NTable::TAbi().Check(abi->GetTail(), abi->GetHead(), "snap"); - } - + << ", GC{ +" << Proto.GcSnapDiscoveredSize() + << " -" << Proto.GcSnapLeftSize() << " }"; + } + + if (auto *abi = Proto.HasVersion() ? &Proto.GetVersion() : nullptr) + NTable::TAbi().Check(abi->GetTail(), abi->GetHead(), "snap"); + } + void ProcessSnap(const NPageCollection::TLargeGlobId &snap) noexcept - { - Back->Snap = snap; - Back->Serial = Proto.GetSerial(); - - ReadAlterLog(); - ReadRedoSnap(); - + { + Back->Snap = snap; + Back->Serial = Proto.GetSerial(); + + ReadAlterLog(); + ReadRedoSnap(); + if (Logic->Result().Comp) { for (const auto &one : Proto.GetCompactionStates()) { Back->Switches.emplace_back().Init(one); @@ -111,253 +111,253 @@ namespace NBoot { Back->Switches.emplace_back().Init(one); } - for (const auto &one : Proto.GetDbParts()) { - Back->Switches.emplace_back(); - Back->Switches.back().Init(one); - } - + for (const auto &one : Proto.GetDbParts()) { + Back->Switches.emplace_back(); + Back->Switches.back().Init(one); + } + for (const auto &one : Proto.GetTxStatusParts()) { Back->Switches.emplace_back(); Back->Switches.back().Init(one); } - for (const auto &x : Proto.GetTableSnapshoted()) - Back->SetTableEdge(x); - - if (Logic->Result().Loans) { - for (const auto &one : Proto.GetBorrowInfoIds()) { - const auto logo = LogoBlobIDFromLogoBlobID(one); - - Back->LoansLog.push_back({{ Logic->GetBSGroupFor(logo), logo }, { }}); - } - } - - ReadGcSnap(); - ReadWaste(); - } - - void ReadAlterLog() noexcept - { - TVector<TLogoBlobID> blobs; - - blobs.reserve(Proto.SchemeInfoBodiesSize()); - - for (const auto &one : Proto.GetSchemeInfoBodies()) - blobs.emplace_back(LogoBlobIDFromLogoBlobID(one)); - + for (const auto &x : Proto.GetTableSnapshoted()) + Back->SetTableEdge(x); + + if (Logic->Result().Loans) { + for (const auto &one : Proto.GetBorrowInfoIds()) { + const auto logo = LogoBlobIDFromLogoBlobID(one); + + Back->LoansLog.push_back({{ Logic->GetBSGroupFor(logo), logo }, { }}); + } + } + + ReadGcSnap(); + ReadWaste(); + } + + void ReadAlterLog() noexcept + { + TVector<TLogoBlobID> blobs; + + blobs.reserve(Proto.SchemeInfoBodiesSize()); + + for (const auto &one : Proto.GetSchemeInfoBodies()) + blobs.emplace_back(LogoBlobIDFromLogoBlobID(one)); + NPageCollection::TGroupBlobsByCookie chop(blobs); - - while (auto span = chop.Do()) { - const auto group = Logic->GetBSGroupFor(span[0]); - + + while (auto span = chop.Do()) { + const auto group = Logic->GetBSGroupFor(span[0]); + Back->AlterLog.push_back({ NPageCollection::TGroupBlobsByCookie::ToLargeGlobId(span, group), { } }); - } - } - - void ReadRedoSnap() noexcept - { - /* Merge of two lists with redo log records preferring records with - embedded bodies. Later merge will be dropped and replaced with - linear reading of generalized embedded records. - */ - - TVector<TLogoBlobID> logos; - - for (const auto &x : Proto.GetNonSnapLogBodies()) - logos.emplace_back(LogoBlobIDFromLogoBlobID(x)); - + } + } + + void ReadRedoSnap() noexcept + { + /* Merge of two lists with redo log records preferring records with + embedded bodies. Later merge will be dropped and replaced with + linear reading of generalized embedded records. + */ + + TVector<TLogoBlobID> logos; + + for (const auto &x : Proto.GetNonSnapLogBodies()) + logos.emplace_back(LogoBlobIDFromLogoBlobID(x)); + NPageCollection::TGroupBlobsByCookie chop(logos); - - size_t offset = 0; - const size_t size = Proto.EmbeddedLogBodiesSize(); - - for (auto span = chop.Do(); span || offset < size;) { - auto *lx = offset < size ? &Proto.GetEmbeddedLogBodies(offset) : nullptr; - auto right = lx ? TTxStamp{ lx->GetGeneration(), lx->GetStep() } : TTxStamp{ Max<ui64>() }; - auto left = span ? TTxStamp{ span[0].Generation(), span[0].Step() } : TTxStamp{ Max<ui64>() }; - - if (left < right) { + + size_t offset = 0; + const size_t size = Proto.EmbeddedLogBodiesSize(); + + for (auto span = chop.Do(); span || offset < size;) { + auto *lx = offset < size ? &Proto.GetEmbeddedLogBodies(offset) : nullptr; + auto right = lx ? TTxStamp{ lx->GetGeneration(), lx->GetStep() } : TTxStamp{ Max<ui64>() }; + auto left = span ? TTxStamp{ span[0].Generation(), span[0].Step() } : TTxStamp{ Max<ui64>() }; + + if (left < right) { auto largeGlobId = NPageCollection::TGroupBlobsByCookie::ToLargeGlobId(span, Logic->GetBSGroupFor(span[0])); - + Back->RedoLog.emplace_back(left, largeGlobId); - } else { - Back->RedoLog.emplace_back(right, lx->GetBody()); - - offset++; - } - - span = left > right ? span : chop.Do(); - } - } - - void ReadGcSnap() noexcept - { - if (auto *logic = Logic->Result().GcLogic.Get()) { - const auto &lead = Back->Snap.Lead; - - TGCLogEntry entry({ lead.Generation(), lead.Step() - 1 }); - - entry.Delta.Created.reserve(Proto.GcSnapDiscoveredSize()); - entry.Delta.Deleted.reserve(Proto.GcSnapLeftSize()); - - for (const auto &x : Proto.GetGcSnapDiscovered()) - entry.Delta.Created.push_back(LogoBlobIDFromLogoBlobID(x)); - for (const auto &x : Proto.GetGcSnapLeft()) - entry.Delta.Deleted.push_back(LogoBlobIDFromLogoBlobID(x)); - - TVector<std::pair<ui32, ui64>> barriers; - barriers.reserve(Proto.GcBarrierInfoSize()); - - for (const auto &x : Proto.GetGcBarrierInfo()) - barriers.push_back({x.GetChannel(), MakeGenStepPair(x.GetSetToGeneration(), x.GetSetToStep())}); - - if (auto logl = Env->Logger()->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Back) << " process gc snapshot" - << ", + " << entry.Delta.Created - << ", - " << entry.Delta.Deleted; - } - - logic->ApplyLogSnapshot(entry, barriers); - } - } - - void ReadWaste() const noexcept - { - if (auto *waste = Back->Waste.Get()) { - if (Proto.HasWaste()) { - waste->Since = Proto.GetWaste().GetSince(); - waste->Level = Proto.GetWaste().GetLevel(); - waste->Keep = Proto.GetWaste().GetKeep(); - waste->Drop = Proto.GetWaste().GetDrop(); - } else { + } else { + Back->RedoLog.emplace_back(right, lx->GetBody()); + + offset++; + } + + span = left > right ? span : chop.Do(); + } + } + + void ReadGcSnap() noexcept + { + if (auto *logic = Logic->Result().GcLogic.Get()) { + const auto &lead = Back->Snap.Lead; + + TGCLogEntry entry({ lead.Generation(), lead.Step() - 1 }); + + entry.Delta.Created.reserve(Proto.GcSnapDiscoveredSize()); + entry.Delta.Deleted.reserve(Proto.GcSnapLeftSize()); + + for (const auto &x : Proto.GetGcSnapDiscovered()) + entry.Delta.Created.push_back(LogoBlobIDFromLogoBlobID(x)); + for (const auto &x : Proto.GetGcSnapLeft()) + entry.Delta.Deleted.push_back(LogoBlobIDFromLogoBlobID(x)); + + TVector<std::pair<ui32, ui64>> barriers; + barriers.reserve(Proto.GcBarrierInfoSize()); + + for (const auto &x : Proto.GetGcBarrierInfo()) + barriers.push_back({x.GetChannel(), MakeGenStepPair(x.GetSetToGeneration(), x.GetSetToStep())}); + + if (auto logl = Env->Logger()->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Back) << " process gc snapshot" + << ", + " << entry.Delta.Created + << ", - " << entry.Delta.Deleted; + } + + logic->ApplyLogSnapshot(entry, barriers); + } + } + + void ReadWaste() const noexcept + { + if (auto *waste = Back->Waste.Get()) { + if (Proto.HasWaste()) { + waste->Since = Proto.GetWaste().GetSince(); + waste->Level = Proto.GetWaste().GetLevel(); + waste->Keep = Proto.GetWaste().GetKeep(); + waste->Drop = Proto.GetWaste().GetDrop(); + } else { /* Old snapshot without step pollution accounting, - promote start age to the current snapshot since - waste, produced until current state, is known. */ - + promote start age to the current snapshot since + waste, produced until current state, is known. */ + const auto &lead = Snap->LargeGlobId.Lead; - - waste->Since = TTxStamp(lead.Generation(), lead.Step()); - } - } - } - - void GrabSnapFromDeps() noexcept - { - auto *entry = (Deps && Deps->Entries) ? &Deps->Entries[0] : nullptr; - - if (entry && entry->IsSnapshot) { - TTxStamp stamp{ entry->Id.first, entry->Id.second }; - + + waste->Since = TTxStamp(lead.Generation(), lead.Step()); + } + } + } + + void GrabSnapFromDeps() noexcept + { + auto *entry = (Deps && Deps->Entries) ? &Deps->Entries[0] : nullptr; + + if (entry && entry->IsSnapshot) { + TTxStamp stamp{ entry->Id.first, entry->Id.second }; + const auto span = NPageCollection::TGroupBlobsByCookie(entry->References).Do(); const auto largeGlobId = NPageCollection::TGroupBlobsByCookie::ToLargeGlobId(span, Logic->GetBSGroupFor(span[0])); - - Y_VERIFY(span.size() == entry->References.size()); - Y_VERIFY(TCookie(span[0].Cookie()).Type() == TCookie::EType::Log); + + Y_VERIFY(span.size() == entry->References.size()); + Y_VERIFY(TCookie(span[0].Cookie()).Type() == TCookie::EType::Log); Y_VERIFY(largeGlobId, "Cannot make TLargeGlobId for snapshot"); - - if (auto logl = Env->Logger()->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Back) << " snap in deps on " + + if (auto logl = Env->Logger()->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Back) << " snap in deps on " << NFmt::TStamp(stamp) << ", " << NFmt::Do(largeGlobId); - } - - ProcessGcLogEntry(*entry, true); - - Deps->Entries.pop_front(); /* skip record in ProcessDeps() */ + } + + ProcessGcLogEntry(*entry, true); + + Deps->Entries.pop_front(); /* skip record in ProcessDeps() */ Snap = new TBody{ largeGlobId, { } }; - } - } - - void ProcessDeps() noexcept - { - if (Deps) { - for (auto &entry : Deps->Entries) { - Y_VERIFY(!entry.IsSnapshot); - - TTxStamp stamp{ entry.Id.first, entry.Id.second }; - - if (entry.EmbeddedLogBody) { - Y_VERIFY(entry.References.empty()); - Back->RedoLog.emplace_back(stamp, entry.EmbeddedLogBody); - } else { + } + } + + void ProcessDeps() noexcept + { + if (Deps) { + for (auto &entry : Deps->Entries) { + Y_VERIFY(!entry.IsSnapshot); + + TTxStamp stamp{ entry.Id.first, entry.Id.second }; + + if (entry.EmbeddedLogBody) { + Y_VERIFY(entry.References.empty()); + Back->RedoLog.emplace_back(stamp, entry.EmbeddedLogBody); + } else { NPageCollection::TGroupBlobsByCookie chop(entry.References); - + while (auto span = chop.Do()) SortLogoSpan(stamp, span); - } - - ProcessGcLogEntry(entry, false); - } - } - } - - void ProcessGcLogEntry(TDependency::TEntry &entry, bool snap) - { + } + + ProcessGcLogEntry(entry, false); + } + } + } + + void ProcessGcLogEntry(TDependency::TEntry &entry, bool snap) + { if (Back->Follower) // do nothing for followers return; - if (auto logl = Env->Logger()->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Back) << " process " << (snap ? "snap" : "log") - << " gc entry, + " << entry.GcDiscovered - << ", - " << entry.GcLeft; - } - - TGCLogEntry gcEntry({ entry.Id.first, entry.Id.second }); - gcEntry.Delta.Created.swap(entry.GcDiscovered); - gcEntry.Delta.Deleted.swap(entry.GcLeft); - Back->Waste->Account(gcEntry.Delta); - Logic->Result().GcLogic->ApplyLogEntry(gcEntry); - } - + if (auto logl = Env->Logger()->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Back) << " process " << (snap ? "snap" : "log") + << " gc entry, + " << entry.GcDiscovered + << ", - " << entry.GcLeft; + } + + TGCLogEntry gcEntry({ entry.Id.first, entry.Id.second }); + gcEntry.Delta.Created.swap(entry.GcDiscovered); + gcEntry.Delta.Deleted.swap(entry.GcLeft); + Back->Waste->Account(gcEntry.Delta); + Logic->Result().GcLogic->ApplyLogEntry(gcEntry); + } + void SortLogoSpan(TTxStamp stamp, NPageCollection::TGroupBlobsByCookie::TArray span) - { - Y_VERIFY(TCookie(span[0].Cookie()).Type() == TCookie::EType::Log); - - const auto group = Logic->GetBSGroupFor(span[0]); - const auto index = TCookie(span[0].Cookie()).Index(); - - if (index == EIdx::Redo || index == EIdx::RedoLz4) { - + { + Y_VERIFY(TCookie(span[0].Cookie()).Type() == TCookie::EType::Log); + + const auto group = Logic->GetBSGroupFor(span[0]); + const auto index = TCookie(span[0].Cookie()).Index(); + + if (index == EIdx::Redo || index == EIdx::RedoLz4) { + Back->RedoLog.emplace_back(stamp, NPageCollection::TGroupBlobsByCookie::ToLargeGlobId(span, group)); - - } else if (index == EIdx::Alter) { - + + } else if (index == EIdx::Alter) { + Back->AlterLog.push_back({ NPageCollection::TGroupBlobsByCookie::ToLargeGlobId(span, group), { } }); - - } else if (index == EIdx::Turn || index == EIdx::TurnLz4) { - - for (auto &one: span) { + + } else if (index == EIdx::Turn || index == EIdx::TurnLz4) { + + for (auto &one: span) { Back->Switches.push_back(NPageCollection::TLargeGlobId{ group, one }); - } - - } else if (index == EIdx::Loan) { - - for (auto &one: span) - Back->LoansLog.push_back({{ group, one }, { }}); - - } else if (index == EIdx::GCExt) { - if (Logic->Result().GcLogic) { - for (auto &one: span) - Back->GCELog.push_back({ { group, one }, { }}); - } + } + + } else if (index == EIdx::Loan) { + + for (auto &one: span) + Back->LoansLog.push_back({{ group, one }, { }}); + + } else if (index == EIdx::GCExt) { + if (Logic->Result().GcLogic) { + for (auto &one: span) + Back->GCELog.push_back({ { group, one }, { }}); + } } else if (TCookie::CookieRangeRaw().Has(span[0].Cookie())) { - /* Annex (external blobs for redo log), isn't used here */ - } else { - Y_Fail( - NFmt::Do(*Back) << " got on booting blob " << span[0] - << " with unknown TCookie structue, EIdx " << ui32(index)); - } - } - - private: - const NBlockCodecs::ICodec *Codec = nullptr; - TLeft Pending; + /* Annex (external blobs for redo log), isn't used here */ + } else { + Y_Fail( + NFmt::Do(*Back) << " got on booting blob " << span[0] + << " with unknown TCookie structue, EIdx " << ui32(index)); + } + } + + private: + const NBlockCodecs::ICodec *Codec = nullptr; + TLeft Pending; TIntrusivePtr<TDependency> Deps; TAutoPtr<TBody> Snap; - NKikimrExecutorFlat::TLogSnapshot Proto; - }; -} -} -} + NKikimrExecutorFlat::TLogSnapshot Proto; + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_boot_stages.h b/ydb/core/tablet_flat/flat_boot_stages.h index 8fde38a5e7..f1a01eb155 100644 --- a/ydb/core/tablet_flat/flat_boot_stages.h +++ b/ydb/core/tablet_flat/flat_boot_stages.h @@ -1,126 +1,126 @@ -#pragma once - -#include "flat_boot_iface.h" -#include "flat_boot_back.h" -#include "flat_boot_snap.h" -#include "flat_boot_turns.h" -#include "flat_boot_gclog.h" -#include "flat_boot_loans.h" -#include "flat_boot_alter.h" -#include "flat_boot_bundle.h" -#include "flat_boot_redo.h" -#include "flat_boot_warm.h" +#pragma once + +#include "flat_boot_iface.h" +#include "flat_boot_back.h" +#include "flat_boot_snap.h" +#include "flat_boot_turns.h" +#include "flat_boot_gclog.h" +#include "flat_boot_loans.h" +#include "flat_boot_alter.h" +#include "flat_boot_bundle.h" +#include "flat_boot_redo.h" +#include "flat_boot_warm.h" #include "flat_boot_txstatus.h" -#include "flat_dbase_naked.h" -#include "logic_redo_queue.h" -#include "flat_database.h" - -#include <util/generic/xrange.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NBoot { - - class TStages final: public NBoot::IStep { - - enum class EStage : unsigned { +#include "flat_dbase_naked.h" +#include "logic_redo_queue.h" +#include "flat_database.h" + +#include <util/generic/xrange.h> + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NBoot { + + class TStages final: public NBoot::IStep { + + enum class EStage : unsigned { Snap = 1, /* Read snapshot and deps graph log */ Meta = 2, /* Executor system metalog queues */ DatabaseImpl = 3, /* Roll up TDatabaseImpl to actual state*/ Blobs = 4, /* Load TMemTable blobs to its cache */ Result = 5, /* Finalize NBoot::TResult object */ Ready = 6, - }; - - public: - TStages() = delete; - + }; + + public: + TStages() = delete; + TStages(IStep *owner, TIntrusivePtr<TDependency> deps, TAutoPtr<TBody> snap) - : IStep(owner, NBoot::EStep::Stages) - , Deps(std::move(deps)) - , Snap(std::move(snap)) - { - - } - - private: /* IStep, boot logic DSL actor interface */ - void Start() noexcept override - { - Execute(); - } - + : IStep(owner, NBoot::EStep::Stages) + , Deps(std::move(deps)) + , Snap(std::move(snap)) + { + + } + + private: /* IStep, boot logic DSL actor interface */ + void Start() noexcept override + { + Execute(); + } + void HandleStep(TIntrusivePtr<IStep>) noexcept override - { - Pending -=1, Execute(); - } - - private: - void Execute() noexcept - { - while (!Pending && Next < EStage::Ready) { - if (EStage::Snap == Next) { - StartStageSnap(); - } else if (EStage::Meta == Next) { - StartStageMeta(); + { + Pending -=1, Execute(); + } + + private: + void Execute() noexcept + { + while (!Pending && Next < EStage::Ready) { + if (EStage::Snap == Next) { + StartStageSnap(); + } else if (EStage::Meta == Next) { + StartStageMeta(); } else if (EStage::DatabaseImpl == Next) { StartStageDatabaseImpl(); - } else if (EStage::Blobs == Next) { + } else if (EStage::Blobs == Next) { Pending += Spawn<TMemTable>(); - } else if (EStage::Result == Next) { - StartStageResult(Logic->Result()); - } - - Next = EStage(unsigned(Next) + 1); - - if (auto logl = Env->Logger()->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Back) - << " fired stage " << (unsigned(Next) - 1) << ", has " - << Pending.Get() << " jobs, " << NFmt::Do(*Env); - } - } - } - - void StartStageSnap() noexcept - { - if (auto logl = Env->Logger()->Log(ELnLev::Info)) { - logl - << NFmt::Do(*Back) << " booting" - << " " << NFmt::If(Deps.Get()) - << " " << NFmt::If(Snap.Get()); - } - + } else if (EStage::Result == Next) { + StartStageResult(Logic->Result()); + } + + Next = EStage(unsigned(Next) + 1); + + if (auto logl = Env->Logger()->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Back) + << " fired stage " << (unsigned(Next) - 1) << ", has " + << Pending.Get() << " jobs, " << NFmt::Do(*Env); + } + } + } + + void StartStageSnap() noexcept + { + if (auto logl = Env->Logger()->Log(ELnLev::Info)) { + logl + << NFmt::Do(*Back) << " booting" + << " " << NFmt::If(Deps.Get()) + << " " << NFmt::If(Snap.Get()); + } + Pending += Spawn<TSnap>(std::move(Deps), Snap); - } - - void StartStageMeta() noexcept - { - if (auto logl = Env->Logger()->Log(ELnLev::Info)) { - logl - << NFmt::Do(*Back) << " loading {" - << " Alter " << Back->AlterLog.size() - << ", Turns " << Back->Switches.size() - << ", Loans " << Back->LoansLog.size() - << ", GCExt " << Back->GCELog.size() << " }"; - } - + } + + void StartStageMeta() noexcept + { + if (auto logl = Env->Logger()->Log(ELnLev::Info)) { + logl + << NFmt::Do(*Back) << " loading {" + << " Alter " << Back->AlterLog.size() + << ", Turns " << Back->Switches.size() + << ", Loans " << Back->LoansLog.size() + << ", GCExt " << Back->GCELog.size() << " }"; + } + Pending += Spawn<TGCLog>(std::move(Back->GCELog)); Pending += Spawn<TLoans>(std::move(Back->LoansLog)); Pending += Spawn<TAlter>(std::move(Back->AlterLog)); Pending += Spawn<TTurns>(); - } - + } + void StartStageDatabaseImpl() noexcept - { - auto weak = Back->RedoLog ? Back->RedoLog.back().Stamp + 1 : 0; - + { + auto weak = Back->RedoLog ? Back->RedoLog.back().Stamp + 1 : 0; + Back->DatabaseImpl = new NTable::TDatabaseImpl(weak, Back->Scheme, &Back->Edges); - + if (!Back->Follower) { - Back->Redo = new NRedo::TQueue(std::move(Back->Edges)); - } - - for (auto &se: std::exchange(Back->Switches, { })) { + Back->Redo = new NRedo::TQueue(std::move(Back->Edges)); + } + + for (auto &se: std::exchange(Back->Switches, { })) { auto &wrap = Back->DatabaseImpl->Get(se.Table, false); if (!wrap) { @@ -134,7 +134,7 @@ namespace NBoot { if (bundle.Load) { bundle.AddGroups([this](const TLogoBlobID &logo) { return Logic->GetBSGroupFor(logo); }); - + // FIXME: currently it's only safe to use cold mode // for borrowed parts, otherwise we cannot perform // many important gc tasks without knowing the full @@ -167,56 +167,56 @@ namespace NBoot { for (auto &range : std::exchange(se.RemovedRowVersions, { })) { wrap->RemoveRowVersions(range.Lower, range.Upper); } - } - + } + Pending += Spawn<TRedo>(std::move(Back->RedoLog)); - } - - void StartStageResult(TResult &result) noexcept - { - /* Tail of redo log before snapshot may have holes in space of - db change serial numbers. Thus embedded serials into log may - leave serial less than the real last change. This last hole - is healed by db serial embedded to snapshot. - - - snapshot >--. head --. - `. `. - ..... ...... :.................: - | 1 | | 7 | | 13 | 14 | 15 | < redo log - ''''' '''''' :''''''''''''''''': - : : - sparse area : dense area : - - >----------------> time - - */ - + } + + void StartStageResult(TResult &result) noexcept + { + /* Tail of redo log before snapshot may have holes in space of + db change serial numbers. Thus embedded serials into log may + leave serial less than the real last change. This last hole + is healed by db serial embedded to snapshot. + + + snapshot >--. head --. + `. `. + ..... ...... :.................: + | 1 | | 7 | | 13 | 14 | 15 | < redo log + ''''' '''''' :''''''''''''''''': + : : + sparse area : dense area : + + >----------------> time + + */ + const auto was = Back->DatabaseImpl->Rewind(Back->Serial); - + result.Database = new NTable::TDatabase(Back->DatabaseImpl.Release()); - - if (auto logl = Env->Logger()->Log(ELnLev::Info)) { - auto serial = result.Database->Head(Max<ui32>()).Serial; - - logl - << NFmt::Do(*Back) << " result: db change {" << was - << " -> " << serial << "} snap on " << Back->Serial; - } - + + if (auto logl = Env->Logger()->Log(ELnLev::Info)) { + auto serial = result.Database->Head(Max<ui32>()).Serial; + + logl + << NFmt::Do(*Back) << " result: db change {" << was + << " -> " << serial << "} snap on " << Back->Serial; + } + if (!Back->Follower) { FinalizeLeaderLogics(result, *Back->SteppedCookieAllocatorFactory); - } - } - + } + } + void FinalizeLeaderLogics(TResult&, TSteppedCookieAllocatorFactory&) noexcept; - - private: - EStage Next = EStage::Snap; /* Next stage to execute */ - TLeft Pending; + + private: + EStage Next = EStage::Snap; /* Next stage to execute */ + TLeft Pending; TIntrusivePtr<TDependency> Deps; TAutoPtr<TBody> Snap; - }; -} -} -} + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_boot_switch.h b/ydb/core/tablet_flat/flat_boot_switch.h index 6442b82f0b..7e4c9d1e95 100644 --- a/ydb/core/tablet_flat/flat_boot_switch.h +++ b/ydb/core/tablet_flat/flat_boot_switch.h @@ -1,20 +1,20 @@ -#pragma once - -#include "flat_boot_blobs.h" -#include "flat_store_hotdog.h" -#include "flat_store_solid.h" - +#pragma once + +#include "flat_boot_blobs.h" +#include "flat_store_hotdog.h" +#include "flat_store_solid.h" + #include <ydb/core/tablet_flat/flat_executor.pb.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NBoot { - + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NBoot { + struct TSwitch { - + struct TBundle { TVector<NPageCollection::TLargeGlobId> LargeGlobIds; - TString Legacy; + TString Legacy; TString Opaque; TVector<TString> Deltas; NTable::TEpoch Epoch = NTable::TEpoch::Max(); @@ -33,9 +33,9 @@ namespace NBoot { } }; - struct TChange { + struct TChange { TLogoBlobID Label; - TString Legacy; + TString Legacy; TString Opaque; }; @@ -66,14 +66,14 @@ namespace NBoot { bool Load = true; }; - TSwitch() { } + TSwitch() { } TSwitch(NPageCollection::TLargeGlobId largeGlobId) : LargeGlobId(largeGlobId) { } - - bool Loaded() const noexcept - { - return Table != Max<ui32>(); - } - + + bool Loaded() const noexcept + { + return Table != Max<ui32>(); + } + void Init(const NKikimrExecutorFlat::TTablePartSwitch &proto) { InitTable(proto.GetTableId()); @@ -120,52 +120,52 @@ namespace NBoot { } } - void Init(const NKikimrExecutorFlat::TLogTableSnap &snap) - { + void Init(const NKikimrExecutorFlat::TLogTableSnap &snap) + { InitTable(snap.GetTable()); - + if (snap.HasCompactionLevel()) { Level = snap.GetCompactionLevel(); } - + if (snap.DbPartMetaInfoBodySize() > 0) { /* Legacy mode, may hold only one page collection per entity */ - + AddLegacyLargeGlobId(Bundles.emplace_back(), snap.GetDbPartMetaInfoBody()); } - + if (snap.BundlesSize() > 0) { Bundles.reserve(Bundles.size() + snap.BundlesSize()); for (auto &bundle: snap.GetBundles()) { - auto &one = Bundles.emplace_back(); + auto &one = Bundles.emplace_back(); one.LargeGlobIds.reserve(bundle.PageCollectionsSize()); for (auto &pageCollection: bundle.GetPageCollections()) { if (pageCollection.HasLargeGlobId()) { auto largeGlobId = TLargeGlobIdProto::Get(pageCollection.GetLargeGlobId()); - + one.LargeGlobIds.emplace_back(largeGlobId); - } else { + } else { AddLegacyLargeGlobId(one, pageCollection.GetMetaId()); - } - } - + } + } + Y_VERIFY(one.LargeGlobIds.size(), "Part bundle has no page collections"); - if (bundle.HasLegacy()) - one.Legacy = bundle.GetLegacy(); - - if (bundle.HasOpaque()) - one.Opaque = bundle.GetOpaque(); + if (bundle.HasLegacy()) + one.Legacy = bundle.GetLegacy(); + + if (bundle.HasOpaque()) + one.Opaque = bundle.GetOpaque(); if (bundle.HasEpoch()) one.Epoch = NTable::TEpoch(bundle.GetEpoch()); } } } - + void Init(const NKikimrExecutorFlat::TLogTxStatusSnap &snap) { InitTable(snap.GetTable()); @@ -181,13 +181,13 @@ namespace NBoot { void Init(const NKikimrExecutorFlat::TCompactionState &proto) { InitTable(proto.GetTable()); - + CompactionChanges.Strategy = proto.GetStrategy(); for (const auto& kv : proto.GetKeyValues()) { CompactionChanges.KeyValues[kv.GetKey()] = kv.GetValue(); - } - } - + } + } + void Init(const NKikimrExecutorFlat::TRowVersionState &proto) { InitTable(proto.GetTable()); @@ -207,11 +207,11 @@ namespace NBoot { c.Label = LogoBlobIDFromLogoBlobID(change.GetLabel()); - if (change.HasLegacy()) - c.Legacy = change.GetLegacy(); - + if (change.HasLegacy()) + c.Legacy = change.GetLegacy(); + if (change.HasOpaque()) - c.Opaque = change.GetOpaque(); + c.Opaque = change.GetOpaque(); } void AddDelta(const NKikimrExecutorFlat::TBundleDelta &delta) @@ -225,9 +225,9 @@ namespace NBoot { } void AddMove(const NKikimrExecutorFlat::TBundleMove &proto) - { + { auto &m = Moves.emplace_back(); - + m.Label = LogoBlobIDFromLogoBlobID(proto.GetLabel()); if (proto.HasRebasedEpoch()) @@ -235,18 +235,18 @@ namespace NBoot { if (proto.HasSourceTable()) m.SourceTable = proto.GetSourceTable(); - } - - private: + } + + private: void AddLegacyLargeGlobId(TBundle &bundle, const TLargeGlobIdProto::TRep &rep) - { - auto lookup = [](const TLogoBlobID&) { + { + auto lookup = [](const TLogoBlobID&) { return NPageCollection::TLargeGlobId::InvalidGroup; /* Don't know now group id */ - }; - + }; + bundle.LargeGlobIds.emplace_back(TLargeGlobIdProto::Get(rep, lookup)); - } - + } + void InitTable(ui32 table) { Y_VERIFY(table != Max<ui32>(), "Invalid table id in switch"); if (Table == Max<ui32>()) { @@ -258,15 +258,15 @@ namespace NBoot { } } - public: + public: const NPageCollection::TLargeGlobId LargeGlobId; /* Switch blob LargeGlobId */ - - ui32 Table = Max<ui32>(); + + ui32 Table = Max<ui32>(); ui32 Level = 255; - + TVector<TBundle> Bundles; TVector<TBundle> MovedBundles; - TVector<TChange> Changes; + TVector<TChange> Changes; TVector<TDelta> Deltas; TVector<TMove> Moves; TVector<TLogoBlobID> Leaving; @@ -276,7 +276,7 @@ namespace NBoot { TCompactionChanges CompactionChanges; TVector<TRemovedRowVersions> RemovedRowVersions; - }; -} -} -} + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_boot_turns.h b/ydb/core/tablet_flat/flat_boot_turns.h index 7730e9cbb9..fa7cae739b 100644 --- a/ydb/core/tablet_flat/flat_boot_turns.h +++ b/ydb/core/tablet_flat/flat_boot_turns.h @@ -1,86 +1,86 @@ -#pragma once - -#include "flat_boot_iface.h" -#include "flat_boot_back.h" -#include "flat_boot_blobs.h" -#include "flat_boot_switch.h" - +#pragma once + +#include "flat_boot_iface.h" +#include "flat_boot_back.h" +#include "flat_boot_blobs.h" +#include "flat_boot_switch.h" + #include <ydb/core/util/pb.h> -#include <util/generic/xrange.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NBoot { - - class TTurns final: public NBoot::IStep { - public: - TTurns(IStep *owner) - : IStep(owner, NBoot::EStep::Turns) - , Codec(NBlockCodecs::Codec("lz4fast")) - { - - } - - private: /* IStep, boot logic DSL actor interface */ - void Start() noexcept override - { - for (auto slot: xrange(Back->Switches.size())) +#include <util/generic/xrange.h> + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NBoot { + + class TTurns final: public NBoot::IStep { + public: + TTurns(IStep *owner) + : IStep(owner, NBoot::EStep::Turns) + , Codec(NBlockCodecs::Codec("lz4fast")) + { + + } + + private: /* IStep, boot logic DSL actor interface */ + void Start() noexcept override + { + for (auto slot: xrange(Back->Switches.size())) if (const auto &largeGlobId = Back->Switches[slot].LargeGlobId) Pending += Spawn<TLoadBlobs>(largeGlobId, slot); - - Flush(); - } - + + Flush(); + } + void HandleStep(TIntrusivePtr<IStep> step) noexcept override - { - auto *load = step->ConsumeAs<TLoadBlobs>(Pending); - - Assign(load->Cookie, load->Plain()); - Flush(); - } - - private: - void Flush() noexcept - { - Process(); - + { + auto *load = step->ConsumeAs<TLoadBlobs>(Pending); + + Assign(load->Cookie, load->Plain()); + Flush(); + } + + private: + void Flush() noexcept + { + Process(); + if (!Pending && Handled >= Back->Switches.size()) Env->Finish(this); - } - + } + void Assign(ui32 slot, TArrayRef<const char> body) noexcept - { - Y_VERIFY(slot < Back->Switches.size(), "Invalid switch index"); - - auto &entry = Back->Switches[slot]; + { + Y_VERIFY(slot < Back->Switches.size(), "Invalid switch index"); + + auto &entry = Back->Switches[slot]; auto index = TCookie(entry.LargeGlobId.Lead.Cookie()).Index(); - + Y_VERIFY(entry.LargeGlobId, "Assigning TSwitch entry w/o valid TLargeGlobId"); - - if (index != TCookie::EIdx::TurnLz4) { - Apply(entry, body); - } else { - Apply(entry, Codec->Decode(body)); - } - } - + + if (index != TCookie::EIdx::TurnLz4) { + Apply(entry, body); + } else { + Apply(entry, Codec->Decode(body)); + } + } + void Apply(TSwitch &entry, TArrayRef<const char> body) noexcept - { - TProtoBox<NKikimrExecutorFlat::TTablePartSwitch> proto(body); - + { + TProtoBox<NKikimrExecutorFlat::TTablePartSwitch> proto(body); + entry.Init(proto); - - if (auto logl = Env->Logger()->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Back) << " switching packs" - << ", table " << entry.Table << ", bundles ["; - + + if (auto logl = Env->Logger()->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Back) << " switching packs" + << ", table " << entry.Table << ", bundles ["; + for (const auto &one : entry.Bundles) { logl << " " << one.LargeGlobIds[0].Lead; if (one.Epoch != NTable::TEpoch::Max()) { logl << "{epoch " << one.Epoch << "}"; } } - + for (const auto &one : entry.Moves) { logl << " " << one.Label; if (one.RebasedEpoch != NTable::TEpoch::Max()) { @@ -89,21 +89,21 @@ namespace NBoot { logl << " from table " << one.SourceTable; } - logl << " ]"; - } - - if (proto.HasTableSnapshoted()) - Back->SetTableEdge(proto.GetTableSnapshoted()); - } - - void Process() noexcept - { - for (; Handled < Back->Switches.size(); Handled++) { - auto &front = Back->Switches[Handled]; - - if (!front.Loaded()) - return; - + logl << " ]"; + } + + if (proto.HasTableSnapshoted()) + Back->SetTableEdge(proto.GetTableSnapshoted()); + } + + void Process() noexcept + { + for (; Handled < Back->Switches.size(); Handled++) { + auto &front = Back->Switches[Handled]; + + if (!front.Loaded()) + return; + for (auto &txStatusId : front.LeavingTxStatus) { auto it = TxStatus.find(txStatusId); if (it == TxStatus.end()) { @@ -132,22 +132,22 @@ namespace NBoot { auto it = Bundles.find(bundleId); if (it == Bundles.end()) { Y_Fail("Part switch has removal for an unknown bundle " << bundleId); - } + } it->second->Load = false; Bundles.erase(it); Leaving.insert(bundleId); - } - + } + for (auto &change : front.Changes) { auto *bundle = Bundles.Value(change.Label, nullptr); if (!bundle) { Y_Fail("Part switch has changes for an unknown bundle " << change.Label); - } + } bundle->Legacy = std::move(change.Legacy); bundle->Opaque = std::move(change.Opaque); bundle->Deltas.clear(); - } - + } + for (auto &delta : front.Deltas) { auto *bundle = Bundles.Value(delta.Label, nullptr); if (!bundle) { @@ -156,19 +156,19 @@ namespace NBoot { bundle->Deltas.push_back(std::move(delta.Delta)); } - for (auto &bundle : front.Bundles) { + for (auto &bundle : front.Bundles) { if (!bundle.LargeGlobIds) { Y_Fail("Part switch has bundle without page collections"); - } + } const auto &bundleId = bundle.LargeGlobIds[0].Lead; if (Bundles.contains(bundleId)) { - Y_Fail("Part switch has a duplicate bundle " << bundleId); - } + Y_Fail("Part switch has a duplicate bundle " << bundleId); + } if (Leaving.contains(bundleId)) { - Y_Fail("Part switch has a removed bundle" << bundleId); - } - Bundles[bundleId] = &bundle; - } + Y_Fail("Part switch has a removed bundle" << bundleId); + } + Bundles[bundleId] = &bundle; + } auto *compaction = Logic->Result().Comp.Get(); @@ -235,18 +235,18 @@ namespace NBoot { std::exchange(front.Changes, { }); std::exchange(front.Deltas, { }); std::exchange(front.Moves, { }); - } - } - - private: - const NBlockCodecs::ICodec *Codec = nullptr; - TLeft Pending; - ui64 Handled = 0; - THashSet<TLogoBlobID> Leaving; /* Dropped bundles */ - THashMap<TLogoBlobID, TSwitch::TBundle*> Bundles; + } + } + + private: + const NBlockCodecs::ICodec *Codec = nullptr; + TLeft Pending; + ui64 Handled = 0; + THashSet<TLogoBlobID> Leaving; /* Dropped bundles */ + THashMap<TLogoBlobID, TSwitch::TBundle*> Bundles; THashSet<TLogoBlobID> LeavingTxStatus; /* Dropped tx status */ THashMap<TLogoBlobID, TSwitch::TTxStatus*> TxStatus; - }; -} -} -} + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_boot_util.h b/ydb/core/tablet_flat/flat_boot_util.h index 54c8bf9b48..5ac65350f2 100644 --- a/ydb/core/tablet_flat/flat_boot_util.h +++ b/ydb/core/tablet_flat/flat_boot_util.h @@ -1,12 +1,12 @@ -#pragma once - -#include <util/system/yassert.h> -#include <util/generic/ylimits.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NBoot { - +#pragma once + +#include <util/system/yassert.h> +#include <util/generic/ylimits.h> + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NBoot { + class TSpawned { public: explicit TSpawned(bool spawned) @@ -22,20 +22,20 @@ namespace NBoot { const bool Spawned; }; - class TLeft { - public: - TLeft() = default; - - explicit operator bool() const noexcept - { - return Value > 0; - } - - ui64 Get() const noexcept - { - return Value; - } - + class TLeft { + public: + TLeft() = default; + + explicit operator bool() const noexcept + { + return Value > 0; + } + + ui64 Get() const noexcept + { + return Value; + } + TLeft& operator +=(const TSpawned& spawned) noexcept { if (spawned) { @@ -45,30 +45,30 @@ namespace NBoot { return *this; } - TLeft& operator +=(size_t inc) noexcept - { - if (Value > Max<decltype(Value)>() - inc) { - - Y_FAIL("TLeft counter is overflowed"); - } - - Value += inc; - - return *this; - } - - TLeft& operator -=(size_t dec) noexcept - { - Y_VERIFY(Value >= dec, "TLeft counter is underflowed"); - - Value -= dec; - - return *this; - } - - private: - ui64 Value = 0; - }; -} -} -} + TLeft& operator +=(size_t inc) noexcept + { + if (Value > Max<decltype(Value)>() - inc) { + + Y_FAIL("TLeft counter is overflowed"); + } + + Value += inc; + + return *this; + } + + TLeft& operator -=(size_t dec) noexcept + { + Y_VERIFY(Value >= dec, "TLeft counter is underflowed"); + + Value -= dec; + + return *this; + } + + private: + ui64 Value = 0; + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_boot_warm.h b/ydb/core/tablet_flat/flat_boot_warm.h index bca1ff0dd1..4ab95c7019 100644 --- a/ydb/core/tablet_flat/flat_boot_warm.h +++ b/ydb/core/tablet_flat/flat_boot_warm.h @@ -1,29 +1,29 @@ -#pragma once - -#include "flat_boot_iface.h" -#include "flat_boot_back.h" -#include "flat_bio_events.h" -#include "flat_dbase_naked.h" +#pragma once + +#include "flat_boot_iface.h" +#include "flat_boot_back.h" +#include "flat_bio_events.h" +#include "flat_dbase_naked.h" #include "flat_mem_blobs.h" -#include "flat_sausage_fetch.h" - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NBoot { - +#include "flat_sausage_fetch.h" + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NBoot { + class TMemTable final: public NBoot::IStep { using TBlobs = NTable::NMem::TBlobs; using TLargeGlobId = NPageCollection::TLargeGlobId; - - public: + + public: TMemTable(IStep *owner) : IStep(owner, NBoot::EStep::MemTable) { } - - private: /* IStep, boot logic DSL actor interface */ - void Start() noexcept override - { + + private: /* IStep, boot logic DSL actor interface */ + void Start() noexcept override + { for (auto it: Back->DatabaseImpl->Scheme->Tables) { const auto &wrap = Back->DatabaseImpl->Get(it.first, true); - + for (auto &mem : wrap->GetMemTables()) { size_t size = mem->GetBlobs()->Size(); if (size > 0) { @@ -39,19 +39,19 @@ namespace NBoot { Pending += Spawn<TLoadBlobs>(TLargeGlobId(it->GId.Group, it->GId.Logo), cookie); ++state.Pending; } - } + } } - } - + } + if (!Pending) { Env->Finish(this); } - } - + } + void HandleStep(TIntrusivePtr<IStep> step) noexcept override - { + { auto *load = step->ConsumeAs<TLoadBlobs>(Pending); - + size_t index = load->Cookie >> 32; Y_VERIFY(index < States.size()); auto& state = States[index]; @@ -68,14 +68,14 @@ namespace NBoot { state.Blobs->Assign(state.Pages); state.Blobs = nullptr; state.Pages.clear(); - } - + } + if (!Pending) { Env->Finish(this); } - } - - private: + } + + private: struct TLoadState { TBlobs* Blobs; TVector<NPageCollection::TLoadedPage> Pages; @@ -84,8 +84,8 @@ namespace NBoot { private: TDeque<TLoadState> States; - TLeft Pending; - }; -} -} -} + TLeft Pending; + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_cxx_database.h b/ydb/core/tablet_flat/flat_cxx_database.h index 27a260bcb2..51b09c3687 100644 --- a/ydb/core/tablet_flat/flat_cxx_database.h +++ b/ydb/core/tablet_flat/flat_cxx_database.h @@ -16,9 +16,9 @@ namespace NKikimr { namespace NIceDb { -using TToughDb = NTable::TDatabase; -using NTable::TUpdateOp; -using NTable::ELookup; +using TToughDb = NTable::TDatabase; +using NTable::TUpdateOp; +using NTable::ELookup; class TTypeValue : public TRawTypeValue { public: @@ -826,7 +826,7 @@ struct Schema { template <typename T> struct TableKeyMaterializer<T> { static void Materialize(TToughDb& database) { - database.Alter().AddColumnToKey(TableId, T::ColumnId); + database.Alter().AddColumnToKey(TableId, T::ColumnId); } }; @@ -972,12 +972,12 @@ struct Schema { KeyIterator& operator =(KeyIterator&&) = default; void Init() { - if (Iterator) + if (Iterator) Next(); /* should invoke for the first key */ } bool IsReady() const { - return Iterator && Iterator->Last() != NTable::EReady::Page; + return Iterator && Iterator->Last() != NTable::EReady::Page; } bool IsValid() const { @@ -990,7 +990,7 @@ struct Schema { bool Next() { while (Iterator->Next(NTable::ENext::Data) == NTable::EReady::Data && IsDeleted()) { } - return IsReady(); + return IsReady(); } TDbTupleRef GetValues() const { @@ -1177,7 +1177,7 @@ struct Schema { { TTupleToRawTypeValue<KeyValuesType, KeyColumnsType> maxKey(keyValues); if (!Precharger<typename TableType::Precharge>::Precharge(database, TableId, {}, maxKey, columns, IteratorType::Direction)) { - return nullptr; + return nullptr; } NTable::TKeyRange range; range.MinKey = { }; @@ -1820,7 +1820,7 @@ struct Schema { template <bool Allow = false> struct ExecutorLogBatching { static void Materialize(TToughDb& database) { - database.Alter().SetExecutorAllowLogBatching(Allow); + database.Alter().SetExecutorAllowLogBatching(Allow); } }; @@ -1834,14 +1834,14 @@ struct Schema { template <ui32 LimitTxInFly = 0> struct ExecutorLimitInFlyTx { static void Materialize(TToughDb& database) { - database.Alter().SetExecutorLimitInFlyTx(LimitTxInFly); + database.Alter().SetExecutorLimitInFlyTx(LimitTxInFly); } }; template <ui64 CacheSize> struct ExecutorCacheSize { static void Materialize(TToughDb& database) { - database.Alter().SetExecutorCacheSize(CacheSize); + database.Alter().SetExecutorCacheSize(CacheSize); } }; @@ -1892,17 +1892,17 @@ struct Schema { break; } - database.Alter().AddTable(GetTableName(TypeName<Type>()), Type::TableId); + database.Alter().AddTable(GetTableName(TypeName<Type>()), Type::TableId); Type::TColumns::Materialize(database); Type::TKey::Materialize(database); } static void Cleanup(TToughDb& database) { - auto* table = database.GetScheme().GetTableInfo(Type::TableId); - if (table != nullptr) { - for (const auto& column : table->Columns) { - if (!Type::TColumns::HaveColumn(column.first)) { - database.Alter().DropColumn(Type::TableId, column.first); + auto* table = database.GetScheme().GetTableInfo(Type::TableId); + if (table != nullptr) { + for (const auto& column : table->Columns) { + if (!Type::TColumns::HaveColumn(column.first)) { + database.Alter().DropColumn(Type::TableId, column.first); } } } @@ -1971,10 +1971,10 @@ public: template <typename SchemaType> void Cleanup() { SchemaType::TTables::Cleanup(Database); - - for (const auto& table : Database.GetScheme().Tables) { - if (!SchemaType::TTables::HaveTable(table.first)) { - Database.Alter().DropTable(table.first); + + for (const auto& table : Database.GetScheme().Tables) { + if (!SchemaType::TTables::HaveTable(table.first)) { + Database.Alter().DropTable(table.first); } } } diff --git a/ydb/core/tablet_flat/flat_cxx_database_ut.cpp b/ydb/core/tablet_flat/flat_cxx_database_ut.cpp index 0423d82e62..e0186e79cd 100644 --- a/ydb/core/tablet_flat/flat_cxx_database_ut.cpp +++ b/ydb/core/tablet_flat/flat_cxx_database_ut.cpp @@ -3,15 +3,15 @@ #include <ydb/core/tablet_flat/test/libs/table/test_dummy.h> #include <ydb/library/mkql_proto/protos/minikql.pb.h> #include "flat_cxx_database.h" -#include "flat_dbase_scheme.h" -#include "flat_dbase_apply.h" +#include "flat_dbase_scheme.h" +#include "flat_dbase_apply.h" namespace NKikimr { -namespace NTable { +namespace NTable { Y_UNIT_TEST_SUITE(TFlatCxxDatabaseTest) { - using TDummyEnv = NTable::TDummyEnv; + using TDummyEnv = NTable::TDummyEnv; enum ESomeEnum : ui8 { SomeValue0, @@ -67,7 +67,7 @@ Y_UNIT_TEST_SUITE(TFlatCxxDatabaseTest) { }; Y_UNIT_TEST(BasicSchemaTest) { - TDatabase DB; + TDatabase DB; NIceDb::TNiceDb db(DB); ui64 stamp = 0; @@ -587,16 +587,16 @@ Y_UNIT_TEST_SUITE(TFlatCxxDatabaseTest) { Y_UNIT_TEST(RenameColumnSchemaTest) { TScheme scheme; - TSchemeModifier applier(scheme); - TAlter delta; + TSchemeModifier applier(scheme); + TAlter delta; delta.AddTable("test", 1); - delta.AddColumn(1, "test", 1, 1, { }); - applier.Apply(*delta.Flush()); + delta.AddColumn(1, "test", 1, 1, { }); + applier.Apply(*delta.Flush()); delta.AddTable("testtest", 1); - delta.AddColumn(1, "testtest", 1, 1, { }); - applier.Apply(*delta.Flush()); + delta.AddColumn(1, "testtest", 1, 1, { }); + applier.Apply(*delta.Flush()); UNIT_ASSERT(scheme.Tables.find(1)->second.Name == "testtest"); UNIT_ASSERT(scheme.TableNames.find("testtest")->second == 1); diff --git a/ydb/core/tablet_flat/flat_database.cpp b/ydb/core/tablet_flat/flat_database.cpp index c459119515..e65d452809 100644 --- a/ydb/core/tablet_flat/flat_database.cpp +++ b/ydb/core/tablet_flat/flat_database.cpp @@ -1,37 +1,37 @@ -#include "defs.h" -#include "flat_abi_evol.h" +#include "defs.h" +#include "flat_abi_evol.h" #include "flat_database.h" -#include "flat_redo_writer.h" -#include "flat_redo_player.h" -#include "flat_dbase_naked.h" -#include "flat_dbase_apply.h" -#include "flat_dbase_annex.h" -#include "flat_dbase_sz_env.h" -#include "flat_part_shrink.h" -#include "flat_util_misc.h" -#include "flat_sausage_grind.h" +#include "flat_redo_writer.h" +#include "flat_redo_player.h" +#include "flat_dbase_naked.h" +#include "flat_dbase_apply.h" +#include "flat_dbase_annex.h" +#include "flat_dbase_sz_env.h" +#include "flat_part_shrink.h" +#include "flat_util_misc.h" +#include "flat_sausage_grind.h" #include <ydb/core/util/pb.h> #include <ydb/core/scheme_types/scheme_type_registry.h> -#include <util/generic/cast.h> +#include <util/generic/cast.h> #define MAX_REDO_BYTES_PER_COMMIT 268435456U // 256MB namespace NKikimr { -namespace NTable { +namespace NTable { TDatabase::TDatabase(TDatabaseImpl *databaseImpl) noexcept : DatabaseImpl(databaseImpl ? databaseImpl : new TDatabaseImpl(0, new TScheme, nullptr)) , NoMoreReadsFlag(true) -{ - +{ + } -TDatabase::~TDatabase() { } - -const TScheme& TDatabase::GetScheme() const noexcept -{ +TDatabase::~TDatabase() { } + +const TScheme& TDatabase::GetScheme() const noexcept +{ return *DatabaseImpl->Scheme; } @@ -41,32 +41,32 @@ TIntrusiveConstPtr<TRowScheme> TDatabase::GetRowScheme(ui32 table) const noexcep } TAutoPtr<TTableIt> TDatabase::Iterate(ui32 table, TRawVals key, TTagsRef tags, ELookup mode) const noexcept -{ - Y_VERIFY(!NoMoreReadsFlag, "Trying to read after reads prohibited, table %u", table); - - const auto seekBy = [](TRawVals key, ELookup mode) { - if (!key && mode != ELookup::ExactMatch) { - /* Compatability mode with outer iterator interface that yields - * begin() for non-exact lookups with empty key. Inner iterator - * yields begin() for ({}, Lower) and end() for ({}, Upper). - */ - - return ESeek::Lower; - - } else { - switch (mode) { - case ELookup::ExactMatch: - return ESeek::Exact; - case ELookup::GreaterThan: - return ESeek::Upper; - case ELookup::GreaterOrEqualThan: - return ESeek::Lower; - } - } - - Y_FAIL("Don't know how to convert ELookup to ESeek mode"); - }; - +{ + Y_VERIFY(!NoMoreReadsFlag, "Trying to read after reads prohibited, table %u", table); + + const auto seekBy = [](TRawVals key, ELookup mode) { + if (!key && mode != ELookup::ExactMatch) { + /* Compatability mode with outer iterator interface that yields + * begin() for non-exact lookups with empty key. Inner iterator + * yields begin() for ({}, Lower) and end() for ({}, Upper). + */ + + return ESeek::Lower; + + } else { + switch (mode) { + case ELookup::ExactMatch: + return ESeek::Exact; + case ELookup::GreaterThan: + return ESeek::Upper; + case ELookup::GreaterOrEqualThan: + return ESeek::Lower; + } + } + + Y_FAIL("Don't know how to convert ELookup to ESeek mode"); + }; + IteratedTables.insert(table); return Require(table)->Iterate(key, tags, Env, seekBy(key, mode), TRowVersion::Max()); @@ -144,17 +144,17 @@ TAutoPtr<TTableReverseIt> TDatabase::IterateRangeGeneric<TTableReverseIt>(ui32 t } EReady TDatabase::Select(ui32 table, TRawVals key, TTagsRef tags, TRowState &row, ui64 flg, TRowVersion snapshot) const noexcept -{ +{ TempIterators.clear(); - Y_VERIFY(!NoMoreReadsFlag, "Trying to read after reads prohibited, table %u", table); + Y_VERIFY(!NoMoreReadsFlag, "Trying to read after reads prohibited, table %u", table); auto res = Require(table)->Select(key, tags, Env, row, flg, snapshot, TempIterators); - Change->Stats.SelectSieved += res.Sieved; - Change->Stats.SelectWeeded += res.Weeded; - Change->Stats.SelectNoKey += res.NoKey; + Change->Stats.SelectSieved += res.Sieved; + Change->Stats.SelectWeeded += res.Weeded; + Change->Stats.SelectNoKey += res.NoKey; Change->Stats.SelectInvisible += res.Invisible; - return res.Ready; -} - + return res.Ready; +} + EReady TDatabase::Select(ui32 table, TRawVals key, TTagsRef tags, TRowState &row, TSelectStats& stats, ui64 flg, TRowVersion snapshot) const noexcept { TempIterators.clear(); @@ -177,7 +177,7 @@ void TDatabase::CalculateReadSize(TSizeEnv& env, ui32 table, TRawVals minKey, TR TTagsRef tags, ui64 flg, ui64 items, ui64 bytes, EDirection direction, TRowVersion snapshot) { - Y_VERIFY(!NoMoreReadsFlag, "Trying to do precharge after reads prohibited, table %u", table); + Y_VERIFY(!NoMoreReadsFlag, "Trying to do precharge after reads prohibited, table %u", table); Require(table)->Precharge(minKey, maxKey, tags, &env, flg, items, bytes, direction, snapshot); } @@ -185,15 +185,15 @@ bool TDatabase::Precharge(ui32 table, TRawVals minKey, TRawVals maxKey, TTagsRef tags, ui64 flg, ui64 items, ui64 bytes, EDirection direction, TRowVersion snapshot) { - Y_VERIFY(!NoMoreReadsFlag, "Trying to do precharge after reads prohibited, table %u", table); + Y_VERIFY(!NoMoreReadsFlag, "Trying to do precharge after reads prohibited, table %u", table); auto res = Require(table)->Precharge(minKey, maxKey, tags, Env, flg, items, bytes, direction, snapshot); - Change->Stats.ChargeSieved += res.Sieved; - Change->Stats.ChargeWeeded += res.Weeded; - return res.Ready == EReady::Data; + Change->Stats.ChargeSieved += res.Sieved; + Change->Stats.ChargeWeeded += res.Weeded; + return res.Ready == EReady::Data; } void TDatabase::Update(ui32 table, ERowOp rop, TRawVals key, TArrayRef<const TUpdateOp> ops, TRowVersion rowVersion) -{ +{ Y_VERIFY_DEBUG(rowVersion != TRowVersion::Max(), "Updates cannot have v{max} as row version"); Redo->EvUpdate(table, rop, key, ops, rowVersion); @@ -236,8 +236,8 @@ void TDatabase::NoMoreReadsForTx() { } void TDatabase::Begin(TTxStamp stamp, IPages& env) -{ - Y_VERIFY(!Redo, "Transaction already in progress"); +{ + Y_VERIFY(!Redo, "Transaction already in progress"); Y_VERIFY(!Env); Annex = new TAnnex(*DatabaseImpl->Scheme); Redo = new NRedo::TWriter{ Annex.Get(), DatabaseImpl->AnnexByteLimit() }; @@ -294,76 +294,76 @@ ui64 TDatabase::EstimateRowSize(ui32 tableId) const { return Require(tableId)->EstimateRowSize(); } -const TDbStats& TDatabase::Counters() const noexcept -{ +const TDbStats& TDatabase::Counters() const noexcept +{ return DatabaseImpl->Stats; } -TDatabase::TChg TDatabase::Head(ui32 table) const noexcept -{ - if (table == Max<ui32>()) { +TDatabase::TChg TDatabase::Head(ui32 table) const noexcept +{ + if (table == Max<ui32>()) { return { DatabaseImpl->Serial(), TEpoch::Max() }; - } else { + } else { auto &wrap = DatabaseImpl->Get(table, true); - - return { wrap.Serial, wrap->Head() }; - } + + return { wrap.Serial, wrap->Head() }; + } } -TString TDatabase::SnapshotToLog(ui32 table, TTxStamp stamp) -{ +TString TDatabase::SnapshotToLog(ui32 table, TTxStamp stamp) +{ auto scn = DatabaseImpl->Serial() + 1; auto epoch = DatabaseImpl->Get(table, true)->Snapshot(); - + DatabaseImpl->Rewind(scn); - - return - NRedo::TWriter{ } + + return + NRedo::TWriter{ } .EvBegin(ui32(ECompatibility::Head), ui32(ECompatibility::Edge), scn, stamp) - .EvFlush(table, stamp, epoch).Dump(); + .EvFlush(table, stamp, epoch).Dump(); } -ui32 TDatabase::TxSnapTable(ui32 table) -{ - Require(table); - Change->Snapshots.emplace_back(table); - return Change->Snapshots.size() - 1; +ui32 TDatabase::TxSnapTable(ui32 table) +{ + Require(table); + Change->Snapshots.emplace_back(table); + return Change->Snapshots.size() - 1; } TAutoPtr<TSubset> TDatabase::Subset(ui32 table, TArrayRef<const TLogoBlobID> bundle, TEpoch before) const -{ +{ return Require(table)->Subset(bundle, before); } TAutoPtr<TSubset> TDatabase::Subset(ui32 table, TEpoch before, TRawVals from, TRawVals to) const -{ - auto subset = Require(table)->Subset(before); - - if (from || to) { - Y_VERIFY(!subset->Frozen, "Got subset with frozens, cannot shrink it"); +{ + auto subset = Require(table)->Subset(before); + + if (from || to) { + Y_VERIFY(!subset->Frozen, "Got subset with frozens, cannot shrink it"); Y_VERIFY(!subset->ColdParts, "Got subset with cold parts, cannot shrink it"); - + TShrink shrink(Env, subset->Scheme->Keys); - - if (shrink.Put(subset->Flatten, from, to).Skipped) { - return nullptr; /* Cannot shrink due to lack of some pages */ - } else { + + if (shrink.Put(subset->Flatten, from, to).Skipped) { + return nullptr; /* Cannot shrink due to lack of some pages */ + } else { subset->Flatten = std::move(shrink.PartView); - } - } - - return subset; -} - + } + } + + return subset; +} + TAutoPtr<TSubset> TDatabase::ScanSnapshot(ui32 table, TRowVersion snapshot) { return Require(table)->ScanSnapshot(snapshot); } TBundleSlicesMap TDatabase::LookupSlices(ui32 table, TArrayRef<const TLogoBlobID> bundles) const -{ +{ return Require(table)->LookupSlices(bundles); -} +} void TDatabase::ReplaceSlices(ui32 table, TBundleSlicesMap slices) { @@ -381,7 +381,7 @@ void TDatabase::ReplaceTxStatus(ui32 table, TArrayRef<const TIntrusiveConstPtr<T } void TDatabase::Merge(ui32 table, TPartView partView) -{ +{ return DatabaseImpl->Merge(table, std::move(partView)); } @@ -395,16 +395,16 @@ void TDatabase::Merge(ui32 table, TIntrusiveConstPtr<TTxStatusPart> txStatus) return DatabaseImpl->Merge(table, std::move(txStatus)); } -TAlter& TDatabase::Alter() -{ - Y_VERIFY(Redo, "Scheme change must be done within a transaction"); - Y_VERIFY(!*Redo, "Scheme change must be done before any data updates"); - - return *(Alter_ ? Alter_ : (Alter_ = new TAlter())); +TAlter& TDatabase::Alter() +{ + Y_VERIFY(Redo, "Scheme change must be done within a transaction"); + Y_VERIFY(!*Redo, "Scheme change must be done before any data updates"); + + return *(Alter_ ? Alter_ : (Alter_ = new TAlter())); } -void TDatabase::DebugDumpTable(ui32 table, IOutputStream& str, const NScheme::TTypeRegistry& typeRegistry) const { - str << "Table " << table << Endl; +void TDatabase::DebugDumpTable(ui32 table, IOutputStream& str, const NScheme::TTypeRegistry& typeRegistry) const { + str << "Table " << table << Endl; if (auto &wrap = DatabaseImpl->Get(table, false)) wrap->DebugDump(str, Env, typeRegistry); else @@ -414,8 +414,8 @@ void TDatabase::DebugDumpTable(ui32 table, IOutputStream& str, const NScheme::TT void TDatabase::DebugDump(IOutputStream& str, const NScheme::TTypeRegistry& typeRegistry) const { for (const auto& it: DatabaseImpl->Scheme->Tables) { if (DatabaseImpl->Get(it.first, false)) { - str << "======= " << it.second.Name << " ======\n"; - DebugDumpTable(it.first, str, typeRegistry); + str << "======= " << it.second.Name << " ======\n"; + DebugDumpTable(it.first, str, typeRegistry); } } } @@ -441,7 +441,7 @@ bool TDatabase::ValidateCommit(TString &err) } TDatabase::TProd TDatabase::Commit(TTxStamp stamp, bool commit, TCookieAllocator *cookieAllocator) -{ +{ TempIterators.clear(); if (IteratedTables) { @@ -457,66 +457,66 @@ TDatabase::TProd TDatabase::Commit(TTxStamp stamp, bool commit, TCookieAllocator } if (commit && (*Redo || Alter_ || Change->Snapshots || Change->RemovedRowVersions)) { - Y_VERIFY(stamp >= Change->Stamp); - - /* TODO: Temporary hack fot getting correct Stamp and Serial state - against invocation of SnapshotToLog() between Begin(...) and - Commit(...). Read KIKIMR-5366 for details and progress. */ - - const_cast<TTxStamp&>(Change->Stamp) = stamp; + Y_VERIFY(stamp >= Change->Stamp); + + /* TODO: Temporary hack fot getting correct Stamp and Serial state + against invocation of SnapshotToLog() between Begin(...) and + Commit(...). Read KIKIMR-5366 for details and progress. */ + + const_cast<TTxStamp&>(Change->Stamp) = stamp; const_cast<ui64&>(Change->Serial) = DatabaseImpl->Serial() + 1; - - NRedo::TWriter prefix{ }; - - { + + NRedo::TWriter prefix{ }; + + { const ui32 head = ui32(ECompatibility::Head); const ui32 edge = ui32(ECompatibility::Edge); - - prefix.EvBegin(head, edge, Change->Serial, Change->Stamp); - } - - const auto offset = prefix.Bytes(); /* useful payload starts here */ - - if (auto annex = Annex->Unwrap()) { + + prefix.EvBegin(head, edge, Change->Serial, Change->Stamp); + } + + const auto offset = prefix.Bytes(); /* useful payload starts here */ + + if (auto annex = Annex->Unwrap()) { Y_VERIFY(cookieAllocator, "Have to provide TCookieAllocator with enabled annex"); - + TVector<NPageCollection::TGlobId> blobs; - - blobs.reserve(annex.size()); - - for (auto &one: annex) { + + blobs.reserve(annex.size()); + + for (auto &one: annex) { auto glob = cookieAllocator->Do(one.GId.Logo.Channel(), one.Data.size()); - - blobs.emplace_back(one.GId = glob); - - Y_VERIFY(glob.Logo.BlobSize(), "Blob cannot have zero bytes"); - } - - prefix.EvAnnex(blobs); + + blobs.emplace_back(one.GId = glob); + + Y_VERIFY(glob.Logo.BlobSize(), "Blob cannot have zero bytes"); + } + + prefix.EvAnnex(blobs); DatabaseImpl->Assign(std::move(annex)); - } - + } + DatabaseImpl->Switch(Stamp); - - if (Alter_) { - auto delta = Alter_->Flush(); + + if (Alter_) { + auto delta = Alter_->Flush(); if (DatabaseImpl->Apply(*delta, &prefix)) Y_PROTOBUF_SUPPRESS_NODISCARD delta->SerializeToString(&Change->Scheme); } - for (auto &one: Change->Snapshots) { - one.Epoch = Require(one.Table)->Snapshot(); - prefix.EvFlush(one.Table, Stamp, one.Epoch); - } - - prefix.Join(*Redo); - - Change->Redo = prefix.Dump(); - - for (auto &entry: prefix.Unwrap()) + for (auto &one: Change->Snapshots) { + one.Epoch = Require(one.Table)->Snapshot(); + prefix.EvFlush(one.Table, Stamp, one.Epoch); + } + + prefix.Join(*Redo); + + Change->Redo = prefix.Dump(); + + for (auto &entry: prefix.Unwrap()) DatabaseImpl->ApplyRedo(entry); - + for (const auto& xpair : Change->RemovedRowVersions) { if (auto& wrap = DatabaseImpl->Get(xpair.first, false)) { for (const auto& range : xpair.second) { @@ -529,57 +529,57 @@ TDatabase::TProd TDatabase::Commit(TTxStamp stamp, bool commit, TCookieAllocator Change->Deleted = std::move(DatabaseImpl->Deleted); Change->Affects = DatabaseImpl->GrabAffects(); Change->Annex = DatabaseImpl->GrabAnnex(); - - if (Change->Redo.size() == offset && !Change->Affects) { - std::exchange(Change->Redo, { }); /* omit complete NOOP redo */ - } - - if (Change->Redo.size() > offset && !Change->Affects) { - Y_Fail( + + if (Change->Redo.size() == offset && !Change->Affects) { + std::exchange(Change->Redo, { }); /* omit complete NOOP redo */ + } + + if (Change->Redo.size() > offset && !Change->Affects) { + Y_Fail( NFmt::Do(*Change) << " produced " << (Change->Redo.size() - offset) - << "b of non technical redo without leaving effects on data"); + << "b of non technical redo without leaving effects on data"); } else if (Change->Serial != DatabaseImpl->Serial()) { - Y_Fail( - NFmt::Do(*Change) << " serial diverged from current db " + Y_Fail( + NFmt::Do(*Change) << " serial diverged from current db " << DatabaseImpl->Serial() << " after rolling up redo log"); - } else if (Change->Deleted.size() != Change->Garbage.size()) { - Y_Fail(NFmt::Do(*Change) << " has inconsistent garbage data"); - } + } else if (Change->Deleted.size() != Change->Garbage.size()) { + Y_Fail(NFmt::Do(*Change) << " has inconsistent garbage data"); + } } - Redo = nullptr; - Annex = nullptr; - Alter_ = nullptr; + Redo = nullptr; + Annex = nullptr; + Alter_ = nullptr; Env = nullptr; - + return { std::move(Change) }; } -TTable* TDatabase::Require(ui32 table) const noexcept -{ +TTable* TDatabase::Require(ui32 table) const noexcept +{ return DatabaseImpl->Get(table, true).Self.Get(); -} - +} + TGarbage TDatabase::RollUp(TTxStamp stamp, TArrayRef<const char> delta, TArrayRef<const char> redo, TMemGlobs annex) { - Y_VERIFY(!annex || redo, "Annex have to be rolled up with redo log"); - + Y_VERIFY(!annex || redo, "Annex have to be rolled up with redo log"); + DatabaseImpl->Switch(stamp); - if (delta) { - TSchemeChanges changes; - bool parseOk = ParseFromStringNoSizeLimit(changes, delta); - Y_VERIFY(parseOk); - + if (delta) { + TSchemeChanges changes; + bool parseOk = ParseFromStringNoSizeLimit(changes, delta); + Y_VERIFY(parseOk); + DatabaseImpl->Apply(changes, nullptr); - } + } - if (redo) { + if (redo) { DatabaseImpl->Assign(std::move(annex)); DatabaseImpl->ApplyRedo(redo); DatabaseImpl->GrabAnnex(); - } + } return std::move(DatabaseImpl->Garbage); } diff --git a/ydb/core/tablet_flat/flat_database.h b/ydb/core/tablet_flat/flat_database.h index 98baa8f438..ba16bd4adc 100644 --- a/ydb/core/tablet_flat/flat_database.h +++ b/ydb/core/tablet_flat/flat_database.h @@ -1,35 +1,35 @@ #pragma once -#include "flat_row_eggs.h" +#include "flat_row_eggs.h" #include "flat_row_versions.h" #include "flat_update_op.h" -#include "flat_dbase_scheme.h" -#include "flat_dbase_change.h" -#include "flat_dbase_misc.h" +#include "flat_dbase_scheme.h" +#include "flat_dbase_change.h" +#include "flat_dbase_misc.h" #include "flat_iterator.h" #include "util_basics.h" namespace NKikimr { - + namespace NPageCollection { class TCookieAllocator; struct TMemGlob; -} - -namespace NTable { - - struct TStats; - struct TSizeEnv; - class TRowState; - struct TChange; +} + +namespace NTable { + + struct TStats; + struct TSizeEnv; + class TRowState; + struct TChange; class TDatabaseImpl; - class TAnnex; - class TTable; + class TAnnex; + class TTable; class TKeyRangeCache; - - namespace NRedo { - class TWriter; - } - + + namespace NRedo { + class TWriter; + } + struct TKeyRange { TRawVals MinKey; TRawVals MaxKey; @@ -37,36 +37,36 @@ struct TKeyRange { bool MaxInclusive = true; }; -class TDatabase { +class TDatabase { public: using TMemGlobs = TVector<NPageCollection::TMemGlob>; using TCookieAllocator = NPageCollection::TCookieAllocator; - using TCounters = TDbStats; + using TCounters = TDbStats; - struct TProd { + struct TProd { THolder<TChange> Change; - }; - - struct TChg { - ui64 Serial; + }; + + struct TChg { + ui64 Serial; TEpoch Epoch; - }; - - TDatabase(const TDatabase&) = delete; + }; + + TDatabase(const TDatabase&) = delete; TDatabase(TDatabaseImpl *databaseImpl = nullptr) noexcept; ~TDatabase(); - /* Returns durable monotonic change number for table or entire database - on default (table = Max<ui32>()). Serial is incremented for each - successful Commit(). AHTUNG: Serial may go to the past in case of - migration to older db versions with (Evolution < 18). Thus do not - rely on durability until of kikimr stable 18-08. - */ - - TChg Head(ui32 table = Max<ui32>()) const noexcept; - - /*_ Call Next() before accessing each row including the 1st row. */ - + /* Returns durable monotonic change number for table or entire database + on default (table = Max<ui32>()). Serial is incremented for each + successful Commit(). AHTUNG: Serial may go to the past in case of + migration to older db versions with (Evolution < 18). Thus do not + rely on durability until of kikimr stable 18-08. + */ + + TChg Head(ui32 table = Max<ui32>()) const noexcept; + + /*_ Call Next() before accessing each row including the 1st row. */ + TAutoPtr<TTableIt> Iterate(ui32 table, TRawVals key, TTagsRef tags, ELookup) const noexcept; TAutoPtr<TTableIt> IterateExact(ui32 table, TRawVals key, TTagsRef tags, TRowVersion snapshot = TRowVersion::Max()) const noexcept; TAutoPtr<TTableIt> IterateRange(ui32 table, const TKeyRange& range, TTagsRef tags, TRowVersion snapshot = TRowVersion::Max()) const noexcept; @@ -93,7 +93,7 @@ public: TRowVersion snapshot = TRowVersion::Max()); void Update(ui32 table, ERowOp, TRawVals key, TArrayRef<const TUpdateOp>, TRowVersion rowVersion = TRowVersion::Min()); - + void UpdateTx(ui32 table, ERowOp, TRawVals key, TArrayRef<const TUpdateOp>, ui64 txId); void RemoveTx(ui32 table, ui64 txId); void CommitTx(ui32 table, ui64 txId, TRowVersion rowVersion = TRowVersion::Min()); @@ -116,11 +116,11 @@ public: void NoMoreReadsForTx(); - TAlter& Alter(); /* Begin DDL ALTER script */ - - ui32 TxSnapTable(ui32 table); - - const TScheme& GetScheme() const noexcept; + TAlter& Alter(); /* Begin DDL ALTER script */ + + ui32 TxSnapTable(ui32 table); + + const TScheme& GetScheme() const noexcept; TIntrusiveConstPtr<TRowScheme> GetRowScheme(ui32 table) const noexcept; @@ -133,16 +133,16 @@ public: void EnumerateTxStatusParts(const std::function<void(const TIntrusiveConstPtr<TTxStatusPart>&)>& callback) const; ui64 GetTableMemSize(ui32 table, TEpoch epoch = TEpoch::Max()) const; ui64 GetTableMemRowCount(ui32 tableId) const; - ui64 GetTableIndexSize(ui32 table) const; + ui64 GetTableIndexSize(ui32 table) const; ui64 GetTableSearchHeight(ui32 table) const; - ui64 EstimateRowSize(ui32 table) const; - const TCounters& Counters() const noexcept; - TString SnapshotToLog(ui32 table, TTxStamp); + ui64 EstimateRowSize(ui32 table) const; + const TCounters& Counters() const noexcept; + TString SnapshotToLog(ui32 table, TTxStamp); TAutoPtr<TSubset> Subset(ui32 table, TArrayRef<const TLogoBlobID> bundle, TEpoch before) const; TAutoPtr<TSubset> Subset(ui32 table, TEpoch before, TRawVals from, TRawVals to) const; TAutoPtr<TSubset> ScanSnapshot(ui32 table, TRowVersion snapshot = TRowVersion::Max()); - + TBundleSlicesMap LookupSlices(ui32 table, TArrayRef<const TLogoBlobID> bundles) const; void ReplaceSlices(ui32 table, TBundleSlicesMap slices); @@ -152,7 +152,7 @@ public: void Merge(ui32 table, TIntrusiveConstPtr<TColdPart>); void Merge(ui32 table, TIntrusiveConstPtr<TTxStatusPart>); - void DebugDumpTable(ui32 table, IOutputStream& str, const NScheme::TTypeRegistry& typeRegistry) const; + void DebugDumpTable(ui32 table, IOutputStream& str, const NScheme::TTypeRegistry& typeRegistry) const; void DebugDump(IOutputStream& str, const NScheme::TTypeRegistry& typeRegistry) const; TKeyRangeCache* DebugGetTableErasedKeysCache(ui32 table) const; @@ -169,12 +169,12 @@ public: TCompactionStats GetCompactionStats(ui32 table) const; private: - TTable* Require(ui32 tableId) const noexcept; - + TTable* Require(ui32 tableId) const noexcept; + private: const THolder<TDatabaseImpl> DatabaseImpl; - ui64 Stamp = Max<ui64>(); + ui64 Stamp = Max<ui64>(); bool NoMoreReadsFlag; IPages* Env = nullptr; THolder<TChange> Change; diff --git a/ydb/core/tablet_flat/flat_dbase_annex.h b/ydb/core/tablet_flat/flat_dbase_annex.h index 754103c95d..fd7dcbcafb 100644 --- a/ydb/core/tablet_flat/flat_dbase_annex.h +++ b/ydb/core/tablet_flat/flat_dbase_annex.h @@ -1,73 +1,73 @@ -#pragma once - -#include "flat_page_label.h" -#include "flat_redo_writer.h" -#include "flat_dbase_scheme.h" -#include "flat_sausage_solid.h" - -namespace NKikimr { -namespace NTable { - - class TAnnex : public NRedo::IAnnex { - using TFamily = TScheme::TFamily; +#pragma once + +#include "flat_page_label.h" +#include "flat_redo_writer.h" +#include "flat_dbase_scheme.h" +#include "flat_sausage_solid.h" + +namespace NKikimr { +namespace NTable { + + class TAnnex : public NRedo::IAnnex { + using TFamily = TScheme::TFamily; using TGlobId = NPageCollection::TGlobId; - - public: - TAnnex(const TScheme &scheme) : Scheme(scheme) { } - + + public: + TAnnex(const TScheme &scheme) : Scheme(scheme) { } + TVector<NPageCollection::TMemGlob> Unwrap() noexcept - { - return std::move(Blobs); - } - - explicit operator bool() const noexcept - { - return bool(Blobs); - } - - private: + { + return std::move(Blobs); + } + + explicit operator bool() const noexcept + { + return bool(Blobs); + } + + private: TLimit Limit(ui32 table) noexcept override - { + { if (Lookup(table)) { return TLimit{ Family->Large, 8 * 1024 * 1024 - 8 }; } else { return TLimit{ Max<ui32>(), 0 }; } - } - + } + TResult Place(ui32 table, TTag, TArrayRef<const char> data) noexcept override - { + { Y_VERIFY(Lookup(table) && data.size() >= Family->Large); - + auto blob = NPage::THello::Wrap(data, EPage::Opaque, 0); - + const TLogoBlobID fake(0, 0, 0, Room->Blobs, blob.size(), 0); - + Blobs.emplace_back(TGlobId{ fake, 0 }, std::move(blob)); return Blobs.size() - 1; - } - - bool Lookup(ui32 table) noexcept - { - if (std::exchange(Table, table) != table) { - Family = Scheme.DefaultFamilyFor(Table); - Room = Scheme.DefaultRoomFor(Table); - - Y_VERIFY(bool(Family) == bool(Room)); - } - - return nullptr != Family; /* table may be created with data tx */ - } - - private: - const TScheme &Scheme; + } + + bool Lookup(ui32 table) noexcept + { + if (std::exchange(Table, table) != table) { + Family = Scheme.DefaultFamilyFor(Table); + Room = Scheme.DefaultRoomFor(Table); + + Y_VERIFY(bool(Family) == bool(Room)); + } + + return nullptr != Family; /* table may be created with data tx */ + } + + private: + const TScheme &Scheme; TVector<NPageCollection::TMemGlob> Blobs; - - /*_ Simple table info lookup cache */ - ui32 Table = Max<ui32>(); - const TScheme::TFamily *Family = nullptr; - const TScheme::TRoom *Room = nullptr; - }; -} -} + + /*_ Simple table info lookup cache */ + ui32 Table = Max<ui32>(); + const TScheme::TFamily *Family = nullptr; + const TScheme::TRoom *Room = nullptr; + }; +} +} diff --git a/ydb/core/tablet_flat/flat_dbase_apply.cpp b/ydb/core/tablet_flat/flat_dbase_apply.cpp index f87b315d33..de5ec675e9 100644 --- a/ydb/core/tablet_flat/flat_dbase_apply.cpp +++ b/ydb/core/tablet_flat/flat_dbase_apply.cpp @@ -1,96 +1,96 @@ -#include "flat_dbase_apply.h" - +#include "flat_dbase_apply.h" + #include <ydb/core/base/localdb.h> - -namespace NKikimr { -namespace NTable { - - -TSchemeModifier::TSchemeModifier(TScheme &scheme) - : Scheme(scheme) -{ - -} - -bool TSchemeModifier::Apply(const TAlterRecord &delta) -{ - const auto table = delta.HasTableId() ? delta.GetTableId() : Max<ui32>(); - const auto action = delta.GetDeltaType(); - bool changes = false; - - if (action == TAlterRecord::AddTable) { - changes = AddTable(delta.GetTableName(), table); - } else if (action == TAlterRecord::DropTable) { - changes = DropTable(table); - } else if (action == TAlterRecord::AddColumn) { - TCell null; - - if (delta.HasDefault()) { - auto raw = delta.GetDefault(); - - null = TCell(raw.data(), raw.size()); - } - - changes = AddColumn(table, delta.GetColumnName(), delta.GetColumnId(), + +namespace NKikimr { +namespace NTable { + + +TSchemeModifier::TSchemeModifier(TScheme &scheme) + : Scheme(scheme) +{ + +} + +bool TSchemeModifier::Apply(const TAlterRecord &delta) +{ + const auto table = delta.HasTableId() ? delta.GetTableId() : Max<ui32>(); + const auto action = delta.GetDeltaType(); + bool changes = false; + + if (action == TAlterRecord::AddTable) { + changes = AddTable(delta.GetTableName(), table); + } else if (action == TAlterRecord::DropTable) { + changes = DropTable(table); + } else if (action == TAlterRecord::AddColumn) { + TCell null; + + if (delta.HasDefault()) { + auto raw = delta.GetDefault(); + + null = TCell(raw.data(), raw.size()); + } + + changes = AddColumn(table, delta.GetColumnName(), delta.GetColumnId(), delta.GetColumnType(), delta.GetNotNull(), null); - } else if (action == TAlterRecord::DropColumn) { - changes = DropColumn(table, delta.GetColumnId()); - } else if (action == TAlterRecord::AddColumnToKey) { - changes = AddColumnToKey(table, delta.GetColumnId()); - } else if (action == TAlterRecord::AddFamily) { - auto &family = Table(table)->Families[delta.GetFamilyId()]; - - const ui32 room = delta.GetRoomId(); - - changes = (std::exchange(family.Room, room) != room); - - } else if (action == TAlterRecord::SetFamily) { - auto &family = Table(table)->Families[delta.GetFamilyId()]; - - auto codec = delta.HasCodec() ? ECodec(delta.GetCodec()) :family.Codec; - - Y_VERIFY(ui32(codec) <= 1, "Invalid page encoding code value"); - - bool ever = delta.HasInMemory() && delta.GetInMemory(); - auto cache = ever ? ECache::Ever : family.Cache; - - cache = delta.HasCache() ? ECache(delta.GetCache()) : cache; - ui32 small = delta.HasSmall() ? delta.GetSmall() : family.Small; - ui32 large = delta.HasLarge() ? delta.GetLarge() : family.Large; - - Y_VERIFY(ui32(cache) <= 2, "Invalid pages cache policy value"); - - changes = - (std::exchange(family.Cache, cache) != cache) - | (std::exchange(family.Codec, codec) != codec) - | (std::exchange(family.Small, small) != small) - | (std::exchange(family.Large, large) != large); - - } else if (action == TAlterRecord::AddColumnToFamily) { - changes = AddColumnToFamily(table, delta.GetColumnId(), delta.GetFamilyId()); - } else if (action == TAlterRecord::SetRoom) { - auto &room = Table(table)->Rooms[delta.GetRoomId()]; - - ui32 main = delta.HasMain() ? delta.GetMain() : room.Main; - ui32 blobs = delta.HasBlobs() ? delta.GetBlobs() : room.Blobs; - ui32 outer = delta.HasOuter() ? delta.GetOuter() : room.Outer; - - changes = - (std::exchange(room.Main, main) != main) - | (std::exchange(room.Blobs, blobs) != blobs) - | (std::exchange(room.Outer, outer) != outer); - - } else if (action == TAlterRecord::SetRedo) { - const ui32 annex = delta.HasAnnex() ? delta.GetAnnex() : 0; - - changes = (std::exchange(Scheme.Redo.Annex, annex) != annex); - - } else if (action == TAlterRecord::SetTable) { + } else if (action == TAlterRecord::DropColumn) { + changes = DropColumn(table, delta.GetColumnId()); + } else if (action == TAlterRecord::AddColumnToKey) { + changes = AddColumnToKey(table, delta.GetColumnId()); + } else if (action == TAlterRecord::AddFamily) { + auto &family = Table(table)->Families[delta.GetFamilyId()]; + + const ui32 room = delta.GetRoomId(); + + changes = (std::exchange(family.Room, room) != room); + + } else if (action == TAlterRecord::SetFamily) { + auto &family = Table(table)->Families[delta.GetFamilyId()]; + + auto codec = delta.HasCodec() ? ECodec(delta.GetCodec()) :family.Codec; + + Y_VERIFY(ui32(codec) <= 1, "Invalid page encoding code value"); + + bool ever = delta.HasInMemory() && delta.GetInMemory(); + auto cache = ever ? ECache::Ever : family.Cache; + + cache = delta.HasCache() ? ECache(delta.GetCache()) : cache; + ui32 small = delta.HasSmall() ? delta.GetSmall() : family.Small; + ui32 large = delta.HasLarge() ? delta.GetLarge() : family.Large; + + Y_VERIFY(ui32(cache) <= 2, "Invalid pages cache policy value"); + + changes = + (std::exchange(family.Cache, cache) != cache) + | (std::exchange(family.Codec, codec) != codec) + | (std::exchange(family.Small, small) != small) + | (std::exchange(family.Large, large) != large); + + } else if (action == TAlterRecord::AddColumnToFamily) { + changes = AddColumnToFamily(table, delta.GetColumnId(), delta.GetFamilyId()); + } else if (action == TAlterRecord::SetRoom) { + auto &room = Table(table)->Rooms[delta.GetRoomId()]; + + ui32 main = delta.HasMain() ? delta.GetMain() : room.Main; + ui32 blobs = delta.HasBlobs() ? delta.GetBlobs() : room.Blobs; + ui32 outer = delta.HasOuter() ? delta.GetOuter() : room.Outer; + + changes = + (std::exchange(room.Main, main) != main) + | (std::exchange(room.Blobs, blobs) != blobs) + | (std::exchange(room.Outer, outer) != outer); + + } else if (action == TAlterRecord::SetRedo) { + const ui32 annex = delta.HasAnnex() ? delta.GetAnnex() : 0; + + changes = (std::exchange(Scheme.Redo.Annex, annex) != annex); + + } else if (action == TAlterRecord::SetTable) { if (delta.HasByKeyFilter()) { bool enabled = delta.GetByKeyFilter(); changes |= (std::exchange(Table(table)->ByKeyFilter, enabled) != enabled); } - + if (delta.HasEraseCacheEnabled()) { bool enabled = delta.GetEraseCacheEnabled(); changes |= (std::exchange(Table(table)->EraseCacheEnabled, enabled) != enabled); @@ -101,98 +101,98 @@ bool TSchemeModifier::Apply(const TAlterRecord &delta) changes |= (std::exchange(Table(table)->EraseCacheMaxBytes, maxBytes) != maxBytes); } } - + if (delta.HasColdBorrow()) { bool enabled = delta.GetColdBorrow(); changes |= (std::exchange(Table(table)->ColdBorrow, enabled) != enabled); } - } else if (action == TAlterRecord::UpdateExecutorInfo) { - if (delta.HasExecutorCacheSize()) - changes |= SetExecutorCacheSize(delta.GetExecutorCacheSize()); - if (delta.HasExecutorAllowLogBatching()) - changes |= SetExecutorAllowLogBatching(delta.GetExecutorAllowLogBatching()); - if (delta.HasExecutorLogFlushPeriod()) - changes |= SetExecutorLogFlushPeriod(TDuration::MicroSeconds(delta.GetExecutorLogFlushPeriod())); - if (delta.HasExecutorLimitInFlyTx()) - changes |= SetExecutorLimitInFlyTx(delta.GetExecutorLimitInFlyTx()); + } else if (action == TAlterRecord::UpdateExecutorInfo) { + if (delta.HasExecutorCacheSize()) + changes |= SetExecutorCacheSize(delta.GetExecutorCacheSize()); + if (delta.HasExecutorAllowLogBatching()) + changes |= SetExecutorAllowLogBatching(delta.GetExecutorAllowLogBatching()); + if (delta.HasExecutorLogFlushPeriod()) + changes |= SetExecutorLogFlushPeriod(TDuration::MicroSeconds(delta.GetExecutorLogFlushPeriod())); + if (delta.HasExecutorLimitInFlyTx()) + changes |= SetExecutorLimitInFlyTx(delta.GetExecutorLimitInFlyTx()); if (delta.HasExecutorResourceProfile()) changes |= SetExecutorResourceProfile(delta.GetExecutorResourceProfile()); if (delta.HasExecutorLogFastCommitTactic()) changes |= SetExecutorLogFastCommitTactic(delta.GetExecutorLogFastCommitTactic()); - } else if (action == TAlterRecord::SetCompactionPolicy) { - changes = SetCompactionPolicy(table, delta.GetCompactionPolicy()); - } else { - Y_FAIL("unknown scheme delta record type"); - } - - if (delta.HasTableId() && changes) - Affects.insert(table); - return changes; -} - -bool TSchemeModifier::AddColumnToFamily(ui32 tid, ui32 cid, ui32 family) -{ - auto* column = Scheme.GetColumnInfo(Table(tid), cid); - Y_VERIFY(column); - - return std::exchange(column->Family, family) != family; -} - -bool TSchemeModifier::AddTable(const TString &name, ui32 id) -{ - auto itName = Scheme.TableNames.find(name); - auto it = Scheme.Tables.emplace(id, TTable(name, id)); - if (itName != Scheme.TableNames.end()) { - Y_VERIFY(!it.second && it.first->second.Name == name && itName->second == it.first->first); - return false; - } else if (!it.second) { - // renaming table - Scheme.TableNames.erase(it.first->second.Name); - Scheme.TableNames.emplace(name, id); - it.first->second.Name = name; - return true; - } else { - Y_VERIFY(it.second); - Scheme.TableNames.emplace(name, id); - if (id >= 100) { - auto *table = &it.first->second; - // HACK: Force user tables to have some reasonable policy with multiple levels - table->CompactionPolicy = NLocalDb::CreateDefaultUserTablePolicy(); - } - return true; - } -} - -bool TSchemeModifier::DropTable(ui32 id) -{ - auto it = Scheme.Tables.find(id); - if (it != Scheme.Tables.end()) { - Scheme.TableNames.erase(it->second.Name); - Scheme.Tables.erase(it); - return true; - } - return false; -} - + } else if (action == TAlterRecord::SetCompactionPolicy) { + changes = SetCompactionPolicy(table, delta.GetCompactionPolicy()); + } else { + Y_FAIL("unknown scheme delta record type"); + } + + if (delta.HasTableId() && changes) + Affects.insert(table); + return changes; +} + +bool TSchemeModifier::AddColumnToFamily(ui32 tid, ui32 cid, ui32 family) +{ + auto* column = Scheme.GetColumnInfo(Table(tid), cid); + Y_VERIFY(column); + + return std::exchange(column->Family, family) != family; +} + +bool TSchemeModifier::AddTable(const TString &name, ui32 id) +{ + auto itName = Scheme.TableNames.find(name); + auto it = Scheme.Tables.emplace(id, TTable(name, id)); + if (itName != Scheme.TableNames.end()) { + Y_VERIFY(!it.second && it.first->second.Name == name && itName->second == it.first->first); + return false; + } else if (!it.second) { + // renaming table + Scheme.TableNames.erase(it.first->second.Name); + Scheme.TableNames.emplace(name, id); + it.first->second.Name = name; + return true; + } else { + Y_VERIFY(it.second); + Scheme.TableNames.emplace(name, id); + if (id >= 100) { + auto *table = &it.first->second; + // HACK: Force user tables to have some reasonable policy with multiple levels + table->CompactionPolicy = NLocalDb::CreateDefaultUserTablePolicy(); + } + return true; + } +} + +bool TSchemeModifier::DropTable(ui32 id) +{ + auto it = Scheme.Tables.find(id); + if (it != Scheme.Tables.end()) { + Scheme.TableNames.erase(it->second.Name); + Scheme.Tables.erase(it); + return true; + } + return false; +} + bool TSchemeModifier::AddColumn(ui32 tid, const TString &name, ui32 id, ui32 type, bool notNull, TCell null) -{ - auto *table = Table(tid); - auto itName = table->ColumnNames.find(name); - bool haveName = itName != table->ColumnNames.end(); +{ + auto *table = Table(tid); + auto itName = table->ColumnNames.find(name); + bool haveName = itName != table->ColumnNames.end(); auto it = table->Columns.emplace(id, TColumn(name, id, type, notNull)); - - if (it.second) - it.first->second.SetDefault(null); - - if (!it.second && !haveName && it.first->second.PType == type) { - // renaming column - table->ColumnNames.erase(it.first->second.Name); - table->ColumnNames.emplace(name, id); - it.first->second.Name = name; - return true; - } else { - // do we have inserted a new column, OR we already have the same column with the same name? + + if (it.second) + it.first->second.SetDefault(null); + + if (!it.second && !haveName && it.first->second.PType == type) { + // renaming column + table->ColumnNames.erase(it.first->second.Name); + table->ColumnNames.emplace(name, id); + it.first->second.Name = name; + return true; + } else { + // do we have inserted a new column, OR we already have the same column with the same name? bool insertedNew = it.second && !haveName; bool replacedExisting = !it.second && it.first->second.Name == name && haveName && itName->second == it.first->first; Y_VERIFY_S((insertedNew || replacedExisting), @@ -200,80 +200,80 @@ bool TSchemeModifier::AddColumn(ui32 tid, const TString &name, ui32 id, ui32 typ " OldName: " << (haveName ? itName->first : it.first->second.Name) << " NewId: " << id << " OldId: " << (haveName ? itName->second : it.first->first)); - if (!haveName) { - table->ColumnNames.emplace(name, id); - return true; - } - } - return false; -} - -bool TSchemeModifier::DropColumn(ui32 tid, ui32 id) -{ - auto *table = Table(tid); - auto it = table->Columns.find(id); - if (it != table->Columns.end()) { - table->ColumnNames.erase(it->second.Name); - table->Columns.erase(it); - return true; - } - return false; -} - -bool TSchemeModifier::AddColumnToKey(ui32 tid, ui32 columnId) -{ - auto *table = Table(tid); - auto* column = Scheme.GetColumnInfo(table, columnId); - Y_VERIFY(column); - - auto keyPos = std::find(table->KeyColumns.begin(), table->KeyColumns.end(), column->Id); - if (keyPos == table->KeyColumns.end()) { - column->KeyOrder = table->KeyColumns.size(); - table->KeyColumns.push_back(column->Id); - return true; - } - return false; -} - -bool TSchemeModifier::SetExecutorCacheSize(ui64 size) -{ - return std::exchange(Scheme.Executor.CacheSize, size) != size; -} - -bool TSchemeModifier::SetExecutorAllowLogBatching(bool allow) -{ - return std::exchange(Scheme.Executor.AllowLogBatching, allow) != allow; -} - + if (!haveName) { + table->ColumnNames.emplace(name, id); + return true; + } + } + return false; +} + +bool TSchemeModifier::DropColumn(ui32 tid, ui32 id) +{ + auto *table = Table(tid); + auto it = table->Columns.find(id); + if (it != table->Columns.end()) { + table->ColumnNames.erase(it->second.Name); + table->Columns.erase(it); + return true; + } + return false; +} + +bool TSchemeModifier::AddColumnToKey(ui32 tid, ui32 columnId) +{ + auto *table = Table(tid); + auto* column = Scheme.GetColumnInfo(table, columnId); + Y_VERIFY(column); + + auto keyPos = std::find(table->KeyColumns.begin(), table->KeyColumns.end(), column->Id); + if (keyPos == table->KeyColumns.end()) { + column->KeyOrder = table->KeyColumns.size(); + table->KeyColumns.push_back(column->Id); + return true; + } + return false; +} + +bool TSchemeModifier::SetExecutorCacheSize(ui64 size) +{ + return std::exchange(Scheme.Executor.CacheSize, size) != size; +} + +bool TSchemeModifier::SetExecutorAllowLogBatching(bool allow) +{ + return std::exchange(Scheme.Executor.AllowLogBatching, allow) != allow; +} + bool TSchemeModifier::SetExecutorLogFastCommitTactic(bool allow) { return std::exchange(Scheme.Executor.LogFastTactic, allow) != allow; } -bool TSchemeModifier::SetExecutorLogFlushPeriod(TDuration delay) -{ - return std::exchange(Scheme.Executor.LogFlushPeriod, delay) != delay; -} - -bool TSchemeModifier::SetExecutorLimitInFlyTx(ui32 limit) -{ - return std::exchange(Scheme.Executor.LimitInFlyTx, limit) != limit; -} - +bool TSchemeModifier::SetExecutorLogFlushPeriod(TDuration delay) +{ + return std::exchange(Scheme.Executor.LogFlushPeriod, delay) != delay; +} + +bool TSchemeModifier::SetExecutorLimitInFlyTx(ui32 limit) +{ + return std::exchange(Scheme.Executor.LimitInFlyTx, limit) != limit; +} + bool TSchemeModifier::SetExecutorResourceProfile(const TString &name) { return std::exchange(Scheme.Executor.ResourceProfile, name) != name; } bool TSchemeModifier::SetCompactionPolicy(ui32 tid, const NKikimrSchemeOp::TCompactionPolicy &proto) -{ - auto *table = Table(tid); - TIntrusiveConstPtr<TCompactionPolicy> policy(new TCompactionPolicy(proto)); - if (table->CompactionPolicy && *(table->CompactionPolicy) == *policy) - return false; - table->CompactionPolicy = policy; - return true; -} - -} -} +{ + auto *table = Table(tid); + TIntrusiveConstPtr<TCompactionPolicy> policy(new TCompactionPolicy(proto)); + if (table->CompactionPolicy && *(table->CompactionPolicy) == *policy) + return false; + table->CompactionPolicy = policy; + return true; +} + +} +} diff --git a/ydb/core/tablet_flat/flat_dbase_apply.h b/ydb/core/tablet_flat/flat_dbase_apply.h index 3502030b71..62543d53ae 100644 --- a/ydb/core/tablet_flat/flat_dbase_apply.h +++ b/ydb/core/tablet_flat/flat_dbase_apply.h @@ -1,61 +1,61 @@ -#pragma once - -#include "flat_dbase_scheme.h" -#include "flat_page_iface.h" -#include <util/generic/hash_set.h> +#pragma once + +#include "flat_dbase_scheme.h" +#include "flat_page_iface.h" +#include <util/generic/hash_set.h> #include <ydb/core/protos/scheme_log.pb.h> - -namespace NKikimr { -namespace NTable { - - class TSchemeModifier { - public: - using TTable = TScheme::TTableInfo; - using TFamily = TScheme::TFamily; - using ECodec = NPage::ECodec; - using ECache = NPage::ECache; - - explicit TSchemeModifier(TScheme &scheme); - - bool Apply(const TSchemeChanges &delta) - { - bool changed = false; - - for (const auto &delta : delta.GetDelta()) - changed = Apply(delta) || changed; - - return changed; - } - - protected: - bool Apply(const TAlterRecord &delta); - - bool AddTable(const TString& name, ui32 id); - bool DropTable(ui32 id); + +namespace NKikimr { +namespace NTable { + + class TSchemeModifier { + public: + using TTable = TScheme::TTableInfo; + using TFamily = TScheme::TFamily; + using ECodec = NPage::ECodec; + using ECache = NPage::ECache; + + explicit TSchemeModifier(TScheme &scheme); + + bool Apply(const TSchemeChanges &delta) + { + bool changed = false; + + for (const auto &delta : delta.GetDelta()) + changed = Apply(delta) || changed; + + return changed; + } + + protected: + bool Apply(const TAlterRecord &delta); + + bool AddTable(const TString& name, ui32 id); + bool DropTable(ui32 id); bool AddColumn(ui32 table, const TString& name, ui32 id, ui32 type, bool notNull, TCell null = { }); - bool DropColumn(ui32 table, ui32 id); - bool AddColumnToFamily(ui32 table, ui32 column, ui32 family); - bool AddColumnToKey(ui32 table, ui32 column); - - bool SetExecutorCacheSize(ui64 cacheSize); - bool SetExecutorAllowLogBatching(bool allow); + bool DropColumn(ui32 table, ui32 id); + bool AddColumnToFamily(ui32 table, ui32 column, ui32 family); + bool AddColumnToKey(ui32 table, ui32 column); + + bool SetExecutorCacheSize(ui64 cacheSize); + bool SetExecutorAllowLogBatching(bool allow); bool SetExecutorLogFastCommitTactic(bool allow); - bool SetExecutorLogFlushPeriod(TDuration flushPeriod); - bool SetExecutorLimitInFlyTx(ui32 limitTxInFly); + bool SetExecutorLogFlushPeriod(TDuration flushPeriod); + bool SetExecutorLimitInFlyTx(ui32 limitTxInFly); bool SetExecutorResourceProfile(const TString &name); bool SetCompactionPolicy(ui32 tableId, const NKikimrSchemeOp::TCompactionPolicy& newPolicy); - - TTable* Table(ui32 tid) const noexcept - { - auto* table = Scheme.GetTableInfo(tid); - Y_VERIFY(table, "Acccessing table that isn't exists"); - return table; - } - - public: - TScheme &Scheme; - THashSet<ui32> Affects; - }; - -} -} + + TTable* Table(ui32 tid) const noexcept + { + auto* table = Scheme.GetTableInfo(tid); + Y_VERIFY(table, "Acccessing table that isn't exists"); + return table; + } + + public: + TScheme &Scheme; + THashSet<ui32> Affects; + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_dbase_change.h b/ydb/core/tablet_flat/flat_dbase_change.h index 641e08b63d..25ef278057 100644 --- a/ydb/core/tablet_flat/flat_dbase_change.h +++ b/ydb/core/tablet_flat/flat_dbase_change.h @@ -1,74 +1,74 @@ -#pragma once - -#include "flat_table_subset.h" -#include "flat_sausage_solid.h" -#include "util_fmt_flat.h" - +#pragma once + +#include "flat_table_subset.h" +#include "flat_sausage_solid.h" +#include "util_fmt_flat.h" + #include <ydb/core/base/row_version.h> -namespace NKikimr { -namespace NTable { - - struct TChange { +namespace NKikimr { +namespace NTable { + + struct TChange { using TMemGlobs = TVector<NPageCollection::TMemGlob>; - + struct TSnapshot { TSnapshot(ui32 table) : Table(table) { } - - ui32 Table = Max<ui32>(); + + ui32 Table = Max<ui32>(); TEpoch Epoch = TEpoch::Max(); - }; - - struct TStats { - ui64 ChargeSieved = 0; - ui64 ChargeWeeded = 0; - ui64 SelectSieved = 0; - ui64 SelectWeeded = 0; - ui64 SelectNoKey = 0; + }; + + struct TStats { + ui64 ChargeSieved = 0; + ui64 ChargeWeeded = 0; + ui64 SelectSieved = 0; + ui64 SelectWeeded = 0; + ui64 SelectNoKey = 0; ui64 SelectInvisible = 0; - }; - + }; + struct TRemovedRowVersions { TRowVersion Lower; TRowVersion Upper; }; - TChange(TTxStamp stamp, ui64 serial) - : Stamp(stamp), Serial(serial) { } - - bool HasAny() const noexcept - { + TChange(TTxStamp stamp, ui64 serial) + : Stamp(stamp), Serial(serial) { } + + bool HasAny() const noexcept + { return Scheme || Redo || RemovedRowVersions; - } - - void Describe(IOutputStream &out) const noexcept - { - out - << "Change{" << Serial - << ", redo " << Redo.size() << "b" - << " alter " << Scheme.size() << "b" - << " annex " << Annex.size() - << ", ~" << NFmt::Arr(Affects) << " -" << NFmt::Arr(Deleted) - << ", " << Garbage.size() << " gb}"; - } - - const TTxStamp Stamp{ Max<ui64>() }; - const ui64 Serial = Max<ui64>(); - - TString Scheme; /* Serialized sheme delta */ - TString Redo; /* Serialized db redo log */ + } + + void Describe(IOutputStream &out) const noexcept + { + out + << "Change{" << Serial + << ", redo " << Redo.size() << "b" + << " alter " << Scheme.size() << "b" + << " annex " << Annex.size() + << ", ~" << NFmt::Arr(Affects) << " -" << NFmt::Arr(Deleted) + << ", " << Garbage.size() << " gb}"; + } + + const TTxStamp Stamp{ Max<ui64>() }; + const ui64 Serial = Max<ui64>(); + + TString Scheme; /* Serialized sheme delta */ + TString Redo; /* Serialized db redo log */ TMemGlobs Annex; /* Enum of blobs used in redo */ - - TVector<ui32> Affects; /* This tables touched in redo */ - TVector<ui32> Deleted; /* Tables deleted in some alter */ - TGarbage Garbage; /* Wiped tables, ids in Deleted */ - + + TVector<ui32> Affects; /* This tables touched in redo */ + TVector<ui32> Deleted; /* Tables deleted in some alter */ + TGarbage Garbage; /* Wiped tables, ids in Deleted */ + TVector<TSnapshot> Snapshots; - + TMap<ui32, TVector<TRemovedRowVersions>> RemovedRowVersions; - TStats Stats; - }; - -} -} + TStats Stats; + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_dbase_misc.h b/ydb/core/tablet_flat/flat_dbase_misc.h index 1163eb05f9..2d3357b944 100644 --- a/ydb/core/tablet_flat/flat_dbase_misc.h +++ b/ydb/core/tablet_flat/flat_dbase_misc.h @@ -1,35 +1,35 @@ -#pragma once +#pragma once #include "flat_table_stats.h" - + #include <ydb/core/scheme_types/scheme_raw_type_value.h> #include <util/generic/hash.h> -#include <util/system/types.h> - -namespace NKikimr { -namespace NTable { - - using TKeys = TArrayRef<const TRawTypeValue>; - - struct TDbStats { - - void Describe(IOutputStream &out) const noexcept - { +#include <util/system/types.h> + +namespace NKikimr { +namespace NTable { + + using TKeys = TArrayRef<const TRawTypeValue>; + + struct TDbStats { + + void Describe(IOutputStream &out) const noexcept + { const ui64 sys = Parts.IndexBytes + Parts.ByKeyBytes + Parts.OtherBytes; - - out + + out << "DBase{" << Tables << "t " << Parts.PartsCount << "p" << " " << Parts.RowsTotal << "r" << ", (" << MemTableBytes << " mem, " << sys << " sys, " << (Parts.CodedBytes + Parts.LargeBytes) << ")b}"; - } - - ui32 Tables = 0; - ui64 TxCommited = 0; + } + + ui32 Tables = 0; + ui64 TxCommited = 0; ui64 MemTableWaste = 0; ui64 MemTableBytes = 0; ui64 MemTableOps = 0; TPartStats Parts; THashMap<ui64, TPartStats> PartsPerTablet; - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_dbase_naked.h b/ydb/core/tablet_flat/flat_dbase_naked.h index 493867a7f8..d805c592d5 100644 --- a/ydb/core/tablet_flat/flat_dbase_naked.h +++ b/ydb/core/tablet_flat/flat_dbase_naked.h @@ -1,62 +1,62 @@ -#pragma once - -#include "flat_table.h" -#include "flat_table_subset.h" -#include "flat_dbase_misc.h" -#include "flat_dbase_apply.h" -#include "flat_dbase_scheme.h" -#include "flat_redo_writer.h" -#include "flat_redo_player.h" -#include "flat_util_misc.h" -#include "flat_abi_evol.h" -#include "flat_abi_check.h" -#include "util_fmt_flat.h" +#pragma once + +#include "flat_table.h" +#include "flat_table_subset.h" +#include "flat_dbase_misc.h" +#include "flat_dbase_apply.h" +#include "flat_dbase_scheme.h" +#include "flat_redo_writer.h" +#include "flat_redo_player.h" +#include "flat_util_misc.h" +#include "flat_abi_evol.h" +#include "flat_abi_check.h" +#include "util_fmt_flat.h" #include "util_basics.h" #include "util_deref.h" - -namespace NKikimr { -namespace NTable { - + +namespace NKikimr { +namespace NTable { + class TDatabaseImpl { - + struct TArgs { - ui32 Table; - TEpoch Head; - TTxStamp Edge; - }; - + ui32 Table; + TEpoch Head; + TTxStamp Edge; + }; + struct TTableWrapper { TTableWrapper() = default; TTableWrapper(const TTableWrapper&) = delete; - + TTableWrapper(TArgs args) - : Table(args.Table) - , Self(new TTable(args.Head)) - , Edge(args.Edge) - { - - } - - explicit operator bool() const noexcept - { - return bool(Self); - } - - TTable* operator->() const noexcept - { - return Self.Get(); - } - - bool Touch(ui64 edge, ui64 serial) noexcept - { - return std::exchange(Serial, serial) <= edge; - } - - void Aggr(TDbStats &aggr, bool enter) const noexcept - { - const auto &stat = Self->Stat(); - - if (enter) { + : Table(args.Table) + , Self(new TTable(args.Head)) + , Edge(args.Edge) + { + + } + + explicit operator bool() const noexcept + { + return bool(Self); + } + + TTable* operator->() const noexcept + { + return Self.Get(); + } + + bool Touch(ui64 edge, ui64 serial) noexcept + { + return std::exchange(Serial, serial) <= edge; + } + + void Aggr(TDbStats &aggr, bool enter) const noexcept + { + const auto &stat = Self->Stat(); + + if (enter) { aggr.MemTableWaste += Self->GetMemWaste(); aggr.MemTableBytes += Self->GetMemSize(); aggr.MemTableOps += Self->GetOpsCount(); @@ -64,7 +64,7 @@ namespace NTable { for (const auto& kv : stat.PartsPerTablet) { aggr.PartsPerTablet[kv.first] += kv.second; } - } else { + } else { NUtil::SubSafe(aggr.MemTableWaste, Self->GetMemWaste()); NUtil::SubSafe(aggr.MemTableBytes, Self->GetMemSize()); NUtil::SubSafe(aggr.MemTableOps, Self->GetOpsCount()); @@ -74,82 +74,82 @@ namespace NTable { aggr.PartsPerTablet[kv.first] -= kv.second; } aggr.Parts -= stat.Parts; - } - } - - const ui32 Table = Max<ui32>(); + } + } + + const ui32 Table = Max<ui32>(); const TIntrusivePtr<TTable> Self; - const TTxStamp Edge = 0; /* Stamp of last snapshot */ - ui64 Serial = 0; - }; - - public: - using TEdges = THashMap<ui32, TSnapEdge>; - using TInfo = TScheme::TTableInfo; - using TOps = TArrayRef<const TUpdateOp>; - using TModifier = TSchemeModifier; + const TTxStamp Edge = 0; /* Stamp of last snapshot */ + ui64 Serial = 0; + }; + + public: + using TEdges = THashMap<ui32, TSnapEdge>; + using TInfo = TScheme::TTableInfo; + using TOps = TArrayRef<const TUpdateOp>; + using TModifier = TSchemeModifier; using TMemGlob = NPageCollection::TMemGlob; - + TDatabaseImpl(TTxStamp weak, TAutoPtr<TScheme> scheme, const TEdges *edges) - : Weak(weak) - , Redo(*this) - , Scheme(scheme) - { - for (auto it : Scheme->Tables) { - auto *mine = edges ? edges->FindPtr(it.first) : nullptr; - - MakeTable(it.first, mine ? *mine : TSnapEdge{ })->SetScheme(it.second); - } - - CalculateAnnexEdge(); /* bring bootstrapped redo settings */ - } - - ui64 Serial() const noexcept - { - return Serial_; - } - + : Weak(weak) + , Redo(*this) + , Scheme(scheme) + { + for (auto it : Scheme->Tables) { + auto *mine = edges ? edges->FindPtr(it.first) : nullptr; + + MakeTable(it.first, mine ? *mine : TSnapEdge{ })->SetScheme(it.second); + } + + CalculateAnnexEdge(); /* bring bootstrapped redo settings */ + } + + ui64 Serial() const noexcept + { + return Serial_; + } + TTableWrapper& Get(ui32 table, bool require) noexcept - { - auto *wrap = Tables.FindPtr(table); - - Y_VERIFY(wrap || !require, "Cannot find given table"); - - return wrap ? *wrap : Dummy; - } - - ui64 Rewind(ui64 serial) noexcept - { - return std::exchange(Serial_, Max(Serial_, serial)); - } - + { + auto *wrap = Tables.FindPtr(table); + + Y_VERIFY(wrap || !require, "Cannot find given table"); + + return wrap ? *wrap : Dummy; + } + + ui64 Rewind(ui64 serial) noexcept + { + return std::exchange(Serial_, Max(Serial_, serial)); + } + TDatabaseImpl& Switch(TTxStamp stamp) noexcept - { - if (std::exchange(Stamp, stamp) > stamp) - Y_FAIL("Executor tx stamp cannot go to the past"); - - First_ = Max<ui64>(), Begin_ = Serial_; - Stats.TxCommited++, Affects = { }; - - return *this; - } - + { + if (std::exchange(Stamp, stamp) > stamp) + Y_FAIL("Executor tx stamp cannot go to the past"); + + First_ = Max<ui64>(), Begin_ = Serial_; + Stats.TxCommited++, Affects = { }; + + return *this; + } + void Assign(TVector<TMemGlob> annex) noexcept - { + { Y_VERIFY(!Annex, "Annex has been already attached to TDatabaseImpl"); - - Annex = std::move(annex); - } - + + Annex = std::move(annex); + } + void ReplaceSlices(ui32 tid, TBundleSlicesMap slices) noexcept - { - auto &wrap = Get(tid, true); - - wrap.Aggr(Stats, false /* leave */); + { + auto &wrap = Get(tid, true); + + wrap.Aggr(Stats, false /* leave */); wrap->ReplaceSlices(std::move(slices)); - wrap.Aggr(Stats, true /* enter */); - } - + wrap.Aggr(Stats, true /* enter */); + } + void Replace(ui32 tid, TArrayRef<const TPartView> partViews, const TSubset &subset) noexcept { auto &wrap = Get(tid, true); @@ -169,14 +169,14 @@ namespace NTable { } void Merge(ui32 tid, TPartView partView) noexcept - { - auto &wrap = Get(tid, true); - - wrap.Aggr(Stats, false /* leave */); + { + auto &wrap = Get(tid, true); + + wrap.Aggr(Stats, false /* leave */); wrap->Merge(std::move(partView)); - wrap.Aggr(Stats, true /* enter */); - } - + wrap.Aggr(Stats, true /* enter */); + } + void Merge(ui32 tid, TIntrusiveConstPtr<TColdPart> part) noexcept { auto &wrap = Get(tid, true); @@ -195,173 +195,173 @@ namespace NTable { wrap.Aggr(Stats, true /* enter */); } - bool Apply(const TSchemeChanges &delta, NRedo::TWriter *writer) - { - TModifier modifier(*Scheme); - - if (modifier.Apply(delta)) { - Apply(modifier.Affects, writer); - - return true; - } else { - return false; - } - } - + bool Apply(const TSchemeChanges &delta, NRedo::TWriter *writer) + { + TModifier modifier(*Scheme); + + if (modifier.Apply(delta)) { + Apply(modifier.Affects, writer); + + return true; + } else { + return false; + } + } + TDatabaseImpl& ApplyRedo(TArrayRef<const char> plain) noexcept - { - return Redo.Replay(plain), *this; - } - - TVector<ui32> GrabAffects() noexcept - { - return std::move(Affects); - } - + { + return Redo.Replay(plain), *this; + } + + TVector<ui32> GrabAffects() noexcept + { + return std::move(Affects); + } + TVector<TMemGlob> GrabAnnex() noexcept - { - return std::move(Annex); - } - - ui32 AnnexByteLimit() const noexcept - { - return Large; - } - - protected: /*_ Mine private methods */ - void CalculateAnnexEdge() noexcept - { - Large = Max<ui32>(); - - for (auto table: Scheme->Tables) - for (auto family: table.second.Families) - Large = Min(Large, family.second.Large); - - Large = Max(Large, Scheme->Redo.Annex); - } - + { + return std::move(Annex); + } + + ui32 AnnexByteLimit() const noexcept + { + return Large; + } + + protected: /*_ Mine private methods */ + void CalculateAnnexEdge() noexcept + { + Large = Max<ui32>(); + + for (auto table: Scheme->Tables) + for (auto family: table.second.Families) + Large = Min(Large, family.second.Large); + + Large = Max(Large, Scheme->Redo.Annex); + } + TTableWrapper& MakeTable(ui32 table, TSnapEdge edge) noexcept - { - if (edge.TxStamp == Max<ui64>()) { - Y_FAIL("Cannot make table on undefined TxStamp edge"); + { + if (edge.TxStamp == Max<ui64>()) { + Y_FAIL("Cannot make table on undefined TxStamp edge"); } else if (edge.Head == TEpoch::Zero()) { - /* Table written in compatability mode utilizes global - TxStamp instead of private TEpoch values. In order - to correcly handle legacy tables should rewind epoch - above of the last tx. - */ - + /* Table written in compatability mode utilizes global + TxStamp instead of private TEpoch values. In order + to correcly handle legacy tables should rewind epoch + above of the last tx. + */ + ui64 head = edge.TxStamp + 1; Y_VERIFY(head < Max<i64>(), "TxStamp is too large for epoch"); edge.Head = TEpoch(i64(head)); - } - + } + TArgs args{ table, edge.Head, edge.TxStamp }; - - auto result = Tables.emplace(table, args); - - Y_VERIFY(result.second, "Table alredy exists"); - - Stats.Tables += 1; - - return result.first->second; - } - - void Apply(const THashSet<ui32> &affects, NRedo::TWriter *writer) - { - for (ui32 table : affects) { - auto &wrap = Get(table, false); - - if (auto *info = Scheme->GetTableInfo(table)) { - if (wrap && writer) { - /* Hack keeps table epoches consistent in regular - flow and on db bootstap. Required due to scheme - deltas and redo log async rollup on bootstrap. - */ - - writer->EvFlush(table, Stamp, wrap->Snapshot()); - } - - (wrap ? wrap : MakeTable(table, { }))->SetScheme(*info); - - } else { - wrap.Aggr(Stats, false /* leave */); - - Deleted.emplace_back(table); - Garbage.emplace_back(wrap->Unwrap()); - Tables.erase(table); - NUtil::SubSafe(Stats.Tables, ui32(1)); - } - } - - CalculateAnnexEdge(); /* could be changed in scheme alter */ - } - - public: /*_ Redo log player interface impl. */ - bool NeedIn(ui32 table) noexcept - { - /* Scheme deltas are applied before any redo log entries on - db bootstrap and udate log entries for already deleted - tables may appear. Weak stamp points to the end of asyncs. - */ - - const auto &wrap = Get(table, Weak <= Stamp); - - return wrap ? Stamp > wrap.Edge : false; - } - - void DoBegin(ui32 tail, ui32 head, ui64 serial, ui64 stamp) noexcept - { - TAbi().Check(tail, head, "redo"); - - /* Hack for redo logs affected by bug in KIKIMR-5323 */ - - const auto back = Stamp - (head >= 21 ? 0 : Min(Stamp, ui64(2))); - - if (serial == 0) { - Serial_++; /* Legacy EvBegin without embedded serial */ - } else if (Serial_ < serial && (stamp == 0 || stamp >= back)) { - Serial_ = serial; - } else { - Y_Fail("EvBegin{" << serial << " " << NFmt::TStamp(stamp) - << "} is not fits to db state {" << Serial_ << " " - << NFmt::TStamp(Stamp) << "} (redo log was reordered)"); - } - - First_ = Min(First_, Serial_); - } - + + auto result = Tables.emplace(table, args); + + Y_VERIFY(result.second, "Table alredy exists"); + + Stats.Tables += 1; + + return result.first->second; + } + + void Apply(const THashSet<ui32> &affects, NRedo::TWriter *writer) + { + for (ui32 table : affects) { + auto &wrap = Get(table, false); + + if (auto *info = Scheme->GetTableInfo(table)) { + if (wrap && writer) { + /* Hack keeps table epoches consistent in regular + flow and on db bootstap. Required due to scheme + deltas and redo log async rollup on bootstrap. + */ + + writer->EvFlush(table, Stamp, wrap->Snapshot()); + } + + (wrap ? wrap : MakeTable(table, { }))->SetScheme(*info); + + } else { + wrap.Aggr(Stats, false /* leave */); + + Deleted.emplace_back(table); + Garbage.emplace_back(wrap->Unwrap()); + Tables.erase(table); + NUtil::SubSafe(Stats.Tables, ui32(1)); + } + } + + CalculateAnnexEdge(); /* could be changed in scheme alter */ + } + + public: /*_ Redo log player interface impl. */ + bool NeedIn(ui32 table) noexcept + { + /* Scheme deltas are applied before any redo log entries on + db bootstrap and udate log entries for already deleted + tables may appear. Weak stamp points to the end of asyncs. + */ + + const auto &wrap = Get(table, Weak <= Stamp); + + return wrap ? Stamp > wrap.Edge : false; + } + + void DoBegin(ui32 tail, ui32 head, ui64 serial, ui64 stamp) noexcept + { + TAbi().Check(tail, head, "redo"); + + /* Hack for redo logs affected by bug in KIKIMR-5323 */ + + const auto back = Stamp - (head >= 21 ? 0 : Min(Stamp, ui64(2))); + + if (serial == 0) { + Serial_++; /* Legacy EvBegin without embedded serial */ + } else if (Serial_ < serial && (stamp == 0 || stamp >= back)) { + Serial_ = serial; + } else { + Y_Fail("EvBegin{" << serial << " " << NFmt::TStamp(stamp) + << "} is not fits to db state {" << Serial_ << " " + << NFmt::TStamp(Stamp) << "} (redo log was reordered)"); + } + + First_ = Min(First_, Serial_); + } + void DoAnnex(TArrayRef<const TStdPad<NPageCollection::TGlobId>> annex) noexcept - { - if (Annex) { - Y_VERIFY(annex.size() == Annex.size()); - - for (auto it : xrange(Annex.size())) - if (Annex[it].GId != *annex[it]) { - Y_FAIL("NRedo EvAnnex isn't match to assigned annex"); + { + if (Annex) { + Y_VERIFY(annex.size() == Annex.size()); + + for (auto it : xrange(Annex.size())) + if (Annex[it].GId != *annex[it]) { + Y_FAIL("NRedo EvAnnex isn't match to assigned annex"); } - - } else { - Annex.reserve(annex.size()); - - for (auto &one : annex) + + } else { + Annex.reserve(annex.size()); + + for (auto &one : annex) Annex.emplace_back(*one, TSharedData{ }); - } - } - + } + } + void DoUpdate(ui32 tid, ERowOp rop, TKeys key, TOps ops, TRowVersion rowVersion) noexcept - { - auto &wrap = Touch(tid); - + { + auto &wrap = Touch(tid); + NUtil::SubSafe(Stats.MemTableWaste, wrap->GetMemWaste()); NUtil::SubSafe(Stats.MemTableBytes, wrap->GetMemSize()); wrap->Update(rop, key, ops, Annex, rowVersion); Stats.MemTableWaste += wrap->GetMemWaste(); Stats.MemTableBytes += wrap->GetMemSize(); Stats.MemTableOps += 1; - } - + } + void DoUpdateTx(ui32 tid, ERowOp rop, TKeys key, TOps ops, ui64 txId) noexcept { auto &wrap = Touch(tid); @@ -397,31 +397,31 @@ namespace NTable { } void DoFlush(ui32 tid, ui64 /* stamp */, TEpoch epoch) noexcept - { - auto on = Touch(tid)->Snapshot(); - + { + auto on = Touch(tid)->Snapshot(); + if (epoch != TEpoch::Zero() && epoch != on) { - Y_Fail("EvFlush{" << tid << ", " << epoch << "eph} turned" + Y_Fail("EvFlush{" << tid << ", " << epoch << "eph} turned" << " table to unexpected epoch " << on); - } - } - + } + } + TTableWrapper& Touch(ui32 table) noexcept - { - auto &wrap = Get(table, true); - - /* Modern redo log starts each logical update with single EvBegin - allowing to grow db change serial number in a log driven way. - Legacy log (Evolution < 12) have no EvBegin and progression - of serial require hack with virtual insertion of EvBegin here. - */ - - if (wrap.Touch(Begin_, Begin_ == Serial_ ? ++Serial_ : Serial_)) - Affects.emplace_back(table); - - return First_ = Min(First_, Serial_), wrap; - } - + { + auto &wrap = Get(table, true); + + /* Modern redo log starts each logical update with single EvBegin + allowing to grow db change serial number in a log driven way. + Legacy log (Evolution < 12) have no EvBegin and progression + of serial require hack with virtual insertion of EvBegin here. + */ + + if (wrap.Touch(Begin_, Begin_ == Serial_ ? ++Serial_ : Serial_)) + Affects.emplace_back(table); + + return First_ = Min(First_, Serial_), wrap; + } + public: void EnumerateTxStatusParts(const std::function<void(const TIntrusiveConstPtr<TTxStatusPart>&)>& callback) { for (auto &it : Tables) { @@ -429,24 +429,24 @@ namespace NTable { } } - private: - const TTxStamp Weak; /* db bootstrap upper stamp */ - ui64 Stamp = 0; - ui64 Serial_ = 1; /* db global change serial number */ - ui64 Begin_ = 0; /* Serial at moment of Switch() call */ - ui32 Large = Max<ui32>();/* The lowest limit for large blobs */ + private: + const TTxStamp Weak; /* db bootstrap upper stamp */ + ui64 Stamp = 0; + ui64 Serial_ = 1; /* db global change serial number */ + ui64 Begin_ = 0; /* Serial at moment of Switch() call */ + ui32 Large = Max<ui32>();/* The lowest limit for large blobs */ TTableWrapper Dummy; THashMap<ui32, TTableWrapper> Tables; NRedo::TPlayer<TDatabaseImpl> Redo; - TVector<ui32> Affects; + TVector<ui32> Affects; TVector<TMemGlob> Annex; - - public: + + public: const TAutoPtr<TScheme> Scheme; - TGarbage Garbage; /* Unused full table subsets */ - TVector<ui32> Deleted; - TDbStats Stats; - ui64 First_ = Max<ui64>(); /* First used serial after Switch() */ - }; -} -} + TGarbage Garbage; /* Unused full table subsets */ + TVector<ui32> Deleted; + TDbStats Stats; + ui64 First_ = Max<ui64>(); /* First used serial after Switch() */ + }; +} +} diff --git a/ydb/core/tablet_flat/flat_dbase_scheme.cpp b/ydb/core/tablet_flat/flat_dbase_scheme.cpp index fa12005009..c1cdb91b3f 100644 --- a/ydb/core/tablet_flat/flat_dbase_scheme.cpp +++ b/ydb/core/tablet_flat/flat_dbase_scheme.cpp @@ -1,41 +1,41 @@ -#include "flat_dbase_scheme.h" +#include "flat_dbase_scheme.h" namespace NKikimr { -namespace NTable { +namespace NTable { TAutoPtr<TSchemeChanges> TScheme::GetSnapshot() const { - TAlter delta; - + TAlter delta; + for (const auto& itTable : Tables) { - const auto table = itTable.first; - - delta.AddTable(itTable.second.Name, table); - - for(const auto& it : itTable.second.Rooms) { - auto &room = it.second; - - delta.SetRoom(table, it.first, room.Main, room.Blobs, room.Outer); - } - - for(const auto& it : itTable.second.Families) { - auto &family = it.second; - - delta.AddFamily(table, it.first, family.Room); - delta.SetFamily(table, it.first, family.Cache, family.Codec); + const auto table = itTable.first; + + delta.AddTable(itTable.second.Name, table); + + for(const auto& it : itTable.second.Rooms) { + auto &room = it.second; + + delta.SetRoom(table, it.first, room.Main, room.Blobs, room.Outer); + } + + for(const auto& it : itTable.second.Families) { + auto &family = it.second; + + delta.AddFamily(table, it.first, family.Room); + delta.SetFamily(table, it.first, family.Cache, family.Codec); delta.SetFamilyBlobs(table, it.first, family.Small, family.Large); - } - - for(const auto& it : itTable.second.Columns) { - const auto &col = it.second; - + } + + for(const auto& it : itTable.second.Columns) { + const auto &col = it.second; + delta.AddColumn(table, col.Name, it.first, col.PType, col.NotNull, col.Null); - delta.AddColumnToFamily(table, it.first, col.Family); + delta.AddColumnToFamily(table, it.first, col.Family); } - - for(ui32 columnId : itTable.second.KeyColumns) - delta.AddColumnToKey(table, columnId); - - delta.SetCompactionPolicy(table, *itTable.second.CompactionPolicy); + + for(ui32 columnId : itTable.second.KeyColumns) + delta.AddColumnToKey(table, columnId); + + delta.SetCompactionPolicy(table, *itTable.second.CompactionPolicy); delta.SetEraseCache( table, @@ -44,161 +44,161 @@ TAutoPtr<TSchemeChanges> TScheme::GetSnapshot() const { itTable.second.EraseCacheMaxBytes); // N.B. must be last for compatibility with older versions :( - delta.SetByKeyFilter(table, itTable.second.ByKeyFilter); + delta.SetByKeyFilter(table, itTable.second.ByKeyFilter); delta.SetColdBorrow(table, itTable.second.ColdBorrow); } - - delta.SetRedo(Redo.Annex); - delta.SetExecutorCacheSize(Executor.CacheSize); - delta.SetExecutorAllowLogBatching(Executor.AllowLogBatching); - delta.SetExecutorLogFlushPeriod(Executor.LogFlushPeriod); + + delta.SetRedo(Redo.Annex); + delta.SetExecutorCacheSize(Executor.CacheSize); + delta.SetExecutorAllowLogBatching(Executor.AllowLogBatching); + delta.SetExecutorLogFlushPeriod(Executor.LogFlushPeriod); delta.SetExecutorResourceProfile(Executor.ResourceProfile); delta.SetExecutorFastLogPolicy(Executor.LogFastTactic); - return delta.Flush(); + return delta.Flush(); } -TAlter& TAlter::Merge(const TSchemeChanges &log) -{ - Log.MutableDelta()->MergeFrom(log.GetDelta()); - - return *this; -} - -TAlter& TAlter::AddTable(const TString& name, ui32 id) -{ - TAlterRecord& delta = *Log.AddDelta(); - delta.SetDeltaType(TAlterRecord::AddTable); +TAlter& TAlter::Merge(const TSchemeChanges &log) +{ + Log.MutableDelta()->MergeFrom(log.GetDelta()); + + return *this; +} + +TAlter& TAlter::AddTable(const TString& name, ui32 id) +{ + TAlterRecord& delta = *Log.AddDelta(); + delta.SetDeltaType(TAlterRecord::AddTable); delta.SetTableName(name); delta.SetTableId(id); - - return *this; + + return *this; } -TAlter& TAlter::DropTable(ui32 id) -{ - TAlterRecord& delta = *Log.AddDelta(); - delta.SetDeltaType(TAlterRecord::DropTable); +TAlter& TAlter::DropTable(ui32 id) +{ + TAlterRecord& delta = *Log.AddDelta(); + delta.SetDeltaType(TAlterRecord::DropTable); delta.SetTableId(id); - - return *this; + + return *this; } TAlter& TAlter::AddColumn(ui32 table, const TString& name, ui32 id, ui32 type, bool notNull, TCell null) -{ - TAlterRecord& delta = *Log.AddDelta(); - delta.SetDeltaType(TAlterRecord::AddColumn); +{ + TAlterRecord& delta = *Log.AddDelta(); + delta.SetDeltaType(TAlterRecord::AddColumn); delta.SetColumnName(name); delta.SetTableId(table); delta.SetColumnId(id); delta.SetColumnType(type); delta.SetNotNull(notNull); - - if (!null.IsNull()) - delta.SetDefault(null.Data(), null.Size()); - - return *this; + + if (!null.IsNull()) + delta.SetDefault(null.Data(), null.Size()); + + return *this; } -TAlter& TAlter::DropColumn(ui32 table, ui32 id) -{ - TAlterRecord& delta = *Log.AddDelta(); - delta.SetDeltaType(TAlterRecord::DropColumn); +TAlter& TAlter::DropColumn(ui32 table, ui32 id) +{ + TAlterRecord& delta = *Log.AddDelta(); + delta.SetDeltaType(TAlterRecord::DropColumn); delta.SetTableId(table); delta.SetColumnId(id); - - return *this; + + return *this; } -TAlter& TAlter::AddColumnToFamily(ui32 table, ui32 column, ui32 family) -{ - TAlterRecord& delta = *Log.AddDelta(); - delta.SetDeltaType(TAlterRecord::AddColumnToFamily); +TAlter& TAlter::AddColumnToFamily(ui32 table, ui32 column, ui32 family) +{ + TAlterRecord& delta = *Log.AddDelta(); + delta.SetDeltaType(TAlterRecord::AddColumnToFamily); delta.SetTableId(table); delta.SetColumnId(column); - delta.SetFamilyId(family); - - return *this; + delta.SetFamilyId(family); + + return *this; } -TAlter& TAlter::AddFamily(ui32 table, ui32 family, ui32 room) -{ - TAlterRecord& delta = *Log.AddDelta(); - delta.SetDeltaType(TAlterRecord::AddFamily); +TAlter& TAlter::AddFamily(ui32 table, ui32 family, ui32 room) +{ + TAlterRecord& delta = *Log.AddDelta(); + delta.SetDeltaType(TAlterRecord::AddFamily); delta.SetTableId(table); - delta.SetFamilyId(family); - delta.SetRoomId(room); - - return *this; + delta.SetFamilyId(family); + delta.SetRoomId(room); + + return *this; } -TAlter& TAlter::AddColumnToKey(ui32 table, ui32 column) -{ - TAlterRecord& delta = *Log.AddDelta(); - delta.SetDeltaType(TAlterRecord::AddColumnToKey); +TAlter& TAlter::AddColumnToKey(ui32 table, ui32 column) +{ + TAlterRecord& delta = *Log.AddDelta(); + delta.SetDeltaType(TAlterRecord::AddColumnToKey); delta.SetTableId(table); delta.SetColumnId(column); - - return *this; -} - -TAlter& TAlter::SetFamily(ui32 table, ui32 family, ECache cache, ECodec codec) -{ - TAlterRecord& delta = *Log.AddDelta(); - delta.SetDeltaType(TAlterRecord::SetFamily); - delta.SetTableId(table); - delta.SetFamilyId(family); - delta.SetInMemory(cache == ECache::Ever); - delta.SetCodec(ui32(codec)); - delta.SetCache(ui32(cache)); - - return *this; + + return *this; } +TAlter& TAlter::SetFamily(ui32 table, ui32 family, ECache cache, ECodec codec) +{ + TAlterRecord& delta = *Log.AddDelta(); + delta.SetDeltaType(TAlterRecord::SetFamily); + delta.SetTableId(table); + delta.SetFamilyId(family); + delta.SetInMemory(cache == ECache::Ever); + delta.SetCodec(ui32(codec)); + delta.SetCache(ui32(cache)); + + return *this; +} + TAlter& TAlter::SetFamilyBlobs(ui32 table, ui32 family, ui32 small, ui32 large) -{ - TAlterRecord& delta = *Log.AddDelta(); - delta.SetDeltaType(TAlterRecord::SetFamily); - delta.SetTableId(table); - delta.SetFamilyId(family); - delta.SetSmall(small); - delta.SetLarge(large); - - return *this; -} - -TAlter& TAlter::SetRoom(ui32 table, ui32 room, ui32 main, ui32 blobs, ui32 outer) -{ - auto *delta = Log.AddDelta(); - - delta->SetDeltaType(TAlterRecord::SetRoom); - delta->SetTableId(table); - delta->SetRoomId(room); - delta->SetMain(main); - delta->SetBlobs(blobs); - delta->SetOuter(outer); - - return *this; -} - -TAlter& TAlter::SetRedo(ui32 annex) -{ - auto *delta = Log.AddDelta(); - - delta->SetDeltaType(TAlterRecord::SetRedo); - delta->SetAnnex(annex); - - return *this; -} - -TAlter& TAlter::SetExecutorCacheSize(ui64 cacheSize) -{ - TAlterRecord &delta = *Log.AddDelta(); - delta.SetDeltaType(TAlterRecord::UpdateExecutorInfo); +{ + TAlterRecord& delta = *Log.AddDelta(); + delta.SetDeltaType(TAlterRecord::SetFamily); + delta.SetTableId(table); + delta.SetFamilyId(family); + delta.SetSmall(small); + delta.SetLarge(large); + + return *this; +} + +TAlter& TAlter::SetRoom(ui32 table, ui32 room, ui32 main, ui32 blobs, ui32 outer) +{ + auto *delta = Log.AddDelta(); + + delta->SetDeltaType(TAlterRecord::SetRoom); + delta->SetTableId(table); + delta->SetRoomId(room); + delta->SetMain(main); + delta->SetBlobs(blobs); + delta->SetOuter(outer); + + return *this; +} + +TAlter& TAlter::SetRedo(ui32 annex) +{ + auto *delta = Log.AddDelta(); + + delta->SetDeltaType(TAlterRecord::SetRedo); + delta->SetAnnex(annex); + + return *this; +} + +TAlter& TAlter::SetExecutorCacheSize(ui64 cacheSize) +{ + TAlterRecord &delta = *Log.AddDelta(); + delta.SetDeltaType(TAlterRecord::UpdateExecutorInfo); delta.SetExecutorCacheSize(cacheSize); - - return *this; + + return *this; } TAlter& TAlter::SetExecutorFastLogPolicy(bool allow) @@ -210,62 +210,62 @@ TAlter& TAlter::SetExecutorFastLogPolicy(bool allow) return *this; } -TAlter& TAlter::SetExecutorAllowLogBatching(bool allow) -{ - TAlterRecord &delta = *Log.AddDelta(); - delta.SetDeltaType(TAlterRecord::UpdateExecutorInfo); +TAlter& TAlter::SetExecutorAllowLogBatching(bool allow) +{ + TAlterRecord &delta = *Log.AddDelta(); + delta.SetDeltaType(TAlterRecord::UpdateExecutorInfo); delta.SetExecutorAllowLogBatching(allow); - - return *this; + + return *this; } -TAlter& TAlter::SetExecutorLogFlushPeriod(TDuration flushPeriod) -{ - TAlterRecord &delta = *Log.AddDelta(); - delta.SetDeltaType(TAlterRecord::UpdateExecutorInfo); +TAlter& TAlter::SetExecutorLogFlushPeriod(TDuration flushPeriod) +{ + TAlterRecord &delta = *Log.AddDelta(); + delta.SetDeltaType(TAlterRecord::UpdateExecutorInfo); delta.SetExecutorLogFlushPeriod(flushPeriod.MicroSeconds()); - - return *this; + + return *this; } -TAlter& TAlter::SetExecutorLimitInFlyTx(ui32 limitTxInFly) -{ - TAlterRecord &delta = *Log.AddDelta(); - delta.SetDeltaType(TAlterRecord::UpdateExecutorInfo); +TAlter& TAlter::SetExecutorLimitInFlyTx(ui32 limitTxInFly) +{ + TAlterRecord &delta = *Log.AddDelta(); + delta.SetDeltaType(TAlterRecord::UpdateExecutorInfo); delta.SetExecutorLimitInFlyTx(limitTxInFly); - - return *this; + + return *this; } -TAlter& TAlter::SetExecutorResourceProfile(const TString &name) -{ - TAlterRecord &delta = *Log.AddDelta(); - delta.SetDeltaType(TAlterRecord::UpdateExecutorInfo); +TAlter& TAlter::SetExecutorResourceProfile(const TString &name) +{ + TAlterRecord &delta = *Log.AddDelta(); + delta.SetDeltaType(TAlterRecord::UpdateExecutorInfo); delta.SetExecutorResourceProfile(name); - - return *this; + + return *this; } -TAlter& TAlter::SetCompactionPolicy(ui32 tableId, const TCompactionPolicy& newPolicy) -{ - TAlterRecord &delta = *Log.AddDelta(); - delta.SetDeltaType(TAlterRecord::SetCompactionPolicy); +TAlter& TAlter::SetCompactionPolicy(ui32 tableId, const TCompactionPolicy& newPolicy) +{ + TAlterRecord &delta = *Log.AddDelta(); + delta.SetDeltaType(TAlterRecord::SetCompactionPolicy); delta.SetTableId(tableId); newPolicy.Serialize(*delta.MutableCompactionPolicy()); - - return *this; -} - -TAlter& TAlter::SetByKeyFilter(ui32 tableId, bool enabled) -{ - TAlterRecord &delta = *Log.AddDelta(); - delta.SetDeltaType(TAlterRecord::SetTable); - delta.SetTableId(tableId); - delta.SetByKeyFilter(enabled ? 1 : 0); - - return *this; + + return *this; } +TAlter& TAlter::SetByKeyFilter(ui32 tableId, bool enabled) +{ + TAlterRecord &delta = *Log.AddDelta(); + delta.SetDeltaType(TAlterRecord::SetTable); + delta.SetTableId(tableId); + delta.SetByKeyFilter(enabled ? 1 : 0); + + return *this; +} + TAlter& TAlter::SetColdBorrow(ui32 tableId, bool enabled) { TAlterRecord &delta = *Log.AddDelta(); @@ -290,10 +290,10 @@ TAlter& TAlter::SetEraseCache(ui32 tableId, bool enabled, ui32 minRows, ui32 max return *this; } -TAutoPtr<TSchemeChanges> TAlter::Flush() -{ +TAutoPtr<TSchemeChanges> TAlter::Flush() +{ TAutoPtr<TSchemeChanges> log(new TSchemeChanges); - log->MutableDelta()->Swap(Log.MutableDelta()); + log->MutableDelta()->Swap(Log.MutableDelta()); return log; } diff --git a/ydb/core/tablet_flat/flat_dbase_scheme.h b/ydb/core/tablet_flat/flat_dbase_scheme.h index 1fd5ed2b48..3ba1f7ead9 100644 --- a/ydb/core/tablet_flat/flat_dbase_scheme.h +++ b/ydb/core/tablet_flat/flat_dbase_scheme.h @@ -1,18 +1,18 @@ #pragma once - -#include "flat_table_column.h" -#include "flat_page_iface.h" + +#include "flat_table_column.h" +#include "flat_page_iface.h" #include "util_basics.h" - + #include <ydb/core/base/localdb.h> #include <ydb/core/protos/scheme_log.pb.h> - + #include <util/generic/map.h> #include <util/generic/hash_set.h> #include <util/generic/list.h> namespace NKikimr { -namespace NTable { +namespace NTable { using namespace NTabletFlatScheme; @@ -23,56 +23,56 @@ using TCompactionPolicy = NLocalDb::TCompactionPolicy; class TScheme { public: using TTypeId = ui32; - using ECache = NPage::ECache; + using ECache = NPage::ECache; - enum EDefault { - DefaultRoom = 0, - DefaultChannel = 1, + enum EDefault { + DefaultRoom = 0, + DefaultChannel = 1, }; struct TRoom /* Storage unit settings (page collection) */ { - TRoom() = default; - - TRoom(ui32 channel) - : Main(channel) - { - - } - - bool IsTheSame(const TRoom &room) const noexcept - { - return - Main == room.Main - && Blobs == room.Blobs - && Outer == room.Outer; - } - + TRoom() = default; + + TRoom(ui32 channel) + : Main(channel) + { + + } + + bool IsTheSame(const TRoom &room) const noexcept + { + return + Main == room.Main + && Blobs == room.Blobs + && Outer == room.Outer; + } + ui8 Main = DefaultChannel; /* Primary channel for page collection */ - ui8 Blobs = DefaultChannel; /* Channel for external blobs */ - ui8 Outer = DefaultChannel; /* Channel for outer values pack*/ + ui8 Blobs = DefaultChannel; /* Channel for external blobs */ + ui8 Outer = DefaultChannel; /* Channel for outer values pack*/ }; - struct TFamily /* group of columns configuration */ { - using ECodec = NPage::ECodec; - - bool IsTheSame(const TFamily &other) const noexcept - { - return - Room == other.Room - && Cache == other.Cache - && Codec == other.Codec - && Small == other.Small - && Large == other.Large; - } - - ui32 Room = DefaultRoom; - ECache Cache = ECache::None; /* How to cache data pages */ - ECodec Codec = ECodec::Plain; /* How to encode data pages */ - ui32 Small = Max<ui32>(); /* When pack values to outer blobs */ - ui32 Large = Max<ui32>(); /* When keep values in single blobs */ - }; - - using TColumn = NTable::TColumn; + struct TFamily /* group of columns configuration */ { + using ECodec = NPage::ECodec; + + bool IsTheSame(const TFamily &other) const noexcept + { + return + Room == other.Room + && Cache == other.Cache + && Codec == other.Codec + && Small == other.Small + && Large == other.Large; + } + + ui32 Room = DefaultRoom; + ECache Cache = ECache::None; /* How to cache data pages */ + ECodec Codec = ECodec::Plain; /* How to encode data pages */ + ui32 Small = Max<ui32>(); /* When pack values to outer blobs */ + ui32 Large = Max<ui32>(); /* When keep values in single blobs */ + }; + + using TColumn = NTable::TColumn; struct TTableSchema { using TColumns = THashMap<ui32, TColumn>; @@ -84,15 +84,15 @@ public: }; struct TTableInfo : public TTableSchema { - TTableInfo(TString name, ui32 id) - : Id(id) - , Name(std::move(name)) + TTableInfo(TString name, ui32 id) + : Id(id) + , Name(std::move(name)) , CompactionPolicy(NLocalDb::CreateDefaultTablePolicy()) - { - Families[TColumn::LeaderFamily]; - Rooms[DefaultRoom]; - } - + { + Families[TColumn::LeaderFamily]; + Rooms[DefaultRoom]; + } + ui32 Id; TString Name; THashMap<ui32, TRoom> Rooms; @@ -100,40 +100,40 @@ public: TIntrusiveConstPtr<TCompactionPolicy> CompactionPolicy; bool ColdBorrow = false; - bool ByKeyFilter = false; + bool ByKeyFilter = false; bool EraseCacheEnabled = false; ui32 EraseCacheMinRows = 0; // 0 means use default ui32 EraseCacheMaxBytes = 0; // 0 means use default - }; - - struct TRedo { - /* Do not put cell values below this byte limit to external blobs - on writing redo log update entries (annex to log). By default - this limit is taken from Large field of family settings. Thus - - effective = Max(Annex, TFamily::Large) - - However cell value may be converted to external blob eventually - on compaction if Annex field overrides actual Large setting for - cell. This feature is required for testing and for ability to - turn off annex at all putting Max<ui32>() to Annex setting. - */ - - ui32 Annex = 512; /* some reasonably low default value */ + }; + + struct TRedo { + /* Do not put cell values below this byte limit to external blobs + on writing redo log update entries (annex to log). By default + this limit is taken from Large field of family settings. Thus + + effective = Max(Annex, TFamily::Large) + + However cell value may be converted to external blob eventually + on compaction if Annex field overrides actual Large setting for + cell. This feature is required for testing and for ability to + turn off annex at all putting Max<ui32>() to Annex setting. + */ + + ui32 Annex = 512; /* some reasonably low default value */ }; struct TExecutorInfo { ui64 CacheSize = 384 * 1024; - bool AllowLogBatching = false; + bool AllowLogBatching = false; bool LogFastTactic = true; - TDuration LogFlushPeriod = TDuration::MicroSeconds(500); - ui32 LimitInFlyTx = 0; + TDuration LogFlushPeriod = TDuration::MicroSeconds(500); + ui32 LimitInFlyTx = 0; TString ResourceProfile = "default"; ECompactionStrategy DefaultCompactionStrategy = NKikimrSchemeOp::CompactionStrategyGenerational; }; const TTableInfo* GetTableInfo(ui32 id) const { return const_cast<TScheme*>(this)->GetTableInfo(id); } - const TColumn* GetColumnInfo(ui32 table, ui32 id) const { return const_cast<TScheme*>(this)->GetColumnInfo(const_cast<TScheme*>(this)->GetTableInfo(table), id); } + const TColumn* GetColumnInfo(ui32 table, ui32 id) const { return const_cast<TScheme*>(this)->GetColumnInfo(const_cast<TScheme*>(this)->GetTableInfo(table), id); } TAutoPtr<TSchemeChanges> GetSnapshot() const; @@ -141,41 +141,41 @@ public: return Tables.FindPtr(id); } - inline TColumn* GetColumnInfo(TTableInfo* ptable, ui32 id) { - return ptable ? ptable->Columns.FindPtr(id) : nullptr; + inline TColumn* GetColumnInfo(TTableInfo* ptable, ui32 id) { + return ptable ? ptable->Columns.FindPtr(id) : nullptr; } - inline const TColumn* GetColumnInfo(const TTableInfo* ptable, ui32 id) const { - return ptable ? ptable->Columns.FindPtr(id) : nullptr; + inline const TColumn* GetColumnInfo(const TTableInfo* ptable, ui32 id) const { + return ptable ? ptable->Columns.FindPtr(id) : nullptr; } bool IsEmpty() const { return Tables.empty(); } - const TRoom* DefaultRoomFor(ui32 id) const noexcept - { - if (auto *table = GetTableInfo(id)) - return table->Rooms.FindPtr(DefaultRoom); - - return nullptr; - } - - const TFamily* DefaultFamilyFor(ui32 id) const noexcept - { - if (auto *table = GetTableInfo(id)) - return table->Families.FindPtr(TColumn::LeaderFamily); - - return nullptr; - } - - ECache CachePolicy(ui32 id) const noexcept - { - auto *family = DefaultFamilyFor(id); - - return family ? family->Cache : ECache::None; - } - + const TRoom* DefaultRoomFor(ui32 id) const noexcept + { + if (auto *table = GetTableInfo(id)) + return table->Rooms.FindPtr(DefaultRoom); + + return nullptr; + } + + const TFamily* DefaultFamilyFor(ui32 id) const noexcept + { + if (auto *table = GetTableInfo(id)) + return table->Families.FindPtr(TColumn::LeaderFamily); + + return nullptr; + } + + ECache CachePolicy(ui32 id) const noexcept + { + auto *family = DefaultFamilyFor(id); + + return family ? family->Cache : ECache::None; + } + ECompactionStrategy CompactionStrategyFor(ui32 id) const noexcept { if (auto *table = GetTableInfo(id)) { @@ -189,54 +189,54 @@ public: return strategy; } } - + return Executor.DefaultCompactionStrategy; } THashMap<ui32, TTableInfo> Tables; THashMap<TString, ui32> TableNames; - TExecutorInfo Executor; - TRedo Redo; + TExecutorInfo Executor; + TRedo Redo; }; // scheme delta -class TAlter { +class TAlter { public: - using ECodec = NPage::ECodec; - using ECache = NPage::ECache; - - const TSchemeChanges& operator*() const noexcept - { - return Log; - } - - TAlter& Merge(const TSchemeChanges &delta); - TAlter& AddTable(const TString& name, ui32 id); - TAlter& DropTable(ui32 id); + using ECodec = NPage::ECodec; + using ECache = NPage::ECache; + + const TSchemeChanges& operator*() const noexcept + { + return Log; + } + + TAlter& Merge(const TSchemeChanges &delta); + TAlter& AddTable(const TString& name, ui32 id); + TAlter& DropTable(ui32 id); TAlter& AddColumn(ui32 table, const TString& name, ui32 id, ui32 type, bool notNull, TCell null = { }); - TAlter& DropColumn(ui32 table, ui32 id); - TAlter& AddColumnToFamily(ui32 table, ui32 column, ui32 family); - TAlter& AddFamily(ui32 table, ui32 family, ui32 room); - TAlter& AddColumnToKey(ui32 table, ui32 column); - TAlter& SetFamily(ui32 table, ui32 family, ECache cache, ECodec codec); + TAlter& DropColumn(ui32 table, ui32 id); + TAlter& AddColumnToFamily(ui32 table, ui32 column, ui32 family); + TAlter& AddFamily(ui32 table, ui32 family, ui32 room); + TAlter& AddColumnToKey(ui32 table, ui32 column); + TAlter& SetFamily(ui32 table, ui32 family, ECache cache, ECodec codec); TAlter& SetFamilyBlobs(ui32 table, ui32 family, ui32 small, ui32 large); - TAlter& SetRoom(ui32 table, ui32 room, ui32 main, ui32 blobs, ui32 outer); - TAlter& SetRedo(ui32 annex); - TAlter& SetExecutorCacheSize(ui64 cacheSize); + TAlter& SetRoom(ui32 table, ui32 room, ui32 main, ui32 blobs, ui32 outer); + TAlter& SetRedo(ui32 annex); + TAlter& SetExecutorCacheSize(ui64 cacheSize); TAlter& SetExecutorFastLogPolicy(bool allow); - TAlter& SetExecutorAllowLogBatching(bool allow); - TAlter& SetExecutorLogFlushPeriod(TDuration flushPeriod); - TAlter& SetExecutorLimitInFlyTx(ui32 limitTxInFly); - TAlter& SetExecutorResourceProfile(const TString &name); - TAlter& SetCompactionPolicy(ui32 tableId, const TCompactionPolicy& newPolicy); - TAlter& SetByKeyFilter(ui32 tableId, bool enabled); + TAlter& SetExecutorAllowLogBatching(bool allow); + TAlter& SetExecutorLogFlushPeriod(TDuration flushPeriod); + TAlter& SetExecutorLimitInFlyTx(ui32 limitTxInFly); + TAlter& SetExecutorResourceProfile(const TString &name); + TAlter& SetCompactionPolicy(ui32 tableId, const TCompactionPolicy& newPolicy); + TAlter& SetByKeyFilter(ui32 tableId, bool enabled); TAlter& SetColdBorrow(ui32 tableId, bool enabled); TAlter& SetEraseCache(ui32 tableId, bool enabled, ui32 minRows, ui32 maxBytes); - - TAutoPtr<TSchemeChanges> Flush(); + + TAutoPtr<TSchemeChanges> Flush(); protected: - TSchemeChanges Log; + TSchemeChanges Log; }; }} diff --git a/ydb/core/tablet_flat/flat_dbase_sz_env.h b/ydb/core/tablet_flat/flat_dbase_sz_env.h index 39be8cd853..3a75b6deae 100644 --- a/ydb/core/tablet_flat/flat_dbase_sz_env.h +++ b/ydb/core/tablet_flat/flat_dbase_sz_env.h @@ -1,55 +1,55 @@ -#pragma once - -#include "flat_page_iface.h" -#include "flat_part_store.h" -#include <util/generic/hash_set.h> -#include <util/generic/cast.h> - -namespace NKikimr { -namespace NTable { - - struct TSizeEnv : public IPages { +#pragma once + +#include "flat_page_iface.h" +#include "flat_part_store.h" +#include <util/generic/hash_set.h> +#include <util/generic/cast.h> + +namespace NKikimr { +namespace NTable { + + struct TSizeEnv : public IPages { using TInfo = NTabletFlatExecutor::TPrivatePageCache::TInfo; - + TResult Locate(const TMemTable*, ui64, ui32) noexcept override - { + { Y_FAIL("IPages::Locate(TMemTable*, ...) shouldn't be used here"); - } - + } + TResult Locate(const TPart *part, ui64 ref, ELargeObj lob) noexcept override - { + { auto *partStore = CheckedCast<const NTable::TPartStore*>(part); - + return { true, Touch(partStore->Locate(lob, ref), ref) }; - } - + } + const TSharedData* TryGetPage(const TPart* part, TPageId page, TGroupId groupId) override - { + { auto *partStore = CheckedCast<const NTable::TPartStore*>(part); - + return Touch(partStore->PageCollections.at(groupId.Index).Get(), page); - } - - ui64 GetSize() const { - return Bytes; - } - - private: + } + + ui64 GetSize() const { + return Bytes; + } + + private: const TSharedData* Touch(TInfo *info, TPageId page) noexcept - { - if (Touched[info].insert(page).second) { - Pages++; + { + if (Touched[info].insert(page).second) { + Pages++; Bytes += info->PageCollection->Page(page).Size; - } - - return nullptr; - } - - private: + } + + return nullptr; + } + + private: THashMap<const void*, THashSet<TPageId>> Touched; - ui64 Pages = 0; - ui64 Bytes = 0; - }; - -} -} + ui64 Pages = 0; + ui64 Bytes = 0; + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_exec_broker.h b/ydb/core/tablet_flat/flat_exec_broker.h index 7e2647419f..26bcfa5e60 100644 --- a/ydb/core/tablet_flat/flat_exec_broker.h +++ b/ydb/core/tablet_flat/flat_exec_broker.h @@ -1,46 +1,46 @@ -#pragma once - +#pragma once + #include "util_basics.h" #include "flat_broker.h" #include <ydb/core/tablet/resource_broker.h> #include <library/cpp/actors/core/actor.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { - + +namespace NKikimr { +namespace NTabletFlatExecutor { + using TTaskId = NTable::TTaskId; using TResourceParams = NTable::TResourceParams; using EResourceStatus = NTable::EResourceStatus; using IResourceBroker = NTable::IResourceBroker; - enum class EWakeTag : ui64 { - Default = 0, /* Shouldn't be ever used */ - Memory = 1, /* TMemory GC scheduler */ - }; - + enum class EWakeTag : ui64 { + Default = 0, /* Shouldn't be ever used */ + Memory = 1, /* TMemory GC scheduler */ + }; + struct TIdEmitter : public TSimpleRefCount<TIdEmitter> { - ui64 Do() noexcept - { - return ++Serial; - } - - protected: - ui64 Serial = 0; - }; - - struct TResource : public TThrRefBase { - enum class ESource { - Seat, + ui64 Do() noexcept + { + return ++Serial; + } + + protected: + ui64 Serial = 0; + }; + + struct TResource : public TThrRefBase { + enum class ESource { + Seat, Scan, - }; - - TResource(ESource source) - : Source(source) + }; + + TResource(ESource source) + : Source(source) { } const ESource Source; - }; - + }; + class TBroker final : public IResourceBroker { using IOps = NActors::IActorOps; @@ -65,5 +65,5 @@ namespace NTabletFlatExecutor { THashMap<TTaskId, TResourceConsumer> Submitted; }; -} -} +} +} diff --git a/ydb/core/tablet_flat/flat_exec_commit.h b/ydb/core/tablet_flat/flat_exec_commit.h index 7212449c25..17b3b8ef68 100644 --- a/ydb/core/tablet_flat/flat_exec_commit.h +++ b/ydb/core/tablet_flat/flat_exec_commit.h @@ -1,61 +1,61 @@ -#pragma once - +#pragma once + #include <ydb/core/base/logoblob.h> -#include <util/generic/vector.h> -#include <util/generic/string.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { - +#include <util/generic/vector.h> +#include <util/generic/string.h> + +namespace NKikimr { +namespace NTabletFlatExecutor { + struct TSeat; - enum class ECommit { - Redo = 1, /* Tables data redo log */ - Snap = 2, /* Executor states snapshot */ - Data = 3, /* Page packets compaction */ - Misc = 8, /* The rest of commit types */ - }; - - struct TGCBlobDelta { - /* born -> [ Created ] -> hold -> [ Deleted ] -> gone */ - - TVector<TLogoBlobID> Created; - TVector<TLogoBlobID> Deleted; - }; - - struct TLogCommit { - TLogCommit(bool sync, ui32 step, ECommit type) - : Step(step) - , Type(type) - , Sync(sync) - { - - } - - void Describe(IOutputStream &out) const noexcept - { - out - << "Commit{" << Step << " orig " << ui32(Type) - << ", " << (Sync ? "S" : "-") << (Embedded ? "E" : "-") + enum class ECommit { + Redo = 1, /* Tables data redo log */ + Snap = 2, /* Executor states snapshot */ + Data = 3, /* Page packets compaction */ + Misc = 8, /* The rest of commit types */ + }; + + struct TGCBlobDelta { + /* born -> [ Created ] -> hold -> [ Deleted ] -> gone */ + + TVector<TLogoBlobID> Created; + TVector<TLogoBlobID> Deleted; + }; + + struct TLogCommit { + TLogCommit(bool sync, ui32 step, ECommit type) + : Step(step) + , Type(type) + , Sync(sync) + { + + } + + void Describe(IOutputStream &out) const noexcept + { + out + << "Commit{" << Step << " orig " << ui32(Type) + << ", " << (Sync ? "S" : "-") << (Embedded ? "E" : "-") << (FollowerAux ? "X" : "-") << " " << Refs.size() << " refs" - << ", Gc (+" << +GcDelta.Created.size() - << " -" << GcDelta.Deleted.size() << ")}"; - } - + << ", Gc (+" << +GcDelta.Created.size() + << " -" << GcDelta.Deleted.size() << ")}"; + } + void PushTx(TSeat *seat) noexcept; TSeat* PopTx() noexcept; - const ui32 Step = Max<ui32>(); - const ECommit Type = ECommit::Misc; - const bool Sync = false; + const ui32 Step = Max<ui32>(); + const ECommit Type = ECommit::Misc; + const bool Sync = false; bool WaitFollowerGcAck = false; - TString Embedded; + TString Embedded; TString FollowerAux; - TVector<TLogoBlob> Refs; - TGCBlobDelta GcDelta; + TVector<TLogoBlob> Refs; + TGCBlobDelta GcDelta; TSeat *FirstTx = nullptr; TSeat *LastTx = nullptr; - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_exec_commit_mgr.h b/ydb/core/tablet_flat/flat_exec_commit_mgr.h index 20f5d5ffe1..0de970fd0d 100644 --- a/ydb/core/tablet_flat/flat_exec_commit_mgr.h +++ b/ydb/core/tablet_flat/flat_exec_commit_mgr.h @@ -1,206 +1,206 @@ -#pragma once - -#include "flat_bio_eggs.h" -#include "flat_exec_commit.h" -#include "flat_boot_oven.h" -#include "logic_snap_waste.h" -#include "flat_sausage_slicer.h" -#include "flat_executor_gclogic.h" -#include "flat_executor_counters.h" +#pragma once + +#include "flat_bio_eggs.h" +#include "flat_exec_commit.h" +#include "flat_boot_oven.h" +#include "logic_snap_waste.h" +#include "flat_sausage_slicer.h" +#include "flat_executor_gclogic.h" +#include "flat_executor_counters.h" #include <ydb/core/base/blobstorage.h> #include <ydb/core/base/tablet.h> #include <ydb/core/tablet_flat/flat_executor.pb.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { - + +namespace NKikimr { +namespace NTabletFlatExecutor { + class TCommitManager { - /*_ TExecutor log commits flow controller module - - Optional synchronous ~ on the current Step0 --. - vvvvv - >---------.-----------.-----------.-----------.-----------.----------.-> - | Pending.4 | Pending.3 | Detach.2 | Detach.1 | Sync | - >---------'-----------'-----------'-----------'-----------'----------'-> - + /*_ TExecutor log commits flow controller module + + Optional synchronous ~ on the current Step0 --. + vvvvv + >---------.-----------.-----------.-----------.-----------.----------.-> + | Pending.4 | Pending.3 | Detach.2 | Detach.1 | Sync | + >---------'-----------'-----------'-----------'-----------'----------'-> + Confirmed | Commit(..)-ed | Acquired with Begin(..) | - - . N-4 N-3 N-2 N-1 N N+1 - Step | >---|-----------'-----------|-----------'-----------|----------'> - | ' ' ' - ' Back Tail Head - - * There may be at most one synchronous ~ on the current Head step; + + . N-4 N-3 N-2 N-1 N N+1 + Step | >---|-----------'-----------|-----------'-----------|----------'> + | ' ' ' + ' Back Tail Head + + * There may be at most one synchronous ~ on the current Head step; * detached ~ acquires step by moving Head forward on Begin(false); * synchronus ~ moves Head step forward only on its Commit(...); * all Commit(..) calls have to be serialized by commit Step order. - + > CommitManager{ 1:1 | 4 [7, 7], lvl 5982068b } ^^^. ^.^^^^^^. ^^^^^^^. `. `. `. `- Blobs KEEPing by tablet `. `. `-- Current active commits steps span `. `------- Pending commit confirmation step `--------- Tablet:Generation of the tablet - - [7, 7] has one active synchronous commit on the Head - [7, 8) has one detached commit on past step 7 - [6, 8] has two detached commits on {6, 7} and one sync - [8, 8) has no any allocated active commits at all - */ - - public: - using IOps = NActors::IActorOps; - using ETactic = TEvBlobStorage::TEvPut::ETactic; - using TMonCo = TExecutorCounters; - using TGcLogic = TExecutorGCLogic; - using TEvCommit = TEvTablet::TEvCommit; - + + [7, 7] has one active synchronous commit on the Head + [7, 8) has one detached commit on past step 7 + [6, 8] has two detached commits on {6, 7} and one sync + [8, 8) has no any allocated active commits at all + */ + + public: + using IOps = NActors::IActorOps; + using ETactic = TEvBlobStorage::TEvPut::ETactic; + using TMonCo = TExecutorCounters; + using TGcLogic = TExecutorGCLogic; + using TEvCommit = TEvTablet::TEvCommit; + TCommitManager(NBoot::TSteppedCookieAllocatorFactory &steppedCookieAllocatorFactory, TIntrusivePtr<NSnap::TWaste> waste, TGcLogic *logic) : Tablet(steppedCookieAllocatorFactory.Tablet) , Gen(steppedCookieAllocatorFactory.Gen) - , Waste(std::move(waste)) - , GcLogic(logic) + , Waste(std::move(waste)) + , GcLogic(logic) , Turns_(steppedCookieAllocatorFactory.Sys(NBoot::TCookie::EIdx::TurnLz4)) , Annex(steppedCookieAllocatorFactory.Data()) , Turns(1, Turns_.Get(), NBlockIO::BlockSize) - { - - } - - void Describe(IOutputStream &out) const noexcept - { - out + { + + } + + void Describe(IOutputStream &out) const noexcept + { + out << "CommitManager{" << Tablet << ":" << Gen << " | " - << Min(Back, Tail) << " [" << Tail << ", " - << Head << (Sync ? "]" : ")") - << ", lvl " << Waste->Level << "b}"; - } - + << Min(Back, Tail) << " [" << Tail << ", " + << Head << (Sync ? "]" : ")") + << ", lvl " << Waste->Level << "b}"; + } + void Start(IOps *ops, TActorId owner, ui32 *step0, TMonCo *monCo) - { + { Y_VERIFY(!std::exchange(Ops, ops), "Commit manager is already started"); - - Step0 = step0; - Owner = owner; - MonCo = monCo; - - *Step0 = Head = Tail = 1; - } - - void SetTactic(ETactic tactic) noexcept { Tactic = tactic; } - - ui64 Stamp() const noexcept - { - return NTable::TTxStamp{ Gen, Head }; - } - + + Step0 = step0; + Owner = owner; + MonCo = monCo; + + *Step0 = Head = Tail = 1; + } + + void SetTactic(ETactic tactic) noexcept { Tactic = tactic; } + + ui64 Stamp() const noexcept + { + return NTable::TTxStamp{ Gen, Head }; + } + TAutoPtr<TLogCommit> Begin(bool sync, ECommit type) noexcept - { - const auto step = Head; - - if (Sync && sync) { - Y_Fail(NFmt::Do(*this) << " tried to start nested commit"); - } else if (Sync && !sync) { - Y_Fail(NFmt::Do(*this) << " tried to detach sync commit"); - } else if (sync) { - Sync = true; - } else { - Switch(Head += 1); /* detached commits moves head now */ - } - - return new TLogCommit(sync, step, type); - } - + { + const auto step = Head; + + if (Sync && sync) { + Y_Fail(NFmt::Do(*this) << " tried to start nested commit"); + } else if (Sync && !sync) { + Y_Fail(NFmt::Do(*this) << " tried to detach sync commit"); + } else if (sync) { + Sync = true; + } else { + Switch(Head += 1); /* detached commits moves head now */ + } + + return new TLogCommit(sync, step, type); + } + void Commit(TAutoPtr<TLogCommit> commit) noexcept - { - if (commit->Step != Tail || (commit->Sync && !Sync)) { - Y_Fail( - NFmt::Do(*this) << " got unordered " << NFmt::Do(*commit)); - } else if (commit->Step == Head) { - Sync = false, Switch(Head += 1); /* sync ~ moves head forward */ - } - - Tail += 1; - Back = (Back == Max<ui32>() ? commit->Step : Back); - - StatsAccount(*commit); - Waste->Account(commit->GcDelta); - GcLogic->WriteToLog(*commit); + { + if (commit->Step != Tail || (commit->Sync && !Sync)) { + Y_Fail( + NFmt::Do(*this) << " got unordered " << NFmt::Do(*commit)); + } else if (commit->Step == Head) { + Sync = false, Switch(Head += 1); /* sync ~ moves head forward */ + } + + Tail += 1; + Back = (Back == Max<ui32>() ? commit->Step : Back); + + StatsAccount(*commit); + Waste->Account(commit->GcDelta); + GcLogic->WriteToLog(*commit); TrackCommitTxs(*commit); - SendCommitEv(*commit); - } - + SendCommitEv(*commit); + } + void Confirm(const ui32 step) noexcept - { - if (Back == Max<ui32>() || step != Back || step >= Tail) { - Y_Fail(NFmt::Do(*this) << " got unexpected confirm " << step); - } else { - Back = (Back + 1 == Tail) ? Max<ui32>() : Back + 1; - } - } - - private: - void Switch(ui32 step) noexcept - { - *Step0 = step; - - Turns_->Switch(step, true /* require step switch */); - Annex->Switch(step, true /* require step switch */); - } - - void StatsAccount(const TLogCommit &commit) noexcept - { - ui64 bytes = 0; - - for (const auto &one : commit.Refs) - bytes += one.Buffer.size(); - - MonCo->Cumulative()[TMonCo::LOG_COMMITS].Increment(1); - MonCo->Cumulative()[TMonCo::LOG_WRITTEN].Increment(bytes); - MonCo->Cumulative()[TMonCo::LOG_EMBEDDED].Increment(commit.Embedded.size()); - } - + { + if (Back == Max<ui32>() || step != Back || step >= Tail) { + Y_Fail(NFmt::Do(*this) << " got unexpected confirm " << step); + } else { + Back = (Back + 1 == Tail) ? Max<ui32>() : Back + 1; + } + } + + private: + void Switch(ui32 step) noexcept + { + *Step0 = step; + + Turns_->Switch(step, true /* require step switch */); + Annex->Switch(step, true /* require step switch */); + } + + void StatsAccount(const TLogCommit &commit) noexcept + { + ui64 bytes = 0; + + for (const auto &one : commit.Refs) + bytes += one.Buffer.size(); + + MonCo->Cumulative()[TMonCo::LOG_COMMITS].Increment(1); + MonCo->Cumulative()[TMonCo::LOG_WRITTEN].Increment(bytes); + MonCo->Cumulative()[TMonCo::LOG_EMBEDDED].Increment(commit.Embedded.size()); + } + void TrackCommitTxs(TLogCommit &commit) noexcept; - void SendCommitEv(TLogCommit &commit) noexcept - { - const bool snap = (commit.Type == ECommit::Snap); - - auto *ev = new TEvCommit(Tablet, Gen, commit.Step, { commit.Step - 1 }, snap); - - ev->CommitTactic = Tactic; - ev->References = std::move(commit.Refs); - ev->EmbeddedLogBody = std::move(commit.Embedded); + void SendCommitEv(TLogCommit &commit) noexcept + { + const bool snap = (commit.Type == ECommit::Snap); + + auto *ev = new TEvCommit(Tablet, Gen, commit.Step, { commit.Step - 1 }, snap); + + ev->CommitTactic = Tactic; + ev->References = std::move(commit.Refs); + ev->EmbeddedLogBody = std::move(commit.Embedded); ev->WaitFollowerGcAck = commit.WaitFollowerGcAck; ev->FollowerAux = std::move(commit.FollowerAux); - ev->GcDiscovered = std::move(commit.GcDelta.Created); - ev->GcLeft = std::move(commit.GcDelta.Deleted); - - Ops->Send(Owner, ev, 0, ui64(commit.Type)); - } - - public: - const ui64 Tablet = Max<ui64>(); - const ui32 Gen = Max<ui32>(); - - private: - IOps * Ops = nullptr; + ev->GcDiscovered = std::move(commit.GcDelta.Created); + ev->GcLeft = std::move(commit.GcDelta.Deleted); + + Ops->Send(Owner, ev, 0, ui64(commit.Type)); + } + + public: + const ui64 Tablet = Max<ui64>(); + const ui32 Gen = Max<ui32>(); + + private: + IOps * Ops = nullptr; TActorId Owner; - ui32 Back = Max<ui32>();/* Commits confirmation edge step */ - ui32 Tail = 0; /* Active detached lower Step */ - ui32 Head = 0; /* Tablet current step, AKA Step0 */ - ui32 *Step0 = nullptr; /* Compatability for tablet Step0 */ - bool Sync = false; /* Synchromous commit in progress */ + ui32 Back = Max<ui32>();/* Commits confirmation edge step */ + ui32 Tail = 0; /* Active detached lower Step */ + ui32 Head = 0; /* Tablet current step, AKA Step0 */ + ui32 *Step0 = nullptr; /* Compatability for tablet Step0 */ + bool Sync = false; /* Synchromous commit in progress */ TIntrusivePtr<NSnap::TWaste> Waste; - ETactic Tactic = ETactic::TacticDefault; - TGcLogic * const GcLogic = nullptr; - TMonCo * MonCo = nullptr; + ETactic Tactic = ETactic::TacticDefault; + TGcLogic * const GcLogic = nullptr; + TMonCo * MonCo = nullptr; TAutoPtr<NPageCollection::TSteppedCookieAllocator> Turns_; - - public: + + public: TAutoPtr<NPageCollection::TSteppedCookieAllocator> Annex; NPageCollection::TSlicer Turns; - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_exec_memory.h b/ydb/core/tablet_flat/flat_exec_memory.h index 9f827bd75e..fae882b38f 100644 --- a/ydb/core/tablet_flat/flat_exec_memory.h +++ b/ydb/core/tablet_flat/flat_exec_memory.h @@ -1,431 +1,431 @@ -#pragma once - -#include "flat_exec_seat.h" -#include "flat_exec_broker.h" -#include "util_fmt_line.h" - +#pragma once + +#include "flat_exec_seat.h" +#include "flat_exec_broker.h" +#include "util_fmt_line.h" + #include <library/cpp/actors/core/actor.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { - - class TMemory { - static constexpr ui32 MyPrio = 5; - - public: - using ELnLev = NUtil::ELnLev; - using TEvs = NResourceBroker::TEvResourceBroker; - using ETablet = NKikimrTabletBase::TTabletTypes::EType; - using IOps = NActors::IActorOps; - - struct TUsed { - void Describe(IOutputStream &out) const noexcept - { - out << "Memory{" << Static << " dyn " << Dynamic << "}"; - } - - ui64 Static = 0; - ui64 Dynamic = 0; - }; - - struct TCookie : public TResource { - TCookie(TSeat *seat) - : TResource(ESource::Seat) - , Seat(seat) - { - - } - - TSeat * const Seat = nullptr; - }; - + +namespace NKikimr { +namespace NTabletFlatExecutor { + + class TMemory { + static constexpr ui32 MyPrio = 5; + + public: + using ELnLev = NUtil::ELnLev; + using TEvs = NResourceBroker::TEvResourceBroker; + using ETablet = NKikimrTabletBase::TTabletTypes::EType; + using IOps = NActors::IActorOps; + + struct TUsed { + void Describe(IOutputStream &out) const noexcept + { + out << "Memory{" << Static << " dyn " << Dynamic << "}"; + } + + ui64 Static = 0; + ui64 Dynamic = 0; + }; + + struct TCookie : public TResource { + TCookie(TSeat *seat) + : TResource(ESource::Seat) + , Seat(seat) + { + + } + + TSeat * const Seat = nullptr; + }; + TMemory( NUtil::ILogger *logger, IOps *ops, TIntrusivePtr<TIdEmitter> emitter, TString taskNameSuffix = { }) - : Logger(logger) - , Ops(ops) + : Logger(logger) + , Ops(ops) , Emitter(emitter) - , Profiles(new TResourceProfiles) + , Profiles(new TResourceProfiles) , TaskNameSuffix(std::move(taskNameSuffix)) - { - - } - - const TUsed& Stats() const noexcept { return Used; } - - ui64 RemainedStatic(const TSeat &seat) noexcept - { - ui64 txLimit = Profile->GetStaticTxMemoryLimit() - ? Profile->GetStaticTxMemoryLimit() : Max<ui64>(); - if (txLimit <= seat.CurrentMemoryLimit) - return 0; - const ui64 remain = txLimit - seat.CurrentMemoryLimit; - - ui64 tabletLimit = Profile->GetStaticTabletTxMemoryLimit() - ? Profile->GetStaticTabletTxMemoryLimit() : Max<ui64>(); - if (tabletLimit <= Used.Static) - return 0; - - return Min(remain, tabletLimit - Used.Static); - } - - void RequestLimit(TSeat &seat, ui64 desired) noexcept - { - seat.CurrentMemoryLimit = desired; - - const auto type = GetTaskType(seat.CurrentMemoryLimit); - + { + + } + + const TUsed& Stats() const noexcept { return Used; } + + ui64 RemainedStatic(const TSeat &seat) noexcept + { + ui64 txLimit = Profile->GetStaticTxMemoryLimit() + ? Profile->GetStaticTxMemoryLimit() : Max<ui64>(); + if (txLimit <= seat.CurrentMemoryLimit) + return 0; + const ui64 remain = txLimit - seat.CurrentMemoryLimit; + + ui64 tabletLimit = Profile->GetStaticTabletTxMemoryLimit() + ? Profile->GetStaticTabletTxMemoryLimit() : Max<ui64>(); + if (tabletLimit <= Used.Static) + return 0; + + return Min(remain, tabletLimit - Used.Static); + } + + void RequestLimit(TSeat &seat, ui64 desired) noexcept + { + seat.CurrentMemoryLimit = desired; + + const auto type = GetTaskType(seat.CurrentMemoryLimit); + ui64 taskId = seat.TaskId ? seat.TaskId : Emitter->Do(); - - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Ops) << " " << NFmt::Do(seat) << " " - << (seat.TaskId ? "update" : "request") << " Res{" - << taskId << " " << seat.CurrentMemoryLimit << "b}" - << " type " << type; - } - - if (seat.TaskId) { - Send(new TEvs::TEvUpdateTask( - seat.TaskId, - {{ 0, seat.CurrentMemoryLimit }}, - type, MyPrio, true)); - } else { - Send(new TEvs::TEvSubmitTask( - taskId, + + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Ops) << " " << NFmt::Do(seat) << " " + << (seat.TaskId ? "update" : "request") << " Res{" + << taskId << " " << seat.CurrentMemoryLimit << "b}" + << " type " << type; + } + + if (seat.TaskId) { + Send(new TEvs::TEvUpdateTask( + seat.TaskId, + {{ 0, seat.CurrentMemoryLimit }}, + type, MyPrio, true)); + } else { + Send(new TEvs::TEvSubmitTask( + taskId, NFmt::Ln(seat) + TaskNameSuffix, - {{ 0, seat.CurrentMemoryLimit }}, - type, MyPrio, new TCookie(&seat))); - } - } - - void AcquiredMemory(TSeat &seat, ui32 task) noexcept - { - seat.TaskId = task; - - Used.Dynamic += seat.CurrentMemoryLimit; - - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Ops) << " " << NFmt::Do(seat) - << " acquired dyn mem Res{" << seat.TaskId << " " - << seat.CurrentMemoryLimit << "b}, " << NFmt::Do(Used); - } - } - - void ReleaseMemory(TSeat &seat) noexcept - { - if (!seat.TaskId) { - FreeStatic(seat, seat.CapturedMemory ? seat.CapturedMemory->Size : 0); - } else if (seat.CapturedMemory) { - CaptureDynamic(seat); - } else { - Used.Dynamic -= seat.CurrentMemoryLimit; - - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Ops) << " " << NFmt::Do(seat) - << " release Res{"<< seat.TaskId - << " " << seat.CurrentMemoryLimit << "b}" - << ", " << NFmt::Do(Used); - } - - Send(new TEvs::TEvFinishTask(seat.TaskId)); - - seat.TaskId = 0; - } - - if (seat.CapturedMemory) { - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Ops) << " " << NFmt::Do(seat) << " " - << "captured " << NFmt::Do(*seat.CapturedMemory); - } - - Tokens.insert(std::move(seat.CapturedMemory)); - } - - if (seat.AttachedMemory) { - if (seat.AttachedMemory->GCToken->TaskId) { - Send(new TEvs::TEvFinishTask(seat.AttachedMemory->GCToken->TaskId)); - - Used.Dynamic -= seat.AttachedMemory->GCToken->Size; - } else { - Used.Static -= seat.AttachedMemory->GCToken->Size; - } - - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Ops) << " release attached " - << NFmt::Do(*seat.AttachedMemory->GCToken) - << ", " << NFmt::Do(Used); - } - - Tokens.erase(seat.AttachedMemory->GCToken); - seat.AttachedMemory = nullptr; - } - } - - void ReleaseTxData(TSeat &seat) noexcept - { - if (seat.CapturedMemory) { - - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Ops) << " " << NFmt::Do(seat) << " " - << "captured " << NFmt::Do(*seat.CapturedMemory); - } - - if (seat.CapturedMemory->TaskId) { - CaptureDynamic(seat); - } else { - seat.CurrentMemoryLimit -= seat.CapturedMemory->Size; - seat.CurrentTxDataLimit -= seat.CapturedMemory->Size; - } - - Tokens.insert(std::move(seat.CapturedMemory)); - - ScheduleGC(); - } - - if (seat.TaskId) { - Used.Dynamic -= seat.CurrentMemoryLimit; - - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Ops) << " released on update Res{" - << seat.TaskId << " " << seat.CurrentMemoryLimit << "b}" - << ", " << NFmt::Do(Used); - } - } - } - - void AttachMemory(TSeat &seat) noexcept - { - const ui64 taskId = seat.AttachedMemory->GCToken->TaskId; - const ui64 bytes = seat.AttachedMemory->GCToken->Size; - - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Ops) << " found attached " - << NFmt::Do(*seat.AttachedMemory->GCToken); - } - - if (!taskId) { - /* Attached static memory is just released here. It will - be allocated back if needed and possible. */ - - Used.Static -= bytes; - seat.CurrentTxDataLimit = bytes; - - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Ops) << " release captured by tx " - << NFmt::Do(*seat.AttachedMemory->GCToken) - << ", " << NFmt::Do(Used); - } - - } else if (seat.TaskId) { - // If we have two tasks then merge resources into a single one. - seat.CurrentTxDataLimit = bytes; - seat.CurrentMemoryLimit += bytes; - - auto limit = Profile->GetTxMemoryLimit(); - - if (limit && seat.CurrentMemoryLimit > limit) - seat.CurrentMemoryLimit = limit; - - const auto type = GetTaskType(seat.CurrentMemoryLimit); - - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Ops) << " moving tx data from attached " - << NFmt::Do(*seat.AttachedMemory->GCToken) - << " to Res{" << seat.TaskId << " ...}"; - } - - Send(new TEvs::TEvUpdateTask( - seat.TaskId, - {{ 0, seat.CurrentMemoryLimit }}, - type, MyPrio, false)); - - Send(new TEvs::TEvFinishTask(taskId)); - - } else { - // Don't support mix of static and dynamic memory. - // Release static memory then. - seat.TaskId = taskId; - Used.Static -= seat.CurrentMemoryLimit; - - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << "release " << seat.CurrentMemoryLimit << "b of" - << " static tx data due to attached res " << taskId - << ", " << NFmt::Do(Used); - } - - Send(new TEvs::TEvUpdateTaskCookie(taskId, new TCookie(&seat))); - - seat.CurrentTxDataLimit = bytes; - seat.CurrentMemoryLimit = bytes; - } - - Tokens.erase(seat.AttachedMemory->GCToken); - seat.AttachedMemory = nullptr; - } - - void AllocStatic(TSeat &seat, ui64 newLimit) noexcept - { - Y_VERIFY(newLimit >= seat.CurrentTxDataLimit + seat.MemoryTouched); - - Used.Static -= seat.CurrentMemoryLimit; - seat.CurrentMemoryLimit = newLimit; - Used.Static += seat.CurrentMemoryLimit; - - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Ops) << " " << NFmt::Do(seat) << " took " - << newLimit << "b of static mem, " << NFmt::Do(Used); - } - } - - void FreeStatic(TSeat &seat, ui64 hold) noexcept - { - if (seat.TaskId) - return; - - Y_VERIFY(seat.CurrentMemoryLimit >= hold); - ui64 release = seat.CurrentMemoryLimit - hold; - Used.Static -= release; - - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Ops) << " " << NFmt::Do(seat) << " release" - << " " << release << "b of static, " << NFmt::Do(Used); - } - } - - void RunMemoryGC() noexcept - { - GCScheduled = false; - + {{ 0, seat.CurrentMemoryLimit }}, + type, MyPrio, new TCookie(&seat))); + } + } + + void AcquiredMemory(TSeat &seat, ui32 task) noexcept + { + seat.TaskId = task; + + Used.Dynamic += seat.CurrentMemoryLimit; + + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Ops) << " " << NFmt::Do(seat) + << " acquired dyn mem Res{" << seat.TaskId << " " + << seat.CurrentMemoryLimit << "b}, " << NFmt::Do(Used); + } + } + + void ReleaseMemory(TSeat &seat) noexcept + { + if (!seat.TaskId) { + FreeStatic(seat, seat.CapturedMemory ? seat.CapturedMemory->Size : 0); + } else if (seat.CapturedMemory) { + CaptureDynamic(seat); + } else { + Used.Dynamic -= seat.CurrentMemoryLimit; + + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Ops) << " " << NFmt::Do(seat) + << " release Res{"<< seat.TaskId + << " " << seat.CurrentMemoryLimit << "b}" + << ", " << NFmt::Do(Used); + } + + Send(new TEvs::TEvFinishTask(seat.TaskId)); + + seat.TaskId = 0; + } + + if (seat.CapturedMemory) { + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Ops) << " " << NFmt::Do(seat) << " " + << "captured " << NFmt::Do(*seat.CapturedMemory); + } + + Tokens.insert(std::move(seat.CapturedMemory)); + } + + if (seat.AttachedMemory) { + if (seat.AttachedMemory->GCToken->TaskId) { + Send(new TEvs::TEvFinishTask(seat.AttachedMemory->GCToken->TaskId)); + + Used.Dynamic -= seat.AttachedMemory->GCToken->Size; + } else { + Used.Static -= seat.AttachedMemory->GCToken->Size; + } + + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Ops) << " release attached " + << NFmt::Do(*seat.AttachedMemory->GCToken) + << ", " << NFmt::Do(Used); + } + + Tokens.erase(seat.AttachedMemory->GCToken); + seat.AttachedMemory = nullptr; + } + } + + void ReleaseTxData(TSeat &seat) noexcept + { + if (seat.CapturedMemory) { + + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Ops) << " " << NFmt::Do(seat) << " " + << "captured " << NFmt::Do(*seat.CapturedMemory); + } + + if (seat.CapturedMemory->TaskId) { + CaptureDynamic(seat); + } else { + seat.CurrentMemoryLimit -= seat.CapturedMemory->Size; + seat.CurrentTxDataLimit -= seat.CapturedMemory->Size; + } + + Tokens.insert(std::move(seat.CapturedMemory)); + + ScheduleGC(); + } + + if (seat.TaskId) { + Used.Dynamic -= seat.CurrentMemoryLimit; + + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Ops) << " released on update Res{" + << seat.TaskId << " " << seat.CurrentMemoryLimit << "b}" + << ", " << NFmt::Do(Used); + } + } + } + + void AttachMemory(TSeat &seat) noexcept + { + const ui64 taskId = seat.AttachedMemory->GCToken->TaskId; + const ui64 bytes = seat.AttachedMemory->GCToken->Size; + + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Ops) << " found attached " + << NFmt::Do(*seat.AttachedMemory->GCToken); + } + + if (!taskId) { + /* Attached static memory is just released here. It will + be allocated back if needed and possible. */ + + Used.Static -= bytes; + seat.CurrentTxDataLimit = bytes; + + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Ops) << " release captured by tx " + << NFmt::Do(*seat.AttachedMemory->GCToken) + << ", " << NFmt::Do(Used); + } + + } else if (seat.TaskId) { + // If we have two tasks then merge resources into a single one. + seat.CurrentTxDataLimit = bytes; + seat.CurrentMemoryLimit += bytes; + + auto limit = Profile->GetTxMemoryLimit(); + + if (limit && seat.CurrentMemoryLimit > limit) + seat.CurrentMemoryLimit = limit; + + const auto type = GetTaskType(seat.CurrentMemoryLimit); + + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Ops) << " moving tx data from attached " + << NFmt::Do(*seat.AttachedMemory->GCToken) + << " to Res{" << seat.TaskId << " ...}"; + } + + Send(new TEvs::TEvUpdateTask( + seat.TaskId, + {{ 0, seat.CurrentMemoryLimit }}, + type, MyPrio, false)); + + Send(new TEvs::TEvFinishTask(taskId)); + + } else { + // Don't support mix of static and dynamic memory. + // Release static memory then. + seat.TaskId = taskId; + Used.Static -= seat.CurrentMemoryLimit; + + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << "release " << seat.CurrentMemoryLimit << "b of" + << " static tx data due to attached res " << taskId + << ", " << NFmt::Do(Used); + } + + Send(new TEvs::TEvUpdateTaskCookie(taskId, new TCookie(&seat))); + + seat.CurrentTxDataLimit = bytes; + seat.CurrentMemoryLimit = bytes; + } + + Tokens.erase(seat.AttachedMemory->GCToken); + seat.AttachedMemory = nullptr; + } + + void AllocStatic(TSeat &seat, ui64 newLimit) noexcept + { + Y_VERIFY(newLimit >= seat.CurrentTxDataLimit + seat.MemoryTouched); + + Used.Static -= seat.CurrentMemoryLimit; + seat.CurrentMemoryLimit = newLimit; + Used.Static += seat.CurrentMemoryLimit; + + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Ops) << " " << NFmt::Do(seat) << " took " + << newLimit << "b of static mem, " << NFmt::Do(Used); + } + } + + void FreeStatic(TSeat &seat, ui64 hold) noexcept + { + if (seat.TaskId) + return; + + Y_VERIFY(seat.CurrentMemoryLimit >= hold); + ui64 release = seat.CurrentMemoryLimit - hold; + Used.Static -= release; + + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Ops) << " " << NFmt::Do(seat) << " release" + << " " << release << "b of static, " << NFmt::Do(Used); + } + } + + void RunMemoryGC() noexcept + { + GCScheduled = false; + TVector<TIntrusivePtr<TMemoryGCToken>> dropped; - - for (auto it = Tokens.begin(); it != Tokens.end(); ++it) { - if ((*it)->IsDropped()) { - if ((*it)->TaskId) { - Send(new TEvs::TEvFinishTask((*it)->TaskId)); - - Used.Dynamic -= (*it)->Size; - } else { - Used.Static -= (*it)->Size; - } - - if (auto logl = Logger->Log(ELnLev::Crit)) { - logl - << NFmt::Do(*Ops) << " released leaked " - << NFmt::Do(**it) << ", " << NFmt::Do(Used); - } - - dropped.push_back(*it); - } - } - - for (auto &token : dropped) - Tokens.erase(token); - - ScheduleGC(); - } - - void ScheduleGC() noexcept - { - if (Tokens && !std::exchange(GCScheduled, true)) - Ops->Schedule(TDuration::Minutes(1), - new TEvents::TEvWakeup(ui64(EWakeTag::Memory))); - } - - void DumpStateToHTML(IOutputStream &out) noexcept - { - HTML(out) { - DIV_CLASS("row") {out << "profile: " << Profile->ShortDebugString(); } - DIV_CLASS("row") {out << "static memory: " << Used.Static; } - DIV_CLASS("row") {out << "dynamic memory: " << Used.Dynamic; } - - for (auto &token : Tokens) { - DIV_CLASS("row") { - out << "captured memory: " << NFmt::Do(*token); - } - } - } - } - + + for (auto it = Tokens.begin(); it != Tokens.end(); ++it) { + if ((*it)->IsDropped()) { + if ((*it)->TaskId) { + Send(new TEvs::TEvFinishTask((*it)->TaskId)); + + Used.Dynamic -= (*it)->Size; + } else { + Used.Static -= (*it)->Size; + } + + if (auto logl = Logger->Log(ELnLev::Crit)) { + logl + << NFmt::Do(*Ops) << " released leaked " + << NFmt::Do(**it) << ", " << NFmt::Do(Used); + } + + dropped.push_back(*it); + } + } + + for (auto &token : dropped) + Tokens.erase(token); + + ScheduleGC(); + } + + void ScheduleGC() noexcept + { + if (Tokens && !std::exchange(GCScheduled, true)) + Ops->Schedule(TDuration::Minutes(1), + new TEvents::TEvWakeup(ui64(EWakeTag::Memory))); + } + + void DumpStateToHTML(IOutputStream &out) noexcept + { + HTML(out) { + DIV_CLASS("row") {out << "profile: " << Profile->ShortDebugString(); } + DIV_CLASS("row") {out << "static memory: " << Used.Static; } + DIV_CLASS("row") {out << "dynamic memory: " << Used.Dynamic; } + + for (auto &token : Tokens) { + DIV_CLASS("row") { + out << "captured memory: " << NFmt::Do(*token); + } + } + } + } + void SetProfiles(TResourceProfilesPtr profiles) noexcept - { - Profiles = profiles ? profiles : new TResourceProfiles; - } - - void UseProfile(ETablet type, const TString &name) noexcept - { - Profile = Profiles->GetProfile(type, name); - } - - private: - void CaptureDynamic(TSeat &seat) noexcept - { - const auto type = GetTaskType(seat.CapturedMemory->Size); - - Send(new TEvs::TEvUpdateTask( - seat.TaskId, - {{ 0, seat.CapturedMemory->Size }}, - type, MyPrio, false)); - - auto released = seat.CurrentMemoryLimit - seat.CapturedMemory->Size; - Used.Dynamic -= released; - - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*Ops) << " " << NFmt::Do(seat) - << " update resource task " << seat.CapturedMemory->TaskId - << " releasing " << released << "b, " << NFmt::Do(Used); - } - - seat.TaskId = 0; - seat.CurrentMemoryLimit = 0; - seat.CurrentTxDataLimit -= seat.CapturedMemory->Size; - } - + { + Profiles = profiles ? profiles : new TResourceProfiles; + } + + void UseProfile(ETablet type, const TString &name) noexcept + { + Profile = Profiles->GetProfile(type, name); + } + + private: + void CaptureDynamic(TSeat &seat) noexcept + { + const auto type = GetTaskType(seat.CapturedMemory->Size); + + Send(new TEvs::TEvUpdateTask( + seat.TaskId, + {{ 0, seat.CapturedMemory->Size }}, + type, MyPrio, false)); + + auto released = seat.CurrentMemoryLimit - seat.CapturedMemory->Size; + Used.Dynamic -= released; + + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*Ops) << " " << NFmt::Do(seat) + << " update resource task " << seat.CapturedMemory->TaskId + << " releasing " << released << "b, " << NFmt::Do(Used); + } + + seat.TaskId = 0; + seat.CurrentMemoryLimit = 0; + seat.CurrentTxDataLimit -= seat.CapturedMemory->Size; + } + void Send(TAutoPtr<IEventBase> event) - { - using namespace NResourceBroker; - - Ops->Send(MakeResourceBrokerID(), event.Release(), 0); - } - - TString GetTaskType(ui64 limit) const noexcept - { - if (limit <= Profile->GetSmallTxMemoryLimit()) - return Profile->GetSmallTxTaskType(); - if (limit <= Profile->GetMediumTxMemoryLimit()) - return Profile->GetMediumTxTaskType(); - return Profile->GetLargeTxTaskType(); - } - - private: - NUtil::ILogger * const Logger = nullptr; - IOps * const Ops = nullptr; + { + using namespace NResourceBroker; + + Ops->Send(MakeResourceBrokerID(), event.Release(), 0); + } + + TString GetTaskType(ui64 limit) const noexcept + { + if (limit <= Profile->GetSmallTxMemoryLimit()) + return Profile->GetSmallTxTaskType(); + if (limit <= Profile->GetMediumTxMemoryLimit()) + return Profile->GetMediumTxTaskType(); + return Profile->GetLargeTxTaskType(); + } + + private: + NUtil::ILogger * const Logger = nullptr; + IOps * const Ops = nullptr; const TIntrusivePtr<TIdEmitter> Emitter; - - bool GCScheduled = false; - TUsed Used; + + bool GCScheduled = false; + TUsed Used; THashSet<TIntrusivePtr<TMemoryGCToken>, TPtrHash> Tokens; TIntrusivePtr<TResourceProfiles> Profiles; TString TaskNameSuffix; - public: - TResourceProfiles::TPtr Profile; - }; - -} -} + public: + TResourceProfiles::TPtr Profile; + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_exec_scans.h b/ydb/core/tablet_flat/flat_exec_scans.h index 4ab7047351..1487489029 100644 --- a/ydb/core/tablet_flat/flat_exec_scans.h +++ b/ydb/core/tablet_flat/flat_exec_scans.h @@ -1,23 +1,23 @@ -#pragma once - -#include "flat_scan_eggs.h" +#pragma once + +#include "flat_scan_eggs.h" #include "flat_scan_actor.h" #include "flat_exec_broker.h" -#include "util_fmt_line.h" +#include "util_fmt_line.h" #include "util_fmt_abort.h" #include "flat_util_misc.h" #include "tablet_flat_executor.h" - -namespace NKikimr { -namespace NTabletFlatExecutor { - + +namespace NKikimr { +namespace NTabletFlatExecutor { + struct TScanOutcome { bool System; bool Cancelled; }; - class TScans { /* NOps state tracker */ - + class TScans { /* NOps state tracker */ + using IScan = NTable::IScan; using EAbort = NTable::EAbort; using IOps = NActors::IActorOps; @@ -49,8 +49,8 @@ namespace NTabletFlatExecutor { const ui64 Serial; }; - struct TOne : public TIntrusiveListItem<TOne> { - + struct TOne : public TIntrusiveListItem<TOne> { + TOne(ui64 serial, ui32 table, const TScanOptions& options, THolder<TScanSnapshot> snapshot) : Serial(serial) , Table(table) @@ -86,8 +86,8 @@ namespace NTabletFlatExecutor { TAutoPtr<IScan> Scan; /* Valid before EState::Scan */ ui64 Cookie = Max<ui64>(); ui64 TaskId = 0; /* Task number in res. broker */ - }; - + }; + struct TTable { ui32 Prio = 0; /* Scan task priotity in broker */ TString Type; /* Resource broker task type */ @@ -116,34 +116,34 @@ namespace NTabletFlatExecutor { } }; - public: + public: TScans(NUtil::ILogger *logger, IOps *ops, TIntrusivePtr<TIdEmitter> emitter, ITablet *owner, const TActorId& ownerActorId) - : Logger(logger) - , Ops(ops) + : Logger(logger) + , Ops(ops) , Owner(owner) , OwnerActorId(ownerActorId) , Tablet(Owner->TabletID()) , Emitter(std::move(emitter)) - { - - } - - void Describe(IOutputStream &out) const noexcept - { - out - << "Scans{serial " << Serial << ", " << Tables.size() << " tbl" + { + + } + + void Describe(IOutputStream &out) const noexcept + { + out + << "Scans{serial " << Serial << ", " << Tables.size() << " tbl" << ", " << Scans.size() << " ~" << CounterAlive << " scn}"; - } - + } + void Configure(ui32 table, ui64 aLo, ui64 aHi, ui32 prio, TString type) - { + { Tables[table].AheadLo = aLo; Tables[table].AheadHi = aHi; - + Tables[table].Prio = prio; Tables[table].Type = std::move(type); - + if (Y_UNLIKELY(NLocalDb::IsLegacyQueueIdTaskName(Tables[table].Type))) { // There are a lot of legacy tablets where old config has scans // and gen1 compaction on the same queue. It causes delayed @@ -153,13 +153,13 @@ namespace NTabletFlatExecutor { ++Tables[table].Prio; } } - + ui64 Queue(ui32 table, TAutoPtr<IScan> scan, ui64 cookie, const TScanOptions& options, THolder<TScanSnapshot> snapshot) { auto &one = Make(table, scan, EType::Client, options, std::move(snapshot)); - + one.Cookie = cookie; - + if (options.IsResourceBrokerDisabled()) { // A call to Start is expected now one.State = EState::Ready; @@ -168,7 +168,7 @@ namespace NTabletFlatExecutor { // A call to Acquired is expected later one.State = EState::Task; one.TaskId = Emitter->Do(); - + const auto* overrides = std::get_if<TScanOptions::TResourceBrokerOptions>(&options.ResourceBroker); ToBroker(new TEvResourceBroker::TEvSubmitTask( @@ -181,11 +181,11 @@ namespace NTabletFlatExecutor { return one.Serial; } - + TAcquired Acquired(ui64 task, TResource *cookie) noexcept { auto *one = Lookup(CheckedCast<TCookie*>(cookie)->Serial, false); - + if (one == nullptr) { ToBroker(new TEvResourceBroker::TEvFinishTask(task)); @@ -198,8 +198,8 @@ namespace NTabletFlatExecutor { return { one->Serial, one->Table }; } - } - + } + void Start(ui64 serial) { auto &one = *Lookup(serial, true); @@ -214,15 +214,15 @@ namespace NTabletFlatExecutor { return Start(one, conf); } - void Drop() noexcept - { + void Drop() noexcept + { while (Tables) { Drop(Tables.begin()->first); } - } - + } + TVector<THolder<TScanSnapshot>> Drop(ui32 table) noexcept - { + { TVector<THolder<TScanSnapshot>> snapshots; if (auto *entry = Tables.FindPtr(table)) { @@ -233,17 +233,17 @@ namespace NTabletFlatExecutor { } Cancel(*one, EState::Gone); } - - Tables.erase(table); - } + + Tables.erase(table); + } return snapshots; - } - + } + TCancelled Cancel(ui64 serial) noexcept - { + { auto *one = Lookup(serial, false); - + if (serial & 0x1 /* system scan */) { Y_Fail(NFmt::If(one) << " is system (" << serial << "), cannot be cancelled this way"); } @@ -253,16 +253,16 @@ namespace NTabletFlatExecutor { } TCancelled cancelled{ one->Serial, one->Table, std::move(one->Options), std::move(one->Snapshot) }; - + if (!Cancel(*one, EState::Forget)) { return { }; } - + return cancelled; - } - + } + bool CancelSystem(ui64 serial) noexcept - { + { auto *one = Lookup(serial, false); if (!(serial & 0x1 /* system scan */)) { @@ -279,7 +279,7 @@ namespace NTabletFlatExecutor { TScanOutcome Release(ui64 serial, EAbort &code, TAutoPtr<IDestructable> &result) noexcept { auto *one = Lookup(serial, true); - + if (one->State < EState::Scan) { Y_Fail(NFmt::Do(*one) << " got unexpected scan result"); } else { @@ -291,13 +291,13 @@ namespace NTabletFlatExecutor { return Throw(*one, one->State, code, result); } - } - - private: + } + + private: TOne& Make(ui32 table, TAutoPtr<IScan> scan, EType type, const TScanOptions& options, THolder<TScanSnapshot> snapshot) noexcept - { + { /* odd NOps used to mark compactions (system scans) */ - + const ui64 token = (Serial += 2) - (type == EType::System ? 1 : 0); auto got = Scans.emplace( @@ -319,8 +319,8 @@ namespace NTabletFlatExecutor { { if (one.State != EState::None && one.State != EState::Ready) { Y_Fail(NFmt::Do(one) << " is not in start condition"); - } - + } + switch (one.Options.ReadPrio) { case TScanOptions::EReadPrio::Default: break; @@ -359,8 +359,8 @@ namespace NTabletFlatExecutor { one.Actor = Ops->Register(actor, TMailboxType::HTSwap, pool); return one.Serial; - } - + } + bool Cancel(TOne &one, EState state) noexcept { if (one.State == EState::Task || one.State == EState::Ready) { @@ -438,19 +438,19 @@ namespace NTabletFlatExecutor { Ops->Send(MakeResourceBrokerID(), event.Release(), 0); } - private: + private: NUtil::ILogger * const Logger; IOps * const Ops; ITablet * const Owner; const TActorId OwnerActorId; const ui64 Tablet; - - ui64 Serial = 0; - + + ui64 Serial = 0; + const TIntrusivePtr<TIdEmitter> Emitter; ui32 CounterAlive = 0; THashMap<ui64, TOne> Scans; THashMap<ui32, TTable> Tables; /* only alive scans */ - }; -} -} + }; +} +} diff --git a/ydb/core/tablet_flat/flat_exec_seat.h b/ydb/core/tablet_flat/flat_exec_seat.h index f37d3bfb0b..e11c0620fa 100644 --- a/ydb/core/tablet_flat/flat_exec_seat.h +++ b/ydb/core/tablet_flat/flat_exec_seat.h @@ -1,64 +1,64 @@ -#pragma once - -#include "defs.h" -#include "tablet_flat_executor.h" -#include "flat_sausagecache.h" - -#include <util/generic/ptr.h> -#include <util/system/hp_timer.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { - - struct TSeat { +#pragma once + +#include "defs.h" +#include "tablet_flat_executor.h" +#include "flat_sausagecache.h" + +#include <util/generic/ptr.h> +#include <util/system/hp_timer.h> + +namespace NKikimr { +namespace NTabletFlatExecutor { + + struct TSeat { using TPinned = THashMap<TLogoBlobID, THashMap<ui32, TIntrusivePtr<TPrivatePageCachePinPad>>>; - - TSeat(const TSeat&) = delete; - + + TSeat(const TSeat&) = delete; + TSeat(ui32 uniqId, TAutoPtr<ITransaction> self) - : UniqID(uniqId) - , Self(self) - { - - } - - void Describe(IOutputStream &out) const noexcept - { + : UniqID(uniqId) + , Self(self) + { + + } + + void Describe(IOutputStream &out) const noexcept + { out << "Tx{" << UniqID << ", "; Self->Describe(out); out << "}"; - } - + } + void Complete(const TActorContext& ctx) noexcept; - const ui64 UniqID = Max<ui64>(); + const ui64 UniqID = Max<ui64>(); const TAutoPtr<ITransaction> Self; - ui64 Retries = 0; - TPinned Pinned; - - THPTimer LatencyTimer; - THPTimer CommitTimer; - - double CPUExecTime = 0; - double CPUBookkeepingTime = 0; - - ui64 MemoryTouched = 0; - ui64 RequestedMemory = 0; - - ui64 CurrentTxDataLimit = 0; - ui64 CurrentMemoryLimit = 0; + ui64 Retries = 0; + TPinned Pinned; + + THPTimer LatencyTimer; + THPTimer CommitTimer; + + double CPUExecTime = 0; + double CPUBookkeepingTime = 0; + + ui64 MemoryTouched = 0; + ui64 RequestedMemory = 0; + + ui64 CurrentTxDataLimit = 0; + ui64 CurrentMemoryLimit = 0; ui32 NotEnoughMemoryCount = 0; - ui64 TaskId = 0; - + ui64 TaskId = 0; + TAutoPtr<TMemoryToken> AttachedMemory; TIntrusivePtr<TMemoryGCToken> CapturedMemory; TVector<std::function<void()>> OnCommitted; - - ETerminationReason TerminationReason = ETerminationReason::None; + + ETerminationReason TerminationReason = ETerminationReason::None; TSeat *NextCommitTx = nullptr; - }; - - -} -} + }; + + +} +} diff --git a/ydb/core/tablet_flat/flat_executor.cpp b/ydb/core/tablet_flat/flat_executor.cpp index 59afc46215..fe0bd9d4b4 100644 --- a/ydb/core/tablet_flat/flat_executor.cpp +++ b/ydb/core/tablet_flat/flat_executor.cpp @@ -2,28 +2,28 @@ #include "flat_executor_bootlogic.h" #include "flat_executor_txloglogic.h" #include "flat_executor_borrowlogic.h" -#include "flat_bio_actor.h" -#include "flat_executor_snapshot.h" -#include "flat_scan_actor.h" -#include "flat_ops_compact.h" -#include "flat_part_loader.h" -#include "flat_store_hotdog.h" +#include "flat_bio_actor.h" +#include "flat_executor_snapshot.h" +#include "flat_scan_actor.h" +#include "flat_ops_compact.h" +#include "flat_part_loader.h" +#include "flat_store_hotdog.h" #include "flat_store_solid.h" -#include "flat_exec_broker.h" -#include "flat_exec_seat.h" +#include "flat_exec_broker.h" +#include "flat_exec_seat.h" #include "flat_exec_commit_mgr.h" -#include "flat_exec_scans.h" -#include "flat_exec_memory.h" -#include "flat_boot_cookie.h" -#include "flat_boot_oven.h" -#include "flat_executor_tx_env.h" +#include "flat_exec_scans.h" +#include "flat_exec_memory.h" +#include "flat_boot_cookie.h" +#include "flat_boot_oven.h" +#include "flat_executor_tx_env.h" #include "flat_executor_counters.h" -#include "logic_snap_main.h" -#include "logic_alter_main.h" -#include "flat_abi_evol.h" +#include "logic_snap_main.h" +#include "logic_alter_main.h" +#include "flat_abi_evol.h" #include "probes.h" #include "shared_sausagecache.h" -#include "util_fmt_desc.h" +#include "util_fmt_desc.h" #include <ydb/core/base/appdata.h> #include <ydb/core/base/compile_time_flags.h> @@ -66,7 +66,7 @@ TExecutor::TExecutor( NFlatExecutorSetup::ITablet* owner, const TActorId& ownerActorId) : TActor(&TThis::StateInit) - , Time(TAppData::TimeProvider) + , Time(TAppData::TimeProvider) , Owner(owner) , OwnerActorId(ownerActorId) , ActivationQueue(new TActivationQueue()) @@ -81,18 +81,18 @@ TExecutor::~TExecutor() { } -ui64 TExecutor::Stamp() const noexcept -{ +ui64 TExecutor::Stamp() const noexcept +{ return CommitManager ? CommitManager->Stamp() : TTxStamp{ Generation0, Step0 }.Raw; -} - +} + TActorContext TExecutor::OwnerCtx() const { return TActivationContext::ActorContextFor(OwnerActorId); } void TExecutor::Registered(TActorSystem *sys, const TActorId&) -{ - Logger = new NUtil::TLogger(sys, NKikimrServices::TABLET_EXECUTOR); +{ + Logger = new NUtil::TLogger(sys, NKikimrServices::TABLET_EXECUTOR); Broker = new TBroker(this, Emitter); Scans = new TScans(Logger.Get(), this, Emitter, Owner, OwnerActorId); Memory = new TMemory(Logger.Get(), this, Emitter, Sprintf(" at tablet %" PRIu64, Owner->TabletID())); @@ -104,35 +104,35 @@ void TExecutor::Registered(TActorSystem *sys, const TActorId&) GetServiceCounters(AppData()->Counters, "tablets")->GetCounter("alerts_req_nodata", true); GetServiceCounters(AppData()->Counters, "tablets")->GetCounter("alerts_scan_nodata", true); GetServiceCounters(AppData()->Counters, "tablets")->GetCounter("alerts_boot_nodata", true); -} - -void TExecutor::PassAway() { - if (auto logl = Logger->Log(ELnLev::Info)) { - auto *waste = LogicSnap ? &LogicSnap->Waste() : nullptr; - - logl - << NFmt::Do(*this) << " suiciding, " << NFmt::If(waste, true); - } - +} + +void TExecutor::PassAway() { + if (auto logl = Logger->Log(ELnLev::Info)) { + auto *waste = LogicSnap ? &LogicSnap->Waste() : nullptr; + + logl + << NFmt::Do(*this) << " suiciding, " << NFmt::If(waste, true); + } + if (CompactionLogic) { CompactionLogic->Stop(); } if (Broker || Scans || Memory) { - Send(NResourceBroker::MakeResourceBrokerID(), new NResourceBroker::TEvResourceBroker::TEvNotifyActorDied); + Send(NResourceBroker::MakeResourceBrokerID(), new NResourceBroker::TEvResourceBroker::TEvNotifyActorDied); } - Scans->Drop(); + Scans->Drop(); Owner = nullptr; Send(MakeSharedPageCacheId(), new NSharedCache::TEvUnregister()); - return TActor::PassAway(); + return TActor::PassAway(); } void TExecutor::Broken() { if (BootLogic) - BootLogic->Cancel(); + BootLogic->Cancel(); if (Owner) { TabletCountersForgetTablet(Owner->TabletID(), Owner->TabletType(), @@ -140,22 +140,22 @@ void TExecutor::Broken() { Owner->Detach(OwnerCtx()); } - return PassAway(); + return PassAway(); } void TExecutor::RecreatePageCollectionsCache() noexcept -{ +{ TCacheCacheConfig cacheConfig(Scheme().Executor.CacheSize, CounterCacheFresh, CounterCacheStaging, CounterCacheMemTable); PrivatePageCache = MakeHolder<TPrivatePageCache>(cacheConfig); + + Stats->PacksMetaBytes = 0; - Stats->PacksMetaBytes = 0; - - for (const auto &it : Database->GetScheme().Tables) { + for (const auto &it : Database->GetScheme().Tables) { auto subset = Database->Subset(it.first, NTable::TEpoch::Max(), { }, { }); - + for (auto &partView : subset->Flatten) AddCachesOfBundle(partView); - } - + } + if (TransactionWaitPads) { for (auto &xpair : TransactionWaitPads) { auto &seat = xpair.second->Seat; @@ -246,7 +246,7 @@ void TExecutor::CheckYellow(TVector<ui32> &&yellowMoveChannels, TVector<ui32> && return; HasYellowCheckInFly = true; - Schedule(TDuration::Seconds(15), new TEvPrivate::TEvCheckYellow()); + Schedule(TDuration::Seconds(15), new TEvPrivate::TEvCheckYellow()); } void TExecutor::SendReassignYellowChannels(const TVector<ui32> &yellowChannels) { @@ -262,16 +262,16 @@ void TExecutor::SendReassignYellowChannels(const TVector<ui32> &yellowChannels) } } -void TExecutor::UpdateYellow() { - Register(CreateTabletDSChecker(SelfId(), Owner->Info())); +void TExecutor::UpdateYellow() { + Register(CreateTabletDSChecker(SelfId(), Owner->Info())); } -void TExecutor::UpdateCompactions() { - CompactionLogic->UpdateCompactions(); - Schedule(TDuration::Minutes(1), new TEvPrivate::TEvUpdateCompactions); +void TExecutor::UpdateCompactions() { + CompactionLogic->UpdateCompactions(); + Schedule(TDuration::Minutes(1), new TEvPrivate::TEvUpdateCompactions); } -void TExecutor::Handle(TEvTablet::TEvCheckBlobstorageStatusResult::TPtr &ev) { +void TExecutor::Handle(TEvTablet::TEvCheckBlobstorageStatusResult::TPtr &ev) { Y_VERIFY(HasYellowCheckInFly); HasYellowCheckInFly = false; @@ -307,18 +307,18 @@ void TExecutor::Handle(TEvTablet::TEvCheckBlobstorageStatusResult::TPtr &ev) { } void TExecutor::ActivateFollower(const TActorContext &ctx) { - if (auto logl = Logger->Log(ELnLev::Info)) - logl << NFmt::Do(*this) << " activating executor"; + if (auto logl = Logger->Log(ELnLev::Info)) + logl << NFmt::Do(*this) << " activating executor"; - auto loadedState = BootLogic->ExtractState(); + auto loadedState = BootLogic->ExtractState(); BootLogic.Destroy(); Y_VERIFY(!GcLogic); - Y_VERIFY(!LogicRedo); - Y_VERIFY(!LogicAlter); - - Database = loadedState->Database; - BorrowLogic = loadedState->Loans; + Y_VERIFY(!LogicRedo); + Y_VERIFY(!LogicAlter); + + Database = loadedState->Database; + BorrowLogic = loadedState->Loans; Y_VERIFY(!CompactionLogic); if (!Counters) { @@ -338,7 +338,7 @@ void TExecutor::ActivateFollower(const TActorContext &ctx) { PendingBlobQueue.Config.Follower = true; PendingBlobQueue.Config.NoDataCounter = GetServiceCounters(AppData()->Counters, "tablets")->GetCounter("alerts_pending_nodata", true); - ReadResourceProfile(); + ReadResourceProfile(); RecreatePageCollectionsCache(); ReflectSchemeSettings(); @@ -355,31 +355,31 @@ void TExecutor::ActivateFollower(const TActorContext &ctx) { } void TExecutor::Active(const TActorContext &ctx) { - if (auto logl = Logger->Log(ELnLev::Info)) - logl << NFmt::Do(*this) << " activating executor"; + if (auto logl = Logger->Log(ELnLev::Info)) + logl << NFmt::Do(*this) << " activating executor"; - auto loadedState = BootLogic->ExtractState(); + auto loadedState = BootLogic->ExtractState(); BootLogic.Destroy(); Counters = MakeHolder<TExecutorCounters>(); - + CommitManager = loadedState->CommitManager; - Database = loadedState->Database; - LogicSnap = loadedState->Snap; + Database = loadedState->Database; + LogicSnap = loadedState->Snap; GcLogic = loadedState->GcLogic; - LogicRedo = loadedState->Redo; - LogicAlter = loadedState->Alter; - BorrowLogic = loadedState->Loans; + LogicRedo = loadedState->Redo; + LogicAlter = loadedState->Alter; + BorrowLogic = loadedState->Loans; Stats->CompactedPartLoans = BorrowLogic->GetCompactedLoansList(); Stats->HasSharedBlobs = BorrowLogic->GetHasFlag(); CommitManager->Start(this, Owner->Tablet(), &Step0, Counters.Get()); - + CompactionLogic = THolder<TCompactionLogic>(new TCompactionLogic(Logger.Get(), Broker.Get(), this, loadedState->Comp, Sprintf("tablet-%" PRIu64, Owner->TabletID()))); CountersBaseline = MakeHolder<TExecutorCounters>(); Counters->RememberCurrentStateAsBaseline(*CountersBaseline); - LogicRedo->InstallCounters(Counters.Get(), nullptr); + LogicRedo->InstallCounters(Counters.Get(), nullptr); CounterCacheFresh = new NMonitoring::TCounterForPtr; CounterCacheStaging = new NMonitoring::TCounterForPtr; @@ -404,16 +404,16 @@ void TExecutor::Active(const TActorContext &ctx) { CompactionLogic->Start(); - for (const auto &it: Database->GetScheme().Tables) - CompactionLogic->UpdateInMemStatsStep(it.first, 0, Database->GetTableMemSize(it.first)); - - UpdateCompactions(); - MakeLogSnapshot(); + for (const auto &it: Database->GetScheme().Tables) + CompactionLogic->UpdateInMemStatsStep(it.first, 0, Database->GetTableMemSize(it.first)); + + UpdateCompactions(); + MakeLogSnapshot(); - if (auto error = CheckBorrowConsistency()) { - if (auto logl = Logger->Log(ELnLev::Crit)) - logl << NFmt::Do(*this) << " Borrow consistency failed: " << error; - } + if (auto error = CheckBorrowConsistency()) { + if (auto logl = Logger->Log(ELnLev::Crit)) + logl << NFmt::Do(*this) << " Borrow consistency failed: " << error; + } PlanTransactionActivation(); PlanCompactionReadActivation(); @@ -463,7 +463,7 @@ void TExecutor::TranscriptFollowerBootOpResult(ui32 res, const TActorContext &ct } } -void TExecutor::PlanTransactionActivation() { +void TExecutor::PlanTransactionActivation() { if (!CanExecuteTransaction()) return; @@ -477,7 +477,7 @@ void TExecutor::PlanTransactionActivation() { } while (ActivateTransactionInFlight < ActivateTransactionWaiting) { - Send(SelfId(), new TEvPrivate::TEvActivateExecution()); + Send(SelfId(), new TEvPrivate::TEvActivateExecution()); ActivateTransactionInFlight++; } } @@ -512,70 +512,70 @@ void TExecutor::ActivateWaitingTransactions(TPrivatePageCache::TPage::TWaitQueue } void TExecutor::AddCachesOfBundle(const NTable::TPartView &partView) noexcept -{ +{ auto *partStore = partView.As<NTable::TPartStore>(); - { - ui32 room = 0; - + { + ui32 room = 0; + while (auto *pack = partStore->Packet(room++)) - Stats->PacksMetaBytes += pack->Meta.Raw.size(); - } - + Stats->PacksMetaBytes += pack->Meta.Raw.size(); + } + for (auto &cache : partStore->PageCollections) AddSingleCache(cache); - + if (const auto &blobs = partStore->Pseudo) AddSingleCache(blobs); -} - +} + void TExecutor::AddSingleCache(const TIntrusivePtr<TPrivatePageCache::TInfo> &info) noexcept { PrivatePageCache->RegisterPageCollection(info); Send(MakeSharedPageCacheId(), new NSharedCache::TEvAttach(info->PageCollection, SelfId())); } -void TExecutor::DropCachesOfBundle(const NTable::TPart &part) noexcept -{ +void TExecutor::DropCachesOfBundle(const NTable::TPart &part) noexcept +{ auto *partStore = CheckedCast<const NTable::TPartStore*>(&part); - - { - ui32 room = 0; - + + { + ui32 room = 0; + while (auto *pack = partStore->Packet(room++)) - NUtil::SubSafe(Stats->PacksMetaBytes, ui64(pack->Meta.Raw.size())); - } - + NUtil::SubSafe(Stats->PacksMetaBytes, ui64(pack->Meta.Raw.size())); + } + for (auto &cache : partStore->PageCollections) - DropSingleCache(cache->Id); - + DropSingleCache(cache->Id); + if (const auto &blobs = partStore->Pseudo) - DropSingleCache(blobs->Id); -} - -void TExecutor::DropSingleCache(const TLogoBlobID &label) noexcept -{ + DropSingleCache(blobs->Id); +} + +void TExecutor::DropSingleCache(const TLogoBlobID &label) noexcept +{ auto toActivate = PrivatePageCache->ForgetPageCollection(label); - ActivateWaitingTransactions(toActivate); + ActivateWaitingTransactions(toActivate); if (!PrivatePageCache->Info(label)) Send(MakeSharedPageCacheId(), new NSharedCache::TEvInvalidate(label)); - + Counters->Simple()[TExecutorCounters::CACHE_PINNED_SET] = PrivatePageCache->GetStats().PinnedSetSize; Counters->Simple()[TExecutorCounters::CACHE_PINNED_LOAD] = PrivatePageCache->GetStats().PinnedLoadSize; -} - +} + void TExecutor::TranslateCacheTouchesToSharedCache() { auto touches = PrivatePageCache->GetPrepareSharedTouched(); if (touches.empty()) return; Send(MakeSharedPageCacheId(), new NSharedCache::TEvTouch(std::move(touches))); } - + void TExecutor::RequestInMemPagesForDatabase() { const auto &scheme = Scheme(); for (auto &sxpair : scheme.Tables) { // should be over page collection cache with already set inmem flags? - if (scheme.CachePolicy(sxpair.first) == NTable::NPage::ECache::Ever) { + if (scheme.CachePolicy(sxpair.first) == NTable::NPage::ECache::Ever) { auto subset = Database->Subset(sxpair.first, NTable::TEpoch::Max(), { } , { }); for (auto &partView: subset->Flatten) @@ -605,10 +605,10 @@ TExecutorCaches TExecutor::CleanupState() { PostponedFollowerUpdates.clear(); PendingPartSwitches.clear(); ReadyPartSwitches = 0; - Y_VERIFY(!LogicRedo); + Y_VERIFY(!LogicRedo); Database.Destroy(); Y_VERIFY(!GcLogic); - Y_VERIFY(!LogicAlter); + Y_VERIFY(!LogicAlter); Y_VERIFY(!CompactionLogic); BorrowLogic.Destroy(); @@ -631,13 +631,13 @@ void TExecutor::Boot(TEvTablet::TEvBoot::TPtr &ev, const TActorContext &ctx) { Generation0 = msg->Generation; Step0 = 0; Launcher = msg->Launcher; - Memory->SetProfiles(msg->ResourceProfiles); + Memory->SetProfiles(msg->ResourceProfiles); const ui64 maxBootBytesInFly = 12 * 1024 * 1024; auto executorCaches = CleanupState(); - BootLogic.Reset(new TExecutorBootLogic(this, SelfId(), Owner->Info(), maxBootBytesInFly)); + BootLogic.Reset(new TExecutorBootLogic(this, SelfId(), Owner->Info(), maxBootBytesInFly)); ui64 totalBytes = 0; for (auto& kv : msg->GroupReadBytes) { @@ -673,14 +673,14 @@ void TExecutor::FollowerBoot(TEvTablet::TEvFBoot::TPtr &ev, const TActorContext Generation0 = msg->Generation; Step0 = 0; Launcher = msg->Launcher; - Memory->SetProfiles(msg->ResourceProfiles); + Memory->SetProfiles(msg->ResourceProfiles); FollowerId = msg->FollowerID; const ui64 maxBootBytesInFly = 12 * 1024 * 1024; auto executorCaches = CleanupState(); - BootLogic.Reset(new TExecutorBootLogic(this, SelfId(), Owner->Info(), maxBootBytesInFly)); + BootLogic.Reset(new TExecutorBootLogic(this, SelfId(), Owner->Info(), maxBootBytesInFly)); const auto res = BootLogic->ReceiveFollowerBoot(ev, std::move(executorCaches)); return TranscriptFollowerBootOpResult(res, ctx); } @@ -691,14 +691,14 @@ void TExecutor::Restored(TEvTablet::TEvRestored::TPtr &ev, const TActorContext & TEvTablet::TEvRestored *msg = ev->Get(); Y_VERIFY(Generation() == msg->Generation); - const TExecutorBootLogic::EOpResult res = BootLogic->ReceiveRestored(ev); + const TExecutorBootLogic::EOpResult res = BootLogic->ReceiveRestored(ev); return TranscriptBootOpResult(res, ctx); } void TExecutor::DetachTablet(const TActorContext &) { TabletCountersForgetTablet(Owner->TabletID(), Owner->TabletType(), Owner->Info()->TenantPathId, Stats->IsFollower, SelfId()); - return PassAway(); + return PassAway(); } void TExecutor::FollowerUpdate(THolder<TEvTablet::TFUpdateBody> upd) { @@ -736,7 +736,7 @@ void TExecutor::FollowerAttached() { if (CurrentStateFunc() != &TThis::StateWork) return; - MakeLogSnapshot(); + MakeLogSnapshot(); } void TExecutor::FollowerSyncComplete() { @@ -753,7 +753,7 @@ void TExecutor::FollowerGcApplied(ui32 step, TDuration followerSyncDelay) { if (auto logl = Logger->Log(ELnLev::Debug)) { logl << NFmt::Do(*this) << " switch applied on followers, step " << step; } - + auto it = InFlyCompactionGcBarriers.find(step); Y_VERIFY(it != InFlyCompactionGcBarriers.end()); CheckCollectionBarrier(it->second); @@ -763,9 +763,9 @@ void TExecutor::FollowerGcApplied(ui32 step, TDuration followerSyncDelay) { Counters->Percentile()[TExecutorCounters::TX_PERCENTILE_FOLLOWERSYNC_LATENCY].IncrementFor(followerSyncDelay.MicroSeconds()); } -void TExecutor::CheckCollectionBarrier(TIntrusivePtr<TBarrier> &barrier) { +void TExecutor::CheckCollectionBarrier(TIntrusivePtr<TBarrier> &barrier) { if (barrier && barrier->RefCount() == 1) { - GcLogic->ReleaseBarrier(barrier->Step); + GcLogic->ReleaseBarrier(barrier->Step); if (BorrowLogic->SetGcBarrier(GcLogic->GetActiveGcBarrier())) { // N.B. PassAway may have already been called if (Owner) { @@ -792,13 +792,13 @@ void TExecutor::ApplyFollowerPostponedUpdates() { void TExecutor::ApplyFollowerUpdate(THolder<TEvTablet::TFUpdateBody> update) { if (update->Step <= Step0 || CommitManager) { - Y_Fail( + Y_Fail( NFmt::Do(*this) << " got unexpected follower update to Step " << update->Step << ", " << NFmt::If(CommitManager.Get())); - } - - Step0 = update->Step; - + } + + Step0 = update->Step; + if (update->IsSnapshot) // do nothing over snapshot after initial one return; @@ -816,37 +816,37 @@ void TExecutor::ApplyFollowerUpdate(THolder<TEvTablet::TFUpdateBody> update) { const TLogoBlobID &id = xpair.first; const TString &body = xpair.second; - const NBoot::TCookie cookie(id.Cookie()); - Y_VERIFY(cookie.Type() == NBoot::TCookie::EType::Log); - + const NBoot::TCookie cookie(id.Cookie()); + Y_VERIFY(cookie.Type() == NBoot::TCookie::EType::Log); + if (NBoot::TCookie::CookieRangeRaw().Has(cookie.Raw)) { - auto group = Owner->Info()->GroupFor(id.Channel(), id.Generation()); - + auto group = Owner->Info()->GroupFor(id.Channel(), id.Generation()); + annex.emplace_back(NPageCollection::TGlobId{ id, group }, TSharedData::Copy(body)); - - continue; - } - + + continue; + } + switch (cookie.Index()) { - case NBoot::TCookie::EIdx::RedoLz4: + case NBoot::TCookie::EIdx::RedoLz4: if (dataUpdate) dataUpdate.append(body); else dataUpdate = body; break; - case NBoot::TCookie::EIdx::Alter: + case NBoot::TCookie::EIdx::Alter: if (schemeUpdate) schemeUpdate.append(body); else schemeUpdate = body; break; - case NBoot::TCookie::EIdx::TurnLz4: + case NBoot::TCookie::EIdx::TurnLz4: partSwitches.push_back(body); break; - case NBoot::TCookie::EIdx::Loan: + case NBoot::TCookie::EIdx::Loan: loanPartInfos.push_back(TLogoBlob(id, body)); break; - case NBoot::TCookie::EIdx::GCExt: + case NBoot::TCookie::EIdx::GCExt: // ignore break; default: @@ -855,11 +855,11 @@ void TExecutor::ApplyFollowerUpdate(THolder<TEvTablet::TFUpdateBody> update) { } } - if (schemeUpdate || dataUpdate || annex) { - if (dataUpdate) + if (schemeUpdate || dataUpdate || annex) { + if (dataUpdate) dataUpdate = NPageCollection::TSlicer::Lz4()->Decode(dataUpdate); - - for (auto &subset : Database->RollUp(Stamp(), schemeUpdate, dataUpdate, annex)) + + for (auto &subset : Database->RollUp(Stamp(), schemeUpdate, dataUpdate, annex)) for (auto &partView: subset->Flatten) DropCachesOfBundle(*partView); @@ -872,7 +872,7 @@ void TExecutor::ApplyFollowerUpdate(THolder<TEvTablet::TFUpdateBody> update) { for (const TLogoBlob &loanQu : loanPartInfos) { const TString uncompressed = NPageCollection::TSlicer::Lz4()->Decode(loanQu.Buffer); - TProtoBox<NKikimrExecutorFlat::TBorrowedPart> proto(uncompressed); + TProtoBox<NKikimrExecutorFlat::TBorrowedPart> proto(uncompressed); // for now follower borrowed info is not cleared. // it's not problem as by design we expect limited number of loans @@ -939,12 +939,12 @@ void TExecutor::ApplyFollowerAuxUpdate(const TString &auxBody) { continue; TVector<NTable::TPageId> pages; - + for (ui32 pageId : x.GetTouchedPages()) { auto* page = collectionInfo->EnsurePage(pageId); switch (page->LoadState) { case TPrivatePageCache::TPage::LoadStateNo: - pages.push_back(pageId); + pages.push_back(pageId); page->LoadState = TPrivatePageCache::TPage::LoadStateRequestedAsync; break; case TPrivatePageCache::TPage::LoadStateRequested: @@ -958,15 +958,15 @@ void TExecutor::ApplyFollowerAuxUpdate(const TString &auxBody) { } } - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl << NFmt::Do(*this) << " refresh pageCollection " << metaId << " " << pages.size() << " pages of " << x.TouchedPagesSize(); - } + } - if (pages) { + if (pages) { auto *req = new NPageCollection::TFetch(0, collectionInfo->PageCollection, std::move(pages)); - + RequestFromSharedCache(req, NBlockIO::EPriority::Bkgr, EPageCollectionRequest::CacheSync); } } @@ -979,11 +979,11 @@ void TExecutor::RequestFromSharedCache(TAutoPtr<NPageCollection::TFetch> fetch, NBlockIO::EPriority priority, EPageCollectionRequest requestCategory) { - Y_VERIFY(fetch->Pages.size() > 0, "Got TFetch req w/o any page"); - + Y_VERIFY(fetch->Pages.size() > 0, "Got TFetch req w/o any page"); + Send(MakeSharedPageCacheId(), new NSharedCache::TEvRequest( priority, - fetch, + fetch, SelfId()), 0, (ui64)requestCategory); } @@ -997,15 +997,15 @@ void TExecutor::AddFollowerPartSwitch( partSwitch.FollowerUpdateStep = updateStep; partSwitch.TableId = switchProto.GetTableId(); partSwitch.Step = step; - + if (switchProto.HasIntroducedParts() && switchProto.GetIntroducedParts().BundlesSize()) { Y_VERIFY(aux && aux->HotBundlesSize() == switchProto.GetIntroducedParts().BundlesSize()); for (auto x : xrange(aux->HotBundlesSize())) { NTable::TPartComponents c = TPageCollectionProtoHelper::MakePageCollectionComponents(aux->GetHotBundles(x)); PrepareExternalPart(partSwitch, std::move(c)); } - } - + } + if (switchProto.HasIntroducedTxStatus()) { Y_VERIFY(aux && aux->HotTxStatusSize() == switchProto.GetIntroducedTxStatus().TxStatusSize()); for (const auto &x : aux->GetHotTxStatus()) { @@ -1016,15 +1016,15 @@ void TExecutor::AddFollowerPartSwitch( } } - if (switchProto.HasTableSnapshoted()) + if (switchProto.HasTableSnapshoted()) partSwitch.Head = NTable::TEpoch(switchProto.GetTableSnapshoted().GetHead()); - + partSwitch.Changed.reserve(switchProto.ChangedBundlesSize()); for (auto &x : switchProto.GetChangedBundles()) { auto &change = partSwitch.Changed.emplace_back(); change.Label = LogoBlobIDFromLogoBlobID(x.GetLabel()); - if (x.HasLegacy()) - change.Legacy = x.GetLegacy(); + if (x.HasLegacy()) + change.Legacy = x.GetLegacy(); if (x.HasOpaque()) change.Opaque = x.GetOpaque(); } @@ -1038,7 +1038,7 @@ void TExecutor::AddFollowerPartSwitch( } } - for (auto &x : switchProto.GetLeavingBundles()) + for (auto &x : switchProto.GetLeavingBundles()) partSwitch.Leaving.push_back(LogoBlobIDFromLogoBlobID(x)); for (auto &x : switchProto.GetLeavingTxStatus()) @@ -1056,7 +1056,7 @@ void TExecutor::AddFollowerPartSwitch( } } } - + bool TExecutor::PrepareExternalPart(TPendingPartSwitch &partSwitch, NTable::TPartComponents &&pc) { Y_VERIFY(pc); @@ -1122,12 +1122,12 @@ bool TExecutor::PrepareExternalPart(TPendingPartSwitch &partSwitch, TPendingPart auto partView = stage->Loader.Result(); bundle.Stage.emplace<TPendingPartSwitch::TResultStage>(std::move(partView)); - return false; - } + return false; + } Y_FAIL("Unexpected PrepareExternalPart called"); } - + bool TExecutor::PrepareExternalTxStatus( TPendingPartSwitch &partSwitch, const NPageCollection::TLargeGlobId &dataId, @@ -1215,7 +1215,7 @@ void TExecutor::Handle(TEvBlobStorage::TEvGetResult::TPtr& ev, const TActorConte } } -void TExecutor::AdvancePendingPartSwitches() { +void TExecutor::AdvancePendingPartSwitches() { while (PendingPartSwitches && ApplyReadyPartSwitches()) { if (Stats->IsFollower) { ApplyFollowerPostponedUpdates(); @@ -1253,9 +1253,9 @@ bool TExecutor::ApplyReadyPartSwitches() { void TExecutor::RequestInMemPagesForPartStore(ui32 tableId, const NTable::TPartView &partView) { if (Scheme().CachePolicy(tableId) == NTable::NPage::ECache::Ever) { auto req = partView.As<NTable::TPartStore>()->DataPages(); - + TPrivatePageCache::TInfo *info = PrivatePageCache->Info(req->PageCollection->Label()); - for (ui32 pageId : req->Pages) + for (ui32 pageId : req->Pages) PrivatePageCache->MarkSticky(pageId, info); RequestFromSharedCache(req, NBlockIO::EPriority::Bkgr, EPageCollectionRequest::CacheSync); @@ -1271,7 +1271,7 @@ void TExecutor::ApplyExternalPartSwitch(TPendingPartSwitch &partSwitch) { AddCachesOfBundle(stage->PartView); RequestInMemPagesForPartStore(partSwitch.TableId, stage->PartView); newParts.push_back(std::move(stage->PartView)); - } + } TVector<TIntrusiveConstPtr<NTable::TColdPart>> newColdParts = std::move(partSwitch.NewColdParts); @@ -1286,7 +1286,7 @@ void TExecutor::ApplyExternalPartSwitch(TPendingPartSwitch &partSwitch) { if (partSwitch.Changed) { NTable::TBundleSlicesMap updatedBundles; for (auto &change : partSwitch.Changed) { - auto overlay = NTable::TOverlay::Decode(change.Legacy, change.Opaque); + auto overlay = NTable::TOverlay::Decode(change.Legacy, change.Opaque); Y_VERIFY(overlay.Slices && *overlay.Slices, "Change for bundle %s has unexpected empty slices", change.Label.ToString().data()); @@ -1325,9 +1325,9 @@ void TExecutor::ApplyExternalPartSwitch(TPendingPartSwitch &partSwitch) { Y_VERIFY(newColdParts.empty(), "Unexpected cold part at a follower"); Database->Replace(partSwitch.TableId, std::move(newParts), *subset); Database->ReplaceTxStatus(partSwitch.TableId, std::move(newTxStatus), *subset); - - for (auto &gone : subset->Flatten) - DropCachesOfBundle(*gone); + + for (auto &gone : subset->Flatten) + DropCachesOfBundle(*gone); Send(Owner->Tablet(), new TEvTablet::TEvFGcAck(Owner->TabletID(), Generation(), partSwitch.FollowerUpdateStep)); } else { @@ -1403,81 +1403,81 @@ void TExecutor::Execute(TAutoPtr<ITransaction> self, const TActorContext &ctx) { Y_VERIFY(ActivationQueue, "attempt to execute transaction before activation"); TAutoPtr<TSeat> seat = new TSeat(++TransactionUniqCounter, self); - + LWTRACK(TransactionBegin, seat->Self->Orbit, seat->UniqID, Owner->TabletID(), TypeName(*seat->Self)); ++Stats->TxInFly; Counters->Simple()[TExecutorCounters::DB_TX_IN_FLY] = Stats->TxInFly; - Counters->Cumulative()[TExecutorCounters::TX_COUNT_ALL].Increment(1); //Deprecated - Counters->Cumulative()[TExecutorCounters::TX_QUEUED].Increment(1); + Counters->Cumulative()[TExecutorCounters::TX_COUNT_ALL].Increment(1); //Deprecated + Counters->Cumulative()[TExecutorCounters::TX_QUEUED].Increment(1); - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*this) << " " << NFmt::Do(*seat) - << " queued, type " << NFmt::Do(*seat->Self); - } + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*this) << " " << NFmt::Do(*seat) + << " queued, type " << NFmt::Do(*seat->Self); + } - ui64 staticRemain = Memory->RemainedStatic(*seat); + ui64 staticRemain = Memory->RemainedStatic(*seat); // Submit resource broker task if there is no enough memory to start // new transaction. - seat->CurrentTxDataLimit = Memory->Profile->GetInitialTxMemory(); - if (staticRemain < seat->CurrentTxDataLimit) { + seat->CurrentTxDataLimit = Memory->Profile->GetInitialTxMemory(); + if (staticRemain < seat->CurrentTxDataLimit) { LWTRACK(TransactionNeedMemory, seat->Self->Orbit, seat->UniqID); - Memory->RequestLimit(*seat, seat->CurrentTxDataLimit); - auto *transptr = seat.Release(); + Memory->RequestLimit(*seat, seat->CurrentTxDataLimit); + auto *transptr = seat.Release(); auto pairIt = PostponedTransactions.emplace(transptr, transptr); Y_VERIFY(pairIt.second); return; } - Memory->AllocStatic(*seat, Memory->Profile->GetInitialTxMemory()); + Memory->AllocStatic(*seat, Memory->Profile->GetInitialTxMemory()); if (!CanExecuteTransaction() || Scheme().Executor.LimitInFlyTx && Stats->TxInFly > Scheme().Executor.LimitInFlyTx) { LWTRACK(TransactionPending, seat->Self->Orbit, seat->UniqID, CanExecuteTransaction() ? "tx limit reached" : "transactions paused"); - PendingQueue->Push(seat.Release()); + PendingQueue->Push(seat.Release()); ++Stats->TxPending; return; } if (ActiveTransaction || ActivateTransactionWaiting) { LWTRACK(TransactionEnqueued, seat->Self->Orbit, seat->UniqID); - ActivationQueue->Push(seat.Release()); + ActivationQueue->Push(seat.Release()); ActivateTransactionWaiting++; - PlanTransactionActivation(); + PlanTransactionActivation(); return; } - ExecuteTransaction(seat, ctx); + ExecuteTransaction(seat, ctx); } void TExecutor::ExecuteTransaction(TAutoPtr<TSeat> seat, const TActorContext &ctx) { Y_VERIFY_DEBUG(!ActiveTransaction); ActiveTransaction = true; - ++seat->Retries; + ++seat->Retries; THPTimer cpuTimer; - + TPageCollectionTxEnv env(*PrivatePageCache); - + TTransactionContext txc(Owner->TabletID(), Generation(), Step(), *Database, env, seat->CurrentTxDataLimit, seat->TaskId); txc.NotEnoughMemory(seat->NotEnoughMemoryCount); - + Database->Begin(Stamp(), env); LWTRACK(TransactionExecuteBegin, seat->Self->Orbit, seat->UniqID); const bool done = seat->Self->Execute(txc, ctx.MakeFor(OwnerActorId)); LWTRACK(TransactionExecuteEnd, seat->Self->Orbit, seat->UniqID, done); - seat->CPUExecTime += cpuTimer.PassedReset(); + seat->CPUExecTime += cpuTimer.PassedReset(); if (done && !Stats->IsFollower) { /* possible rw commit */ for (auto one: env.MakeSnap) - Database->TxSnapTable(one.first /* table */); - } + Database->TxSnapTable(one.first /* table */); + } bool failed = false; TString failureReason; @@ -1491,36 +1491,36 @@ void TExecutor::ExecuteTransaction(TAutoPtr<TSeat> seat, const TActorContext &ct auto *annex = CommitManager ? CommitManager->Annex.Get() : nullptr; auto prod = Database->Commit(Stamp(), done && !failed, annex); - - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*this) << " " << NFmt::Do(*seat) - << " hope " << seat->Retries << " ->" + + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*this) << " " << NFmt::Do(*seat) + << " hope " << seat->Retries << " ->" << " " << (failed ? "failed" : done ? "done" : "retry") - << " " << NFmt::If(prod.Change.Get()); - } - - seat->AttachedMemory = txc.ExtractMemoryToken(); - seat->RequestedMemory = txc.GetRequestedMemory(); - seat->CapturedMemory = txc.GetMemoryGCToken(); + << " " << NFmt::If(prod.Change.Get()); + } + + seat->AttachedMemory = txc.ExtractMemoryToken(); + seat->RequestedMemory = txc.GetRequestedMemory(); + seat->CapturedMemory = txc.GetMemoryGCToken(); seat->NotEnoughMemoryCount = txc.GetNotEnoughMemoryCount(); if (seat->AttachedMemory) - Counters->Cumulative()[TExecutorCounters::TX_MEM_ATTACHES].Increment(1); + Counters->Cumulative()[TExecutorCounters::TX_MEM_ATTACHES].Increment(1); if (seat->RequestedMemory) - Counters->Cumulative()[TExecutorCounters::TX_MEM_REQUESTS].Increment(1); + Counters->Cumulative()[TExecutorCounters::TX_MEM_REQUESTS].Increment(1); if (seat->CapturedMemory) { - Counters->Cumulative()[TExecutorCounters::TX_MEM_CAPTURES].Increment(1); - Memory->ScheduleGC(); + Counters->Cumulative()[TExecutorCounters::TX_MEM_CAPTURES].Increment(1); + Memory->ScheduleGC(); } - const auto& txStats = prod.Change->Stats; - Counters->Cumulative()[TExecutorCounters::TX_CHARGE_WEEDED].Increment(txStats.ChargeWeeded); - Counters->Cumulative()[TExecutorCounters::TX_CHARGE_SIEVED].Increment(txStats.ChargeSieved); - Counters->Cumulative()[TExecutorCounters::TX_SELECT_WEEDED].Increment(txStats.SelectWeeded); - Counters->Cumulative()[TExecutorCounters::TX_SELECT_SIEVED].Increment(txStats.SelectSieved); - Counters->Cumulative()[TExecutorCounters::TX_SELECT_NO_KEY].Increment(txStats.SelectNoKey); - + const auto& txStats = prod.Change->Stats; + Counters->Cumulative()[TExecutorCounters::TX_CHARGE_WEEDED].Increment(txStats.ChargeWeeded); + Counters->Cumulative()[TExecutorCounters::TX_CHARGE_SIEVED].Increment(txStats.ChargeSieved); + Counters->Cumulative()[TExecutorCounters::TX_SELECT_WEEDED].Increment(txStats.SelectWeeded); + Counters->Cumulative()[TExecutorCounters::TX_SELECT_SIEVED].Increment(txStats.SelectSieved); + Counters->Cumulative()[TExecutorCounters::TX_SELECT_NO_KEY].Increment(txStats.SelectNoKey); + if (failed) { // Block new transactions from executing BrokenTransaction = true; @@ -1528,7 +1528,7 @@ void TExecutor::ExecuteTransaction(TAutoPtr<TSeat> seat, const TActorContext &ct // It may not be safe to call Broken right now, call it later Send(SelfId(), new TEvPrivate::TEvBrokenTransaction()); } else if (done) { - Y_VERIFY(!seat->RequestedMemory); + Y_VERIFY(!seat->RequestedMemory); seat->OnCommitted = std::move(txc.OnCommitted_); CommitTransactionLog(seat, env, prod.Change, cpuTimer, ctx); } else { @@ -1537,11 +1537,11 @@ void TExecutor::ExecuteTransaction(TAutoPtr<TSeat> seat, const TActorContext &ct } ActiveTransaction = false; - PlanTransactionActivation(); + PlanTransactionActivation(); } -void TExecutor::UnpinTransactionPages(TSeat &seat) { - for (auto &xinfoid : seat.Pinned) { +void TExecutor::UnpinTransactionPages(TSeat &seat) { + for (auto &xinfoid : seat.Pinned) { if (TPrivatePageCache::TInfo *info = PrivatePageCache->Info(xinfoid.first)) { for (auto &x : xinfoid.second) { ui32 pageId = x.first; @@ -1551,121 +1551,121 @@ void TExecutor::UnpinTransactionPages(TSeat &seat) { } } } - seat.Pinned.clear(); - seat.MemoryTouched = 0; + seat.Pinned.clear(); + seat.MemoryTouched = 0; Counters->Simple()[TExecutorCounters::CACHE_PINNED_SET] = PrivatePageCache->GetStats().PinnedSetSize; Counters->Simple()[TExecutorCounters::CACHE_PINNED_LOAD] = PrivatePageCache->GetStats().PinnedLoadSize; } -void TExecutor::ReleaseTxData(TSeat &seat, ui64 requested, const TActorContext &ctx) -{ - if (auto logl = Logger->Log(ELnLev::Debug)) - logl << NFmt::Do(*this) << " " << NFmt::Do(seat) << " release tx data"; - - TTxMemoryProvider provider(seat.CurrentTxDataLimit - requested, seat.TaskId); +void TExecutor::ReleaseTxData(TSeat &seat, ui64 requested, const TActorContext &ctx) +{ + if (auto logl = Logger->Log(ELnLev::Debug)) + logl << NFmt::Do(*this) << " " << NFmt::Do(seat) << " release tx data"; + + TTxMemoryProvider provider(seat.CurrentTxDataLimit - requested, seat.TaskId); static_cast<TTxMemoryProviderBase&>(provider).RequestMemory(requested); seat.Self->ReleaseTxData(provider, ctx.MakeFor(OwnerActorId)); - Counters->Cumulative()[TExecutorCounters::TX_DATA_RELEASES].Increment(1); + Counters->Cumulative()[TExecutorCounters::TX_DATA_RELEASES].Increment(1); - if (seat.CapturedMemory = provider.GetMemoryGCToken()) - Counters->Cumulative()[TExecutorCounters::TX_MEM_CAPTURES].Increment(1); + if (seat.CapturedMemory = provider.GetMemoryGCToken()) + Counters->Cumulative()[TExecutorCounters::TX_MEM_CAPTURES].Increment(1); - Memory->ReleaseTxData(seat); + Memory->ReleaseTxData(seat); } void TExecutor::PostponeTransaction(TAutoPtr<TSeat> seat, TPageCollectionTxEnv &env, TAutoPtr<NTable::TChange> change, THPTimer &bookkeepingTimer, const TActorContext &ctx) { - if (!env.ToLoad && !seat->RequestedMemory) { - Y_Fail(NFmt::Do(*this) << " " << NFmt::Do(*seat) << " type " - << NFmt::Do(*seat->Self) << " postoned w/o demands"); + if (!env.ToLoad && !seat->RequestedMemory) { + Y_Fail(NFmt::Do(*this) << " " << NFmt::Do(*seat) << " type " + << NFmt::Do(*seat->Self) << " postoned w/o demands"); } - TTxType txType = seat->Self->GetTxType(); + TTxType txType = seat->Self->GetTxType(); - ui32 touchedPages = 0; - ui32 touchedBytes = 0; - ui32 newPinnedPages = 0; - ui32 waitPages = 0; - ui32 loadPages = 0; - ui64 loadBytes = 0; - ui64 prevTouched = seat->MemoryTouched; + ui32 touchedPages = 0; + ui32 touchedBytes = 0; + ui32 newPinnedPages = 0; + ui32 waitPages = 0; + ui32 loadPages = 0; + ui64 loadBytes = 0; + ui64 prevTouched = seat->MemoryTouched; // must pin new entries - for (auto &xpair : env.Touches) { + for (auto &xpair : env.Touches) { TPrivatePageCache::TInfo *pageCollectionInfo = xpair.first; auto &pinned = seat->Pinned[pageCollectionInfo->Id]; for (auto &x : xpair.second) { // would insert only if first seen if (pinned.insert(std::make_pair(x, PrivatePageCache->Pin(x, pageCollectionInfo))).second) { - ++newPinnedPages; + ++newPinnedPages; seat->MemoryTouched += pageCollectionInfo->GetPage(x)->Size; } } touchedPages += xpair.second.size(); } - touchedBytes = seat->MemoryTouched - prevTouched; - prevTouched = seat->MemoryTouched; + touchedBytes = seat->MemoryTouched - prevTouched; + prevTouched = seat->MemoryTouched; - for (auto &xpair : env.ToLoad) { + for (auto &xpair : env.ToLoad) { TPrivatePageCache::TInfo *pageCollectionInfo = xpair.first; auto &pinned = seat->Pinned[pageCollectionInfo->Id]; for (auto &x : xpair.second) { if (pinned.insert(std::make_pair(x, PrivatePageCache->Pin(x, pageCollectionInfo))).second) { - ++newPinnedPages; + ++newPinnedPages; seat->MemoryTouched += pageCollectionInfo->GetPage(x)->Size; } } } - if (seat->AttachedMemory) - Memory->AttachMemory(*seat); + if (seat->AttachedMemory) + Memory->AttachMemory(*seat); - const ui64 requestedMemory = std::exchange(seat->RequestedMemory, 0); - seat->CurrentTxDataLimit += requestedMemory; + const ui64 requestedMemory = std::exchange(seat->RequestedMemory, 0); + seat->CurrentTxDataLimit += requestedMemory; - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*this) << " " << NFmt::Do(*seat) - << " touch new " << touchedBytes << "b" - << ", " << (seat->MemoryTouched - prevTouched) << "b lo load" - << " (" << seat->MemoryTouched << "b in total)" - << ", " << requestedMemory << "b requested for data" - << " (" << seat->CurrentTxDataLimit << "b in total)"; - } + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*this) << " " << NFmt::Do(*seat) + << " touch new " << touchedBytes << "b" + << ", " << (seat->MemoryTouched - prevTouched) << "b lo load" + << " (" << seat->MemoryTouched << "b in total)" + << ", " << requestedMemory << "b requested for data" + << " (" << seat->CurrentTxDataLimit << "b in total)"; + } // Check if additional resources should be requested. - ui64 totalMemory = seat->MemoryTouched + seat->CurrentTxDataLimit; - auto limit = Memory->Profile->GetTxMemoryLimit(); + ui64 totalMemory = seat->MemoryTouched + seat->CurrentTxDataLimit; + auto limit = Memory->Profile->GetTxMemoryLimit(); if (limit && totalMemory > limit) { - if (auto logl = Logger->Log(ELnLev::Error)) { - logl - << NFmt::Do(*this) << " " << NFmt::Do(*seat) - << " mem " << totalMemory << "b terminated" - << ", limit " << limit << "b is exceeded"; - } - - seat->TerminationReason = ETerminationReason::MemoryLimitExceeded; - CommitTransactionLog(seat, env, change, bookkeepingTimer, ctx); + if (auto logl = Logger->Log(ELnLev::Error)) { + logl + << NFmt::Do(*this) << " " << NFmt::Do(*seat) + << " mem " << totalMemory << "b terminated" + << ", limit " << limit << "b is exceeded"; + } + + seat->TerminationReason = ETerminationReason::MemoryLimitExceeded; + CommitTransactionLog(seat, env, change, bookkeepingTimer, ctx); return; - } else if (totalMemory > seat->CurrentMemoryLimit) { + } else if (totalMemory > seat->CurrentMemoryLimit) { // We usually try to at least double allocated memory. But it's OK to use less // to avoid resource broker request. - ui64 desired = Max(totalMemory, seat->CurrentMemoryLimit * 2); + ui64 desired = Max(totalMemory, seat->CurrentMemoryLimit * 2); bool allocated = false; // Try to allocate static memory. - if (!seat->TaskId) { - ui64 staticRemain = Memory->RemainedStatic(*seat); - if (staticRemain >= totalMemory - seat->CurrentMemoryLimit) { - ui64 limit = Min(staticRemain + seat->CurrentMemoryLimit, desired); - Memory->AllocStatic(*seat, limit); + if (!seat->TaskId) { + ui64 staticRemain = Memory->RemainedStatic(*seat); + if (staticRemain >= totalMemory - seat->CurrentMemoryLimit) { + ui64 limit = Min(staticRemain + seat->CurrentMemoryLimit, desired); + Memory->AllocStatic(*seat, limit); allocated = true; } } @@ -1673,13 +1673,13 @@ void TExecutor::PostponeTransaction(TAutoPtr<TSeat> seat, TPageCollectionTxEnv & // Submit or resubmit task with new resource requirements. if (!allocated) { LWTRACK(TransactionNeedMemory, seat->Self->Orbit, seat->UniqID); - Memory->FreeStatic(*seat, 0); - UnpinTransactionPages(*seat); - ReleaseTxData(*seat, requestedMemory, ctx); - - Memory->RequestLimit(*seat, desired); + Memory->FreeStatic(*seat, 0); + UnpinTransactionPages(*seat); + ReleaseTxData(*seat, requestedMemory, ctx); - auto *transptr = seat.Release(); + Memory->RequestLimit(*seat, desired); + + auto *transptr = seat.Release(); auto pairIt = PostponedTransactions.emplace(transptr, transptr); Y_VERIFY(pairIt.second); @@ -1690,11 +1690,11 @@ void TExecutor::PostponeTransaction(TAutoPtr<TSeat> seat, TPageCollectionTxEnv & // If memory was allocated and there is nothing to load // then tx may be re-activated. - if (!env.ToLoad) { + if (!env.ToLoad) { LWTRACK(TransactionEnqueued, seat->Self->Orbit, seat->UniqID); - ActivationQueue->Push(seat.Release()); + ActivationQueue->Push(seat.Release()); ActivateTransactionWaiting++; - PlanTransactionActivation(); + PlanTransactionActivation(); return; } @@ -1703,51 +1703,51 @@ void TExecutor::PostponeTransaction(TAutoPtr<TSeat> seat, TPageCollectionTxEnv & auto *const pad = padHolder.Get(); TransactionWaitPads[pad] = std::move(padHolder); - for (auto &xpair : env.ToLoad) { + for (auto &xpair : env.ToLoad) { TPrivatePageCache::TInfo *pageCollectionInfo = xpair.first; - + TVector<NTable::TPageId> pages; - pages.reserve(xpair.second.size()); - - waitPages += xpair.second.size(); + pages.reserve(xpair.second.size()); + + waitPages += xpair.second.size(); for (auto &x : xpair.second) { - pages.push_back(x); + pages.push_back(x); } const std::pair<ui32, ui64> toLoad = PrivatePageCache->Load(pages, pad, pageCollectionInfo); if (toLoad.first) { auto *req = new NPageCollection::TFetch(0, pageCollectionInfo->PageCollection, std::move(pages)); - - loadPages += toLoad.first; - loadBytes += toLoad.second; + + loadPages += toLoad.first; + loadBytes += toLoad.second; RequestFromSharedCache(req, NBlockIO::EPriority::Fast, EPageCollectionRequest::Cache); } } - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*this) << " " << NFmt::Do(*pad->Seat) << " postponed" - << ", " << loadBytes << "b, pages " - << "{" << waitPages << " wait, " << loadPages << " load}" - << ", freshly touched " << newPinnedPages << " pages"; - } + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*this) << " " << NFmt::Do(*pad->Seat) << " postponed" + << ", " << loadBytes << "b, pages " + << "{" << waitPages << " wait, " << loadPages << " load}" + << ", freshly touched " << newPinnedPages << " pages"; + } - pad->Seat->CPUBookkeepingTime += bookkeepingTimer.PassedReset(); + pad->Seat->CPUBookkeepingTime += bookkeepingTimer.PassedReset(); Counters->Cumulative()[TExecutorCounters::TX_POSTPONED].Increment(1); - - if (AppTxCounters && txType != UnknownTxType) - AppTxCounters->TxCumulative(txType, COUNTER_TT_POSTPONED).Increment(1); - - if (pad->Seat->Retries == 1) { - Counters->Cumulative()[TExecutorCounters::TX_RETRIED].Increment(1); - Counters->Cumulative()[TExecutorCounters::TX_CACHE_HITS].Increment(touchedPages); - } - - Counters->Cumulative()[TExecutorCounters::TX_BYTES_READ].Increment(loadBytes); - Counters->Cumulative()[TExecutorCounters::TX_CACHE_MISSES].Increment(loadPages); + + if (AppTxCounters && txType != UnknownTxType) + AppTxCounters->TxCumulative(txType, COUNTER_TT_POSTPONED).Increment(1); + + if (pad->Seat->Retries == 1) { + Counters->Cumulative()[TExecutorCounters::TX_RETRIED].Increment(1); + Counters->Cumulative()[TExecutorCounters::TX_CACHE_HITS].Increment(touchedPages); + } + + Counters->Cumulative()[TExecutorCounters::TX_BYTES_READ].Increment(loadBytes); + Counters->Cumulative()[TExecutorCounters::TX_CACHE_MISSES].Increment(loadPages); if (AppTxCounters && txType != UnknownTxType) { - AppTxCounters->TxCumulative(txType, COUNTER_TT_LOADED_BLOCKS).Increment(loadPages); - AppTxCounters->TxCumulative(txType, COUNTER_TT_BYTES_READ).Increment(loadBytes); + AppTxCounters->TxCumulative(txType, COUNTER_TT_LOADED_BLOCKS).Increment(loadPages); + AppTxCounters->TxCumulative(txType, COUNTER_TT_BYTES_READ).Increment(loadBytes); } Counters->Simple()[TExecutorCounters::CACHE_PINNED_SET] = PrivatePageCache->GetStats().PinnedSetSize; @@ -1756,12 +1756,12 @@ void TExecutor::PostponeTransaction(TAutoPtr<TSeat> seat, TPageCollectionTxEnv & void TExecutor::CommitTransactionLog(TAutoPtr<TSeat> seat, TPageCollectionTxEnv &env, TAutoPtr<NTable::TChange> change, THPTimer &bookkeepingTimer, const TActorContext &ctx) { - const bool isReadOnly = !(change->HasAny() || env.HasChanges()); - const bool isTerminated = seat->TerminationReason != ETerminationReason::None; - const TTxType txType = seat->Self->GetTxType(); + const bool isReadOnly = !(change->HasAny() || env.HasChanges()); + const bool isTerminated = seat->TerminationReason != ETerminationReason::None; + const TTxType txType = seat->Self->GetTxType(); ui64 touchedBlocks = 0; - for (auto &xpair : env.Touches) { + for (auto &xpair : env.Touches) { TPrivatePageCache::TInfo *pageCollectionInfo = xpair.first; touchedBlocks += xpair.second.size(); for (ui32 blockId : xpair.second) @@ -1771,21 +1771,21 @@ void TExecutor::CommitTransactionLog(TAutoPtr<TSeat> seat, TPageCollectionTxEnv if (AppTxCounters && txType != UnknownTxType) AppTxCounters->TxCumulative(txType, COUNTER_TT_TOUCHED_BLOCKS).Increment(touchedBlocks); - if (seat->Retries == 1) { - Counters->Cumulative()[TExecutorCounters::TX_CACHE_HITS].Increment(touchedBlocks); + if (seat->Retries == 1) { + Counters->Cumulative()[TExecutorCounters::TX_CACHE_HITS].Increment(touchedBlocks); } - UnpinTransactionPages(*seat); - Memory->ReleaseMemory(*seat); + UnpinTransactionPages(*seat); + Memory->ReleaseMemory(*seat); - const double currentBookkeepingTime = seat->CPUBookkeepingTime; - const double currentExecTime = seat->CPUExecTime; + const double currentBookkeepingTime = seat->CPUBookkeepingTime; + const double currentExecTime = seat->CPUExecTime; if (isTerminated) { if (Stats->IsFollower) { --Stats->TxInFly; Counters->Simple()[TExecutorCounters::DB_TX_IN_FLY] = Stats->TxInFly; - seat->Self->Terminate(seat->TerminationReason, OwnerCtx()); + seat->Self->Terminate(seat->TerminationReason, OwnerCtx()); } else if (LogicRedo->TerminateTransaction(seat, ctx, OwnerActorId)) { --Stats->TxInFly; Counters->Simple()[TExecutorCounters::DB_TX_IN_FLY] = Stats->TxInFly; @@ -1795,8 +1795,8 @@ void TExecutor::CommitTransactionLog(TAutoPtr<TSeat> seat, TPageCollectionTxEnv // todo: extract completion counters from txloglogic --Stats->TxInFly; Counters->Simple()[TExecutorCounters::DB_TX_IN_FLY] = Stats->TxInFly; - CompleteRoTransaction(seat, OwnerCtx(), Counters.Get(), AppTxCounters); - } else if (LogicRedo->CommitROTransaction(seat, OwnerCtx())) { + CompleteRoTransaction(seat, OwnerCtx(), Counters.Get(), AppTxCounters); + } else if (LogicRedo->CommitROTransaction(seat, OwnerCtx())) { --Stats->TxInFly; Counters->Simple()[TExecutorCounters::DB_TX_IN_FLY] = Stats->TxInFly; } @@ -1805,48 +1805,48 @@ void TExecutor::CommitTransactionLog(TAutoPtr<TSeat> seat, TPageCollectionTxEnv const bool allowBatching = Scheme().Executor.AllowLogBatching; const bool force = !allowBatching - || change->Scheme + || change->Scheme || change->Annex /* Required for replication to followers */ || change->RemovedRowVersions /* Required for replication to followers */ - || env.MakeSnap - || env.DropSnap - || env.LoanBundle + || env.MakeSnap + || env.DropSnap + || env.LoanBundle || env.LoanTxStatus - || env.LoanConfirmation - || env.BorrowUpdates; - - auto commitResult = LogicRedo->CommitRWTransaction(seat, *change, force); - - Y_VERIFY(!force || commitResult.Commit); - auto *commit = commitResult.Commit.Get(); // could be nullptr + || env.LoanConfirmation + || env.BorrowUpdates; - Y_VERIFY(env.MakeSnap.size() == change->Snapshots.size()); + auto commitResult = LogicRedo->CommitRWTransaction(seat, *change, force); - for (auto seq: xrange(env.MakeSnap.size())) { - const auto &snap = change->Snapshots[seq]; + Y_VERIFY(!force || commitResult.Commit); + auto *commit = commitResult.Commit.Get(); // could be nullptr + Y_VERIFY(env.MakeSnap.size() == change->Snapshots.size()); + + for (auto seq: xrange(env.MakeSnap.size())) { + const auto &snap = change->Snapshots[seq]; + Y_VERIFY(snap.Epoch != NTable::TEpoch::Max(), "Table was not snapshoted"); - - for (auto &context: env.MakeSnap.at(snap.Table).Context) { - auto edge = NTable::TSnapEdge(change->Stamp, snap.Epoch); - - if (!context->Impl) - context->Impl.Reset(new TTableSnapshotContext::TImpl); - - context->Impl->Prepare(snap.Table, edge); - CompactionLogic->PrepareTableSnapshot(snap.Table, edge, context.Get()); - WaitingSnapshots.insert(std::make_pair(context.Get(), context)); - } - } - - if (auto alter = std::move(change->Scheme)) { - LogicAlter->WriteLog(*commit, std::move(alter)); + + for (auto &context: env.MakeSnap.at(snap.Table).Context) { + auto edge = NTable::TSnapEdge(change->Stamp, snap.Epoch); + + if (!context->Impl) + context->Impl.Reset(new TTableSnapshotContext::TImpl); + + context->Impl->Prepare(snap.Table, edge); + CompactionLogic->PrepareTableSnapshot(snap.Table, edge, context.Get()); + WaitingSnapshots.insert(std::make_pair(context.Get(), context)); + } + } + + if (auto alter = std::move(change->Scheme)) { + LogicAlter->WriteLog(*commit, std::move(alter)); PrivatePageCache->UpdateCacheSize(Scheme().Executor.CacheSize); auto reflectResult = CompactionLogic->ReflectSchemeChanges(); ReadResourceProfile(); ReflectSchemeSettings(); - + // For every table that changed strategy we need to generate a // special part switch that notifies bootlogic about new strategy // type and a cleared compaction state. @@ -1866,8 +1866,8 @@ void TExecutor::CommitTransactionLog(TAutoPtr<TSeat> seat, TPageCollectionTxEnv Y_UNUSED(glob); } - } - + } + // Generate a special part switch for removed row versions for (auto& xpair : change->RemovedRowVersions) { const auto tableId = xpair.first; @@ -1896,47 +1896,47 @@ void TExecutor::CommitTransactionLog(TAutoPtr<TSeat> seat, TPageCollectionTxEnv Y_UNUSED(glob); } - for (auto num : xrange(change->Deleted.size())) { - /* Wipe and table deletion happens before any data updates, so - edge should be put before the current redo log step and table - head epoch. Now this code is used only for flushing redo log - to gc, but edge in switch record may turn deletion into table - wipe feature. - */ - + for (auto num : xrange(change->Deleted.size())) { + /* Wipe and table deletion happens before any data updates, so + edge should be put before the current redo log step and table + head epoch. Now this code is used only for flushing redo log + to gc, but edge in switch record may turn deletion into table + wipe feature. + */ + auto head = change->Garbage[num]->Head; if (head > NTable::TEpoch::Zero()) { --head; } else { head = NTable::TEpoch::Zero(); } - + NTable::TSnapEdge edge(change->Stamp - 1, head); - + for (auto& snapshot : Scans->Drop(change->Deleted[num])) { ReleaseScanLocks(std::move(snapshot->Barrier), *snapshot->Subset); } - LogicRedo->CutLog(change->Deleted[num], edge, commit->GcDelta); + LogicRedo->CutLog(change->Deleted[num], edge, commit->GcDelta); } - if (auto garbage = std::move(change->Garbage)) { + if (auto garbage = std::move(change->Garbage)) { commit->WaitFollowerGcAck = true; // as we could collect some page collections - for (auto &subset: garbage) { - ui64 total = 0; - TDeque<NTable::NFwd::TSieve> sieve(subset->Flatten.size() + 1); + for (auto &subset: garbage) { + ui64 total = 0; + TDeque<NTable::NFwd::TSieve> sieve(subset->Flatten.size() + 1); - for (auto seq: xrange(subset->Flatten.size())) { + for (auto seq: xrange(subset->Flatten.size())) { sieve[seq] = { subset->Flatten[seq]->Blobs, subset->Flatten[seq]->Large, subset->Flatten[seq].Slices, { } }; - + total += sieve[seq].Total(); - } - + } + { /* the last sieve corresponds to all TMemTable tables blobs */ sieve.back() = { NTable::TMemTable::MakeBlobsPage(subset->Frozen), @@ -1944,38 +1944,38 @@ void TExecutor::CommitTransactionLog(TAutoPtr<TSeat> seat, TPageCollectionTxEnv nullptr, { } }; - + total += sieve.back().Total(); - } - - UtilizeSubset(*subset, { total, 0, std::move(sieve) }, { }, commit); - } - - TIntrusivePtr<TBarrier> barrier(new TBarrier(commit->Step)); - Y_VERIFY(InFlyCompactionGcBarriers.emplace(commit->Step, barrier).second); + } + + UtilizeSubset(*subset, { total, 0, std::move(sieve) }, { }, commit); + } + + TIntrusivePtr<TBarrier> barrier(new TBarrier(commit->Step)); + Y_VERIFY(InFlyCompactionGcBarriers.emplace(commit->Step, barrier).second); GcLogic->HoldBarrier(barrier->Step); } NKikimrExecutorFlat::TFollowerPartSwitchAux aux; - if (auto *snap = env.DropSnap.Get()) { - auto result = snap->SnapContext->Impl->Release(); - - if (result.Step != commit->Step && result.Bundles) { - /* It is possible to make a valid borrow snapshot only on the - last Execute(..) call of tx having ClearSnapshot(..) before - any desired BorrowSnapshot(..). The other ways are unsafe - due to races with compaction commits which eventually drops - blobs of compacted bundles. - */ - + if (auto *snap = env.DropSnap.Get()) { + auto result = snap->SnapContext->Impl->Release(); + + if (result.Step != commit->Step && result.Bundles) { + /* It is possible to make a valid borrow snapshot only on the + last Execute(..) call of tx having ClearSnapshot(..) before + any desired BorrowSnapshot(..). The other ways are unsafe + due to races with compaction commits which eventually drops + blobs of compacted bundles. + */ + Y_Fail("Dropping snapshot in step " << result.Step << " is" - << " unsafe, final tx Execute() step is " << commit->Step - << ", borrowed " << result.Bundles.size() << " bundles"); - } - - for (auto &bundle: result.Bundles) - BorrowLogic->BorrowBundle(bundle.first, bundle.second, commit); + << " unsafe, final tx Execute() step is " << commit->Step + << ", borrowed " << result.Bundles.size() << " bundles"); + } + + for (auto &bundle: result.Bundles) + BorrowLogic->BorrowBundle(bundle.first, bundle.second, commit); if (result.Moved) { for (const auto& [src, dst] : result.Moved) { @@ -2082,54 +2082,54 @@ void TExecutor::CommitTransactionLog(TAutoPtr<TSeat> seat, TPageCollectionTxEnv } } - InFlySnapCollectionBarriers.emplace(commit->Step, std::move(result.Barriers)); + InFlySnapCollectionBarriers.emplace(commit->Step, std::move(result.Barriers)); } bool hadPendingPartSwitches = bool(PendingPartSwitches); aux.MutableBySwitchAux()->Reserve(aux.BySwitchAuxSize() + env.LoanBundle.size() + env.LoanTxStatus.size()); - for (auto &loaned : env.LoanBundle) { + for (auto &loaned : env.LoanBundle) { auto& partSwitch = PendingPartSwitches.emplace_back(); partSwitch.TableId = loaned->LocalTableId; partSwitch.Step = commit->Step; Y_VERIFY(loaned->PartComponents.PageCollectionComponents, "Loaned PartComponents without any page collections"); - BorrowLogic->LoanBundle( + BorrowLogic->LoanBundle( loaned->PartComponents.PageCollectionComponents.front().LargeGlobId.Lead, *loaned, commit); { NKikimrExecutorFlat::TTablePartSwitch proto; proto.SetTableId(partSwitch.TableId); - - { - TGCBlobDelta dummy; /* this isn't real cut log operation */ - + + { + TGCBlobDelta dummy; /* this isn't real cut log operation */ + auto epoch = Max(loaned->PartComponents.GetEpoch(), NTable::TEpoch::Zero()) + 1; - auto stamp = MakeGenStepPair(Generation(), commit->Step); - - LogicRedo->CutLog(loaned->LocalTableId, { stamp, epoch }, dummy); - - Y_VERIFY(!dummy.Deleted && !dummy.Created); - - auto *sx = proto.MutableTableSnapshoted(); - sx->SetTable(loaned->LocalTableId); - sx->SetGeneration(Generation()); - sx->SetStep(commit->Step); + auto stamp = MakeGenStepPair(Generation(), commit->Step); + + LogicRedo->CutLog(loaned->LocalTableId, { stamp, epoch }, dummy); + + Y_VERIFY(!dummy.Deleted && !dummy.Created); + + auto *sx = proto.MutableTableSnapshoted(); + sx->SetTable(loaned->LocalTableId); + sx->SetGeneration(Generation()); + sx->SetStep(commit->Step); sx->SetHead(epoch.ToProto()); - } - + } + auto *snap = proto.MutableIntroducedParts(); auto *bySwitchAux = aux.AddBySwitchAux(); TPageCollectionProtoHelper::Snap(snap, loaned->PartComponents, partSwitch.TableId, CompactionLogic->BorrowedPartLevel()); TPageCollectionProtoHelper(true, false).Do(bySwitchAux->AddHotBundles(), loaned->PartComponents); - auto body = proto.SerializeAsString(); + auto body = proto.SerializeAsString(); auto glob = CommitManager->Turns.One(commit->Refs, std::move(body), true); - - LogoBlobIDFromLogoBlobID(glob.Logo, bySwitchAux->MutablePartSwitchRef()); + + LogoBlobIDFromLogoBlobID(glob.Logo, bySwitchAux->MutablePartSwitchRef()); } PrepareExternalPart(partSwitch, std::move(loaned->PartComponents)); @@ -2195,19 +2195,19 @@ void TExecutor::CommitTransactionLog(TAutoPtr<TSeat> seat, TPageCollectionTxEnv if (aux.BySwitchAuxSize()) { commit->FollowerAux = NPageCollection::TSlicer::Lz4()->Encode(aux.SerializeAsString()); - } - + } + if (env.BorrowUpdates) { commit->WaitFollowerGcAck = true; for (auto &borrowUpdate : env.BorrowUpdates) { BorrowLogic->UpdateBorrow( borrowUpdate.first, borrowUpdate.second, - commit); + commit); } - TIntrusivePtr<TBarrier> barrier(new TBarrier(commit->Step)); - Y_VERIFY(InFlyCompactionGcBarriers.emplace(commit->Step, barrier).second); + TIntrusivePtr<TBarrier> barrier(new TBarrier(commit->Step)); + Y_VERIFY(InFlyCompactionGcBarriers.emplace(commit->Step, barrier).second); GcLogic->HoldBarrier(barrier->Step); } @@ -2217,22 +2217,22 @@ void TExecutor::CommitTransactionLog(TAutoPtr<TSeat> seat, TPageCollectionTxEnv BorrowLogic->ConfirmUpdateLoan( xupd.first, xupd.second.BorrowId, - commit); + commit); } - TIntrusivePtr<TBarrier> barrier(new TBarrier(commit->Step)); - Y_VERIFY(InFlyCompactionGcBarriers.emplace(commit->Step, barrier).second); + TIntrusivePtr<TBarrier> barrier(new TBarrier(commit->Step)); + Y_VERIFY(InFlyCompactionGcBarriers.emplace(commit->Step, barrier).second); GcLogic->HoldBarrier(barrier->Step); } - if (commitResult.Commit) + if (commitResult.Commit) CommitManager->Commit(commitResult.Commit); - for (auto &affectedTable : change->Affects) - CompactionLogic->UpdateInMemStatsStep(affectedTable, 1, Database->GetTableMemSize(affectedTable)); + for (auto &affectedTable : change->Affects) + CompactionLogic->UpdateInMemStatsStep(affectedTable, 1, Database->GetTableMemSize(affectedTable)); if (commitResult.NeedFlush && !LogBatchFlushScheduled) { LogBatchFlushScheduled = true; - + auto delay = Scheme().Executor.LogFlushPeriod; if (LogFlushDelayOverrideUsec != -1) { delay = TDuration::MicroSeconds(LogFlushDelayOverrideUsec); @@ -2247,15 +2247,15 @@ void TExecutor::CommitTransactionLog(TAutoPtr<TSeat> seat, TPageCollectionTxEnv } if (NeedFollowerSnapshot || LogicSnap->MayFlush(false)) - MakeLogSnapshot(); + MakeLogSnapshot(); - CompactionLogic->UpdateLogUsage(LogicRedo->GrabLogUsage()); + CompactionLogic->UpdateLogUsage(LogicRedo->GrabLogUsage()); } if (!Stats->IsFollower && HadFollowerAttached && env.Touches) { NKikimrExecutorFlat::TFollowerAux proto; proto.MutablePageCollectionsTouched()->Reserve(env.Touches.size()); - for (auto &xpair : env.Touches) { + for (auto &xpair : env.Touches) { auto *px = proto.AddPageCollectionsTouched(); LogoBlobIDFromLogoBlobID(xpair.first->Id, px->MutableMetaInfoId()); px->MutableTouchedPages()->Reserve(xpair.second.size()); @@ -2265,13 +2265,13 @@ void TExecutor::CommitTransactionLog(TAutoPtr<TSeat> seat, TPageCollectionTxEnv auto coded = NPageCollection::TSlicer::Lz4()->Encode(proto.SerializeAsString()); - Send(Owner->Tablet(), new TEvTablet::TEvAux(std::move(coded))); + Send(Owner->Tablet(), new TEvTablet::TEvAux(std::move(coded))); } const ui64 bookkeepingTimeuS = ui64(1000000. * (currentBookkeepingTime + bookkeepingTimer.PassedReset())); const ui64 execTimeuS = ui64(1000000. * currentExecTime); - Counters->Cumulative()[TExecutorCounters::TX_FINISHED].Increment(1); + Counters->Cumulative()[TExecutorCounters::TX_FINISHED].Increment(1); Counters->Percentile()[TExecutorCounters::TX_PERCENTILE_EXECUTE_CPUTIME].IncrementFor(execTimeuS); Counters->Percentile()[TExecutorCounters::TX_PERCENTILE_BOOKKEEPING_CPUTIME].IncrementFor(bookkeepingTimeuS); Counters->Cumulative()[TExecutorCounters::CONSUMED_CPU].Increment(execTimeuS + bookkeepingTimeuS); @@ -2281,33 +2281,33 @@ void TExecutor::CommitTransactionLog(TAutoPtr<TSeat> seat, TPageCollectionTxEnv } if (ResourceMetrics) { - ResourceMetrics->CPU.Increment(bookkeepingTimeuS + execTimeuS, Time->Now()); + ResourceMetrics->CPU.Increment(bookkeepingTimeuS + execTimeuS, Time->Now()); ResourceMetrics->TryUpdate(ctx); } } -void TExecutor::MakeLogSnapshot() { - if (!LogicSnap->MayFlush(true) || PendingPartSwitches) +void TExecutor::MakeLogSnapshot() { + if (!LogicSnap->MayFlush(true) || PendingPartSwitches) return; NeedFollowerSnapshot = false; THPTimer makeLogSnapTimer; - LogicRedo->FlushBatchedLog(); + LogicRedo->FlushBatchedLog(); auto commit = CommitManager->Begin(true, ECommit::Snap); - NKikimrExecutorFlat::TLogSnapshot snap; - - snap.SetSerial(Database->Head(Max<ui32>()).Serial); - - if (auto *version = snap.MutableVersion()) { + NKikimrExecutorFlat::TLogSnapshot snap; + + snap.SetSerial(Database->Head(Max<ui32>()).Serial); + + if (auto *version = snap.MutableVersion()) { version->SetTail(ui32(NTable::ECompatibility::Head)); version->SetHead(ui32(NTable::ECompatibility::Edge)); - } - - LogicAlter->SnapToLog(snap); - LogicRedo->SnapToLog(snap); + } + + LogicAlter->SnapToLog(snap); + LogicRedo->SnapToLog(snap); bool haveTxStatus = false; @@ -2330,7 +2330,7 @@ void TExecutor::MakeLogSnapshot() { auto dump = [&](const NTable::TPartView& partView) { ui32 level = state.State.PartLevels.Value(partView->Label, 255); - + TPageCollectionProtoHelper::Snap(snap.AddDbParts(), partView, tableId, level); }; @@ -2357,7 +2357,7 @@ void TExecutor::MakeLogSnapshot() { Database->EnumerateTableTxStatusParts(tableId, std::move(dumpTxStatus)); } - + if (haveTxStatus) { // Make sure older versions won't try loading an incomplete snapshot ui32 tail = Max(ui32(28), snap.GetVersion().GetTail()); @@ -2385,13 +2385,13 @@ void TExecutor::MakeLogSnapshot() { } } - BorrowLogic->SnapToLog(snap, *commit); - GcLogic->SnapToLog(snap, commit->Step); - LogicSnap->MakeSnap(snap, *commit, Logger.Get()); + BorrowLogic->SnapToLog(snap, *commit); + GcLogic->SnapToLog(snap, commit->Step); + LogicSnap->MakeSnap(snap, *commit, Logger.Get()); CommitManager->Commit(commit); - CompactionLogic->UpdateLogUsage(LogicRedo->GrabLogUsage()); + CompactionLogic->UpdateLogUsage(LogicRedo->GrabLogUsage()); const ui64 makeLogSnapTimeuS = ui64(1000000. * makeLogSnapTimer.Passed()); Counters->Percentile()[TExecutorCounters::TX_PERCENTILE_LOGSNAP_CPUTIME].IncrementFor(makeLogSnapTimeuS); @@ -2408,7 +2408,7 @@ void TExecutor::Handle(TEvPrivate::TEvActivateExecution::TPtr &ev, const TActorC if (TAutoPtr<TSeat> seat = ActivationQueue->Pop()) { Y_VERIFY(ActivateTransactionWaiting > 0); ActivateTransactionWaiting--; - ExecuteTransaction(seat, ctx); + ExecuteTransaction(seat, ctx); } else { // N.B. it should actually never happen, since ActivationQueue size // is always exactly equal to ActivateTransactionWaiting and we never @@ -2427,19 +2427,19 @@ void TExecutor::Handle(TEvPrivate::TEvBrokenTransaction::TPtr &ev, const TActorC return Broken(); } -void TExecutor::Wakeup(TEvents::TEvWakeup::TPtr &ev, const TActorContext&) { - if (ev->Get()->Tag == ui64(EWakeTag::Memory)) { - Memory->RunMemoryGC(); - } else { - Y_Fail("Unknown TExecutor module wakeup tag " << ev->Get()->Tag); - } -} - -void TExecutor::Handle(TEvents::TEvFlushLog::TPtr &ev) { +void TExecutor::Wakeup(TEvents::TEvWakeup::TPtr &ev, const TActorContext&) { + if (ev->Get()->Tag == ui64(EWakeTag::Memory)) { + Memory->RunMemoryGC(); + } else { + Y_Fail("Unknown TExecutor module wakeup tag " << ev->Get()->Tag); + } +} + +void TExecutor::Handle(TEvents::TEvFlushLog::TPtr &ev) { Y_UNUSED(ev); - LogBatchFlushScheduled = false; - LogicRedo->FlushBatchedLog(); - CompactionLogic->UpdateLogUsage(LogicRedo->GrabLogUsage()); + LogBatchFlushScheduled = false; + LogicRedo->FlushBatchedLog(); + CompactionLogic->UpdateLogUsage(LogicRedo->GrabLogUsage()); } void TExecutor::Handle(NSharedCache::TEvRequest::TPtr &ev) { @@ -2447,73 +2447,73 @@ void TExecutor::Handle(NSharedCache::TEvRequest::TPtr &ev) { TAutoPtr<NPageCollection::TFetch> msg = ev->Get()->Fetch; Y_VERIFY(msg->Pages, "empty page collection request, do not do it"); - + const TLogoBlobID &metaId = msg->PageCollection->Label(); TPrivatePageCache::TInfo *collectionInfo = PrivatePageCache->Info(metaId); if (!collectionInfo) { auto *reply = new NSharedCache::TEvResult(std::move(msg->PageCollection), msg->Cookie, NKikimrProto::RACE); - Send(ev->Sender, reply, 0, ev->Cookie); + Send(ev->Sender, reply, 0, ev->Cookie); return; } TVector<NSharedCache::TEvResult::TLoaded> cached; TVector<NTable::TPageId> left; - for (auto &x : msg->Pages) { + for (auto &x : msg->Pages) { if (TSharedPageRef body = PrivatePageCache->LookupShared(x, collectionInfo)) { cached.emplace_back(x, body); } else { - left.push_back(x); + left.push_back(x); } } if (cached) { - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*this) << " cache hit for data request from: " + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*this) << " cache hit for data request from: " << ev->Sender << ", pageCollection " << msg->PageCollection->Label(); - } - + } + auto *reply = new NSharedCache::TEvResult(msg->PageCollection, msg->Cookie, NKikimrProto::OK); reply->Loaded.swap(cached); - Send(ev->Sender, reply, 0, ev->Cookie); + Send(ev->Sender, reply, 0, ev->Cookie); } - if (left) { - DoSwap(msg->Pages, left); - - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*this) << " cache miss for data request from: " + if (left) { + DoSwap(msg->Pages, left); + + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*this) << " cache miss for data request from: " << ev->Sender << ", pageCollection " << msg->PageCollection->Label(); - } - + } + auto *req = new NSharedCache::TEvRequest(priority, msg, SelfId()); - + TActorIdentity(ev->Sender).Send(MakeSharedPageCacheId(), req, 0, ev->Cookie); } } void TExecutor::Handle(NSharedCache::TEvResult::TPtr &ev) { - const bool failed = (ev->Get()->Status != NKikimrProto::OK); - - if (auto logl = Logger->Log(failed ? ELnLev::Info : ELnLev::Debug)) { - logl - << NFmt::Do(*this) << " got result " << NFmt::Do(*ev->Get()) - << ", category " << ev->Cookie; - } - + const bool failed = (ev->Get()->Status != NKikimrProto::OK); + + if (auto logl = Logger->Log(failed ? ELnLev::Info : ELnLev::Debug)) { + logl + << NFmt::Do(*this) << " got result " << NFmt::Do(*ev->Get()) + << ", category " << ev->Cookie; + } + switch (EPageCollectionRequest(ev->Cookie)) { case EPageCollectionRequest::Cache: case EPageCollectionRequest::CacheSync: { auto *msg = ev->CastAsLocal<NSharedCache::TEvResult>(); - + TPrivatePageCache::TInfo *collectionInfo = PrivatePageCache->Info(msg->Origin->Label()); if (!collectionInfo) // collection could be outdated return; - if (msg->Status != NKikimrProto::OK) { // collection is still active but we got bs error. no choice then die + if (msg->Status != NKikimrProto::OK) { // collection is still active but we got bs error. no choice then die if (auto logl = Logger->Log(ELnLev::Error)) { logl << NFmt::Do(*this) << " Broken on page collection request error " << NFmt::Do(*ev->Get()); } @@ -2527,7 +2527,7 @@ void TExecutor::Handle(NSharedCache::TEvResult::TPtr &ev) { for (auto& loaded : msg->Loaded) { TPrivatePageCache::TPage::TWaitQueuePtr transactionsToActivate = PrivatePageCache->ProvideBlock(std::move(loaded), collectionInfo); - ActivateWaitingTransactions(transactionsToActivate); + ActivateWaitingTransactions(transactionsToActivate); } } return; @@ -2535,7 +2535,7 @@ void TExecutor::Handle(NSharedCache::TEvResult::TPtr &ev) { case EPageCollectionRequest::PendingInit: { auto *msg = ev->CastAsLocal<NSharedCache::TEvResult>(); - + const auto *pageCollection = msg->Origin.Get(); TPendingPartSwitch *foundSwitch = nullptr; TPendingPartSwitch::TNewBundle *foundBundle = nullptr; @@ -2561,7 +2561,7 @@ void TExecutor::Handle(NSharedCache::TEvResult::TPtr &ev) { foundStage->Fetching = nullptr; - if (msg->Status != NKikimrProto::OK) { + if (msg->Status != NKikimrProto::OK) { if (auto logl = Logger->Log(ELnLev::Error)) { logl << NFmt::Do(*this) << " Broken while pending part init" << NFmt::Do(*ev->Get()); } @@ -2581,7 +2581,7 @@ void TExecutor::Handle(NSharedCache::TEvResult::TPtr &ev) { return; } - AdvancePendingPartSwitches(); + AdvancePendingPartSwitches(); } return; @@ -2623,16 +2623,16 @@ void TExecutor::Handle(TEvTablet::TEvCommitResult::TPtr &ev, const TActorContext GcLogic->OnCommitLog(step, msg->ConfirmedOnSend, ctx); CommitManager->Confirm(step); - const auto cookie = static_cast<ECommit>(ev->Cookie); - - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*this) << " commited cookie " << int(cookie) - << " for step " << step; - } - - switch (cookie) { - case ECommit::Redo: + const auto cookie = static_cast<ECommit>(ev->Cookie); + + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*this) << " commited cookie " << int(cookie) + << " for step " << step; + } + + switch (cookie) { + case ECommit::Redo: { const ui64 confirmedTransactions = LogicRedo->Confirm(step, ctx, OwnerActorId); Stats->TxInFly -= confirmedTransactions; @@ -2646,14 +2646,14 @@ void TExecutor::Handle(TEvTablet::TEvCommitResult::TPtr &ev, const TActorContext } } break; - case ECommit::Snap: - LogicSnap->Confirm(msg->Step); + case ECommit::Snap: + LogicSnap->Confirm(msg->Step); if (NeedFollowerSnapshot) - MakeLogSnapshot(); + MakeLogSnapshot(); break; - case ECommit::Data: + case ECommit::Data: { auto it = InFlyCompactionGcBarriers.find(step); Y_VERIFY(it != InFlyCompactionGcBarriers.end()); @@ -2662,7 +2662,7 @@ void TExecutor::Handle(TEvTablet::TEvCommitResult::TPtr &ev, const TActorContext // any action on snapshot commit? break; - case ECommit::Misc: + case ECommit::Misc: break; default: Y_FAIL("unknown event cookie"); @@ -2686,14 +2686,14 @@ void TExecutor::Handle(TEvTablet::TEvCommitResult::TPtr &ev, const TActorContext std::move(msg->GroupWrittenOps))); ActiveTransaction = false; - PlanTransactionActivation(); + PlanTransactionActivation(); } -void TExecutor::Handle(TEvBlobStorage::TEvCollectGarbageResult::TPtr &ev) { +void TExecutor::Handle(TEvBlobStorage::TEvCollectGarbageResult::TPtr &ev) { GcLogic->OnCollectGarbageResult(ev); } -void TExecutor::Handle(TEvResourceBroker::TEvResourceAllocated::TPtr &ev) { +void TExecutor::Handle(TEvResourceBroker::TEvResourceAllocated::TPtr &ev) { auto *msg = ev->Get(); if (!msg->Cookie.Get()) { // Generic broker is not using cookies @@ -2701,10 +2701,10 @@ void TExecutor::Handle(TEvResourceBroker::TEvResourceAllocated::TPtr &ev) { return; } - auto *cookie = CheckedCast<TResource*>(msg->Cookie.Get()); + auto *cookie = CheckedCast<TResource*>(msg->Cookie.Get()); - switch (cookie->Source) { - case TResource::ESource::Seat: + switch (cookie->Source) { + case TResource::ESource::Seat: return StartSeat(msg->TaskId, cookie); case TResource::ESource::Scan: return StartScan(msg->TaskId, cookie); @@ -2716,20 +2716,20 @@ void TExecutor::Handle(TEvResourceBroker::TEvResourceAllocated::TPtr &ev) { void TExecutor::StartSeat(ui64 task, TResource *cookie_) noexcept { auto *cookie = CheckedCast<TMemory::TCookie*>(cookie_); - auto it = PostponedTransactions.find(cookie->Seat); - Y_VERIFY(it != PostponedTransactions.end()); + auto it = PostponedTransactions.find(cookie->Seat); + Y_VERIFY(it != PostponedTransactions.end()); TAutoPtr<TSeat> seat = std::move(it->second); - PostponedTransactions.erase(it); + PostponedTransactions.erase(it); Memory->AcquiredMemory(*seat, task); LWTRACK(TransactionEnqueued, seat->Self->Orbit, seat->UniqID); - ActivationQueue->Push(seat.Release()); + ActivationQueue->Push(seat.Release()); ActivateTransactionWaiting++; - PlanTransactionActivation(); + PlanTransactionActivation(); } THolder<TScanSnapshot> TExecutor::PrepareScanSnapshot(ui32 table, const NTable::TCompactionParams *params, TRowVersion snapshot) { - LogicRedo->FlushBatchedLog(); + LogicRedo->FlushBatchedLog(); auto commit = CommitManager->Begin(true, ECommit::Misc); @@ -2737,9 +2737,9 @@ THolder<TScanSnapshot> TExecutor::PrepareScanSnapshot(ui32 table, const NTable:: auto redo = Database->SnapshotToLog(table, { Generation(), commit->Step }); LogicRedo->MakeLogEntry(*commit, std::move(redo), { table }, true); } - + TIntrusivePtr<TBarrier> barrier = new TBarrier(commit->Step); - + CommitManager->Commit(commit); TAutoPtr<NTable::TSubset> subset; @@ -2767,8 +2767,8 @@ THolder<TScanSnapshot> TExecutor::PrepareScanSnapshot(ui32 table, const NTable:: PrivatePageCache->LockPageCollection(partView->Label); GcLogic->HoldBarrier(barrier->Step); - CompactionLogic->UpdateLogUsage(LogicRedo->GrabLogUsage()); - + CompactionLogic->UpdateLogUsage(LogicRedo->GrabLogUsage()); + return THolder<TScanSnapshot>(new TScanSnapshot{table, std::move(barrier), subset, snapshot}); } @@ -2786,22 +2786,22 @@ void TExecutor::StartScan(ui64 task, TResource *cookie) noexcept } void TExecutor::Handle(NBlockIO::TEvStat::TPtr &ev, const TActorContext &ctx) { - auto *msg = ev->Get(); - - if (auto *metrics = ResourceMetrics.Get()) { + auto *msg = ev->Get(); + + if (auto *metrics = ResourceMetrics.Get()) { auto &bandBytes = msg->Dir == NBlockIO::EDir::Read ? metrics->ReadThroughput : metrics->WriteThroughput; - + for (auto &it: msg->GroupBytes) bandBytes[it.first].Increment(it.second, Time->Now()); - + auto &bandOps = msg->Dir == NBlockIO::EDir::Read ? metrics->ReadIops : metrics->WriteIops; for (auto &it: msg->GroupOps) bandOps[it.first].Increment(it.second, Time->Now()); - metrics->TryUpdate(ctx); - } - + metrics->TryUpdate(ctx); + } + if (msg->Priority == NBlockIO::EPriority::Bulk) { switch (msg->Dir) { case NBlockIO::EDir::Read: @@ -2824,35 +2824,35 @@ void TExecutor::Handle(NBlockIO::TEvStat::TPtr &ev, const TActorContext &ctx) { Counters->Cumulative()[TExecutorCounters::TABLET_BLOBS_WRITTEN].Increment(msg->Ops); break; } - } + } } -void TExecutor::UtilizeSubset(const NTable::TSubset &subset, - const NTable::NFwd::TSeen &seen, +void TExecutor::UtilizeSubset(const NTable::TSubset &subset, + const NTable::NFwd::TSeen &seen, THashSet<TLogoBlobID> reusedBundles, - TLogCommit *commit) + TLogCommit *commit) { - if (seen.Sieve.size() == subset.Flatten.size() + 1) { - /* The last TSieve, if present, corresponds to external blobs of all + if (seen.Sieve.size() == subset.Flatten.size() + 1) { + /* The last TSieve, if present, corresponds to external blobs of all compacted TMemTable tables, this pseudo NPage::TBlobs is generated by - NFwd blobs tracer for this GC logic and may bypass borrow logic + NFwd blobs tracer for this GC logic and may bypass borrow logic since TMemTable cannot be borrowed. - */ - - seen.Sieve.back().MaterializeTo(commit->GcDelta.Deleted); - } else if (seen.Sieve.size() != subset.Flatten.size()) { - Y_FAIL("Got an unexpected TSieve items count after compaction"); - } - - for (auto it : xrange(subset.Flatten.size())) { + */ + + seen.Sieve.back().MaterializeTo(commit->GcDelta.Deleted); + } else if (seen.Sieve.size() != subset.Flatten.size()) { + Y_FAIL("Got an unexpected TSieve items count after compaction"); + } + + for (auto it : xrange(subset.Flatten.size())) { auto *partStore = subset.Flatten[it].As<const NTable::TPartStore>(); - + Y_VERIFY(seen.Sieve[it].Blobs.Get() == partStore->Blobs.Get()); - + if (reusedBundles.contains(partStore->Label)) { // Delete only compacted large blobs at this moment if (BorrowLogic->BundlePartiallyCompacted(*partStore, seen.Sieve[it], commit)) { - seen.Sieve[it].MaterializeTo(commit->GcDelta.Deleted); + seen.Sieve[it].MaterializeTo(commit->GcDelta.Deleted); } continue; @@ -2860,13 +2860,13 @@ void TExecutor::UtilizeSubset(const NTable::TSubset &subset, if (BorrowLogic->BundleCompacted(*partStore, seen.Sieve[it], commit)) { partStore->SaveAllBlobIdsTo(commit->GcDelta.Deleted); - - seen.Sieve[it].MaterializeTo(commit->GcDelta.Deleted); - } - + + seen.Sieve[it].MaterializeTo(commit->GcDelta.Deleted); + } + DropCachesOfBundle(*partStore); - } - + } + for (auto it : xrange(subset.ColdParts.size())) { auto *part = subset.ColdParts[it].Get(); @@ -2884,7 +2884,7 @@ void TExecutor::UtilizeSubset(const NTable::TSubset &subset, } } - Counters->Cumulative()[TExecutorCounters::DB_ELOBS_ITEMS_GONE].Increment(seen.Total - seen.Seen); + Counters->Cumulative()[TExecutorCounters::DB_ELOBS_ITEMS_GONE].Increment(seen.Total - seen.Seen); } void TExecutor::ReleaseScanLocks(TIntrusivePtr<TBarrier> barrier, const NTable::TSubset &subset) @@ -2906,17 +2906,17 @@ void TExecutor::Handle(NOps::TEvScanStat::TPtr &ev, const TActorContext &ctx) { } void TExecutor::Handle(NOps::TEvResult::TPtr &ev) { - auto *msg = ev->Get(); + auto *msg = ev->Get(); const auto outcome = Scans->Release(msg->Serial, msg->Status, msg->Result); if (outcome.System) { /* System scans are used for compactions and specially handled */ Handle(msg, CheckedCast<TProdCompact*>(msg->Result.Get()), outcome.Cancelled); - } + } ReleaseScanLocks(std::move(msg->Barrier), *msg->Subset); -} - +} + void TExecutor::Handle(NOps::TEvResult *ops, TProdCompact *msg, bool cancelled) { THPTimer partSwitchCpuTimer; @@ -2933,24 +2933,24 @@ void TExecutor::Handle(NOps::TEvResult *ops, TProdCompact *msg, bool cancelled) TProdCompact::TResults results = std::move(msg->Results); TVector<TIntrusiveConstPtr<NTable::TTxStatusPart>> newTxStatus = std::move(msg->TxStatus); - if (auto logl = Logger->Log(msg->Success ? ELnLev::Info : ELnLev::Error)) { - logl - << NFmt::Do(*this) << " Compact " << ops->Serial + if (auto logl = Logger->Log(msg->Success ? ELnLev::Info : ELnLev::Error)) { + logl + << NFmt::Do(*this) << " Compact " << ops->Serial << " on " << NFmt::Do(*msg->Params) << " step " << msg->Step << ", product {" << (newTxStatus ? "tx status + " : "") << results.size() << " parts" - << " epoch " << ops->Subset->Head << "} "; - + << " epoch " << ops->Subset->Head << "} "; + if (abandoned) { - logl << "thrown"; - } else if (!msg->Success) { - logl << "failed"; - } else { - logl << "done"; - } - } - + logl << "thrown"; + } else if (!msg->Success) { + logl << "failed"; + } else { + logl << "done"; + } + } + if (abandoned) { if (cancelled && Scheme().GetTableInfo(tableId)) { CompactionLogic->CancelledCompaction(ops->Serial, std::move(msg->Params)); @@ -2970,7 +2970,7 @@ void TExecutor::Handle(NOps::TEvResult *ops, TProdCompact *msg, bool cancelled) const ui64 snapStamp = msg->Params->Edge.TxStamp ? msg->Params->Edge.TxStamp : MakeGenStepPair(Generation(), msg->Step); - LogicRedo->FlushBatchedLog(); + LogicRedo->FlushBatchedLog(); // now apply effects NKikimrExecutorFlat::TTablePartSwitch proto; @@ -2979,28 +2979,28 @@ void TExecutor::Handle(NOps::TEvResult *ops, TProdCompact *msg, bool cancelled) NKikimrExecutorFlat::TFollowerPartSwitchAux aux; auto commit = CommitManager->Begin(true, ECommit::Data); - + commit->WaitFollowerGcAck = true; - + const bool hadFrozen = bool(ops->Subset->Frozen); if (ops->Subset->Head > NTable::TEpoch::Zero()) { // Some compactions (e.g. triggered by log overhead after many scans) // may have no TMemTable inputs, we still want to cut log since it's // effectively a snapshot. Y_VERIFY(msg->Params->Edge.Head > NTable::TEpoch::Zero()); - LogicRedo->CutLog(tableId, { snapStamp, ops->Subset->Head }, commit->GcDelta); + LogicRedo->CutLog(tableId, { snapStamp, ops->Subset->Head }, commit->GcDelta); auto *sx = proto.MutableTableSnapshoted(); sx->SetTable(tableId); - sx->SetGeneration(ExpandGenStepPair(snapStamp).first); - sx->SetStep(ExpandGenStepPair(snapStamp).second); + sx->SetGeneration(ExpandGenStepPair(snapStamp).first); + sx->SetStep(ExpandGenStepPair(snapStamp).second); sx->SetHead(ops->Subset->Head.ToProto()); } else { Y_VERIFY(!hadFrozen, "Compacted frozen parts without correct head epoch"); } if (results) { - auto &gcDiscovered = commit->GcDelta.Created; - + auto &gcDiscovered = commit->GcDelta.Created; + for (const auto &result : results) { const auto &newPart = result.Part; @@ -3010,7 +3010,7 @@ void TExecutor::Handle(NOps::TEvResult *ops, TProdCompact *msg, bool cancelled) { /*_ enum all new blobs (include external) to gc logic */ partStore->SaveAllBlobIdsTo(commit->GcDelta.Created); - + for (auto &hole: result.Growth) for (auto seq: xrange(hole.Begin, hole.End)) gcDiscovered.push_back(partStore->Blobs->Glob(seq).Logo); @@ -3026,16 +3026,16 @@ void TExecutor::Handle(NOps::TEvResult *ops, TProdCompact *msg, bool cancelled) } } - { /*_ Check that all external blobs will be accounted in GC logic */ + { /*_ Check that all external blobs will be accounted in GC logic */ ui64 totalBlobs = 0; ui64 totalGrow = 0; for (const auto &result : results) { totalBlobs += result.Part->Blobs ? result.Part->Blobs->Total() : 0; totalGrow += NTable::TScreen::Sum(result.Growth); } - + Y_VERIFY(ops->Trace->Seen + totalGrow == totalBlobs); - + Counters->Cumulative()[TExecutorCounters::DB_ELOBS_ITEMS_GROW].Increment(totalGrow); } @@ -3049,7 +3049,7 @@ void TExecutor::Handle(NOps::TEvResult *ops, TProdCompact *msg, bool cancelled) Database->Replace(tableId, newParts, *ops->Subset); Database->ReplaceTxStatus(tableId, newTxStatus, *ops->Subset); - + TVector<TLogoBlobID> bundles(Reserve(ops->Subset->Flatten.size() + ops->Subset->ColdParts.size())); for (auto &part: ops->Subset->Flatten) { bundles.push_back(part->Label); @@ -3059,7 +3059,7 @@ void TExecutor::Handle(NOps::TEvResult *ops, TProdCompact *msg, bool cancelled) } auto updatedSlices = Database->LookupSlices(tableId, bundles); - + THashSet<TLogoBlobID> reusedBundles; for (auto &part: ops->Subset->Flatten) { if (updatedSlices.contains(part->Label)) { @@ -3070,7 +3070,7 @@ void TExecutor::Handle(NOps::TEvResult *ops, TProdCompact *msg, bool cancelled) Y_VERIFY(!updatedSlices.contains(part->Label)); } - UtilizeSubset(*ops->Subset, *ops->Trace, std::move(reusedBundles), commit.Get()); + UtilizeSubset(*ops->Subset, *ops->Trace, std::move(reusedBundles), commit.Get()); const bool writeBundleDeltas = KIKIMR_TABLET_WRITE_BUNDLE_DELTAS; @@ -3097,8 +3097,8 @@ void TExecutor::Handle(NOps::TEvResult *ops, TProdCompact *msg, bool cancelled) for (auto &gone: ops->Subset->TxStatus) { LogoBlobIDFromLogoBlobID(gone->Label, proto.AddLeavingTxStatus()); } - } - + } + // We have applied all effects, time to notify compaction of completion auto compactionResult = MakeHolder<NTable::TCompactionResult>( @@ -3157,20 +3157,20 @@ void TExecutor::Handle(NOps::TEvResult *ops, TProdCompact *msg, bool cancelled) } } - { /*_ Finalize switch (turn) blob and attach it to commit */ - auto body = proto.SerializeAsString(); + { /*_ Finalize switch (turn) blob and attach it to commit */ + auto body = proto.SerializeAsString(); auto glob = CommitManager->Turns.One(commit->Refs, std::move(body), true); if (bySwitchAux) LogoBlobIDFromLogoBlobID(glob.Logo, bySwitchAux->MutablePartSwitchRef()); - } + } commit->FollowerAux = NPageCollection::TSlicer::Lz4()->Encode(aux.SerializeAsString()); Y_VERIFY(InFlyCompactionGcBarriers.emplace(commit->Step, ops->Barrier).second); CommitManager->Commit(commit); - + if (hadFrozen || logicResult.MemCompacted) CompactionLogic->UpdateInMemStatsStep(tableId, 0, Database->GetTableMemSize(tableId)); @@ -3185,7 +3185,7 @@ void TExecutor::Handle(NOps::TEvResult *ops, TProdCompact *msg, bool cancelled) for (auto &snap : logicResult.CompleteSnapshots) { if (snap->Impl->Complete(tableId, ops->Barrier)) { - auto snapIt = WaitingSnapshots.find(snap.Get()); + auto snapIt = WaitingSnapshots.find(snap.Get()); Y_VERIFY(snapIt != WaitingSnapshots.end()); TIntrusivePtr<TTableSnapshotContext> snapCtxPtr = snapIt->second; WaitingSnapshots.erase(snapIt); @@ -3197,9 +3197,9 @@ void TExecutor::Handle(NOps::TEvResult *ops, TProdCompact *msg, bool cancelled) Owner->CompactionComplete(tableId, OwnerCtx()); ActiveTransaction = false; - - if (LogicSnap->MayFlush(false)) { - MakeLogSnapshot(); + + if (LogicSnap->MayFlush(false)) { + MakeLogSnapshot(); } } @@ -3212,14 +3212,14 @@ void TExecutor::UpdateUsedTabletMemory() { UsedTabletMemory += PrivatePageCache->GetStats().TotalExclusive; } // Estimate memory used by database structures. - auto &counters = Database->Counters(); + auto &counters = Database->Counters(); UsedTabletMemory += counters.MemTableWaste; UsedTabletMemory += counters.MemTableBytes; UsedTabletMemory += counters.Parts.IndexBytes; UsedTabletMemory += counters.Parts.OtherBytes; UsedTabletMemory += counters.Parts.ByKeyBytes; - UsedTabletMemory += Stats->PacksMetaBytes; - + UsedTabletMemory += Stats->PacksMetaBytes; + // Add tablet memory usage. UsedTabletMemory += Owner->GetMemoryUsage(); } @@ -3232,30 +3232,30 @@ void TExecutor::UpdateCounters(const TActorContext &ctx) { UpdateUsedTabletMemory(); if (Counters) { - + const auto& dbCounters = Database->Counters(); { /* Memory consumption of common for leader and follower components */ Counters->Simple()[TExecutorCounters::DB_WARM_BYTES].Set(dbCounters.MemTableBytes); - Counters->Simple()[TExecutorCounters::DB_META_BYTES].Set(Stats->PacksMetaBytes); + Counters->Simple()[TExecutorCounters::DB_META_BYTES].Set(Stats->PacksMetaBytes); Counters->Simple()[TExecutorCounters::DB_INDEX_BYTES].Set(dbCounters.Parts.IndexBytes); Counters->Simple()[TExecutorCounters::DB_OTHER_BYTES].Set(dbCounters.Parts.OtherBytes); Counters->Simple()[TExecutorCounters::DB_BYKEY_BYTES].Set(dbCounters.Parts.ByKeyBytes); - Counters->Simple()[TExecutorCounters::CACHE_FRESH_SIZE].Set(CounterCacheFresh->Val()); - Counters->Simple()[TExecutorCounters::CACHE_STAGING_SIZE].Set(CounterCacheStaging->Val()); + Counters->Simple()[TExecutorCounters::CACHE_FRESH_SIZE].Set(CounterCacheFresh->Val()); + Counters->Simple()[TExecutorCounters::CACHE_STAGING_SIZE].Set(CounterCacheStaging->Val()); Counters->Simple()[TExecutorCounters::CACHE_WARM_SIZE].Set(CounterCacheMemTable->Val()); - Counters->Simple()[TExecutorCounters::USED_TABLET_MEMORY].Set(UsedTabletMemory); + Counters->Simple()[TExecutorCounters::USED_TABLET_MEMORY].Set(UsedTabletMemory); } if (CommitManager) /* exists only on leader, mostly storage usage data */ { - auto redo = LogicRedo->LogStats(); - Counters->Simple()[TExecutorCounters::LOG_REDO_COUNT].Set(redo.Items); - Counters->Simple()[TExecutorCounters::LOG_REDO_MEMORY].Set(redo.Memory); + auto redo = LogicRedo->LogStats(); + Counters->Simple()[TExecutorCounters::LOG_REDO_COUNT].Set(redo.Items); + Counters->Simple()[TExecutorCounters::LOG_REDO_MEMORY].Set(redo.Memory); Counters->Simple()[TExecutorCounters::LOG_REDO_SOLIDS].Set(redo.LargeGlobIds); - Counters->Simple()[TExecutorCounters::LOG_SNAP_BYTES].Set(LogicSnap->LogBytes()); - Counters->Simple()[TExecutorCounters::LOG_ALTER_BYTES].Set(LogicAlter->LogBytes()); - Counters->Simple()[TExecutorCounters::LOG_RIVER_LEVEL].Set(Max(LogicSnap->Waste().Level, i64(0))); - Counters->Simple()[TExecutorCounters::DB_DATA_BYTES].Set(CompactionLogic->GetBackingSize()); + Counters->Simple()[TExecutorCounters::LOG_SNAP_BYTES].Set(LogicSnap->LogBytes()); + Counters->Simple()[TExecutorCounters::LOG_ALTER_BYTES].Set(LogicAlter->LogBytes()); + Counters->Simple()[TExecutorCounters::LOG_RIVER_LEVEL].Set(Max(LogicSnap->Waste().Level, i64(0))); + Counters->Simple()[TExecutorCounters::DB_DATA_BYTES].Set(CompactionLogic->GetBackingSize()); Counters->Simple()[TExecutorCounters::DB_WARM_OPS].Set(dbCounters.MemTableOps); Counters->Simple()[TExecutorCounters::DB_ROWS_TOTAL].Set(dbCounters.Parts.RowsTotal); Counters->Simple()[TExecutorCounters::DB_ROWS_ERASE].Set(dbCounters.Parts.RowsErase); @@ -3309,11 +3309,11 @@ void TExecutor::UpdateCounters(const TActorContext &ctx) { Counters->Simple()[TExecutorCounters::CACHE_TOTAL_STICKY].Set(stats.TotalSticky); } - const auto &memory = Memory->Stats(); - - Counters->Simple()[TExecutorCounters::USED_TABLET_TX_MEMORY].Set(memory.Static); - Counters->Simple()[TExecutorCounters::USED_DYNAMIC_TX_MEMORY].Set(memory.Dynamic); - + const auto &memory = Memory->Stats(); + + Counters->Simple()[TExecutorCounters::USED_TABLET_TX_MEMORY].Set(memory.Static); + Counters->Simple()[TExecutorCounters::USED_DYNAMIC_TX_MEMORY].Set(memory.Dynamic); + executorCounters = Counters->MakeDiffForAggr(*CountersBaseline); Counters->RememberCurrentStateAsBaseline(*CountersBaseline); @@ -3323,10 +3323,10 @@ void TExecutor::UpdateCounters(const TActorContext &ctx) { ui64 storageSize = Counters->Simple()[TExecutorCounters::DB_UNIQUE_DATA_BYTES].Get() + Counters->Simple()[TExecutorCounters::DB_UNIQUE_ELOBS_BYTES].Get() + Counters->Simple()[TExecutorCounters::DB_UNIQUE_KEEP_BYTES].Get(); - + ResourceMetrics->StorageSystem.Set(storageSize); - auto limit = Memory->Profile->GetStaticTabletTxMemoryLimit(); + auto limit = Memory->Profile->GetStaticTabletTxMemoryLimit(); auto memorySize = limit ? (UsedTabletMemory + limit) : (UsedTabletMemory + memory.Static); ResourceMetrics->Memory.Set(memorySize); Counters->Simple()[TExecutorCounters::CONSUMED_STORAGE].Set(storageSize); @@ -3345,14 +3345,14 @@ void TExecutor::UpdateCounters(const TActorContext &ctx) { auto tenantPathId = Owner->Info()->TenantPathId; TActorId countersAggregator = MakeTabletCountersAggregatorID(SelfId().NodeId(), Stats->IsFollower); - Send(countersAggregator, new TEvTabletCounters::TEvTabletAddCounters( + Send(countersAggregator, new TEvTabletCounters::TEvTabletAddCounters( CounterEventsInFlight, tabletId, tabletType, tenantPathId, executorCounters, externalTabletCounters)); if (ResourceMetrics) { ResourceMetrics->TryUpdate(ctx); } } - Schedule(TDuration::Seconds(15), new TEvPrivate::TEvUpdateCounters()); + Schedule(TDuration::Seconds(15), new TEvPrivate::TEvUpdateCounters()); } float TExecutor::GetRejectProbability() const { @@ -3387,31 +3387,31 @@ float TExecutor::GetRejectProbability() const { return rejectProbability; } - -TString TExecutor::BorrowSnapshot(ui32 table, const TTableSnapshotContext &snap, TRawVals from, TRawVals to, ui64 loaner) const -{ + +TString TExecutor::BorrowSnapshot(ui32 table, const TTableSnapshotContext &snap, TRawVals from, TRawVals to, ui64 loaner) const +{ auto subset = Database->Subset(table, snap.Edge(table).Head, from, to); - - if (subset == nullptr) - return { }; /* Lack of required pages in cache, retry later */ - - Y_VERIFY(!subset->Frozen, "Don't know how to borrow frozen parts"); - - NKikimrExecutorFlat::TDatabaseBorrowPart proto; - - proto.SetSourceTable(table); - proto.SetLenderTablet(TabletId()); - proto.MutableParts()->Reserve(subset->Flatten.size()); - + + if (subset == nullptr) + return { }; /* Lack of required pages in cache, retry later */ + + Y_VERIFY(!subset->Frozen, "Don't know how to borrow frozen parts"); + + NKikimrExecutorFlat::TDatabaseBorrowPart proto; + + proto.SetSourceTable(table); + proto.SetLenderTablet(TabletId()); + proto.MutableParts()->Reserve(subset->Flatten.size()); + const bool includeMeta = !bool(KIKIMR_TABLET_BORROW_WITHOUT_META); for (const auto &partView : subset->Flatten) { - auto *x = proto.AddParts(); - + auto *x = proto.AddParts(); + TPageCollectionProtoHelper(includeMeta, false).Do(x->MutableBundle(), partView); snap.Impl->Borrowed(Step(), table, partView->Label, loaner); - } - + } + for (const auto &part : subset->ColdParts) { auto *x = proto.AddParts(); @@ -3428,10 +3428,10 @@ TString TExecutor::BorrowSnapshot(ui32 table, const TTableSnapshotContext &snap, snap.Impl->Borrowed(Step(), table, txStatus->Label, loaner); } - return proto.SerializeAsString(); -} - -ui64 TExecutor::MakeScanSnapshot(ui32 table) + return proto.SerializeAsString(); +} + +ui64 TExecutor::MakeScanSnapshot(ui32 table) { if (auto snapshot = PrepareScanSnapshot(table, nullptr)) { ScanSnapshots.emplace(++ScanSnapshotId, std::move(snapshot)); @@ -3520,7 +3520,7 @@ ui64 TExecutor::CompactMemTable(ui32 tableId) { ui64 TExecutor::CompactTable(ui32 tableId) { if (CompactionLogic) { - return CompactionLogic->PrepareForceCompaction(tableId); + return CompactionLogic->PrepareForceCompaction(tableId); } else { return 0; } @@ -3549,7 +3549,7 @@ STFUNC(TExecutor::StateBoot) { HFunc(TEvents::TEvWakeup, Wakeup); hFunc(TEvResourceBroker::TEvResourceAllocated, Handle); default: - return TranscriptBootOpResult(BootLogic->Receive(*ev), ctx); + return TranscriptBootOpResult(BootLogic->Receive(*ev), ctx); } } @@ -3560,18 +3560,18 @@ STFUNC(TExecutor::StateWork) { HFunc(TEvPrivate::TEvActivateCompactionRead, Handle); HFunc(TEvPrivate::TEvActivateCompactionChanges, Handle); CFunc(TEvPrivate::EvUpdateCounters, UpdateCounters); - cFunc(TEvPrivate::EvCheckYellow, UpdateYellow); - cFunc(TEvPrivate::EvUpdateCompactions, UpdateCompactions); - HFunc(TEvents::TEvWakeup, Wakeup); - hFunc(TEvents::TEvFlushLog, Handle); + cFunc(TEvPrivate::EvCheckYellow, UpdateYellow); + cFunc(TEvPrivate::EvUpdateCompactions, UpdateCompactions); + HFunc(TEvents::TEvWakeup, Wakeup); + hFunc(TEvents::TEvFlushLog, Handle); hFunc(NSharedCache::TEvRequest, Handle); hFunc(NSharedCache::TEvResult, Handle); hFunc(NSharedCache::TEvUpdated, Handle); HFunc(TEvTablet::TEvCommitResult, Handle); - hFunc(TEvTablet::TEvCheckBlobstorageStatusResult, Handle); - hFunc(TEvBlobStorage::TEvCollectGarbageResult, Handle); + hFunc(TEvTablet::TEvCheckBlobstorageStatusResult, Handle); + hFunc(TEvBlobStorage::TEvCollectGarbageResult, Handle); HFunc(TEvBlobStorage::TEvGetResult, Handle); - hFunc(TEvResourceBroker::TEvResourceAllocated, Handle); + hFunc(TEvResourceBroker::TEvResourceAllocated, Handle); HFunc(NOps::TEvScanStat, Handle); hFunc(NOps::TEvResult, Handle); HFunc(NBlockIO::TEvStat, Handle); @@ -3628,10 +3628,10 @@ const TExecutorStats& TExecutor::GetStats() const { return *Stats; } -void TExecutor::RenderHtmlCounters(NMon::TEvRemoteHttpInfo::TPtr &ev) const { +void TExecutor::RenderHtmlCounters(NMon::TEvRemoteHttpInfo::TPtr &ev) const { TStringStream str; - if (Database) { + if (Database) { HTML(str) { str << "<style>"; str << "table.metrics { margin-bottom: 20px; }"; @@ -3656,13 +3656,13 @@ void TExecutor::RenderHtmlCounters(NMon::TEvRemoteHttpInfo::TPtr &ev) const { HTML(str) {str << "loading...";} // todo: populate from bootlogic } - Send(ev->Sender, new NMon::TEvRemoteHttpInfoRes(str.Str())); + Send(ev->Sender, new NMon::TEvRemoteHttpInfoRes(str.Str())); } -void TExecutor::RenderHtmlPage(NMon::TEvRemoteHttpInfo::TPtr &ev) const { +void TExecutor::RenderHtmlPage(NMon::TEvRemoteHttpInfo::TPtr &ev) const { auto cgi = ev->Get()->Cgi(); TStringStream str; - const NScheme::TTypeRegistry& tr = *AppData()->TypeRegistry; + const NScheme::TTypeRegistry& tr = *AppData()->TypeRegistry; if (cgi.Has("force_compaction")) { bool ok; @@ -3700,35 +3700,35 @@ void TExecutor::RenderHtmlPage(NMon::TEvRemoteHttpInfo::TPtr &ev) const { } } else if (auto *scheme = Database ? &Database->GetScheme() : nullptr) { HTML(str) { - H3() { str << NFmt::Do(*this) << " tablet synopsis"; } - - if (auto *logic = BootLogic.Get()) { - DIV_CLASS("row") {str << NFmt::Do(*logic); } - } else if (auto *dbase = Database.Get()) { + H3() { str << NFmt::Do(*this) << " tablet synopsis"; } + + if (auto *logic = BootLogic.Get()) { + DIV_CLASS("row") {str << NFmt::Do(*logic); } + } else if (auto *dbase = Database.Get()) { if (CommitManager) /* Leader tablet, commit manager owner */ { DIV_CLASS("row") { str << NFmt::Do(*CommitManager); } - DIV_CLASS("row") { str << NFmt::Do(LogicSnap->Waste(), true);} - DIV_CLASS("row") { str << NFmt::Do(*LogicSnap); } - DIV_CLASS("row") { str << NFmt::Do(*LogicRedo); } - DIV_CLASS("row") { str << NFmt::Do(*LogicAlter); } - } else { - DIV_CLASS("row") { str << "Sync{on step " << Step0 << "}"; } - } - - DIV_CLASS("row") { str << NFmt::Do(dbase->Counters()); } - DIV_CLASS("row") { str << NFmt::Do(*Scans); } - DIV_CLASS("row") { str << NFmt::Do(Memory->Stats()); } - } else { - DIV_CLASS("row") { str << "Booted tablet without dbase"; } - } - + DIV_CLASS("row") { str << NFmt::Do(LogicSnap->Waste(), true);} + DIV_CLASS("row") { str << NFmt::Do(*LogicSnap); } + DIV_CLASS("row") { str << NFmt::Do(*LogicRedo); } + DIV_CLASS("row") { str << NFmt::Do(*LogicAlter); } + } else { + DIV_CLASS("row") { str << "Sync{on step " << Step0 << "}"; } + } + + DIV_CLASS("row") { str << NFmt::Do(dbase->Counters()); } + DIV_CLASS("row") { str << NFmt::Do(*Scans); } + DIV_CLASS("row") { str << NFmt::Do(Memory->Stats()); } + } else { + DIV_CLASS("row") { str << "Booted tablet without dbase"; } + } + H3() {str << "Scheme:";} TVector<ui32> tables; - for (const auto &xtable : scheme->Tables) + for (const auto &xtable : scheme->Tables) tables.push_back(xtable.first); Sort(tables); for (auto itable : tables) { - const auto &tinfo = scheme->Tables.find(itable)->second; + const auto &tinfo = scheme->Tables.find(itable)->second; H4() {str << "<a href='db?TabletID=" << Owner->TabletID() << "&TableID=" << tinfo.Id << "'>Table: \"" << tinfo.Name << "\" id: " << tinfo.Id << "</a>";} TABLE_SORTABLE_CLASS("table") { TABLEHEAD() { @@ -3764,7 +3764,7 @@ void TExecutor::RenderHtmlPage(NMon::TEvRemoteHttpInfo::TPtr &ev) const { H3() {str << "Resource usage:";} DIV_CLASS("row") {str << "used tablet memory: " << UsedTabletMemory; } - Memory->DumpStateToHTML(str); + Memory->DumpStateToHTML(str); if (CompactionLogic) CompactionLogic->OutputHtml(str, *scheme, cgi); @@ -3803,12 +3803,12 @@ void TExecutor::RenderHtmlPage(NMon::TEvRemoteHttpInfo::TPtr &ev) const { HTML(str) {str << "loading...";} // todo: populate from bootlogic } - Send(ev->Sender, new NMon::TEvRemoteHttpInfoRes(str.Str())); + Send(ev->Sender, new NMon::TEvRemoteHttpInfoRes(str.Str())); } const NTable::TScheme& TExecutor::Scheme() const noexcept { Y_VERIFY_DEBUG(Database); - return Database->GetScheme(); + return Database->GetScheme(); } void TExecutor::RegisterExternalTabletCounters(TAutoPtr<TTabletCountersBase> appCounters) { @@ -3816,22 +3816,22 @@ void TExecutor::RegisterExternalTabletCounters(TAutoPtr<TTabletCountersBase> app AppCountersBaseline = MakeHolder<TTabletCountersBase>(); AppCounters->RememberCurrentStateAsBaseline(*AppCountersBaseline); - if (LogicRedo) { + if (LogicRedo) { AppTxCounters = dynamic_cast<TTabletCountersWithTxTypes*>(AppCounters.Get()); - LogicRedo->InstallCounters(Counters.Get(), AppTxCounters); + LogicRedo->InstallCounters(Counters.Get(), AppTxCounters); } } -void TExecutor::GetTabletCounters(TEvTablet::TEvGetCounters::TPtr &ev) { +void TExecutor::GetTabletCounters(TEvTablet::TEvGetCounters::TPtr &ev) { TAutoPtr<TEvTablet::TEvGetCountersResponse> response = new TEvTablet::TEvGetCountersResponse(); Counters->OutputProto(*response->Record.MutableTabletCounters()->MutableExecutorCounters()); AppCounters->OutputProto(*response->Record.MutableTabletCounters()->MutableAppCounters()); - Send(ev->Sender, response.Release(), 0, ev->Cookie); + Send(ev->Sender, response.Release(), 0, ev->Cookie); } -void TExecutor::UpdateConfig(TEvTablet::TEvUpdateConfig::TPtr &ev) { - Memory->SetProfiles(ev->Get()->ResourceProfiles); - ReadResourceProfile(); +void TExecutor::UpdateConfig(TEvTablet::TEvUpdateConfig::TPtr &ev) { + Memory->SetProfiles(ev->Get()->ResourceProfiles); + ReadResourceProfile(); } void TExecutor::SendUserAuxUpdateToFollowers(TString upd, const TActorContext &ctx) { @@ -3845,15 +3845,15 @@ void TExecutor::SendUserAuxUpdateToFollowers(TString upd, const TActorContext &c ctx.Send(Owner->Tablet(), new TEvTablet::TEvAux(std::move(coded))); } -NMetrics::TResourceMetrics* TExecutor::GetResourceMetrics() const { +NMetrics::TResourceMetrics* TExecutor::GetResourceMetrics() const { return ResourceMetrics.Get(); } void TExecutor::ReadResourceProfile() { - if (Database) { - auto type = static_cast<TMemory::ETablet>(Owner->TabletType()); + if (Database) { + auto type = static_cast<TMemory::ETablet>(Owner->TabletType()); Memory->UseProfile(type, Scheme().Executor.ResourceProfile); - } + } } TString TExecutor::CheckBorrowConsistency() { diff --git a/ydb/core/tablet_flat/flat_executor.h b/ydb/core/tablet_flat/flat_executor.h index df08b3a338..3081df35aa 100644 --- a/ydb/core/tablet_flat/flat_executor.h +++ b/ydb/core/tablet_flat/flat_executor.h @@ -2,26 +2,26 @@ #include "defs.h" #include "tablet_flat_executor.h" #include "flat_database.h" -#include "flat_dbase_change.h" +#include "flat_dbase_change.h" #include "flat_sausagecache.h" -#include "flat_part_store.h" -#include "flat_part_outset.h" +#include "flat_part_store.h" +#include "flat_part_outset.h" #include "flat_part_loader.h" #include "flat_load_blob_queue.h" #include "flat_comp.h" -#include "flat_scan_events.h" +#include "flat_scan_events.h" #include "flat_scan_eggs.h" -#include "flat_exec_commit.h" +#include "flat_exec_commit.h" #include "flat_exec_read.h" -#include "flat_executor_misc.h" +#include "flat_executor_misc.h" #include "flat_executor_compaction_logic.h" #include "flat_executor_gclogic.h" -#include "flat_bio_events.h" -#include "flat_bio_stats.h" -#include "flat_fwd_sieve.h" -#include "flat_sausage_grind.h" -#include "shared_cache_events.h" -#include "util_fmt_logger.h" +#include "flat_bio_events.h" +#include "flat_bio_stats.h" +#include "flat_fwd_sieve.h" +#include "flat_sausage_grind.h" +#include "shared_cache_events.h" +#include "util_fmt_logger.h" #include <ydb/core/control/immediate_control_board_wrapper.h> #include <ydb/core/tablet/tablet_counters.h> @@ -39,29 +39,29 @@ #include <variant> namespace NKikimr { - -namespace NTable { - class TLoader; -} - + +namespace NTable { + class TLoader; +} + namespace NTabletFlatExecutor { -class TLogicSnap; +class TLogicSnap; class TExecutorBootLogic; -class TLogicRedo; -class TLogicAlter; -class TLogicSnap; +class TLogicRedo; +class TLogicAlter; +class TLogicSnap; class TExecutorBorrowLogic; class TExecutorCounters; class TCommitManager; -class TScans; -class TMemory; +class TScans; +class TMemory; struct TIdEmitter; struct TPageCollectionReadEnv; struct TPageCollectionTxEnv; -struct TProdCompact; -struct TProdBackup; -struct TSeat; +struct TProdCompact; +struct TProdBackup; +struct TSeat; struct TPendingPartSwitch { struct TLargeGlobLoader { @@ -199,7 +199,7 @@ struct TPendingPartSwitch { struct TChangedBundle { TLogoBlobID Label; - TString Legacy; + TString Legacy; TString Opaque; }; @@ -318,8 +318,8 @@ class TExecutor , private NTable::ICompactionBackend , private ILoadBlob { - using ELnLev = NUtil::ELnLev; - + using ELnLev = NUtil::ELnLev; + friend class TExecutorCompactionLogic; class TTxExecutorDbMon; @@ -350,13 +350,13 @@ class TExecutor }; const TIntrusivePtr<ITimeProvider> Time = nullptr; - NFlatExecutorSetup::ITablet * Owner; + NFlatExecutorSetup::ITablet * Owner; const TActorId OwnerActorId; TAutoPtr<NUtil::ILogger> Logger; ui32 FollowerId = 0; - using TActivationQueue = TOneOneQueueInplace<TSeat *, 64>; + using TActivationQueue = TOneOneQueueInplace<TSeat *, 64>; THolder<TActivationQueue, TActivationQueue::TPtrCleanDestructor> ActivationQueue; THolder<TActivationQueue, TActivationQueue::TPtrCleanDestructor> PendingQueue; @@ -365,32 +365,32 @@ class TExecutor bool CompactionReadActivating = false; bool CompactionChangesActivating = false; - TMap<TSeat*, TAutoPtr<TSeat>> PostponedTransactions; + TMap<TSeat*, TAutoPtr<TSeat>> PostponedTransactions; THashMap<ui64, THolder<TScanSnapshot>> ScanSnapshots; - ui64 ScanSnapshotId = 1; + ui64 ScanSnapshotId = 1; - bool ActiveTransaction = false; + bool ActiveTransaction = false; bool BrokenTransaction = false; ui32 ActivateTransactionWaiting = 0; ui32 ActivateTransactionInFlight = 0; using TWaitingSnaps = THashMap<TTableSnapshotContext *, TIntrusivePtr<TTableSnapshotContext>>; - + const TIntrusivePtr<TIdEmitter> Emitter; TAutoPtr<TBroker> Broker; - + TWaitingSnaps WaitingSnapshots; THolder<TExecutorBootLogic> BootLogic; THolder<TPrivatePageCache> PrivatePageCache; - THolder<TExecutorCounters> Counters; - THolder<TTabletCountersBase> AppCounters; - THolder<TTabletCountersBase> CountersBaseline; - THolder<TTabletCountersBase> AppCountersBaseline; - THolder<NMetrics::TResourceMetrics> ResourceMetrics; + THolder<TExecutorCounters> Counters; + THolder<TTabletCountersBase> AppCounters; + THolder<TTabletCountersBase> CountersBaseline; + THolder<TTabletCountersBase> AppCountersBaseline; + THolder<NMetrics::TResourceMetrics> ResourceMetrics; TAutoPtr<NTable::TDatabase> Database; - + TAutoPtr<TCommitManager> CommitManager; TAutoPtr<TScans> Scans; TAutoPtr<TMemory> Memory; @@ -413,10 +413,10 @@ class TExecutor THashMap<TPrivatePageCacheWaitPad*, THolder<TTransactionWaitPad>> TransactionWaitPads; THashMap<TPrivatePageCacheWaitPad*, THolder<TCompactionReadWaitPad>> CompactionReadWaitPads; - ui64 TransactionUniqCounter = 0; + ui64 TransactionUniqCounter = 0; ui64 CompactionReadUniqCounter = 0; - bool LogBatchFlushScheduled = false; + bool LogBatchFlushScheduled = false; bool HadFollowerAttached = false; bool NeedFollowerSnapshot = false; @@ -429,20 +429,20 @@ class TExecutor THashMap<ui32, TVector<TIntrusivePtr<TBarrier>>> InFlySnapCollectionBarriers; THolder<TExecutorStatsImpl> Stats; - bool HasYellowCheckInFly = false; + bool HasYellowCheckInFly = false; TDeque<TPendingPartSwitch> PendingPartSwitches; size_t ReadyPartSwitches = 0; - ui64 UsedTabletMemory = 0; + ui64 UsedTabletMemory = 0; TActorContext OwnerCtx() const; TControlWrapper LogFlushDelayOverrideUsec; - ui64 Stamp() const noexcept; + ui64 Stamp() const noexcept; void Registered(TActorSystem*, const TActorId&) override; - void PassAway() override; + void PassAway() override; void Broken(); void Active(const TActorContext &ctx); void ActivateFollower(const TActorContext &ctx); @@ -452,14 +452,14 @@ class TExecutor void CheckYellow(TVector<ui32> &&yellowMoveChannels, TVector<ui32> &&yellowStopChannels, bool terminal = false); void SendReassignYellowChannels(const TVector<ui32> &yellowChannels); void CheckCollectionBarrier(TIntrusivePtr<TBarrier> &barrier); - void UtilizeSubset(const NTable::TSubset&, const NTable::NFwd::TSeen&, - THashSet<TLogoBlobID> reusedBundles, TLogCommit *commit); + void UtilizeSubset(const NTable::TSubset&, const NTable::NFwd::TSeen&, + THashSet<TLogoBlobID> reusedBundles, TLogCommit *commit); bool PrepareExternalPart(TPendingPartSwitch &partSwitch, NTable::TPartComponents &&pc); bool PrepareExternalPart(TPendingPartSwitch &partSwitch, TPendingPartSwitch::TNewBundle &bundle); bool PrepareExternalTxStatus(TPendingPartSwitch &partSwitch, const NPageCollection::TLargeGlobId &dataId, NTable::TEpoch epoch, const TString &data); bool PrepareExternalTxStatus(TPendingPartSwitch &partSwitch, TPendingPartSwitch::TNewTxStatus &txStatus); void OnBlobLoaded(const TLogoBlobID& id, TString body, uintptr_t cookie) override; - void AdvancePendingPartSwitches(); + void AdvancePendingPartSwitches(); bool ApplyReadyPartSwitches(); TExecutorCaches CleanupState(); @@ -467,20 +467,20 @@ class TExecutor void TranscriptBootOpResult(ui32 res, const TActorContext &ctx); void TranscriptFollowerBootOpResult(ui32 res, const TActorContext &ctx); - void ExecuteTransaction(TAutoPtr<TSeat> seat, const TActorContext &ctx); + void ExecuteTransaction(TAutoPtr<TSeat> seat, const TActorContext &ctx); void CommitTransactionLog(TAutoPtr<TSeat>, TPageCollectionTxEnv&, TAutoPtr<NTable::TChange>, THPTimer &bookkeepingTimer, const TActorContext &ctx); - void UnpinTransactionPages(TSeat &seat); + void UnpinTransactionPages(TSeat &seat); void ReleaseTxData(TSeat &seat, ui64 requested, const TActorContext &ctx); void PostponeTransaction(TAutoPtr<TSeat>, TPageCollectionTxEnv&, TAutoPtr<NTable::TChange>, THPTimer &bookkeepingTimer, const TActorContext &ctx); - void PlanTransactionActivation(); - void MakeLogSnapshot(); + void PlanTransactionActivation(); + void MakeLogSnapshot(); void ActivateWaitingTransactions(TPrivatePageCache::TPage::TWaitQueuePtr waitPadsQueue); void AddCachesOfBundle(const NTable::TPartView &partView) noexcept; void AddSingleCache(const TIntrusivePtr<TPrivatePageCache::TInfo> &info) noexcept; - void DropCachesOfBundle(const NTable::TPart &part) noexcept; - void DropSingleCache(const TLogoBlobID&) noexcept; - + void DropCachesOfBundle(const NTable::TPart &part) noexcept; + void DropSingleCache(const TLogoBlobID&) noexcept; + void TranslateCacheTouchesToSharedCache(); void RequestInMemPagesForDatabase(); void RequestInMemPagesForPartStore(ui32 tableId, const NTable::TPartView &partView); @@ -501,16 +501,16 @@ class TExecutor const NKikimrExecutorFlat::TFollowerPartSwitchAux::TBySwitch *aux, ui32 updateStep, ui32 step); void ApplyExternalPartSwitch(TPendingPartSwitch &partSwitch); - void Wakeup(TEvents::TEvWakeup::TPtr &ev, const TActorContext &ctx); + void Wakeup(TEvents::TEvWakeup::TPtr &ev, const TActorContext &ctx); void Handle(TEvTablet::TEvCommitResult::TPtr &ev, const TActorContext &ctx); void Handle(TEvPrivate::TEvActivateExecution::TPtr &ev, const TActorContext &ctx); void Handle(TEvPrivate::TEvBrokenTransaction::TPtr &ev, const TActorContext &ctx); - void Handle(TEvents::TEvFlushLog::TPtr &ev); - void Handle(TEvBlobStorage::TEvCollectGarbageResult::TPtr&); + void Handle(TEvents::TEvFlushLog::TPtr &ev); + void Handle(TEvBlobStorage::TEvCollectGarbageResult::TPtr&); void Handle(NSharedCache::TEvResult::TPtr &ev); void Handle(NSharedCache::TEvRequest::TPtr &ev); void Handle(NSharedCache::TEvUpdated::TPtr &ev); - void Handle(NResourceBroker::TEvResourceBroker::TEvResourceAllocated::TPtr&); + void Handle(NResourceBroker::TEvResourceBroker::TEvResourceAllocated::TPtr&); void Handle(NOps::TEvScanStat::TPtr &ev, const TActorContext &ctx); void Handle(NOps::TEvResult::TPtr &ev); void Handle(NBlockIO::TEvStat::TPtr &ev, const TActorContext &ctx); @@ -519,9 +519,9 @@ class TExecutor void UpdateUsedTabletMemory(); void UpdateCounters(const TActorContext &ctx); - void UpdateYellow(); - void UpdateCompactions(); - void Handle(TEvTablet::TEvCheckBlobstorageStatusResult::TPtr &ev); + void UpdateYellow(); + void UpdateCompactions(); + void Handle(TEvTablet::TEvCheckBlobstorageStatusResult::TPtr &ev); void ReadResourceProfile(); TString CheckBorrowConsistency(); @@ -562,13 +562,13 @@ class TExecutor public: void Describe(IOutputStream &out) const noexcept override - { - out + { + out << (Stats->IsFollower ? "Follower" : "Leader") - << "{" << Owner->TabletID() - << ":" << Generation() << ":" << Step() << "}"; - } - + << "{" << Owner->TabletID() + << ":" << Generation() << ":" << Step() << "}"; + } + // IExecutor interface void Boot(TEvTablet::TEvBoot::TPtr &ev, const TActorContext &ctx) override; void Restored(TEvTablet::TEvRestored::TPtr &ev, const TActorContext &ctx) override; @@ -577,8 +577,8 @@ public: TString BorrowSnapshot(ui32 tableId, const TTableSnapshotContext& snap, TRawVals from, TRawVals to, ui64 loaner) const override; - ui64 MakeScanSnapshot(ui32 table) override; - void DropScanSnapshot(ui64 snapId) override; + ui64 MakeScanSnapshot(ui32 table) override; + void DropScanSnapshot(ui64 snapId) override; ui64 QueueScan(ui32 tableId, TAutoPtr<NTable::IScan> scan, ui64 cookie, const TScanOptions& options) override; bool CancelScan(ui32 tableId, ui64 taskId) override; @@ -595,19 +595,19 @@ public: void FollowerUpdate(THolder<TEvTablet::TFUpdateBody> update) override; void FollowerAuxUpdate(TString upd) override; - void RenderHtmlPage(NMon::TEvRemoteHttpInfo::TPtr &ev) const override; - void RenderHtmlCounters(NMon::TEvRemoteHttpInfo::TPtr &ev) const override; + void RenderHtmlPage(NMon::TEvRemoteHttpInfo::TPtr &ev) const override; + void RenderHtmlCounters(NMon::TEvRemoteHttpInfo::TPtr &ev) const override; void RenderHtmlDb(NMon::TEvRemoteHttpInfo::TPtr &ev, const TActorContext &ctx) const override; - void GetTabletCounters(TEvTablet::TEvGetCounters::TPtr &ev) override; + void GetTabletCounters(TEvTablet::TEvGetCounters::TPtr &ev) override; - void UpdateConfig(TEvTablet::TEvUpdateConfig::TPtr &ev) override; + void UpdateConfig(TEvTablet::TEvUpdateConfig::TPtr &ev) override; void SendUserAuxUpdateToFollowers(TString upd, const TActorContext &ctx) override; THashMap<TLogoBlobID, TVector<ui64>> GetBorrowedParts() const override; const TExecutorStats& GetStats() const override; - NMetrics::TResourceMetrics* GetResourceMetrics() const override; + NMetrics::TResourceMetrics* GetResourceMetrics() const override; void RegisterExternalTabletCounters(TAutoPtr<TTabletCountersBase> appCounters) override; @@ -628,7 +628,7 @@ public: const NTable::TScheme& Scheme() const noexcept override; ui64 TabletId() const { return Owner->TabletID(); } - float GetRejectProbability() const override; + float GetRejectProbability() const override; TActorId GetLauncher() const { return Launcher; } }; diff --git a/ydb/core/tablet_flat/flat_executor.proto b/ydb/core/tablet_flat/flat_executor.proto index 7758812187..2981cb65a0 100644 --- a/ydb/core/tablet_flat/flat_executor.proto +++ b/ydb/core/tablet_flat/flat_executor.proto @@ -6,59 +6,59 @@ package NKikimrExecutorFlat; option java_package = "ru.yandex.kikimr.proto"; message TLargeGlobId { - // This is the correct way of doing for what StorageInfo is now used. - - required uint32 Group = 1; - required uint32 Bytes = 2; - required NKikimrProto.TLogoBlobID Lead = 3; -} - + // This is the correct way of doing for what StorageInfo is now used. + + required uint32 Group = 1; + required uint32 Bytes = 2; + required NKikimrProto.TLogoBlobID Lead = 3; +} + message TPageCollection { - message TPage { - required uint32 Id = 1; - required bytes Body = 2; - } - + message TPage { + required uint32 Id = 1; + required bytes Body = 2; + } + repeated NKikimrProto.TLogoBlobID MetaId = 1; // Replaced by TLargeGlobId - + optional TLargeGlobId LargeGlobId = 6; - + // Page collection may be serialized with some meta blobs (its meanings is defined - // at application level), may be used for quick cooking on a receiver side, + // at application level), may be used for quick cooking on a receiver side, // i.e. without extra blob loadings at page collection warming stage. This kind of // packed page collection is called HotBundle. - - optional bytes Meta = 2; - repeated TPage Pages = 5; -} - -message TBundle { + + optional bytes Meta = 2; + repeated TPage Pages = 5; +} + +message TBundle { // Bundle, a generic page collections ordered sequence with properties: - // + // // * PageCollections bundle have to be composed at least with one page collection. // * Bundle Id is TLogoBlobID of first meta blob of first page collection. // * Bundle holds an opaque entity in general indivisible by page collections to - // two or more bundles producing new valid entities of the same kind. - + // two or more bundles producing new valid entities of the same kind. + repeated TPageCollection PageCollections = 2; + + // Legacy opaque can only be used for non-empty screen in TPart bundles, + + optional bytes Legacy = 3; - // Legacy opaque can only be used for non-empty screen in TPart bundles, + // Attached to bundle app. defined data that cannot be placed within parts. - optional bytes Legacy = 3; - - // Attached to bundle app. defined data that cannot be placed within parts. - - optional bytes Opaque = 4; + optional bytes Opaque = 4; // An optional epoch used for ordering bundles in logical time optional int64 Epoch = 5; -} - +} + message TBundleChange { optional NKikimrProto.TLogoBlobID Label = 1; - optional bytes Legacy = 2; - optional bytes Opaque = 3; + optional bytes Legacy = 2; + optional bytes Opaque = 3; } message TBundleDelta { @@ -83,22 +83,22 @@ message TTxStatus { optional bytes Data = 3; } -message TEvolution { - required uint32 Tail = 1; - required uint32 Head = 2; -} - +message TEvolution { + required uint32 Tail = 1; + required uint32 Head = 2; +} + message TLogTableSnap { optional uint32 Table = 1; - repeated NKikimrProto.TLogoBlobID DbPartMetaInfoBody = 2; // Legacy, replaced with Bundles - optional uint32 Legacy0_ = 3; - optional uint32 Legacy1_ = 4; - optional uint32 Legacy2_ = 5; - optional uint32 Legacy3_ = 6; + repeated NKikimrProto.TLogoBlobID DbPartMetaInfoBody = 2; // Legacy, replaced with Bundles + optional uint32 Legacy0_ = 3; + optional uint32 Legacy1_ = 4; + optional uint32 Legacy2_ = 5; + optional uint32 Legacy3_ = 6; optional uint32 CompactionLevel = 7; - - repeated TBundle Bundles = 8; + + repeated TBundle Bundles = 8; } message TLogTxStatusSnap { @@ -143,13 +143,13 @@ message TBorrowedPart { repeated NKikimrProto.TLogoBlobID LoanKeepList = 13; } -message TSnapWaste { - optional uint64 Since = 1; // Stamp of waste accounting age - optional uint64 Level = 2; // Total bytes keeping by tablet - optional uint64 Keep = 3; // Total bytes designed for KEEP flag - optional uint64 Drop = 4; // Total dropped blobs designed for KEEP. -} - +message TSnapWaste { + optional uint64 Since = 1; // Stamp of waste accounting age + optional uint64 Level = 2; // Total bytes keeping by tablet + optional uint64 Keep = 3; // Total bytes designed for KEEP flag + optional uint64 Drop = 4; // Total dropped blobs designed for KEEP. +} + message TCompactionState { message TKeyValue { optional uint64 Key = 1; @@ -182,11 +182,11 @@ message TLogSnapshot { repeated NKikimrProto.TLogoBlobID GcSnapDiscovered = 12; repeated NKikimrProto.TLogoBlobID GcSnapLeft = 13; repeated TGcChannelBarrierInfo GcBarrierInfo = 14; - - optional bytes Legacy0_ = 15; - optional TEvolution Version = 16; - optional uint64 Serial = 17; // db change serial at moment of snapshot - optional TSnapWaste Waste = 18; + + optional bytes Legacy0_ = 15; + optional TEvolution Version = 16; + optional uint64 Serial = 17; // db change serial at moment of snapshot + optional TSnapWaste Waste = 18; repeated TCompactionState CompactionStates = 19; repeated TRowVersionState RowVersionStates = 20; @@ -198,7 +198,7 @@ message TTablePartSwitch { optional TLogMemSnap TableSnapshoted = 2; optional uint32 TableId = 3; - repeated NKikimrProto.TLogoBlobID LeavingBundles = 10; + repeated NKikimrProto.TLogoBlobID LeavingBundles = 10; repeated TBundleChange ChangedBundles = 11; optional TCompactionState CompactionChanges = 12; repeated TBundleDelta BundleDeltas = 13; diff --git a/ydb/core/tablet_flat/flat_executor_bootlogic.cpp b/ydb/core/tablet_flat/flat_executor_bootlogic.cpp index cf72960f9c..12dc1d252f 100644 --- a/ydb/core/tablet_flat/flat_executor_bootlogic.cpp +++ b/ydb/core/tablet_flat/flat_executor_bootlogic.cpp @@ -1,16 +1,16 @@ #include "flat_executor_bootlogic.h" -#include "flat_boot_env.h" -#include "flat_boot_blobs.h" -#include "flat_boot_back.h" -#include "flat_boot_stages.h" +#include "flat_boot_env.h" +#include "flat_boot_blobs.h" +#include "flat_boot_back.h" +#include "flat_boot_stages.h" #include "flat_exec_commit_mgr.h" -#include "flat_bio_actor.h" -#include "flat_bio_events.h" -#include "flat_sausage_chop.h" -#include "logic_snap_waste.h" -#include "logic_snap_main.h" -#include "util_fmt_logger.h" -#include "util_fmt_basic.h" +#include "flat_bio_actor.h" +#include "flat_bio_events.h" +#include "flat_sausage_chop.h" +#include "logic_snap_waste.h" +#include "logic_snap_main.h" +#include "util_fmt_logger.h" +#include "util_fmt_basic.h" #include "shared_sausagecache.h" #include <ydb/core/base/appdata.h> #include <ydb/core/base/counters.h> @@ -20,42 +20,42 @@ namespace NKikimr { namespace NTabletFlatExecutor { NBoot::TLoadBlobs::TLoadBlobs(IStep *owner, NPageCollection::TLargeGlobId largeGlobId, ui64 cookie) - : IStep(owner, NBoot::EStep::Blobs) - , Cookie(cookie) + : IStep(owner, NBoot::EStep::Blobs) + , Cookie(cookie) , LargeGlobId(largeGlobId) , State(LargeGlobId) -{ - Logic->LoadEntry(this); -} - +{ + Logic->LoadEntry(this); +} + TExecutorBootLogic::TExecutorBootLogic(IOps *ops, const TActorId &self, TTabletStorageInfo *info, ui64 maxBytesInFly) - : Ops(ops) - , SelfId(self) - , Info(info) + : Ops(ops) + , SelfId(self) + , Info(info) , GroupResolveCachedChannel(Max<ui32>()) , GroupResolveCachedGeneration(Max<ui32>()) , GroupResolveCachedGroup(Max<ui32>()) -{ +{ LoadBlobQueue.Config.MaxBytesInFly = maxBytesInFly; -} - +} + TExecutorBootLogic::~TExecutorBootLogic() -{ +{ LoadBlobQueue.Clear(); - Loads.clear(); - EntriesToLoad.clear(); - - Steps->Execute(); /* should flush all jobs in internal queue */ - - Y_VERIFY(Steps->Alone(), "Bootlogic is still has pending IStep()s"); -} - -void TExecutorBootLogic::Describe(IOutputStream &out) const noexcept -{ - return Steps->Describe(out); -} - + Loads.clear(); + EntriesToLoad.clear(); + + Steps->Execute(); /* should flush all jobs in internal queue */ + + Y_VERIFY(Steps->Alone(), "Bootlogic is still has pending IStep()s"); +} + +void TExecutorBootLogic::Describe(IOutputStream &out) const noexcept +{ + return Steps->Describe(out); +} + TExecutorBootLogic::EOpResult TExecutorBootLogic::ReceiveFollowerBoot( TEvTablet::TEvFBoot::TPtr &ev, TExecutorCaches &&caches) @@ -73,7 +73,7 @@ TExecutorBootLogic::EOpResult TExecutorBootLogic::ReceiveFollowerBoot( if (auto logl = Steps->Logger()->Log(ELnLev::Debug)) logl << NFmt::Do(State()) << " start follower from log" - << " snapshot " << State().Generation << ":" << update->Step; + << " snapshot " << State().Generation << ":" << update->Step; TString body; TVector<TLogoBlobID> logo; @@ -86,14 +86,14 @@ TExecutorBootLogic::EOpResult TExecutorBootLogic::ReceiveFollowerBoot( const auto span = NPageCollection::TGroupBlobsByCookie(logo).Do(); const auto largeGlobId = NPageCollection::TGroupBlobsByCookie::ToLargeGlobId(span, GetBSGroupFor(logo[0])); - + Y_VERIFY(span.size() == update->References.size()); Y_VERIFY(TCookie(logo[0].Cookie()).Type() == TCookie::EType::Log); Y_VERIFY(largeGlobId, "Cannot make TLargeGlobId for snapshot"); - + Steps->Spawn<NBoot::TStages>(nullptr, new NBoot::TBody{ largeGlobId, std::move(body) }); } - + Steps->Execute(); return CheckCompletion(); @@ -104,64 +104,64 @@ TExecutorBootLogic::EOpResult TExecutorBootLogic::ReceiveBoot( TExecutorCaches &&caches) { PrepareEnv(false, ev->Get()->Generation, std::move(caches)); - - Steps->Spawn<NBoot::TStages>(std::move(ev->Get()->DependencyGraph), nullptr); + + Steps->Spawn<NBoot::TStages>(std::move(ev->Get()->DependencyGraph), nullptr); Steps->Execute(); return CheckCompletion(); } void TExecutorBootLogic::PrepareEnv(bool follower, ui32 gen, TExecutorCaches caches) noexcept -{ - BootStartTime = TAppData::TimeProvider->Now(); - - auto *sys = TlsActivationContext->ExecutorThread.ActorSystem; - auto *logger = new NUtil::TLogger(sys, NKikimrServices::TABLET_FLATBOOT); - +{ + BootStartTime = TAppData::TimeProvider->Now(); + + auto *sys = TlsActivationContext->ExecutorThread.ActorSystem; + auto *logger = new NUtil::TLogger(sys, NKikimrServices::TABLET_FLATBOOT); + LoadBlobQueue.Config.TabletID = Info->TabletID; LoadBlobQueue.Config.Generation = gen; LoadBlobQueue.Config.Follower = follower; LoadBlobQueue.Config.NoDataCounter = GetServiceCounters(AppData()->Counters, "tablets")->GetCounter("alerts_boot_nodata", true); State_ = new NBoot::TBack(follower, Info->TabletID, gen); - State().Scheme = new NTable::TScheme; + State().Scheme = new NTable::TScheme; State().PageCaches = std::move(caches.PageCaches); State().TxStatusCaches = std::move(caches.TxStatusCaches); - - Steps = new NBoot::TRoot(this, State_.Get(), logger); - - Result_ = new NBoot::TResult; - + + Steps = new NBoot::TRoot(this, State_.Get(), logger); + + Result_ = new NBoot::TResult; + if (follower) { /* Required for TLargeGlobId-less TPart data (Evolution < 12) */ - - Result().Loans = new TExecutorBorrowLogic(nullptr); - } else { + + Result().Loans = new TExecutorBorrowLogic(nullptr); + } else { auto &steppedCookieAllocatorFactory = *(State().SteppedCookieAllocatorFactory = new NBoot::TSteppedCookieAllocatorFactory(*Info, gen)); - - State().Waste = new NSnap::TWaste(gen); + + State().Waste = new NSnap::TWaste(gen); Result().GcLogic = new TExecutorGCLogic(Info, steppedCookieAllocatorFactory.Sys(TCookie::EIdx::GCExt)); Result().Alter = new TLogicAlter(steppedCookieAllocatorFactory.Sys(TCookie::EIdx::Alter)); Result().Loans = new TExecutorBorrowLogic(steppedCookieAllocatorFactory.Sys(TCookie::EIdx::Loan)); - Result().Comp = new TCompactionLogicState(); - - /* The rest of ... are produced on TStages::FinalizeLogicObjects() */ - } -} - + Result().Comp = new TCompactionLogicState(); + + /* The rest of ... are produced on TStages::FinalizeLogicObjects() */ + } +} + void TExecutorBootLogic::LoadEntry(TIntrusivePtr<NBoot::TLoadBlobs> entry) { - if (auto logl = Steps->Logger()->Log(ELnLev::Debug)) { - logl + if (auto logl = Steps->Logger()->Log(ELnLev::Debug)) { + logl << NFmt::Do(State()) << " Loading " << NFmt::Do(entry->LargeGlobId); - } - + } + Y_VERIFY(entry->LargeGlobId, "Support loads only of valid TLargeGlobId units"); Y_VERIFY(entry->Blobs(), "Valid TLargeGlobId unit hasn't been expanded to blobs"); - + const ui32 group = entry->LargeGlobId.Group; - + Y_VERIFY(group != NPageCollection::TLargeGlobId::InvalidGroup, "Got TLargeGlobId without BS group"); - + for (const auto &blobId : entry->Blobs()) { EntriesToLoad[blobId] = entry; LoadBlobQueue.Enqueue(blobId, group, this); @@ -170,9 +170,9 @@ void TExecutorBootLogic::LoadEntry(TIntrusivePtr<NBoot::TLoadBlobs> entry) { NBoot::TSpawned TExecutorBootLogic::LoadPages(NBoot::IStep *step, TAutoPtr<NPageCollection::TFetch> req) { auto success = Loads.insert(std::make_pair(req->PageCollection.Get(), step)).second; - + Y_VERIFY(success, "IPageCollection queued twice for loading"); - + Ops->Send( MakeSharedPageCacheId(), new NSharedCache::TEvRequest( @@ -180,91 +180,91 @@ NBoot::TSpawned TExecutorBootLogic::LoadPages(NBoot::IStep *step, TAutoPtr<NPage req, SelfId), 0, (ui64)EPageCollectionRequest::BootLogic); - + return NBoot::TSpawned(true); -} - -ui32 TExecutorBootLogic::GetBSGroupFor(const TLogoBlobID &logo) const { - auto *info = (logo.TabletID() == Info->TabletID) ? Info.Get() : Result().Loans->StorageInfoFor(logo); - return info->GroupFor(logo.Channel(), logo.Generation()); -} - +} + +ui32 TExecutorBootLogic::GetBSGroupFor(const TLogoBlobID &logo) const { + auto *info = (logo.TabletID() == Info->TabletID) ? Info.Get() : Result().Loans->StorageInfoFor(logo); + return info->GroupFor(logo.Channel(), logo.Generation()); +} + ui32 TExecutorBootLogic::GetBSGroupID(ui32 channel, ui32 generation) { if (generation != GroupResolveCachedGeneration || channel != GroupResolveCachedChannel) { GroupResolveCachedChannel = channel; GroupResolveCachedGeneration = generation; - GroupResolveCachedGroup = Info->GroupFor(channel, generation); + GroupResolveCachedGroup = Info->GroupFor(channel, generation); } return GroupResolveCachedGroup; } -TExecutorBootLogic::EOpResult TExecutorBootLogic::CheckCompletion() -{ +TExecutorBootLogic::EOpResult TExecutorBootLogic::CheckCompletion() +{ if (LoadBlobQueue.SendRequests(SelfId)) return OpResultContinue; Y_VERIFY(EntriesToLoad.empty()); - if (Steps && !Steps->Alone()) - return OpResultContinue; - - if (Loads) + if (Steps && !Steps->Alone()) + return OpResultContinue; + + if (Loads) return OpResultContinue; if (State().Follower || Restored) { - if (auto logl = Steps->Logger()->Log(ELnLev::Info)) { - auto spent = TAppData::TimeProvider->Now() - BootStartTime; - - logl - << NFmt::Do(State()) << " booting completed" - << ", took " << NFmt::TDelay(spent); - } - + if (auto logl = Steps->Logger()->Log(ELnLev::Info)) { + auto spent = TAppData::TimeProvider->Now() - BootStartTime; + + logl + << NFmt::Do(State()) << " booting completed" + << ", took " << NFmt::TDelay(spent); + } + return OpResultComplete; } return OpResultContinue; } -TExecutorBootLogic::EOpResult TExecutorBootLogic::ReceiveRestored(TEvTablet::TEvRestored::TPtr &ev) { +TExecutorBootLogic::EOpResult TExecutorBootLogic::ReceiveRestored(TEvTablet::TEvRestored::TPtr &ev) { Y_UNUSED(ev); Restored = true; - return CheckCompletion(); + return CheckCompletion(); } void TExecutorBootLogic::OnBlobLoaded(const TLogoBlobID& id, TString body, uintptr_t cookie) { Y_UNUSED(cookie); - + auto it = EntriesToLoad.find(id); Y_VERIFY(it != EntriesToLoad.end(), "OnBlobLoaded with unexpected blob id %s", id.ToString().c_str()); auto entry = std::move(it->second); - + EntriesToLoad.erase(it); entry->Feed(id, std::move(body)); entry.Reset(); - + Steps->Execute(); } - + TExecutorBootLogic::EOpResult TExecutorBootLogic::Receive(::NActors::IEventHandle &ev) { if (auto *msg = ev.CastAsLocal<TEvBlobStorage::TEvGetResult>()) { if (!LoadBlobQueue.ProcessResult(msg)) return OpResultBroken; - + } else if (auto *msg = ev.CastAsLocal<NSharedCache::TEvResult>()) { if (EPageCollectionRequest(ev.Cookie) != EPageCollectionRequest::BootLogic) return OpResultUnhandled; - auto it = Loads.find(msg->Origin.Get()); - if (it == Loads.end()) // could receive outdated results + auto it = Loads.find(msg->Origin.Get()); + if (it == Loads.end()) // could receive outdated results return OpResultUnhandled; - + // Remove step from loads first (so HandleBio may request more pages) auto step = std::move(it->second); Loads.erase(it); @@ -277,30 +277,30 @@ TExecutorBootLogic::EOpResult TExecutorBootLogic::Receive(::NActors::IEventHandl return OpResultBroken; step.Drop(); - Steps->Execute(); - } else { + Steps->Execute(); + } else { return OpResultUnhandled; } - - return CheckCompletion(); + + return CheckCompletion(); } -TAutoPtr<NBoot::TResult> TExecutorBootLogic::ExtractState() noexcept { - Y_VERIFY(Result_->Database, "Looks like booting hasn't been done"); - return Result_; +TAutoPtr<NBoot::TResult> TExecutorBootLogic::ExtractState() noexcept { + Y_VERIFY(Result_->Database, "Looks like booting hasn't been done"); + return Result_; } -void TExecutorBootLogic::Cancel() { +void TExecutorBootLogic::Cancel() { } void TExecutorBootLogic::FollowersSyncComplete() { - Y_VERIFY(Result_); - Y_VERIFY(Result().GcLogic); + Y_VERIFY(Result_); + Y_VERIFY(Result().GcLogic); Result().GcLogic->FollowersSyncComplete(true); } TExecutorCaches TExecutorBootLogic::DetachCaches() { - if (Result_) { + if (Result_) { for (auto &x : Result().PageCaches) State().PageCaches[x->Id] = x; } diff --git a/ydb/core/tablet_flat/flat_executor_bootlogic.h b/ydb/core/tablet_flat/flat_executor_bootlogic.h index 34edb2d6b4..f6e00810bb 100644 --- a/ydb/core/tablet_flat/flat_executor_bootlogic.h +++ b/ydb/core/tablet_flat/flat_executor_bootlogic.h @@ -1,7 +1,7 @@ #pragma once #include "defs.h" #include "flat_executor.h" -#include "flat_boot_cookie.h" +#include "flat_boot_cookie.h" #include "flat_boot_util.h" #include "flat_load_blob_queue.h" @@ -9,23 +9,23 @@ namespace NKikimr { namespace NTabletFlatExecutor { class TCommitManager; - -namespace NBoot { - class IStep; - class TRoot; + +namespace NBoot { + class IStep; + class TRoot; class TBundleLoadStep; - class TRedo; + class TRedo; class TMemTable; - class TStages; - class TGCLog; - class TLoans; - class TAlter; - class TTurns; - class TSnap; - class TLoadBlobs; - struct TBack; - - struct TResult { + class TStages; + class TGCLog; + class TLoans; + class TAlter; + class TTurns; + class TSnap; + class TLoadBlobs; + struct TBack; + + struct TResult { TAutoPtr<NTable::TDatabase> Database; TAutoPtr<TCommitManager> CommitManager; TAutoPtr<TLogicSnap> Snap; @@ -35,24 +35,24 @@ namespace NBoot { TAutoPtr<TCompactionLogicState> Comp; TAutoPtr<TExecutorBorrowLogic> Loans; THashMap<ui32, NTable::TRowVersionRanges> RemovedRowVersions; - + TVector<TIntrusivePtr<TPrivatePageCache::TInfo>> PageCaches; - }; -} - + }; +} + class TExecutorBootLogic : private ILoadBlob { friend class NBoot::TBundleLoadStep; - friend class NBoot::TRedo; - friend class NBoot::TStages; - friend class NBoot::TLoadBlobs; + friend class NBoot::TRedo; + friend class NBoot::TStages; + friend class NBoot::TLoadBlobs; friend class NBoot::TMemTable; - friend class NBoot::TGCLog; - friend class NBoot::TLoans; - friend class NBoot::TAlter; - friend class NBoot::TTurns; - friend class NBoot::TSnap; + friend class NBoot::TGCLog; + friend class NBoot::TLoans; + friend class NBoot::TAlter; + friend class NBoot::TTurns; + friend class NBoot::TSnap; public: enum EOpResult { OpResultUnhandled, @@ -62,19 +62,19 @@ public: }; private: - using ELnLev = NUtil::ELnLev; - using IOps = NActors::IActorOps; - using TCookie = NBoot::TCookie; + using ELnLev = NUtil::ELnLev; + using IOps = NActors::IActorOps; + using TCookie = NBoot::TCookie; private: - bool Restored = false; + bool Restored = false; - IOps * const Ops = nullptr; + IOps * const Ops = nullptr; const TActorId SelfId; - TAutoPtr<NBoot::TBack> State_; - TAutoPtr<NBoot::TResult> Result_; - TAutoPtr<NBoot::TRoot> Steps; - + TAutoPtr<NBoot::TBack> State_; + TAutoPtr<NBoot::TResult> Result_; + TAutoPtr<NBoot::TRoot> Steps; + TInstant BootStartTime; const TIntrusiveConstPtr<TTabletStorageInfo> Info; @@ -88,33 +88,33 @@ private: ui32 GroupResolveCachedGeneration; ui32 GroupResolveCachedGroup; - EOpResult CheckCompletion(); + EOpResult CheckCompletion(); void PrepareEnv(bool follower, ui32 generation, TExecutorCaches caches) noexcept; - ui32 GetBSGroupFor(const TLogoBlobID &logo) const; + ui32 GetBSGroupFor(const TLogoBlobID &logo) const; ui32 GetBSGroupID(ui32 channel, ui32 generation); void LoadEntry(TIntrusivePtr<NBoot::TLoadBlobs>); NBoot::TSpawned LoadPages(NBoot::IStep*, TAutoPtr<NPageCollection::TFetch> req); - + void OnBlobLoaded(const TLogoBlobID& id, TString body, uintptr_t cookie) override; - inline NBoot::TResult& Result() const noexcept { return *Result_; } - inline NBoot::TBack& State() const noexcept { return *State_; } - + inline NBoot::TResult& Result() const noexcept { return *Result_; } + inline NBoot::TBack& State() const noexcept { return *State_; } + public: TExecutorBootLogic(IOps*, const TActorId&, TTabletStorageInfo *info, ui64 maxBytesInFly); ~TExecutorBootLogic(); - void Describe(IOutputStream&) const noexcept; + void Describe(IOutputStream&) const noexcept; EOpResult ReceiveBoot(TEvTablet::TEvBoot::TPtr &ev, TExecutorCaches &&caches); EOpResult ReceiveFollowerBoot(TEvTablet::TEvFBoot::TPtr &ev, TExecutorCaches &&caches); - EOpResult ReceiveRestored(TEvTablet::TEvRestored::TPtr &ev); - EOpResult Receive(::NActors::IEventHandle&); + EOpResult ReceiveRestored(TEvTablet::TEvRestored::TPtr &ev); + EOpResult Receive(::NActors::IEventHandle&); void FollowersSyncComplete(); - void Cancel(); + void Cancel(); - TAutoPtr<NBoot::TResult> ExtractState() noexcept; + TAutoPtr<NBoot::TResult> ExtractState() noexcept; TExecutorCaches DetachCaches(); }; diff --git a/ydb/core/tablet_flat/flat_executor_borrowlogic.cpp b/ydb/core/tablet_flat/flat_executor_borrowlogic.cpp index bd52264b10..77eaaf69d9 100644 --- a/ydb/core/tablet_flat/flat_executor_borrowlogic.cpp +++ b/ydb/core/tablet_flat/flat_executor_borrowlogic.cpp @@ -1,5 +1,5 @@ #include "flat_executor_borrowlogic.h" -#include "flat_bio_eggs.h" +#include "flat_bio_eggs.h" #include <library/cpp/monlib/service/pages/templates.h> #include <util/generic/xrange.h> @@ -9,8 +9,8 @@ namespace NKikimr { namespace NTabletFlatExecutor { TExecutorBorrowLogic::TExecutorBorrowLogic(TAutoPtr<NPageCollection::TSteppedCookieAllocator> cookies) - : SelfTabletId(cookies ? cookies->Tablet : 0) - , Cookies(cookies) + : SelfTabletId(cookies ? cookies->Tablet : 0) + , Cookies(cookies) , Slicer(1, Cookies.Get(), NBlockIO::BlockSize) , HasFlag(false) {} @@ -48,9 +48,9 @@ void TExecutorBorrowLogic::FillBorrowProto( if (storedInfo.LoanInfo.Lender) { proto.SetLender(storedInfo.LoanInfo.Lender); - if (auto *info = storedInfo.LoanInfo.StorageInfo.Get()) - TabletStorageInfoToProto(*info, proto.AddStorageInfo()); - + if (auto *info = storedInfo.LoanInfo.StorageInfo.Get()) + TabletStorageInfoToProto(*info, proto.AddStorageInfo()); + if (storedInfo.LoanInfo.Collected) { proto.SetLoanCollected(true); if (storedInfo.LoanInfo.Keep) { @@ -62,28 +62,28 @@ void TExecutorBorrowLogic::FillBorrowProto( } } -void TExecutorBorrowLogic::StoreBorrowProto( +void TExecutorBorrowLogic::StoreBorrowProto( const TLogoBlobID &metaId, - TBorrowedPartInfo &info, - TLogCommit *commit) + TBorrowedPartInfo &info, + TLogCommit *commit) { - Cookies->Switch(commit->Step, false /* could reuse step */); - + Cookies->Switch(commit->Step, false /* could reuse step */); + NKikimrExecutorFlat::TBorrowedPart proto; - FillBorrowProto(metaId, proto, info); + FillBorrowProto(metaId, proto, info); - auto glob = Slicer.One(commit->Refs, proto.SerializeAsString(), true); + auto glob = Slicer.One(commit->Refs, proto.SerializeAsString(), true); + + commit->GcDelta.Created.push_back(glob.Logo); - commit->GcDelta.Created.push_back(glob.Logo); - - if (auto gone = std::exchange(info.BorrowBlobId, glob.Logo)) - Garbage.push_back(gone); + if (auto gone = std::exchange(info.BorrowBlobId, glob.Logo)) + Garbage.push_back(gone); } bool TExecutorBorrowLogic::BundlePartiallyCompacted( const NTable::IBundle &bundle, const NTable::NFwd::TSieve &sieve, - TLogCommit *commit) + TLogCommit *commit) { const TLogoBlobID &metaId = bundle.BundleId(); TBorrowedPartInfo *info = BorrowedInfo.FindPtr(metaId); @@ -108,32 +108,32 @@ bool TExecutorBorrowLogic::BundlePartiallyCompacted( Y_VERIFY(commit->WaitFollowerGcAck); if (haveChanges) { - StoreBorrowProto(metaId, *info, commit); + StoreBorrowProto(metaId, *info, commit); } // must be loaned or borrowed, cannot collect blobs return false; } -bool TExecutorBorrowLogic::BundleCompacted( - const NTable::IBundle &bundle, - const NTable::NFwd::TSieve &sieve, - TLogCommit *commit) +bool TExecutorBorrowLogic::BundleCompacted( + const NTable::IBundle &bundle, + const NTable::NFwd::TSieve &sieve, + TLogCommit *commit) { - const TLogoBlobID &metaId = bundle.BundleId(); + const TLogoBlobID &metaId = bundle.BundleId(); TBorrowedPartInfo *info = BorrowedInfo.FindPtr(metaId); if (info == nullptr) return true; - // 1. if bundle borrowed - keep blobs non-collected + // 1. if bundle borrowed - keep blobs non-collected if (info->BorrowInfo.FullBorrow) { Y_VERIFY(!info->BorrowInfo.HasKeep(bundle.BundleId()), "Trying to compact the same page collection twice"); if (SelfTabletId == metaId.TabletID()) { sieve.MaterializeTo(info->BorrowInfo.Keep); - bundle.SaveAllBlobIdsTo(info->BorrowInfo.Keep); - + bundle.SaveAllBlobIdsTo(info->BorrowInfo.Keep); + std::sort(info->BorrowInfo.Keep.begin(), info->BorrowInfo.Keep.end()); auto end = std::unique(info->BorrowInfo.Keep.begin(), info->BorrowInfo.Keep.end()); Y_VERIFY(end == info->BorrowInfo.Keep.end(), @@ -146,13 +146,13 @@ bool TExecutorBorrowLogic::BundleCompacted( info->LoanInfo.Collected = true; } - CheckLoanCompletion(metaId, *info, commit->Step); + CheckLoanCompletion(metaId, *info, commit->Step); Y_VERIFY(commit->WaitFollowerGcAck); // must be loaned or borrowed (otherwise would be not on list) // in this case - changes must be propagated to lender before cleanup - // in that case - loaner must detach from borrowed bundle and we must keep blobs non-collect awhile - StoreBorrowProto(metaId, *info, commit); + // in that case - loaner must detach from borrowed bundle and we must keep blobs non-collect awhile + StoreBorrowProto(metaId, *info, commit); return false; } @@ -218,12 +218,12 @@ bool TExecutorBorrowLogic::BundleCompacted( return false; } -void TExecutorBorrowLogic::BorrowBundle( - const TLogoBlobID &bundleId, +void TExecutorBorrowLogic::BorrowBundle( + const TLogoBlobID &bundleId, const TSet<ui64> &loaners, - TLogCommit *commit) + TLogCommit *commit) { - auto storedInfoItPair = BorrowedInfo.insert(std::make_pair(bundleId, TBorrowedPartInfo())); + auto storedInfoItPair = BorrowedInfo.insert(std::make_pair(bundleId, TBorrowedPartInfo())); HasFlag = true; TBorrowedPartInfo &storedInfo = storedInfoItPair.first->second; @@ -249,24 +249,24 @@ void TExecutorBorrowLogic::BorrowBundle( //Y_VERIFY(std::adjacent_find(fullBorrow.begin(), fullBorrow.end()) == fullBorrow.end()); fullBorrow.erase(std::unique(fullBorrow.begin(), fullBorrow.end()), fullBorrow.end()); - StoreBorrowProto(bundleId, storedInfo, commit); + StoreBorrowProto(bundleId, storedInfo, commit); } -void TExecutorBorrowLogic::LoanBundle( - const TLogoBlobID &bundleId, +void TExecutorBorrowLogic::LoanBundle( + const TLogoBlobID &bundleId, TPageCollectionTxEnv::TLoanBundle &loaned, - TLogCommit *commit) + TLogCommit *commit) { - auto storedInfoItPair = BorrowedInfo.insert(std::make_pair(bundleId, TBorrowedPartInfo())); + auto storedInfoItPair = BorrowedInfo.insert(std::make_pair(bundleId, TBorrowedPartInfo())); Y_VERIFY(storedInfoItPair.second, "must not back-borrow parts at %" PRIu64 " part owner %" PRIu64 " existing loan from %" PRIu64 " new loan from %" PRIu64, SelfTabletId, bundleId.TabletID(), storedInfoItPair.first->second.LoanInfo.Lender, loaned.Lender); HasFlag = true; TBorrowedPartInfo &storedInfo = storedInfoItPair.first->second; - storedInfo.LoanInfo.Lender = loaned.Lender; + storedInfo.LoanInfo.Lender = loaned.Lender; - StoreBorrowProto(bundleId, storedInfo, commit); + StoreBorrowProto(bundleId, storedInfo, commit); } void TExecutorBorrowLogic::LoanTxStatus( @@ -286,16 +286,16 @@ void TExecutorBorrowLogic::LoanTxStatus( StoreBorrowProto(bundleId, storedInfo, commit); } -void TExecutorBorrowLogic::SnapToLog(NKikimrExecutorFlat::TLogSnapshot &snap, TLogCommit &commit) -{ - snap.MutableBorrowInfoIds()->Reserve(BorrowedInfo.size()); +void TExecutorBorrowLogic::SnapToLog(NKikimrExecutorFlat::TLogSnapshot &snap, TLogCommit &commit) +{ + snap.MutableBorrowInfoIds()->Reserve(BorrowedInfo.size()); for (auto &xpair : BorrowedInfo) - LogoBlobIDFromLogoBlobID(xpair.second.BorrowBlobId, snap.AddBorrowInfoIds()); + LogoBlobIDFromLogoBlobID(xpair.second.BorrowBlobId, snap.AddBorrowInfoIds()); - commit.GcDelta.Deleted.insert( - commit.GcDelta.Deleted.end(), Garbage.begin(), Garbage.end()); - - Garbage.clear(); + commit.GcDelta.Deleted.insert( + commit.GcDelta.Deleted.end(), Garbage.begin(), Garbage.end()); + + Garbage.clear(); } const THashMap<TLogoBlobID, TCompactedPartLoans>* TExecutorBorrowLogic::GetCompactedLoansList() { @@ -352,14 +352,14 @@ bool TExecutorBorrowLogic::SetGcBarrier(ui32 step) { return somethingChanged; } -void TExecutorBorrowLogic::UpdateBorrow( +void TExecutorBorrowLogic::UpdateBorrow( const TLogoBlobID &metaInfoId, TPageCollectionTxEnv::TBorrowUpdate &borrowUpdate, - TLogCommit *commit) + TLogCommit *commit) { auto storedInfoIt = BorrowedInfo.find(metaInfoId); if (storedInfoIt == BorrowedInfo.end()) - return; + return; bool smthChanged = false; @@ -374,8 +374,8 @@ void TExecutorBorrowLogic::UpdateBorrow( if (storedInfo.BorrowInfo.FullBorrow.size() == 1) { TVector<ui64>().swap(storedInfo.BorrowInfo.FullBorrow); if (storedInfo.BorrowInfo.Keep) { - commit->GcDelta.Deleted.insert( - commit->GcDelta.Deleted.end(), + commit->GcDelta.Deleted.insert( + commit->GcDelta.Deleted.end(), storedInfo.BorrowInfo.Keep.begin(), storedInfo.BorrowInfo.Keep.end()); TVector<TLogoBlobID>().swap(storedInfo.BorrowInfo.Keep); @@ -388,43 +388,43 @@ void TExecutorBorrowLogic::UpdateBorrow( } if (!smthChanged) // if nothing changes - nothing to change - return; + return; if (metaInfoId.TabletID() == SelfTabletId) { // could not be loaned, so if complete - could be erased - StoreBorrowProto(metaInfoId, storedInfo, commit); + StoreBorrowProto(metaInfoId, storedInfo, commit); if (storedInfo.BorrowInfo.FullBorrow.empty()) { - Garbage.push_back(storedInfo.BorrowBlobId); + Garbage.push_back(storedInfo.BorrowBlobId); BorrowedInfo.erase(storedInfoIt); HasFlag = !BorrowedInfo.empty(); } } else { // if not local - must be loaned - CheckLoanCompletion(metaInfoId, storedInfo, commit->Step); - StoreBorrowProto(metaInfoId, storedInfo, commit); + CheckLoanCompletion(metaInfoId, storedInfo, commit->Step); + StoreBorrowProto(metaInfoId, storedInfo, commit); Y_VERIFY(commit->WaitFollowerGcAck); } } -void TExecutorBorrowLogic::ConfirmUpdateLoan( +void TExecutorBorrowLogic::ConfirmUpdateLoan( const TLogoBlobID &metaInfoId, const TLogoBlobID &borrowId, - TLogCommit *commit) + TLogCommit *commit) { auto storedInfoIt = BorrowedInfo.find(metaInfoId); if (storedInfoIt == BorrowedInfo.end()) - return; + return; Y_UNUSED(borrowId); TBorrowedPartInfo &storedInfo = storedInfoIt->second; //if (storedInfo.BorrowBlobId != borrowId) - // return; + // return; //if (storedInfo.LoanInfo.Lender == 0) // already confirmed, nothing to update - // return; + // return; Y_VERIFY(storedInfo.LoanInfo.Collected, "must not stop loan for non-collected parts"); Y_VERIFY(!storedInfo.BorrowInfo.FullBorrow, "must not stop loan for borrowed parts"); @@ -433,9 +433,9 @@ void TExecutorBorrowLogic::ConfirmUpdateLoan( // so naive approach would not work storedInfo.LoanInfo.Lender = 0; - StoreBorrowProto(metaInfoId, storedInfo, commit); + StoreBorrowProto(metaInfoId, storedInfo, commit); - Garbage.push_back(storedInfo.BorrowBlobId); + Garbage.push_back(storedInfo.BorrowBlobId); BorrowedInfo.erase(storedInfoIt); CompactedPartLoans.erase(metaInfoId); @@ -451,12 +451,12 @@ void TExecutorBorrowLogic::RestoreFollowerBorrowedInfo(const TLogoBlobID &blobId TBorrowedPartInfo &storedInfo = storedInfoItPair.first->second; storedInfo.LoanInfo.Lender = proto.GetLender(); - - if (proto.StorageInfoSize() > 0) { - Y_VERIFY(proto.StorageInfoSize() == 1); + + if (proto.StorageInfoSize() > 0) { + Y_VERIFY(proto.StorageInfoSize() == 1); storedInfo.LoanInfo.StorageInfo = TabletStorageInfoFromProto(proto.GetStorageInfo(0)); - UpdateStorageInfo(storedInfo.LoanInfo.StorageInfo.Get()); - } + UpdateStorageInfo(storedInfo.LoanInfo.StorageInfo.Get()); + } } // as part switch could be pending - we could not drop info right now @@ -471,7 +471,7 @@ void TExecutorBorrowLogic::RestoreBorrowedInfo(const TLogoBlobID &blobId, const if (!storedInfoItPair.second) { Y_VERIFY(blobId > storedInfo.BorrowBlobId); - Garbage.push_back(storedInfo.BorrowBlobId); + Garbage.push_back(storedInfo.BorrowBlobId); KeepBytes -= storedInfo.BorrowInfo.KeepBytes; storedInfo = TBorrowedPartInfo(); } @@ -496,12 +496,12 @@ void TExecutorBorrowLogic::RestoreBorrowedInfo(const TLogoBlobID &blobId, const if (proto.HasLender()) { storedInfo.LoanInfo.Lender = proto.GetLender(); - - if (proto.StorageInfoSize() > 0) { - Y_VERIFY(proto.StorageInfoSize() == 1); + + if (proto.StorageInfoSize() > 0) { + Y_VERIFY(proto.StorageInfoSize() == 1); storedInfo.LoanInfo.StorageInfo = TabletStorageInfoFromProto(proto.GetStorageInfo(0)); - UpdateStorageInfo(storedInfo.LoanInfo.StorageInfo.Get()); - } + UpdateStorageInfo(storedInfo.LoanInfo.StorageInfo.Get()); + } } storedInfo.LoanInfo.Collected = proto.HasLoanCollected() && proto.GetLoanCollected(); @@ -515,7 +515,7 @@ void TExecutorBorrowLogic::RestoreBorrowedInfo(const TLogoBlobID &blobId, const // todo: partial borrow && !storedInfo.LoanInfo.Lender) { - Garbage.push_back(storedInfo.BorrowBlobId); + Garbage.push_back(storedInfo.BorrowBlobId); BorrowedInfo.erase(storedInfoItPair.first); CompactedPartLoans.erase(metaInfoId); } else { diff --git a/ydb/core/tablet_flat/flat_executor_borrowlogic.h b/ydb/core/tablet_flat/flat_executor_borrowlogic.h index 5d990b49dc..29e0e62f3a 100644 --- a/ydb/core/tablet_flat/flat_executor_borrowlogic.h +++ b/ydb/core/tablet_flat/flat_executor_borrowlogic.h @@ -1,9 +1,9 @@ #pragma once #include "defs.h" -#include "flat_fwd_sieve.h" -#include "flat_exec_commit.h" -#include "flat_executor_tx_env.h" -#include "flat_sausage_slicer.h" +#include "flat_fwd_sieve.h" +#include "flat_exec_commit.h" +#include "flat_executor_tx_env.h" +#include "flat_sausage_slicer.h" #include <ydb/core/tablet_flat/flat_executor.pb.h> namespace NKikimr { @@ -54,7 +54,7 @@ class TExecutorBorrowLogic { }; THashMap<TLogoBlobID, TBorrowedPartInfo> BorrowedInfo; - TDeque<TLogoBlobID> Garbage; + TDeque<TLogoBlobID> Garbage; THashMap<TLogoBlobID, TCompactedPartLoans> CompactedPartLoans; TDeque<TCompactedPart> PendingCompactedPartLoans; @@ -70,10 +70,10 @@ class TExecutorBorrowLogic { NKikimrExecutorFlat::TBorrowedPart &proto, const TBorrowedPartInfo &storedInfo); - void StoreBorrowProto( + void StoreBorrowProto( const TLogoBlobID &metaId, TBorrowedPartInfo &storedInfo, - TLogCommit *commit); + TLogCommit *commit); bool CheckLoanCompletion(const TLogoBlobID &metaId, TBorrowedPartInfo &storedInfo, ui32 step); @@ -93,16 +93,16 @@ public: } // called on lender at moment of sharing part - void BorrowBundle( - const TLogoBlobID &bundleId, + void BorrowBundle( + const TLogoBlobID &bundleId, const TSet<ui64> &loaners, - TLogCommit *commit); + TLogCommit *commit); // called on loaner at moment of attaching part - void LoanBundle( - const TLogoBlobID &bundleId, + void LoanBundle( + const TLogoBlobID &bundleId, TPageCollectionTxEnv::TLoanBundle &loaned, - TLogCommit *commit); + TLogCommit *commit); // called on loaner at moment of attaching part void LoanTxStatus( @@ -111,32 +111,32 @@ public: TLogCommit *commit); // called on lender - void UpdateBorrow( - const TLogoBlobID &bundleId, + void UpdateBorrow( + const TLogoBlobID &bundleId, TPageCollectionTxEnv::TBorrowUpdate &borrowUpdate, - TLogCommit *commit); + TLogCommit *commit); // confirmation for loaner - void ConfirmUpdateLoan( - const TLogoBlobID &bundleId, + void ConfirmUpdateLoan( + const TLogoBlobID &bundleId, const TLogoBlobID &borrowId, - TLogCommit *commit); + TLogCommit *commit); - void SnapToLog(NKikimrExecutorFlat::TLogSnapshot&, TLogCommit&); + void SnapToLog(NKikimrExecutorFlat::TLogSnapshot&, TLogCommit&); // returns true if sieve blobs could be collected // returning false means those blobs are still in use bool BundlePartiallyCompacted( const NTable::IBundle &bundle, const NTable::NFwd::TSieve &sieve, - TLogCommit *commit); + TLogCommit *commit); // returns true if part blobs could be collected // returning false means part is still in use - bool BundleCompacted( - const NTable::IBundle &bundle, - const NTable::NFwd::TSieve &sieve, - TLogCommit *commit); + bool BundleCompacted( + const NTable::IBundle &bundle, + const NTable::NFwd::TSieve &sieve, + TLogCommit *commit); // returns true if bundle blobs could be collected // returns false when part is still in use diff --git a/ydb/core/tablet_flat/flat_executor_compaction_logic.cpp b/ydb/core/tablet_flat/flat_executor_compaction_logic.cpp index 3d699e8f87..7b89d1bea2 100644 --- a/ydb/core/tablet_flat/flat_executor_compaction_logic.cpp +++ b/ydb/core/tablet_flat/flat_executor_compaction_logic.cpp @@ -1,6 +1,6 @@ #include "flat_executor_compaction_logic.h" -#include "flat_exec_broker.h" -#include "flat_dbase_scheme.h" +#include "flat_exec_broker.h" +#include "flat_dbase_scheme.h" #include "flat_comp_create.h" #include <ydb/core/base/appdata.h> @@ -21,12 +21,12 @@ TCompactionLogic::TCompactionLogic(NUtil::ILogger *logger, NTable::IResourceBroker *broker, NTable::ICompactionBackend *backend, TAutoPtr<TCompactionLogicState> state, - TString taskNameSuffix) + TString taskNameSuffix) : Logger(logger) , Broker(broker) , Backend(backend) - , Time(TAppData::TimeProvider.Get()) - , State(state) + , Time(TAppData::TimeProvider.Get()) + , State(state) , TaskNameSuffix(taskNameSuffix) {} @@ -55,7 +55,7 @@ TCompactionLogicState::TSnapshotState TCompactionLogic::SnapToLog(ui32 tableId) return ret; } -void TCompactionLogic::UpdateCompactions() +void TCompactionLogic::UpdateCompactions() { for (auto &tpr : State->Tables) { auto &tableInfo = tpr.second; @@ -63,14 +63,14 @@ void TCompactionLogic::UpdateCompactions() auto &inMem = tableInfo.InMem; if (inMem.State == ECompactionState::PendingBackground) { - auto priority = tableInfo.ComputeBackgroundPriority(inMem, policy, Time->Now()); + auto priority = tableInfo.ComputeBackgroundPriority(inMem, policy, Time->Now()); auto oldPriority = inMem.CompactionTask.Priority; // Avoid task updates in case of small priority changes. if (priority < oldPriority && (oldPriority - priority) >= oldPriority / PRIORITY_UPDATE_FACTOR) { UpdateCompactionTask(policy.BackgroundSnapshotPolicy.ResourceBrokerTask, - priority, inMem.CompactionTask); + priority, inMem.CompactionTask); } } @@ -104,21 +104,21 @@ TVector<TTableCompactionChanges> TCompactionLogic::ApplyChanges() return results; } -void TCompactionLogic::PrepareTableSnapshot(ui32 table, NTable::TSnapEdge edge, TTableSnapshotContext *snapContext) { +void TCompactionLogic::PrepareTableSnapshot(ui32 table, NTable::TSnapEdge edge, TTableSnapshotContext *snapContext) { TCompactionLogicState::TTableInfo *tableInfo = State->Tables.FindPtr(table); Y_VERIFY_DEBUG(tableInfo); TCompactionLogicState::TInMem &inMem = tableInfo->InMem; - Y_VERIFY(edge.TxStamp != Max<ui64>(), "TxStamp of snapshot is undefined"); - - tableInfo->SnapRequests.emplace_back(TCompactionLogicState::TSnapRequest(edge, snapContext)); + Y_VERIFY(edge.TxStamp != Max<ui64>(), "TxStamp of snapshot is undefined"); + tableInfo->SnapRequests.emplace_back(TCompactionLogicState::TSnapRequest(edge, snapContext)); + switch (inMem.State) { case ECompactionState::Free: SubmitCompactionTask(table, 0, tableInfo->Policy->SnapshotResourceBrokerTask, tableInfo->Policy->DefaultTaskPriority, - inMem.CompactionTask); + inMem.CompactionTask); inMem.State = ECompactionState::SnapshotPending; break; case ECompactionState::Pending: @@ -128,7 +128,7 @@ void TCompactionLogic::PrepareTableSnapshot(ui32 table, NTable::TSnapEdge edge, // Replace background compaction with regular snapshot task. UpdateCompactionTask(tableInfo->Policy->SnapshotResourceBrokerTask, tableInfo->Policy->DefaultTaskPriority, - inMem.CompactionTask); + inMem.CompactionTask); inMem.State = ECompactionState::SnapshotPending; break; default: @@ -165,13 +165,13 @@ ui64 TCompactionLogic::PrepareForceCompaction(ui32 table, EForceCompaction mode) SubmitCompactionTask(table, 0, tableInfo->Policy->InMemResourceBrokerTask, tableInfo->Policy->DefaultTaskPriority, - inMem.CompactionTask); + inMem.CompactionTask); inMem.State = ECompactionState::Pending; break; case ECompactionState::PendingBackground: UpdateCompactionTask(tableInfo->Policy->InMemResourceBrokerTask, tableInfo->Policy->DefaultTaskPriority, - inMem.CompactionTask); + inMem.CompactionTask); inMem.State = ECompactionState::Pending; break; default: @@ -363,12 +363,12 @@ void TCompactionLogic::StrategyChanging(TCompactionLogicState::TTableInfo &table } } -void TCompactionLogic::UpdateInMemStatsStep(ui32 table, ui32 steps, ui64 size) { - auto *info = State->Tables.FindPtr(table); - Y_VERIFY(info); - auto &mem = info->InMem; - mem.EstimatedSize = size; - mem.Steps += steps; +void TCompactionLogic::UpdateInMemStatsStep(ui32 table, ui32 steps, ui64 size) { + auto *info = State->Tables.FindPtr(table); + Y_VERIFY(info); + auto &mem = info->InMem; + mem.EstimatedSize = size; + mem.Steps += steps; CheckInMemStats(table); } @@ -385,53 +385,53 @@ void TCompactionLogic::CheckInMemStats(ui32 table) { if (mem.State != ECompactionState::Free && mem.State != ECompactionState::PendingBackground) { - return; + return; } - - if (policy.InMemForceSizeToSnapshot <= mem.EstimatedSize - || policy.InMemForceStepsToSnapshot <= mem.Steps + + if (policy.InMemForceSizeToSnapshot <= mem.EstimatedSize + || policy.InMemForceStepsToSnapshot <= mem.Steps || (policy.InMemSizeToSnapshot <= mem.EstimatedSize && policy.InMemStepsToSnapshot <= mem.Steps)) { // Replace background task or submit a new one. if (mem.State == ECompactionState::PendingBackground) { UpdateCompactionTask(policy.InMemResourceBrokerTask, policy.DefaultTaskPriority, - mem.CompactionTask); + mem.CompactionTask); } else { SubmitCompactionTask(table, 0, policy.InMemResourceBrokerTask, policy.DefaultTaskPriority, - mem.CompactionTask); + mem.CompactionTask); } - mem.State = ECompactionState::Pending; + mem.State = ECompactionState::Pending; } else if (mem.State == ECompactionState::Free && (mem.EstimatedSize > 0 || mem.Steps > 0)) { - auto priority = info->ComputeBackgroundPriority(mem, policy, Time->Now()); + auto priority = info->ComputeBackgroundPriority(mem, policy, Time->Now()); if (priority != BAD_PRIORITY) { SubmitCompactionTask(table, 0, policy.BackgroundSnapshotPolicy.ResourceBrokerTask, - priority, mem.CompactionTask); + priority, mem.CompactionTask); mem.State = ECompactionState::PendingBackground; } - } + } } -void TCompactionLogic::UpdateLogUsage(TArrayRef<const NRedo::TUsage> usage) -{ +void TCompactionLogic::UpdateLogUsage(TArrayRef<const NRedo::TUsage> usage) +{ for (auto &one : usage) { UpdateLogUsage(one); } -} - -void TCompactionLogic::UpdateLogUsage(const NRedo::TUsage &usage) -{ - auto* tableInfo = State->Tables.FindPtr(usage.Table); +} + +void TCompactionLogic::UpdateLogUsage(const NRedo::TUsage &usage) +{ + auto* tableInfo = State->Tables.FindPtr(usage.Table); if (!tableInfo) { // Ignore deleted tables return; } auto& inMem = tableInfo->InMem; - inMem.LogOverheadCount = usage.Items; - inMem.LogOverheadSize = usage.Bytes; + inMem.LogOverheadCount = usage.Items; + inMem.LogOverheadSize = usage.Bytes; if (inMem.State != ECompactionState::Free && inMem.State != ECompactionState::PendingBackground) @@ -447,19 +447,19 @@ void TCompactionLogic::UpdateLogUsage(const NRedo::TUsage &usage) if (inMem.State == ECompactionState::PendingBackground) { UpdateCompactionTask(policy.InMemResourceBrokerTask, policy.DefaultTaskPriority, - inMem.CompactionTask); + inMem.CompactionTask); } else { - SubmitCompactionTask(usage.Table, 0, + SubmitCompactionTask(usage.Table, 0, policy.InMemResourceBrokerTask, policy.DefaultTaskPriority, - inMem.CompactionTask); + inMem.CompactionTask); } inMem.State = ECompactionState::Pending; } } bool TCompactionLogic::BeginMemTableCompaction(ui64 taskId, ui32 tableId) -{ +{ TCompactionLogicState::TTableInfo *tableInfo = State->Tables.FindPtr(tableId); Y_VERIFY(tableInfo, "Unexpected BeginMemTableCompaction(%" PRIu64 ", %" PRIu32 ") for a dropped table", @@ -560,14 +560,14 @@ TCompactionLogic::HandleCompaction( SubmitCompactionTask(tableId, 0, tableInfo->Policy->SnapshotResourceBrokerTask, tableInfo->Policy->DefaultTaskPriority, - inMem.CompactionTask); + inMem.CompactionTask); inMem.State = ECompactionState::SnapshotPending; } else if (tableInfo->ForcedCompactionState == EForcedCompactionState::PendingMem) { // There is another memory compaction request SubmitCompactionTask(tableId, 0, tableInfo->Policy->InMemResourceBrokerTask, tableInfo->Policy->DefaultTaskPriority, - inMem.CompactionTask); + inMem.CompactionTask); inMem.State = ECompactionState::Pending; } @@ -616,11 +616,11 @@ TCompactionLogic::CancelledCompaction( } void TCompactionLogic::BorrowedPart(ui32 tableId, NTable::TPartView partView) { - auto *tableInfo = State->Tables.FindPtr(tableId); + auto *tableInfo = State->Tables.FindPtr(tableId); Y_VERIFY(tableInfo); tableInfo->Strategy->PartMerged(std::move(partView), 255); } - + void TCompactionLogic::BorrowedPart(ui32 tableId, TIntrusiveConstPtr<NTable::TColdPart> part) { auto *tableInfo = State->Tables.FindPtr(tableId); Y_VERIFY(tableInfo); @@ -628,7 +628,7 @@ void TCompactionLogic::BorrowedPart(ui32 tableId, TIntrusiveConstPtr<NTable::TCo } ui32 TCompactionLogic::BorrowedPartLevel() { - return 255; + return 255; } TTableCompactionChanges TCompactionLogic::RemovedParts(ui32 tableId, TArrayRef<const TLogoBlobID> parts) { @@ -645,12 +645,12 @@ void TCompactionLogic::SubmitCompactionTask(ui32 table, ui32 generation, const TString &type, ui32 priority, - TCompactionLogicState::TCompactionTask &task) + TCompactionLogicState::TCompactionTask &task) { Y_VERIFY(generation == 0, "Unexpected gen %" PRIu32 " in compaction logic", generation); task.Priority = priority; - task.SubmissionTimestamp = Time->Now(); + task.SubmissionTimestamp = Time->Now(); TString name = Sprintf("gen%" PRIu32 "-table-%" PRIu32 "-%s", generation, table, TaskNameSuffix.data()); @@ -668,7 +668,7 @@ void TCompactionLogic::SubmitCompactionTask(ui32 table, void TCompactionLogic::UpdateCompactionTask(const TString &type, ui32 priority, - TCompactionLogicState::TCompactionTask &task) + TCompactionLogicState::TCompactionTask &task) { task.Priority = priority; diff --git a/ydb/core/tablet_flat/flat_executor_compaction_logic.h b/ydb/core/tablet_flat/flat_executor_compaction_logic.h index b85a13a19e..0fc1c29dd5 100644 --- a/ydb/core/tablet_flat/flat_executor_compaction_logic.h +++ b/ydb/core/tablet_flat/flat_executor_compaction_logic.h @@ -1,20 +1,20 @@ #pragma once #include "defs.h" #include "tablet_flat_executor.h" -#include "flat_executor_misc.h" -#include "flat_store_bundle.h" -#include "flat_exec_broker.h" -#include "logic_redo_eggs.h" +#include "flat_executor_misc.h" +#include "flat_store_bundle.h" +#include "flat_exec_broker.h" +#include "logic_redo_eggs.h" #include "util_fmt_line.h" #include <ydb/core/base/localdb.h> #include <library/cpp/time_provider/time_provider.h> namespace NKikimr { - -namespace NTable{ - class TScheme; -} - + +namespace NTable{ + class TScheme; +} + namespace NTabletFlatExecutor { class TTableSnapshotContext; @@ -63,11 +63,11 @@ struct TCompactionLogicState { }; struct TSnapRequest { - const NTable::TSnapEdge Edge; + const NTable::TSnapEdge Edge; TIntrusivePtr<TTableSnapshotContext> Context; - TSnapRequest(NTable::TSnapEdge edge, TTableSnapshotContext *context) - : Edge(edge) + TSnapRequest(NTable::TSnapEdge edge, TTableSnapshotContext *context) + : Edge(edge) , Context(context) {} @@ -123,14 +123,14 @@ struct TCompactionLogicState { // not have any strategy markers in their history are assumed to have // used the generational compaction. NKikimrSchemeOp::ECompactionStrategy Strategy = NKikimrSchemeOp::CompactionStrategyGenerational; - }; - + }; + TMap<ui32, TTableInfo> Tables; THashMap<ui32, TSnapshotState> Snapshots; }; class TFlatTableScan; - + struct TTableCompactionResult { NTable::TCompactionChanges Changes; NKikimrSchemeOp::ECompactionStrategy Strategy; @@ -157,7 +157,7 @@ class TCompactionLogic { NUtil::ILogger * const Logger; NTable::IResourceBroker * const Broker; NTable::ICompactionBackend * const Backend; - ITimeProvider * const Time = nullptr; + ITimeProvider * const Time = nullptr; TAutoPtr<TCompactionLogicState> State; TString TaskNameSuffix; @@ -167,9 +167,9 @@ class TCompactionLogic { void SubmitCompactionTask(ui32 table, ui32 generation, const TString &type, ui32 priority, - TCompactionLogicState::TCompactionTask &task); + TCompactionLogicState::TCompactionTask &task); void UpdateCompactionTask(const TString &type, ui32 priority, - TCompactionLogicState::TCompactionTask &task); + TCompactionLogicState::TCompactionTask &task); bool BeginMemTableCompaction(ui64 taskId, ui32 tableId); @@ -200,14 +200,14 @@ public: TCompactionLogicState::TSnapshotState SnapToLog(ui32 tableId); // Update priorities for background compaction tasks. - void UpdateCompactions(); + void UpdateCompactions(); // Strategy of this table wants to apply some changes void RequestChanges(ui32 tableId); TVector<TTableCompactionChanges> ApplyChanges(); // - void PrepareTableSnapshot(ui32 table, NTable::TSnapEdge edge, TTableSnapshotContext *snapContext); + void PrepareTableSnapshot(ui32 table, NTable::TSnapEdge edge, TTableSnapshotContext *snapContext); // Force compaction support // See slightly simlified state diagram: jing.yandex-team.ru/files/eivanov89/ForcedCompactionPath.png @@ -218,10 +218,10 @@ public: TFinishedCompactionInfo GetFinishedCompactionInfo(ui32 table); TReflectSchemeChangesResult ReflectSchemeChanges(); - void UpdateInMemStatsStep(ui32 table, ui32 steps, ui64 size); + void UpdateInMemStatsStep(ui32 table, ui32 steps, ui64 size); void CheckInMemStats(ui32 table); - void UpdateLogUsage(TArrayRef<const NRedo::TUsage>); - void UpdateLogUsage(const NRedo::TUsage&); + void UpdateLogUsage(TArrayRef<const NRedo::TUsage>); + void UpdateLogUsage(const NRedo::TUsage&); float GetOverloadFactor() const; ui64 GetBackingSize() const; ui64 GetBackingSize(ui64 ownerTabletId) const; diff --git a/ydb/core/tablet_flat/flat_executor_counters.h b/ydb/core/tablet_flat/flat_executor_counters.h index f100bc48a0..5a74b11b30 100644 --- a/ydb/core/tablet_flat/flat_executor_counters.h +++ b/ydb/core/tablet_flat/flat_executor_counters.h @@ -7,28 +7,28 @@ namespace NTabletFlatExecutor { #define FLAT_EXECUTOR_SIMPLE_COUNTERS_MAP(XX) \ XX(DB_TX_IN_FLY, "ExecutorTxInFly") \ - XX(LOG_REDO_COUNT, "LogRedoItems") \ - XX(LOG_REDO_MEMORY, "LogRedoMemory") \ + XX(LOG_REDO_COUNT, "LogRedoItems") \ + XX(LOG_REDO_MEMORY, "LogRedoMemory") \ XX(LOG_REDO_SOLIDS, "LogRedoLargeGlobIds") \ - XX(LOG_ALTER_BYTES, "LogAlterBytes") \ - XX(LOG_SNAP_BYTES, "LogSnapBytes") \ - XX(LOG_RIVER_LEVEL, "LogRiverLevel") \ + XX(LOG_ALTER_BYTES, "LogAlterBytes") \ + XX(LOG_SNAP_BYTES, "LogSnapBytes") \ + XX(LOG_RIVER_LEVEL, "LogRiverLevel") \ XX(DB_WARM_OPS, "DbMemTableOps") \ XX(DB_WARM_BYTES, "DbMemTableBytes") \ - XX(DB_ROWS_ERASE, "DbRowsErase") \ - XX(DB_ROWS_TOTAL, "DbRowsTotal") \ - XX(DB_META_BYTES, "DbMetaBytes") \ - XX(DB_INDEX_BYTES, "DbIndexBytes") \ - XX(DB_OTHER_BYTES, "DbOtherBytes") \ - XX(DB_BYKEY_BYTES, "DbByKeyBytes") \ - XX(DB_PLAIN_BYTES, "DbPlainBytes") \ - XX(DB_CODED_BYTES, "DbCodedBytes") \ + XX(DB_ROWS_ERASE, "DbRowsErase") \ + XX(DB_ROWS_TOTAL, "DbRowsTotal") \ + XX(DB_META_BYTES, "DbMetaBytes") \ + XX(DB_INDEX_BYTES, "DbIndexBytes") \ + XX(DB_OTHER_BYTES, "DbOtherBytes") \ + XX(DB_BYKEY_BYTES, "DbByKeyBytes") \ + XX(DB_PLAIN_BYTES, "DbPlainBytes") \ + XX(DB_CODED_BYTES, "DbCodedBytes") \ XX(DB_ELOBS_BYTES, "DbELargeObjsBytes") \ XX(DB_ELOBS_ITEMS, "DbELargeObjsItems") \ - XX(DB_OUTER_BYTES, "DbOuterBytes") \ - XX(DB_OUTER_ITEMS, "DbOuterItems") \ - XX(DB_DATA_BYTES, "DbDataBytes") \ - XX(DB_PARTS_COUNT, "DbPartsCount") \ + XX(DB_OUTER_BYTES, "DbOuterBytes") \ + XX(DB_OUTER_ITEMS, "DbOuterItems") \ + XX(DB_DATA_BYTES, "DbDataBytes") \ + XX(DB_PARTS_COUNT, "DbPartsCount") \ XX(DB_UNIQUE_DATA_BYTES, "DbUniqueDataBytes") \ XX(DB_UNIQUE_PARTS_COUNT, "DbUniquePartsCount") \ XX(DB_UNIQUE_ROWS_ERASE, "DbUniqueRowsErase") \ @@ -63,48 +63,48 @@ namespace NTabletFlatExecutor { XX(COMPACTION_READ_IN_FLY, "CompactionReadInFly") \ #define FLAT_EXECUTOR_CUMULATIVE_COUNTERS_MAP(XX) \ - XX(LOG_COMMITS, "LogCommits") \ - XX(LOG_WRITTEN, "LogWritten") \ - XX(LOG_EMBEDDED, "LogEmbedded" ) \ - XX(LOG_REDO_WRITTEN, "LogRedoWritten") \ + XX(LOG_COMMITS, "LogCommits") \ + XX(LOG_WRITTEN, "LogWritten") \ + XX(LOG_EMBEDDED, "LogEmbedded" ) \ + XX(LOG_REDO_WRITTEN, "LogRedoWritten") \ XX(TABLET_BYTES_WRITTEN, "TabletBytesWritten") \ XX(TABLET_BLOBS_WRITTEN, "TabletBlobsWritten") \ XX(TABLET_BYTES_READ, "TabletBytesRead") \ XX(TABLET_BLOBS_READ, "TabletBlobsRead") \ - XX(COMP_BYTES_WRITTEN, "CompactionBytesWritten") \ + XX(COMP_BYTES_WRITTEN, "CompactionBytesWritten") \ XX(COMP_BLOBS_WRITTEN, "CompactionBlobsWritten") \ - XX(COMP_BYTES_READ, "CompactionBytesRead") \ + XX(COMP_BYTES_READ, "CompactionBytesRead") \ XX(COMP_BLOBS_READ, "CompactionBlobsRead") \ - XX(DB_ANNEX_ITEMS_GROW, "DbAnnexItemsGrow") \ + XX(DB_ANNEX_ITEMS_GROW, "DbAnnexItemsGrow") \ XX(DB_ELOBS_ITEMS_GROW, "DbELargeObjsItemsGrow") \ XX(DB_ELOBS_ITEMS_GONE, "DbELargeObjsItemsGone") \ - XX(DB_REDO_WRITTEN_BYTES, "DbRedoWrittenBytes") \ - XX(DB_ANNEX_WRITTEN_BYTES, "DbAnnexWrittenBytes") \ + XX(DB_REDO_WRITTEN_BYTES, "DbRedoWrittenBytes") \ + XX(DB_ANNEX_WRITTEN_BYTES, "DbAnnexWrittenBytes") \ XX(TX_COUNT_ALL, "Tx(all)") \ - XX(TX_QUEUED, "TxQueued") \ - XX(TX_RETRIED, "TxRetried") \ - XX(TX_FINISHED, "TxFinished") \ + XX(TX_QUEUED, "TxQueued") \ + XX(TX_RETRIED, "TxRetried") \ + XX(TX_FINISHED, "TxFinished") \ XX(TX_POSTPONED, "TxPostponed") \ - XX(TX_MEM_REQUESTS, "TxMemoryRequests") \ - XX(TX_MEM_CAPTURES, "TxMemoryCaptures") \ - XX(TX_MEM_ATTACHES, "TxMemoryAttaches") \ - XX(TX_DATA_RELEASES, "TxDataReleases") \ + XX(TX_MEM_REQUESTS, "TxMemoryRequests") \ + XX(TX_MEM_CAPTURES, "TxMemoryCaptures") \ + XX(TX_MEM_ATTACHES, "TxMemoryAttaches") \ + XX(TX_DATA_RELEASES, "TxDataReleases") \ XX(TX_RO_COMPLETED, "Tx(ro complete)") \ XX(TX_RW_COMPLETED, "Tx(rw complete)") \ XX(TX_TERMINATED, "Tx(terminated)") \ - XX(TX_CHARGE_WEEDED, "TxKeyChargeWeeded") \ - XX(TX_CHARGE_SIEVED, "TxKeyChargeSieved") \ - XX(TX_SELECT_WEEDED, "TxKeySelectWeeded") \ - XX(TX_SELECT_SIEVED, "TxKeySelectSieved") \ - XX(TX_SELECT_NO_KEY, "TxKeySelectNoKey") \ - XX(TX_BYTES_READ, "TxReadBytes") \ - XX(TX_CACHE_HITS, "TxPageCacheHits") \ - XX(TX_CACHE_MISSES, "TxPageCacheMisses") \ + XX(TX_CHARGE_WEEDED, "TxKeyChargeWeeded") \ + XX(TX_CHARGE_SIEVED, "TxKeyChargeSieved") \ + XX(TX_SELECT_WEEDED, "TxKeySelectWeeded") \ + XX(TX_SELECT_SIEVED, "TxKeySelectSieved") \ + XX(TX_SELECT_NO_KEY, "TxKeySelectNoKey") \ + XX(TX_BYTES_READ, "TxReadBytes") \ + XX(TX_CACHE_HITS, "TxPageCacheHits") \ + XX(TX_CACHE_MISSES, "TxPageCacheMisses") \ XX(GC_DISCOVERED, "GcBlobsDiscovered") \ XX(GC_DISCARDED, "GcBlobsDiscarded") \ XX(GC_FORGOTTEN, "GcBlobsForgotten") \ XX(GC_KEEPSET, "GcKeepFlagsSet") \ - XX(GC_NOTKEEPSET, "GcNotKeepFlagsSet") \ + XX(GC_NOTKEEPSET, "GcNotKeepFlagsSet") \ XX(CONSUMED_CPU, "ConsumedCPU") \ XX(COMPACTION_READ_POSTPONED, "CompactionReadPostponed") \ XX(COMPACTION_READ_CACHE_HITS, "CompactionReadCacheHits") \ diff --git a/ydb/core/tablet_flat/flat_executor_database_ut.cpp b/ydb/core/tablet_flat/flat_executor_database_ut.cpp index 0168615c55..5b0ad7165d 100644 --- a/ydb/core/tablet_flat/flat_executor_database_ut.cpp +++ b/ydb/core/tablet_flat/flat_executor_database_ut.cpp @@ -4,7 +4,7 @@ #include <ydb/core/tablet_flat/test/libs/exec/nanny.h> #include <ydb/core/tablet_flat/test/libs/exec/fuzzy.h> #include <library/cpp/testing/unittest/registar.h> -#include "flat_database.h" +#include "flat_database.h" #include <util/system/sanitizers.h> #include <util/system/valgrind.h> @@ -12,117 +12,117 @@ namespace NKikimr { namespace NTabletFlatExecutor { -using ELookup = NTable::ELookup; -using TDbWrapper = NTable::TDbWrapper; -using ITestDb = NTable::ITestDb; +using ELookup = NTable::ELookup; +using TDbWrapper = NTable::TDbWrapper; +using ITestDb = NTable::ITestDb; -const ui64 MaxActionCount = 12000; +const ui64 MaxActionCount = 12000; const ui64 MultiPageMaxActionCount = 10000; -class TFuzzyActor : public NFake::TNanny { +class TFuzzyActor : public NFake::TNanny { public: - explicit TFuzzyActor(ui32 lives, ui64 limit) - : Respawn(lives) - , Actions(limit) - { - Spawn(); - } - - EDo Run() override - { - using TContext = TTransactionContext; - - Actions -= Min(Actions, ui32(1)); - - NFake::TFuncTx::TCall func; - - const ui32 action = RandomNumber<ui32>(55); - const ui32 table = RandomNumber<ui32>(4); - const ui32 key = RandomNumber<ui32>(300); - - if (Actions == 0) { - func = [this](ITestDb& testDb, TContext &txc) { - return Fuzzy.DropTables(testDb, txc); - }; - } else if (action < 10) { - auto size = 81 + RandomNumber<ui32>(342); - func = [this, table, key, size](ITestDb& testDb, TContext &txc) { - return Fuzzy.UpdateRowTx(testDb, txc, table, key, size); - }; - } else if (action < 20) { - auto size = 3000 + RandomNumber<ui32>(9123); - - func = [this, table, key, size](ITestDb& testDb, TContext &txc) { - return Fuzzy.UpdateRowTx(testDb, txc, table, key, size); - }; - } else if (action < 40) { - func = [this, table](ITestDb& testDb, TContext &txc) { - return Fuzzy.ReadTx(testDb, txc, table); - }; - } else if (action < 50) { - func = [this, table, key](ITestDb& testDb, TContext &txc) { - return Fuzzy.MutipleTablesTx(testDb, txc, table, key); - }; - } else if (action < 55) { - func = [this, table, key](ITestDb& testDb, TContext &txc) { - return Fuzzy.EraseRowTx(testDb, txc, table, key); - }; - } else { - Y_FAIL("Random generator produced unexpected action value"); + explicit TFuzzyActor(ui32 lives, ui64 limit) + : Respawn(lives) + , Actions(limit) + { + Spawn(); + } + + EDo Run() override + { + using TContext = TTransactionContext; + + Actions -= Min(Actions, ui32(1)); + + NFake::TFuncTx::TCall func; + + const ui32 action = RandomNumber<ui32>(55); + const ui32 table = RandomNumber<ui32>(4); + const ui32 key = RandomNumber<ui32>(300); + + if (Actions == 0) { + func = [this](ITestDb& testDb, TContext &txc) { + return Fuzzy.DropTables(testDb, txc); + }; + } else if (action < 10) { + auto size = 81 + RandomNumber<ui32>(342); + func = [this, table, key, size](ITestDb& testDb, TContext &txc) { + return Fuzzy.UpdateRowTx(testDb, txc, table, key, size); + }; + } else if (action < 20) { + auto size = 3000 + RandomNumber<ui32>(9123); + + func = [this, table, key, size](ITestDb& testDb, TContext &txc) { + return Fuzzy.UpdateRowTx(testDb, txc, table, key, size); + }; + } else if (action < 40) { + func = [this, table](ITestDb& testDb, TContext &txc) { + return Fuzzy.ReadTx(testDb, txc, table); + }; + } else if (action < 50) { + func = [this, table, key](ITestDb& testDb, TContext &txc) { + return Fuzzy.MutipleTablesTx(testDb, txc, table, key); + }; + } else if (action < 55) { + func = [this, table, key](ITestDb& testDb, TContext &txc) { + return Fuzzy.EraseRowTx(testDb, txc, table, key); + }; + } else { + Y_FAIL("Random generator produced unexpected action value"); } - QueueTx(func); - - return !Actions ? EDo::Stop : Actions < Rebirth ? Spawn() : EDo::More; + QueueTx(func); + + return !Actions ? EDo::Stop : Actions < Rebirth ? Spawn() : EDo::More; } - -private: - EDo Spawn() noexcept - { - Respawn -= Min(Respawn, ui32(1)); - - auto less = Actions / Max(Respawn + 1, ui32(1)); - - Rebirth = Actions - Min(Actions, Max(less, ui32(1))); - - return EDo::Born; - } - -private: - ui32 Respawn = 0; /* Left tablet restarts */ - ui32 Actions = 0; /* Left transaction actions */ - ui32 Rebirth = 0; /* When to restart tablet */ - - NFake::TFuzzySet Fuzzy{ false }; + +private: + EDo Spawn() noexcept + { + Respawn -= Min(Respawn, ui32(1)); + + auto less = Actions / Max(Respawn + 1, ui32(1)); + + Rebirth = Actions - Min(Actions, Max(less, ui32(1))); + + return EDo::Born; + } + +private: + ui32 Respawn = 0; /* Left tablet restarts */ + ui32 Actions = 0; /* Left transaction actions */ + ui32 Rebirth = 0; /* When to restart tablet */ + + NFake::TFuzzySet Fuzzy{ false }; }; -class TDbTestPlayerActor : public NFake::TNanny { +class TDbTestPlayerActor : public NFake::TNanny { public: - explicit TDbTestPlayerActor(const TVector<NFake::TFuncTx::TCall>& actions) - : Actions(actions) - { - Y_VERIFY(actions.size(), "Have to pass at least one action"); - } + explicit TDbTestPlayerActor(const TVector<NFake::TFuncTx::TCall>& actions) + : Actions(actions) + { + Y_VERIFY(actions.size(), "Have to pass at least one action"); + } - EDo Run() override - { - QueueTx(std::move(Actions.at(Index))); + EDo Run() override + { + QueueTx(std::move(Actions.at(Index))); - return ++Index < Actions.size() ? EDo::More : EDo::Stop; + return ++Index < Actions.size() ? EDo::More : EDo::Stop; } - -private: - TVector<NFake::TFuncTx::TCall> Actions; - size_t Index = 0; + +private: + TVector<NFake::TFuncTx::TCall> Actions; + size_t Index = 0; }; // Mimics schema and transactions that happen inside coordinator -class THeThing : public NFake::TNanny { +class THeThing : public NFake::TNanny { private: - ui64 ActionCount = 0; + ui64 ActionCount = 0; const ui64 MaxActionCount; - bool SchemaReady = false; + bool SchemaReady = false; TIntrusivePtr<IRandomProvider> RandomProvider; @@ -137,34 +137,34 @@ private: ui64 LastDatashardIdx = 0; void CreateSchema(TDbWrapper& db) { - if (std::exchange(SchemaReady, true)) + if (std::exchange(SchemaReady, true)) return; - NTable::TAlter delta; + NTable::TAlter delta; - delta.AddTable("TxTable", TxTable); + delta.AddTable("TxTable", TxTable); delta.AddColumn(TxTable, "TxId", 1, NScheme::TUint64::TypeId, false); delta.AddColumn(TxTable, "Plan", 2, NScheme::TUint64::TypeId, false); - delta.AddColumnToKey(TxTable, 1); + delta.AddColumnToKey(TxTable, 1); - delta.AddTable("AffectedTable", AffectedTable); + delta.AddTable("AffectedTable", AffectedTable); delta.AddColumn(AffectedTable, "TxId", 1, NScheme::TUint64::TypeId, false); delta.AddColumn(AffectedTable, "Datashard", 2, NScheme::TUint64::TypeId, false); delta.AddColumn(AffectedTable, "Plan", 3, NScheme::TUint64::TypeId, false); - delta.AddColumnToKey(AffectedTable, 1); - delta.AddColumnToKey(AffectedTable, 2); - - { - NLocalDb::TCompactionPolicy policy; - - policy.InMemStepsToSnapshot = 10; - policy.InMemForceStepsToSnapshot = 20; - - delta.SetCompactionPolicy(TxTable, policy); - delta.SetCompactionPolicy(AffectedTable, policy); - } - - db.Apply(*delta.Flush()); + delta.AddColumnToKey(AffectedTable, 1); + delta.AddColumnToKey(AffectedTable, 2); + + { + NLocalDb::TCompactionPolicy policy; + + policy.InMemStepsToSnapshot = 10; + policy.InMemForceStepsToSnapshot = 20; + + delta.SetCompactionPolicy(TxTable, policy); + delta.SetCompactionPolicy(AffectedTable, policy); + } + + db.Apply(*delta.Flush()); } void AddRandomTx(TDbWrapper& db) { @@ -197,8 +197,8 @@ private: // Inserts in both TxTable and AffectedTable void StartTransactions(TDbWrapper& db) { - CreateSchema(db); - + CreateSchema(db); + // Generate some new transactions ui64 newTxCount = RandomNumber(5); for (ui64 i = 0; i < newTxCount; ++i) { @@ -224,93 +224,93 @@ private: } public: - THeThing(ui64 maxActionCount, ui64 randomSeed) - : MaxActionCount(maxActionCount) + THeThing(ui64 maxActionCount, ui64 randomSeed) + : MaxActionCount(maxActionCount) , RandomProvider(CreateDeterministicRandomProvider(randomSeed)) { DatashardTxQueues.resize(20); } - EDo Run() override - { - if (RandomNumber(1000) < 4) - return EDo::Born; + EDo Run() override + { + if (RandomNumber(1000) < 4) + return EDo::Born; ui32 action = RandomNumber(8); if (action < 3) { - QueueTx([this](ITestDb& testDb, TTransactionContext&){ TDbWrapper db(testDb); this->StartTransactions(db); return true; }); + QueueTx([this](ITestDb& testDb, TTransactionContext&){ TDbWrapper db(testDb); this->StartTransactions(db); return true; }); } else { - QueueTx([this](ITestDb& testDb, TTransactionContext&){ TDbWrapper db(testDb); this->FinishTransactions(db); return true; }); + QueueTx([this](ITestDb& testDb, TTransactionContext&){ TDbWrapper db(testDb); this->FinishTransactions(db); return true; }); } - return ++ActionCount < MaxActionCount ? EDo::More : EDo::Stop; + return ++ActionCount < MaxActionCount ? EDo::More : EDo::Stop; } }; // Generates a table with many rows and the does a SelectRange query for the whole table // If prefetch works properly the SelectRange transaction it is expected not to have restarts -class TFullScan : public NFake::TNanny { -public: - explicit TFullScan(ui64 rows) : Rows(rows) { } - +class TFullScan : public NFake::TNanny { +public: + explicit TFullScan(ui64 rows) : Rows(rows) { } + private: - EDo Run() override - { - if (++RowCount <= Rows) { - QueueTx([this](ITestDb& testDb, TTransactionContext&){ TDbWrapper db(testDb); this->AddRandomRowTx(db); return true; }); - } else if (RowCount == Rows + 1) { - QueueTx([this](ITestDb& testDb, TTransactionContext&){ TDbWrapper db(testDb); return this->DoFullScanTx(db); }); - } else if (RowCount > Rows + 1) { - Y_FAIL("Shouldn't request more task after EDo::Stop"); - } - - return RowCount <= Rows ? EDo::More : EDo::Stop; - } - - void CreateSchema(TDbWrapper& db) - { - if (std::exchange(SchemaReady, true)) + EDo Run() override + { + if (++RowCount <= Rows) { + QueueTx([this](ITestDb& testDb, TTransactionContext&){ TDbWrapper db(testDb); this->AddRandomRowTx(db); return true; }); + } else if (RowCount == Rows + 1) { + QueueTx([this](ITestDb& testDb, TTransactionContext&){ TDbWrapper db(testDb); return this->DoFullScanTx(db); }); + } else if (RowCount > Rows + 1) { + Y_FAIL("Shouldn't request more task after EDo::Stop"); + } + + return RowCount <= Rows ? EDo::More : EDo::Stop; + } + + void CreateSchema(TDbWrapper& db) + { + if (std::exchange(SchemaReady, true)) return; - NTable::TAlter delta; + NTable::TAlter delta; - delta.AddTable("table", Table); + delta.AddTable("table", Table); delta.SetFamily(Table, AltFamily, NTable::NPage::ECache::None, NTable::NPage::ECodec::Plain); delta.AddColumn(Table, "Id", 1, NScheme::TUint32::TypeId, false); delta.AddColumn(Table, "value", 2, NScheme::TUint64::TypeId, false); delta.AddColumn(Table, "large", 3, NScheme::TString::TypeId, false); - delta.AddColumnToKey(Table, 1); + delta.AddColumnToKey(Table, 1); delta.AddColumnToFamily(Table, 2, AltFamily); delta.AddColumnToFamily(Table, 3, AltFamily); - - { - const auto comp_g0 = NLocalDb::LegacyQueueIdToTaskName(0); - const auto comp_g1 = NLocalDb::LegacyQueueIdToTaskName(1); - - NLocalDb::TCompactionPolicy policy; - - policy.InMemSizeToSnapshot = 40 * 1024 *1024; - policy.InMemStepsToSnapshot = 300; - policy.InMemForceStepsToSnapshot = 500; - policy.InMemForceSizeToSnapshot = 64 * 1024 * 1024; - policy.InMemResourceBrokerTask = comp_g0; - policy.ReadAheadHiThreshold = 100000; - policy.ReadAheadLoThreshold = 50000; - - /* should not warm pages to cache after compaction (last - false), need for testing precharge and exactly one tx - resrart on full scan. - */ - policy.Generations = { + + { + const auto comp_g0 = NLocalDb::LegacyQueueIdToTaskName(0); + const auto comp_g1 = NLocalDb::LegacyQueueIdToTaskName(1); + + NLocalDb::TCompactionPolicy policy; + + policy.InMemSizeToSnapshot = 40 * 1024 *1024; + policy.InMemStepsToSnapshot = 300; + policy.InMemForceStepsToSnapshot = 500; + policy.InMemForceSizeToSnapshot = 64 * 1024 * 1024; + policy.InMemResourceBrokerTask = comp_g0; + policy.ReadAheadHiThreshold = 100000; + policy.ReadAheadLoThreshold = 50000; + + /* should not warm pages to cache after compaction (last + false), need for testing precharge and exactly one tx + resrart on full scan. + */ + policy.Generations = { { 200 * 1024 * 1024, 8, 8, 300 * 1024 * 1024, comp_g0, false }, - { 400 * 1024 * 1024, 8, 8, 800 * 1024 * 1024, comp_g1, false } - }; - - delta.SetCompactionPolicy(Table, policy); - } - - db.Apply(*delta.Flush()); + { 400 * 1024 * 1024, 8, 8, 800 * 1024 * 1024, comp_g1, false } + }; + + delta.SetCompactionPolicy(Table, policy); + } + + db.Apply(*delta.Flush()); } void AddRandomRowTx(TDbWrapper& db) { @@ -319,120 +319,120 @@ private: ui64 rowId = RowCount; // Add big rows with big values in order to produce many pages - db.Apply(db.Update(Table).Key(rowId).Set("value", rowId).Set("large", TString(10000, 'A'))); + db.Apply(db.Update(Table).Key(rowId).Set("value", rowId).Set("large", TString(10000, 'A'))); } bool DoFullScanTx(TDbWrapper& db) { try { - const std::array<ui32, 2> tags{{ 1 /* Id */, 2 /* value */ }}; - - db->Precharge(Table, { }, { }, tags, 0); - - TAutoPtr<NTable::ITestIterator> it = db->Iterate(Table, { }, tags, ELookup::GreaterOrEqualThan); + const std::array<ui32, 2> tags{{ 1 /* Id */, 2 /* value */ }}; + db->Precharge(Table, { }, { }, tags, 0); + + TAutoPtr<NTable::ITestIterator> it = db->Iterate(Table, { }, tags, ELookup::GreaterOrEqualThan); + while (it->Next(NTable::ENext::All) == NTable::EReady::Data) { LastKey = it->GetValues().Columns[0].AsValue<ui32>(); } - + Y_VERIFY(LastKey + 1 == RowCount /* incomplete read */); Y_VERIFY(Restarts == 1 /* exactly one precharge */); - + return true; - } catch (NTable::TIteratorNotReady&) { - Restarts++; - Cerr << "Full scan restart at id = " << LastKey << Endl; + } catch (NTable::TIteratorNotReady&) { + Restarts++; + Cerr << "Full scan restart at id = " << LastKey << Endl; return false; } } -private: - const ui64 Rows = 0; - const ui32 Table = 1; +private: + const ui64 Rows = 0; + const ui32 Table = 1; const ui32 AltFamily = 1; - ui32 Restarts = 0; - ui64 RowCount = 0; - ui64 LastKey = Max<ui64>(); - bool SchemaReady = false; + ui32 Restarts = 0; + ui64 RowCount = 0; + ui64 LastKey = Max<ui64>(); + bool SchemaReady = false; }; -void RunTest(IActor *test) -{ - NFake::TRunner env; - - env->SetLogPriority(NKikimrServices::TABLET_MAIN, NActors::NLog::PRI_CRIT); - env->SetLogPriority(NKikimrServices::TABLET_EXECUTOR, NActors::NLog::PRI_INFO); - env->SetLogPriority(NKikimrServices::TABLET_OPS_HOST, NActors::NLog::PRI_INFO); - env->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); - env->SetLogPriority(NKikimrServices::OPS_BACKUP, NActors::NLog::PRI_INFO); - env->SetLogPriority(NKikimrServices::SAUSAGE_BIO, NActors::NLog::PRI_INFO); - env->SetLogPriority(NKikimrServices::TABLET_SAUSAGECACHE, NActors::NLog::PRI_INFO); - - if (false) { - env->SetLogPriority(NKikimrServices::TABLET_EXECUTOR, NActors::NLog::PRI_DEBUG); - env->SetLogPriority(NKikimrServices::TABLET_FLATBOOT, NActors::NLog::PRI_DEBUG); - env->SetLogPriority(NKikimrServices::TABLET_SAUSAGECACHE, NActors::NLog::PRI_DEBUG); - } - - env.RunTest(test); - env.Finalize(); +void RunTest(IActor *test) +{ + NFake::TRunner env; + + env->SetLogPriority(NKikimrServices::TABLET_MAIN, NActors::NLog::PRI_CRIT); + env->SetLogPriority(NKikimrServices::TABLET_EXECUTOR, NActors::NLog::PRI_INFO); + env->SetLogPriority(NKikimrServices::TABLET_OPS_HOST, NActors::NLog::PRI_INFO); + env->SetLogPriority(NKikimrServices::OPS_COMPACT, NActors::NLog::PRI_INFO); + env->SetLogPriority(NKikimrServices::OPS_BACKUP, NActors::NLog::PRI_INFO); + env->SetLogPriority(NKikimrServices::SAUSAGE_BIO, NActors::NLog::PRI_INFO); + env->SetLogPriority(NKikimrServices::TABLET_SAUSAGECACHE, NActors::NLog::PRI_INFO); + + if (false) { + env->SetLogPriority(NKikimrServices::TABLET_EXECUTOR, NActors::NLog::PRI_DEBUG); + env->SetLogPriority(NKikimrServices::TABLET_FLATBOOT, NActors::NLog::PRI_DEBUG); + env->SetLogPriority(NKikimrServices::TABLET_SAUSAGECACHE, NActors::NLog::PRI_DEBUG); + } + + env.RunTest(test); + env.Finalize(); } Y_UNIT_TEST_SUITE(TExecutorDb) { Y_UNIT_TEST(RandomOps) - { - RunTest(new TFuzzyActor(5, MaxActionCount)); + { + RunTest(new TFuzzyActor(5, MaxActionCount)); } Y_UNIT_TEST(FullScan) - { - RunTest(new TFullScan(MultiPageMaxActionCount)); + { + RunTest(new TFullScan(MultiPageMaxActionCount)); } Y_UNIT_TEST(CoordinatorSimulation) - { - RunTest(new THeThing(MaxActionCount, 42)); + { + RunTest(new THeThing(MaxActionCount, 42)); } Y_UNIT_TEST(RandomCoordinatorSimulation) - { - RunTest(new THeThing(MaxActionCount, TInstant::Now().Seconds())); + { + RunTest(new THeThing(MaxActionCount, TInstant::Now().Seconds())); } Y_UNIT_TEST(MultiPage) - { - NFake::TFuzzySet fuzzy(false /* no compression */); - - TVector<NFake::TFuncTx::TCall> tx = { - [&fuzzy](ITestDb& testDb, TTransactionContext &txc){ return fuzzy.UpdateRowTx(testDb, txc, 2, 100, 10000000); }, - [&fuzzy](ITestDb& testDb, TTransactionContext &txc){ return fuzzy.UpdateRowTx(testDb, txc, 2, 101, 10000000); }, - [&fuzzy](ITestDb& testDb, TTransactionContext &txc){ return fuzzy.UpdateRowTx(testDb, txc, 2, 100, 10000000); }, - [&fuzzy](ITestDb& testDb, TTransactionContext &txc){ return fuzzy.ReadTx(testDb, txc, 2); } + { + NFake::TFuzzySet fuzzy(false /* no compression */); + + TVector<NFake::TFuncTx::TCall> tx = { + [&fuzzy](ITestDb& testDb, TTransactionContext &txc){ return fuzzy.UpdateRowTx(testDb, txc, 2, 100, 10000000); }, + [&fuzzy](ITestDb& testDb, TTransactionContext &txc){ return fuzzy.UpdateRowTx(testDb, txc, 2, 101, 10000000); }, + [&fuzzy](ITestDb& testDb, TTransactionContext &txc){ return fuzzy.UpdateRowTx(testDb, txc, 2, 100, 10000000); }, + [&fuzzy](ITestDb& testDb, TTransactionContext &txc){ return fuzzy.ReadTx(testDb, txc, 2); } }; - RunTest(new TDbTestPlayerActor(tx)); + RunTest(new TDbTestPlayerActor(tx)); } - + Y_UNIT_TEST(EncodedPage) - { - NFake::TFuzzySet fuzzy(true /* compress */); - - TVector<NFake::TFuncTx::TCall> tx = { - [&fuzzy](ITestDb& db, TTransactionContext &txc){ return fuzzy.UpdateRowTx(db, txc, 2, 100, 10000000); }, - [&fuzzy](ITestDb& db, TTransactionContext &txc){ return fuzzy.UpdateRowTx(db, txc, 2, 101, 10000000); }, - [&fuzzy](ITestDb& db, TTransactionContext &txc){ return fuzzy.UpdateRowTx(db, txc, 2, 100, 10000000); }, - [&fuzzy](ITestDb& db, TTransactionContext &txc){ return fuzzy.ReadTx(db, txc, 2); } - - /* There should be yet another tx or something else that checks - page compression in parts, but this is going to be very wired - here. Thus check manually OPS_COMPACT log output and compare - the result with MultiPage output, it works on the same rows. - */ - }; - - RunTest(new TDbTestPlayerActor(tx)); - } - + { + NFake::TFuzzySet fuzzy(true /* compress */); + + TVector<NFake::TFuncTx::TCall> tx = { + [&fuzzy](ITestDb& db, TTransactionContext &txc){ return fuzzy.UpdateRowTx(db, txc, 2, 100, 10000000); }, + [&fuzzy](ITestDb& db, TTransactionContext &txc){ return fuzzy.UpdateRowTx(db, txc, 2, 101, 10000000); }, + [&fuzzy](ITestDb& db, TTransactionContext &txc){ return fuzzy.UpdateRowTx(db, txc, 2, 100, 10000000); }, + [&fuzzy](ITestDb& db, TTransactionContext &txc){ return fuzzy.ReadTx(db, txc, 2); } + + /* There should be yet another tx or something else that checks + page compression in parts, but this is going to be very wired + here. Thus check manually OPS_COMPACT log output and compare + the result with MultiPage output, it works on the same rows. + */ + }; + + RunTest(new TDbTestPlayerActor(tx)); + } + } } diff --git a/ydb/core/tablet_flat/flat_executor_db_mon.cpp b/ydb/core/tablet_flat/flat_executor_db_mon.cpp index d5353747be..d5f2992d8d 100644 --- a/ydb/core/tablet_flat/flat_executor_db_mon.cpp +++ b/ydb/core/tablet_flat/flat_executor_db_mon.cpp @@ -21,12 +21,12 @@ public: bool Execute(TTransactionContext &txc, const TActorContext &ctx) override { TStringStream str; - { - const auto &scheme = txc.DB.GetScheme(); + { + const auto &scheme = txc.DB.GetScheme(); TCgiParameters cgi(Event->Get()->Cgi()); if (cgi.Has("TableID")) { ui32 tableId = FromStringWithDefault<ui32>(cgi.Get("TableID")); - const auto *tableInfo = scheme.GetTableInfo(tableId); + const auto *tableInfo = scheme.GetTableInfo(tableId); if (tableInfo != nullptr) { str << "<script>$('.container').toggleClass('container container-fluid').css('padding-left','5%').css('padding-right','5%');</script>"; str << "<h3>" << tableInfo->Id << ":" << tableInfo->Name << "</h3>"; @@ -127,7 +127,7 @@ public: str << "<thead>"; str << "<tr>"; for (ui32 column : columns) { - const auto &columnInfo = tableInfo->Columns.find(column)->second; + const auto &columnInfo = tableInfo->Columns.find(column)->second; str << "<th>" << column << ":" << columnInfo.Name << "</th>"; } str << "</tr>"; @@ -142,7 +142,7 @@ public: ++rowCount; if (rowCount > rowOffset) { str << "<tr>"; - TDbTupleRef tuple = result->GetValues(); + TDbTupleRef tuple = result->GetValues(); for (size_t i = 0; i < columns.size(); ++i) { const void *data = tuple.Columns[i].Data(); ui32 size = tuple.Columns[i].Size(); @@ -234,9 +234,9 @@ public: str << "</tbody>"; str << "</table>"; - if (result->Last() == NTable::EReady::Page) - return false; - + if (result->Last() == NTable::EReady::Page) + return false; + auto fnPrintLink = [this, &str, tableId, &cgi] (ssize_t offset, ssize_t limit, TString caption) { str << "<a href='db?TabletID=" << Self->TabletId() << "&TableID=" << tableId; diff --git a/ydb/core/tablet_flat/flat_executor_gclogic.cpp b/ydb/core/tablet_flat/flat_executor_gclogic.cpp index bded66353e..d1cf2ab36f 100644 --- a/ydb/core/tablet_flat/flat_executor_gclogic.cpp +++ b/ydb/core/tablet_flat/flat_executor_gclogic.cpp @@ -1,14 +1,14 @@ #include "flat_executor_gclogic.h" -#include "flat_bio_eggs.h" +#include "flat_bio_eggs.h" #include <ydb/core/base/tablet.h> namespace NKikimr { namespace NTabletFlatExecutor { TExecutorGCLogic::TExecutorGCLogic(TIntrusiveConstPtr<TTabletStorageInfo> info, TAutoPtr<NPageCollection::TSteppedCookieAllocator> cookies) - : TabletStorageInfo(std::move(info)) - , Cookies(cookies) - , Generation(Cookies->Gen) + : TabletStorageInfo(std::move(info)) + , Cookies(cookies) + , Generation(Cookies->Gen) , Slicer(1, Cookies.Get(), NBlockIO::BlockSize) , SnapshotStep(0) , PrevSnapshotStep(0) @@ -17,33 +17,33 @@ TExecutorGCLogic::TExecutorGCLogic(TIntrusiveConstPtr<TTabletStorageInfo> info, { } -void TExecutorGCLogic::WriteToLog(TLogCommit &commit) { - TGCTime time(Generation, commit.Step); +void TExecutorGCLogic::WriteToLog(TLogCommit &commit) { + TGCTime time(Generation, commit.Step); TGCLogEntry& uncommittedDelta = UncommittedDeltaLog[time]; uncommittedDelta.Time = time; const ui32 gcEntriesInBatch = 250000; // ~7mb rawsize - Cookies->Switch(commit.Step, true /* require step switch */); + Cookies->Switch(commit.Step, true /* require step switch */); - const ui32 gcGrowSize = commit.GcDelta.Created.size(); - const ui32 gcLeftSize = commit.GcDelta.Deleted.size(); - - if (commit.Type == ECommit::Snap || gcGrowSize + gcLeftSize < gcEntriesInBatch) { - uncommittedDelta.Delta = commit.GcDelta; /* preserve for embedding */ + const ui32 gcGrowSize = commit.GcDelta.Created.size(); + const ui32 gcLeftSize = commit.GcDelta.Deleted.size(); + + if (commit.Type == ECommit::Snap || gcGrowSize + gcLeftSize < gcEntriesInBatch) { + uncommittedDelta.Delta = commit.GcDelta; /* preserve for embedding */ } else { ui32 placedDiscovered = 0; ui32 placedLeft = 0; - uncommittedDelta.Delta = std::exchange(commit.GcDelta, { }); - - while (placedDiscovered < gcGrowSize || placedLeft < gcLeftSize) { - NKikimrExecutorFlat::TExternalGcEntry proto; - + uncommittedDelta.Delta = std::exchange(commit.GcDelta, { }); + + while (placedDiscovered < gcGrowSize || placedLeft < gcLeftSize) { + NKikimrExecutorFlat::TExternalGcEntry proto; + ui32 leftInBatch = gcEntriesInBatch; - if (placedDiscovered < gcGrowSize) { - const ui32 toMove = Min(leftInBatch, gcGrowSize - placedDiscovered); - auto it = uncommittedDelta.Delta.Created.begin() + placedDiscovered; + if (placedDiscovered < gcGrowSize) { + const ui32 toMove = Min(leftInBatch, gcGrowSize - placedDiscovered); + auto it = uncommittedDelta.Delta.Created.begin() + placedDiscovered; LogoBlobIDRepatedFromLogoBlobIDVector(proto.MutableGcDiscovered(), it, it + toMove); placedDiscovered += toMove; leftInBatch -= toMove; @@ -51,12 +51,12 @@ void TExecutorGCLogic::WriteToLog(TLogCommit &commit) { if (leftInBatch && placedLeft < gcLeftSize) { const ui32 toMove = Min(leftInBatch, gcLeftSize - placedLeft); - auto it = uncommittedDelta.Delta.Deleted.begin() + placedLeft; + auto it = uncommittedDelta.Delta.Deleted.begin() + placedLeft; LogoBlobIDRepatedFromLogoBlobIDVector(proto.MutableGcLeft(), it, it + toMove); placedLeft += toMove; } - Slicer.One(commit.Refs, proto.SerializeAsString(), true); + Slicer.One(commit.Refs, proto.SerializeAsString(), true); } } } @@ -67,14 +67,14 @@ TGCLogEntry TExecutorGCLogic::SnapshotLog(ui32 step) { for (const auto& chIt : ChannelInfo) { for (const auto& le : chIt.second.CommittedDelta) { Y_VERIFY(le.first <= snapshotTime); - TExecutorGCLogic::MergeVectors(snapshot.Delta.Created, le.second.Created); - TExecutorGCLogic::MergeVectors(snapshot.Delta.Deleted, le.second.Deleted); + TExecutorGCLogic::MergeVectors(snapshot.Delta.Created, le.second.Created); + TExecutorGCLogic::MergeVectors(snapshot.Delta.Deleted, le.second.Deleted); } } for (const auto &it : UncommittedDeltaLog) { - TExecutorGCLogic::MergeVectors(snapshot.Delta.Created, it.second.Delta.Created); - TExecutorGCLogic::MergeVectors(snapshot.Delta.Deleted, it.second.Delta.Deleted); + TExecutorGCLogic::MergeVectors(snapshot.Delta.Created, it.second.Delta.Created); + TExecutorGCLogic::MergeVectors(snapshot.Delta.Deleted, it.second.Delta.Deleted); } PrevSnapshotStep = SnapshotStep; @@ -82,22 +82,22 @@ TGCLogEntry TExecutorGCLogic::SnapshotLog(ui32 step) { return snapshot; } -void TExecutorGCLogic::SnapToLog(NKikimrExecutorFlat::TLogSnapshot &snap, ui32 step) { +void TExecutorGCLogic::SnapToLog(NKikimrExecutorFlat::TLogSnapshot &snap, ui32 step) { TGCLogEntry gcLogEntry = SnapshotLog(step); - auto *gcSnapDiscovered = snap.MutableGcSnapDiscovered(); - auto *gcSnapLeft = snap.MutableGcSnapLeft(); + auto *gcSnapDiscovered = snap.MutableGcSnapDiscovered(); + auto *gcSnapLeft = snap.MutableGcSnapLeft(); - gcSnapDiscovered->Reserve(gcLogEntry.Delta.Created.size()); - for (const TLogoBlobID &x : gcLogEntry.Delta.Created) + gcSnapDiscovered->Reserve(gcLogEntry.Delta.Created.size()); + for (const TLogoBlobID &x : gcLogEntry.Delta.Created) LogoBlobIDFromLogoBlobID(x, gcSnapDiscovered->Add()); - gcSnapLeft->Reserve(gcLogEntry.Delta.Deleted.size()); - for (const TLogoBlobID &x : gcLogEntry.Delta.Deleted) + gcSnapLeft->Reserve(gcLogEntry.Delta.Deleted.size()); + for (const TLogoBlobID &x : gcLogEntry.Delta.Deleted) LogoBlobIDFromLogoBlobID(x, gcSnapLeft->Add()); for (const auto &chIt : ChannelInfo) { if (chIt.second.CommitedGcBarrier) { - auto *x = snap.AddGcBarrierInfo(); + auto *x = snap.AddGcBarrierInfo(); x->SetChannel(chIt.first); x->SetSetToGeneration(chIt.second.CommitedGcBarrier.Generation); x->SetSetToStep(chIt.second.CommitedGcBarrier.Step); @@ -145,7 +145,7 @@ void TExecutorGCLogic::HoldBarrier(ui32 step) { Y_VERIFY(true == HoldBarriersSet.insert(TGCTime(Generation, step)).second); } -void TExecutorGCLogic::ReleaseBarrier(ui32 step) { +void TExecutorGCLogic::ReleaseBarrier(ui32 step) { Y_VERIFY(1 == HoldBarriersSet.erase(TGCTime(Generation, step))); } @@ -161,16 +161,16 @@ void TExecutorGCLogic::FollowersSyncComplete(bool isBoot) { } void TExecutorGCLogic::ApplyDelta(TGCTime time, TGCBlobDelta &delta) { - for (const TLogoBlobID &blobId : delta.Created) { + for (const TLogoBlobID &blobId : delta.Created) { auto &channel = ChannelInfo[blobId.Channel()]; TGCTime gcTime(blobId.Generation(), blobId.Step()); Y_VERIFY(channel.KnownGcBarrier < gcTime); - channel.CommittedDelta[gcTime].Created.push_back(blobId); + channel.CommittedDelta[gcTime].Created.push_back(blobId); } - for (const TLogoBlobID &blobId : delta.Deleted) { + for (const TLogoBlobID &blobId : delta.Deleted) { auto &channel = ChannelInfo[blobId.Channel()]; - channel.CommittedDelta[time].Deleted.push_back(blobId); + channel.CommittedDelta[time].Deleted.push_back(blobId); } } @@ -197,8 +197,8 @@ TExecutorGCLogic::TChannelInfo::TChannelInfo() void TExecutorGCLogic::TChannelInfo::ApplyDelta(TGCTime time, TGCBlobDelta& delta) { TGCBlobDelta& committedDelta = CommittedDelta[time]; - DoSwap(committedDelta, delta); - Y_VERIFY_DEBUG(delta.Created.empty() && delta.Deleted.empty()); + DoSwap(committedDelta, delta); + Y_VERIFY_DEBUG(delta.Created.empty() && delta.Deleted.empty()); } void TExecutorGCLogic::MergeVectors(TVector<TLogoBlobID>& destination, const TVector<TLogoBlobID>& source) { @@ -297,7 +297,7 @@ TExecutorGCLogic::TIntrospection TExecutorGCLogic::IntrospectStateSize() const { for (auto &xpair : UncommittedDeltaLog) { ++ret.UncommitedEntries; - ret.UncommitedBlobIds += xpair.second.Delta.Created.size() + xpair.second.Delta.Deleted.size(); + ret.UncommitedBlobIds += xpair.second.Delta.Created.size() + xpair.second.Delta.Deleted.size(); } ret.UncommitedEntriesBytes += ret.UncommitedBlobIds * sizeof(TLogoBlobID) + 96; ret.BarriersSetSize += HoldBarriersSet.size(); @@ -305,8 +305,8 @@ TExecutorGCLogic::TIntrospection TExecutorGCLogic::IntrospectStateSize() const { for (auto xchannelp : ChannelInfo) { for (auto &xpair : xchannelp.second.CommittedDelta) { ++ret.CommitedEntries; - ret.CommitedBlobIdsKnown += xpair.second.Created.size(); - ret.CommitedBlobIdsLeft += xpair.second.Deleted.size(); + ret.CommitedBlobIdsKnown += xpair.second.Created.size(); + ret.CommitedBlobIdsLeft += xpair.second.Deleted.size(); } ret.CommitedEntriesBytes += sizeof(TLogoBlobID) *(ret.CommitedBlobIdsKnown + ret.CommitedBlobIdsLeft) + 96; } diff --git a/ydb/core/tablet_flat/flat_executor_gclogic.h b/ydb/core/tablet_flat/flat_executor_gclogic.h index 9c1fa568a2..e3fc2c09e3 100644 --- a/ydb/core/tablet_flat/flat_executor_gclogic.h +++ b/ydb/core/tablet_flat/flat_executor_gclogic.h @@ -1,7 +1,7 @@ #pragma once #include "defs.h" -#include "flat_sausage_slicer.h" -#include "flat_exec_commit.h" +#include "flat_sausage_slicer.h" +#include "flat_exec_commit.h" #include <util/generic/vector.h> #include <util/generic/set.h> #include <ydb/core/base/blobstorage.h> @@ -38,15 +38,15 @@ struct TGCLogEntry { class TExecutorGCLogic { public: TExecutorGCLogic(TIntrusiveConstPtr<TTabletStorageInfo>, TAutoPtr<NPageCollection::TSteppedCookieAllocator>); - void WriteToLog(TLogCommit &logEntry); + void WriteToLog(TLogCommit &logEntry); TGCLogEntry SnapshotLog(ui32 step); - void SnapToLog(NKikimrExecutorFlat::TLogSnapshot &logSnapshot, ui32 step); + void SnapToLog(NKikimrExecutorFlat::TLogSnapshot &logSnapshot, ui32 step); void OnCommitLog(ui32 step, ui32 confirmedOnSend, const TActorContext &ctx); // notification about log commit - could send GC to blob storage void OnCollectGarbageResult(TEvBlobStorage::TEvCollectGarbageResult::TPtr& ev); // notification on any garbage collection results void ApplyLogEntry(TGCLogEntry &entry); // apply one log entry, used during recovery and also from WriteToLog void ApplyLogSnapshot(TGCLogEntry &snapshot, const TVector<std::pair<ui32, ui64>> &barriers); void HoldBarrier(ui32 step); // holds GC on no more than this step for channels specified - void ReleaseBarrier(ui32 step); + void ReleaseBarrier(ui32 step); ui32 GetActiveGcBarrier(); void FollowersSyncComplete(bool isBoot); diff --git a/ydb/core/tablet_flat/flat_executor_misc.h b/ydb/core/tablet_flat/flat_executor_misc.h index a1382963bf..9466ce69ac 100644 --- a/ydb/core/tablet_flat/flat_executor_misc.h +++ b/ydb/core/tablet_flat/flat_executor_misc.h @@ -1,36 +1,36 @@ -#pragma once - -#include "defs.h" -#include "flat_util_misc.h" -#include "flat_page_iface.h" -#include "flat_page_conf.h" +#pragma once + +#include "defs.h" +#include "flat_util_misc.h" +#include "flat_page_iface.h" +#include "flat_page_conf.h" #include "flat_row_versions.h" #include "flat_table_committed.h" -#include "flat_writer_conf.h" +#include "flat_writer_conf.h" #include "flat_comp.h" - -namespace NKikimr { -namespace NTabletFlatExecutor { - - struct TBarrier : public TSimpleRefCount<TBarrier> { - TBarrier(ui32 step) - : Step(step) + +namespace NKikimr { +namespace NTabletFlatExecutor { + + struct TBarrier : public TSimpleRefCount<TBarrier> { + TBarrier(ui32 step) + : Step(step) { } - - const ui32 Step = Max<ui32>(); - }; - + + const ui32 Step = Max<ui32>(); + }; + struct TCompactCfg final : public IDestructable { using TConf = NTable::NPage::TConf; - + explicit TCompactCfg(THolder<NTable::TCompactionParams> params) : Params(std::move(params)) - { - } - + { + } + NTable::TEpoch Epoch = NTable::TEpoch::Zero(); /* Result epoch of compacted part */ - NTable::NPage::TConf Layout; - NWriter::TConf Writer; + NTable::NPage::TConf Layout; + NWriter::TConf Writer; THolder<NTable::TCompactionParams> Params; NTable::TRowVersionRanges::TSnapshot RemovedRowVersions; @@ -40,7 +40,7 @@ namespace NTabletFlatExecutor { // The above may contain extra keys, these allow them to be narrowed TVector<TIntrusiveConstPtr<NTable::TMemTable>> Frozen; TVector<TIntrusiveConstPtr<NTable::TTxStatusPart>> TxStatus; - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_executor_snapshot.h b/ydb/core/tablet_flat/flat_executor_snapshot.h index fae02f7fc8..5b141e5b94 100644 --- a/ydb/core/tablet_flat/flat_executor_snapshot.h +++ b/ydb/core/tablet_flat/flat_executor_snapshot.h @@ -1,61 +1,61 @@ -#pragma once - -#include "defs.h" -#include "tablet_flat_executor.h" -#include "flat_executor_misc.h" - -namespace NKikimr { -namespace NTabletFlatExecutor { - - class TTableSnapshotContext::TImpl { - public: - using TSnapEdge = NTable::TSnapEdge; - - enum class EReady { - Zero = 0, - Wait = 1, - Done = 2, - }; - - struct TState { - EReady Ready = EReady::Zero; - TSnapEdge Edge; - }; - - struct TFlush { - ui32 Step = Max<ui32>(); +#pragma once + +#include "defs.h" +#include "tablet_flat_executor.h" +#include "flat_executor_misc.h" + +namespace NKikimr { +namespace NTabletFlatExecutor { + + class TTableSnapshotContext::TImpl { + public: + using TSnapEdge = NTable::TSnapEdge; + + enum class EReady { + Zero = 0, + Wait = 1, + Done = 2, + }; + + struct TState { + EReady Ready = EReady::Zero; + TSnapEdge Edge; + }; + + struct TFlush { + ui32 Step = Max<ui32>(); TVector<TIntrusivePtr<TBarrier>> Barriers; THashMap<TLogoBlobID, TSet<ui64>> Bundles; TMap<ui32, ui32> Moved; - }; - - void Prepare(ui32 table, TSnapEdge edge) - { - auto &state = Get(table, EReady::Zero); - - state.Ready = EReady::Wait; - state.Edge = edge; - - Pending++; - } - + }; + + void Prepare(ui32 table, TSnapEdge edge) + { + auto &state = Get(table, EReady::Zero); + + state.Ready = EReady::Wait; + state.Edge = edge; + + Pending++; + } + bool Complete(ui32 table, TIntrusivePtr<TBarrier> barrier) - { - Get(table, EReady::Wait).Ready = EReady::Done; - Holds.Barriers.push_back(barrier); - - Y_VERIFY(Pending, "Snapshot pending counter is out of sync"); - - return --Pending == 0; - } - - void Borrowed(ui32 step, ui32 table, const TLogoBlobID &bundle, ui64 loaner) - { - Get(table, EReady::Done); - Holds.Step = Min(Holds.Step, step); + { + Get(table, EReady::Wait).Ready = EReady::Done; + Holds.Barriers.push_back(barrier); + + Y_VERIFY(Pending, "Snapshot pending counter is out of sync"); + + return --Pending == 0; + } + + void Borrowed(ui32 step, ui32 table, const TLogoBlobID &bundle, ui64 loaner) + { + Get(table, EReady::Done); + Holds.Step = Min(Holds.Step, step); Holds.Bundles[bundle].insert(loaner); - } - + } + void Moved(ui32 src, ui32 dst) { Get(src, EReady::Done); @@ -63,36 +63,36 @@ namespace NTabletFlatExecutor { Holds.Moved[src] = dst; } - void Clear() - { - Holds.Step = Max<ui32>(); - Holds.Bundles.clear(); + void Clear() + { + Holds.Step = Max<ui32>(); + Holds.Bundles.clear(); Holds.Moved.clear(); - } - - TSnapEdge Edge(ui32 table) - { - return Get(table, EReady::Done).Edge; - } - - TFlush Release() - { - return std::move(Holds); - } - - private: - TState& Get(ui32 table, EReady ready) - { - auto &state = Tables[table]; - Y_VERIFY(state.Ready == ready, "Table snapshot is not in state"); - return state; - } - - private: - ui32 Pending = 0; + } + + TSnapEdge Edge(ui32 table) + { + return Get(table, EReady::Done).Edge; + } + + TFlush Release() + { + return std::move(Holds); + } + + private: + TState& Get(ui32 table, EReady ready) + { + auto &state = Tables[table]; + Y_VERIFY(state.Ready == ready, "Table snapshot is not in state"); + return state; + } + + private: + ui32 Pending = 0; THashMap<ui32, TState> Tables; - TFlush Holds; - }; - -} -} + TFlush Holds; + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_executor_tx_env.h b/ydb/core/tablet_flat/flat_executor_tx_env.h index e3b54db82e..c3d4cf3149 100644 --- a/ydb/core/tablet_flat/flat_executor_tx_env.h +++ b/ydb/core/tablet_flat/flat_executor_tx_env.h @@ -1,19 +1,19 @@ -#pragma once -#include "defs.h" -#include "flat_table_misc.h" -#include "flat_part_store.h" -#include "flat_store_hotdog.h" +#pragma once +#include "defs.h" +#include "flat_table_misc.h" +#include "flat_part_store.h" +#include "flat_store_hotdog.h" #include "flat_store_solid.h" -#include "flat_sausagecache.h" -#include "tablet_flat_executor.h" -#include "flat_executor_snapshot.h" +#include "flat_sausagecache.h" +#include "tablet_flat_executor.h" +#include "flat_executor_snapshot.h" #include <ydb/core/util/pb.h> -#include <util/generic/hash_set.h> +#include <util/generic/hash_set.h> #include <ydb/core/tablet_flat/flat_executor.pb.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { - + +namespace NKikimr { +namespace NTabletFlatExecutor { + struct TPageCollectionReadEnv : public NTable::IPages { TPageCollectionReadEnv(TPrivatePageCache& cache) : Cache(cache) @@ -67,35 +67,35 @@ namespace NTabletFlatExecutor { }; struct TPageCollectionTxEnv : public TPageCollectionReadEnv, public IExecuting { - using TLogoId = TLogoBlobID; - - struct TBorrowSnap { + using TLogoId = TLogoBlobID; + + struct TBorrowSnap { TIntrusivePtr<TTableSnapshotContext> SnapContext; - }; - - struct TBorrowUpdate { - TDeque<ui64> StoppedLoans; - }; - - struct TLoanConfirmation { - const TLogoId BorrowId; - }; - - struct TLoanBundle { + }; + + struct TBorrowUpdate { + TDeque<ui64> StoppedLoans; + }; + + struct TLoanConfirmation { + const TLogoId BorrowId; + }; + + struct TLoanBundle { TLoanBundle(ui32 sourceTableId, ui32 localTableId, ui64 lender, NTable::TPartComponents&& pc) - : SourceTableId(sourceTableId) - , LocalTableId(localTableId) - , Lender(lender) + : SourceTableId(sourceTableId) + , LocalTableId(localTableId) + , Lender(lender) , PartComponents(std::move(pc)) - {} - - const ui32 SourceTableId; - const ui32 LocalTableId; - const ui64 Lender; - + {} + + const ui32 SourceTableId; + const ui32 LocalTableId; + const ui64 Lender; + NTable::TPartComponents PartComponents; - }; - + }; + struct TLoanTxStatus { TLoanTxStatus(ui32 sourceTableId, ui32 localTableId, ui64 lender, const NPageCollection::TLargeGlobId& dataId, NTable::TEpoch epoch, @@ -118,61 +118,61 @@ namespace NTabletFlatExecutor { struct TSnapshot { TVector<TIntrusivePtr<TTableSnapshotContext>> Context; - }; - + }; + using TPageCollectionReadEnv::TPageCollectionReadEnv; - - bool HasChanges() const noexcept - { - return - DropSnap - || MakeSnap - || LoanBundle + + bool HasChanges() const noexcept + { + return + DropSnap + || MakeSnap + || LoanBundle || LoanTxStatus - || BorrowUpdates - || LoanConfirmation; - } - - protected: /* IExecuting, tx stage func implementation */ + || BorrowUpdates + || LoanConfirmation; + } + + protected: /* IExecuting, tx stage func implementation */ void MakeSnapshot(TIntrusivePtr<TTableSnapshotContext> snap) override - { - Y_VERIFY(snap->TablesToSnapshot()); - - for (ui32 table : snap->TablesToSnapshot()) - MakeSnap[table].Context.push_back(snap); - } - + { + Y_VERIFY(snap->TablesToSnapshot()); + + for (ui32 table : snap->TablesToSnapshot()) + MakeSnap[table].Context.push_back(snap); + } + void DropSnapshot(TIntrusivePtr<TTableSnapshotContext> snap) override - { - Y_VERIFY(!DropSnap, "only one snapshot per transaction"); - - DropSnap.Reset(new TBorrowSnap{ snap }); - } - + { + Y_VERIFY(!DropSnap, "only one snapshot per transaction"); + + DropSnap.Reset(new TBorrowSnap{ snap }); + } + void MoveSnapshot(const TTableSnapshotContext &snap, ui32 src, ui32 dst) override { snap.Impl->Moved(src, dst); } - void ClearSnapshot(const TTableSnapshotContext &snap) override - { - snap.Impl->Clear(); - } - - // NOTE: It's allowed to add parts in the same Tx where the table gets created (and is not visible yet) - void LoanTable(ui32 tableId, const TString &raw) override - { - TProtoBox<NKikimrExecutorFlat::TDatabaseBorrowPart> proto(raw); - - const ui64 lender = proto.GetLenderTablet(); - const ui32 source = proto.GetSourceTable(); - - for (auto &part : proto.GetParts()) { + void ClearSnapshot(const TTableSnapshotContext &snap) override + { + snap.Impl->Clear(); + } + + // NOTE: It's allowed to add parts in the same Tx where the table gets created (and is not visible yet) + void LoanTable(ui32 tableId, const TString &raw) override + { + TProtoBox<NKikimrExecutorFlat::TDatabaseBorrowPart> proto(raw); + + const ui64 lender = proto.GetLenderTablet(); + const ui32 source = proto.GetSourceTable(); + + for (auto &part : proto.GetParts()) { Y_VERIFY(part.HasBundle(), "Cannot find attached hotdogs in borrow"); - + LoanBundle.emplace_back(new TLoanBundle(source, tableId, lender, TPageCollectionProtoHelper::MakePageCollectionComponents(part.GetBundle(), /* unsplit */ true))); - } + } for (auto &part : proto.GetTxStatusParts()) { LoanTxStatus.emplace_back(new TLoanTxStatus( @@ -181,32 +181,32 @@ namespace NTabletFlatExecutor { NTable::TEpoch(part.GetEpoch()), part.GetData())); } - } - - void CleanupLoan(const TLogoId &bundle, ui64 from) override - { - Y_VERIFY(!DropSnap, "must not drop snapshot and update loan in same transaction"); - BorrowUpdates[bundle].StoppedLoans.push_back(from); - } - - void ConfirmLoan(const TLogoId &bundle, const TLogoId &borrow) override - { - LoanConfirmation.insert(std::make_pair(bundle, TLoanConfirmation{borrow})); - } - - public: - /*_ Pending database shanshots */ - + } + + void CleanupLoan(const TLogoId &bundle, ui64 from) override + { + Y_VERIFY(!DropSnap, "must not drop snapshot and update loan in same transaction"); + BorrowUpdates[bundle].StoppedLoans.push_back(from); + } + + void ConfirmLoan(const TLogoId &bundle, const TLogoId &borrow) override + { + LoanConfirmation.insert(std::make_pair(bundle, TLoanConfirmation{borrow})); + } + + public: + /*_ Pending database shanshots */ + TMap<ui32, TSnapshot> MakeSnap; - - /*_ In tx tables borrow proto API */ - - THolder<TBorrowSnap> DropSnap; - THashMap<TLogoId, TBorrowUpdate> BorrowUpdates; + + /*_ In tx tables borrow proto API */ + + THolder<TBorrowSnap> DropSnap; + THashMap<TLogoId, TBorrowUpdate> BorrowUpdates; TVector<THolder<TLoanBundle>> LoanBundle; TVector<THolder<TLoanTxStatus>> LoanTxStatus; - THashMap<TLogoId, TLoanConfirmation> LoanConfirmation; - }; - -} -} + THashMap<TLogoId, TLoanConfirmation> LoanConfirmation; + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_executor_txloglogic.cpp b/ydb/core/tablet_flat/flat_executor_txloglogic.cpp index df59ddc245..58b38b0ba4 100644 --- a/ydb/core/tablet_flat/flat_executor_txloglogic.cpp +++ b/ydb/core/tablet_flat/flat_executor_txloglogic.cpp @@ -1,11 +1,11 @@ #include "flat_executor_txloglogic.h" -#include "flat_executor_counters.h" -#include "flat_exec_seat.h" +#include "flat_executor_counters.h" +#include "flat_exec_seat.h" #include "flat_exec_commit_mgr.h" -#include "flat_bio_eggs.h" -#include "logic_redo_batch.h" -#include "logic_redo_entry.h" -#include "logic_redo_queue.h" +#include "flat_bio_eggs.h" +#include "logic_redo_batch.h" +#include "logic_redo_entry.h" +#include "logic_redo_queue.h" #include "probes.h" #include <ydb/core/tablet_flat/flat_executor.pb.h> #include <util/system/sanitizers.h> @@ -16,56 +16,56 @@ namespace NTabletFlatExecutor { LWTRACE_USING(TABLET_FLAT_PROVIDER) const static ui64 MaxSizeToEmbedInLog = 2048; -const static ui64 MaxBytesToBatch = 2 * 1024 * 1024; -const static ui64 MaxItemsToBatch = 64; +const static ui64 MaxBytesToBatch = 2 * 1024 * 1024; +const static ui64 MaxItemsToBatch = 64; TLogicRedo::TCompletionEntry::TCompletionEntry(TAutoPtr<TSeat> seat, ui32 step) : Step(step) - , InFlyRWTransaction(seat) + , InFlyRWTransaction(seat) {} TLogicRedo::TLogicRedo(TAutoPtr<NPageCollection::TSteppedCookieAllocator> cookies, TCommitManager *commitManager, TAutoPtr<NRedo::TQueue> queue) : CommitManager(commitManager) - , Cookies(cookies) - , Batch(new NRedo::TBatch) - , Queue(queue) + , Cookies(cookies) + , Batch(new NRedo::TBatch) + , Queue(queue) , Slicer(1, Cookies.Get(), NBlockIO::BlockSize) {} -TLogicRedo::~TLogicRedo() +TLogicRedo::~TLogicRedo() {} -void TLogicRedo::Describe(IOutputStream &out) const noexcept -{ - return Queue->Describe(out); -} - -void TLogicRedo::InstallCounters(TExecutorCounters *counters, TTabletCountersWithTxTypes *appTxCounters) { +void TLogicRedo::Describe(IOutputStream &out) const noexcept +{ + return Queue->Describe(out); +} + +void TLogicRedo::InstallCounters(TExecutorCounters *counters, TTabletCountersWithTxTypes *appTxCounters) { Counters = counters; AppTxCounters = appTxCounters; } -NRedo::TStats TLogicRedo::LogStats() const noexcept -{ +NRedo::TStats TLogicRedo::LogStats() const noexcept +{ return { Queue->Items, Queue->Memory, Queue->LargeGlobIdsBytes }; -} - -TArrayRef<const NRedo::TUsage> TLogicRedo::GrabLogUsage() const noexcept -{ - return Queue->GrabUsage(); -} - +} + +TArrayRef<const NRedo::TUsage> TLogicRedo::GrabLogUsage() const noexcept +{ + return Queue->GrabUsage(); +} + bool TLogicRedo::TerminateTransaction(TAutoPtr<TSeat> seat, const TActorContext &ctx, const TActorId &ownerID) { if (CompletionQueue.empty()) { - const TTxType txType = seat->Self->GetTxType(); + const TTxType txType = seat->Self->GetTxType(); - seat->Self->Terminate(seat->TerminationReason, ctx.MakeFor(ownerID)); + seat->Self->Terminate(seat->TerminationReason, ctx.MakeFor(ownerID)); Counters->Cumulative()[TExecutorCounters::TX_TERMINATED].Increment(1); if (AppTxCounters && txType != UnknownTxType) AppTxCounters->TxCumulative(txType, COUNTER_TT_TERMINATED).Increment(1); return true; } else { - CompletionQueue.back().WaitingTerminatedTransactions.push_back(seat); + CompletionQueue.back().WaitingTerminatedTransactions.push_back(seat); return false; } } @@ -98,133 +98,133 @@ bool TLogicRedo::CommitROTransaction(TAutoPtr<TSeat> seat, const TActorContext & return true; } else { LWTRACK(TransactionReadOnlyWait, seat->Self->Orbit, seat->UniqID, CompletionQueue.back().Step); - CompletionQueue.back().WaitingROTransactions.push_back(seat); + CompletionQueue.back().WaitingROTransactions.push_back(seat); return false; } } -void TLogicRedo::FlushBatchedLog() -{ +void TLogicRedo::FlushBatchedLog() +{ if (TAutoPtr<TLogCommit> commit = Batch->Commit) { - auto affects = Batch->Affects(); - MakeLogEntry(*commit, Batch->Flush(), affects, true); + auto affects = Batch->Affects(); + MakeLogEntry(*commit, Batch->Flush(), affects, true); CommitManager->Commit(commit); } - Y_VERIFY(Batch->Commit == nullptr, "Batch still has acquired commit"); + Y_VERIFY(Batch->Commit == nullptr, "Batch still has acquired commit"); } -TLogicRedo::TCommitRWTransactionResult TLogicRedo::CommitRWTransaction( +TLogicRedo::TCommitRWTransactionResult TLogicRedo::CommitRWTransaction( TAutoPtr<TSeat> seat, NTable::TChange &change, bool force) -{ - seat->CommitTimer.Reset(); - - Y_VERIFY(force || !(change.Scheme || change.Annex)); +{ + seat->CommitTimer.Reset(); + Y_VERIFY(force || !(change.Scheme || change.Annex)); + const TTxType txType = seat->Self->GetTxType(); - if (auto bytes = change.Redo.size()) { - Counters->Cumulative()[TMonCo::DB_REDO_WRITTEN_BYTES].Increment(bytes); + if (auto bytes = change.Redo.size()) { + Counters->Cumulative()[TMonCo::DB_REDO_WRITTEN_BYTES].Increment(bytes); if (AppTxCounters && txType != UnknownTxType) - AppTxCounters->TxCumulative(txType, COUNTER_TT_REDO_WRITTEN_BYTES).Increment(bytes); + AppTxCounters->TxCumulative(txType, COUNTER_TT_REDO_WRITTEN_BYTES).Increment(bytes); } - if (change.Annex) { - ui64 bytes = 0; - for (const auto &one : change.Annex) { - bytes += one.Data.size(); + if (change.Annex) { + ui64 bytes = 0; + for (const auto &one : change.Annex) { + bytes += one.Data.size(); } - + Counters->Cumulative()[TMonCo::DB_ANNEX_ITEMS_GROW].Increment(change.Annex.size()); - Counters->Cumulative()[TMonCo::DB_ANNEX_WRITTEN_BYTES].Increment(bytes); + Counters->Cumulative()[TMonCo::DB_ANNEX_WRITTEN_BYTES].Increment(bytes); if (AppTxCounters && txType != UnknownTxType) - AppTxCounters->TxCumulative(txType, COUNTER_TT_ANNEX_WRITTEN_BYTES).Increment(bytes); + AppTxCounters->TxCumulative(txType, COUNTER_TT_ANNEX_WRITTEN_BYTES).Increment(bytes); } - if (force || MaxItemsToBatch < 2 || change.Redo.size() > MaxBytesToBatch) { - FlushBatchedLog(); + if (force || MaxItemsToBatch < 2 || change.Redo.size() > MaxBytesToBatch) { + FlushBatchedLog(); auto commit = CommitManager->Begin(true, ECommit::Redo); commit->PushTx(seat.Get()); - CompletionQueue.push_back({ seat, commit->Step }); - MakeLogEntry(*commit, std::move(change.Redo), change.Affects, !force); - - const auto was = commit->GcDelta.Created.size(); - - for (auto &one: change.Annex) { - if (one.GId.Logo.Step() != commit->Step) { - Y_Fail( + CompletionQueue.push_back({ seat, commit->Step }); + MakeLogEntry(*commit, std::move(change.Redo), change.Affects, !force); + + const auto was = commit->GcDelta.Created.size(); + + for (auto &one: change.Annex) { + if (one.GId.Logo.Step() != commit->Step) { + Y_Fail( "Leader{" << Cookies->Tablet << ":" << Cookies->Gen << "}" - << " got for " << NFmt::Do(*commit) << " annex blob " - << one.GId.Logo << " out of step order"); - } - - commit->GcDelta.Created.emplace_back(one.GId.Logo); + << " got for " << NFmt::Do(*commit) << " annex blob " + << one.GId.Logo << " out of step order"); + } + + commit->GcDelta.Created.emplace_back(one.GId.Logo); commit->Refs.emplace_back(one.GId.Logo, one.Data.ToString()); - } - - /* Sometimes clang drops the last emplace_back above if move was used - before for data field. This hacky Y_VERIFY prevents this and check - that emplace always happens. - */ - - Y_VERIFY(was + change.Annex.size() == commit->GcDelta.Created.size()); - - return { commit, false }; + } + + /* Sometimes clang drops the last emplace_back above if move was used + before for data field. This hacky Y_VERIFY prevents this and check + that emplace always happens. + */ + + Y_VERIFY(was + change.Annex.size() == commit->GcDelta.Created.size()); + + return { commit, false }; } else { - if (Batch->Bytes + change.Redo.size() > MaxBytesToBatch) - FlushBatchedLog(); + if (Batch->Bytes + change.Redo.size() > MaxBytesToBatch) + FlushBatchedLog(); - if (!Batch->Commit) + if (!Batch->Commit) Batch->Commit = CommitManager->Begin(false, ECommit::Redo); Batch->Commit->PushTx(seat.Get()); - CompletionQueue.push_back({ seat, Batch->Commit->Step }); - - Batch->Add(std::move(change.Redo), change.Affects); - - if (Batch->Bodies.size() >= MaxItemsToBatch) - FlushBatchedLog(); - - return { nullptr, bool(Batch->Commit) }; + CompletionQueue.push_back({ seat, Batch->Commit->Step }); + + Batch->Add(std::move(change.Redo), change.Affects); + + if (Batch->Bodies.size() >= MaxItemsToBatch) + FlushBatchedLog(); + + return { nullptr, bool(Batch->Commit) }; } } -void TLogicRedo::MakeLogEntry(TLogCommit &commit, TString redo, TArrayRef<const ui32> affects, bool embed) -{ - if (redo) { +void TLogicRedo::MakeLogEntry(TLogCommit &commit, TString redo, TArrayRef<const ui32> affects, bool embed) +{ + if (redo) { NSan::CheckMemIsInitialized(redo.data(), redo.size()); - Cookies->Switch(commit.Step, true /* require step switch */); - + Cookies->Switch(commit.Step, true /* require step switch */); + auto coded = NPageCollection::TSlicer::Lz4()->Encode(redo); - + Counters->Cumulative()[TMonCo::LOG_REDO_WRITTEN].Increment(coded.size()); - - if (embed && coded.size() <= MaxSizeToEmbedInLog) { - commit.Embedded = std::move(coded); - Queue->Push({ Cookies->Gen, commit.Step }, affects, commit.Embedded); - } else { + + if (embed && coded.size() <= MaxSizeToEmbedInLog) { + commit.Embedded = std::move(coded); + Queue->Push({ Cookies->Gen, commit.Step }, affects, commit.Embedded); + } else { auto largeGlobId = Slicer.Do(commit.Refs, std::move(coded), false); largeGlobId.MaterializeTo(commit.GcDelta.Created); - + Queue->Push({ Cookies->Gen, commit.Step }, affects, largeGlobId); - } + } } } ui64 TLogicRedo::Confirm(ui32 step, const TActorContext &ctx, const TActorId &ownerId) { Y_VERIFY(!CompletionQueue.empty(), "t: %" PRIu64 " non-expected confirmation %" PRIu32 - ", prev %" PRIu32, Cookies->Tablet, step, PrevConfirmedStep); + ", prev %" PRIu32, Cookies->Tablet, step, PrevConfirmedStep); Y_VERIFY(CompletionQueue[0].Step == step, "t: %" PRIu64 " inconsistent confirmation head: %" PRIu32 ", step: %" PRIu32 ", queue size: %" PRISZT ", prev confimed: %" PRIu32 - , Cookies->Tablet, CompletionQueue[0].Step, step, CompletionQueue.size(), PrevConfirmedStep); + , Cookies->Tablet, CompletionQueue[0].Step, step, CompletionQueue.size(), PrevConfirmedStep); PrevConfirmedStep = step; @@ -262,7 +262,7 @@ ui64 TLogicRedo::Confirm(ui32 step, const TActorContext &ctx, const TActorId &ow } for (auto &x : entry.WaitingTerminatedTransactions) { - const TTxType roTxType = x->Self->GetTxType(); + const TTxType roTxType = x->Self->GetTxType(); x->Self->Terminate(x->TerminationReason, ownerCtx); Counters->Cumulative()[TExecutorCounters::TX_TERMINATED].Increment(1); @@ -278,15 +278,15 @@ ui64 TLogicRedo::Confirm(ui32 step, const TActorContext &ctx, const TActorId &ow return confirmedTransactions; } -void TLogicRedo::SnapToLog(NKikimrExecutorFlat::TLogSnapshot &snap) -{ - Y_VERIFY(Batch->Commit == nullptr); +void TLogicRedo::SnapToLog(NKikimrExecutorFlat::TLogSnapshot &snap) +{ + Y_VERIFY(Batch->Commit == nullptr); - Queue->Flush(snap); + Queue->Flush(snap); - for (auto &xpair : Queue->Edges) { - auto genstep = ExpandGenStepPair(xpair.second.TxStamp); - auto *x = snap.AddTableSnapshoted(); + for (auto &xpair : Queue->Edges) { + auto genstep = ExpandGenStepPair(xpair.second.TxStamp); + auto *x = snap.AddTableSnapshoted(); x->SetTable(xpair.first); x->SetGeneration(genstep.first); x->SetStep(genstep.second); @@ -294,9 +294,9 @@ void TLogicRedo::SnapToLog(NKikimrExecutorFlat::TLogSnapshot &snap) } } -void TLogicRedo::CutLog(ui32 table, NTable::TSnapEdge edge, TGCBlobDelta &gc) -{ - Queue->Cut(table, edge, gc); +void TLogicRedo::CutLog(ui32 table, NTable::TSnapEdge edge, TGCBlobDelta &gc) +{ + Queue->Cut(table, edge, gc); } }} diff --git a/ydb/core/tablet_flat/flat_executor_txloglogic.h b/ydb/core/tablet_flat/flat_executor_txloglogic.h index 1272c4f947..7c5d9f329c 100644 --- a/ydb/core/tablet_flat/flat_executor_txloglogic.h +++ b/ydb/core/tablet_flat/flat_executor_txloglogic.h @@ -1,13 +1,13 @@ #pragma once #include "defs.h" -#include "flat_sausage_grind.h" -#include "flat_sausage_slicer.h" -#include "flat_dbase_change.h" -#include "flat_exec_seat.h" -#include "flat_exec_commit.h" -#include "flat_executor_counters.h" -#include "flat_sausage_slicer.h" -#include "logic_redo_eggs.h" +#include "flat_sausage_grind.h" +#include "flat_sausage_slicer.h" +#include "flat_dbase_change.h" +#include "flat_exec_seat.h" +#include "flat_exec_commit.h" +#include "flat_executor_counters.h" +#include "flat_sausage_slicer.h" +#include "logic_redo_eggs.h" #include <ydb/core/tablet_flat/flat_executor.pb.h> #include <ydb/core/tablet/tablet_counters_protobuf.h> @@ -15,38 +15,38 @@ namespace NKikimr { namespace NTabletFlatExecutor { class TCommitManager; - -namespace NRedo { - struct TBatch; - struct TEntry; - struct TQueue; -} - -class TLogicRedo { - using TMonCo = TExecutorCounters; - + +namespace NRedo { + struct TBatch; + struct TEntry; + struct TQueue; +} + +class TLogicRedo { + using TMonCo = TExecutorCounters; + TCommitManager * const CommitManager; TAutoPtr<NPageCollection::TSteppedCookieAllocator> Cookies; TAutoPtr<NRedo::TBatch> Batch; TAutoPtr<NRedo::TQueue> Queue; NPageCollection::TSlicer Slicer; - TExecutorCounters *Counters = nullptr; - TTabletCountersWithTxTypes *AppTxCounters = nullptr; - + TExecutorCounters *Counters = nullptr; + TTabletCountersWithTxTypes *AppTxCounters = nullptr; + struct TCompletionEntry { ui32 Step; - /* vvvv argh.... */ + /* vvvv argh.... */ TAutoPtr<TSeat> InFlyRWTransaction; TVector<TAutoPtr<TSeat>> WaitingROTransactions; TVector<TAutoPtr<TSeat>> WaitingTerminatedTransactions; - + TCompletionEntry(TAutoPtr<TSeat> seat, ui32 step); }; TDeque<TCompletionEntry> CompletionQueue; // would be graph once data-dependencies implemented - ui32 PrevConfirmedStep = 0; + ui32 PrevConfirmedStep = 0; public: struct TCommitRWTransactionResult { @@ -55,22 +55,22 @@ public: }; TLogicRedo(TAutoPtr<NPageCollection::TSteppedCookieAllocator>, TCommitManager*, TAutoPtr<NRedo::TQueue>); - ~TLogicRedo(); + ~TLogicRedo(); - void Describe(IOutputStream &out) const noexcept; + void Describe(IOutputStream &out) const noexcept; void InstallCounters(TExecutorCounters *counters, TTabletCountersWithTxTypes* appTxCounters); bool TerminateTransaction(TAutoPtr<TSeat>, const TActorContext &ctx, const TActorId &ownerId); bool CommitROTransaction(TAutoPtr<TSeat> seat, const TActorContext &ownerCtx); TCommitRWTransactionResult CommitRWTransaction(TAutoPtr<TSeat> seat, NTable::TChange &change, bool force); - void MakeLogEntry(TLogCommit&, TString redo, TArrayRef<const ui32> affects, bool embed); - void FlushBatchedLog(); + void MakeLogEntry(TLogCommit&, TString redo, TArrayRef<const ui32> affects, bool embed); + void FlushBatchedLog(); ui64 Confirm(ui32 step, const TActorContext &ctx, const TActorId &ownerId); - void CutLog(ui32 table, NTable::TSnapEdge, TGCBlobDelta&); - void SnapToLog(NKikimrExecutorFlat::TLogSnapshot&); - NRedo::TStats LogStats() const noexcept; - TArrayRef<const NRedo::TUsage> GrabLogUsage() const noexcept; + void CutLog(ui32 table, NTable::TSnapEdge, TGCBlobDelta&); + void SnapToLog(NKikimrExecutorFlat::TLogSnapshot&); + NRedo::TStats LogStats() const noexcept; + TArrayRef<const NRedo::TUsage> GrabLogUsage() const noexcept; }; void CompleteRoTransaction(TAutoPtr<TSeat>, const TActorContext &ownerCtx, TExecutorCounters *counters, TTabletCountersWithTxTypes *appTxCounters); diff --git a/ydb/core/tablet_flat/flat_executor_ut.cpp b/ydb/core/tablet_flat/flat_executor_ut.cpp index c9cf528971..4b0eabe993 100644 --- a/ydb/core/tablet_flat/flat_executor_ut.cpp +++ b/ydb/core/tablet_flat/flat_executor_ut.cpp @@ -3,91 +3,91 @@ namespace NKikimr { namespace NTabletFlatExecutor { - struct TRowsModel { - enum : ui32 { - TableId = 101, - ColumnKeyId = 1, - ColumnValueId = 20, + struct TRowsModel { + enum : ui32 { + TableId = 101, + ColumnKeyId = 1, + ColumnValueId = 20, AltFamilyId = 1, - }; - - struct TTxSchema : public ITransaction { - + }; + + struct TTxSchema : public ITransaction { + TTxSchema(TIntrusiveConstPtr<TCompactionPolicy> policy, bool groups = false) : Policy(std::move(policy)) , Groups(groups) { } - - bool Execute(TTransactionContext &txc, const TActorContext &) override - { - if (txc.DB.GetScheme().GetTableInfo(TableId)) - return true; - - txc.DB.Alter() - .AddTable("test" + ToString(ui32(TableId)), TableId) + + bool Execute(TTransactionContext &txc, const TActorContext &) override + { + if (txc.DB.GetScheme().GetTableInfo(TableId)) + return true; + + txc.DB.Alter() + .AddTable("test" + ToString(ui32(TableId)), TableId) .AddColumn(TableId, "key", ColumnKeyId, NScheme::TInt64::TypeId, false) .AddColumn(TableId, "value", ColumnValueId, NScheme::TString::TypeId, false) - .AddColumnToKey(TableId, ColumnKeyId) - .SetCompactionPolicy(TableId, *Policy); - + .AddColumnToKey(TableId, ColumnKeyId) + .SetCompactionPolicy(TableId, *Policy); + if (Groups) { txc.DB.Alter() .SetFamily(TableId, AltFamilyId, NTable::NPage::ECache::None, NTable::NPage::ECodec::Plain) .AddColumnToFamily(TableId, ColumnValueId, AltFamilyId); } - return true; - } - - void Complete(const TActorContext &ctx) override - { - ctx.Send(ctx.SelfID, new NFake::TEvReturn); - } - + return true; + } + + void Complete(const TActorContext &ctx) override + { + ctx.Send(ctx.SelfID, new NFake::TEvReturn); + } + TIntrusiveConstPtr<TCompactionPolicy> Policy; const bool Groups; - }; - - struct TTxAddRows : public ITransaction { - + }; + + struct TTxAddRows : public ITransaction { + TTxAddRows(ui64 key, ui64 rows, ui64 pack, ui32 bytes, TRowVersion writeVersion) : Key(key), Rows(rows), Pack(pack), Bytes(bytes), WriteVersion(writeVersion) {} - - bool Execute(TTransactionContext &txc, const TActorContext &) override - { - for (auto end = Key + Min(Pack, Rows); Key < end; Key++, Rows--) { - const auto key = NScheme::TInt64::TInstance(Key); - - TString str = Bytes ? TString(Bytes, (char)Key) : "value"; + + bool Execute(TTransactionContext &txc, const TActorContext &) override + { + for (auto end = Key + Min(Pack, Rows); Key < end; Key++, Rows--) { + const auto key = NScheme::TInt64::TInstance(Key); + + TString str = Bytes ? TString(Bytes, (char)Key) : "value"; const auto val = NScheme::TString::TInstance(str); NTable::TUpdateOp ops{ ColumnValueId, NTable::ECellOp::Set, val }; - + txc.DB.Update(TableId, NTable::ERowOp::Upsert, { key }, { ops }, WriteVersion); - } - - return true; - } - - void Complete(const TActorContext &ctx) override - { - if (Rows > 0) { + } + + return true; + } + + void Complete(const TActorContext &ctx) override + { + if (Rows > 0) { auto *next = new TTxAddRows(Key, Rows, Pack, Bytes, WriteVersion); - - ctx.Send(ctx.SelfID, new NFake::TEvExecute{ next }); - } else { - ctx.Send(ctx.SelfID, new NFake::TEvReturn); - } - } - - private: - ui64 Key = 0; - ui64 Rows = 0; - const ui64 Pack = 1; - const ui32 Bytes = 0; + + ctx.Send(ctx.SelfID, new NFake::TEvExecute{ next }); + } else { + ctx.Send(ctx.SelfID, new NFake::TEvReturn); + } + } + + private: + ui64 Key = 0; + ui64 Rows = 0; + const ui64 Pack = 1; + const ui32 Bytes = 0; const TRowVersion WriteVersion; - }; - + }; + struct TTxEraseRows : public ITransaction { TTxEraseRows(ui64 key, ui64 rows, ui64 pack, TRowVersion writeVersion) : Key(key), Rows(rows), Pack(pack), WriteVersion(writeVersion) @@ -123,18 +123,18 @@ namespace NTabletFlatExecutor { }; NFake::TEvExecute* MakeScheme(TIntrusiveConstPtr<TCompactionPolicy> policy, bool groups = false) - { + { return new NFake::TEvExecute{ new TTxSchema(std::move(policy), groups) }; - } - - NFake::TEvExecute* MakeRows(ui32 rows, ui32 bytes = 0, ui32 pack = 1) - { - auto key = std::exchange(Key, Key + rows); - - return + } + + NFake::TEvExecute* MakeRows(ui32 rows, ui32 bytes = 0, ui32 pack = 1) + { + auto key = std::exchange(Key, Key + rows); + + return new NFake::TEvExecute{ new TTxAddRows(key, rows, pack, bytes, WriteVersion) }; - } - + } + NFake::TEvExecute* MakeErase(ui32 rows, ui32 pack = 1) { auto key = std::exchange(Key, Key + rows); @@ -143,23 +143,23 @@ namespace NTabletFlatExecutor { new NFake::TEvExecute{ new TTxEraseRows(key, rows, pack, WriteVersion) }; } - TRowsModel& RowTo(ui64 key) noexcept - { - return Key = key, *this; - } - + TRowsModel& RowTo(ui64 key) noexcept + { + return Key = key, *this; + } + TRowsModel& VersionTo(TRowVersion writeVersion) noexcept { WriteVersion = writeVersion; return *this; } - ui64 Rows() const { return Key - 1; }; - - ui64 Key = 1; + ui64 Rows() const { return Key - 1; }; + + ui64 Key = 1; TRowVersion WriteVersion = TRowVersion::Min(); - }; - + }; + class TSnapshotModel : public NFake::TDummySnapshotContext { public: static TIntrusivePtr<TSnapshotModel> Create(ui32 tableId = TRowsModel::TableId) { @@ -238,12 +238,12 @@ namespace NTabletFlatExecutor { }; struct TDummyResult: public IDestructable { - TDummyResult(ui64 count, ui64 expect) - : Count(count), Expect(expect) + TDummyResult(ui64 count, ui64 expect) + : Count(count), Expect(expect) {} - ui64 Count = 0; - ui64 Expect = 0; + ui64 Count = 0; + ui64 Expect = 0; }; class TDummyScan : public TActor<TDummyScan>, public NTable::IScan { @@ -251,8 +251,8 @@ public: TDummyScan(TActorId tablet, bool postponed, EAbort abort, ui32 rows) : TActor(&TThis::StateWork) , Tablet(tablet) - , ExpectedRows(rows) - , Postponed(postponed) + , ExpectedRows(rows) + , Postponed(postponed) , Abort(abort) {} ~TDummyScan() {} @@ -284,11 +284,11 @@ private: auto ctx = TActivationContext::AsActorContext(); ctx.RegisterWithSameMailbox(this); - if (Postponed) { - ctx.Send(Tablet, new NFake::TEvReturn); - return { EScan::Sleep, { } }; + if (Postponed) { + ctx.Send(Tablet, new NFake::TEvReturn); + return { EScan::Sleep, { } }; } else { - return { EScan::Feed, { } }; + return { EScan::Feed, { } }; } } @@ -297,7 +297,7 @@ private: if (seq && Abort == EAbort::None) return EScan::Final; - lead.To(Scheme->Tags(), { }, NTable::ESeek::Lower); + lead.To(Scheme->Tags(), { }, NTable::ESeek::Lower); return EScan::Feed; } @@ -315,22 +315,22 @@ private: auto ctx = TActivationContext::ActorContextFor(SelfId()); if (abort == EAbort::None) { - UNIT_ASSERT_VALUES_EQUAL(ExpectedRows, StoredRows); - } - + UNIT_ASSERT_VALUES_EQUAL(ExpectedRows, StoredRows); + } + Die(ctx); - return new TDummyResult(StoredRows, ExpectedRows); + return new TDummyResult(StoredRows, ExpectedRows); } private: TActorId Tablet; - IDriver *Driver = nullptr; + IDriver *Driver = nullptr; TIntrusiveConstPtr<TScheme> Scheme; - ui64 StoredRows = 0; - ui64 ExpectedRowId = 1; - ui64 ExpectedRows = 0; - bool Postponed = false; + ui64 StoredRows = 0; + ui64 ExpectedRowId = 1; + ui64 ExpectedRows = 0; + bool Postponed = false; EAbort Abort; }; @@ -348,12 +348,12 @@ struct TEvTestFlatTablet { struct TEvScanFinished : public TEventLocal<TEvScanFinished, EvScanFinished> {}; struct TEvQueueScan : public TEventLocal<TEvQueueScan, EvQueueScan> { - TEvQueueScan(ui32 rows, bool postponed = false, bool snap = false, NTable::EAbort abort = NTable::EAbort::None) - : Postponed(postponed) - , UseSnapshot(snap) + TEvQueueScan(ui32 rows, bool postponed = false, bool snap = false, NTable::EAbort abort = NTable::EAbort::None) + : Postponed(postponed) + , UseSnapshot(snap) , Abort(abort) , ReadVersion(TRowVersion::Max()) - , ExpectRows(rows) + , ExpectRows(rows) {} TEvQueueScan(ui32 rows, TRowVersion snapshot, bool postponed = false, NTable::EAbort abort = NTable::EAbort::None) @@ -364,11 +364,11 @@ struct TEvTestFlatTablet { , ExpectRows(rows) {} - bool Postponed; + bool Postponed; bool UseSnapshot; NTable::EAbort Abort; const TRowVersion ReadVersion; - const ui32 ExpectRows = 0; + const ui32 ExpectRows = 0; }; struct TEvStartQueuedScan : public TEventLocal<TEvStartQueuedScan, EvStartQueuedScan> {}; struct TEvMakeScanSnapshot : public TEventLocal<TEvMakeScanSnapshot, EvMakeScanSnapshot> {}; @@ -381,7 +381,7 @@ struct TEvTestFlatTablet { : SnapContext(std::move(snapContext)) { } }; -}; +}; class TTestTableSnapshotContext : public TTableSnapshotContext { public: @@ -422,26 +422,26 @@ class TTestFlatTablet : public TActor<TTestFlatTablet>, public TTabletExecutedFl void ScanComplete(NTable::EAbort, TAutoPtr<IDestructable>, ui64 cookie, const TActorContext&) override { UNIT_ASSERT_VALUES_EQUAL(cookie, ScanCookie); - Send(Sender, new TEvTestFlatTablet::TEvScanFinished); + Send(Sender, new TEvTestFlatTablet::TEvScanFinished); } - void Handle(TEvTestFlatTablet::TEvMakeScanSnapshot::TPtr&) { - SnapshotId = Executor()->MakeScanSnapshot(TRowsModel::TableId); + void Handle(TEvTestFlatTablet::TEvMakeScanSnapshot::TPtr&) { + SnapshotId = Executor()->MakeScanSnapshot(TRowsModel::TableId); UNIT_ASSERT(SnapshotId); - Send(Sender, new TEvents::TEvWakeup); + Send(Sender, new TEvents::TEvWakeup); } void Handle(TEvTestFlatTablet::TEvCancelScan::TPtr &/*ev*/, const TActorContext &ctx) { - Executor()->CancelScan(TRowsModel::TableId, ScanTaskId); + Executor()->CancelScan(TRowsModel::TableId, ScanTaskId); ctx.Send(Sender, new TEvents::TEvWakeup); } - void Handle(TEvTestFlatTablet::TEvQueueScan::TPtr &ev) { - bool postpone = ev->Get()->Postponed; + void Handle(TEvTestFlatTablet::TEvQueueScan::TPtr &ev) { + bool postpone = ev->Get()->Postponed; ui64 snap = ev->Get()->UseSnapshot ? SnapshotId : 0; auto abort = ev->Get()->Abort; - auto rows = abort != NTable::EAbort::None ? 0 : ev->Get()->ExpectRows; - Scan = new TDummyScan(SelfId(), postpone, abort, rows); + auto rows = abort != NTable::EAbort::None ? 0 : ev->Get()->ExpectRows; + Scan = new TDummyScan(SelfId(), postpone, abort, rows); TScanOptions options; if (snap) { Y_VERIFY(ev->Get()->ReadVersion.IsMax(), "Cannot combine multiple snapshot techniques"); @@ -456,7 +456,7 @@ class TTestFlatTablet : public TActor<TTestFlatTablet>, public TTabletExecutedFl ctx.Send(Scan->SelfId(), new TEvents::TEvWakeup); } - void Handle(NFake::TEvExecute::TPtr &ev, const TActorContext &ctx) { + void Handle(NFake::TEvExecute::TPtr &ev, const TActorContext &ctx) { for (auto& f : ev->Get()->Funcs) { if (auto* tx = dynamic_cast<ITransactionWithExecutor*>(f.Get())) { tx->Executor = Executor(); @@ -474,19 +474,19 @@ class TTestFlatTablet : public TActor<TTestFlatTablet>, public TTabletExecutedFl Send(Sender, new TEvents::TEvWakeup); } - void Handle(NFake::TEvReturn::TPtr&, const TActorContext&) { - Send(Sender, new TEvents::TEvWakeup); + void Handle(NFake::TEvReturn::TPtr&, const TActorContext&) { + Send(Sender, new TEvents::TEvWakeup); } - void Handle(TEvents::TEvPoison::TPtr &, const TActorContext &ctx) { + void Handle(TEvents::TEvPoison::TPtr &, const TActorContext &ctx) { Become(&TThis::StateBroken); - Executor()->DetachTablet(ctx), Detach(ctx); /* see TDummy tablet */ - ctx.Send(Sender, new TEvents::TEvGone); + Executor()->DetachTablet(ctx), Detach(ctx); /* see TDummy tablet */ + ctx.Send(Sender, new TEvents::TEvGone); } - void OnActivateExecutor(const TActorContext&) override { + void OnActivateExecutor(const TActorContext&) override { Become(&TThis::StateWork); - Send(Sender, new TEvents::TEvWakeup); + Send(Sender, new TEvents::TEvWakeup); } void OnDetach(const TActorContext &ctx) override { @@ -500,7 +500,7 @@ class TTestFlatTablet : public TActor<TTestFlatTablet>, public TTabletExecutedFl public: TTestFlatTablet(const TActorId &sender, const TActorId &tablet, TTabletStorageInfo *info) : TActor(&TThis::StateInit) - , TTabletExecutedFlat(info, tablet, nullptr) + , TTabletExecutedFlat(info, tablet, nullptr) , Scan(nullptr) , ScanTaskId(0) , ScanCookie(123) @@ -514,15 +514,15 @@ public: STFUNC(StateWork) { switch (ev->GetTypeRewrite()) { - hFunc(TEvTestFlatTablet::TEvQueueScan, Handle); + hFunc(TEvTestFlatTablet::TEvQueueScan, Handle); HFunc(TEvTestFlatTablet::TEvStartQueuedScan, Handle); - hFunc(TEvTestFlatTablet::TEvMakeScanSnapshot, Handle); + hFunc(TEvTestFlatTablet::TEvMakeScanSnapshot, Handle); HFunc(TEvTestFlatTablet::TEvCancelScan, Handle); - HFunc(NFake::TEvExecute, Handle); + HFunc(NFake::TEvExecute, Handle); HFunc(NFake::TEvCompact, Handle); HFunc(TEvTablet::TEvTabletDead, HandleTabletDead); - HFunc(NFake::TEvReturn, Handle); - HFunc(TEvents::TEvPoison, Handle); + HFunc(NFake::TEvReturn, Handle); + HFunc(TEvents::TEvPoison, Handle); default: HandleDefaultEvents(ev, ctx); break; @@ -548,17 +548,17 @@ public: */ Y_UNIT_TEST_SUITE(TFlatTableCompactionScan) { Y_UNIT_TEST(TestCompactionScan) { - TMyEnvBase env; - TRowsModel data; - - env->SetLogPriority(NKikimrServices::RESOURCE_BROKER, NActors::NLog::PRI_DEBUG); + TMyEnvBase env; + TRowsModel data; + env->SetLogPriority(NKikimrServices::RESOURCE_BROKER, NActors::NLog::PRI_DEBUG); + env.FireTablet(env.Edge, env.Tablet, [&env](const TActorId &tablet, TTabletStorageInfo *info) { - return new TTestFlatTablet(env.Edge, tablet, info); - }); - - env.WaitForWakeUp(); - + return new TTestFlatTablet(env.Edge, tablet, info); + }); + + env.WaitForWakeUp(); + TIntrusivePtr<TCompactionPolicy> policy = new TCompactionPolicy(); policy->InMemSizeToSnapshot = 40 * 1024 *1024; policy->InMemStepsToSnapshot = 10; @@ -577,189 +577,189 @@ Y_UNIT_TEST_SUITE(TFlatTableCompactionScan) { gen.UpliftPartSize = 0; } - env.SendSync(data.MakeScheme(std::move(policy))); - env.SendAsync(data.MakeRows(249)); + env.SendSync(data.MakeScheme(std::move(policy))); + env.SendAsync(data.MakeRows(249)); env.WaitFor<NFake::TEvCompacted>(28); - env.WaitForWakeUp(); + env.WaitForWakeUp(); - env.SendSync(new TEvTestFlatTablet::TEvQueueScan(data.Rows(), true)); - env.SendAsync(data.MakeRows(1)); + env.SendSync(new TEvTestFlatTablet::TEvQueueScan(data.Rows(), true)); + env.SendAsync(data.MakeRows(1)); env.WaitFor<NFake::TEvCompacted>(3); - env.WaitForWakeUp(); - env.SendAsync(new TEvTestFlatTablet::TEvStartQueuedScan()); - TAutoPtr<IEventHandle> handle; - env->GrabEdgeEventRethrow<TEvTestFlatTablet::TEvScanFinished>(handle); - env.SendSync(new TEvents::TEvPoison, false, true); + env.WaitForWakeUp(); + env.SendAsync(new TEvTestFlatTablet::TEvStartQueuedScan()); + TAutoPtr<IEventHandle> handle; + env->GrabEdgeEventRethrow<TEvTestFlatTablet::TEvScanFinished>(handle); + env.SendSync(new TEvents::TEvPoison, false, true); } } Y_UNIT_TEST_SUITE(TFlatTableExecutorTxLimit) { - struct TTxSchema : public ITransaction { + struct TTxSchema : public ITransaction { TTxSchema(TActorId owner) : Owner(owner) { } - bool Execute(TTransactionContext &txc, const TActorContext&) override - { - txc.DB.Alter().SetExecutorLimitInFlyTx(2); + bool Execute(TTransactionContext &txc, const TActorContext&) override + { + txc.DB.Alter().SetExecutorLimitInFlyTx(2); - return true; - } + return true; + } - void Complete(const TActorContext &ctx) override - { - ctx.Send(Owner, new NFake::TEvResult); - } + void Complete(const TActorContext &ctx) override + { + ctx.Send(Owner, new NFake::TEvResult); + } const TActorId Owner; - }; + }; - struct TTxNoop : public ITransaction { + struct TTxNoop : public ITransaction { TTxNoop(TActorId owner) : Owner(owner) { } - bool Execute(TTransactionContext&, const TActorContext&) override - { - return true; - } + bool Execute(TTransactionContext&, const TActorContext&) override + { + return true; + } - void Complete(const TActorContext &ctx) override - { - ctx.Send(Owner, new NFake::TEvResult); - } + void Complete(const TActorContext &ctx) override + { + ctx.Send(Owner, new NFake::TEvResult); + } const TActorId Owner; - }; + }; - Y_UNIT_TEST(TestExecutorTxLimit) { - TMyEnvBase env; + Y_UNIT_TEST(TestExecutorTxLimit) { + TMyEnvBase env; - env.FireDummyTablet(); - env.SendAsync(new NFake::TEvExecute{ new TTxSchema(env.Edge) }); - env.WaitFor<NFake::TEvResult>(); + env.FireDummyTablet(); + env.SendAsync(new NFake::TEvExecute{ new TTxSchema(env.Edge) }); + env.WaitFor<NFake::TEvResult>(); - for (size_t seq = 0; seq++ < 5;) - env.SendAsync(new NFake::TEvExecute{ new TTxNoop(env.Edge) }); + for (size_t seq = 0; seq++ < 5;) + env.SendAsync(new NFake::TEvExecute{ new TTxNoop(env.Edge) }); - env.WaitFor<NFake::TEvResult>(5); - env.SendSync(new TEvents::TEvPoison, false, true); - } -} + env.WaitFor<NFake::TEvResult>(5); + env.SendSync(new TEvents::TEvPoison, false, true); + } +} -Y_UNIT_TEST_SUITE(TFlatTableBackgroundCompactions) { +Y_UNIT_TEST_SUITE(TFlatTableBackgroundCompactions) { - using namespace NKikimrResourceBroker; - using namespace NResourceBroker; + using namespace NKikimrResourceBroker; + using namespace NResourceBroker; - struct TIsTaskSubmission { - TIsTaskSubmission(const TString &type, ui32 maxPriority = Max<ui32>()) - : Type(type) - , MaxPriority(maxPriority) - {} + struct TIsTaskSubmission { + TIsTaskSubmission(const TString &type, ui32 maxPriority = Max<ui32>()) + : Type(type) + , MaxPriority(maxPriority) + {} - bool operator()(IEventHandle &ev) { - if (ev.GetTypeRewrite() == NResourceBroker::TEvResourceBroker::EvSubmitTask) { - auto *e = ev.Get<NResourceBroker::TEvResourceBroker::TEvSubmitTask>(); - if (e->Task.Type == Type && e->Task.Priority <= MaxPriority) { - return true; - } + bool operator()(IEventHandle &ev) { + if (ev.GetTypeRewrite() == NResourceBroker::TEvResourceBroker::EvSubmitTask) { + auto *e = ev.Get<NResourceBroker::TEvResourceBroker::TEvSubmitTask>(); + if (e->Task.Type == Type && e->Task.Priority <= MaxPriority) { + return true; + } } - return false; + return false; } - TString Type; - ui32 MaxPriority; - }; + TString Type; + ui32 MaxPriority; + }; - struct TIsTaskUpdate { - TIsTaskUpdate(const TString &type, ui32 maxPriority = Max<ui32>()) - : Type(type) - , MaxPriority(maxPriority) - {} + struct TIsTaskUpdate { + TIsTaskUpdate(const TString &type, ui32 maxPriority = Max<ui32>()) + : Type(type) + , MaxPriority(maxPriority) + {} - bool operator()(IEventHandle &ev) { - if (ev.GetTypeRewrite() == NResourceBroker::TEvResourceBroker::EvUpdateTask) { - auto *e = ev.Get<NResourceBroker::TEvResourceBroker::TEvUpdateTask>(); - if (e->Type == Type && e->Priority <= MaxPriority) - return true; - } + bool operator()(IEventHandle &ev) { + if (ev.GetTypeRewrite() == NResourceBroker::TEvResourceBroker::EvUpdateTask) { + auto *e = ev.Get<NResourceBroker::TEvResourceBroker::TEvUpdateTask>(); + if (e->Type == Type && e->Priority <= MaxPriority) + return true; + } - return false; + return false; } - TString Type; - ui32 MaxPriority; - }; + TString Type; + ui32 MaxPriority; + }; - struct TIsResourceAllocation { - TIsResourceAllocation() + struct TIsResourceAllocation { + TIsResourceAllocation() {} - bool operator()(IEventHandle &ev) { - if (ev.GetTypeRewrite() == NResourceBroker::TEvResourceBroker::EvResourceAllocated) - return true; + bool operator()(IEventHandle &ev) { + if (ev.GetTypeRewrite() == NResourceBroker::TEvResourceBroker::EvResourceAllocated) + return true; - return false; + return false; } }; - struct TMyEnvCompaction : public TMyEnvBase { - TMyEnvCompaction() - { - Env.SetLogPriority(NKikimrServices::RESOURCE_BROKER, NActors::NLog::PRI_DEBUG); - FireDummyTablet(); - SendSync(Rows.MakeScheme(MakeCompactionPolicy())); - } - - ~TMyEnvCompaction() - { - SendSync(new TEvents::TEvPoison, false, true); - } - - void BlockBackgroundQueue(ui64 block = 0, ui64 level = 0, bool instant = true) - { - ui64 id = 987987987987 + block; - TAutoPtr<TEvResourceBroker::TEvSubmitTask> event - = new TEvResourceBroker::TEvSubmitTask(id, - "bckg-block", - {{1, 0}}, - "background_compaction", - level, - nullptr); - SendEv(MakeResourceBrokerID(), event.Release()); - - if (instant) { - TAutoPtr<IEventHandle> handle; - auto reply = Env.GrabEdgeEventRethrow<TEvResourceBroker::TEvResourceAllocated>(handle); - UNIT_ASSERT_VALUES_EQUAL(reply->TaskId, id); - } - } - - void UnblockBackgroundQueue(ui64 block = 0) - { - ui64 id = 987987987987 + block; - TAutoPtr<TEvResourceBroker::TEvFinishTask> event - = new TEvResourceBroker::TEvFinishTask(id); - SendEv(MakeResourceBrokerID(), event.Release()); - } - - static TCompactionPolicy* MakeCompactionPolicy() noexcept - { - auto *policy = new TCompactionPolicy(); - policy->InMemSizeToSnapshot = 40 * 1024 *1024; - policy->InMemStepsToSnapshot = 10; - policy->InMemForceStepsToSnapshot = 10; - policy->InMemForceSizeToSnapshot = 64 * 1024 * 1024; - policy->InMemResourceBrokerTask = NLocalDb::LegacyQueueIdToTaskName(0); - policy->ReadAheadHiThreshold = 100000; - policy->ReadAheadLoThreshold = 50000; - policy->BackgroundSnapshotPolicy.Threshold = 50; - policy->BackgroundSnapshotPolicy.ResourceBrokerTask = "background_compaction_gen0"; - policy->Generations.push_back({100 * 1024 * 1024, 10, 10, 200 * 1024 * 1024, NLocalDb::LegacyQueueIdToTaskName(1), true, - {50, 100, 0.0, "background_compaction_gen1"}}); - policy->Generations.push_back({400 * 1024 * 1024, 10, 10, 800 * 1024 * 1024, NLocalDb::LegacyQueueIdToTaskName(2), false, - {50, 200, 1.0, "background_compaction_gen2"}}); + struct TMyEnvCompaction : public TMyEnvBase { + TMyEnvCompaction() + { + Env.SetLogPriority(NKikimrServices::RESOURCE_BROKER, NActors::NLog::PRI_DEBUG); + FireDummyTablet(); + SendSync(Rows.MakeScheme(MakeCompactionPolicy())); + } + + ~TMyEnvCompaction() + { + SendSync(new TEvents::TEvPoison, false, true); + } + + void BlockBackgroundQueue(ui64 block = 0, ui64 level = 0, bool instant = true) + { + ui64 id = 987987987987 + block; + TAutoPtr<TEvResourceBroker::TEvSubmitTask> event + = new TEvResourceBroker::TEvSubmitTask(id, + "bckg-block", + {{1, 0}}, + "background_compaction", + level, + nullptr); + SendEv(MakeResourceBrokerID(), event.Release()); + + if (instant) { + TAutoPtr<IEventHandle> handle; + auto reply = Env.GrabEdgeEventRethrow<TEvResourceBroker::TEvResourceAllocated>(handle); + UNIT_ASSERT_VALUES_EQUAL(reply->TaskId, id); + } + } + + void UnblockBackgroundQueue(ui64 block = 0) + { + ui64 id = 987987987987 + block; + TAutoPtr<TEvResourceBroker::TEvFinishTask> event + = new TEvResourceBroker::TEvFinishTask(id); + SendEv(MakeResourceBrokerID(), event.Release()); + } + + static TCompactionPolicy* MakeCompactionPolicy() noexcept + { + auto *policy = new TCompactionPolicy(); + policy->InMemSizeToSnapshot = 40 * 1024 *1024; + policy->InMemStepsToSnapshot = 10; + policy->InMemForceStepsToSnapshot = 10; + policy->InMemForceSizeToSnapshot = 64 * 1024 * 1024; + policy->InMemResourceBrokerTask = NLocalDb::LegacyQueueIdToTaskName(0); + policy->ReadAheadHiThreshold = 100000; + policy->ReadAheadLoThreshold = 50000; + policy->BackgroundSnapshotPolicy.Threshold = 50; + policy->BackgroundSnapshotPolicy.ResourceBrokerTask = "background_compaction_gen0"; + policy->Generations.push_back({100 * 1024 * 1024, 10, 10, 200 * 1024 * 1024, NLocalDb::LegacyQueueIdToTaskName(1), true, + {50, 100, 0.0, "background_compaction_gen1"}}); + policy->Generations.push_back({400 * 1024 * 1024, 10, 10, 800 * 1024 * 1024, NLocalDb::LegacyQueueIdToTaskName(2), false, + {50, 200, 1.0, "background_compaction_gen2"}}); for (auto& gen : policy->Generations) { gen.ExtraCompactionPercent = 0; gen.ExtraCompactionMinSize = 0; @@ -767,120 +767,120 @@ Y_UNIT_TEST_SUITE(TFlatTableBackgroundCompactions) { gen.ExtraCompactionExpMaxSize = 0; gen.UpliftPartSize = 0; } - return policy; - } - - TRowsModel Rows; - }; + return policy; + } + + TRowsModel Rows; + }; Y_UNIT_TEST(TestRunBackgroundSnapshot) { - TMyEnvCompaction env; + TMyEnvCompaction env; - env.SendAsync(env.Rows.MakeRows(5)); + env.SendAsync(env.Rows.MakeRows(5)); TDispatchOptions options; options.FinalEvents.emplace_back(TIsTaskSubmission("background_compaction_gen0")); - env->DispatchEvents(options); + env->DispatchEvents(options); } Y_UNIT_TEST(TestChangeBackgroundSnapshotToRegular) { - TMyEnvCompaction env; + TMyEnvCompaction env; - env.BlockBackgroundQueue(); + env.BlockBackgroundQueue(); - env.SendAsync(env.Rows.MakeRows(5)); + env.SendAsync(env.Rows.MakeRows(5)); TDispatchOptions options1; options1.FinalEvents.emplace_back(TIsTaskSubmission("background_compaction_gen0")); - env->DispatchEvents(options1); + env->DispatchEvents(options1); - env.SendAsync(env.Rows.MakeRows(5)); + env.SendAsync(env.Rows.MakeRows(5)); TDispatchOptions options2; options2.FinalEvents.emplace_back(TIsTaskUpdate("compaction_gen0", 5)); - env->DispatchEvents(options2); + env->DispatchEvents(options2); } Y_UNIT_TEST(TestRunBackgroundCompactionGen1) { - TMyEnvCompaction env; + TMyEnvCompaction env; - env.BlockBackgroundQueue(); - env.SendAsync(env.Rows.MakeRows(50)); + env.BlockBackgroundQueue(); + env.SendAsync(env.Rows.MakeRows(50)); TDispatchOptions options; options.FinalEvents.emplace_back(TIsTaskSubmission("background_compaction_gen1")); - env->DispatchEvents(options); + env->DispatchEvents(options); } Y_UNIT_TEST(TestChangeBackgroundCompactionToRegular) { - TMyEnvCompaction env; + TMyEnvCompaction env; - env.BlockBackgroundQueue(); - env.SendAsync(env.Rows.MakeRows(50)); + env.BlockBackgroundQueue(); + env.SendAsync(env.Rows.MakeRows(50)); TDispatchOptions options1; options1.FinalEvents.emplace_back(TIsTaskSubmission("background_compaction_gen1")); - env->DispatchEvents(options1); - - env.SendAsync(env.Rows.MakeRows(50)); + env->DispatchEvents(options1); + env.SendAsync(env.Rows.MakeRows(50)); + TDispatchOptions options2; options2.FinalEvents.emplace_back(TIsTaskUpdate("compaction_gen1", 5)); - env->DispatchEvents(options2); + env->DispatchEvents(options2); } Y_UNIT_TEST(TestRunBackgroundCompactionGen2) { - TMyEnvCompaction env; + TMyEnvCompaction env; - env.BlockBackgroundQueue(); - env.SendAsync(env.Rows.MakeRows(500)); + env.BlockBackgroundQueue(); + env.SendAsync(env.Rows.MakeRows(500)); TDispatchOptions options; options.FinalEvents.emplace_back(TIsTaskSubmission("background_compaction_gen2")); - env->DispatchEvents(options); + env->DispatchEvents(options); } Y_UNIT_TEST(TestChangeBackgroundSnapshotPriorityByTime) { - TMyEnvCompaction env; + TMyEnvCompaction env; - env.BlockBackgroundQueue(); - env.SendAsync(env.Rows.MakeRows(5)); + env.BlockBackgroundQueue(); + env.SendAsync(env.Rows.MakeRows(5)); TDispatchOptions options1; options1.FinalEvents.emplace_back(TIsTaskSubmission("background_compaction_gen0")); - env->DispatchEvents(options1); + env->DispatchEvents(options1); TDispatchOptions options2; options2.FinalEvents.emplace_back(TIsTaskUpdate("background_compaction_gen0", 50)); - env->SetDispatchTimeout(TDuration::Minutes(1)); - env->DispatchEvents(options2); + env->SetDispatchTimeout(TDuration::Minutes(1)); + env->DispatchEvents(options2); } Y_UNIT_TEST(TestChangeBackgroundCompactionPriorityByTime) { - TMyEnvCompaction env; + TMyEnvCompaction env; - env.BlockBackgroundQueue(); - env.SendAsync(env.Rows.MakeRows(550)); + env.BlockBackgroundQueue(); + env.SendAsync(env.Rows.MakeRows(550)); TDispatchOptions options1; options1.FinalEvents.emplace_back(TIsTaskSubmission("background_compaction_gen1"), 6); options1.FinalEvents.emplace_back(TIsTaskSubmission("background_compaction_gen2")); - env->DispatchEvents(options1); + env->DispatchEvents(options1); TDispatchOptions options2; options2.FinalEvents.emplace_back(TIsTaskUpdate("background_compaction_gen2", 100)); - env->SetDispatchTimeout(TDuration::Minutes(1)); - env->DispatchEvents(options2); - + env->SetDispatchTimeout(TDuration::Minutes(1)); + env->DispatchEvents(options2); + // GEN2 compaction should become more prioritized due to time factor. TDispatchOptions options3; - env.BlockBackgroundQueue(1, 150, false); - env.UnblockBackgroundQueue(); + env.BlockBackgroundQueue(1, 150, false); + env.UnblockBackgroundQueue(); options3.FinalEvents.emplace_back(TIsResourceAllocation()); - env->DispatchEvents(options3); - - env.SendAsync(env.Rows.MakeRows(10)); + env->DispatchEvents(options3); + env.SendAsync(env.Rows.MakeRows(10)); + TDispatchOptions options4; options4.FinalEvents.emplace_back(TIsTaskUpdate("background_compaction_gen1", 170)); - env->DispatchEvents(options4); + env->DispatchEvents(options4); } } @@ -890,54 +890,54 @@ Y_UNIT_TEST_SUITE(TFlatTablePostponedScan) { using namespace NKikimrResourceBroker; using namespace NResourceBroker; - struct TMyEnvScans : public TMyEnvBase { - - TMyEnvScans() - { - Env.SetLogPriority(NKikimrServices::RESOURCE_BROKER, NActors::NLog::PRI_INFO); - Env.SetLogPriority(NKikimrServices::TABLET_EXECUTOR, NActors::NLog::PRI_INFO); - Env.SetLogPriority(NKikimrServices::TABLET_OPS_HOST, NActors::NLog::PRI_INFO); + struct TMyEnvScans : public TMyEnvBase { + + TMyEnvScans() + { + Env.SetLogPriority(NKikimrServices::RESOURCE_BROKER, NActors::NLog::PRI_INFO); + Env.SetLogPriority(NKikimrServices::TABLET_EXECUTOR, NActors::NLog::PRI_INFO); + Env.SetLogPriority(NKikimrServices::TABLET_OPS_HOST, NActors::NLog::PRI_INFO); FireTablet(Edge, Tablet, [this](const TActorId &tablet, TTabletStorageInfo *info) { - return new TTestFlatTablet(Edge, tablet, info); + return new TTestFlatTablet(Edge, tablet, info); }); - WaitForWakeUp(); - - SendSync(Rows.MakeScheme(MakeCompactionPolicy())); - } - - ~TMyEnvScans() - { - SendSync(new TEvents::TEvPoison, false, true); - } - - static TCompactionPolicy* MakeCompactionPolicy() noexcept - { - auto *policy = new TCompactionPolicy(); - policy->InMemSizeToSnapshot = 40 * 1024 *1024; - policy->InMemStepsToSnapshot = 10; - policy->InMemForceStepsToSnapshot = 10; - policy->InMemForceSizeToSnapshot = 64 * 1024 * 1024; - policy->InMemResourceBrokerTask = NLocalDb::LegacyQueueIdToTaskName(0); - policy->ReadAheadHiThreshold = 100000; - policy->ReadAheadLoThreshold = 50000; - policy->Generations.push_back({100 * 1024 * 1024, 10, 10, 200 * 1024 * 1024, NLocalDb::LegacyQueueIdToTaskName(1), true}); - return policy; - } - - TRowsModel Rows; - }; + WaitForWakeUp(); + + SendSync(Rows.MakeScheme(MakeCompactionPolicy())); + } + + ~TMyEnvScans() + { + SendSync(new TEvents::TEvPoison, false, true); + } + + static TCompactionPolicy* MakeCompactionPolicy() noexcept + { + auto *policy = new TCompactionPolicy(); + policy->InMemSizeToSnapshot = 40 * 1024 *1024; + policy->InMemStepsToSnapshot = 10; + policy->InMemForceStepsToSnapshot = 10; + policy->InMemForceSizeToSnapshot = 64 * 1024 * 1024; + policy->InMemResourceBrokerTask = NLocalDb::LegacyQueueIdToTaskName(0); + policy->ReadAheadHiThreshold = 100000; + policy->ReadAheadLoThreshold = 50000; + policy->Generations.push_back({100 * 1024 * 1024, 10, 10, 200 * 1024 * 1024, NLocalDb::LegacyQueueIdToTaskName(1), true}); + return policy; + } + + TRowsModel Rows; + }; Y_UNIT_TEST(TestPostponedScan) { - TMyEnvScans env; - TAutoPtr<IEventHandle> handle; - - env.SendSync(env.Rows.MakeRows(111)); - env.SendSync(new TEvTestFlatTablet::TEvMakeScanSnapshot); - env.SendSync(env.Rows.MakeRows(111)); - env.SendAsync(new TEvTestFlatTablet::TEvQueueScan(111, false, true)); - env->GrabEdgeEventRethrow<TEvTestFlatTablet::TEvScanFinished>(handle); + TMyEnvScans env; + TAutoPtr<IEventHandle> handle; + + env.SendSync(env.Rows.MakeRows(111)); + env.SendSync(new TEvTestFlatTablet::TEvMakeScanSnapshot); + env.SendSync(env.Rows.MakeRows(111)); + env.SendAsync(new TEvTestFlatTablet::TEvQueueScan(111, false, true)); + env->GrabEdgeEventRethrow<TEvTestFlatTablet::TEvScanFinished>(handle); } Y_UNIT_TEST(TestCancelFinishedScan) { @@ -953,14 +953,14 @@ Y_UNIT_TEST_SUITE(TFlatTablePostponedScan) { } Y_UNIT_TEST(TestCancelRunningPostponedScan) { - TMyEnvScans env; - TAutoPtr<IEventHandle> handle; + TMyEnvScans env; + TAutoPtr<IEventHandle> handle; - env.SendSync(env.Rows.MakeRows(111)); - env.SendSync(new TEvTestFlatTablet::TEvMakeScanSnapshot); - env.SendSync(new TEvTestFlatTablet::TEvQueueScan(111, true, true, NTable::EAbort::Term)); + env.SendSync(env.Rows.MakeRows(111)); + env.SendSync(new TEvTestFlatTablet::TEvMakeScanSnapshot); + env.SendSync(new TEvTestFlatTablet::TEvQueueScan(111, true, true, NTable::EAbort::Term)); env.SendSync(new TEvTestFlatTablet::TEvCancelScan); -// env->GrabEdgeEventRethrow<TEvTestFlatTablet::TEvScanFinished>(handle); +// env->GrabEdgeEventRethrow<TEvTestFlatTablet::TEvScanFinished>(handle); } Y_UNIT_TEST(TestPostponedScanSnapshotMVCC) { @@ -977,54 +977,54 @@ Y_UNIT_TEST_SUITE(TFlatTablePostponedScan) { Y_UNIT_TEST_SUITE(TFlatTableExecutorResourceProfile) { - struct TTaskSequence { - struct TEvent { - ui32 EventType; - TString TaskType; - }; - - TTaskSequence() - {} - - void Add(ui32 event, const TString &task = "") - { - Events.push_back({event, task}); - } - - bool operator()(IEventHandle &ev) { - if (Current == Events.size()) - return false; - - auto &event = Events[Current]; - bool match = false; - if (ev.GetTypeRewrite() == event.EventType) { - if (ev.GetTypeRewrite() == NResourceBroker::TEvResourceBroker::EvSubmitTask) { - auto *e = ev.Get<NResourceBroker::TEvResourceBroker::TEvSubmitTask>(); - if (e->Task.Type == event.TaskType) { - match = true; - } - } else if (ev.GetTypeRewrite() == NResourceBroker::TEvResourceBroker::EvUpdateTask) { - auto *e = ev.Get<NResourceBroker::TEvResourceBroker::TEvUpdateTask>(); - if (e->Type == event.TaskType) { - match = true; - } - } else { - Y_VERIFY(!event.TaskType); - match = true; - } - } - - if (match) { - ++Current; - } - - return Current == Events.size(); - } - - TVector<TEvent> Events; - size_t Current = 0; - }; - + struct TTaskSequence { + struct TEvent { + ui32 EventType; + TString TaskType; + }; + + TTaskSequence() + {} + + void Add(ui32 event, const TString &task = "") + { + Events.push_back({event, task}); + } + + bool operator()(IEventHandle &ev) { + if (Current == Events.size()) + return false; + + auto &event = Events[Current]; + bool match = false; + if (ev.GetTypeRewrite() == event.EventType) { + if (ev.GetTypeRewrite() == NResourceBroker::TEvResourceBroker::EvSubmitTask) { + auto *e = ev.Get<NResourceBroker::TEvResourceBroker::TEvSubmitTask>(); + if (e->Task.Type == event.TaskType) { + match = true; + } + } else if (ev.GetTypeRewrite() == NResourceBroker::TEvResourceBroker::EvUpdateTask) { + auto *e = ev.Get<NResourceBroker::TEvResourceBroker::TEvUpdateTask>(); + if (e->Type == event.TaskType) { + match = true; + } + } else { + Y_VERIFY(!event.TaskType); + match = true; + } + } + + if (match) { + ++Current; + } + + return Current == Events.size(); + } + + TVector<TEvent> Events; + size_t Current = 0; + }; + struct TMemoryCheckEntry { struct TEntryEvents { TString MergeTask; @@ -1139,233 +1139,233 @@ Y_UNIT_TEST_SUITE(TFlatTableExecutorResourceProfile) { {} }; - struct TTxSetResourceProfile : public ITransaction { - TString ProfileName; - - TTxSetResourceProfile(const TString &name) : ProfileName(name) {} - - bool Execute(TTransactionContext &txc, const TActorContext &) override { - txc.DB.Alter().SetExecutorResourceProfile(ProfileName); - return true; - } - - void Complete(const TActorContext &ctx) override { - ctx.Send(ctx.SelfID, new NFake::TEvReturn); - } - }; - - struct TTxCheckResourceProfile : public ITransaction { - TString ProfileName; - - TTxCheckResourceProfile(const TString &name) : ProfileName(name) {} - - bool Execute(TTransactionContext &txc, const TActorContext&) override { - UNIT_ASSERT_VALUES_EQUAL(txc.DB.GetScheme().Executor.ResourceProfile, ProfileName); - return true; - } - - void Complete(const TActorContext &ctx) override { - ctx.Send(ctx.SelfID, new NFake::TEvReturn); - } - }; - - struct TTxRequestMemory : public ITransaction { - struct TRequest { - TVector<ui64> Keys; - ui64 TxDataSize; - bool StaticResult; - bool OutOfMemoryResult; - bool Hold; - bool Use; - ui64 HoldSize; - bool Finish; - }; - - using TRequests = TVector<TRequest>; - - struct TCfg { - bool Static = false; - bool Dynamic = false; - }; - - const TCfg Cfg; - TRequests Requests; - size_t ReqNo = 0; - TAutoPtr<TMemoryToken> Token; - + struct TTxSetResourceProfile : public ITransaction { + TString ProfileName; + + TTxSetResourceProfile(const TString &name) : ProfileName(name) {} + + bool Execute(TTransactionContext &txc, const TActorContext &) override { + txc.DB.Alter().SetExecutorResourceProfile(ProfileName); + return true; + } + + void Complete(const TActorContext &ctx) override { + ctx.Send(ctx.SelfID, new NFake::TEvReturn); + } + }; + + struct TTxCheckResourceProfile : public ITransaction { + TString ProfileName; + + TTxCheckResourceProfile(const TString &name) : ProfileName(name) {} + + bool Execute(TTransactionContext &txc, const TActorContext&) override { + UNIT_ASSERT_VALUES_EQUAL(txc.DB.GetScheme().Executor.ResourceProfile, ProfileName); + return true; + } + + void Complete(const TActorContext &ctx) override { + ctx.Send(ctx.SelfID, new NFake::TEvReturn); + } + }; + + struct TTxRequestMemory : public ITransaction { + struct TRequest { + TVector<ui64> Keys; + ui64 TxDataSize; + bool StaticResult; + bool OutOfMemoryResult; + bool Hold; + bool Use; + ui64 HoldSize; + bool Finish; + }; + + using TRequests = TVector<TRequest>; + + struct TCfg { + bool Static = false; + bool Dynamic = false; + }; + + const TCfg Cfg; + TRequests Requests; + size_t ReqNo = 0; + TAutoPtr<TMemoryToken> Token; + TTxRequestMemory(TRequests requests, size_t reqNo, TAutoPtr<TMemoryToken> token, TCfg cfg) - : Cfg(cfg) - , Requests(requests) - , ReqNo(reqNo) - , Token(token) - {} - - bool Execute(TTransactionContext &txc, const TActorContext &/*ctx*/) override { - if (ReqNo) { - auto &prev = Requests[ReqNo - 1]; - - if (!prev.Finish) { - UNIT_ASSERT(!prev.OutOfMemoryResult); - UNIT_ASSERT(Cfg.Dynamic || Cfg.Static || prev.TxDataSize <= txc.GetMemoryLimit()); - if (prev.StaticResult) - UNIT_ASSERT_VALUES_EQUAL(txc.GetTaskId(), 0); - else - UNIT_ASSERT(txc.GetTaskId() > 0); - } - } - - if (ReqNo == Requests.size()) - return true; - - auto &req = Requests[ReqNo++]; - ui64 mem = txc.GetMemoryLimit(); - - if (req.Use) { - UNIT_ASSERT(Token); - mem = Token->GCToken->Size; - txc.UseMemoryToken(std::move(Token)); - Token = nullptr; - } - - if (req.Hold) { - if (req.HoldSize) { - Token = txc.HoldMemory(req.HoldSize); - if (!req.Use) - mem -= req.HoldSize; - } else { - Token = txc.HoldMemory(); - if (!req.Use) - mem = 0; - } - } - - if (req.Finish) - return true; - - if (req.TxDataSize) { - UNIT_ASSERT(req.TxDataSize >= mem); - txc.RequestMemory(req.TxDataSize - mem); - } else { - txc.RequestMemory(1); - } - - if (!req.Keys.empty()) { - for (auto val : req.Keys) { - ui64 key1 = val; - TRawTypeValue key[] = {TRawTypeValue(&key1, sizeof(key1), NScheme::NTypeIds::Int64)}; - NTable::TTag tags[] = {TRowsModel::ColumnKeyId}; - NTable::TRowState row; - txc.DB.Select(TRowsModel::TableId, {key, 1}, {tags, 1}, row); - } - } - - return false; - } - - void Complete(const TActorContext &ctx) override { - if (ReqNo) - UNIT_ASSERT(!Requests[ReqNo - 1].OutOfMemoryResult); - if (ReqNo == Requests.size()) - ctx.Send(ctx.SelfID, new NFake::TEvReturn); - else - ctx.Send(ctx.SelfID, new NFake::TEvExecute{ new TTxRequestMemory(Requests, ReqNo, std::move(Token), Cfg) }); - } - - void Terminate(ETerminationReason reason, const TActorContext &ctx) override { - UNIT_ASSERT_EQUAL(reason, ETerminationReason::MemoryLimitExceeded); - UNIT_ASSERT(ReqNo); - UNIT_ASSERT(Requests[ReqNo - 1].OutOfMemoryResult); - - ctx.Send(ctx.SelfID, new NFake::TEvReturn); - } - - void ReleaseTxData(TTxMemoryProvider &provider, const TActorContext &/*ctx*/) override { - if ((provider.GetTaskId() && Cfg.Dynamic) - || (!provider.GetTaskId() && Cfg.Static)) - Token = provider.HoldMemory(); - } - }; - - struct TMyEnvProfiles : public TMyEnvBase { - - TMyEnvProfiles() - { - Env.SetLogPriority(NKikimrServices::RESOURCE_BROKER, NActors::NLog::PRI_DEBUG); - Env.SetLogPriority(NKikimrServices::TABLET_EXECUTOR, NActors::NLog::PRI_DEBUG); - SetupProfile("profile1"); - FireDummyTablet(); - SendSync(Rows.MakeScheme(MakeCompactionPolicy())); - SendSync(new NFake::TEvExecute(new TTxSetResourceProfile("profile1"))); - - Profile = Env.GetAppData().ResourceProfiles->GetProfile(NKikimrTabletBase::TTabletTypes::Unknown, "profile1"); - } - - ~TMyEnvProfiles() - { - SendSync(new TEvents::TEvPoison, false, true); - } - - static TCompactionPolicy* MakeCompactionPolicy() noexcept - { - auto *policy = new TCompactionPolicy(); - policy->InMemSizeToSnapshot = 40 * 1024 *1024; - policy->InMemStepsToSnapshot = 5; - policy->InMemForceStepsToSnapshot = 5; - policy->InMemForceSizeToSnapshot = 64 * 1024 * 1024; - policy->InMemResourceBrokerTask = NLocalDb::LegacyQueueIdToTaskName(0); - policy->ReadAheadHiThreshold = 100000; - policy->ReadAheadLoThreshold = 50000; - policy->Generations.push_back({100 * 1024 * 1024, 100, 100, 200 * 1024 * 1024, NLocalDb::LegacyQueueIdToTaskName(1), true}); - return policy; - } - - void SetupProfile(const TString profileName) - { - auto &appData = Env.GetAppData(); - appData.ResourceProfiles = new TResourceProfiles; - - TResourceProfiles::TResourceProfile profile; - profile.SetTabletType(NKikimrTabletBase::TTabletTypes::Unknown); - profile.SetName(profileName); - profile.SetStaticTabletTxMemoryLimit(100 << 20); - profile.SetStaticTxMemoryLimit(15 << 10); - profile.SetTxMemoryLimit(300 << 20); - profile.SetInitialTxMemory(1 << 10); - profile.SetSmallTxMemoryLimit(40 << 10); - profile.SetMediumTxMemoryLimit(100 << 10); - profile.SetSmallTxTaskType("small_transaction"); - profile.SetMediumTxTaskType("medium_transaction"); - profile.SetLargeTxTaskType("large_transaction"); - appData.ResourceProfiles->AddProfile(profile); - } - - void CheckMemoryRequest(std::initializer_list<TMemoryCheckEntry> list, + : Cfg(cfg) + , Requests(requests) + , ReqNo(reqNo) + , Token(token) + {} + + bool Execute(TTransactionContext &txc, const TActorContext &/*ctx*/) override { + if (ReqNo) { + auto &prev = Requests[ReqNo - 1]; + + if (!prev.Finish) { + UNIT_ASSERT(!prev.OutOfMemoryResult); + UNIT_ASSERT(Cfg.Dynamic || Cfg.Static || prev.TxDataSize <= txc.GetMemoryLimit()); + if (prev.StaticResult) + UNIT_ASSERT_VALUES_EQUAL(txc.GetTaskId(), 0); + else + UNIT_ASSERT(txc.GetTaskId() > 0); + } + } + + if (ReqNo == Requests.size()) + return true; + + auto &req = Requests[ReqNo++]; + ui64 mem = txc.GetMemoryLimit(); + + if (req.Use) { + UNIT_ASSERT(Token); + mem = Token->GCToken->Size; + txc.UseMemoryToken(std::move(Token)); + Token = nullptr; + } + + if (req.Hold) { + if (req.HoldSize) { + Token = txc.HoldMemory(req.HoldSize); + if (!req.Use) + mem -= req.HoldSize; + } else { + Token = txc.HoldMemory(); + if (!req.Use) + mem = 0; + } + } + + if (req.Finish) + return true; + + if (req.TxDataSize) { + UNIT_ASSERT(req.TxDataSize >= mem); + txc.RequestMemory(req.TxDataSize - mem); + } else { + txc.RequestMemory(1); + } + + if (!req.Keys.empty()) { + for (auto val : req.Keys) { + ui64 key1 = val; + TRawTypeValue key[] = {TRawTypeValue(&key1, sizeof(key1), NScheme::NTypeIds::Int64)}; + NTable::TTag tags[] = {TRowsModel::ColumnKeyId}; + NTable::TRowState row; + txc.DB.Select(TRowsModel::TableId, {key, 1}, {tags, 1}, row); + } + } + + return false; + } + + void Complete(const TActorContext &ctx) override { + if (ReqNo) + UNIT_ASSERT(!Requests[ReqNo - 1].OutOfMemoryResult); + if (ReqNo == Requests.size()) + ctx.Send(ctx.SelfID, new NFake::TEvReturn); + else + ctx.Send(ctx.SelfID, new NFake::TEvExecute{ new TTxRequestMemory(Requests, ReqNo, std::move(Token), Cfg) }); + } + + void Terminate(ETerminationReason reason, const TActorContext &ctx) override { + UNIT_ASSERT_EQUAL(reason, ETerminationReason::MemoryLimitExceeded); + UNIT_ASSERT(ReqNo); + UNIT_ASSERT(Requests[ReqNo - 1].OutOfMemoryResult); + + ctx.Send(ctx.SelfID, new NFake::TEvReturn); + } + + void ReleaseTxData(TTxMemoryProvider &provider, const TActorContext &/*ctx*/) override { + if ((provider.GetTaskId() && Cfg.Dynamic) + || (!provider.GetTaskId() && Cfg.Static)) + Token = provider.HoldMemory(); + } + }; + + struct TMyEnvProfiles : public TMyEnvBase { + + TMyEnvProfiles() + { + Env.SetLogPriority(NKikimrServices::RESOURCE_BROKER, NActors::NLog::PRI_DEBUG); + Env.SetLogPriority(NKikimrServices::TABLET_EXECUTOR, NActors::NLog::PRI_DEBUG); + SetupProfile("profile1"); + FireDummyTablet(); + SendSync(Rows.MakeScheme(MakeCompactionPolicy())); + SendSync(new NFake::TEvExecute(new TTxSetResourceProfile("profile1"))); + + Profile = Env.GetAppData().ResourceProfiles->GetProfile(NKikimrTabletBase::TTabletTypes::Unknown, "profile1"); + } + + ~TMyEnvProfiles() + { + SendSync(new TEvents::TEvPoison, false, true); + } + + static TCompactionPolicy* MakeCompactionPolicy() noexcept + { + auto *policy = new TCompactionPolicy(); + policy->InMemSizeToSnapshot = 40 * 1024 *1024; + policy->InMemStepsToSnapshot = 5; + policy->InMemForceStepsToSnapshot = 5; + policy->InMemForceSizeToSnapshot = 64 * 1024 * 1024; + policy->InMemResourceBrokerTask = NLocalDb::LegacyQueueIdToTaskName(0); + policy->ReadAheadHiThreshold = 100000; + policy->ReadAheadLoThreshold = 50000; + policy->Generations.push_back({100 * 1024 * 1024, 100, 100, 200 * 1024 * 1024, NLocalDb::LegacyQueueIdToTaskName(1), true}); + return policy; + } + + void SetupProfile(const TString profileName) + { + auto &appData = Env.GetAppData(); + appData.ResourceProfiles = new TResourceProfiles; + + TResourceProfiles::TResourceProfile profile; + profile.SetTabletType(NKikimrTabletBase::TTabletTypes::Unknown); + profile.SetName(profileName); + profile.SetStaticTabletTxMemoryLimit(100 << 20); + profile.SetStaticTxMemoryLimit(15 << 10); + profile.SetTxMemoryLimit(300 << 20); + profile.SetInitialTxMemory(1 << 10); + profile.SetSmallTxMemoryLimit(40 << 10); + profile.SetMediumTxMemoryLimit(100 << 10); + profile.SetSmallTxTaskType("small_transaction"); + profile.SetMediumTxTaskType("medium_transaction"); + profile.SetLargeTxTaskType("large_transaction"); + appData.ResourceProfiles->AddProfile(profile); + } + + void CheckMemoryRequest(std::initializer_list<TMemoryCheckEntry> list, TTxRequestMemory::TCfg cfg = { }, bool follower = false) - { + { TAutoPtr<TTxRequestMemory> event = new TTxRequestMemory({ }, 0, nullptr, cfg); - - TTaskSequence sequence; - - for (auto &entry : list) { - event->Requests.push_back({entry.Keys, entry.NewSize, entry.Static, entry.OutOfMemory, - entry.Hold, entry.Use, entry.HoldSize, entry.Finish}); - if (entry.Events.MergeTask) { - sequence.Add(NResourceBroker::TEvResourceBroker::EvUpdateTask, entry.Events.MergeTask); - sequence.Add(NResourceBroker::TEvResourceBroker::EvFinishTask); - } - if (entry.Events.UpdateTask) { - sequence.Add(NResourceBroker::TEvResourceBroker::EvUpdateTask, entry.Events.UpdateTask); - sequence.Add(NResourceBroker::TEvResourceBroker::EvResourceAllocated); - } - if (entry.Events.SubmitTask) { - sequence.Add(NResourceBroker::TEvResourceBroker::EvSubmitTask, entry.Events.SubmitTask); - sequence.Add(NResourceBroker::TEvResourceBroker::EvResourceAllocated); - } - for (ui32 i = 0; i < entry.Events.FinishTasks; ++i) { - sequence.Add(NResourceBroker::TEvResourceBroker::EvFinishTask); - } - } + + TTaskSequence sequence; + + for (auto &entry : list) { + event->Requests.push_back({entry.Keys, entry.NewSize, entry.Static, entry.OutOfMemory, + entry.Hold, entry.Use, entry.HoldSize, entry.Finish}); + if (entry.Events.MergeTask) { + sequence.Add(NResourceBroker::TEvResourceBroker::EvUpdateTask, entry.Events.MergeTask); + sequence.Add(NResourceBroker::TEvResourceBroker::EvFinishTask); + } + if (entry.Events.UpdateTask) { + sequence.Add(NResourceBroker::TEvResourceBroker::EvUpdateTask, entry.Events.UpdateTask); + sequence.Add(NResourceBroker::TEvResourceBroker::EvResourceAllocated); + } + if (entry.Events.SubmitTask) { + sequence.Add(NResourceBroker::TEvResourceBroker::EvSubmitTask, entry.Events.SubmitTask); + sequence.Add(NResourceBroker::TEvResourceBroker::EvResourceAllocated); + } + for (ui32 i = 0; i < entry.Events.FinishTasks; ++i) { + sequence.Add(NResourceBroker::TEvResourceBroker::EvFinishTask); + } + } if (follower) { SendFollowerAsync(new NFake::TEvExecute{ event.Release() }); @@ -1373,52 +1373,52 @@ Y_UNIT_TEST_SUITE(TFlatTableExecutorResourceProfile) { SendAsync(new NFake::TEvExecute{ event.Release() }); } - if (!sequence.Events.empty()) { - TDispatchOptions options; - options.FinalEvents.emplace_back(sequence); - Env.DispatchEvents(options); - } - - WaitForWakeUp(); - } + if (!sequence.Events.empty()) { + TDispatchOptions options; + options.FinalEvents.emplace_back(sequence); + Env.DispatchEvents(options); + } + WaitForWakeUp(); + } + void CheckMemoryRequestFollower(std::initializer_list<TMemoryCheckEntry> list, TTxRequestMemory::TCfg cfg = { }) { return CheckMemoryRequest(list, std::move(cfg), /* follower */ true); } - TResourceProfiles::TPtr Profile; - TRowsModel Rows; - }; - - + TResourceProfiles::TPtr Profile; + TRowsModel Rows; + }; + + Y_UNIT_TEST(TestExecutorSetResourceProfile) { - TMyEnvProfiles env; - - env.SendSync(new NFake::TEvExecute{ new TTxCheckResourceProfile("profile1") }); - env.SendSync(new TEvents::TEvPoison(), false, true); - env.FireDummyTablet(); - env.SendSync(new NFake::TEvExecute{ new TTxCheckResourceProfile("profile1") }, true); + TMyEnvProfiles env; + + env.SendSync(new NFake::TEvExecute{ new TTxCheckResourceProfile("profile1") }); + env.SendSync(new TEvents::TEvPoison(), false, true); + env.FireDummyTablet(); + env.SendSync(new NFake::TEvExecute{ new TTxCheckResourceProfile("profile1") }, true); } Y_UNIT_TEST(TestExecutorRequestTxData) { - TMyEnvProfiles env; + TMyEnvProfiles env; // Request static memory. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{10 << 10, {}, true}}); // Request dynamic memory (small task). - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{20 << 10, {"small_transaction"}}}); // Request dynamic memory (medium task). - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{50 << 10, {"medium_transaction"}}}); // Request dynamic memory (large task). - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{110 << 10, {"large_transaction"}}}); // Request static memory, into small task, into medium task, into large task. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{10 << 10, {}, true}, {20 << 10, {"small_transaction"}}, {50 << 10, {"", "medium_transaction"}}, @@ -1426,63 +1426,63 @@ Y_UNIT_TEST_SUITE(TFlatTableExecutorResourceProfile) { } Y_UNIT_TEST(TestExecutorStaticMemoryLimits) { - TMyEnvProfiles env; + TMyEnvProfiles env; - const ui64 limit = env.Profile->GetStaticTabletTxMemoryLimit(); + const ui64 limit = env.Profile->GetStaticTabletTxMemoryLimit(); // Check static tablet limit has priority over tx limits. - env.Profile->SetStaticTxMemoryLimit(limit * 2); - env.CheckMemoryRequest({{limit + 1, {"large_transaction"}}}); - + env.Profile->SetStaticTxMemoryLimit(limit * 2); + env.CheckMemoryRequest({{limit + 1, {"large_transaction"}}}); + // Check unlimited tablet memory. - env.Profile->SetStaticTabletTxMemoryLimit(0); - env.CheckMemoryRequest({{limit + 1, {}, true}}); - env.CheckMemoryRequest({{limit * 2 + 1, {"large_transaction"}}}); - + env.Profile->SetStaticTabletTxMemoryLimit(0); + env.CheckMemoryRequest({{limit + 1, {}, true}}); + env.CheckMemoryRequest({{limit * 2 + 1, {"large_transaction"}}}); + // Check unlimited tx memory. - env.Profile->SetStaticTxMemoryLimit(0); - env.CheckMemoryRequest({{limit * 2 + 1, {}, true}}); + env.Profile->SetStaticTxMemoryLimit(0); + env.CheckMemoryRequest({{limit * 2 + 1, {}, true}}); } Y_UNIT_TEST(TestExecutorReuseStaticMemory) { - TMyEnvProfiles env; + TMyEnvProfiles env; - env.Profile->SetStaticTxMemoryLimit(100 << 20); + env.Profile->SetStaticTxMemoryLimit(100 << 20); // Check static tablet memory is freed and reused by transactions. for (int i = 0; i < 100; ++i) { if (i % 2) { - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{50 << 20, {}, true}, {150 << 20, {"large_transaction"}}}); } else { - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{50 << 20, {}, true}}); } } } Y_UNIT_TEST(TestExecutorTxDataLimitExceeded) { - TMyEnvProfiles().CheckMemoryRequest({{500 << 20, {}, false, true}}); + TMyEnvProfiles().CheckMemoryRequest({{500 << 20, {}, false, true}}); } Y_UNIT_TEST(TestExecutorRequestPages) { - TMyEnvProfiles env; + TMyEnvProfiles env; - env.SendSync(env.Rows.MakeRows(100, 2 << 10)); + env.SendSync(env.Rows.MakeRows(100, 2 << 10)); // Static memory for pages. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{{1}, 0, {}, true}}); // Dynamic memory for pages. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 0, {"small_transaction"}}}); // Dynamic memory for pages. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30}, 0, {"medium_transaction"}}}); // Dynamic memory for pages. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, @@ -1496,32 +1496,32 @@ Y_UNIT_TEST_SUITE(TFlatTableExecutorResourceProfile) { } Y_UNIT_TEST(TestExecutorPageLimitExceeded) { - TMyEnvProfiles env; + TMyEnvProfiles env; - env.Profile->SetTxMemoryLimit(50 << 10); - env.SendSync(env.Rows.MakeRows(20, 10 << 10)); + env.Profile->SetTxMemoryLimit(50 << 10); + env.SendSync(env.Rows.MakeRows(20, 10 << 10)); // Pages are out of tx limit. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 0, {}, false, true}}); } Y_UNIT_TEST(TestExecutorRequestMemory) { - TMyEnvProfiles env; + TMyEnvProfiles env; - env.SendSync(env.Rows.MakeRows(100, 2 << 10)); + env.SendSync(env.Rows.MakeRows(100, 2 << 10)); // Static memory. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{{1}, 4 << 10, {}, true}}); // Dynamic memory. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{{1, 2, 3, 4, 5}, 14 << 10, {"small_transaction"}}}); // Dynamic memory. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 35 << 10, {"medium_transaction"}}}); // Dynamic memory. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 95 << 10, {"large_transaction"}}}); } @@ -1547,88 +1547,88 @@ Y_UNIT_TEST_SUITE(TFlatTableExecutorResourceProfile) { } Y_UNIT_TEST(TestExecutorMemoryLimitExceeded) { - TMyEnvProfiles env; + TMyEnvProfiles env; - env.Profile->SetTxMemoryLimit(50 << 10); - env.SendSync(env.Rows.MakeRows(20, 2 << 10)); + env.Profile->SetTxMemoryLimit(50 << 10); + env.SendSync(env.Rows.MakeRows(20, 2 << 10)); // Memory is out of tx limit. - env.CheckMemoryRequest({{{1, 2, 3, 4, 5}, 45 << 10, {}, false, true}}); + env.CheckMemoryRequest({{{1, 2, 3, 4, 5}, 45 << 10, {}, false, true}}); } Y_UNIT_TEST(TestExecutorPreserveTxData) { - TMyEnvProfiles env; + TMyEnvProfiles env; // Preserved static replaces static. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{10 << 10, {}, true}, {true, 0, {}, true}, {12 << 10, {}, true}, {false, true, 0, {}, true}}); // Preserved static replaces dynamic. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{10 << 10, {}, true}, {true, 0, {}, true}, {20 << 10, {"small_transaction"}}, {false, true, 0, {}}}); // Preserved dynamic replaces static. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{20 << 10, {"small_transaction"}}, {true, 0, {}}, {10 << 10, {}, true}, {false, true, 0, {}}}); // Preserved dynamic replaces dynamic. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{20 << 10, {"small_transaction"}}, {true, 0, {}}, {20 << 10, {"small_transaction"}}, {false, true, 0, {}}}); // Preserved static replaces static. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{10 << 10, {}, true}, {true, 0, {}, true}, {12 << 10, {}, true}, {false, true, 11 << 10, {}, true}}); // Preserved static replaces dynamic. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{10 << 10, {}, true}, {true, 0, {}, true}, {20 << 10, {"small_transaction"}}, {false, true, 30 << 10, {}}}); // Preserved dynamic replaces static. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{20 << 10, {"small_transaction"}}, {true, 0, {}}, {10 << 10, {}, true}, {false, true, 50 << 10, {"", "medium_transaction"}}}); // Preserved dynamic replaces dynamic. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{20 << 10, {"small_transaction"}}, {true, 0, {}, true}, {20 << 10, {"small_transaction"}}, {false, true, 50 << 10, {"", "medium_transaction", "small_transaction"}}}); // Preserved static replaces static. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{10 << 10, {}, true}, {true, 0, {}, true}, {12 << 10, {}, true}, {false, true, 500 << 20, {}, true, true}}); // Preserved static replaces dynamic. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{10 << 10, {}, true}, {true, 0, {}, true}, {20 << 10, {"small_transaction"}}, {false, true, 500 << 20, {}, false, true}}); // Preserved dynamic replaces static. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{20 << 10, {"small_transaction"}}, {true, 0, {}}, {10 << 10, {}, true}, {false, true, 500 << 20, {}, false, true}}); // Preserved dynamic replaces dynamic. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{20 << 10, {"small_transaction"}}, {true, 0, {}, true}, {20 << 10, {"small_transaction"}}, @@ -1636,39 +1636,39 @@ Y_UNIT_TEST_SUITE(TFlatTableExecutorResourceProfile) { } Y_UNIT_TEST(TestExecutorTxDataGC) { - TMyEnvProfiles env; + TMyEnvProfiles env; // Preserve dynamic and drop it. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{50 << 20, {"large_transaction"}}, {true, 0, {}}}); } Y_UNIT_TEST(TestExecutorTxPartialDataHold) { - TMyEnvProfiles env; + TMyEnvProfiles env; // Hold part of static data. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{10 << 10, {}, true}, {(ui64)(5 << 10), 0, {}, true}, {false, true, 0, {}, true}}); // Hold part of dynamic data. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{20 << 10, {"small_transaction"}}, {(ui64)(10 << 10), 0, {}}, {false, true, 0, {}}}); } Y_UNIT_TEST(TestExecutorTxHoldAndUse) { - TMyEnvProfiles env; + TMyEnvProfiles env; // Hold part of static data. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{10 << 10, {}, true}, {(ui64)(5 << 10), 0, {}, true}, {true, true, 0, {}, true}}); // Hold part of dynamic data. Merge two small tasks into one medium. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{20 << 10, {"small_transaction"}}, {(ui64)(15 << 10), 0, {}}, {30 << 10, {"small_transaction"}}, @@ -1678,68 +1678,68 @@ Y_UNIT_TEST_SUITE(TFlatTableExecutorResourceProfile) { } Y_UNIT_TEST(TestExecutorTxHoldOnRelease) { - TMyEnvProfiles env; + TMyEnvProfiles env; // Hold dynamic data on task extend. Merge two small tasks into one medium. - env.CheckMemoryRequest( + env.CheckMemoryRequest( {{20 << 10, {"small_transaction"}}, // 20KB is captured on ReleaseTxData -> small task is requested. {30 << 10, {"small_transaction"}}, - {false, true, 0, {"", "", "medium_transaction", 1}}}, - { false /* static */, true /* dynamic */ }); + {false, true, 0, {"", "", "medium_transaction", 1}}}, + { false /* static */, true /* dynamic */ }); } Y_UNIT_TEST(TestUpdateConfig) { - TMyEnvProfiles env; + TMyEnvProfiles env; // Request dynamic memory (large task). - env.CheckMemoryRequest({{110 << 10, {"large_transaction"}}}); + env.CheckMemoryRequest({{110 << 10, {"large_transaction"}}}); // Gen new profile with no required profile. EvUpdateConfig should cause // default profile to be chosen then. - env.SetupProfile("profile2"); - env.SendAsync(new TEvTablet::TEvUpdateConfig(env->GetAppData().ResourceProfiles)); + env.SetupProfile("profile2"); + env.SendAsync(new TEvTablet::TEvUpdateConfig(env->GetAppData().ResourceProfiles)); // Profile name in schema is unmodified. - env.SendSync(new NFake::TEvExecute{ new TTxCheckResourceProfile("profile1") }); + env.SendSync(new NFake::TEvExecute{ new TTxCheckResourceProfile("profile1") }); // But default profile is actually used now. - env.CheckMemoryRequest({{200 << 20, {}, true}}); + env.CheckMemoryRequest({{200 << 20, {}, true}}); } } Y_UNIT_TEST_SUITE(TFlatTableExecutorSliceOverlapScan) { - Y_UNIT_TEST(TestSliceOverlapScan) { - TMyEnvBase env; - TRowsModel rows; + Y_UNIT_TEST(TestSliceOverlapScan) { + TMyEnvBase env; + TRowsModel rows; - env.FireDummyTablet(ui32(NFake::TDummy::EFlg::Comp)); + env.FireDummyTablet(ui32(NFake::TDummy::EFlg::Comp)); TIntrusivePtr<TCompactionPolicy> policy = new TCompactionPolicy; - policy->InMemForceSizeToSnapshot = 4 * 1024 * 1024; - policy->Generations.push_back({0, 2, 2, ui64(-1), - NLocalDb::LegacyQueueIdToTaskName(1), false}); - { - // Don't allow any extras during compaction - auto &gen = policy->Generations.back(); - gen.ExtraCompactionMinSize = 0; - gen.ExtraCompactionPercent = 0; - gen.ExtraCompactionExpPercent = 0; - gen.ExtraCompactionExpMaxSize = 0; - } - - env.SendSync(rows.MakeScheme(std::move(policy))); - // Insert ~32MB of data, this will generate ~4x8MB slices - env.SendSync(rows.RowTo(1000000).MakeRows(32768, 1024, 32768)); - env.WaitFor<NFake::TEvCompacted>(); - // Insert 32MB more data, ~4x8MB slices will half-overlap - env.SendSync(rows.RowTo(1000000 - 16384).MakeRows(32768, 1024, 32768)); - // Don't do anything, this new part will trigger final compaction - env.WaitFor<NFake::TEvCompacted>(); - // If we didn't crash, then traced scan worked correctly - env.WaitFor<NFake::TEvCompacted>(); - env.SendSync(new TEvents::TEvPoison, false, true); + policy->InMemForceSizeToSnapshot = 4 * 1024 * 1024; + policy->Generations.push_back({0, 2, 2, ui64(-1), + NLocalDb::LegacyQueueIdToTaskName(1), false}); + { + // Don't allow any extras during compaction + auto &gen = policy->Generations.back(); + gen.ExtraCompactionMinSize = 0; + gen.ExtraCompactionPercent = 0; + gen.ExtraCompactionExpPercent = 0; + gen.ExtraCompactionExpMaxSize = 0; + } + + env.SendSync(rows.MakeScheme(std::move(policy))); + // Insert ~32MB of data, this will generate ~4x8MB slices + env.SendSync(rows.RowTo(1000000).MakeRows(32768, 1024, 32768)); + env.WaitFor<NFake::TEvCompacted>(); + // Insert 32MB more data, ~4x8MB slices will half-overlap + env.SendSync(rows.RowTo(1000000 - 16384).MakeRows(32768, 1024, 32768)); + // Don't do anything, this new part will trigger final compaction + env.WaitFor<NFake::TEvCompacted>(); + // If we didn't crash, then traced scan worked correctly + env.WaitFor<NFake::TEvCompacted>(); + env.SendSync(new TEvents::TEvPoison, false, true); } } diff --git a/ydb/core/tablet_flat/flat_fwd_blobs.h b/ydb/core/tablet_flat/flat_fwd_blobs.h index 583ba48ee8..8a9accaf89 100644 --- a/ydb/core/tablet_flat/flat_fwd_blobs.h +++ b/ydb/core/tablet_flat/flat_fwd_blobs.h @@ -1,86 +1,86 @@ -#pragma once - -#include "flat_fwd_iface.h" -#include "flat_fwd_page.h" -#include "flat_fwd_misc.h" -#include "flat_page_blobs.h" -#include "flat_part_screen.h" +#pragma once + +#include "flat_fwd_iface.h" +#include "flat_fwd_page.h" +#include "flat_fwd_misc.h" +#include "flat_page_blobs.h" +#include "flat_part_screen.h" #include "flat_part_slice.h" - -namespace NKikimr { -namespace NTable { -namespace NFwd { - + +namespace NKikimr { +namespace NTable { +namespace NFwd { + class TBlobs : public IPageLoadingLogic { - using THoles = TScreen::TCook; - - public: - using TEdges = TVector<ui32>; - + using THoles = TScreen::TCook; + + public: + using TEdges = TVector<ui32>; + TBlobs(TIntrusiveConstPtr<NPage::TFrames> frames, TIntrusiveConstPtr<TSlices> slices, TEdges edge, bool trace) - : Edge(std::move(edge)) - , Frames(std::move(frames)) + : Edge(std::move(edge)) + , Frames(std::move(frames)) , Filter(std::move(slices)) - , Trace(trace ? new THoles{ } : nullptr) - { - Tags.resize(Frames->Stats().Tags.size(), 0); - - Y_VERIFY(Edge.size() == Tags.size(), "Invalid edges vector"); - } - - ~TBlobs() - { - for (auto &it: Pages) it.Release(); - } - + , Trace(trace ? new THoles{ } : nullptr) + { + Tags.resize(Frames->Stats().Tags.size(), 0); + + Y_VERIFY(Edge.size() == Tags.size(), "Invalid edges vector"); + } + + ~TBlobs() + { + for (auto &it: Pages) it.Release(); + } + TResult Handle(IPageLoadingQueue *head, ui32 ref, ui64 lower) noexcept override - { - Y_VERIFY(ref >= Lower, "Cannot handle backward blob reads"); - - auto again = (std::exchange(Tags.at(FrameTo(ref)), 1) == 0); - - Grow = again ? Lower : Max(Lower, Grow); - - Rewind(Lower).Shrink(false); /* points Offset to current frame */ - - bool more = Grow < Max<TPageId>() && (OnHold + OnFetch < lower); - - auto &page = Preload(head, 0).Lookup(ref); - - return { page.Touch(ref, Stat), more, page.Size < Edge[page.Tag] }; - } - + { + Y_VERIFY(ref >= Lower, "Cannot handle backward blob reads"); + + auto again = (std::exchange(Tags.at(FrameTo(ref)), 1) == 0); + + Grow = again ? Lower : Max(Lower, Grow); + + Rewind(Lower).Shrink(false); /* points Offset to current frame */ + + bool more = Grow < Max<TPageId>() && (OnHold + OnFetch < lower); + + auto &page = Preload(head, 0).Lookup(ref); + + return { page.Touch(ref, Stat), more, page.Size < Edge[page.Tag] }; + } + void Forward(IPageLoadingQueue *head, ui64 upper) noexcept override - { - Preload(head, upper); - } - + { + Preload(head, upper); + } + void Apply(TArrayRef<NPageCollection::TLoadedPage> loaded) noexcept override - { - for (auto &one: loaded) { - if (!Pages || one.PageId < Pages.front().PageId) { - Y_FAIL("Blobs fwd cache got page below queue"); - } else if (one.PageId > Pages.back().PageId) { - Y_FAIL("Blobs fwd cache got page above queue"); - } else if (one.Data.size() > OnFetch) { - Y_FAIL("Blobs fwd cache ahead counters is out of sync"); - } - - Stat.Saved += one.Data.size(); - OnFetch -= one.Data.size(); - OnHold += Lookup(one.PageId).Settle(one); - } - - Shrink(false /* do not drop loading pages */); - } - - TDeque<TScreen::THole> Traced() noexcept - { - Rewind(Max<TPageId>()).Shrink(true /* complete trace */); - - return Trace ? Trace->Unwrap() : TDeque<TScreen::THole>{ }; - } - + { + for (auto &one: loaded) { + if (!Pages || one.PageId < Pages.front().PageId) { + Y_FAIL("Blobs fwd cache got page below queue"); + } else if (one.PageId > Pages.back().PageId) { + Y_FAIL("Blobs fwd cache got page above queue"); + } else if (one.Data.size() > OnFetch) { + Y_FAIL("Blobs fwd cache ahead counters is out of sync"); + } + + Stat.Saved += one.Data.size(); + OnFetch -= one.Data.size(); + OnHold += Lookup(one.PageId).Settle(one); + } + + Shrink(false /* do not drop loading pages */); + } + + TDeque<TScreen::THole> Traced() noexcept + { + Rewind(Max<TPageId>()).Shrink(true /* complete trace */); + + return Trace ? Trace->Unwrap() : TDeque<TScreen::THole>{ }; + } + TIntrusiveConstPtr<NPage::TFrames> GetFrames() const noexcept { return Frames; @@ -91,159 +91,159 @@ namespace NFwd { return Filter.GetSlices(); } - private: - TPage& Lookup(ui32 ref) noexcept - { - const auto end = Pages.begin() + Offset; - - if (ref >= end->PageId) { - return Pages.at(Offset + (ref - end->PageId)); - } else { - auto it = std::lower_bound(Pages.begin(), end, ref); - - Y_VERIFY(it != end && it->PageId == ref); - - return *it; - } - } - - ui32 FrameTo(TPageId ref) noexcept - { - if (ref >= Lower && ref < Upper) { - return Lookup(ref).Tag; - } else if (!Pages || Pages.back().PageId < ref) { - return FrameTo(ref, Frames->Relation(ref)); - } else { - const auto &page = Lookup(ref); + private: + TPage& Lookup(ui32 ref) noexcept + { + const auto end = Pages.begin() + Offset; + + if (ref >= end->PageId) { + return Pages.at(Offset + (ref - end->PageId)); + } else { + auto it = std::lower_bound(Pages.begin(), end, ref); + + Y_VERIFY(it != end && it->PageId == ref); + + return *it; + } + } + + ui32 FrameTo(TPageId ref) noexcept + { + if (ref >= Lower && ref < Upper) { + return Lookup(ref).Tag; + } else if (!Pages || Pages.back().PageId < ref) { + return FrameTo(ref, Frames->Relation(ref)); + } else { + const auto &page = Lookup(ref); Y_VERIFY(page.Size < Max<ui32>(), "Unexpected huge page"); - - i16 refer = ref - page.Refer; /* back to relative refer */ - + + i16 refer = ref - page.Refer; /* back to relative refer */ + return FrameTo(ref, { 0, page.Tag, refer, static_cast<ui32>(page.Size) }); - } - } - - ui32 FrameTo(TPageId ref, NPage::TFrames::TEntry rel) noexcept - { - Lower = Min(ref, rel.AbsRef(ref)); - Upper = ref + 1; /* will be extended eventually */ - - return rel.Tag; - } - + } + } + + ui32 FrameTo(TPageId ref, NPage::TFrames::TEntry rel) noexcept + { + Lower = Min(ref, rel.AbsRef(ref)); + Upper = ref + 1; /* will be extended eventually */ + + return rel.Tag; + } + TBlobs& Preload(IPageLoadingQueue *head, ui64 upper) noexcept - { - auto until = [this, upper]() { return OnHold + OnFetch < upper; }; - - while (Grow != Max<TPageId>() && (Grow < Upper || until())) { - const auto next = Propagate(Grow); - - Y_VERIFY(Grow < next, "Unexpected frame upper boundary"); - - Grow = (next < Max<TPageId>() ? Grow : next); - - for ( ; Grow < next; Grow++) { - auto &page = Lookup(Grow); + { + auto until = [this, upper]() { return OnHold + OnFetch < upper; }; + + while (Grow != Max<TPageId>() && (Grow < Upper || until())) { + const auto next = Propagate(Grow); + + Y_VERIFY(Grow < next, "Unexpected frame upper boundary"); + + Grow = (next < Max<TPageId>() ? Grow : next); + + for ( ; Grow < next; Grow++) { + auto &page = Lookup(Grow); const auto rel = Frames->Relation(Grow); - + if (!Tags.at(page.Tag) || page.Size >= Edge.at(page.Tag) || !Filter.Has(rel.Row)) { - /* Page doesn't fits to load criteria */ - } else if (page.Fetch == EFetch::None) { + /* Page doesn't fits to load criteria */ + } else if (page.Fetch == EFetch::None) { auto size = head->AddToQueue(Grow, ui16(EPage::Opaque)); - - Y_VERIFY(size == page.Size, "Inconsistent page sizez"); - - page.Fetch = EFetch::Wait; - Stat.Fetch += page.Size; - OnFetch += page.Size; - } - } - } - - return *this; - } - - TPageId Propagate(const TPageId base) noexcept - { - if (Pages && base <= Pages.back().PageId) { - return Lookup(base).Refer; - } else if (Pages && base != Lower && base - Pages.back().PageId != 1) { - Y_FAIL("Cannot do so long jumps around of frames"); - } else { - const auto end = Frames->Relation(base).AbsRef(base); - - Upper = (base == Lower ? end : Lower); - - for (auto page = base; page < end; page++) { - const auto rel = Frames->Relation(page); - const auto ref = rel.AbsRef(page); - - Pages.emplace_back(page, rel.Size, rel.Tag, ref); - } - - return end == base ? Max<TPageId>() : end; - } - } - - TBlobs& Rewind(TPageId until) noexcept - { - for (; Offset < Pages.size(); Offset++) { - auto &page = Pages.at(Offset); - - if (page.PageId >= until) { - break; - } else if (page.Size == 0) { - Y_FAIL("Dropping page that hasn't been propagated"); - } else if (auto size = page.Release().size()) { - OnHold -= size; - - if (page.Usage == EUsage::None) - *(page.Ready() ? &Stat.After : &Stat.Before) += size; - } - } - - return *this; - } - - TBlobs& Shrink(bool force = false) noexcept - { - for (; Offset && (Pages[0].Ready() || force); Offset--) { - - if (Trace && Pages.front().Usage == EUsage::Seen) { - /* Trace mode is used to track entities that was used by - reference and, thus, has not been materialized into - another storage unit. Later this set may be used for - resource lifetime prolongation. - */ - - Trace->Pass(Pages.front().PageId); - } - - Pages.pop_front(); - } - - return *this; - } - - private: - const TVector<ui32> Edge; /* Desired bytes limit of blobs */ + + Y_VERIFY(size == page.Size, "Inconsistent page sizez"); + + page.Fetch = EFetch::Wait; + Stat.Fetch += page.Size; + OnFetch += page.Size; + } + } + } + + return *this; + } + + TPageId Propagate(const TPageId base) noexcept + { + if (Pages && base <= Pages.back().PageId) { + return Lookup(base).Refer; + } else if (Pages && base != Lower && base - Pages.back().PageId != 1) { + Y_FAIL("Cannot do so long jumps around of frames"); + } else { + const auto end = Frames->Relation(base).AbsRef(base); + + Upper = (base == Lower ? end : Lower); + + for (auto page = base; page < end; page++) { + const auto rel = Frames->Relation(page); + const auto ref = rel.AbsRef(page); + + Pages.emplace_back(page, rel.Size, rel.Tag, ref); + } + + return end == base ? Max<TPageId>() : end; + } + } + + TBlobs& Rewind(TPageId until) noexcept + { + for (; Offset < Pages.size(); Offset++) { + auto &page = Pages.at(Offset); + + if (page.PageId >= until) { + break; + } else if (page.Size == 0) { + Y_FAIL("Dropping page that hasn't been propagated"); + } else if (auto size = page.Release().size()) { + OnHold -= size; + + if (page.Usage == EUsage::None) + *(page.Ready() ? &Stat.After : &Stat.Before) += size; + } + } + + return *this; + } + + TBlobs& Shrink(bool force = false) noexcept + { + for (; Offset && (Pages[0].Ready() || force); Offset--) { + + if (Trace && Pages.front().Usage == EUsage::Seen) { + /* Trace mode is used to track entities that was used by + reference and, thus, has not been materialized into + another storage unit. Later this set may be used for + resource lifetime prolongation. + */ + + Trace->Pass(Pages.front().PageId); + } + + Pages.pop_front(); + } + + return *this; + } + + private: + const TVector<ui32> Edge; /* Desired bytes limit of blobs */ const TIntrusiveConstPtr<NPage::TFrames> Frames; const TSlicesRowFilter Filter; - TVector<ui8> Tags; /* Ever used col tags on env */ - TPageId Lower = 0; /* Pinned frame lower bound ref */ - TPageId Upper = 0; /* Pinned frame upper bound ref */ - TPageId Grow = Max<TPageId>(); /* Edge page of loading process */ - + TVector<ui8> Tags; /* Ever used col tags on env */ + TPageId Lower = 0; /* Pinned frame lower bound ref */ + TPageId Upper = 0; /* Pinned frame upper bound ref */ + TPageId Grow = Max<TPageId>(); /* Edge page of loading process */ + TAutoPtr<THoles> Trace; - - /*_ Forward cache line state */ - - ui64 OnHold = 0; - ui64 OnFetch = 0; - ui32 Offset = 0; - TDeque<TPage> Pages; - }; - -} -} -} + + /*_ Forward cache line state */ + + ui64 OnHold = 0; + ui64 OnFetch = 0; + ui32 Offset = 0; + TDeque<TPage> Pages; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_fwd_cache.h b/ydb/core/tablet_flat/flat_fwd_cache.h index f5ff3f5033..bee382c1e7 100644 --- a/ydb/core/tablet_flat/flat_fwd_cache.h +++ b/ydb/core/tablet_flat/flat_fwd_cache.h @@ -1,182 +1,182 @@ -#pragma once - -#include "flat_part_iface.h" -#include "flat_part_forward.h" -#include "flat_fwd_iface.h" -#include "flat_fwd_misc.h" -#include "flat_fwd_page.h" - -namespace NKikimr { -namespace NTable { -namespace NFwd { - +#pragma once + +#include "flat_part_iface.h" +#include "flat_part_forward.h" +#include "flat_fwd_iface.h" +#include "flat_fwd_misc.h" +#include "flat_fwd_page.h" + +namespace NKikimr { +namespace NTable { +namespace NFwd { + class TCache : public IPageLoadingLogic { - - template<size_t Items> - struct TRound { + + template<size_t Items> + struct TRound { const TSharedData* Get(TPageId pageId) const - { - if (pageId < Edge) { + { + if (pageId < Edge) { const auto pred = [pageId](const NPageCollection::TLoadedPage &page) { - return page.PageId == pageId; - }; - - auto it = std::find_if(Pages.begin(), Pages.end(), pred); - - if (it == Pages.end()) { - Y_FAIL("Failed to locate page within forward trace"); - } - - return &it->Data; - } - - return nullptr; - } - - ui32 Emplace(TPage &page) - { - Y_VERIFY(page, "Cannot push invalid page to trace cache"); - - Offset = (Pages.size() + Offset - 1) % Pages.size(); - - const ui32 was = Pages[Offset].Data.size(); - - Pages[Offset].Data = page.Release(); - Pages[Offset].PageId = page.PageId; - Edge = Max(Edge, page.PageId + 1); - - return was; - } - - private: + return page.PageId == pageId; + }; + + auto it = std::find_if(Pages.begin(), Pages.end(), pred); + + if (it == Pages.end()) { + Y_FAIL("Failed to locate page within forward trace"); + } + + return &it->Data; + } + + return nullptr; + } + + ui32 Emplace(TPage &page) + { + Y_VERIFY(page, "Cannot push invalid page to trace cache"); + + Offset = (Pages.size() + Offset - 1) % Pages.size(); + + const ui32 was = Pages[Offset].Data.size(); + + Pages[Offset].Data = page.Release(); + Pages[Offset].PageId = page.PageId; + Edge = Max(Edge, page.PageId + 1); + + return was; + } + + private: std::array<NPageCollection::TLoadedPage, Items> Pages; - TPageId Edge = 0; - ui32 Offset = 0; - }; - - public: - TCache() = delete; - + TPageId Edge = 0; + ui32 Offset = 0; + }; + + public: + TCache() = delete; + TCache(const NPage::TIndex& index, const TIntrusiveConstPtr<TSlices>& bounds = nullptr) : Index(index, 1, bounds) { } - - ~TCache() - { - for (auto &it: Pages) it.Release(); - } - + + ~TCache() + { + for (auto &it: Pages) it.Release(); + } + TResult Handle(IPageLoadingQueue *head, TPageId pageId, ui64 lower) noexcept override - { - Y_VERIFY(pageId != Max<TPageId>(), "Invalid requested pageId"); - - if (auto *page = Trace.Get(pageId)) - return { page, false, true }; - - Rewind(pageId).Shrink(); /* points Offset to pageId */ - - bool more = Grow && (OnHold + OnFetch <= lower); - - return { Preload(head, 0).Touch(pageId, Stat), more, true }; - } - + { + Y_VERIFY(pageId != Max<TPageId>(), "Invalid requested pageId"); + + if (auto *page = Trace.Get(pageId)) + return { page, false, true }; + + Rewind(pageId).Shrink(); /* points Offset to pageId */ + + bool more = Grow && (OnHold + OnFetch <= lower); + + return { Preload(head, 0).Touch(pageId, Stat), more, true }; + } + void Forward(IPageLoadingQueue *head, ui64 upper) noexcept override - { - Preload(head, upper); - } - + { + Preload(head, upper); + } + void Apply(TArrayRef<NPageCollection::TLoadedPage> loaded) noexcept override - { - auto it = Pages.begin(); - - for (auto &one: loaded) { - if (it == Pages.end() || it->PageId > one.PageId) { - it = std::lower_bound(Pages.begin(), it, one.PageId); - } else if (it->PageId < one.PageId) { - it = std::lower_bound(++it, Pages.end(), one.PageId); - } - - if (it == Pages.end() || it->PageId != one.PageId) { - Y_FAIL("Got page that hasn't been requested for load"); - } if (one.Data.size() > OnFetch) { - Y_FAIL("Forward cache ahead counters is out of sync"); - } - - Stat.Saved += one.Data.size(); - OnFetch -= one.Data.size(); - OnHold += it->Settle(one); - - ++it; - } - - Shrink(); - } - - private: + { + auto it = Pages.begin(); + + for (auto &one: loaded) { + if (it == Pages.end() || it->PageId > one.PageId) { + it = std::lower_bound(Pages.begin(), it, one.PageId); + } else if (it->PageId < one.PageId) { + it = std::lower_bound(++it, Pages.end(), one.PageId); + } + + if (it == Pages.end() || it->PageId != one.PageId) { + Y_FAIL("Got page that hasn't been requested for load"); + } if (one.Data.size() > OnFetch) { + Y_FAIL("Forward cache ahead counters is out of sync"); + } + + Stat.Saved += one.Data.size(); + OnFetch -= one.Data.size(); + OnHold += it->Settle(one); + + ++it; + } + + Shrink(); + } + + private: TPage& Preload(IPageLoadingQueue *head, ui64 upper) noexcept - { - auto until = [this, upper]() { - return OnHold + OnFetch < upper ? Max<TPageId>() : 0; - }; - - while (auto more = Index.More(until())) { + { + auto until = [this, upper]() { + return OnHold + OnFetch < upper ? Max<TPageId>() : 0; + }; + + while (auto more = Index.More(until())) { auto size = head->AddToQueue(more, ui16(EPage::DataPage)); - - Stat.Fetch += size; - OnFetch += size; - - Pages.emplace_back(more, size, 0, Max<TPageId>()); - Pages.back().Fetch = EFetch::Wait; - } - - Grow = Grow && Index.On(true) < Max<TPageId>(); - - return Pages.at(Offset); - } - - TCache& Rewind(TPageId pageId) noexcept - { - while (auto drop = Index.Clean(pageId)) { - auto &page = Pages.at(Offset); - - if (!Pages || page.PageId != drop.PageId) { - Y_FAIL("Dropping page that is not exist in cache"); - } else if (page.Size == 0) { - Y_FAIL("Dropping page that has not been touched"); - } else if (page.Usage == EUsage::Keep) { - OnHold -= Trace.Emplace(page); - } else if (auto size = page.Release().size()) { - OnHold -= size; - - *(page.Ready() ? &Stat.After : &Stat.Before) += size; - } - - Offset++; - } - - return *this; - } - - TCache& Shrink() noexcept - { - for (; Offset && Pages[0].Ready(); Offset--) - Pages.pop_front(); - - return *this; - } - - private: - bool Grow = true; /* Have some pages for Forward(...) */ - TForward Index; - TRound<TPart::Trace> Trace; - - /*_ Forward cache line state */ - - ui64 OnHold = 0; - ui64 OnFetch = 0; - ui32 Offset = 0; + + Stat.Fetch += size; + OnFetch += size; + + Pages.emplace_back(more, size, 0, Max<TPageId>()); + Pages.back().Fetch = EFetch::Wait; + } + + Grow = Grow && Index.On(true) < Max<TPageId>(); + + return Pages.at(Offset); + } + + TCache& Rewind(TPageId pageId) noexcept + { + while (auto drop = Index.Clean(pageId)) { + auto &page = Pages.at(Offset); + + if (!Pages || page.PageId != drop.PageId) { + Y_FAIL("Dropping page that is not exist in cache"); + } else if (page.Size == 0) { + Y_FAIL("Dropping page that has not been touched"); + } else if (page.Usage == EUsage::Keep) { + OnHold -= Trace.Emplace(page); + } else if (auto size = page.Release().size()) { + OnHold -= size; + + *(page.Ready() ? &Stat.After : &Stat.Before) += size; + } + + Offset++; + } + + return *this; + } + + TCache& Shrink() noexcept + { + for (; Offset && Pages[0].Ready(); Offset--) + Pages.pop_front(); + + return *this; + } + + private: + bool Grow = true; /* Have some pages for Forward(...) */ + TForward Index; + TRound<TPart::Trace> Trace; + + /*_ Forward cache line state */ + + ui64 OnHold = 0; + ui64 OnFetch = 0; + ui32 Offset = 0; TDeque<TPage> Pages; - }; -} -} -} + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_fwd_conf.h b/ydb/core/tablet_flat/flat_fwd_conf.h index 3383865bc8..c731134986 100644 --- a/ydb/core/tablet_flat/flat_fwd_conf.h +++ b/ydb/core/tablet_flat/flat_fwd_conf.h @@ -1,30 +1,30 @@ -#pragma once - -#include <util/system/types.h> -#include <util/generic/array_ref.h> -#include <util/generic/vector.h> - -namespace NKikimr { -namespace NTable { -namespace NFwd { - - struct TConf { - /*_ Cache lines read ahead settings */ - - ui64 AheadHi = 1; - ui64 AheadLo = 8 * 1024 * 1024; - - /*_ Outline blobs materialization conf */ - - ui32 Edge = Max<ui32>(); /* Outlined blob materialization edge */ - ui64 Tablet = 0; /* Use Edge only for this tablet if set */ - TVector<ui32> Keys; /* Always materalize this tag values */ - - /*_ Misc features configuation */ - - bool Trace = false; /* Track seen blobs used by reference */ - }; - -} -} -} +#pragma once + +#include <util/system/types.h> +#include <util/generic/array_ref.h> +#include <util/generic/vector.h> + +namespace NKikimr { +namespace NTable { +namespace NFwd { + + struct TConf { + /*_ Cache lines read ahead settings */ + + ui64 AheadHi = 1; + ui64 AheadLo = 8 * 1024 * 1024; + + /*_ Outline blobs materialization conf */ + + ui32 Edge = Max<ui32>(); /* Outlined blob materialization edge */ + ui64 Tablet = 0; /* Use Edge only for this tablet if set */ + TVector<ui32> Keys; /* Always materalize this tag values */ + + /*_ Misc features configuation */ + + bool Trace = false; /* Track seen blobs used by reference */ + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_fwd_env.h b/ydb/core/tablet_flat/flat_fwd_env.h index 93c17490f6..e6302ffcf9 100644 --- a/ydb/core/tablet_flat/flat_fwd_env.h +++ b/ydb/core/tablet_flat/flat_fwd_env.h @@ -1,98 +1,98 @@ -#pragma once - -#include "flat_fwd_iface.h" -#include "flat_fwd_misc.h" -#include "flat_fwd_cache.h" -#include "flat_fwd_blobs.h" -#include "flat_fwd_conf.h" -#include "flat_fwd_sieve.h" -#include "flat_fwd_warmed.h" -#include "flat_table_subset.h" -#include "flat_part_iface.h" -#include "flat_part_store.h" -#include "flat_sausage_packet.h" -#include "flat_sausage_fetch.h" -#include "util_fmt_abort.h" +#pragma once + +#include "flat_fwd_iface.h" +#include "flat_fwd_misc.h" +#include "flat_fwd_cache.h" +#include "flat_fwd_blobs.h" +#include "flat_fwd_conf.h" +#include "flat_fwd_sieve.h" +#include "flat_fwd_warmed.h" +#include "flat_table_subset.h" +#include "flat_part_iface.h" +#include "flat_part_store.h" +#include "flat_sausage_packet.h" +#include "flat_sausage_fetch.h" +#include "util_fmt_abort.h" #include "util_basics.h" -#include <util/generic/deque.h> -#include <util/random/random.h> -#include <util/generic/intrlist.h> - -namespace NKikimr { -namespace NTable { -namespace NFwd { +#include <util/generic/deque.h> +#include <util/random/random.h> +#include <util/generic/intrlist.h> + +namespace NKikimr { +namespace NTable { +namespace NFwd { using IPageCollection = NPageCollection::IPageCollection; using TFetch = NPageCollection::TFetch; - + class TPageLoadingQueue : public IPageLoadingQueue, public TIntrusiveListItem<TPageLoadingQueue> { - public: + public: TPageLoadingQueue(ui32 slot, ui64 cookie, TIntrusiveConstPtr<IPageCollection> pageCollection, TAutoPtr<IPageLoadingLogic> line) - : Cookie(cookie) + : Cookie(cookie) , PageCollection(std::move(pageCollection)) , PageLoadingLogic(line) - , Slot(slot) - { - - } - + , Slot(slot) + { + + } + IPageLoadingLogic* operator->() const - { + { return PageLoadingLogic.Get(); - } - + } + ui64 AddToQueue(TPageId pageId, ui16 type) noexcept override - { - if (!Fetch) { + { + if (!Fetch) { Fetch.Reset(new TFetch(Cookie, PageCollection, { })); - Fetch->Pages.reserve(16); - } - + Fetch->Pages.reserve(16); + } + const auto meta = PageCollection->Page(pageId); - - if (meta.Type != type || meta.Size == 0) - Y_FAIL("Got a non-data page while part index traverse"); - - Fetch->Pages.emplace_back(pageId); - - return meta.Size; - } - - public: - const ui64 Cookie = Max<ui64>(); + + if (meta.Type != type || meta.Size == 0) + Y_FAIL("Got a non-data page while part index traverse"); + + Fetch->Pages.emplace_back(pageId); + + return meta.Size; + } + + public: + const ui64 Cookie = Max<ui64>(); const TIntrusiveConstPtr<IPageCollection> PageCollection; const TAutoPtr<IPageLoadingLogic> PageLoadingLogic; - const ui32 Slot = Max<ui32>(); - bool Grow = false; /* Should call Forward(...) for preloading */ + const ui32 Slot = Max<ui32>(); + bool Grow = false; /* Should call Forward(...) for preloading */ TAutoPtr<TFetch> Fetch; - }; - - struct TEnv: public IPages { - using TSlot = ui32; + }; + + struct TEnv: public IPages { + using TSlot = ui32; using TSlotVec = TSmallVec<TSlot>; - - struct TEgg { + + struct TEgg { TAutoPtr<IPageLoadingLogic> PageLoadingLogic; TIntrusiveConstPtr<IPageCollection> PageCollection; - }; - - public: + }; + + public: using TData = const TSharedData*; - - TEnv(const TConf &conf, const TSubset &subset) + + TEnv(const TConf &conf, const TSubset &subset) : Salt(RandomNumber<ui32>()) - , Conf(conf) + , Conf(conf) , Subset(subset) , Keys(Subset.Scheme->Tags(true)) , MemTable(new TMemTableHandler(Keys, Conf.Edge, - Conf.Trace ? &subset.Frozen : nullptr)) - { - Y_VERIFY(Conf.AheadHi >= Conf.AheadLo); - Y_VERIFY(std::is_sorted(Keys.begin(), Keys.end())); - + Conf.Trace ? &subset.Frozen : nullptr)) + { + Y_VERIFY(Conf.AheadHi >= Conf.AheadLo); + Y_VERIFY(std::is_sorted(Keys.begin(), Keys.end())); + for (auto &one: Subset.Flatten) AddPartView(one); - } - + } + void AddCold(const TPartView& partView) noexcept { auto r = ColdParts.insert(partView.Part.Get()); @@ -101,40 +101,40 @@ namespace NFwd { AddPartView(partView); } - bool MayProgress() const noexcept - { - return Pending == 0; - } - + bool MayProgress() const noexcept + { + return Pending == 0; + } + TData TryGetPage(const TPart* part, TPageId ref, TGroupId groupId) override - { + { ui16 room = (groupId.Historic ? part->Groups + 2 : 0) + groupId.Index; return Handle(GetQueue(part, room), ref).Page; - } - + } + TResult Locate(const TMemTable *memTable, ui64 ref, ui32 tag) noexcept override - { + { return MemTable->Locate(memTable, ref, tag); - } - + } + TResult Locate(const TPart *part, ui64 ref, ELargeObj lob) noexcept override - { + { if ((lob != ELargeObj::Extern && lob != ELargeObj::Outer) || (ref >> 32)) { Y_Fail("Invalid ref ELargeObj{" << int(lob) << ", " << ref << "}"); - } - + } + ui32 room = part->Groups + (lob == ELargeObj::Extern ? 1 : 0); return Handle(GetQueue(part, room), ref); - } - + } + void DoSave(TIntrusiveConstPtr<IPageCollection> pageCollection, ui64 cookie, TArrayRef<NPageCollection::TLoadedPage> pages) - { + { const ui32 epoch = ui32(cookie) - Salt; if (epoch < Epoch) { return; // ignore pages requested before Reset - } - + } + Y_VERIFY(epoch == Epoch, "Got an invalid part cookie on pages absorption"); @@ -149,71 +149,71 @@ namespace NFwd { Y_VERIFY(pages.size() <= Pending, "Page fwd cache got more pages than was requested"); - Pending -= pages.size(); + Pending -= pages.size(); Queues.at(part)->Apply(pages); - } - - IPages* Reset() noexcept - { - /* Current version of cache works only on forward iterations over - parts and cannot handle backward jumps. This call is temporary - workaround for clients that wants to go back. */ - - Y_VERIFY(!Conf.Trace, "Cannot reset NFwd in blobs tracing state"); - + } + + IPages* Reset() noexcept + { + /* Current version of cache works only on forward iterations over + parts and cannot handle backward jumps. This call is temporary + workaround for clients that wants to go back. */ + + Y_VERIFY(!Conf.Trace, "Cannot reset NFwd in blobs tracing state"); + // Ignore all pages fetched before Reset Pending = 0; ++Epoch; - Total = Stats(); - Parts.clear(); + Total = Stats(); + Parts.clear(); Queues.clear(); ColdParts.clear(); - + for (auto &one : Subset.Flatten) AddPartView(one); - return this; - } - - TStat Stats() const noexcept - { + return this; + } + + TStat Stats() const noexcept + { auto aggr = [](auto &&stat, const TPageLoadingQueue &q) { return stat += q->Stat; - }; - - return + }; + + return std::accumulate(Queues.begin(), Queues.end(), Total, aggr); - } - + } + TAutoPtr<TFetch> GrabFetches() noexcept - { + { while (auto *q = Queue ? Queue.PopFront() : nullptr) { if (std::exchange(q->Grow, false)) (*q)->Forward(q, Max(ui64(1), Conf.AheadHi)); - + if (auto req = std::move(q->Fetch)) { - Y_VERIFY(req->Pages, "Shouldn't sent an empty requests"); - - Pending += req->Pages.size(); - - return req; - } - } - - return nullptr; - } - + Y_VERIFY(req->Pages, "Shouldn't sent an empty requests"); + + Pending += req->Pages.size(); + + return req; + } + } + + return nullptr; + } + TAutoPtr<TSeen> GrabTraces() noexcept - { + { TDeque<TSieve> sieves(Parts.size() - ColdParts.size() + 1); - + sieves.back() = MemTable->Traced(); /* blobs of memtable */ - + ui64 total = sieves.back().Total(); ui64 seen = sieves.back().Removed(); - - for (auto &it: Parts) { + + for (auto &it: Parts) { const auto *part = it.first; if (ColdParts.contains(part)) { continue; // we don't trace cold parts @@ -221,7 +221,7 @@ namespace NFwd { if (auto &blobs = part->Blobs) { auto &q = GetQueue(part, part->Groups + 1); auto &line = dynamic_cast<TBlobs&>(*q.PageLoadingLogic); - + Y_VERIFY(q.Slot < (sieves.size() - 1)); sieves.at(q.Slot) = { blobs, @@ -232,26 +232,26 @@ namespace NFwd { total += sieves[q.Slot].Total(); seen += sieves[q.Slot].Removed(); - } - } - - return new TSeen{ total, seen, std::move(sieves) }; - } - - private: + } + } + + return new TSeen{ total, seen, std::move(sieves) }; + } + + private: TResult Handle(TPageLoadingQueue &q, TPageId ref) noexcept - { + { auto got = q->Handle(&q, ref, Conf.AheadLo); - + if ((q.Grow = got.Grow) || bool(q.Fetch)) { Queue.PushBack(&q); - } else if (got.Need && got.Page == nullptr) { - Y_FAIL("Cache line head don't want to do fetch but should"); - } - - return { got.Need, got.Page }; - } - + } else if (got.Need && got.Page == nullptr) { + Y_FAIL("Cache line head don't want to do fetch but should"); + } + + return { got.Need, got.Page }; + } + void AddPartView(const TPartView& partView) noexcept { const auto *part = partView.Part.Get(); @@ -278,8 +278,8 @@ namespace NFwd { } TPageLoadingQueue& GetQueue(const TPart *part, ui16 room) noexcept - { - auto it = Parts.find(part); + { + auto it = Parts.find(part); Y_VERIFY(it != Parts.end(), "NFwd cache tyring to access part outside of subset"); Y_VERIFY(room < it->second.size(), @@ -288,90 +288,90 @@ namespace NFwd { "NFwd cache trying to access room that is not assigned"); Y_VERIFY(Queues.at(it->second[0]).PageCollection->Label() == part->Label, "Cannot handle multiple parts on the same page collection"); - + return Queues.at(it->second[room]); - } - - TSlot Settle(TEgg egg, ui32 slot) noexcept - { + } + + TSlot Settle(TEgg egg, ui32 slot) noexcept + { if (egg.PageLoadingLogic || egg.PageCollection) { const ui64 cookie = (ui64(Queues.size()) << 32) | ui32(Salt + Epoch); - + Queues.emplace_back(slot, cookie, std::move(egg.PageCollection), egg.PageLoadingLogic); - + return Queues.size() - 1; - } else { + } else { return Max<TSlot>(); /* Will fail on access in GetQueue(...) */ - } - } - + } + } + TEgg MakeCache(const TPart *part, NPage::TGroupId groupId, TIntrusiveConstPtr<TSlices> bounds) const noexcept - { + { auto *partStore = dynamic_cast<const TPartStore*>(part); - + Y_VERIFY(groupId.Index < partStore->PageCollections.size(), "Got part without enough page collections"); - + auto& cache = partStore->PageCollections[groupId.Index]; auto& index = part->GetGroupIndex(groupId); if (cache->PageCollection->Total() < index.UpperPage()) - Y_FAIL("Part index last page is out of storage capacity"); - + Y_FAIL("Part index last page is out of storage capacity"); + return { new NFwd::TCache(index, bounds), cache->PageCollection }; - } - + } + TEgg MakeExtern(const TPart *part, TIntrusiveConstPtr<TSlices> bounds) const noexcept - { - if (auto blobs = part->Blobs) { - /* Should always materialize key columns to values since - current impl cannot handle outlined blobs in keys cells. - And have to materialize blobs of alien tablets in some - cases, this behaviour is ruled by Conf.Tablet value. - */ - - const auto tablet = part->Label.TabletID(); - + { + if (auto blobs = part->Blobs) { + /* Should always materialize key columns to values since + current impl cannot handle outlined blobs in keys cells. + And have to materialize blobs of alien tablets in some + cases, this behaviour is ruled by Conf.Tablet value. + */ + + const auto tablet = part->Label.TabletID(); + TVector<ui32> edge(part->Large->Stats().Tags.size(), Conf.Edge); - + for (auto& col : part->Scheme->AllColumns) { - if (TRowScheme::HasTag(Keys, col.Tag)) { - edge.at(col.Pos) = Max<ui32>(); - } else if (Conf.Tablet && Conf.Tablet != tablet) { - edge.at(col.Pos) = Max<ui32>(); - } - } - + if (TRowScheme::HasTag(Keys, col.Tag)) { + edge.at(col.Pos) = Max<ui32>(); + } else if (Conf.Tablet && Conf.Tablet != tablet) { + edge.at(col.Pos) = Max<ui32>(); + } + } + bool trace = Conf.Trace && !ColdParts.contains(part); - return + return { new NFwd::TBlobs(part->Large, std::move(bounds), edge, trace), blobs}; - } else { - return { nullptr, nullptr }; - } - } - + } else { + return { nullptr, nullptr }; + } + } + TEgg MakeOuter(const TPart *part, TIntrusiveConstPtr<TSlices> bounds) const noexcept - { - if (auto small = part->Small) { + { + if (auto small = part->Small) { auto *partStore = CheckedCast<const TPartStore*>(part); - + TVector<ui32> edge(small->Stats().Tags.size(), Max<ui32>()); - + auto pageCollection = partStore->PageCollections.at(partStore->Groups)->PageCollection; - - return + + return { new NFwd::TBlobs(small, std::move(bounds), edge, false), pageCollection }; - } else { - return { nullptr, nullptr }; - } - } - - private: + } else { + return { nullptr, nullptr }; + } + } + + private: const ui32 Salt; ui32 Epoch = 0; - const TConf Conf; + const TConf Conf; const TSubset ⋐ const TVector<ui32> Keys; /* Tags to expand ELargeObj references */ - + TDeque<TPageLoadingQueue> Queues; THashMap<const TPart*, TSlotVec> Parts; THashSet<const TPart*> ColdParts; @@ -383,7 +383,7 @@ namespace NFwd { ui64 Pending = 0; // Accumulated stats on resets TStat Total; - }; -} -} -} + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_fwd_iface.h b/ydb/core/tablet_flat/flat_fwd_iface.h index 460e0412b5..ae083fadc7 100644 --- a/ydb/core/tablet_flat/flat_fwd_iface.h +++ b/ydb/core/tablet_flat/flat_fwd_iface.h @@ -1,39 +1,39 @@ -#pragma once - -#include "flat_sausage_fetch.h" -#include "flat_fwd_misc.h" - -namespace NKikimr { -namespace NTable { -namespace NFwd { - - struct TPage; - +#pragma once + +#include "flat_sausage_fetch.h" +#include "flat_fwd_misc.h" + +namespace NKikimr { +namespace NTable { +namespace NFwd { + + struct TPage; + class IPageLoadingQueue { - public: + public: virtual ~IPageLoadingQueue() = default; virtual ui64 AddToQueue(ui32 page, ui16 type) noexcept = 0; - }; - + }; + class IPageLoadingLogic { - public: + public: struct TResult { const TSharedData *Page; - bool Grow; /* Should give more pages on Forward() */ - bool Need; /* Is vital to client to make progress */ - }; - + bool Grow; /* Should give more pages on Forward() */ + bool Need; /* Is vital to client to make progress */ + }; + virtual ~IPageLoadingLogic() = default; - + virtual TResult Handle(IPageLoadingQueue *head, ui32 page, ui64 lower) noexcept = 0; virtual void Forward(IPageLoadingQueue *head, ui64 upper) noexcept = 0; virtual void Apply(TArrayRef<NPageCollection::TLoadedPage> loaded) noexcept = 0; - + IPageLoadingQueue* Head = nullptr; /* will be set outside of IPageLoadingLogic impl */ - TStat Stat; - }; - -} -} -} + TStat Stat; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_fwd_misc.h b/ydb/core/tablet_flat/flat_fwd_misc.h index 4b7da772f7..f8caecccd7 100644 --- a/ydb/core/tablet_flat/flat_fwd_misc.h +++ b/ydb/core/tablet_flat/flat_fwd_misc.h @@ -1,49 +1,49 @@ -#pragma once - -#include <util/stream/output.h> - -namespace NKikimr { -namespace NTable { -namespace NFwd { - - struct TStat { - /* - Fetch >= Saved >= Usage + After; - Fetch >= Before + Usage + After; - - eff = Usage * [ /Fetch; /(Before + Usage + After) ]; - */ - - void Describe(IOutputStream &out) const noexcept - { - out - << "TFwd{" - << Fetch << "b" - << " > " << Saved << "b" - << " > " << Usage << "b" - << " +" << After << "b" - << " ~" << Before << "b" - << "}"; - } - - TStat& operator +=(const TStat &stat) - { - Fetch += stat.Fetch; - Saved += stat.Saved; - Usage += stat.Usage; - After += stat.After; - Before += stat.Before; - - return *this; - } - - ui64 Fetch = 0; /* Requested to load by cache */ +#pragma once + +#include <util/stream/output.h> + +namespace NKikimr { +namespace NTable { +namespace NFwd { + + struct TStat { + /* + Fetch >= Saved >= Usage + After; + Fetch >= Before + Usage + After; + + eff = Usage * [ /Fetch; /(Before + Usage + After) ]; + */ + + void Describe(IOutputStream &out) const noexcept + { + out + << "TFwd{" + << Fetch << "b" + << " > " << Saved << "b" + << " > " << Usage << "b" + << " +" << After << "b" + << " ~" << Before << "b" + << "}"; + } + + TStat& operator +=(const TStat &stat) + { + Fetch += stat.Fetch; + Saved += stat.Saved; + Usage += stat.Usage; + After += stat.After; + Before += stat.Before; + + return *this; + } + + ui64 Fetch = 0; /* Requested to load by cache */ ui64 Saved = 0; /* Obtained by cache with DoSave() */ - ui64 Usage = 0; /* Actually was used by client */ - ui64 After = 0; /* Dropped after fetch completed */ - ui64 Before = 0; /* Dropped before fetch completed */ - }; - -} -} -} + ui64 Usage = 0; /* Actually was used by client */ + ui64 After = 0; /* Dropped after fetch completed */ + ui64 Before = 0; /* Dropped before fetch completed */ + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_fwd_page.h b/ydb/core/tablet_flat/flat_fwd_page.h index cc903ac366..d81eaacf77 100644 --- a/ydb/core/tablet_flat/flat_fwd_page.h +++ b/ydb/core/tablet_flat/flat_fwd_page.h @@ -1,107 +1,107 @@ -#pragma once - -#include "flat_part_iface.h" -#include "flat_sausage_fetch.h" -#include "flat_fwd_misc.h" - -namespace NKikimr { -namespace NTable { -namespace NFwd { - - enum class EUsage : ui8 { - None = 0, - Seen = 1, /* Page has been used by reference */ - Keep = 2, /* Data has been used at least once */ - }; - - enum class EFetch : ui8 { - Wait = 0, /* Page has been queued for load */ - Drop = 1, /* Queued page page won't be used */ - None = 2, - Done = 3, /* Page has been settled with data */ - }; - - struct TPage { - TPage(TPageId id, ui64 size, ui16 tag, TPageId refer) +#pragma once + +#include "flat_part_iface.h" +#include "flat_sausage_fetch.h" +#include "flat_fwd_misc.h" + +namespace NKikimr { +namespace NTable { +namespace NFwd { + + enum class EUsage : ui8 { + None = 0, + Seen = 1, /* Page has been used by reference */ + Keep = 2, /* Data has been used at least once */ + }; + + enum class EFetch : ui8 { + Wait = 0, /* Page has been queued for load */ + Drop = 1, /* Queued page page won't be used */ + None = 2, + Done = 3, /* Page has been settled with data */ + }; + + struct TPage { + TPage(TPageId id, ui64 size, ui16 tag, TPageId refer) : Size(size), PageId(id), Refer(refer), Tag(tag) - { - - } - - ~TPage() - { - Y_VERIFY(!Data, "Forward cache page is still holds data"); - } - - explicit operator bool() const - { - return bool(Data) && PageId != Max<ui32>(); - } - - bool Ready() const noexcept - { - return Fetch == EFetch::None || Fetch == EFetch::Done; - } - - bool operator<(TPageId pageId) const - { - return PageId < pageId; - } - + { + + } + + ~TPage() + { + Y_VERIFY(!Data, "Forward cache page is still holds data"); + } + + explicit operator bool() const + { + return bool(Data) && PageId != Max<ui32>(); + } + + bool Ready() const noexcept + { + return Fetch == EFetch::None || Fetch == EFetch::Done; + } + + bool operator<(TPageId pageId) const + { + return PageId < pageId; + } + const TSharedData* Plain() const noexcept - { - return Data ? &Data : nullptr; - } - + { + return Data ? &Data : nullptr; + } + ui32 Settle(NPageCollection::TLoadedPage &page) noexcept - { - const auto was = std::exchange(Fetch, EFetch::Done); - - if (PageId != page.PageId) { - Y_FAIL("Settling page with different reference number"); - } else if (Size != page.Data.size()) { + { + const auto was = std::exchange(Fetch, EFetch::Done); + + if (PageId != page.PageId) { + Y_FAIL("Settling page with different reference number"); + } else if (Size != page.Data.size()) { Y_FAIL("Requested and obtained page sizes are not the same"); - } else if (was == EFetch::Drop) { + } else if (was == EFetch::Drop) { std::exchange(page.Data, { }); - } else if (was != EFetch::Wait) { - Y_FAIL("Settling page that is not waiting for any data"); - } else { - Data = std::move(page.Data); - } - - return Data.size(); - } - + } else if (was != EFetch::Wait) { + Y_FAIL("Settling page that is not waiting for any data"); + } else { + Data = std::move(page.Data); + } + + return Data.size(); + } + const TSharedData* Touch(TPageId pageId, TStat &stat) noexcept - { - if (PageId != pageId || (!Data && Fetch == EFetch::Done)) { - Y_FAIL("Touching page thatd doesn't fits to this action"); - } else { - auto to = Fetch == EFetch::None ? EUsage::Seen : EUsage::Keep; - - if (std::exchange(Usage, to) != to && to == EUsage::Keep) - stat.Usage += Size; - } - - return Plain(); - } - + { + if (PageId != pageId || (!Data && Fetch == EFetch::Done)) { + Y_FAIL("Touching page thatd doesn't fits to this action"); + } else { + auto to = Fetch == EFetch::None ? EUsage::Seen : EUsage::Keep; + + if (std::exchange(Usage, to) != to && to == EUsage::Keep) + stat.Usage += Size; + } + + return Plain(); + } + TSharedData Release() noexcept - { - Fetch = Max(Fetch, EFetch::Drop); - + { + Fetch = Max(Fetch, EFetch::Drop); + return std::exchange(Data, { }); - } - + } + const ui64 Size = 0; - const ui32 PageId = Max<ui32>(); - const ui32 Refer = 0; - const ui16 Tag = Max<ui16>(); - EUsage Usage = EUsage::None; - EFetch Fetch = EFetch::None; + const ui32 PageId = Max<ui32>(); + const ui32 Refer = 0; + const ui16 Tag = Max<ui16>(); + EUsage Usage = EUsage::None; + EFetch Fetch = EFetch::None; TSharedData Data; - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_fwd_sieve.h b/ydb/core/tablet_flat/flat_fwd_sieve.h index 3e161415fa..5422583cc4 100644 --- a/ydb/core/tablet_flat/flat_fwd_sieve.h +++ b/ydb/core/tablet_flat/flat_fwd_sieve.h @@ -1,32 +1,32 @@ -#pragma once - -#include "flat_page_blobs.h" -#include "flat_part_screen.h" +#pragma once + +#include "flat_page_blobs.h" +#include "flat_part_screen.h" #include "flat_part_slice.h" -#include <util/generic/deque.h> - -namespace NKikimr { -namespace NTable { -namespace NFwd { - - struct TSieve { - using THoles = TDeque<TScreen::THole>; - - TSieve() { }; - +#include <util/generic/deque.h> + +namespace NKikimr { +namespace NTable { +namespace NFwd { + + struct TSieve { + using THoles = TDeque<TScreen::THole>; + + TSieve() { }; + TSieve( TIntrusiveConstPtr<NPage::TExtBlobs> blobs, TIntrusiveConstPtr<NPage::TFrames> frames, TIntrusiveConstPtr<TSlices> slices, THoles holes) - : Blobs(std::move(blobs)) + : Blobs(std::move(blobs)) , Frames(std::move(frames)) , Filter(std::move(slices)) - , Holes(std::move(holes)) - { - - } - + , Holes(std::move(holes)) + { + + } + ui32 Total() const noexcept { if (!Blobs) { @@ -52,37 +52,37 @@ namespace NFwd { return TScreen::Sum(Holes); } - void MaterializeTo(TVector<TLogoBlobID> &vec) const noexcept - { - const auto limit = Blobs ? Blobs->Total() : 0; - - for (ui64 seq = 0, off = 0; off <= Holes.size(); off++) { + void MaterializeTo(TVector<TLogoBlobID> &vec) const noexcept + { + const auto limit = Blobs ? Blobs->Total() : 0; + + for (ui64 seq = 0, off = 0; off <= Holes.size(); off++) { Y_VERIFY(off == Holes.size() || Holes.at(off).End <= limit); - + auto end = off < Holes.size() ? Holes[off].Begin : limit; - + for (; seq < end; seq++) { if (!Frames || Filter.Has(Frames->Relation(seq).Row)) { vec.emplace_back(Blobs->Glob(seq).Logo); } } - + seq = Max(seq, off < Holes.size() ? Holes[off].End : limit); - } - } - + } + } + TIntrusiveConstPtr<NPage::TExtBlobs> Blobs; TIntrusiveConstPtr<NPage::TFrames> Frames; TSlicesRowFilter Filter; - TDeque<TScreen::THole> Holes; - }; - - struct TSeen { - const ui64 Total; - const ui64 Seen; - TDeque<TSieve> Sieve; - }; - -} -} -} + TDeque<TScreen::THole> Holes; + }; + + struct TSeen { + const ui64 Total; + const ui64 Seen; + TDeque<TSieve> Sieve; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_fwd_warmed.h b/ydb/core/tablet_flat/flat_fwd_warmed.h index 1e8adbbbf1..991f390bd1 100644 --- a/ydb/core/tablet_flat/flat_fwd_warmed.h +++ b/ydb/core/tablet_flat/flat_fwd_warmed.h @@ -1,75 +1,75 @@ -#pragma once - -#include "flat_fwd_conf.h" -#include "flat_fwd_sieve.h" -#include "flat_mem_warm.h" -#include "flat_part_screen.h" -#include "flat_part_iface.h" -#include "flat_page_blobs.h" - -#include <util/generic/bitmap.h> -#include <util/generic/xrange.h> - -namespace NKikimr { -namespace NTable { -namespace NFwd { - +#pragma once + +#include "flat_fwd_conf.h" +#include "flat_fwd_sieve.h" +#include "flat_mem_warm.h" +#include "flat_part_screen.h" +#include "flat_part_iface.h" +#include "flat_page_blobs.h" + +#include <util/generic/bitmap.h> +#include <util/generic/xrange.h> + +namespace NKikimr { +namespace NTable { +namespace NFwd { + class TMemTableHandler /* handler for TMemTable table */ { - public: + public: using TResult = IPages::TResult; using TRace = TVector<TMemTableSnapshot>; - + TMemTableHandler(TArrayRef<const ui32> tags, ui32 edge, const TRace *trace) - : Tags(tags) - , Edge(edge) - { - if (trace) { - for (auto &one: *trace) + : Tags(tags) + , Edge(edge) + { + if (trace) { + for (auto &one: *trace) if (auto *blobs = one->GetBlobs()) - Offset = Min(Offset, blobs->Head); - + Offset = Min(Offset, blobs->Head); + Blobs = TMemTable::MakeBlobsPage(*trace); - Touches.Reserve(Blobs->Total()); - } - } - + Touches.Reserve(Blobs->Total()); + } + } + TResult Locate(const TMemTable *memTable, ui64 ref, ui32 tag) noexcept - { + { const auto &glob = memTable->GetBlobs()->Get(ref); - + Y_VERIFY(glob.Data, "External blob in TMemTable with no data"); Y_VERIFY(!Blobs || ref >= Offset, "Unexpected ELargeObj reference"); - - bool omit = glob.Bytes() >= Edge && !TRowScheme::HasTag(Tags, tag); - - if (omit && Blobs) Touches.Set(ref - Offset); - - return { !omit, omit ? nullptr : &glob.Data }; - } - - TSieve Traced() noexcept - { + + bool omit = glob.Bytes() >= Edge && !TRowScheme::HasTag(Tags, tag); + + if (omit && Blobs) Touches.Set(ref - Offset); + + return { !omit, omit ? nullptr : &glob.Data }; + } + + TSieve Traced() noexcept + { /* Blobs in TMemTable catalog isn't sorted in order of appearance - in rows cells. That is way bitmap is used instead of just - trace cooker as it done for alredy compacted TPart. - */ - - TScreen::TCook trace; - - for (auto seq: xrange(Blobs->Total())) - if (Touches[seq]) - trace.Pass(seq); - + in rows cells. That is way bitmap is used instead of just + trace cooker as it done for alredy compacted TPart. + */ + + TScreen::TCook trace; + + for (auto seq: xrange(Blobs->Total())) + if (Touches[seq]) + trace.Pass(seq); + return { std::move(Blobs), nullptr, nullptr, trace.Unwrap() }; - } - - private: - const TArrayRef<const ui32> Tags; - const ui32 Edge = Max<ui32>(); - ui64 Offset = Max<ui64>(); + } + + private: + const TArrayRef<const ui32> Tags; + const ui32 Edge = Max<ui32>(); + ui64 Offset = Max<ui64>(); TIntrusiveConstPtr<NPage::TExtBlobs> Blobs; - TDynBitMap Touches; - }; -} -} -} + TDynBitMap Touches; + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_iterator.h b/ydb/core/tablet_flat/flat_iterator.h index 60195c17b4..bc52d6d1ec 100644 --- a/ydb/core/tablet_flat/flat_iterator.h +++ b/ydb/core/tablet_flat/flat_iterator.h @@ -1,9 +1,9 @@ #pragma once #include "flat_iterator_ops.h" -#include "flat_mem_iter.h" +#include "flat_mem_iter.h" #include "flat_part_iter_multi.h" -#include "flat_row_remap.h" -#include "flat_row_state.h" +#include "flat_row_remap.h" +#include "flat_row_state.h" #include "flat_range_cache.h" #include "util_fmt_cell.h" @@ -14,7 +14,7 @@ #include <util/generic/queue.h> namespace NKikimr { -namespace NTable { +namespace NTable { enum class ENext { All, @@ -36,13 +36,13 @@ class TTableItBase : TNonCopyable { }; enum class EStage : ui8 { - Seek = 0, /* Have Stuck on Seek() stage */ + Seek = 0, /* Have Stuck on Seek() stage */ Done = 1, Turn = 2, Snap = 3, Fill = 4, - }; - + }; + class TEraseCachingState { using TOps = typename TIteratorOps::TEraseCacheOps; @@ -259,18 +259,18 @@ public: } EReady Next(ENext mode) noexcept - { + { TEraseCachingState eraseCache(this); bool isHead = true; - for (Ready = EReady::Data; Ready == EReady::Data; ) { - if (Stage == EStage::Seek) { - Ready = Start(); + for (Ready = EReady::Data; Ready == EReady::Data; ) { + if (Stage == EStage::Seek) { + Ready = Start(); } else if (Stage == EStage::Done) { Stage = EStage::Turn; Ready = Turn(); - } else if (Stage == EStage::Turn) { - Ready = Turn(); + } else if (Stage == EStage::Turn) { + Ready = Turn(); } else if (Stage == EStage::Snap) { if (mode != ENext::Uncommitted) { ui64 skipsBefore = Stats.InvisibleRowSkips; @@ -281,7 +281,7 @@ public: Stage = EStage::Fill; isHead = false; } - } else if ((Ready = Apply()) != EReady::Data) { + } else if ((Ready = Apply()) != EReady::Data) { } else if (mode == ENext::All || mode == ENext::Uncommitted || State.GetRowState() != ERowOp::Erase) { break; @@ -295,27 +295,27 @@ public: isHead = true; } } - } - } - + } + } + if (ErasedKeysCache && mode != ENext::All) { eraseCache.Flush(); } - return Last(); - } - - EReady Last() const noexcept - { - return Ready; - } - - TDbTupleRef GetKey() const noexcept; - TDbTupleRef GetValues() const noexcept; - - const TRowState& Row() const noexcept - { - return State; + return Last(); + } + + EReady Last() const noexcept + { + return Ready; + } + + TDbTupleRef GetKey() const noexcept; + TDbTupleRef GetValues() const noexcept; + + const TRowState& Row() const noexcept + { + return State; } bool IsUncommitted() const noexcept; @@ -324,16 +324,16 @@ public: TRowVersion GetRowVersion() const noexcept; EReady SkipToRowVersion(TRowVersion rowVersion) noexcept; -public: - const TRowScheme* Scheme; - const TRemap Remap; +public: + const TRowScheme* Scheme; + const TRemap Remap; TIntrusivePtr<TKeyRangeCache> ErasedKeysCache; TIteratorStats Stats; private: - ui64 Limit = 0; + ui64 Limit = 0; - TRowState State; + TRowState State; // RowVersion of a persistent snapshot that we are reading // By default iterator is initialized with the HEAD snapshot @@ -342,9 +342,9 @@ private: // A map of currently committed transactions to corresponding row versions const NTable::TTransactionMap<TRowVersion> CommittedTransactions; - EStage Stage = EStage::Seek; - EReady Ready = EReady::Gone; - THolderVector<TMemIt> MemIters; + EStage Stage = EStage::Seek; + EReady Ready = EReady::Gone; + THolderVector<TMemIt> MemIters; THolderVector<TRunIt> RunIters; TOwnedCellVec StopKey; bool StopKeyInclusive = true; @@ -355,29 +355,29 @@ private: TEpoch Epoch; }; - struct TElement { + struct TElement { TArrayRef<const TCell> Key; TIteratorId IteratorId; }; - struct TComparator { + struct TComparator { TComparator(TArrayRef<const NScheme::TTypeIdOrder> types) - : Types(types) + : Types(types) {} int CompareKeys(TArrayRef<const TCell> a, TArrayRef<const TCell> b) const noexcept - { + { return TIteratorOps::CompareKeys(Types, a, b); } - bool operator() (const TElement& a, const TElement& b) const noexcept - { + bool operator() (const TElement& a, const TElement& b) const noexcept + { if (int cmp = CompareKeys(a.Key, b.Key)) - return cmp > 0; + return cmp > 0; Y_VERIFY_DEBUG(a.IteratorId.Epoch != b.IteratorId.Epoch, "Found equal key iterators with the same epoch"); - return a.IteratorId.Epoch < b.IteratorId.Epoch; + return a.IteratorId.Epoch < b.IteratorId.Epoch; } const TArrayRef<const NScheme::TTypeIdOrder> Types; @@ -405,28 +405,28 @@ private: } // ITERATORS STORAGE - // Range [ IteratorsHeap.begin(); Active ) form a heap - // Range [ Active; IteratorsHeap.end() ) are currently active iterators (i.e. that have key equal to current key) + // Range [ IteratorsHeap.begin(); Active ) form a heap + // Range [ Active; IteratorsHeap.end() ) are currently active iterators (i.e. that have key equal to current key) // Also note that active iterators should be traversed in reverse order - TComparator Comparator; - using TIterators = TSmallVec<TElement>; + TComparator Comparator; + using TIterators = TSmallVec<TElement>; using TForwardIter = typename TIterators::iterator; using TReverseIter = typename TIterators::reverse_iterator; TIterators Iterators; - TForwardIter Active; + TForwardIter Active; TForwardIter Inactive; ui64 DeltaTxId = 0; TRowVersion DeltaVersion; bool Delta = false; bool Uncommitted = false; - EReady Start() noexcept; - EReady Turn() noexcept; + EReady Start() noexcept; + EReady Turn() noexcept; EReady Snap() noexcept; EReady Snap(TRowVersion rowVersion) noexcept; EReady DoSkipUncommitted() noexcept; - EReady Apply() noexcept; + EReady Apply() noexcept; void AddReadyIterator(TArrayRef<const TCell> key, TIteratorId itId); void AddNotReadyIterator(TIteratorId itId); @@ -460,13 +460,13 @@ inline TTableItBase<TIteratorOps>::TTableItBase( TRowVersion snapshot, const NTable::TTransactionMap<TRowVersion>& committedTransactions) : Scheme(scheme) - , Remap(*Scheme, tags) - , Limit(limit) - , State(Remap.Size()) + , Remap(*Scheme, tags) + , Limit(limit) + , State(Remap.Size()) , SnapshotVersion(snapshot) , CommittedTransactions(committedTransactions) - , Comparator(Scheme->Keys->Types) - , Active(Iterators.end()) + , Comparator(Scheme->Keys->Types) + , Active(Iterators.end()) , Inactive(Iterators.end()) {} @@ -477,30 +477,30 @@ inline TTableItBase<TIteratorOps>::~TTableItBase() template<class TIteratorOps> inline void TTableItBase<TIteratorOps>::AddReadyIterator(TArrayRef<const TCell> key, TIteratorId itId) { - Active = Iterators.emplace(Active, TElement({key, itId})); - ++Active; - std::push_heap(Iterators.begin(), Active, Comparator); + Active = Iterators.emplace(Active, TElement({key, itId})); + ++Active; + std::push_heap(Iterators.begin(), Active, Comparator); Inactive = Active; } template<class TIteratorOps> inline void TTableItBase<TIteratorOps>::AddNotReadyIterator(TIteratorId itId) { - size_t actPos = Active - Iterators.begin(); + size_t actPos = Active - Iterators.begin(); Iterators.emplace_back(TElement({{ }, itId})); - Active = Iterators.begin() + actPos; + Active = Iterators.begin() + actPos; Inactive = Active; } template<class TIteratorOps> inline void TTableItBase<TIteratorOps>::Push(TAutoPtr<TMemIt> it) -{ - if (it && it->IsValid()) { +{ + if (it && it->IsValid()) { TIteratorId itId = { EType::Mem, ui16(MemIters.size()), AdjustEpoch(it->MemTable->Epoch) }; - - MemIters.PushBack(it); - TDbTupleRef key = MemIters.back()->GetKey(); + + MemIters.PushBack(it); + TDbTupleRef key = MemIters.back()->GetKey(); AddReadyIterator(key.Cells(), itId); - } + } } template<class TIteratorOps> @@ -555,7 +555,7 @@ inline void TTableItBase<TIteratorOps>::StopAfter(TArrayRef<const TCell> key) template<class TIteratorOps> inline EReady TTableItBase<TIteratorOps>::Start() noexcept -{ +{ if (Active != Iterators.end()) { return EReady::Page; } @@ -568,8 +568,8 @@ inline EReady TTableItBase<TIteratorOps>::Start() noexcept } auto key = Iterators.front().Key; - PopHeap(Iterators.begin(), Active--, Comparator); - while (Active != Iterators.begin()) { + PopHeap(Iterators.begin(), Active--, Comparator); + while (Active != Iterators.begin()) { if (Comparator.CompareKeys(key, Iterators.front().Key) != 0) break; @@ -579,7 +579,7 @@ inline EReady TTableItBase<TIteratorOps>::Start() noexcept break; } - PopHeap(Iterators.begin(), Active--, Comparator); + PopHeap(Iterators.begin(), Active--, Comparator); } Stage = EStage::Snap; @@ -589,7 +589,7 @@ inline EReady TTableItBase<TIteratorOps>::Start() noexcept template<class TIteratorOps> inline EReady TTableItBase<TIteratorOps>::Turn() noexcept -{ +{ if (!Limit) { // Optimization: avoid calling Next after returning the last row return EReady::Gone; @@ -598,7 +598,7 @@ inline EReady TTableItBase<TIteratorOps>::Turn() noexcept bool ready = true; size_t left = Iterators.end() - Active; while (left-- > 0) { - TIteratorId ai = Active->IteratorId; + TIteratorId ai = Active->IteratorId; ui32 idx = ai.Index; switch (ai.Type) { case EType::Mem: { @@ -855,14 +855,14 @@ inline EReady TTableItBase<TIteratorOps>::DoSkipUncommitted() noexcept template<class TIteratorOps> inline EReady TTableItBase<TIteratorOps>::Apply() noexcept -{ - State.Reset(Remap.Nulls()); - - const TDbTupleRef key = GetKey(); +{ + State.Reset(Remap.Nulls()); - for (auto &pin: Remap.KeyPins()) + const TDbTupleRef key = GetKey(); + + for (auto &pin: Remap.KeyPins()) State.Set(pin.Pos, { ECellOp::Set, ELargeObj::Inline }, key.Columns[pin.Key]); - + // We must have at least one active iterator Y_VERIFY_DEBUG(Active != Inactive); @@ -921,14 +921,14 @@ inline EReady TTableItBase<TIteratorOps>::Apply() noexcept if (State.Need()) { return EReady::Page; } - + Stage = EStage::Done; return EReady::Data; } template<class TIteratorOps> inline TDbTupleRef TTableItBase<TIteratorOps>::GetKey() const noexcept -{ +{ TIteratorId ai = Iterators.back().IteratorId; switch (ai.Type) { case EType::Mem: @@ -942,10 +942,10 @@ inline TDbTupleRef TTableItBase<TIteratorOps>::GetKey() const noexcept template<class TIteratorOps> inline TDbTupleRef TTableItBase<TIteratorOps>::GetValues() const noexcept -{ +{ if (State.GetRowState() == ERowOp::Erase) return TDbTupleRef(); - return TDbTupleRef(Remap.Types().begin(), (*State).begin(), (*State).size()); + return TDbTupleRef(Remap.Types().begin(), (*State).begin(), (*State).size()); } template<class TIteratorOps> @@ -1037,5 +1037,5 @@ inline bool TTableItBase<TIteratorOps>::SeekInternal(TArrayRef<const TCell> key, return ready; } -} +} } diff --git a/ydb/core/tablet_flat/flat_mem_blobs.h b/ydb/core/tablet_flat/flat_mem_blobs.h index cb29308fe8..45fcd4c483 100644 --- a/ydb/core/tablet_flat/flat_mem_blobs.h +++ b/ydb/core/tablet_flat/flat_mem_blobs.h @@ -1,25 +1,25 @@ -#pragma once - -#include "flat_sausage_solid.h" -#include "flat_sausage_fetch.h" +#pragma once + +#include "flat_sausage_solid.h" +#include "flat_sausage_fetch.h" #include "util_store.h" #include <ydb/core/base/shared_data.h> -#include <util/generic/ptr.h> - -namespace NKikimr { -namespace NTable { -namespace NMem { - +#include <util/generic/ptr.h> + +namespace NKikimr { +namespace NTable { +namespace NMem { + class TBlobs : private TNonCopyable { using TStore = NUtil::TConcurrentStore<NPageCollection::TMemGlob>; - public: + public: explicit TBlobs(ui64 head) : Head(head) { } - + ui64 GetBytes() const noexcept { return Bytes; @@ -35,55 +35,55 @@ namespace NMem { return Store.Iterator(); } - ui64 Tail() const noexcept - { + ui64 Tail() const noexcept + { return Head + Store.size(); - } - + } + const NPageCollection::TMemGlob& GetRaw(ui64 index) const noexcept { return Store[index]; } const NPageCollection::TMemGlob& Get(ui64 ref) const noexcept - { + { Y_VERIFY(ref >= Head && ref < Tail(), "ELargeObj ref is out of cache"); - + return Store[ref - Head]; - } - + } + ui64 Push(const NPageCollection::TMemGlob &glob) noexcept - { - return Push(glob.GId, glob.Data); - } - + { + return Push(glob.GId, glob.Data); + } + ui64 Push(const NPageCollection::TGlobId& glob, TSharedData data) noexcept - { - Y_VERIFY(glob.Logo.BlobSize(), "Blob cannot have zero bytes"); - + { + Y_VERIFY(glob.Logo.BlobSize(), "Blob cannot have zero bytes"); + Store.emplace_back(glob, std::move(data)); Bytes += glob.Logo.BlobSize(); - + return Head + (Store.size() - 1); - } - + } + void Assign(TArrayRef<NPageCollection::TLoadedPage> pages) noexcept - { - for (auto &one : pages) { + { + for (auto &one : pages) { Y_VERIFY(one.PageId < Store.size()); - + Store[one.PageId].Data = std::move(one.Data); - } - } - + } + } + public: const ui64 Head; private: ui64 Bytes = 0; TStore Store; - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_mem_eggs.h b/ydb/core/tablet_flat/flat_mem_eggs.h index b422598f8d..3101414b6a 100644 --- a/ydb/core/tablet_flat/flat_mem_eggs.h +++ b/ydb/core/tablet_flat/flat_mem_eggs.h @@ -1,62 +1,62 @@ -#pragma once - -#include "flat_row_eggs.h" +#pragma once + +#include "flat_row_eggs.h" #include <ydb/core/scheme/scheme_tablecell.h> #include <ydb/core/scheme/scheme_type_id.h> - + #include <atomic> -namespace NKikimr { -namespace NTable { -namespace NMem { - -#pragma pack(push,4) - +namespace NKikimr { +namespace NTable { +namespace NMem { + +#pragma pack(push,4) + struct TColumnUpdate { TColumnUpdate() : TColumnUpdate(Max<TTag>(), ECellOp::Empty, { }) { } - + TColumnUpdate(TTag tag, TCellOp op, const TCell& value) - : Tag(tag) - , Op((ui32)op.Raw()) - , Value(value) - { - - } - - ui32 Tag:24; - ui32 Op:8; - TCell Value; - }; - -#pragma pack(pop) - - struct TUpdate { + : Tag(tag) + , Op((ui32)op.Raw()) + , Value(value) + { + + } + + ui32 Tag:24; + ui32 Op:8; + TCell Value; + }; + +#pragma pack(pop) + + struct TUpdate { TColumnUpdate* Ops() noexcept - { + { return reinterpret_cast<TColumnUpdate*>(this + 1); - } - + } + const TColumnUpdate* Ops() const noexcept { return reinterpret_cast<const TColumnUpdate*>(this + 1); } TArrayRef<const TColumnUpdate> operator*() const noexcept - { + { return { Ops(), Items }; - } - + } + const TUpdate *Next; TRowVersion RowVersion; ui16 Items; ERowOp Rop; - }; - + }; + struct TTreeKey { explicit TTreeKey(const TCell* keyCells) : KeyCells(keyCells) { } - + const TCell* KeyCells; }; @@ -73,17 +73,17 @@ namespace NMem { } update->Next = next; Chain = update; - } - + } + const TUpdate* GetFirst() const { return Chain; } const TUpdate* Chain; - }; - + }; + static_assert(sizeof(TColumnUpdate) == 16, "TColumnUpdate must be 16 bytes"); static_assert(sizeof(TUpdate) == 32, "TUpdate must be 32 bytes"); -} -} -} +} +} +} diff --git a/ydb/core/tablet_flat/flat_mem_iter.h b/ydb/core/tablet_flat/flat_mem_iter.h index 5d1c4fdf25..c6d5ec17aa 100644 --- a/ydb/core/tablet_flat/flat_mem_iter.h +++ b/ydb/core/tablet_flat/flat_mem_iter.h @@ -1,41 +1,41 @@ -#pragma once - -#include "flat_update_op.h" -#include "flat_row_scheme.h" -#include "flat_row_remap.h" -#include "flat_row_state.h" -#include "flat_mem_warm.h" +#pragma once + +#include "flat_update_op.h" +#include "flat_row_scheme.h" +#include "flat_row_remap.h" +#include "flat_row_state.h" +#include "flat_mem_warm.h" #include "flat_mem_snapshot.h" -#include "flat_part_iface.h" -#include "flat_page_label.h" +#include "flat_part_iface.h" +#include "flat_page_label.h" #include "flat_table_committed.h" #include <ydb/core/scheme/scheme_tablecell.h> #include <ydb/core/scheme/scheme_type_id.h> - -namespace NKikimr { -namespace NTable { - - class TMemIt { - public: - using TCells = TArrayRef<const TCell>; - + +namespace NKikimr { +namespace NTable { + + class TMemIt { + public: + using TCells = TArrayRef<const TCell>; + TMemIt(const TMemTable* memTable, TIntrusiveConstPtr<TKeyNulls> nulls, const TRemap* remap, IPages *env, NMem::TTreeIterator iterator) : MemTable(memTable) - , Nulls(std::move(nulls)) - , Remap(remap) - , Env(env) + , Nulls(std::move(nulls)) + , Remap(remap) + , Env(env) , RowIt(std::move(iterator)) - { - Key.reserve(Nulls->Size()); - - Y_VERIFY(Key.capacity() > 0, "No key cells in part scheme"); - Y_VERIFY(Remap, "Remap cannot be NULL"); - } - + { + Key.reserve(Nulls->Size()); + + Y_VERIFY(Key.capacity() > 0, "No key cells in part scheme"); + Y_VERIFY(Remap, "Remap cannot be NULL"); + } + static TAutoPtr<TMemIt> Make( const TMemTable& memTable, const NMem::TTreeSnapshot& snapshot, @@ -45,9 +45,9 @@ namespace NTable { const TRemap *remap, IPages *env, EDirection direction = EDirection::Forward) noexcept - { + { auto *iter = new TMemIt(&memTable, std::move(nulls), remap, env, snapshot.Iterator()); - + switch (direction) { case EDirection::Forward: iter->Seek(key, seek); @@ -56,18 +56,18 @@ namespace NTable { iter->SeekReverse(key, seek); break; } - - return iter; - } - - void Seek(TCells key, ESeek seek) noexcept - { - Key.clear(); + + return iter; + } + + void Seek(TCells key, ESeek seek) noexcept + { + Key.clear(); CurrentVersion = nullptr; - - if (key) { - NMem::TPoint search{ key, *Nulls }; - + + if (key) { + NMem::TPoint search{ key, *Nulls }; + switch (seek) { case ESeek::Lower: RowIt.SeekLowerBound(search); @@ -78,7 +78,7 @@ namespace NTable { case ESeek::Upper: RowIt.SeekUpperBound(search); break; - } + } } else { switch (seek) { case ESeek::Lower: @@ -89,9 +89,9 @@ namespace NTable { RowIt.Invalidate(); break; } - } - } - + } + } + void SeekReverse(TCells key, ESeek seek) noexcept { Key.clear(); @@ -124,28 +124,28 @@ namespace NTable { } } - TDbTupleRef GetKey() const - { - Y_VERIFY_DEBUG(IsValid()); - + TDbTupleRef GetKey() const + { + Y_VERIFY_DEBUG(IsValid()); + const ui32 len = MemTable->Scheme->Keys->Size(); const auto *key = RowIt.GetKey(); - + if (len >= Nulls->BasicTypes().size()) { return { Nulls->BasicTypes().begin(), key, len }; - } else if (!Key) { - Key.insert(Key.end(), key, key + len); - Key.insert(Key.end(), (**Nulls).begin() + len, (**Nulls).end()); - } - + } else if (!Key) { + Key.insert(Key.end(), key, key + len); + Key.insert(Key.end(), (**Nulls).begin() + len, (**Nulls).end()); + } + return { Nulls->BasicTypes().begin(), Key.begin(), ui32(Key.size()) }; - } - + } + bool IsDelta() const noexcept - { + { auto* update = GetCurrentVersion(); Y_VERIFY(update); - + return update->RowVersion.Step == Max<ui64>(); } @@ -154,7 +154,7 @@ namespace NTable { auto* update = GetCurrentVersion(); Y_VERIFY(update); Y_VERIFY(update->RowVersion.Step == Max<ui64>()); - + return update->RowVersion.TxId; } @@ -172,7 +172,7 @@ namespace NTable { } } } - + bool SkipDelta() noexcept { auto* update = GetCurrentVersion(); @@ -218,7 +218,7 @@ namespace NTable { Y_VERIFY(update->RowVersion.Step != Max<ui64>(), "GetRowVersion cannot be called on deltas"); return update->RowVersion; } - + /** * Skips to row at the current key as seen at row version rowVersion * @@ -274,28 +274,28 @@ namespace NTable { // Only committed deltas increment InvisibleRowSkips InvisibleRowSkips++; } - } - } + } + } CurrentVersion = nullptr; return false; - } - - bool IsValid() const - { - return RowIt.IsValid(); - } - + } + + bool IsValid() const + { + return RowIt.IsValid(); + } + void Next() - { + { Y_VERIFY_DEBUG(IsValid(), "Calling Next on an exhausted iterator"); - Key.clear(); + Key.clear(); CurrentVersion = nullptr; - RowIt.Next(); - } - + RowIt.Next(); + } + void Prev() { Y_VERIFY_DEBUG(IsValid(), "Calling Prev on an exhausted iterator"); @@ -306,35 +306,35 @@ namespace NTable { RowIt.Prev(); } - private: + private: void ApplyColumn(TRowState& row, const NMem::TColumnUpdate &up) const noexcept - { - const auto pos = Remap->Has(up.Tag); + { + const auto pos = Remap->Has(up.Tag); auto op = TCellOp::By(up.Op); - - if (!pos || row.IsFinalized(pos)) { - /* Out of remap or row slot is already filled */ + + if (!pos || row.IsFinalized(pos)) { + /* Out of remap or row slot is already filled */ } else if (op == ELargeObj::Inline) { - row.Set(pos, op, up.Value); + row.Set(pos, op, up.Value); } else if (op != ELargeObj::Extern) { Y_FAIL("Got an unknown ELargeObj reference type"); - } else { + } else { const auto ref = up.Value.AsValue<ui64>(); - + if (auto blob = Env->Locate(MemTable, ref, up.Tag)) { - const auto got = NPage::THello().Read(**blob); - - Y_VERIFY(got == NPage::ECodec::Plain && got.Version == 0); - + const auto got = NPage::THello().Read(**blob); + + Y_VERIFY(got == NPage::ECodec::Plain && got.Version == 0); + row.Set(pos, { ECellOp(op), ELargeObj::Inline }, TCell(*got)); - } else { + } else { op = TCellOp(blob.Need ? ECellOp::Null : ECellOp(op), ELargeObj::GlobId); - + row.Set(pos, op, TCell::Make(MemTable->GetBlobs()->Get(ref).GId)); - } - } - } - + } + } + } + const NMem::TUpdate* GetCurrentVersion() const noexcept { Y_VERIFY_DEBUG(IsValid(), "Attempt to access an invalid row"); @@ -347,18 +347,18 @@ namespace NTable { return CurrentVersion; } - public: + public: const TMemTable *MemTable = nullptr; const TIntrusiveConstPtr<TKeyNulls> Nulls; - const TRemap* Remap = nullptr; - IPages * const Env = nullptr; + const TRemap* Remap = nullptr; + IPages * const Env = nullptr; ui64 InvisibleRowSkips = 0; - - private: + + private: NMem::TTreeIterator RowIt; - mutable TSmallVec<TCell> Key; + mutable TSmallVec<TCell> Key; mutable const NMem::TUpdate* CurrentVersion = nullptr; - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_mem_warm.cpp b/ydb/core/tablet_flat/flat_mem_warm.cpp index df1cb798e2..5779fc6a1d 100644 --- a/ydb/core/tablet_flat/flat_mem_warm.cpp +++ b/ydb/core/tablet_flat/flat_mem_warm.cpp @@ -1,27 +1,27 @@ -#include "flat_mem_warm.h" +#include "flat_mem_warm.h" #include "flat_mem_snapshot.h" -#include "flat_page_other.h" +#include "flat_page_other.h" namespace NKikimr { -namespace NTable { +namespace NTable { TString PrintRow(const TDbTupleRef& row, const NScheme::TTypeRegistry& typeRegistry) { return DbgPrintTuple(row, typeRegistry); } TIntrusiveConstPtr<NPage::TExtBlobs> TMemTable::MakeBlobsPage(TArrayRef<const TMemTableSnapshot> list) -{ +{ NPage::TExtBlobsWriter writer; - + for (auto &one: list) { for (auto it = one->GetBlobs()->Iterator(); it.IsValid(); it.Next()) { writer.Put(it->GId); } } - + return new NPage::TExtBlobs(writer.Make(true), { }); -} - +} + NMem::TTreeSnapshot TMemTable::Snapshot() { return NMem::TTreeSnapshot(Tree.Snapshot()); } @@ -45,25 +45,25 @@ void TMemTable::DebugDump(IOutputStream& str, const NScheme::TTypeRegistry& type TString keyStr = PrintRow(key, typeRegistry) + " -> "; const auto *row = it.GetValue(); - while (row) { + while (row) { str << keyStr << "ERowOp " << int(row->Rop) << " {"; - for (ui32 i = 0; i < row->Items; ++i) { - TTag colId = row->Ops()[i].Tag; - if (Scheme->ColInfo(colId)) { - NScheme::TTypeId typeId = Scheme->ColInfo(colId)->TypeId; - auto &op = row->Ops()[i]; - + for (ui32 i = 0; i < row->Items; ++i) { + TTag colId = row->Ops()[i].Tag; + if (Scheme->ColInfo(colId)) { + NScheme::TTypeId typeId = Scheme->ColInfo(colId)->TypeId; + auto &op = row->Ops()[i]; + str << EOpToStr(ECellOp(op.Op)) << " " << op.Tag << " " << DbgPrintCell(op.Value, typeId, typeRegistry); } else { str << "unknown column " << colId; } - if (i+1 < row->Items) + if (i+1 < row->Items) str << ", "; } str << "}" << Endl; - row = row->Next; + row = row->Next; } } } diff --git a/ydb/core/tablet_flat/flat_mem_warm.h b/ydb/core/tablet_flat/flat_mem_warm.h index 96bb9d65fa..1bd6ec57ea 100644 --- a/ydb/core/tablet_flat/flat_mem_warm.h +++ b/ydb/core/tablet_flat/flat_mem_warm.h @@ -1,56 +1,56 @@ -#pragma once -#include "defs.h" -#include "flat_update_op.h" -#include "flat_mem_eggs.h" -#include "flat_mem_blobs.h" -#include "flat_row_scheme.h" -#include "flat_row_nulls.h" -#include "flat_row_celled.h" -#include "flat_page_blobs.h" -#include "flat_sausage_solid.h" +#pragma once +#include "defs.h" +#include "flat_update_op.h" +#include "flat_mem_eggs.h" +#include "flat_mem_blobs.h" +#include "flat_row_scheme.h" +#include "flat_row_nulls.h" +#include "flat_row_celled.h" +#include "flat_page_blobs.h" +#include "flat_sausage_solid.h" #include "flat_table_committed.h" #include <ydb/core/scheme/scheme_tablecell.h> #include <ydb/core/scheme/scheme_type_id.h> #include <ydb/core/util/btree_cow.h> #include <ydb/core/util/yverify_stream.h> - + #include <library/cpp/containers/stack_vector/stack_vec.h> -#include <util/generic/vector.h> -#include <util/memory/pool.h> - -namespace NKikimr { -namespace NTable { -namespace NMem { - - struct TPoint { - TArrayRef<const TCell> Key; +#include <util/generic/vector.h> +#include <util/memory/pool.h> + +namespace NKikimr { +namespace NTable { +namespace NMem { + + struct TPoint { + TArrayRef<const TCell> Key; const TKeyNulls &Nulls; - }; - + }; + struct TCandidate { const TCell* Key; }; - struct TKeyCmp { + struct TKeyCmp { const NScheme::TTypeIdOrder* Types; - const ui32 Count; - - explicit TKeyCmp(const TRowScheme& rowScheme) - : Types(&rowScheme.Keys->Types[0]) - , Count(rowScheme.Keys->Types.size()) - { - - } - + const ui32 Count; + + explicit TKeyCmp(const TRowScheme& rowScheme) + : Types(&rowScheme.Keys->Types[0]) + , Count(rowScheme.Keys->Types.size()) + { + + } + bool operator()(const TTreeKey& a, const TTreeKey& b) const { return CompareTypedCellVectors(a.KeyCells, b.KeyCells, Types, Count) < 0; - } - + } + bool operator()(const TTreeKey& a, const TCandidate& b) const { return CompareTypedCellVectors(a.KeyCells, b.Key, Types, Count) < 0; } - + bool operator()(const TCandidate& a, const TTreeKey& b) const { return CompareTypedCellVectors(a.Key, b.KeyCells, Types, Count) < 0; } @@ -62,12 +62,12 @@ namespace NMem { const TCell& left = i < Count ? a[i] : b.Nulls[i]; if (int cmp = CompareTypedCells(left, b.Key[i], b.Nulls.Types[i])) - return cmp; - } - + return cmp; + } + // Missing point cells are filled with a virtual +inf return b.Key.size() < b.Nulls->size() ? -1 : 0; - } + } bool operator()(const TTreeKey& a, const TPoint& b) const { return DoCompare(a.KeyCells, b) < 0; @@ -76,41 +76,41 @@ namespace NMem { bool operator()(const TPoint& a, const TTreeKey& b) const { return DoCompare(b.KeyCells, a) > 0; } - }; - + }; + using TTree = TCowBTree<TTreeKey, TTreeValue, TKeyCmp>; - + class TTreeIterator; class TTreeSnapshot; - + } // namespace NMem - class TMemIt; - + class TMemIt; + struct TMemTableSnapshot; class TMemTable : public TThrRefBase { - friend class TMemIt; - - template <size_t SizeCap = 512*1024, size_t Overhead = 64> - class TMyPolicy : public TMemoryPool::IGrowPolicy { - public: - size_t Next(size_t prev) const noexcept override - { - if (prev >= SizeCap - Overhead) - return SizeCap - Overhead; - - // Use same buckets as LF-alloc (4KB, 6KB, 8KB, 12KB, 16KB ...) - size_t size = FastClp2(prev); - - if (size < prev + prev/3) - size += size/2; - - return size - Overhead; - } - }; - - public: + friend class TMemIt; + + template <size_t SizeCap = 512*1024, size_t Overhead = 64> + class TMyPolicy : public TMemoryPool::IGrowPolicy { + public: + size_t Next(size_t prev) const noexcept override + { + if (prev >= SizeCap - Overhead) + return SizeCap - Overhead; + + // Use same buckets as LF-alloc (4KB, 6KB, 8KB, 12KB, 16KB ...) + size_t size = FastClp2(prev); + + if (size < prev + prev/3) + size += size/2; + + return size - Overhead; + } + }; + + public: struct TTxIdStat { ui64 OpsCount = 0; }; @@ -119,27 +119,27 @@ namespace NMem { public: using TTree = NMem::TTree; - using TOpsRef = TArrayRef<const TUpdateOp>; + using TOpsRef = TArrayRef<const TUpdateOp>; using TMemGlob = NPageCollection::TMemGlob; - + TMemTable(TIntrusiveConstPtr<TRowScheme> scheme, TEpoch epoch, ui64 annex, ui64 chunk = 4032) - : Epoch(epoch) - , Scheme(scheme) + : Epoch(epoch) + , Scheme(scheme) , Blobs(annex) - , Comparator(*Scheme) - , Pool(chunk, &Policy) + , Comparator(*Scheme) + , Pool(chunk, &Policy) , Tree(Comparator) // TODO: support TMemoryPool with caching - {} - + {} + void Update(ERowOp rop, TRawVals key_, TOpsRef ops, TArrayRef<TMemGlob> pages, TRowVersion rowVersion, const NTable::TTransactionMap<TRowVersion>& committed) - { + { Y_VERIFY_DEBUG( rop == ERowOp::Upsert || rop == ERowOp::Erase || rop == ERowOp::Reset, "Unexpected row operation"); - Y_VERIFY(ops.size() < Max<ui16>(), "Too large update ops array"); - + Y_VERIFY(ops.size() < Max<ui16>(), "Too large update ops array"); + // Filter legacy empty values and re-order them in tag order ScratchUpdateTags.clear(); for (ui32 it = 0; it < ops.size(); ++it) { @@ -168,13 +168,13 @@ namespace NMem { } // Find possible existing update for the same key - const TCelled key(key_, *Scheme->Keys, true); + const TCelled key(key_, *Scheme->Keys, true); const NMem::TTreeValue* const current = Tree.Find(NMem::TCandidate{ key.Cells }); const NMem::TUpdate* next = current ? current->GetFirst() : nullptr; - + ScratchMergeTags.clear(); ScratchMergeTagsLast.clear(); - + // When writing a committed row we need to create a fully merged row state if (rowVersion.Step != Max<ui64>()) { // Search for the first committed row version we would need to merge from @@ -269,10 +269,10 @@ namespace NMem { update->Next = next; update->RowVersion = rowVersion; update->Items = mergedSize; - update->Rop = rop; - + update->Rop = rop; + ui32 dstIndex = 0; - + auto missing = ScratchMergeTags.begin(); for (const TTagWithPos& src : ScratchUpdateTags) { const TTag tag = src.first; @@ -284,35 +284,35 @@ namespace NMem { const ui32 it = src.second; const auto *info = Scheme->ColInfo(tag); - if (info == nullptr) { - /* Redo log rolling on bootstap happens with the last - actual row scheme that may have some columns already - be deleted. So cannot differ here error and booting. - */ + if (info == nullptr) { + /* Redo log rolling on bootstap happens with the last + actual row scheme that may have some columns already + be deleted. So cannot differ here error and booting. + */ } else if (TCellOp::HaveNoPayload(ops[it].NormalizedCellOp())) { /* Payloadless ECellOp types may have zero type value */ - } else if (info->TypeId != ops[it].Value.Type()) { - Y_FAIL("Got un unexpected column type in cell update ops"); - } - - auto cell = ops[it].AsCell(); - + } else if (info->TypeId != ops[it].Value.Type()) { + Y_FAIL("Got un unexpected column type in cell update ops"); + } + + auto cell = ops[it].AsCell(); + if (ops[it].Op == ELargeObj::Extern) { /* Transformation REDO ELargeObj to TBlobs reference */ - + const auto ref = Blobs.Push(pages.at(cell.AsValue<ui32>())); - - cell = TCell::Make<ui64>(ref); - + + cell = TCell::Make<ui64>(ref); + } else if (ops[it].Op != ELargeObj::Inline) { Y_FAIL("Got an unexpected ELargeObj reference in update ops"); - } else if (!cell.IsInline()) { - cell = Clone(cell.Data(), cell.Size()); - } - + } else if (!cell.IsInline()) { + cell = Clone(cell.Data(), cell.Size()); + } + update->Ops()[dstIndex++] = { ops[it].Tag, ops[it].Op, cell }; - } - + } + while (missing != ScratchMergeTags.end()) { update->Ops()[dstIndex++] = **missing; ++missing; @@ -324,7 +324,7 @@ namespace NMem { Tree.EmplaceUnsafe(NewKey(key.Cells), update); ++RowCount; } - + ++OpsCount; if (rowVersion.Step == Max<ui64>()) { @@ -335,31 +335,31 @@ namespace NMem { MinRowVersion = Min(MinRowVersion, rowVersion); MaxRowVersion = Max(MaxRowVersion, rowVersion); } - } - + } + size_t GetUsedMem() const noexcept - { - return - Pool.MemoryAllocated() + { + return + Pool.MemoryAllocated() + (Tree.AllocatedPages() - Tree.DroppedPages()) * TTree::PageSize + Blobs.GetBytes(); - } - + } + size_t GetWastedMem() const noexcept { return Pool.MemoryWaste(); } - ui64 GetOpsCount() const noexcept { return OpsCount; } - - ui64 GetRowCount() const noexcept { return RowCount; } - + ui64 GetOpsCount() const noexcept { return OpsCount; } + + ui64 GetRowCount() const noexcept { return RowCount; } + TRowVersion GetMinRowVersion() const noexcept { return MinRowVersion; } TRowVersion GetMaxRowVersion() const noexcept { return MaxRowVersion; } static TIntrusiveConstPtr<NPage::TExtBlobs> MakeBlobsPage(TArrayRef<const TMemTableSnapshot>); - void DebugDump(IOutputStream&, const NScheme::TTypeRegistry&) const; - + void DebugDump(IOutputStream&, const NScheme::TTypeRegistry&) const; + NMem::TTreeSnapshot Snapshot(); NMem::TTreeSnapshot Immediate() const; @@ -397,50 +397,50 @@ namespace NMem { return Removed; } - private: + private: NMem::TTreeKey NewKey(const TCell* src) noexcept { const size_t items = Scheme->Keys->Size(); const size_t bytes = sizeof(TCell) * items; - + void* base = Pool.Allocate(bytes); auto* key = reinterpret_cast<TCell*>(base); - + TCell* dst = key; for (size_t i = 0; i < items; ++i, ++src, ++dst) { new (dst) TCell(Clone(src->Data(), src->Size())); } - + return NMem::TTreeKey(key); - } - - NMem::TUpdate* NewUpdate(ui32 cols) noexcept - { + } + + NMem::TUpdate* NewUpdate(ui32 cols) noexcept + { const size_t bytes = sizeof(NMem::TUpdate) + cols * sizeof(NMem::TColumnUpdate); - - return (NMem::TUpdate*)Pool.Allocate(bytes); - } - - TCell Clone(const char *data, ui32 size) noexcept - { - const bool small = TCell::CanInline(size); - - return { small ? data : Pool.Append(data, size), size }; - } - - void DebugDump() const; - - public: + + return (NMem::TUpdate*)Pool.Allocate(bytes); + } + + TCell Clone(const char *data, ui32 size) noexcept + { + const bool small = TCell::CanInline(size); + + return { small ? data : Pool.Append(data, size), size }; + } + + void DebugDump() const; + + public: const TEpoch Epoch; const TIntrusiveConstPtr<TRowScheme> Scheme; - - private: + + private: NMem::TBlobs Blobs; - const NMem::TKeyCmp Comparator; - TMyPolicy<> Policy; - TMemoryPool Pool; + const NMem::TKeyCmp Comparator; + TMyPolicy<> Policy; + TMemoryPool Pool; TTree Tree; - ui64 OpsCount = 0; - ui64 RowCount = 0; + ui64 OpsCount = 0; + ui64 RowCount = 0; TRowVersion MinRowVersion = TRowVersion::Max(); TRowVersion MaxRowVersion = TRowVersion::Min(); TTxIdStats TxIdStats; @@ -453,7 +453,7 @@ namespace NMem { TSmallVec<TTagWithPos> ScratchUpdateTags; std::vector<const NMem::TColumnUpdate*> ScratchMergeTags; std::vector<const NMem::TColumnUpdate*> ScratchMergeTagsLast; - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_ops_compact.h b/ydb/core/tablet_flat/flat_ops_compact.h index 2ac81c4113..1cb7cdb3f4 100644 --- a/ydb/core/tablet_flat/flat_ops_compact.h +++ b/ydb/core/tablet_flat/flat_ops_compact.h @@ -1,27 +1,27 @@ -#pragma once - -#include "flat_scan_iface.h" -#include "flat_scan_spent.h" -#include "flat_bio_events.h" -#include "flat_writer_bundle.h" -#include "flat_sausage_chop.h" -#include "flat_row_misc.h" -#include "flat_part_writer.h" -#include "flat_part_loader.h" +#pragma once + +#include "flat_scan_iface.h" +#include "flat_scan_spent.h" +#include "flat_bio_events.h" +#include "flat_writer_bundle.h" +#include "flat_sausage_chop.h" +#include "flat_row_misc.h" +#include "flat_part_writer.h" +#include "flat_part_loader.h" #include "flat_part_slice.h" -#include "util_fmt_logger.h" -#include "util_fmt_desc.h" +#include "util_fmt_logger.h" +#include "util_fmt_desc.h" #include "util_basics.h" - + #include <ydb/core/base/blobstorage.h> #include <ydb/core/base/appdata.h> #include <library/cpp/actors/core/actor.h> - + #include <bitset> -namespace NKikimr { -namespace NTabletFlatExecutor { - +namespace NKikimr { +namespace NTabletFlatExecutor { + struct TProdCompact: public IDestructable { struct TResult { NTable::TPartView Part; @@ -34,124 +34,124 @@ namespace NTabletFlatExecutor { TVector<ui32>&& yellowMoveChannels, TVector<ui32>&& yellowStopChannels) : Success(ok) - , Step(step) + , Step(step) , Params(std::move(params)) , YellowMoveChannels(std::move(yellowMoveChannels)) , YellowStopChannels(std::move(yellowStopChannels)) - { - - } - - bool Success = false; - ui32 Step = Max<ui32>(); + { + + } + + bool Success = false; + ui32 Step = Max<ui32>(); TResults Results; TVector<TIntrusiveConstPtr<NTable::TTxStatusPart>> TxStatus; THolder<NTable::TCompactionParams> Params; TVector<ui32> YellowMoveChannels; TVector<ui32> YellowStopChannels; - }; - + }; + class TOpsCompact: private ::NActors::IActor, public NTable::IVersionScan { - using TEvPut = TEvBlobStorage::TEvPut; + using TEvPut = TEvBlobStorage::TEvPut; using TEvPutResult = TEvBlobStorage::TEvPutResult; - using TScheme = NTable::TRowScheme; - using TWriter = NTable::TPartWriter; - using TBundle = NWriter::TBundle; - using TStorage = TIntrusivePtr<TTabletStorageInfo>; + using TScheme = NTable::TRowScheme; + using TWriter = NTable::TPartWriter; + using TBundle = NWriter::TBundle; + using TStorage = TIntrusivePtr<TTabletStorageInfo>; using TEventHandlePtr = TAutoPtr<::NActors::IEventHandle>; - using ELnLev = NUtil::ELnLev; - - public: - constexpr static ui64 MaxFlight = 20ll * (1ll << 20); - + using ELnLev = NUtil::ELnLev; + + public: + constexpr static ui64 MaxFlight = 20ll * (1ll << 20); + TOpsCompact(TActorId owner, TLogoBlobID mask, TAutoPtr<TCompactCfg> conf) : ::NActors::IActor(static_cast<TReceiveFunc>(&TOpsCompact::Inbox), NKikimrServices::TActivity::OPS_COMPACT_A) - , Mask(mask) - , Owner(owner) + , Mask(mask) + , Owner(owner) , Conf(std::move(conf)) - , Bundle(new TBundle(Mask, Conf->Writer)) - { - } - - ~TOpsCompact() - { - // Y_VERIFY(!Driver, "TOpsCompact is still running under scan"); - } - - void Describe(IOutputStream &out) const noexcept override - { - out + , Bundle(new TBundle(Mask, Conf->Writer)) + { + } + + ~TOpsCompact() + { + // Y_VERIFY(!Driver, "TOpsCompact is still running under scan"); + } + + void Describe(IOutputStream &out) const noexcept override + { + out << "Compact{" << Mask.TabletID() - << "." << Mask.Generation() - << "." << Mask.Step() - << ", eph " << Conf->Epoch - << "}"; - } - - private: + << "." << Mask.Generation() + << "." << Mask.Step() + << ", eph " << Conf->Epoch + << "}"; + } + + private: void Registered(TActorSystem *sys, const TActorId&) override - { - Logger = new NUtil::TLogger(sys, NKikimrServices::OPS_COMPACT); - } - + { + Logger = new NUtil::TLogger(sys, NKikimrServices::OPS_COMPACT); + } + THello Prepare(IDriver *driver, TIntrusiveConstPtr<TScheme> scheme) noexcept override - { + { TActivationContext::AsActorContext().RegisterWithSameMailbox(this); - - Spent = new TSpent(TAppData::TimeProvider.Get()); - Registry = AppData()->TypeRegistry; - Scheme = std::move(scheme); - Driver = driver; - + + Spent = new TSpent(TAppData::TimeProvider.Get()); + Registry = AppData()->TypeRegistry; + Scheme = std::move(scheme); + Driver = driver; + NTable::IScan::TConf conf; - - conf.NoErased = false; /* emit erase markers */ - conf.LargeEdge = Conf->Layout.LargeEdge; - - return { EScan::Feed, conf }; - } - - EScan Seek(TLead &lead, ui64 seq) noexcept override - { - if (seq == 0) /* on first Seek() init compaction */ { + + conf.NoErased = false; /* emit erase markers */ + conf.LargeEdge = Conf->Layout.LargeEdge; + + return { EScan::Feed, conf }; + } + + EScan Seek(TLead &lead, ui64 seq) noexcept override + { + if (seq == 0) /* on first Seek() init compaction */ { Y_VERIFY(!Writer, "Initial IScan::Seek(...) called twice"); - - const auto tags = Scheme->Tags(); - - lead.To(tags, { }, NTable::ESeek::Lower); - - auto *scheme = new NTable::TPartScheme(Scheme->Cols); - + + const auto tags = Scheme->Tags(); + + lead.To(tags, { }, NTable::ESeek::Lower); + + auto *scheme = new NTable::TPartScheme(Scheme->Cols); + Writer = new TWriter(scheme, tags, *Bundle, Conf->Layout, Conf->Epoch); - - return EScan::Feed; - - } else if (seq == 1) /* after the end(), stop compaction */ { + + return EScan::Feed; + + } else if (seq == 1) /* after the end(), stop compaction */ { if (!Finished) { Stat = Writer->Finish(); Results = Bundle->Results(); Y_VERIFY(Stat.Parts == Results.size()); WriteTxStatus(); Finished = true; - } - - return Flush(true /* final flush, sleep or finish */); - } else { - Y_FAIL("Compaction scan op should get only two Seeks()"); - } - } - + } + + return Flush(true /* final flush, sleep or finish */); + } else { + Y_FAIL("Compaction scan op should get only two Seeks()"); + } + } + EScan BeginKey(TArrayRef<const TCell> key) noexcept override - { + { Writer->BeginKey(key); - - if (auto logl = Logger->Log(ELnLev::Dbg03)) { - logl + + if (auto logl = Logger->Log(ELnLev::Dbg03)) { + logl << NFmt::Do(*this) << " begin key { " << NFmt::TCells(key, *Scheme->Keys, Registry) << "}"; } - + return Flush(false /* intermediate, sleep or feed */); } @@ -224,19 +224,19 @@ namespace NTabletFlatExecutor { logl << NFmt::Do(*this) << " feed row { "; if (row.GetRowState() == NTable::ERowOp::Erase) { - logl << "erased"; - } else { - logl << NFmt::TCells(*row, *Scheme->Nulls, Registry); - } - + logl << "erased"; + } else { + logl << NFmt::TCells(*row, *Scheme->Nulls, Registry); + } + logl << " at " << rowVersion << " }"; } - + Writer->AddKeyVersion(row, rowVersion); - return Flush(false /* intermediate, sleep or feed */); - } - + return Flush(false /* intermediate, sleep or feed */); + } + EScan EndKey() noexcept override { ui32 written = Writer->EndKey(); @@ -300,12 +300,12 @@ namespace NTabletFlatExecutor { } TAutoPtr<IDestructable> Finish(EAbort abort) noexcept override - { + { const auto fail = Failed || !Finished || abort != EAbort::None; - + auto *prod = new TProdCompact(!fail, Mask.Step(), std::move(Conf->Params), std::move(YellowMoveChannels), std::move(YellowStopChannels)); - + for (auto &result : Results) { Y_VERIFY(result.PageCollections, "Compaction produced a part without page collections"); @@ -313,43 +313,43 @@ namespace NTabletFlatExecutor { std::move(result.PageCollections), { }, std::move(result.Overlay)); - + auto fetch = loader.Run(); - + Y_VERIFY(!fetch, "Just compacted part needs to load some pages"); - + auto& res = prod->Results.emplace_back(); res.Part = loader.Result(); res.Growth = std::move(result.Growth); Y_VERIFY(res.Part, "Unexpected result without a part after compaction"); - } - + } + prod->TxStatus = std::move(TxStatus); - if (auto logl = Logger->Log(fail ? ELnLev::Error : ELnLev::Info)) { - auto raito = Stat.Bytes ? (Stat.Coded + 0.) / Stat.Bytes : 0.; - - logl - << NFmt::Do(*this) << " end=" << ui32(abort) - << ", " << Blobs << "blobs " << Stat.Rows << "r" - << " (max " << Conf->Layout.MaxRows << ")" - << ", put " << NFmt::If(Spent.Get()); - + if (auto logl = Logger->Log(fail ? ELnLev::Error : ELnLev::Info)) { + auto raito = Stat.Bytes ? (Stat.Coded + 0.) / Stat.Bytes : 0.; + + logl + << NFmt::Do(*this) << " end=" << ui32(abort) + << ", " << Blobs << "blobs " << Stat.Rows << "r" + << " (max " << Conf->Layout.MaxRows << ")" + << ", put " << NFmt::If(Spent.Get()); + for (const auto &result : prod->Results) { if (auto *part = result.Part.As<NTable::TPartStore>()) { auto lobs = part->Blobs ? part->Blobs->Total() : 0; auto small = part->Small ? part->Small->Stats().Size : 0; auto large = part->Large ? part->Large->Stats().Size : 0; auto grow = NTable::TScreen::Sum(result.Growth); - + logl << " Part{ " << part->PageCollections.size() << " pk" << ", lobs " << (lobs - grow) << " +" << grow - << ", (" << part->DataSize() + << ", (" << part->DataSize() << " " << small << " " << large <<")b" << " }"; } - } + } if (prod->Results) { logl << ", ecr=" << Sprintf("%.3f", raito); @@ -358,72 +358,72 @@ namespace NTabletFlatExecutor { for (const auto &txStatus : prod->TxStatus) { logl << " TxStatus{ " << txStatus->Label << " }"; } - } - - if (fail) { + } + + if (fail) { prod->Results.clear(); /* shouldn't sent w/o fixation in bs */ } else if (bool(prod->Results) != bool(Stat.Rows > 0)) { - Y_FAIL("Unexpexced rows production result after compaction"); + Y_FAIL("Unexpexced rows production result after compaction"); } else if ((bool(prod->Results) || bool(prod->TxStatus)) != bool(Blobs > 0)) { - Y_FAIL("Unexpexced blobs production result after compaction"); - } - - Driver = nullptr; - - PassAway(); - - return prod; - } - - EScan Flush(bool last) noexcept - { + Y_FAIL("Unexpexced blobs production result after compaction"); + } + + Driver = nullptr; + + PassAway(); + + return prod; + } + + EScan Flush(bool last) noexcept + { for (NPageCollection::TGlob& one : Bundle->GetBlobsToSave()) FlushToBs(std::move(one)); - - EScan scan = EScan::Sleep; - - if (last) { - scan = (Flushing > 0 ? EScan::Sleep : EScan::Final); - } else { - scan = (Flushing >= MaxFlight ? EScan::Sleep : EScan::Feed); - } - - Spent->Alter(scan != EScan::Sleep); - - return scan; - } - + + EScan scan = EScan::Sleep; + + if (last) { + scan = (Flushing > 0 ? EScan::Sleep : EScan::Final); + } else { + scan = (Flushing >= MaxFlight ? EScan::Sleep : EScan::Feed); + } + + Spent->Alter(scan != EScan::Sleep); + + return scan; + } + void Inbox(TEventHandlePtr &eh, const ::NActors::TActorContext&) - { + { if (auto *ev = eh->CastAsLocal<TEvPutResult>()) { - Handle(*ev); - } else if (eh->CastAsLocal<TEvents::TEvUndelivered>()) { - if (auto logl = Logger->Log(ELnLev::Error)) { - logl - << NFmt::Do(*this) << " cannot send put event to BS"; - } - - if (!std::exchange(Failed, true)) - Driver->Touch(EScan::Final); - } else { - Y_FAIL("Compaction actor got an unexpected event"); - } - } - + Handle(*ev); + } else if (eh->CastAsLocal<TEvents::TEvUndelivered>()) { + if (auto logl = Logger->Log(ELnLev::Error)) { + logl + << NFmt::Do(*this) << " cannot send put event to BS"; + } + + if (!std::exchange(Failed, true)) + Driver->Touch(EScan::Final); + } else { + Y_FAIL("Compaction actor got an unexpected event"); + } + } + void Handle(TEvPutResult &msg) noexcept - { + { if (!NPageCollection::TGroupBlobsByCookie::IsInPlane(msg.Id, Mask)) { - Y_FAIL("TEvPutResult Id mask is differ from used"); + Y_FAIL("TEvPutResult Id mask is differ from used"); } else if (Writing < msg.Id.BlobSize()) { Y_FAIL("Compaction writing bytes counter is out of sync"); - } else if (Flushing < msg.Id.BlobSize()) { - Y_FAIL("Compaction flushing bytes counter is out of sync"); - } - + } else if (Flushing < msg.Id.BlobSize()) { + Y_FAIL("Compaction flushing bytes counter is out of sync"); + } + Writing -= msg.Id.BlobSize(); - Flushing -= msg.Id.BlobSize(); - - + Flushing -= msg.Id.BlobSize(); + + if (msg.StatusFlags.Check(NKikimrBlobStorage::StatusDiskSpaceLightYellowMove)) { const ui32 channel = msg.Id.Channel(); Y_VERIFY_DEBUG(channel < 256); @@ -440,7 +440,7 @@ namespace NTabletFlatExecutor { YellowStopChannels.push_back(channel); } } - + const auto ok = (msg.Status == NKikimrProto::OK); if (auto logl = Logger->Log(ok ? ELnLev::Debug: ELnLev::Error)) { @@ -452,9 +452,9 @@ namespace NTabletFlatExecutor { << " left " << Flushing << "b"; } - if (ok) { + if (ok) { Send(Owner, new NBlockIO::TEvStat(NBlockIO::EDir::Write, NBlockIO::EPriority::Bulk, msg.GroupId, msg.Id)); - + while (!WriteQueue.empty() && Writing < MaxFlight) { SendToBs(std::move(WriteQueue.front())); WriteQueue.pop_front(); @@ -462,23 +462,23 @@ namespace NTabletFlatExecutor { Y_VERIFY_DEBUG(Flushing == 0 || Writing > 0, "Unexpected: Flushing > 0 and Writing == 0"); - if (Flushing == 0) { - Spent->Alter(true /* resource available again */); + if (Flushing == 0) { + Spent->Alter(true /* resource available again */); Driver->Touch(Finished ? EScan::Final : EScan::Feed); - } - } else if (!std::exchange(Failed, true)) { - Driver->Touch(EScan::Final); - } - } - + } + } else if (!std::exchange(Failed, true)) { + Driver->Touch(EScan::Final); + } + } + void FlushToBs(NPageCollection::TGlob&& glob) noexcept - { + { Y_VERIFY(glob.GId.Logo.BlobSize() == glob.Data.size(), "Written LogoBlob size doesn't match id"); - + Flushing += glob.GId.Logo.BlobSize(); - Blobs++; - + Blobs++; + if (Writing < MaxFlight && WriteQueue.empty()) { SendToBs(std::move(glob)); } else { @@ -494,26 +494,26 @@ namespace NTabletFlatExecutor { Writing += id.Logo.BlobSize(); Y_VERIFY_DEBUG(Writing <= Flushing, "Unexpected: Writing > Flushing"); - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << NFmt::Do(*this) + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << NFmt::Do(*this) << " saving " << id.Logo.ToString() - << " left " << Flushing << "b"; - } - - auto flag = NKikimrBlobStorage::AsyncBlob; + << " left " << Flushing << "b"; + } + + auto flag = NKikimrBlobStorage::AsyncBlob; auto *ev = new TEvPut(id.Logo, std::exchange(glob.Data, TString{ }), TInstant::Max(), flag, TEvBlobStorage::TEvPut::ETactic::TacticMaxThroughput); - auto ctx = TActivationContext::ActorContextFor(SelfId()); - + auto ctx = TActivationContext::ActorContextFor(SelfId()); + SendToBSProxy(ctx, id.Group, ev); - } - - private: - const TLogoBlobID Mask; + } + + private: + const TLogoBlobID Mask; const TActorId Owner; TAutoPtr<NUtil::ILogger> Logger; - IDriver * Driver = nullptr; + IDriver * Driver = nullptr; THolder<TCompactCfg> Conf; TIntrusiveConstPtr<TScheme> Scheme; TAutoPtr<TBundle> Bundle; @@ -521,12 +521,12 @@ namespace NTabletFlatExecutor { NTable::TWritten Stat; TVector<TBundle::TResult> Results; TVector<TIntrusiveConstPtr<NTable::TTxStatusPart>> TxStatus; - const NScheme::TTypeRegistry * Registry = nullptr; - + const NScheme::TTypeRegistry * Registry = nullptr; + bool Finished = false; - bool Failed = false;/* Failed to write blobs */ + bool Failed = false;/* Failed to write blobs */ TAutoPtr<TSpent> Spent; /* Blockage on write stats */ - ui64 Blobs = 0; /* Blobs produced by writer */ + ui64 Blobs = 0; /* Blobs produced by writer */ ui64 Writing = 0; /* Bytes flying to storage */ ui64 Flushing = 0; /* Bytes flushing to storage */ @@ -538,6 +538,6 @@ namespace NTabletFlatExecutor { THashMap<ui64, TRow> Deltas; TSmallVec<ui64> DeltasOrder; - }; -} -} + }; +} +} diff --git a/ydb/core/tablet_flat/flat_page_base.h b/ydb/core/tablet_flat/flat_page_base.h index 8ec91c0956..1d7bc8dc98 100644 --- a/ydb/core/tablet_flat/flat_page_base.h +++ b/ydb/core/tablet_flat/flat_page_base.h @@ -1,59 +1,59 @@ -#pragma once - -#include <util/generic/ptr.h> -#include <iterator> -#include "flat_update_op.h" -#include "flat_part_scheme.h" -#include "flat_row_nulls.h" +#pragma once + +#include <util/generic/ptr.h> +#include <iterator> +#include "flat_update_op.h" +#include "flat_part_scheme.h" +#include "flat_row_nulls.h" #include "util_deref.h" - -namespace NKikimr { -namespace NTable { -namespace NPage { - -using TRecIdx = ui32; // context: page - -template <class T> struct TPgSizeOf { static constexpr TPgSize Value = sizeof(T); }; -struct TEmpty { }; -template <> struct TPgSizeOf<TEmpty> { static constexpr TPgSize Value = 0; }; - -template <class T> -inline void* NextPtr(T* t) { - return (char*)t + TPgSizeOf<T>::Value; -} - -template <class T> -inline const void* NextPtr(const T* t) { - return (const char*)t + TPgSizeOf<T>::Value; -} - - -template <typename TPage, typename TRecord> -class TPageIterator { -public: - typedef std::random_access_iterator_tag iterator_category; - typedef std::ptrdiff_t difference_type; - typedef TRecord value_type; - typedef TRecord const* pointer; - typedef TRecord const& reference; - - using TIterator = TPageIterator<TPage, TRecord>; - - TPageIterator() = default; - - TPageIterator(const TPage* page, TRecIdx on, TRecIdx end) - : Page(page) - , Upper(end) - , Offset(Min(on, end)) - { - Sync(); - } - - TRecIdx Off() const noexcept - { - return Offset; - } - + +namespace NKikimr { +namespace NTable { +namespace NPage { + +using TRecIdx = ui32; // context: page + +template <class T> struct TPgSizeOf { static constexpr TPgSize Value = sizeof(T); }; +struct TEmpty { }; +template <> struct TPgSizeOf<TEmpty> { static constexpr TPgSize Value = 0; }; + +template <class T> +inline void* NextPtr(T* t) { + return (char*)t + TPgSizeOf<T>::Value; +} + +template <class T> +inline const void* NextPtr(const T* t) { + return (const char*)t + TPgSizeOf<T>::Value; +} + + +template <typename TPage, typename TRecord> +class TPageIterator { +public: + typedef std::random_access_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + typedef TRecord value_type; + typedef TRecord const* pointer; + typedef TRecord const& reference; + + using TIterator = TPageIterator<TPage, TRecord>; + + TPageIterator() = default; + + TPageIterator(const TPage* page, TRecIdx on, TRecIdx end) + : Page(page) + , Upper(end) + , Offset(Min(on, end)) + { + Sync(); + } + + TRecIdx Off() const noexcept + { + return Offset; + } + TRecIdx End() const noexcept { return Upper; @@ -64,14 +64,14 @@ public: return Record; } - bool operator==(const TIterator& o) const { - return Offset == o.Offset; - } - - bool operator!=(const TIterator& o) const { - return Offset != o.Offset; - } - + bool operator==(const TIterator& o) const { + return Offset == o.Offset; + } + + bool operator!=(const TIterator& o) const { + return Offset != o.Offset; + } + bool operator<(const TIterator& rhs) const { return Offset < rhs.Offset; } @@ -88,22 +88,22 @@ public: return Offset > rhs.Offset; } - reference operator*() const { - return *Record; - } - - pointer operator->() const { - return Record; - } - - TIterator& operator++() { - return *this += 1; - } - - TIterator& operator--() { - return *this -= 1; - } - + reference operator*() const { + return *Record; + } + + pointer operator->() const { + return Record; + } + + TIterator& operator++() { + return *this += 1; + } + + TIterator& operator--() { + return *this -= 1; + } + TIterator operator++(int) { TIterator copy(*this); *this += 1; @@ -116,124 +116,124 @@ public: return copy; } - TIterator& operator+=(size_t n) { - Offset += Min(TRecIdx(n), Upper - Offset); - Sync(); - return *this; - } - - TIterator& operator-=(size_t n) { - Offset -= Min(TRecIdx(n), Offset); - Sync(); - return *this; - } - - TIterator operator+(size_t n) const { - TIterator ret(*this); - return ret += n; - } - - TIterator operator-(size_t n) const { - TIterator ret(*this); - return ret -= n; - } - - difference_type operator-(const TIterator& rhs) const { - return (difference_type)Offset - (difference_type)rhs.Offset; - } - - explicit operator bool() const noexcept { - return Offset < Upper; - } - -private: - void Sync() { - Record = *this ? Page->Record(Offset) : nullptr; - } - -private: - const TPage * Page = nullptr; - pointer Record = nullptr; - TRecIdx Upper = 0; - TRecIdx Offset = 0; -}; - -#pragma pack(push,1) - -struct TDataRef { - TPgSize Offset; - TPgSize Size; + TIterator& operator+=(size_t n) { + Offset += Min(TRecIdx(n), Upper - Offset); + Sync(); + return *this; + } + + TIterator& operator-=(size_t n) { + Offset -= Min(TRecIdx(n), Offset); + Sync(); + return *this; + } + + TIterator operator+(size_t n) const { + TIterator ret(*this); + return ret += n; + } + + TIterator operator-(size_t n) const { + TIterator ret(*this); + return ret -= n; + } + + difference_type operator-(const TIterator& rhs) const { + return (difference_type)Offset - (difference_type)rhs.Offset; + } + + explicit operator bool() const noexcept { + return Offset < Upper; + } + +private: + void Sync() { + Record = *this ? Page->Record(Offset) : nullptr; + } + +private: + const TPage * Page = nullptr; + pointer Record = nullptr; + TRecIdx Upper = 0; + TRecIdx Offset = 0; +}; + +#pragma pack(push,1) + +struct TDataRef { + TPgSize Offset; + TPgSize Size; } Y_PACKED; - -struct TRecordsHeader { - TRecIdx Records; + +struct TRecordsHeader { + TRecIdx Records; } Y_PACKED; - + struct TRecordsEntry { TPgSize Offset; } Y_PACKED; - -template <class TRecord, class TItem> + +template <class TRecord, class TItem> struct TDataPageRecord { - void* Base() { - return NextPtr((TRecord*)this); - } - - const void* Base() const { - return NextPtr((const TRecord*)this); - } - - TItem* GetItem(const TPartScheme::TColumn& info) { + void* Base() { + return NextPtr((TRecord*)this); + } + + const void* Base() const { + return NextPtr((const TRecord*)this); + } + + TItem* GetItem(const TPartScheme::TColumn& info) { return TDeref<TItem>::At(Base(), info.Offset); - } - - const TItem* GetItem(const TPartScheme::TColumn& info) const { + } + + const TItem* GetItem(const TPartScheme::TColumn& info) const { return TDeref<TItem>::At(Base(), info.Offset); - } - - template <class T> + } + + template <class T> const T* GetTail(const TPartScheme::TGroupInfo& group) const { return TDeref<T>::At(Base(), group.FixedSize); } template <class T> - T* GetFixed(TItem* item) const { - return reinterpret_cast<T*>(NextPtr(item)); - } - - template <class T> - const T* GetFixed(const TItem* item) const { - return reinterpret_cast<const T*>(NextPtr(item)); - } - + T* GetFixed(TItem* item) const { + return reinterpret_cast<T*>(NextPtr(item)); + } + + template <class T> + const T* GetFixed(const TItem* item) const { + return reinterpret_cast<const T*>(NextPtr(item)); + } + TCellOp GetOp(const TPartScheme::TColumn &info) const - { - return GetItem(info)->GetOp(info.IsKey()); - } - - TCell Cell(const TPartScheme::TColumn& info) const - { - const TItem* item = GetItem(info); - const auto op = item->GetOp(info.IsKey()); - + { + return GetItem(info)->GetOp(info.IsKey()); + } + + TCell Cell(const TPartScheme::TColumn& info) const + { + const TItem* item = GetItem(info); + const auto op = item->GetOp(info.IsKey()); + if (op == ECellOp::Empty || op == ECellOp::Null || op == ECellOp::Reset) { - return { }; - } else if (info.IsFixed) { - return { GetFixed<const char>(item), info.FixedSize }; + return { }; + } else if (info.IsFixed) { + return { GetFixed<const char>(item), info.FixedSize }; } else if (op == ELargeObj::Inline) { - auto *ref = GetFixed<TDataRef>(item); - + auto *ref = GetFixed<TDataRef>(item); + return { TDeref<const char>::At(Base(), ref->Offset), ref->Size }; } else { /* ELargeObj::Extern or other link to attached blob */ - return { GetFixed<const char>(item), sizeof(ui64) }; - - static_assert(sizeof(TDataRef) == sizeof(ui64), ""); - } - } + return { GetFixed<const char>(item), sizeof(ui64) }; + + static_assert(sizeof(TDataRef) == sizeof(ui64), ""); + } + } } Y_PACKED; - -#pragma pack(pop) - + +#pragma pack(pop) + static_assert(sizeof(TDataRef) == 8, "Invalid TDataRef size"); static_assert(sizeof(TRecordsHeader) == 4, "Invalid TRecordsHeader size"); static_assert(sizeof(TRecordsEntry) == 4, "Invalid TRecordsEntry size"); @@ -263,47 +263,47 @@ struct TBlockWithRecords { ui32 Records = 0; }; -using TCells = TArrayRef<const TCell>; - -template <typename TRecord> -struct TCompare { - using TColumns = TArrayRef<const TPartScheme::TColumn>; - +using TCells = TArrayRef<const TCell>; + +template <typename TRecord> +struct TCompare { + using TColumns = TArrayRef<const TPartScheme::TColumn>; + TCompare(TColumns keys, const TKeyNulls &nulls) - : Info(keys) - , Nulls(nulls) - { + : Info(keys) + , Nulls(nulls) + { Y_VERIFY(Nulls->size() >= Info.size()); - } - - bool operator()(const TRecord &record, TCells key) const noexcept - { - return Compare(record, key) < 0; - } - - bool operator()(TCells key, const TRecord &record) const noexcept - { - return Compare(record, key) > 0; - } - - int Compare(const TRecord &rec, const TCells key) const noexcept - { + } + + bool operator()(const TRecord &record, TCells key) const noexcept + { + return Compare(record, key) < 0; + } + + bool operator()(TCells key, const TRecord &record) const noexcept + { + return Compare(record, key) > 0; + } + + int Compare(const TRecord &rec, const TCells key) const noexcept + { for (TPos it = 0; it < Min(key.size(), Nulls->size()); it++) { const TCell left = it < Info.size() ? rec.Cell(Info[it]) : Nulls[it]; - - if (int cmp = CompareTypedCells(left, key[it], Nulls.Types[it])) - return cmp; - } - + + if (int cmp = CompareTypedCells(left, key[it], Nulls.Types[it])) + return cmp; + } + return key.size() < Nulls->size() ? -1 : 0; - } - -private: - const TColumns Info; + } + +private: + const TColumns Info; const TKeyNulls &Nulls; -}; - - -} -} -} +}; + + +} +} +} diff --git a/ydb/core/tablet_flat/flat_page_blobs.h b/ydb/core/tablet_flat/flat_page_blobs.h index c5fdb7571e..d10823ed87 100644 --- a/ydb/core/tablet_flat/flat_page_blobs.h +++ b/ydb/core/tablet_flat/flat_page_blobs.h @@ -1,118 +1,118 @@ -#pragma once - -#include "flat_page_label.h" -#include "flat_sausage_gut.h" -#include "flat_sausage_solid.h" +#pragma once + +#include "flat_page_label.h" +#include "flat_sausage_gut.h" +#include "flat_sausage_solid.h" #include "util_deref.h" -#include <array> - -namespace NKikimr { -namespace NTable { -namespace NPage { - +#include <array> + +namespace NKikimr { +namespace NTable { +namespace NPage { + class TExtBlobs : public NPageCollection::IPageCollection { - public: + public: using TEntry = NPageCollection::TGlobId; - - struct THeader { - ui32 Skip = 0; /* Skip bytes from header to frames */ - ui32 Pad0_ = 0; - ui64 Pad1_ = 0; - ui64 Pad2_ = 0; - ui64 Bytes = 0; /* Total blob bytes referenced here */ - ui64 Pad3_ = 0; - }; - - struct TStats { - ui32 Items; - ui64 Bytes; - }; - + + struct THeader { + ui32 Skip = 0; /* Skip bytes from header to frames */ + ui32 Pad0_ = 0; + ui64 Pad1_ = 0; + ui64 Pad2_ = 0; + ui64 Bytes = 0; /* Total blob bytes referenced here */ + ui64 Pad3_ = 0; + }; + + struct TStats { + ui32 Items; + ui64 Bytes; + }; + static_assert(sizeof(TEntry) == 32, "Invalid TExtBlobs entry unit"); static_assert(sizeof(THeader) == 40, "Invalid TExtBlobs header unit"); - + TExtBlobs(TSharedData raw, const TLogoBlobID &label) - : Raw(std::move(raw)) - , Label_(label) - { + : Raw(std::move(raw)) + , Label_(label) + { Y_VERIFY(uintptr_t(Raw.data()) % alignof(TEntry) == 0); - - auto got = NPage::THello().Read(Raw, EPage::Globs); - - Y_VERIFY(got == ECodec::Plain && got.Version == 1); - + + auto got = NPage::THello().Read(Raw, EPage::Globs); + + Y_VERIFY(got == ECodec::Plain && got.Version == 1); + Header = TDeref<THeader>::At(got.Page.data(), 0); - - if (Header->Skip > got.Page.size()) + + if (Header->Skip > got.Page.size()) Y_FAIL("NPage::TExtBlobs header is out of its blob"); - + auto *ptr = TDeref<TEntry>::At(got.Page.data(), Header->Skip); - - Array = { ptr, (got.Page.size() - Header->Skip) / sizeof(TEntry) }; - } - - TStats Stats() const noexcept - { - return { ui32(Array.size()), Header->Bytes }; - } - - TArrayRef<const TEntry> operator*() const noexcept - { - return Array; - } - + + Array = { ptr, (got.Page.size() - Header->Skip) / sizeof(TEntry) }; + } + + TStats Stats() const noexcept + { + return { ui32(Array.size()), Header->Bytes }; + } + + TArrayRef<const TEntry> operator*() const noexcept + { + return Array; + } + const TArrayRef<const TEntry>* operator->() const noexcept { return &Array; } - const TLogoBlobID& Label() const noexcept override - { - return Label_; - } - - ui32 Total() const noexcept override - { - return Array.size(); - } - + const TLogoBlobID& Label() const noexcept override + { + return Label_; + } + + ui32 Total() const noexcept override + { + return Array.size(); + } + NPageCollection::TInfo Page(ui32 page) const noexcept override - { - return { Glob(page).Logo.BlobSize(), ui32(EPage::Opaque) }; - } - + { + return { Glob(page).Logo.BlobSize(), ui32(EPage::Opaque) }; + } + NPageCollection::TBorder Bounds(ui32 page) const noexcept override - { - const auto size = Glob(page).Logo.BlobSize(); - - return { size, { page, 0 }, { page, size } }; - } - + { + const auto size = Glob(page).Logo.BlobSize(); + + return { size, { page, 0 }, { page, size } }; + } + NPageCollection::TGlobId Glob(ui32 page) const noexcept override - { - return page < Array.size() ? Array[page] : Empty; - } - + { + return page < Array.size() ? Array[page] : Empty; + } + bool Verify(ui32 page, TArrayRef<const char> data) const noexcept override - { - return data && data.size() == Array.at(page).Bytes(); - } - + { + return data && data.size() == Array.at(page).Bytes(); + } + size_t BackingSize() const noexcept override { return Raw.size(); } - public: + public: const TSharedData Raw; - - private: - const TLogoBlobID Label_; - const TEntry Empty; - const THeader * Header = nullptr; - TArrayRef<const TEntry> Array; - }; - -} -} -} + + private: + const TLogoBlobID Label_; + const TEntry Empty; + const THeader * Header = nullptr; + TArrayRef<const TEntry> Array; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_page_bloom.h b/ydb/core/tablet_flat/flat_page_bloom.h index 1244d0e2ea..bae4fb6d90 100644 --- a/ydb/core/tablet_flat/flat_page_bloom.h +++ b/ydb/core/tablet_flat/flat_page_bloom.h @@ -1,86 +1,86 @@ -#pragma once - -#include "flat_page_label.h" -#include "flat_bloom_hash.h" +#pragma once + +#include "flat_page_label.h" +#include "flat_bloom_hash.h" #include "util_deref.h" - -namespace NKikimr { -namespace NTable { -namespace NPage { - - struct TBloom : public virtual TThrRefBase { - public: - struct THeader { - ui16 Type = 0; - ui16 Hashes = 0; - ui32 Pad0_ = 0; - ui64 Items = 0; - }; - - struct TStats { - ui32 Items; - ui32 Hashes; - }; - - static_assert(sizeof(THeader) == 16, "Invalid TBloom page header"); - + +namespace NKikimr { +namespace NTable { +namespace NPage { + + struct TBloom : public virtual TThrRefBase { + public: + struct THeader { + ui16 Type = 0; + ui16 Hashes = 0; + ui32 Pad0_ = 0; + ui64 Items = 0; + }; + + struct TStats { + ui32 Items; + ui32 Hashes; + }; + + static_assert(sizeof(THeader) == 16, "Invalid TBloom page header"); + TBloom(TSharedData page) - : Raw(std::move(page)) - { - const auto got = NPage::THello().Read(Raw, EPage::Bloom); - - Y_VERIFY(got == ECodec::Plain && got.Version == 0); - + : Raw(std::move(page)) + { + const auto got = NPage::THello().Read(Raw, EPage::Bloom); + + Y_VERIFY(got == ECodec::Plain && got.Version == 0); + auto *header = TDeref<THeader>::At(got.Page.data(), 0); - - if (sizeof(THeader) > got.Page.size()) - Y_FAIL("NPage::TBloom header is out of its blob"); - + + if (sizeof(THeader) > got.Page.size()) + Y_FAIL("NPage::TBloom header is out of its blob"); + auto *ptr = TDeref<ui64>::At(got.Page.data(), sizeof(THeader)); - - Hashes = header->Hashes; - Items = header->Items; + + Hashes = header->Hashes; + Items = header->Items; Array = { ptr, (got.Page.size() - sizeof(THeader)) / sizeof(ui64) }; - - if (Items == 0) { - Y_FAIL("NPage::TBloom page has zero items in index"); - } else if (Hashes == 0) { - Y_FAIL("NPage::TBloom page has zero hash count"); + + if (Items == 0) { + Y_FAIL("NPage::TBloom page has zero items in index"); + } else if (Hashes == 0) { + Y_FAIL("NPage::TBloom page has zero hash count"); } else if (ui64(Array.size()) << 6 != header->Items) { - Y_FAIL("Items in TBloom header isn't match with array"); - } else if (header->Type != 0) { - Y_FAIL("NPage::TBloom page made with unknown hash type"); - } - } - - TStats Stats() const noexcept - { - return { Items, Hashes }; - } - - bool MightHave(TArrayRef<const char> raw) const noexcept - { - NBloom::THash hash(raw); - - for (ui32 seq = 0; seq++ < Hashes; ) { - const ui64 num = hash.Next() % Items; - - if (!(Array[num >> 6] & (ui64(1) << (num & 0x3f)))) - return false; - } - - return true; - } - - public: + Y_FAIL("Items in TBloom header isn't match with array"); + } else if (header->Type != 0) { + Y_FAIL("NPage::TBloom page made with unknown hash type"); + } + } + + TStats Stats() const noexcept + { + return { Items, Hashes }; + } + + bool MightHave(TArrayRef<const char> raw) const noexcept + { + NBloom::THash hash(raw); + + for (ui32 seq = 0; seq++ < Hashes; ) { + const ui64 num = hash.Next() % Items; + + if (!(Array[num >> 6] & (ui64(1) << (num & 0x3f)))) + return false; + } + + return true; + } + + public: const TSharedData Raw; - - private: - TArrayRef<const ui64> Array; - ui32 Hashes = 0; - ui32 Items = 0; - }; - -} -} -} + + private: + TArrayRef<const ui64> Array; + ui32 Hashes = 0; + ui32 Items = 0; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_page_conf.h b/ydb/core/tablet_flat/flat_page_conf.h index 32255732ea..ba4617ca46 100644 --- a/ydb/core/tablet_flat/flat_page_conf.h +++ b/ydb/core/tablet_flat/flat_page_conf.h @@ -1,16 +1,16 @@ -#pragma once - -#include "flat_page_iface.h" +#pragma once + +#include "flat_page_iface.h" #include "flat_row_eggs.h" - + #include <ydb/core/scheme/scheme_tablecell.h> #include <util/generic/ylimits.h> -namespace NKikimr { -namespace NTable { -namespace NPage { - +namespace NKikimr { +namespace NTable { +namespace NPage { + /** * Used for checking if keys belong to a key space */ @@ -64,25 +64,25 @@ namespace NPage { ui32 IndexMin = 32 * 1024; /* Index initial buffer size */ }; - struct TConf { + struct TConf { TConf() { // There should always be at least 1 group Groups.emplace_back(); } - - TConf(bool fin, ui32 page, ui32 large = Max<ui32>()) - : Final(fin) - , LargeEdge(large) + + TConf(bool fin, ui32 page, ui32 large = Max<ui32>()) + : Final(fin) + , LargeEdge(large) { Group(0).PageSize = page; } - - bool Final = true; + + bool Final = true; ui32 MaxLargeBlob = 8 * 1024 * 1024 - 8; /* Maximum large blob size */ - ui32 LargeEdge = Max<ui32>(); /* External blob edge size */ - ui32 SmallEdge = Max<ui32>(); /* Outer blobs edge bytes limit */ - bool ByKeyFilter = false; /* Per-part bloom filter */ - ui64 MaxRows = 0; /* Used to set up bloom filter size */ + ui32 LargeEdge = Max<ui32>(); /* External blob edge size */ + ui32 SmallEdge = Max<ui32>(); /* Outer blobs edge bytes limit */ + bool ByKeyFilter = false; /* Per-part bloom filter */ + ui64 MaxRows = 0; /* Used to set up bloom filter size */ ui64 SliceSize = Max<ui64>(); /* Data size for slice creation */ ui64 MainPageCollectionEdge = Max<ui64>(); ui64 SmallPageCollectionEdge = Max<ui64>(); @@ -98,8 +98,8 @@ namespace NPage { } return Groups[index]; } - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_page_data.h b/ydb/core/tablet_flat/flat_page_data.h index aab03c724d..75f976cfc7 100644 --- a/ydb/core/tablet_flat/flat_page_data.h +++ b/ydb/core/tablet_flat/flat_page_data.h @@ -1,53 +1,53 @@ -#pragma once - -#include "flat_page_base.h" -#include "flat_page_label.h" -#include "flat_row_nulls.h" +#pragma once + +#include "flat_page_base.h" +#include "flat_page_label.h" +#include "flat_row_nulls.h" #include "util_basics.h" #include "util_deref.h" - + #include <ydb/core/base/shared_data.h> #include <library/cpp/blockcodecs/codecs.h> -#include <util/generic/buffer.h> - -namespace NKikimr { -namespace NTable { -namespace NPage { - - +#include <util/generic/buffer.h> + +namespace NKikimr { +namespace NTable { +namespace NPage { + + struct TDataPage { - - /* - TRecord binary layout v1 - .-------------------------. + + /* + TRecord binary layout v1 + .-------------------------. | ERowOp | header - .---------.---------------. -. - | cell op | value OR offs | cell_1 | - .---------.---------------. | - | . . . | | fixed-size - .---------.---------------. | - | cell op | value OR offs | cell_K | - .-.------.'-.-------.-----. -' - | | | | | | var-size values - '-'------'--'-------'-----' - */ - -#pragma pack(push,1) - - struct TItem { + .---------.---------------. -. + | cell op | value OR offs | cell_1 | + .---------.---------------. | + | . . . | | fixed-size + .---------.---------------. | + | cell op | value OR offs | cell_K | + .-.------.'-.-------.-----. -' + | | | | | | var-size values + '-'------'--'-------'-----' + */ + +#pragma pack(push,1) + + struct TItem { TCellOp GetOp(bool key) const noexcept - { - return + { + return key ? TCellOp(Null ? ECellOp::Null : ECellOp::Set) : TCellOp::By(Flg); - } - - union { - bool Null; - ui8 Flg; - }; + } + + union { + bool Null; + ui8 Flg; + }; } Y_PACKED; - + struct TVersion { ui64 Step_; ui64 TxId_; @@ -142,95 +142,95 @@ namespace NPage { } } } Y_PACKED; - - struct TExtra { - TRowId BaseRow; + + struct TExtra { + TRowId BaseRow; } Y_PACKED; - -#pragma pack(pop) - + +#pragma pack(pop) + static_assert(sizeof(TItem) == 1, "Invalid TDataPage TItem size"); static_assert(sizeof(TVersion) == 16, "Invalid TDataPage TVersion size"); static_assert(sizeof(TRecord) == 1, "Invalid TDataPage TRecord size"); static_assert(sizeof(TExtra) == 8, "Invalid TDataPage page extra chunk"); - - using TBlock = TBlockWithRecords<TRecord>; - - public: - using TIter = TBlock::TIterator; - + + using TBlock = TBlockWithRecords<TRecord>; + + public: + using TIter = TBlock::TIterator; + TDataPage(const TSharedData *raw = nullptr) noexcept - { - Set(raw); - } - - const auto* Label() const noexcept - { + { + Set(raw); + } + + const auto* Label() const noexcept + { return TDeref<const NPage::TLabel>::At(Raw.data()); - } - - explicit operator bool() const noexcept - { - return bool(Raw); - } - - const TBlock* operator->() const noexcept - { - return &Page; - } - - TRowId BaseRow() const noexcept - { - return Raw ? BaseRow_ : Max<TRowId>(); - } - + } + + explicit operator bool() const noexcept + { + return bool(Raw); + } + + const TBlock* operator->() const noexcept + { + return &Page; + } + + TRowId BaseRow() const noexcept + { + return Raw ? BaseRow_ : Max<TRowId>(); + } + TDataPage& Set(const TSharedData *raw = nullptr) noexcept - { - Page = { }; - + { + Page = { }; + if (Raw = raw ? *raw : TSharedData{ }) { const void* base = Raw.data(); auto got = NPage::THello().Read(Raw, EPage::DataPage); - + Y_VERIFY(got.Version == 1, "Unknown EPage::DataPage version"); - - if (got.Codec != ECodec::Plain) { - /* Compressed, should convert to regular page */ - - Y_VERIFY(got == ECodec::LZ4, "Only LZ4 encoding allowed"); - - Codec = Codec ? Codec : NBlockCodecs::Codec("lz4fast"); - auto size = Codec->DecompressedLength(got.Page); - + + if (got.Codec != ECodec::Plain) { + /* Compressed, should convert to regular page */ + + Y_VERIFY(got == ECodec::LZ4, "Only LZ4 encoding allowed"); + + Codec = Codec ? Codec : NBlockCodecs::Codec("lz4fast"); + auto size = Codec->DecompressedLength(got.Page); + // We expect original page had the same label size as a compressed page size_t labelSize = reinterpret_cast<const char*>(got.Page.data()) - reinterpret_cast<const char*>(base); - + Decoded.Resize(labelSize + size); - + size = Codec->Decompress(got.Page, Decoded.Begin() + labelSize); - + Decoded.Resize(labelSize + size); ::memset(Decoded.Begin(), 0, labelSize); base = Decoded.Begin(); got.Page = { Decoded.Begin() + labelSize, Decoded.End() }; - } - + } + auto *hdr = TDeref<TRecordsHeader>::At(got.Page.data(), 0); auto skip = got.Page.size() - hdr->Records * sizeof(TPgSize); - + BaseRow_ = TDeref<const TExtra>::At(hdr + 1, 0)->BaseRow; Page.Base = base; Page.Array = TDeref<const TRecordsEntry>::At(hdr, skip); - Page.Records = hdr->Records; - } - - return *this; - } - + Page.Records = hdr->Records; + } + + return *this; + } + TIter LookupKey(TCells key, const TPartScheme::TGroupInfo &group, ESeek seek, const TKeyNulls *nulls) const noexcept - { + { if (!key) { switch (seek) { case ESeek::Lower: @@ -240,9 +240,9 @@ namespace NPage { return Page.End(); } } - + TIter it; - + const auto cmp = TCompare<TRecord>(group.ColsKeyData, *nulls); switch (seek) { case ESeek::Exact: @@ -255,16 +255,16 @@ namespace NPage { case ESeek::Lower: { it = std::lower_bound(Page.Begin(), Page.End(), key, cmp); break; - } + } case ESeek::Upper: { it = std::upper_bound(Page.Begin(), Page.End(), key, cmp); break; } - } - + } + return it; - } - + } + TIter LookupKeyReverse(TCells key, const TPartScheme::TGroupInfo &group, ESeek seek, const TKeyNulls *nulls) const noexcept { @@ -306,15 +306,15 @@ namespace NPage { return it; } - private: - using ICodec = NBlockCodecs::ICodec; - - TBuffer Decoded; + private: + using ICodec = NBlockCodecs::ICodec; + + TBuffer Decoded; TSharedData Raw; - TBlock Page; - TRowId BaseRow_ = Max<TRowId>(); - const ICodec *Codec = nullptr; - }; -} -} -} + TBlock Page; + TRowId BaseRow_ = Max<TRowId>(); + const ICodec *Codec = nullptr; + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_page_frames.h b/ydb/core/tablet_flat/flat_page_frames.h index 0edcc1eacc..cbcab7b864 100644 --- a/ydb/core/tablet_flat/flat_page_frames.h +++ b/ydb/core/tablet_flat/flat_page_frames.h @@ -1,142 +1,142 @@ -#pragma once - -#include "flat_row_eggs.h" -#include "flat_page_label.h" +#pragma once + +#include "flat_row_eggs.h" +#include "flat_page_label.h" #include "util_deref.h" -#include <algorithm> - -namespace NKikimr { -namespace NTable { -namespace NPage { - - class TFrames : public TAtomicRefCount<TFrames> { - public: - /* Frames index describes how a set of materialized entities relates - to a set of rows and its columns. Usually this index is used for - relation revealing between external blobs and rows in caches. - - * For the first entity in a frame Rerfer sets relative offset to - the next frame with negative frame length. Inner entities has - positive offsets relative to the frame head. Thus, Refer - cannot be equal to zero. - - * Tag just points to physical number of column where entity is - reffered to. It is required for tag values to be dense along - of entrire index as they could be used in basic bitmaps for - speeding filtering. Tag have to be less than (Max<i16>() + 1). - */ - - struct TEntry { - explicit operator bool() const noexcept - { - return Refer != 0 && Row != Max<ui64>(); - } - - bool IsHead() const noexcept - { - return Refer < 0; - } - - ui32 AbsRef(const ui32 page) const noexcept - { - Y_VERIFY(Refer < 0 || page >= ui32(Refer)); - - return page - Refer; - } - - ui64 Row; /* TRowId, the same along the same frame */ - ui16 Tag; - i16 Refer; /* Negative values sets frame size on head */ - ui32 Size; - }; - - struct TStats { - ui32 Items = 0; /* Total records in this index */ - ui32 Rows = 0; /* Total unique frames in relations */ - ui64 Size = 0; /* Sum of all TEntry::Size fields */ - TArrayRef<const ui32> Tags; /* Tags frequency stats */ - }; - - struct THeader { - ui32 Skip = 0; /* Skip bytes from header to frames */ - ui32 Rows = 0; - ui64 Size = 0; - ui32 Pad0_ = 0; - ui32 Tags = 0; - }; - - static_assert(sizeof(TEntry) == 16, "Invalid TFrames record unit"); - static_assert(sizeof(THeader) == 24, "Invalid TFrames header unit"); - +#include <algorithm> + +namespace NKikimr { +namespace NTable { +namespace NPage { + + class TFrames : public TAtomicRefCount<TFrames> { + public: + /* Frames index describes how a set of materialized entities relates + to a set of rows and its columns. Usually this index is used for + relation revealing between external blobs and rows in caches. + + * For the first entity in a frame Rerfer sets relative offset to + the next frame with negative frame length. Inner entities has + positive offsets relative to the frame head. Thus, Refer + cannot be equal to zero. + + * Tag just points to physical number of column where entity is + reffered to. It is required for tag values to be dense along + of entrire index as they could be used in basic bitmaps for + speeding filtering. Tag have to be less than (Max<i16>() + 1). + */ + + struct TEntry { + explicit operator bool() const noexcept + { + return Refer != 0 && Row != Max<ui64>(); + } + + bool IsHead() const noexcept + { + return Refer < 0; + } + + ui32 AbsRef(const ui32 page) const noexcept + { + Y_VERIFY(Refer < 0 || page >= ui32(Refer)); + + return page - Refer; + } + + ui64 Row; /* TRowId, the same along the same frame */ + ui16 Tag; + i16 Refer; /* Negative values sets frame size on head */ + ui32 Size; + }; + + struct TStats { + ui32 Items = 0; /* Total records in this index */ + ui32 Rows = 0; /* Total unique frames in relations */ + ui64 Size = 0; /* Sum of all TEntry::Size fields */ + TArrayRef<const ui32> Tags; /* Tags frequency stats */ + }; + + struct THeader { + ui32 Skip = 0; /* Skip bytes from header to frames */ + ui32 Rows = 0; + ui64 Size = 0; + ui32 Pad0_ = 0; + ui32 Tags = 0; + }; + + static_assert(sizeof(TEntry) == 16, "Invalid TFrames record unit"); + static_assert(sizeof(THeader) == 24, "Invalid TFrames header unit"); + TFrames(TSharedData raw) - : Raw(std::move(raw)) - , End({ Max<TRowId>(), Max<ui16>(), 0, 0 }) - { + : Raw(std::move(raw)) + , End({ Max<TRowId>(), Max<ui16>(), 0, 0 }) + { Y_VERIFY(uintptr_t(Raw.data()) % alignof(TEntry) == 0); - - auto got = NPage::THello().Read(Raw, EPage::Frames); - - Y_VERIFY(got == ECodec::Plain && got.Version == 0); - Y_VERIFY(got.Page.size() > sizeof(THeader), "Damaged page"); - - auto * const ptr = got.Page.data(); + + auto got = NPage::THello().Read(Raw, EPage::Frames); + + Y_VERIFY(got == ECodec::Plain && got.Version == 0); + Y_VERIFY(got.Page.size() > sizeof(THeader), "Damaged page"); + + auto * const ptr = got.Page.data(); auto hdr = TDeref<THeader>::At(ptr, 0); - - if (hdr->Skip > got.Page.size()) - Y_FAIL("NPage::TFrame header is out of its blob"); - - Stats_.Rows = hdr->Rows; - Stats_.Size = hdr->Size; + + if (hdr->Skip > got.Page.size()) + Y_FAIL("NPage::TFrame header is out of its blob"); + + Stats_.Rows = hdr->Rows; + Stats_.Size = hdr->Size; Stats_.Tags = { TDeref<const ui32>::At(ptr, 24), hdr->Tags }; - Stats_.Items = (got.Page.size() - hdr->Skip) / sizeof(TEntry); - - if (hdr->Skip < sizeof(THeader) + Stats_.Tags.size() * sizeof(ui32)) - Y_FAIL("Invalid NPage::TFrame meta info blob header"); - + Stats_.Items = (got.Page.size() - hdr->Skip) / sizeof(TEntry); + + if (hdr->Skip < sizeof(THeader) + Stats_.Tags.size() * sizeof(ui32)) + Y_FAIL("Invalid NPage::TFrame meta info blob header"); + Records = { TDeref<TEntry>::At(ptr, hdr->Skip) , Stats_.Items }; - } - - const TStats& Stats() const noexcept - { - return Stats_; - } - - const TEntry& Relation(ui32 page) const noexcept - { - return page < +Records.size() ? Records[page] : End; - } - - ui32 Lower(ui64 row, ui32 begin, ui32 end) const noexcept - { - begin = Min(begin, Stats_.Items); - end = Min(end, Stats_.Items); - - for (int hope = 0; hope < 4 && begin < end;) { - auto &rel = Records[begin]; - - if (rel.Row >= row) return begin; - - hope += rel.IsHead(); - begin = rel.AbsRef(begin); - } - - auto on = Records.begin() + begin; - - on = std::lower_bound(on, Records.begin() + end, row, - [](const TEntry &left, ui64 row){ return left.Row < row; }); - - return std::distance(Records.begin(), on); - } - - public: + } + + const TStats& Stats() const noexcept + { + return Stats_; + } + + const TEntry& Relation(ui32 page) const noexcept + { + return page < +Records.size() ? Records[page] : End; + } + + ui32 Lower(ui64 row, ui32 begin, ui32 end) const noexcept + { + begin = Min(begin, Stats_.Items); + end = Min(end, Stats_.Items); + + for (int hope = 0; hope < 4 && begin < end;) { + auto &rel = Records[begin]; + + if (rel.Row >= row) return begin; + + hope += rel.IsHead(); + begin = rel.AbsRef(begin); + } + + auto on = Records.begin() + begin; + + on = std::lower_bound(on, Records.begin() + end, row, + [](const TEntry &left, ui64 row){ return left.Row < row; }); + + return std::distance(Records.begin(), on); + } + + public: const TSharedData Raw; - - private: - const TEntry End; - TStats Stats_; - TArrayRef<const TEntry> Records; - }; - -} -} -} + + private: + const TEntry End; + TStats Stats_; + TArrayRef<const TEntry> Records; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_page_iface.h b/ydb/core/tablet_flat/flat_page_iface.h index d1b2386040..41ad70badf 100644 --- a/ydb/core/tablet_flat/flat_page_iface.h +++ b/ydb/core/tablet_flat/flat_page_iface.h @@ -1,14 +1,14 @@ -#pragma once - -#include <util/system/types.h> - -namespace NKikimr { -namespace NTable { -namespace NPage { - - using TSize = ui32; - using TPageId = ui32; - +#pragma once + +#include <util/system/types.h> + +namespace NKikimr { +namespace NTable { +namespace NPage { + + using TSize = ui32; + using TPageId = ui32; + /** * A type-safe column group identifier */ @@ -53,32 +53,32 @@ namespace NPage { } }; - enum class EPage : ui16 { - Undef = 0, - Scheme = 2, - Index = 3, + enum class EPage : ui16 { + Undef = 0, + Scheme = 2, + Index = 3, DataPage = 4, - Frames = 5, /* Tagged entities to TRowId relation index */ + Frames = 5, /* Tagged entities to TRowId relation index */ Globs = 6, /* Just enumartion of NPageCollection::TGlobId refs */ - Schem2 = 7, /* New version of EPage::Scheme with TLabel */ - Opaque = 8, /* User defined content, cell value as blob */ - Bloom = 9, /* Bloom filter for some app. defined cells set */ + Schem2 = 7, /* New version of EPage::Scheme with TLabel */ + Opaque = 8, /* User defined content, cell value as blob */ + Bloom = 9, /* Bloom filter for some app. defined cells set */ GarbageStats = 10, /* Stats on garbage in historic data */ TxIdStats = 11, /* Stats for uncommitted TxIds at compaction time */ TxStatus = 12, /* Status of committed/removed transactions */ - }; - - enum class ECodec : ui8 { - Plain = 0, /* Keep data in page as-is */ - LZ4 = 1, /* Use lz4fast compressor */ - }; - - enum class ECache { - None = 0, - Once = 1, /* Put to cache once at load */ - Ever = 2, /* Keep in cache util the end */ - }; - -} -} -} + }; + + enum class ECodec : ui8 { + Plain = 0, /* Keep data in page as-is */ + LZ4 = 1, /* Use lz4fast compressor */ + }; + + enum class ECache { + None = 0, + Once = 1, /* Put to cache once at load */ + Ever = 2, /* Keep in cache util the end */ + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_page_index.h b/ydb/core/tablet_flat/flat_page_index.h index 467e2303d1..80bb720872 100644 --- a/ydb/core/tablet_flat/flat_page_index.h +++ b/ydb/core/tablet_flat/flat_page_index.h @@ -1,45 +1,45 @@ -#pragma once - -#include "flat_page_base.h" -#include "flat_page_label.h" -#include "flat_row_nulls.h" +#pragma once + +#include "flat_page_base.h" +#include "flat_page_label.h" +#include "flat_row_nulls.h" #include "util_deref.h" - -namespace NKikimr { -namespace NTable { -namespace NPage { - - struct TIndex { - /* - TRecord binary layout v2 - .---------.---------------. - | TRowId | page id | header - .---------.---------------. -. - | is_null | value OR offs | key_1 | - .---------.---------------. | - | . . . | | fixed-size - .---------.---------------. | - | is_null | value OR offs | key_K | - .-.------.--.-------.-----. -' - | | | | | | var-size values - '-'------'--'-------'-----' - */ - -#pragma pack(push,1) - - struct TItem { + +namespace NKikimr { +namespace NTable { +namespace NPage { + + struct TIndex { + /* + TRecord binary layout v2 + .---------.---------------. + | TRowId | page id | header + .---------.---------------. -. + | is_null | value OR offs | key_1 | + .---------.---------------. | + | . . . | | fixed-size + .---------.---------------. | + | is_null | value OR offs | key_K | + .-.------.--.-------.-----. -' + | | | | | | var-size values + '-'------'--'-------'-----' + */ + +#pragma pack(push,1) + + struct TItem { TCellOp GetOp(bool) const noexcept - { + { return { Null ? ECellOp::Null : ECellOp::Set, ELargeObj::Inline }; - } - - bool Null; + } + + bool Null; } Y_PACKED; - + struct TRecord : public TDataPageRecord<TRecord, TItem> { TRowId RowId_; TPageId PageId_; - + inline TRowId GetRowId() const { return RowId_; } inline TPageId GetPageId() const { return PageId_; } @@ -47,73 +47,73 @@ namespace NPage { inline void SetPageId(TPageId value) { PageId_ = value; } } Y_PACKED; -#pragma pack(pop) - +#pragma pack(pop) + static_assert(sizeof(TItem) == 1, "Invalid TIndex TItem size"); static_assert(sizeof(TRecord) == 12, "Invalid TIndex TRecord size"); - using TBlock = TBlockWithRecords<TRecord>; - - public: - using TIter = typename TBlock::TIterator; - + using TBlock = TBlockWithRecords<TRecord>; + + public: + using TIter = typename TBlock::TIterator; + static constexpr ui16 Version = 3; - + TIndex(TSharedData raw) - : Raw(std::move(raw)) - { - const auto got = NPage::THello().Read(Raw, EPage::Index); - - Y_VERIFY(got == ECodec::Plain && (got.Version == 2 || got.Version == 3)); - + : Raw(std::move(raw)) + { + const auto got = NPage::THello().Read(Raw, EPage::Index); + + Y_VERIFY(got == ECodec::Plain && (got.Version == 2 || got.Version == 3)); + auto *hdr = TDeref<const TRecordsHeader>::At(got.Page.data(), 0); auto skip = got.Page.size() - hdr->Records * sizeof(TPgSize); - - Y_VERIFY(hdr->Records >= 1u + (got.Version < 3 ? 0u : 1u)); - + + Y_VERIFY(hdr->Records >= 1u + (got.Version < 3 ? 0u : 1u)); + Page.Base = Raw.data(); Page.Array = TDeref<const TRecordsEntry>::At(hdr, skip); - Page.Records = hdr->Records - (got.Version == 3 ? 1 : 0); + Page.Records = hdr->Records - (got.Version == 3 ? 1 : 0); LastKey = (got.Version == 3) ? Page.Record(Page.Records) : nullptr; EndRowId = LastKey ? LastKey->GetRowId() + 1 : Max<TRowId>(); - } - - const TBlock* operator->() const noexcept - { - return &Page; - } - - const auto* Label() const noexcept - { + } + + const TBlock* operator->() const noexcept + { + return &Page; + } + + const auto* Label() const noexcept + { return TDeref<const NPage::TLabel>::At(Raw.data(), 0); - } - - TIter Rewind(TRowId to, TIter on, int dir) const - { - Y_VERIFY(dir == +1, "Only forward lookups supported"); - + } + + TIter Rewind(TRowId to, TIter on, int dir) const + { + Y_VERIFY(dir == +1, "Only forward lookups supported"); + if (to >= EndRowId || !on) { - return Page.End(); - } else { - /* This branch have to never return End() since the real - upper RowId value isn't known. Only Max<TRowId>() and - invalid on iterator may be safetly mapped to End(). - */ - - for (size_t it = 0; ++it < 4 && ++on;) { + return Page.End(); + } else { + /* This branch have to never return End() since the real + upper RowId value isn't known. Only Max<TRowId>() and + invalid on iterator may be safetly mapped to End(). + */ + + for (size_t it = 0; ++it < 4 && ++on;) { if (on->GetRowId() > to) return --on; - } - - auto less = [](TRowId rowId, const TRecord &rec) { + } + + auto less = [](TRowId rowId, const TRecord &rec) { return rowId < rec.GetRowId(); - }; - - auto it = std::upper_bound(on, Page.End(), to, less); - - return (it && it == on) ? on : --it; - } - } - + }; + + auto it = std::upper_bound(on, Page.End(), to, less); + + return (it && it == on) ? on : --it; + } + } + /** * Lookup a page that contains rowId */ @@ -176,7 +176,7 @@ namespace NPage { TIter LookupKey( TCells key, const TPartScheme::TGroupInfo &group, const ESeek seek, const TKeyNulls *nulls) const noexcept - { + { if (!key) { // Special treatment for an empty key switch (seek) { @@ -185,7 +185,7 @@ namespace NPage { case ESeek::Exact: case ESeek::Upper: return Page.End(); - } + } } const auto cmp = TCompare<TRecord>(group.ColsKeyIdx, *nulls); @@ -196,8 +196,8 @@ namespace NPage { // If LastKey < key then the needed page doesn't exist if (!it && LastKey && cmp(*LastKey, key)) { return it; - } - + } + if (it.Off() == 0) { // If key < FirstKey then exact key doesn't exist if (seek == ESeek::Exact) { @@ -209,8 +209,8 @@ namespace NPage { } return it; - } - + } + /** * Lookup a page that may contain key with specified seek mode * @@ -268,23 +268,23 @@ namespace NPage { return LastKey ? LastKey->GetRowId() : Max<TRowId>(); } - ui64 Rows() const noexcept - { - if (LastKey) { - return LastKey->GetRowId() + 1; /* exact number of rows */ + ui64 Rows() const noexcept + { + if (LastKey) { + return LastKey->GetRowId() + 1; /* exact number of rows */ } else if (auto iter = --Page.End()) { - auto pages = (iter - Page.Begin()) + 1; - + auto pages = (iter - Page.Begin()) + 1; + return iter->GetRowId() * (pages + 1) / pages; - } else - return 0; /* cannot estimate rows for one page part */ - } - - TPageId UpperPage() const noexcept - { + } else + return 0; /* cannot estimate rows for one page part */ + } + + TPageId UpperPage() const noexcept + { return Page.Begin() ? (Page.End() - 1)->GetPageId() + 1 : 0; - } - + } + const TRecord* GetFirstKeyRecord() const noexcept { return Page.Record(0); @@ -292,7 +292,7 @@ namespace NPage { const TRecord* GetLastKeyRecord() const noexcept { - return LastKey; + return LastKey; } TRowId GetEndRowId() const noexcept @@ -305,13 +305,13 @@ namespace NPage { return Raw.size(); } - private: + private: TSharedData Raw; - TBlock Page; - const TRecord* LastKey; + TBlock Page; + const TRecord* LastKey; TRowId EndRowId; - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_page_label.cpp b/ydb/core/tablet_flat/flat_page_label.cpp index 2dba104370..0a25502fa4 100644 --- a/ydb/core/tablet_flat/flat_page_label.cpp +++ b/ydb/core/tablet_flat/flat_page_label.cpp @@ -1,12 +1,12 @@ -#include "flat_page_label.h" +#include "flat_page_label.h" #include "util_deref.h" - -#include <util/system/sanitizers.h> - -namespace NKikimr { -namespace NTable { -namespace NPage { - + +#include <util/system/sanitizers.h> + +namespace NKikimr { +namespace NTable { +namespace NPage { + void TLabel::Init(EPage type, ui16 format, ui64 size) noexcept { Type = type; Format = format; @@ -19,57 +19,57 @@ namespace NPage { } THello::TResult THello::Read(TArrayRef<const char> raw, EPage type) const noexcept - { - auto label = TDeref<TLabel>::Copy(raw.begin(), 0); - + { + auto label = TDeref<TLabel>::Copy(raw.begin(), 0); + if (raw.size() < 8) { - Y_FAIL("NPage blob is too small to hold label"); - } else if (label.Type != type && type != EPage::Undef) { - Y_FAIL("NPage blob has an unexpected label type"); + Y_FAIL("NPage blob is too small to hold label"); + } else if (label.Type != type && type != EPage::Undef) { + Y_FAIL("NPage blob has an unexpected label type"); } else if (label.Size != raw.size() && label.Size != Max<ui32>()) { Y_FAIL("NPage label size doesn't match data size"); } else if (label.Size == Max<ui32>()) { Y_VERIFY(raw.size() >= Max<ui32>(), "NPage label huge page marker doesn't match data size"); - } - - const ui16 version = label.Format & 0x7fff; - - if (label.Format & 0x8000) { - /* New style NPage label, has at least extra 8 bytes, the - current impl use only 1st byte. Futher is reserved for - in-place crc (may be) or other pages common metadata. - */ - + } + + const ui16 version = label.Format & 0x7fff; + + if (label.Format & 0x8000) { + /* New style NPage label, has at least extra 8 bytes, the + current impl use only 1st byte. Futher is reserved for + in-place crc (may be) or other pages common metadata. + */ + auto codec = ECodec(*TDeref<ui8>::At(TDeref<TLabel>::At(raw.begin(), 0) + 1, 0)); - auto *on = raw.begin() + sizeof(TLabel) + 8; - - return { label.Type, version, codec, { on, raw.end() } }; - - } else { - /* old style NPage label, has no any extra attached data */ - - auto *on = raw.begin() + sizeof(TLabel); - - return - { label.Type, version, ECodec::Plain, { on, raw.end() } }; - } - } - + auto *on = raw.begin() + sizeof(TLabel) + 8; + + return { label.Type, version, codec, { on, raw.end() } }; + + } else { + /* old style NPage label, has no any extra attached data */ + + auto *on = raw.begin() + sizeof(TLabel); + + return + { label.Type, version, ECodec::Plain, { on, raw.end() } }; + } + } + TSharedData THello::Wrap(TArrayRef<const char> plain, EPage page, ui16 version) noexcept - { - Y_VERIFY(!(version >> 15), "Version can use only 15 bits"); - + { + Y_VERIFY(!(version >> 15), "Version can use only 15 bits"); + TSharedData blob = TSharedData::Uninitialized(plain.size() + 8); - + TDeref<TLabel>::At(blob.mutable_begin(), 0)->Init(page, version, blob.size()); - + std::copy(plain.begin(), plain.end(), blob.mutable_begin() + 8); - - NSan::CheckMemIsInitialized(blob.data(), blob.size()); - - return blob; - } - + + NSan::CheckMemIsInitialized(blob.data(), blob.size()); + + return blob; + } + TString THello::WrapString(TArrayRef<const char> plain, EPage page, ui16 version) noexcept { Y_VERIFY(!(version >> 15), "Version can use only 15 bits"); @@ -85,6 +85,6 @@ namespace NPage { return blob; } -} -} -} +} +} +} diff --git a/ydb/core/tablet_flat/flat_page_label.h b/ydb/core/tablet_flat/flat_page_label.h index eadf70983e..393ef32293 100644 --- a/ydb/core/tablet_flat/flat_page_label.h +++ b/ydb/core/tablet_flat/flat_page_label.h @@ -1,56 +1,56 @@ -#pragma once - -#include "flat_page_iface.h" +#pragma once + +#include "flat_page_iface.h" #include "util_basics.h" - + #include <ydb/core/base/shared_data.h> -#include <util/generic/array_ref.h> -#include <util/system/unaligned_mem.h> - -namespace NKikimr { -namespace NTable { -namespace NPage { - - struct TLabel { - EPage Type; - ui16 Format; - TSize Size; +#include <util/generic/array_ref.h> +#include <util/system/unaligned_mem.h> + +namespace NKikimr { +namespace NTable { +namespace NPage { + + struct TLabel { + EPage Type; + ui16 Format; + TSize Size; void Init(EPage type, ui16 format, ui64 size) noexcept; void SetSize(ui64 size) noexcept; - }; - - static_assert(sizeof(TLabel) == 8, "Invalid page TLabel unit"); - - struct THello { + }; + + static_assert(sizeof(TLabel) == 8, "Invalid page TLabel unit"); + + struct THello { struct TResult { - bool operator==(NPage::ECodec codec) const noexcept - { - return Codec == codec; - } - - bool operator==(NPage::EPage kind) const noexcept - { - return Type == kind; - } - + bool operator==(NPage::ECodec codec) const noexcept + { + return Codec == codec; + } + + bool operator==(NPage::EPage kind) const noexcept + { + return Type == kind; + } + TArrayRef<const char> operator*() const noexcept - { - return Page; - } - - EPage Type; - ui16 Version; - ECodec Codec; + { + return Page; + } + + EPage Type; + ui16 Version; + ECodec Codec; TArrayRef<const char> Page; - }; - + }; + TResult Read(TArrayRef<const char>, EPage type = EPage::Undef) const noexcept; static TSharedData Wrap(TArrayRef<const char>, EPage, ui16 version) noexcept; static TString WrapString(TArrayRef<const char>, EPage, ui16 version) noexcept; - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_page_other.h b/ydb/core/tablet_flat/flat_page_other.h index 51e5e9f658..824f447361 100644 --- a/ydb/core/tablet_flat/flat_page_other.h +++ b/ydb/core/tablet_flat/flat_page_other.h @@ -1,68 +1,68 @@ -#pragma once - -#include "flat_page_frames.h" -#include "flat_page_blobs.h" -#include "flat_util_binary.h" - -#include <util/generic/vector.h> -#include <util/generic/xrange.h> -#include <util/system/sanitizers.h> - -namespace NKikimr { -namespace NTable { -namespace NPage { - - class TFrameWriter { +#pragma once + +#include "flat_page_frames.h" +#include "flat_page_blobs.h" +#include "flat_util_binary.h" + +#include <util/generic/vector.h> +#include <util/generic/xrange.h> +#include <util/system/sanitizers.h> + +namespace NKikimr { +namespace NTable { +namespace NPage { + + class TFrameWriter { using THeader = TFrames::THeader; using TEntry = TFrames::TEntry; - - struct TFresh { - ui16 Tag; - ui32 Len; - }; - - public: - TFrameWriter(ui32 tags = 1) - : TagsCount(tags) - { - Tags.resize(TagsCount + (TagsCount & 1), 0); - Cook.reserve(tags); - - Y_VERIFY(tags <= ui32(-Min<i16>()), "Too many columnt tags"); - } - - void Put(TRowId row, ui16 tag, ui32 bytes) noexcept - { - if (row < Last && Last != Max<TRowId>()) { - Y_FAIL("Frame items have to follow sorted by row"); - } else if (tag >= TagsCount) { - Y_FAIL("Frame item component tag is out of range"); - } else if (Last != row) { - Flush(); - } - - Size += bytes; - Tags[tag] += 1; - Last = row; - Cook.emplace_back(TFresh{ tag, bytes }); - } - + + struct TFresh { + ui16 Tag; + ui32 Len; + }; + + public: + TFrameWriter(ui32 tags = 1) + : TagsCount(tags) + { + Tags.resize(TagsCount + (TagsCount & 1), 0); + Cook.reserve(tags); + + Y_VERIFY(tags <= ui32(-Min<i16>()), "Too many columnt tags"); + } + + void Put(TRowId row, ui16 tag, ui32 bytes) noexcept + { + if (row < Last && Last != Max<TRowId>()) { + Y_FAIL("Frame items have to follow sorted by row"); + } else if (tag >= TagsCount) { + Y_FAIL("Frame item component tag is out of range"); + } else if (Last != row) { + Flush(); + } + + Size += bytes; + Tags[tag] += 1; + Last = row; + Cook.emplace_back(TFresh{ tag, bytes }); + } + void FlushRow() noexcept { Flush(); } TSharedData Make() noexcept - { - Flush(); - + { + Flush(); + return Array ? MakeAnyway() : TSharedData{ }; - } - + } + ui64 EstimateBytesUsed(size_t extraItems) const noexcept { if (size_t items = Array.size() + Cook.size() + extraItems) { - return sizeof(NPage::TLabel) + sizeof(THeader) + return sizeof(NPage::TLabel) + sizeof(THeader) + NUtil::NBin::SizeOf(Tags) + sizeof(TEntry) * items; } @@ -80,88 +80,88 @@ namespace NPage { Cook.clear(); } - private: + private: TSharedData MakeAnyway() noexcept - { - auto size = sizeof(NPage::TLabel) + sizeof(THeader) - + NUtil::NBin::SizeOf(Tags, Array); - + { + auto size = sizeof(NPage::TLabel) + sizeof(THeader) + + NUtil::NBin::SizeOf(Tags, Array); + TSharedData buf = TSharedData::Uninitialized(size); - + NUtil::NBin::TPut out(buf.mutable_begin()); - - if (auto *hdr = out.Skip<NPage::TLabel>()) { - hdr->Type = EPage::Frames; - hdr->Format = 0; - hdr->Size = size; - } - - if (auto *post = out.Skip<THeader>()) { - Zero(*post); - - post->Skip = sizeof(THeader) + NUtil::NBin::SizeOf(Tags); - post->Rows = Rows; - post->Size = Size; - post->Tags = TagsCount; - } - - out.Put(Tags).Put(Array); - + + if (auto *hdr = out.Skip<NPage::TLabel>()) { + hdr->Type = EPage::Frames; + hdr->Format = 0; + hdr->Size = size; + } + + if (auto *post = out.Skip<THeader>()) { + Zero(*post); + + post->Skip = sizeof(THeader) + NUtil::NBin::SizeOf(Tags); + post->Rows = Rows; + post->Size = Size; + post->Tags = TagsCount; + } + + out.Put(Tags).Put(Array); + Y_VERIFY(*out == buf.mutable_end()); - Y_VERIFY(buf.size() % alignof(TEntry) == 0); + Y_VERIFY(buf.size() % alignof(TEntry) == 0); NSan::CheckMemIsInitialized(buf.data(), buf.size()); - - return buf; - } - - void Flush() noexcept - { - for (auto it: xrange(Cook.size())) { - const i16 ref = it ? i16(it) : -i16(Cook.size()); - - Array.push_back({ Last, Cook[it].Tag, ref, Cook[it].Len }); - } - - Rows += Cook ? 1 : 0; - Cook.clear(); - } - - private: - TRowId Last = Max<TRowId>(); /* Current frame row number */ - ui32 TagsCount = 0; - ui32 Rows = 0; /* Unique rows in frame index */ - ui64 Size = 0; /* Sum of all Size fields in arr*/ - TVector<ui32> Tags; /* By tag frequency historgram */ - TVector<TEntry> Array; - TVector<TFresh> Cook; - }; - + + return buf; + } + + void Flush() noexcept + { + for (auto it: xrange(Cook.size())) { + const i16 ref = it ? i16(it) : -i16(Cook.size()); + + Array.push_back({ Last, Cook[it].Tag, ref, Cook[it].Len }); + } + + Rows += Cook ? 1 : 0; + Cook.clear(); + } + + private: + TRowId Last = Max<TRowId>(); /* Current frame row number */ + ui32 TagsCount = 0; + ui32 Rows = 0; /* Unique rows in frame index */ + ui64 Size = 0; /* Sum of all Size fields in arr*/ + TVector<ui32> Tags; /* By tag frequency historgram */ + TVector<TEntry> Array; + TVector<TFresh> Cook; + }; + class TExtBlobsWriter { using THeader = TExtBlobs::THeader; using TEntry = TExtBlobs::TEntry; - public: + public: ui32 Put(const NPageCollection::TGlobId &glob) noexcept - { - Bytes += glob.Logo.BlobSize(); - Globs.emplace_back(glob); - return Globs.size() - 1; - } - + { + Bytes += glob.Logo.BlobSize(); + Globs.emplace_back(glob); + return Globs.size() - 1; + } + TSharedData Make(bool force = false) const noexcept - { + { return (Globs || force) ? MakeAnyway() : TSharedData{ }; - } - - ui32 Size() const noexcept - { - return Globs.size(); - } - + } + + ui32 Size() const noexcept + { + return Globs.size(); + } + ui64 EstimateBytesUsed(size_t extraItems) const noexcept { if (size_t items = Globs.size() + extraItems) { - return sizeof(NPage::TLabel) + sizeof(THeader) + return sizeof(NPage::TLabel) + sizeof(THeader) + sizeof(TEntry) * items; } @@ -173,43 +173,43 @@ namespace NPage { Globs.clear(); } - private: + private: TSharedData MakeAnyway() const noexcept - { - auto size = sizeof(NPage::TLabel) + sizeof(THeader) - + NUtil::NBin::SizeOf(Globs); - + { + auto size = sizeof(NPage::TLabel) + sizeof(THeader) + + NUtil::NBin::SizeOf(Globs); + TSharedData buf = TSharedData::Uninitialized(size); - + NUtil::NBin::TPut out(buf.mutable_begin()); - - if (auto *hdr = out.Skip<NPage::TLabel>()) { - hdr->Type = EPage::Globs; - hdr->Format = 1; + + if (auto *hdr = out.Skip<NPage::TLabel>()) { + hdr->Type = EPage::Globs; + hdr->Format = 1; hdr->Size = size < Max<ui32>() ? ui32(size) : Max<ui32>(); - } - - if (auto *post = out.Skip<THeader>()) { - Zero(*post); - - post->Skip = sizeof(THeader); - post->Bytes = Bytes; - } - - out.Put(Globs); - + } + + if (auto *post = out.Skip<THeader>()) { + Zero(*post); + + post->Skip = sizeof(THeader); + post->Bytes = Bytes; + } + + out.Put(Globs); + Y_VERIFY(*out == buf.mutable_end()); - Y_VERIFY(buf.size() % alignof(TEntry) == 0); + Y_VERIFY(buf.size() % alignof(TEntry) == 0); NSan::CheckMemIsInitialized(buf.data(), buf.size()); - - return buf; - } - - private: - ui64 Bytes = 0; + + return buf; + } + + private: + ui64 Bytes = 0; TVector<TEntry> Globs; - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_page_writer.h b/ydb/core/tablet_flat/flat_page_writer.h index 005d3dd54c..69fc975b9f 100644 --- a/ydb/core/tablet_flat/flat_page_writer.h +++ b/ydb/core/tablet_flat/flat_page_writer.h @@ -1,48 +1,48 @@ -#pragma once - -#include "flat_page_conf.h" -#include "flat_page_label.h" -#include "flat_page_data.h" -#include "flat_page_index.h" -#include "flat_part_iface.h" -#include "flat_part_pinout.h" -#include "flat_row_state.h" -#include "util_fmt_abort.h" +#pragma once + +#include "flat_page_conf.h" +#include "flat_page_label.h" +#include "flat_page_data.h" +#include "flat_page_index.h" +#include "flat_part_iface.h" +#include "flat_part_pinout.h" +#include "flat_row_state.h" +#include "util_fmt_abort.h" #include "util_deref.h" - -#include <util/generic/vector.h> -#include <util/system/sanitizers.h> - -namespace NKikimr { -namespace NTable { -namespace NPage { - + +#include <util/generic/vector.h> +#include <util/system/sanitizers.h> + +namespace NKikimr { +namespace NTable { +namespace NPage { + struct TDataPageBuilder { TDataPageBuilder(EPage type, ui16 version, bool label, ui32 extra) - : Type(type) - , Version(version) - , V2Label(label) - , Extra(extra) + : Type(type) + , Version(version) + , V2Label(label) + , Extra(extra) , Prefix(sizeof(TLabel) + (label ? 8 : 0) + sizeof(TRecordsHeader) + Extra) - { - Y_VERIFY((version & 0x8000) == 0, "Invalid version value"); - } - - explicit operator bool() const noexcept - { - return Tail && Blob; - } - - template<typename T> - T* ExtraAs() noexcept - { - Y_VERIFY(sizeof(T) == Extra, "Cannot cast extra block to T"); - + { + Y_VERIFY((version & 0x8000) == 0, "Invalid version value"); + } + + explicit operator bool() const noexcept + { + return Tail && Blob; + } + + template<typename T> + T* ExtraAs() noexcept + { + Y_VERIFY(sizeof(T) == Extra, "Cannot cast extra block to T"); + return TDeref<T>::At(Blob.mutable_data(), Prefix - Extra); - } - + } + void Grow(size_t more, size_t least, float factor) noexcept - { + { if (Blob) { size_t desired = BytesUsed() + more; PageBytes = Max(PageBytes, desired); @@ -52,20 +52,20 @@ namespace NPage { } } else { Open(more, least); - } - } - + } + } + void Open(size_t more, size_t least, ui32 rows = 0) noexcept - { + { Y_VERIFY(!Blob, "TDataPageBuilder is already has live page"); - + PageBytes = Max(least, BytesUsed() + more); - PageRows = rows ? rows : Max<ui32>(); + PageRows = rows ? rows : Max<ui32>(); Resize(PageBytes); - } - + } + bool Overflow(size_t more, ui32 rows) const noexcept - { + { return Blob && Deltas.empty() && ((BytesUsed() + more) > PageBytes || (Offsets.size() + rows > PageRows)); } @@ -74,35 +74,35 @@ namespace NPage { Y_VERIFY(Deltas.empty()); if (!Blob) - return { }; - + return { }; + Y_VERIFY_DEBUG(BytesUsed() <= PageBytes); Blob.Trim(BytesUsed()); - + char *ptr = Blob.mutable_begin(); - + if (auto *label = TDeref<NPage::TLabel>::At(ptr, 0)) { label->Init(Type, Version, Blob.size()); - - if (V2Label) { - label->Format |= 0x8000; + + if (V2Label) { + label->Format |= 0x8000; *TDeref<ui8>::At(label + 1, 0) = 0; /* page as-is */ - } - - ptr += sizeof(NPage::TLabel) + (V2Label ? 8 : 0); - } - + } + + ptr += sizeof(NPage::TLabel) + (V2Label ? 8 : 0); + } + if (auto *hdr = TDeref<TRecordsHeader>::At(ptr, 0)) { - hdr->Records = Offsets.size(); - } - - { /* Place on the end reconds offsets */ + hdr->Records = Offsets.size(); + } + + { /* Place on the end reconds offsets */ auto *buf = TDeref<char>::At(Offsets.data(), 0); - - Write(buf, Offsets.size() * sizeof(TPgSize)); - } - + + Write(buf, Offsets.size() * sizeof(TPgSize)); + } + NSan::CheckMemIsInitialized(Blob.data(), Blob.size()); return Reset(); @@ -110,7 +110,7 @@ namespace NPage { TSharedData Reset() noexcept { - Tail = nullptr; + Tail = nullptr; Deltas.clear(); if (Deltas.capacity() > 1024) { TVector<ui64>().swap(Deltas); @@ -118,43 +118,43 @@ namespace NPage { Offsets.clear(); if (Offsets.capacity() > 10240) { TVector<TPgSize>().swap(Offsets); - } - + } + return std::exchange(Blob, TSharedData{ }); - } - + } + ui32 PrefixSize() const noexcept { return Prefix; } size_t BytesUsed() const noexcept - { + { return Tail ? (Offset() + sizeof(ui64) * Deltas.size() + sizeof(TPgSize) * Offsets.size()) : Prefix; - } - + } + size_t Left() const noexcept - { - return Tail ? (Blob.size() - BytesUsed()) : 0; - } - + { + return Tail ? (Blob.size() - BytesUsed()) : 0; + } + void Zero(size_t size) noexcept - { - auto *from = Advance(size); - std::fill(from, Tail, 0); - } - - template <class T> - T& Place() - { - return *reinterpret_cast<T*>(Advance(TPgSizeOf<T>::Value)); - } - + { + auto *from = Advance(size); + std::fill(from, Tail, 0); + } + + template <class T> + T& Place() + { + return *reinterpret_cast<T*>(Advance(TPgSizeOf<T>::Value)); + } + bool HasDeltas() const noexcept - { + { return !Deltas.empty(); - } - + } + void PushDelta(TPgSize recordSize) noexcept { Y_VERIFY_DEBUG(recordSize > 0); @@ -220,77 +220,77 @@ namespace NPage { } } - template<typename TRecord> - auto* AddValue(const TPartScheme::TColumn& info, TCell value, TRecord& rec) - { - auto* item = rec.GetItem(info); - if (info.IsFixed) { - Y_VERIFY(value.Size() == info.FixedSize, "invalid fixed cell size)"); - memcpy(rec.template GetFixed<void>(item), value.Data(), value.Size()); - } else { - auto *ref = rec.template GetFixed<TDataRef>(item); - ref->Offset = Offset(rec.Base()); - ref->Size = value.Size(); - Write(value.Data(), value.Size()); - } - return item; - } - - private: + template<typename TRecord> + auto* AddValue(const TPartScheme::TColumn& info, TCell value, TRecord& rec) + { + auto* item = rec.GetItem(info); + if (info.IsFixed) { + Y_VERIFY(value.Size() == info.FixedSize, "invalid fixed cell size)"); + memcpy(rec.template GetFixed<void>(item), value.Data(), value.Size()); + } else { + auto *ref = rec.template GetFixed<TDataRef>(item); + ref->Offset = Offset(rec.Base()); + ref->Size = value.Size(); + Write(value.Data(), value.Size()); + } + return item; + } + + private: void Resize(size_t bytes) noexcept - { - Y_VERIFY(bytes > Prefix, "Too few bytes for page"); - + { + Y_VERIFY(bytes > Prefix, "Too few bytes for page"); + if (auto was = std::exchange(Blob, TSharedData::Uninitialized(bytes))) { char *end = Blob.mutable_data(); - + Tail = std::copy(was.begin(), static_cast<const char*>(Tail), end); - } else { + } else { char *end = Blob.mutable_data(); - + Tail = TDeref<char>::At(end, Prefix); - - std::fill(Tail - Prefix, Tail, 0); - } - } - + + std::fill(Tail - Prefix, Tail, 0); + } + } + size_t Offset(const void *base = nullptr) const noexcept - { - return Tail - (const char*)(base ? base : Blob.begin()); - } - + { + return Tail - (const char*)(base ? base : Blob.begin()); + } + void Write(const char *buf, size_t size) noexcept - { - std::copy(buf, buf + size, Advance(size)); - } - + { + std::copy(buf, buf + size, Advance(size)); + } + char* Advance(size_t size) noexcept - { + { size_t offset = Tail - Blob.mutable_begin(); size_t available = Blob.size() - offset; Y_VERIFY(size <= available, "Requested %" PRISZT " bytes, have %" PRISZT " available", size, available); Y_VERIFY_DEBUG(offset + size <= PageBytes, "Requested bytes are out of current page limits"); - return std::exchange(Tail, Tail + size); - } - - private: - const EPage Type = EPage::Undef; - const ui16 Version = Max<ui16>(); - const bool V2Label = false; /* Put new style NPage label */ - const ui32 Extra = 0; /* Size of extra data in prefix */ - const ui32 Prefix = 0; /* Prefix size (label + heder) */ - + return std::exchange(Tail, Tail + size); + } + + private: + const EPage Type = EPage::Undef; + const ui16 Version = Max<ui16>(); + const bool V2Label = false; /* Put new style NPage label */ + const ui32 Extra = 0; /* Size of extra data in prefix */ + const ui32 Prefix = 0; /* Prefix size (label + heder) */ + TSharedData Blob; - char* Tail = nullptr; + char* Tail = nullptr; TVector<TPgSize> Offsets; TVector<ui64> Deltas; ui64 PageBytes = Max<ui64>(); /* Max bytes per each page blob */ - ui32 PageRows = Max<ui32>(); /* Max rows per each rows blob */ - }; - - + ui32 PageRows = Max<ui32>(); /* Max rows per each rows blob */ + }; + + class TDataPageWriter { - public: + public: struct TSizeInfo { TPgSize DataPageSize = 0; TPgSize SmallSize = 0; @@ -304,7 +304,7 @@ namespace NPage { public: TDataPageWriter(TIntrusiveConstPtr<TPartScheme> scheme, const TConf &conf, TTagsRef tags, TGroupId groupId) - : Scheme(std::move(scheme)) + : Scheme(std::move(scheme)) , PageSize(conf.Groups[groupId.Index].PageSize) , PageRows(conf.Groups[groupId.Index].PageRows) , SmallEdge(conf.SmallEdge) @@ -314,26 +314,26 @@ namespace NPage { , GroupId(groupId) , GroupInfo(Scheme->GetLayout(groupId)) , DataPageBuilder(EPage::DataPage, 1, bool(conf.Groups[groupId.Index].Codec), sizeof(TDataPage::TExtra)) - { + { size_t expected = GroupInfo.Columns.size() - GroupInfo.ColsKeyData.size(); - + Y_VERIFY(Pinout.size() == expected, "TDataPageWriter got an invalid pinout"); - } - + } + ui32 PrefixSize() const noexcept - { + { return DataPageBuilder.PrefixSize(); - } - + } + ui64 BytesUsed() const noexcept - { + { return DataPageBuilder.BytesUsed(); - } - + } + TSizeInfo CalcSize(TCellsRef key, const TRowState& row, bool finalRow, TRowVersion minVersion, TRowVersion maxVersion, ui64 txId) const - { + { Y_VERIFY(key.size() == GroupInfo.KeyTypes.size()); - + const bool isErased = GroupId.Index == 0 && maxVersion < TRowVersion::Max(); const bool isVersioned = GroupId.Index == 0 && minVersion > TRowVersion::Min(); const bool isDelta = txId != 0; @@ -346,19 +346,19 @@ namespace NPage { ret.DataPageSize += isErased ? sizeof(NPage::TDataPage::TVersion) : 0; ret.DataPageSize += isVersioned ? sizeof(NPage::TDataPage::TVersion) : 0; ret.DataPageSize += GroupId.Index == 0 && isDelta ? sizeof(NPage::TDataPage::TDelta) : 0; - + // Only the main group includes the key for (TPos it = 0; it < GroupInfo.ColsKeyData.size(); it++) { ret.DataPageSize += GroupInfo.ColsKeyData[it].IsFixed ? 0 : key[it].Size(); } - + for (const auto& pin : Pinout) { auto &info = GroupId.Historic ? Scheme->HistoryColumns[pin.From] : Scheme->AllColumns[pin.From]; - - if (!row.IsFinalized(pin.To) || info.IsKey() || info.IsFixed) { - + + if (!row.IsFinalized(pin.To) || info.IsKey() || info.IsFixed) { + } else if (row.GetOp(pin.To) != ELargeObj::Inline) { - /* External blob occupies only fixed technical field */ + /* External blob occupies only fixed technical field */ ++ret.ReusedLargeRefs; } else if (!isDelta && IsLargeSize(row.Get(pin.To).Size())) { ret.LargeSize += row.Get(pin.To).Size(); @@ -368,13 +368,13 @@ namespace NPage { ++ret.NewSmallRefs; } else if (isDelta || !finalRow || row.GetOp(pin.To) != ECellOp::Reset) { ret.DataPageSize += row.Get(pin.To).Size(); - } - } - + } + } + ret.Overflow = DataPageBuilder.Overflow(ret.DataPageSize, 1); - return ret; - } - + return ret; + } + void Add(const TSizeInfo& more, TCellsRef key, const TRowState& row, ISaver &saver, bool finalRow, TRowVersion minVersion, TRowVersion maxVersion, ui64 txId) noexcept { if (more.Overflow) { @@ -431,11 +431,11 @@ namespace NPage { private: void Put(TCellsRef key, const TRowState& row, ISaver &saver, bool finalRow, TRowVersion minVersion, TRowVersion maxVersion, ui64 txId, TPgSize recordSize) noexcept - { + { const bool isErased = !maxVersion.IsMax(); const bool isVersioned = !minVersion.IsMin(); const bool isDelta = txId != 0; - + if (isDelta) { Y_VERIFY(!isErased && !isVersioned); DataPageBuilder.PushDelta(recordSize); @@ -444,12 +444,12 @@ namespace NPage { } auto &rec = DataPageBuilder.Place<NPage::TDataPage::TRecord>(); - + for (const auto &info: GroupInfo.Columns) { DataPageBuilder.Place<NPage::TDataPage::TItem>().Flg = ui8(ECellOp::Empty); DataPageBuilder.Zero(info.FixedSize); - } - + } + if (GroupId.Index == 0) { rec.SetFields(row.GetRowState(), isErased, isVersioned, isDelta); @@ -476,41 +476,41 @@ namespace NPage { DataPageBuilder.AddValue(info, val, rec)->Null = false; } else { rec.GetItem(info)->Null = true; - } - } - + } + } + for (const auto& pin : Pinout) { auto &info = GroupId.Historic ? Scheme->HistoryColumns[pin.From] : Scheme->AllColumns[pin.From]; - - if (!row.IsFinalized(pin.To) || info.IsKey()) { - + + if (!row.IsFinalized(pin.To) || info.IsKey()) { + } else if (row.GetOp(pin.To) == ECellOp::Reset) { if (!finalRow) rec.GetItem(info)->Flg = ui8(ECellOp::Reset); - } else if (auto cell = row.Get(pin.To)) { + } else if (auto cell = row.Get(pin.To)) { auto cellOp = row.GetOp(pin.To); - + if (info.IsFixed /* may place only as ELargeObj::Inline */) { Y_VERIFY(cellOp == ELargeObj::Inline, "Got fixed non-inlined"); - + DataPageBuilder.AddValue(info, cell, rec)->Flg = *cellOp; } else if (auto lob = SaveBlob(cellOp, pin.To, cell, saver, isDelta)) { - auto *item = rec.GetItem(info); - + auto *item = rec.GetItem(info); + WriteUnaligned<ui64>(rec.template GetFixed<void>(item), lob.Ref); item->Flg = *TCellOp{ cellOp, lob.Lob }; - } else + } else DataPageBuilder.AddValue(info, cell, rec)->Flg = *cellOp; - } else { + } else { rec.GetItem(info)->Flg = ui8(ECellOp::Null); - } - } + } + } LastRecord = isDelta ? nullptr : &rec; - } - + } + TLargeObj SaveBlob(TCellOp cellOp, ui32 pin, const TCell &cell, ISaver &saver, bool isDelta) noexcept - { + { if (cellOp == ELargeObj::GlobId) { return saver.Save(BlobRowId, pin, cell.AsValue<NPageCollection::TGlobId>()); } else if (cellOp != ELargeObj::Inline) { @@ -519,11 +519,11 @@ namespace NPage { // FIXME: we cannot handle blob references during scans, so we // avoid creating large objects when they are in deltas return saver.Save(BlobRowId, pin, { cell.Data(), cell.Size() }); - } - - return { }; - } - + } + + return { }; + } + private: bool IsLargeSize(TPgSize size) const noexcept { return size >= LargeEdge && size <= MaxLargeBlob; @@ -533,58 +533,58 @@ namespace NPage { return size >= SmallEdge; } - public: + public: const TIntrusiveConstPtr<TPartScheme> Scheme; - - private: - const TPgSize PageSize = 8 * 1024; - const ui32 PageRows = Max<ui32>(); + + private: + const TPgSize PageSize = 8 * 1024; + const ui32 PageRows = Max<ui32>(); const TPgSize SmallEdge; const TPgSize LargeEdge; const TPgSize MaxLargeBlob; const TPinout Pinout; const TGroupId GroupId; const TPartScheme::TGroupInfo& GroupInfo; - TRowId RowId = 0; + TRowId RowId = 0; TRowId BlobRowId = 0; TDataPageBuilder DataPageBuilder; NPage::TDataPage::TRecord* LastRecord = nullptr; - }; - - - class TIndexWriter { - public: + }; + + + class TIndexWriter { + public: TIndexWriter(TIntrusiveConstPtr<TPartScheme> scheme, const TConf &conf, TGroupId groupId) - : Scheme(std::move(scheme)) + : Scheme(std::move(scheme)) , MinSize(conf.Groups[groupId.Index].IndexMin) , GroupId(groupId) , GroupInfo(Scheme->GetLayout(groupId)) , DataPageBuilder(EPage::Index, groupId.IsMain() ? 3 : 2, false, 0 /* no extra data before block */) - { - - } - + { + + } + ui64 BytesUsed() const noexcept - { + { return DataPageBuilder.BytesUsed(); - } - - TPgSize CalcSize(TCellsRef key) const noexcept - { + } + + TPgSize CalcSize(TCellsRef key) const noexcept + { Y_VERIFY(key.size() == GroupInfo.KeyTypes.size()); - - TPgSize ret = TPgSizeOf<NPage::TIndex::TRecord>::Value; + + TPgSize ret = TPgSizeOf<NPage::TIndex::TRecord>::Value; ret += sizeof(TPgSize); - + ret += GroupInfo.IdxRecFixedSize; for (TPos it = 0; it < GroupInfo.ColsKeyIdx.size(); it++) { ret += GroupInfo.ColsKeyIdx[it].IsFixed ? 0 : key[it].Size(); } - return ret; - } - + return ret; + } + void Add(TPgSize more, TCellsRef key, TRowId row, TPageId page) noexcept { DataPageBuilder.Grow(more, MinSize, 1.42); @@ -609,13 +609,13 @@ namespace NPage { private: void Put(TCellsRef key, TRowId row, TPageId page, TPgSize recordSize) noexcept - { + { DataPageBuilder.PushOffset(recordSize); - + auto &rec = DataPageBuilder.Place<NPage::TIndex::TRecord>(); rec.SetRowId(row); rec.SetPageId(page); - + for (const auto &info: GroupInfo.ColsKeyIdx) { DataPageBuilder.Place<NPage::TIndex::TItem>().Null = true; DataPageBuilder.Zero(info.FixedSize); @@ -625,19 +625,19 @@ namespace NPage { if (const auto &val = key[it]) { DataPageBuilder.AddValue(GroupInfo.ColsKeyIdx[it], val, rec)->Null = false; } - } - } - - public: + } + } + + public: const TIntrusiveConstPtr<TPartScheme> Scheme; - - private: - const TPgSize MinSize = 8 * 1024; + + private: + const TPgSize MinSize = 8 * 1024; const TGroupId GroupId; const TPartScheme::TGroupInfo& GroupInfo; TDataPageBuilder DataPageBuilder; - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_part_charge.h b/ydb/core/tablet_flat/flat_part_charge.h index 2a417a7a1b..778580c606 100644 --- a/ydb/core/tablet_flat/flat_part_charge.h +++ b/ydb/core/tablet_flat/flat_part_charge.h @@ -1,34 +1,34 @@ -#pragma once - -#include "defs.h" -#include "flat_table_part.h" -#include "flat_part_iface.h" -#include "flat_part_slice.h" - +#pragma once + +#include "defs.h" +#include "flat_table_part.h" +#include "flat_part_iface.h" +#include "flat_part_slice.h" + #include <util/generic/bitmap.h> -namespace NKikimr { -namespace NTable { - - class TCharge { - public: - using TCells = NPage::TCells; - - struct TResult { - bool Ready; /* All required pages are already in memory */ - bool Overshot; /* Search may start outside of bounds */ - }; - +namespace NKikimr { +namespace NTable { + + class TCharge { + public: + using TCells = NPage::TCells; + + struct TResult { + bool Ready; /* All required pages are already in memory */ + bool Overshot; /* Search may start outside of bounds */ + }; + TCharge(IPages *env, const TPart &part, TTagsRef tags, bool includeHistory = false) - : Env(env) - , Part(&part) - , Scheme(*Part->Scheme) - , Index(Part->Index) + : Env(env) + , Part(&part) + , Scheme(*Part->Scheme) + , Index(Part->Index) , HistoryIndex( includeHistory && Part->HistoricIndexes ? &Part->GetGroupIndex(NPage::TGroupId(0, true)) : nullptr) - { + { TDynBitMap seen; for (TTag tag : tags) { if (const auto* col = Scheme.FindColumnByTag(tag)) { @@ -43,64 +43,64 @@ namespace NTable { } } } - } - - static bool Range(IPages *env, const TCells key1, const TCells key2, + } + + static bool Range(IPages *env, const TCells key1, const TCells key2, const TRun &run, const TKeyNulls &nulls, TTagsRef tags, ui64 items, ui64 bytes, bool includeHistory = false) noexcept - { - if (run.size() == 1) { - auto pos = run.begin(); + { + if (run.size() == 1) { + auto pos = run.begin(); TRowId row1 = pos->Slice.BeginRowId(); TRowId row2 = pos->Slice.EndRowId() - 1; return TCharge(env, *pos->Part, tags, includeHistory).Do(key1, key2, row1, row2, nulls, items, bytes).Ready; - } - - bool ready = true; - auto pos = run.LowerBound(key1); - - if (pos == run.end()) - return true; - + } + + bool ready = true; + auto pos = run.LowerBound(key1); + + if (pos == run.end()) + return true; + bool fromStart = TSlice::CompareSearchKeyFirstKey(key1, pos->Slice, nulls) <= 0; - - while (pos != run.end()) { + + while (pos != run.end()) { TRowId row1 = pos->Slice.BeginRowId(); TRowId row2 = pos->Slice.EndRowId() - 1; const int cmp = TSlice::CompareLastKeySearchKey(pos->Slice, key2, nulls); - - TArrayRef<const TCell> key1r; - if (!fromStart) { - key1r = key1; - } - TArrayRef<const TCell> key2r; + + TArrayRef<const TCell> key1r; + if (!fromStart) { + key1r = key1; + } + TArrayRef<const TCell> key2r; if (cmp > 0 /* slice->LastKey > key2 */) { - key2r = key2; - } - + key2r = key2; + } + auto r = TCharge(env, *pos->Part, tags, includeHistory).Do(key1r, key2r, row1, row2, nulls, items, bytes); - ready &= r.Ready; - + ready &= r.Ready; + if (cmp >= 0 /* slice->LastKey >= key2 */) { - if (r.Overshot && ++pos != run.end()) { - // Unfortunately key > key2 might be at the start of the next slice + if (r.Overshot && ++pos != run.end()) { + // Unfortunately key > key2 might be at the start of the next slice TRowId firstRow = pos->Slice.BeginRowId(); - // Precharge the first row on the next slice + // Precharge the first row on the next slice TCharge(env, *pos->Part, tags, includeHistory).Do(firstRow, firstRow, items, bytes); - } - - break; - } - - // Will consume this slice before encountering key2 - fromStart = true; - ++pos; - } - - return ready; - } - + } + + break; + } + + // Will consume this slice before encountering key2 + fromStart = true; + ++pos; + } + + return ready; + } + static bool RangeReverse(IPages *env, const TCells key1, const TCells key2, const TRun &run, const TKeyNulls &nulls, TTagsRef tags, ui64 items, ui64 bytes, bool includeHistory = false) noexcept @@ -163,7 +163,7 @@ namespace NTable { return ready; } - /** + /** * Precharges data around the specified splitKey * * This method will ensure pages with the first key >= splitKey and the @@ -224,130 +224,130 @@ namespace NTable { /** * Precharges data for rows between row1 and row2 inclusive - * + * * Important caveat: assumes iteration won't touch any row > row2 - */ + */ bool Do(const TRowId row1, const TRowId row2, ui64 itemsLimit, ui64 bytesLimit) const noexcept - { + { auto startRow = row1; auto endRow = row2; // Page that contains row1 auto first = Index.LookupRow(row1); if (Y_UNLIKELY(!first)) { - return true; // already out of bounds, nothing to precharge - } - + return true; // already out of bounds, nothing to precharge + } + // Page that contains row2 auto last = Index.LookupRow(row2, first); if (Y_UNLIKELY(last < first)) { last = first; endRow = Min(endRow, Index.GetLastRowId(last)); - } - + } + return DoPrecharge(first, last, startRow, endRow, true, itemsLimit, bytesLimit); - } - - /** + } + + /** * Precharges data for rows between row1 and row2 inclusive in reverse - * - * Important caveat: assumes iteration won't touch any row > row2 - */ + * + * Important caveat: assumes iteration won't touch any row > row2 + */ bool DoReverse(const TRowId row1, const TRowId row2, ui64 itemsLimit, ui64 bytesLimit) const noexcept - { + { auto startRow = row1; auto endRow = row2; - // Page that contains row1 + // Page that contains row1 auto first = Index.LookupRow(row1); - if (Y_UNLIKELY(!first)) { + if (Y_UNLIKELY(!first)) { // Looks like row1 is out of bounds, start from the last row startRow = Min(row1, Index.GetEndRowId() - 1); first = --Index->End(); if (Y_UNLIKELY(!first)) { return true; // empty index? } - } - - // Page that contains row2 + } + + // Page that contains row2 auto last = Index.LookupRow(row2, first); if (Y_UNLIKELY(last > first)) { last = first; // will not go past the first page endRow = Max(endRow, last->GetRowId()); - } - + } + return DoPrechargeReverse(first, last, startRow, endRow, true, itemsLimit, bytesLimit); - } - - /** - * Precharges data for rows between max(key1, row1) and min(key2, row2) inclusive - */ - TResult Do(const TCells key1, const TCells key2, const TRowId row1, + } + + /** + * Precharges data for rows between max(key1, row1) and min(key2, row2) inclusive + */ + TResult Do(const TCells key1, const TCells key2, const TRowId row1, const TRowId row2, const TKeyNulls &nulls, ui64 itemsLimit, - ui64 bytesLimit) const noexcept - { - auto startRow = row1; + ui64 bytesLimit) const noexcept + { + auto startRow = row1; auto endRow = row2; bool firstPageLimits = true; - bool overshot = !key2; // +inf is always on the next slice - - // First page to precharge (contains row1) + bool overshot = !key2; // +inf is always on the next slice + + // First page to precharge (contains row1) auto first = Index.LookupRow(row1); - if (Y_UNLIKELY(!first)) { - return { true, true }; // already out of bounds, nothing to precharge - } - - // First extra page to precharge (when key placement is uncertain) - auto firstExt = first; - - // Last page to precharge (contains row2) + if (Y_UNLIKELY(!first)) { + return { true, true }; // already out of bounds, nothing to precharge + } + + // First extra page to precharge (when key placement is uncertain) + auto firstExt = first; + + // Last page to precharge (contains row2) auto last = Index.LookupRow(row2, first); if (Y_UNLIKELY(last < first)) { - last = first; // will not go past the first page + last = first; // will not go past the first page endRow = Min(endRow, Index.GetLastRowId(last)); - } - - if (key1) { - // First page to precharge (may contain key >= key1) + } + + if (key1) { + // First page to precharge (may contain key >= key1) auto keyPage = Index.LookupKey(key1, Scheme.Groups[0], ESeek::Lower, &nulls); if (!keyPage || keyPage > last) { - return { true, true }; // first key is outside of bounds - } + return { true, true }; // first key is outside of bounds + } if (first <= keyPage) { - first = keyPage; // use the maximum - firstExt = keyPage + 1; // first key >= key1 might be on the next page + first = keyPage; // use the maximum + firstExt = keyPage + 1; // first key >= key1 might be on the next page startRow = Max(startRow, keyPage->GetRowId()); firstPageLimits = false; // might find key1 after row1, don't count those rows if (!firstExt || last < firstExt) { firstExt = last; // never precharge past the last page - overshot = true; // may have to touch the next slice - } - } - } - - if (key2) { + overshot = true; // may have to touch the next slice + } + } + } + + if (key2) { // Last page to precharge (may contain key >= key2) // We actually use the next page since lookup is not exact auto keyPage = Index.LookupKey(key2, Scheme.Groups[0], ESeek::Lower, &nulls) + 1; if (keyPage && keyPage <= last) { if (keyPage >= firstExt) { - last = keyPage; // precharge up to keyPage - } else { - last = firstExt; // precharge up to firstExt - } + last = keyPage; // precharge up to keyPage + } else { + last = firstExt; // precharge up to firstExt + } endRow = Min(endRow, last->GetRowId()); // may load the first row of keyPage - } else { - overshot = true; // may find key > key2 on row > row2 - } - } - + } else { + overshot = true; // may find key > key2 on row > row2 + } + } + bool ready = DoPrecharge(first, last, startRow, endRow, firstPageLimits, itemsLimit, bytesLimit); - - return { ready, overshot }; - } - + + return { ready, overshot }; + } + /** * Precharges data for rows between min(key1, row1) and max(key2, row2) inclusive in reverse */ @@ -411,22 +411,22 @@ namespace NTable { return { ready, overshot }; } - private: - /** - * Precharges data from first to last page inclusive - * - * Assumes worst case first page will start iteration from startRowId + private: + /** + * Precharges data from first to last page inclusive + * + * Assumes worst case first page will start iteration from startRowId * Assumes worst case last page will end iteration on endRowId - */ - bool DoPrecharge(NPage::TIndex::TIter first, NPage::TIndex::TIter last, + */ + bool DoPrecharge(NPage::TIndex::TIter first, NPage::TIndex::TIter last, TRowId startRowId, TRowId endRowId, bool firstPageLimits, ui64 itemsLimit, ui64 bytesLimit) const noexcept - { - bool ready = true; - - if (first) { + { + bool ready = true; + + if (first) { Y_VERIFY_DEBUG(first <= last); - + ui64 items = 0; ui64 bytes = 0; @@ -434,8 +434,8 @@ namespace NTable { for (;;) { auto page = first->GetPageId(); - ready &= bool(Env->TryGetPage(Part, page)); - + ready &= bool(Env->TryGetPage(Part, page)); + if (Groups) { auto next = first; ++next; @@ -462,8 +462,8 @@ namespace NTable { // Make sure first points after the precharged page ++first; break; - } - + } + if (!++first) { // Next page doesn't exist for some reason break; @@ -471,19 +471,19 @@ namespace NTable { if (itemsLimit && firstPageLimits && first->GetRowId() > startRowId) { items += first->GetRowId() - startRowId; - if (items > itemsLimit) - break; - } - - if (bytesLimit) { + if (items > itemsLimit) + break; + } + + if (bytesLimit) { bytes += Part->GetPageSize(page); - if (bytes > bytesLimit) - break; - } - + if (bytes > bytesLimit) + break; + } + startRowId = first->GetRowId(); firstPageLimits = true; - } + } if (HistoryIndex) { TRowId prechargedLastRowId = Min( @@ -492,11 +492,11 @@ namespace NTable { ready &= DoPrechargeHistory(prechargedFirstRowId, prechargedLastRowId); } - } - - return ready; - } - + } + + return ready; + } + /** * Precharges data from first to last page inclusive in reverse * @@ -567,7 +567,7 @@ namespace NTable { return ready; } - private: + private: bool DoPrechargeHistory(TRowId startRowId, TRowId endRowId) const noexcept { using TCells = NPage::TCells; @@ -723,14 +723,14 @@ namespace NTable { } private: - IPages * const Env = nullptr; - const TPart * const Part = nullptr; - const TPartScheme &Scheme; - const NPage::TIndex &Index; + IPages * const Env = nullptr; + const TPart * const Part = nullptr; + const TPartScheme &Scheme; + const NPage::TIndex &Index; const NPage::TIndex* const HistoryIndex; mutable TSmallVec<TGroupState> Groups; mutable TSmallVec<TGroupState> HistoryGroups; - }; + }; -} -} +} +} diff --git a/ydb/core/tablet_flat/flat_part_dump.cpp b/ydb/core/tablet_flat/flat_part_dump.cpp index b10f2865e8..2cbd8dea56 100644 --- a/ydb/core/tablet_flat/flat_part_dump.cpp +++ b/ydb/core/tablet_flat/flat_part_dump.cpp @@ -1,251 +1,251 @@ -#include "flat_part_dump.h" -#include "flat_part_iface.h" -#include "flat_page_index.h" -#include "flat_page_data.h" -#include "flat_page_frames.h" -#include "flat_page_blobs.h" -#include "flat_page_bloom.h" -#include "util_fmt_desc.h" -#include <util/stream/printf.h> - +#include "flat_part_dump.h" +#include "flat_part_iface.h" +#include "flat_page_index.h" +#include "flat_page_data.h" +#include "flat_page_frames.h" +#include "flat_page_blobs.h" +#include "flat_page_bloom.h" +#include "util_fmt_desc.h" +#include <util/stream/printf.h> + #include <ydb/core/scheme/scheme_tablecell.h> #include <ydb/core/scheme/scheme_type_registry.h> - -namespace NKikimr { -namespace NTable { - -namespace { + +namespace NKikimr { +namespace NTable { + +namespace { const NPage::TFrames::TEntry& GetFrame(const TPart &part, ui64 ref, TCellOp op) - { - static NPage::TFrames::TEntry None{ Max<TRowId>(), Max<ui16>(), 0, 0 }; - + { + static NPage::TFrames::TEntry None{ Max<TRowId>(), Max<ui16>(), 0, 0 }; + if (op == ELargeObj::Outer && part.Small) { - return part.Small->Relation(ref); + return part.Small->Relation(ref); } else if (op == ELargeObj::Extern && part.Large) { - return part.Large->Relation(ref); - } - - return None; - } -} - - TDump::TDump(IOut &out, IPages *env, const TReg *reg) - : Out(out) - , Env(env) - , Reg(reg) - { - - } - - TDump::~TDump() { } - - void TDump::Part(const TPart &part, ui32 depth) noexcept - { - Out << NFmt::Do(part) << " data " << part.DataSize() << "b" << Endl; - - if (auto *frames = part.Small.Get()) Dump(*frames, "Small"); - if (auto *frames = part.Large.Get()) Dump(*frames, "Large"); - if (auto *blobs = part.Blobs.Get()) Dump(*blobs); - if (auto *bloom = part.ByKey.Get()) Dump(*bloom); - - Index(part, depth); - - if (depth > 2) { - for (auto iter = part.Index->Begin(); iter; ++iter) { - Out << Endl; - + return part.Large->Relation(ref); + } + + return None; + } +} + + TDump::TDump(IOut &out, IPages *env, const TReg *reg) + : Out(out) + , Env(env) + , Reg(reg) + { + + } + + TDump::~TDump() { } + + void TDump::Part(const TPart &part, ui32 depth) noexcept + { + Out << NFmt::Do(part) << " data " << part.DataSize() << "b" << Endl; + + if (auto *frames = part.Small.Get()) Dump(*frames, "Small"); + if (auto *frames = part.Large.Get()) Dump(*frames, "Large"); + if (auto *blobs = part.Blobs.Get()) Dump(*blobs); + if (auto *bloom = part.ByKey.Get()) Dump(*bloom); + + Index(part, depth); + + if (depth > 2) { + for (auto iter = part.Index->Begin(); iter; ++iter) { + Out << Endl; + DataPage(part, iter->GetPageId()); - } - } - } - - void TDump::Dump(const NPage::TFrames &page, const char *tag) noexcept - { - Out - << " + " << tag << " Label{" << page.Raw.size() << "b}" - << " (" << page.Stats().Items << ", " << page.Stats().Size << "b)" + } + } + } + + void TDump::Dump(const NPage::TFrames &page, const char *tag) noexcept + { + Out + << " + " << tag << " Label{" << page.Raw.size() << "b}" + << " (" << page.Stats().Items << ", " << page.Stats().Size << "b)" << " " << page.Stats().Rows << "r " << page.Stats().Tags.size() << " tags" - << Endl; - } - + << Endl; + } + void TDump::Dump(const NPage::TExtBlobs &page) noexcept - { - Out - << " + Blobs Label{" << page.Raw.size() << "b} " - << "(" << page.Stats().Items - << ", " << page.Stats().Bytes << "b) refs" - << Endl; - } - - void TDump::Dump(const NPage::TBloom &page) noexcept - { - Out - << " + Bloom Label{" << page.Raw.size() << "b} " - << page.Stats().Items << " bits, " - << page.Stats().Hashes << " hashes" - << Endl; - } - - void TDump::Index(const TPart &part, ui32 depth) noexcept - { + { + Out + << " + Blobs Label{" << page.Raw.size() << "b} " + << "(" << page.Stats().Items + << ", " << page.Stats().Bytes << "b) refs" + << Endl; + } + + void TDump::Dump(const NPage::TBloom &page) noexcept + { + Out + << " + Bloom Label{" << page.Raw.size() << "b} " + << page.Stats().Items << " bits, " + << page.Stats().Hashes << " hashes" + << Endl; + } + + void TDump::Index(const TPart &part, ui32 depth) noexcept + { Key.reserve(part.Scheme->Groups[0].KeyTypes.size()); - - auto *label = part.Index.Label(); - - const auto items = (part.Index->End() - part.Index->Begin()); - - Out - << " + Index{" << (ui16)label->Type << " rev " - << label->Format << ", " << label->Size << "b}" - << " " << items << " rec" << Endl - << " | Page Row Bytes ("; - + + auto *label = part.Index.Label(); + + const auto items = (part.Index->End() - part.Index->Begin()); + + Out + << " + Index{" << (ui16)label->Type << " rev " + << label->Format << ", " << label->Size << "b}" + << " " << items << " rec" << Endl + << " | Page Row Bytes ("; + for (auto off : xrange(part.Scheme->Groups[0].KeyTypes.size())) { - Out << (off ? ", " : ""); - + Out << (off ? ", " : ""); + TName(part.Scheme->Groups[0].KeyTypes[off]); - } - - Out << ")" << Endl; - - ssize_t seen = 0; - - for (auto iter = part.Index->Begin(); iter; ++iter) { - Key.clear(); - - if (depth < 2 && (seen += 1) > 10) { - Out - << " | -- skipped " << (items - Min(items, seen - 1)) - << " entries, depth level " << depth << Endl; - - break; - } - + } + + Out << ")" << Endl; + + ssize_t seen = 0; + + for (auto iter = part.Index->Begin(); iter; ++iter) { + Key.clear(); + + if (depth < 2 && (seen += 1) > 10) { + Out + << " | -- skipped " << (items - Min(items, seen - 1)) + << " entries, depth level " << depth << Endl; + + break; + } + for (const auto &info: part.Scheme->Groups[0].ColsKeyIdx) - Key.push_back(iter->Cell(info)); - - Out - << " | " << (Printf(Out, " %4u", iter->GetPageId()), " ") - << (Printf(Out, " %6lu", iter->GetRowId()), " "); - - if (auto *page = Env->TryGetPage(&part, iter->GetPageId())) { - Printf(Out, " %6zub ", page->size()); - } else { - Out << "~none~ "; - } - - DumpKey(*part.Scheme); - - Out << Endl; - } - } - + Key.push_back(iter->Cell(info)); + + Out + << " | " << (Printf(Out, " %4u", iter->GetPageId()), " ") + << (Printf(Out, " %6lu", iter->GetRowId()), " "); + + if (auto *page = Env->TryGetPage(&part, iter->GetPageId())) { + Printf(Out, " %6zub ", page->size()); + } else { + Out << "~none~ "; + } + + DumpKey(*part.Scheme); + + Out << Endl; + } + } + void TDump::DataPage(const TPart &part, ui32 page) noexcept - { + { // TODO: need to join with other column groups auto data = NPage::TDataPage(Env->TryGetPage(&part, page)); - - if (auto *label = data.Label()) { - Out - << " + Rows{" << page << "} Label{" << page << (ui16)label->Type - << " rev " << label->Format << ", " << label->Size << "b}" - << ", [" << data.BaseRow() << ", +" << data->Records << ")row" - << Endl; - - } else { - Out << " | " << page << " NOT_LOADED" << Endl; - - return; - } - - for (auto iter = data->Begin(); iter; ++iter) { - Key.clear(); + + if (auto *label = data.Label()) { + Out + << " + Rows{" << page << "} Label{" << page << (ui16)label->Type + << " rev " << label->Format << ", " << label->Size << "b}" + << ", [" << data.BaseRow() << ", +" << data->Records << ")row" + << Endl; + + } else { + Out << " | " << page << " NOT_LOADED" << Endl; + + return; + } + + for (auto iter = data->Begin(); iter; ++iter) { + Key.clear(); for (const auto &info: part.Scheme->Groups[0].ColsKeyData) - Key.push_back(iter->Cell(info)); - + Key.push_back(iter->Cell(info)); + Out << " | ERowOp " << int(iter->GetRop()) << ": "; - - DumpKey(*part.Scheme); - - bool first = true; - + + DumpKey(*part.Scheme); + + bool first = true; + for (const auto &info : part.Scheme->Groups[0].Columns) { - if (info.IsKey()) - continue; - - const auto op = iter->GetOp(info); - + if (info.IsKey()) + continue; + + const auto op = iter->GetOp(info); + if (op == ECellOp::Empty) - continue; - - Out - << (std::exchange(first, false) ? " " : ", ") - << "{" << EOpToStr(op) << " " << info.Tag << " "; - + continue; + + Out + << (std::exchange(first, false) ? " " : ", ") + << "{" << EOpToStr(op) << " " << info.Tag << " "; + if (op == ELargeObj::Inline) { - Out - << DbgPrintCell(iter->Cell(info), info.TypeId, *Reg); - } else { - const auto ref = iter->Cell(info).AsValue<ui64>(); - - TName(info.TypeId); - - const auto frame = GetFrame(part, ref, op); - const auto blob = Env->Locate(&part, ref, op); - + Out + << DbgPrintCell(iter->Cell(info), info.TypeId, *Reg); + } else { + const auto ref = iter->Cell(info).AsValue<ui64>(); + + TName(info.TypeId); + + const auto frame = GetFrame(part, ref, op); + const auto blob = Env->Locate(&part, ref, op); + Out << " ELargeObj{" << int(ELargeObj(op)) << ", " << ref << ": "; - - if (auto bytes = frame.Size) { - Out << "frm " << bytes << "b"; - } else { - Out << "nof"; - } - - if (auto bytes = (blob ? blob.Page->size() : 0)) { - Out << " raw " << bytes << "b"; - } else { - Out << " -"; - } - - if (frame.Size && blob && frame.Size != blob.Page->size()) { - Out << " **"; /* error indicator */ - } - - Out << "}"; - } - - Out << "}"; - } - - Out << Endl; - } - } - - void TDump::TName(ui32 num) noexcept - { - const auto &type = Reg->GetType(num); - - if (type.IsKnownType()) { - Out << type->GetName(); - } else { - Out << "Type?" << num; - } - } - - void TDump::DumpKey(const TPartScheme &scheme) noexcept - { - Out << "("; - - for (auto off : xrange(Key.size())) { - TString str; - + + if (auto bytes = frame.Size) { + Out << "frm " << bytes << "b"; + } else { + Out << "nof"; + } + + if (auto bytes = (blob ? blob.Page->size() : 0)) { + Out << " raw " << bytes << "b"; + } else { + Out << " -"; + } + + if (frame.Size && blob && frame.Size != blob.Page->size()) { + Out << " **"; /* error indicator */ + } + + Out << "}"; + } + + Out << "}"; + } + + Out << Endl; + } + } + + void TDump::TName(ui32 num) noexcept + { + const auto &type = Reg->GetType(num); + + if (type.IsKnownType()) { + Out << type->GetName(); + } else { + Out << "Type?" << num; + } + } + + void TDump::DumpKey(const TPartScheme &scheme) noexcept + { + Out << "("; + + for (auto off : xrange(Key.size())) { + TString str; + DbgPrintValue(str, Key[off], scheme.Groups[0].KeyTypes[off]); - - Out << (off ? ", " : "") << str; - } - - Out << ")"; - } - -} -} + + Out << (off ? ", " : "") << str; + } + + Out << ")"; + } + +} +} diff --git a/ydb/core/tablet_flat/flat_part_dump.h b/ydb/core/tablet_flat/flat_part_dump.h index 50f89a7c7b..88f3069d82 100644 --- a/ydb/core/tablet_flat/flat_part_dump.h +++ b/ydb/core/tablet_flat/flat_part_dump.h @@ -1,34 +1,34 @@ -#pragma once - -#include "flat_table_part.h" -#include <util/stream/output.h> - -namespace NKikimr { -namespace NTable { - - class TDump { - public: - using IOut = IOutputStream; - using TReg = NScheme::TTypeRegistry; - - TDump(IOut &out, IPages *env, const TReg *reg); - ~TDump(); - - void Part(const TPart&, ui32 depth = 10) noexcept; - void Dump(const NPage::TFrames&, const char *tag) noexcept; +#pragma once + +#include "flat_table_part.h" +#include <util/stream/output.h> + +namespace NKikimr { +namespace NTable { + + class TDump { + public: + using IOut = IOutputStream; + using TReg = NScheme::TTypeRegistry; + + TDump(IOut &out, IPages *env, const TReg *reg); + ~TDump(); + + void Part(const TPart&, ui32 depth = 10) noexcept; + void Dump(const NPage::TFrames&, const char *tag) noexcept; void Dump(const NPage::TExtBlobs&) noexcept; - void Dump(const NPage::TBloom&) noexcept; - void Index(const TPart&, ui32 depth = 10) noexcept; + void Dump(const NPage::TBloom&) noexcept; + void Index(const TPart&, ui32 depth = 10) noexcept; void DataPage(const TPart&, ui32 page) noexcept; - void TName(ui32 num) noexcept; - void DumpKey(const TPartScheme&) noexcept; - - private: - IOutputStream &Out; - IPages * const Env = nullptr; - const TReg * const Reg = nullptr; - TSmallVec<TCell> Key; - }; - -} -} + void TName(ui32 num) noexcept; + void DumpKey(const TPartScheme&) noexcept; + + private: + IOutputStream &Out; + IPages * const Env = nullptr; + const TReg * const Reg = nullptr; + TSmallVec<TCell> Key; + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_part_forward.h b/ydb/core/tablet_flat/flat_part_forward.h index 8c0ec51b9a..91e9c9d375 100644 --- a/ydb/core/tablet_flat/flat_part_forward.h +++ b/ydb/core/tablet_flat/flat_part_forward.h @@ -1,40 +1,40 @@ -#pragma once - -#include "flat_table_part.h" -#include "flat_page_index.h" +#pragma once + +#include "flat_table_part.h" +#include "flat_page_index.h" #include "flat_part_slice.h" - -namespace NKikimr { -namespace NTable { - - class TForward { + +namespace NKikimr { +namespace NTable { + + class TForward { using TIndex = NPage::TIndex; using TIter = TIndex::TIter; - - public: + + public: struct TResult { TResult(TPageId pageId) noexcept : PageId(pageId) { } - - explicit operator bool() const noexcept - { - return PageId != Max<TPageId>(); - } - - operator TPageId() const noexcept - { - return PageId; - } - - TPageId PageId = Max<TPageId>(); - }; - + + explicit operator bool() const noexcept + { + return PageId != Max<TPageId>(); + } + + operator TPageId() const noexcept + { + return PageId; + } + + TPageId PageId = Max<TPageId>(); + }; + explicit TForward(const TIndex& index, ui32 trace, const TIntrusiveConstPtr<TSlices>& bounds = nullptr) - : Trace(Max(ui32(1), trace)) + : Trace(Max(ui32(1), trace)) , Tail(index->Begin()) , Head(index->Begin()) , Edge(index->Begin()) , End(index->End()) - { + { if (bounds && !bounds->empty()) { if (auto rowId = bounds->front().BeginRowId(); rowId > 0) { // Find the first page we would allow to load @@ -48,60 +48,60 @@ namespace NTable { } } } - } - - inline TPageId On(bool head = false) const noexcept - { - return PageOf(head ? Head : Edge); - } - - inline size_t Span() const noexcept - { - return Head - Tail; - } - + } + + inline TPageId On(bool head = false) const noexcept + { + return PageOf(head ? Head : Edge); + } + + inline size_t Span() const noexcept + { + return Head - Tail; + } + TResult Clean(TPageId until) noexcept - { - if (PageOf(Tail) > until) { - Y_FAIL("Part lookups goes below of its trace pages"); - } else { - const auto edgeId = Max(PageOf(Edge), until); - + { + if (PageOf(Tail) > until) { + Y_FAIL("Part lookups goes below of its trace pages"); + } else { + const auto edgeId = Max(PageOf(Edge), until); + while (Edge != End && Edge->GetPageId() < until) ++Edge; - - if (PageOf(Edge) != edgeId) - Y_FAIL("Part lookup page is out of its index"); - - if (Tail == Head) Tail = Head = Edge; - } - + + if (PageOf(Edge) != edgeId) + Y_FAIL("Part lookup page is out of its index"); + + if (Tail == Head) Tail = Head = Edge; + } + if (Tail != Head && Edge - Tail >= ssize_t(Trace)) { return (Tail++)->GetPageId(); } - + return Max<TPageId>(); - } - + } + TResult More(TPageId until) noexcept - { + { if (Head != End && ((Edge - Head >= 0) || PageOf(Head) < until)) { return (Head++)->GetPageId(); } - + return Max<TPageId>(); - } - - private: - inline TPageId PageOf(const TIter &it) const - { + } + + private: + inline TPageId PageOf(const TIter &it) const + { return it == End ? Max<TPageId>() : it->GetPageId(); - } - - public: - const ui32 Trace = 0; - - private: - TIter Tail, Head, Edge, End; - }; -} -} + } + + public: + const ui32 Trace = 0; + + private: + TIter Tail, Head, Edge, End; + }; +} +} diff --git a/ydb/core/tablet_flat/flat_part_iface.h b/ydb/core/tablet_flat/flat_part_iface.h index 9be72fc735..ba21ead220 100644 --- a/ydb/core/tablet_flat/flat_part_iface.h +++ b/ydb/core/tablet_flat/flat_part_iface.h @@ -1,8 +1,8 @@ -#pragma once - -#include "flat_page_iface.h" -#include "flat_sausage_solid.h" -#include "flat_row_eggs.h" +#pragma once + +#include "flat_page_iface.h" +#include "flat_sausage_solid.h" +#include "flat_row_eggs.h" #include "util_basics.h" #include <ydb/core/base/shared_data.h> @@ -10,65 +10,65 @@ #include <util/generic/string.h> #include <util/system/types.h> -namespace NKikimr { -namespace NTable { - +namespace NKikimr { +namespace NTable { + class TColdPart; - class TPart; + class TPart; class TMemTable; - - using TPageId = NPage::TPageId; - using EPage = NPage::EPage; - - struct ISaver { + + using TPageId = NPage::TPageId; + using EPage = NPage::EPage; + + struct ISaver { using TGlobId = NPageCollection::TGlobId; - + virtual void Save(TSharedData raw, NPage::TGroupId groupId) noexcept = 0; virtual TLargeObj Save(TRowId, ui32 tag, const TGlobId &glob) noexcept = 0; virtual TLargeObj Save(TRowId, ui32 tag, TArrayRef<const char> blob) noexcept = 0; - }; - - class IPageWriter { - public: - using EPage = NPage::EPage; - using TPageId = NPage::TPageId; - - virtual ~IPageWriter() = default; + }; + + class IPageWriter { + public: + using EPage = NPage::EPage; + using TPageId = NPage::TPageId; + + virtual ~IPageWriter() = default; virtual TPageId Write(TSharedData page, EPage type, ui32 group) = 0; virtual TPageId WriteOuter(TSharedData) noexcept = 0; virtual void WriteInplace(TPageId page, TArrayRef<const char> body) = 0; virtual NPageCollection::TGlobId WriteLarge(TString blob, ui64 ref) noexcept = 0; virtual void Finish(TString overlay) noexcept = 0; - }; - - struct IPages { + }; + + struct IPages { using ELargeObj = NTable::ELargeObj; - using TPart = NTable::TPart; + using TPart = NTable::TPart; using TMemTable = NTable::TMemTable; - using TPageId = NPage::TPageId; + using TPageId = NPage::TPageId; using TGroupId = NPage::TGroupId; - - virtual ~IPages() = default; - + + virtual ~IPages() = default; + struct TResult { - explicit operator bool() const noexcept - { - return bool(Page); - } - + explicit operator bool() const noexcept + { + return bool(Page); + } + const TSharedData* operator*() const noexcept - { - return Page; - } - - bool Need; + { + return Page; + } + + bool Need; const TSharedData *Page; - }; - + }; + virtual TResult Locate(const TMemTable*, ui64 ref, ui32 tag) noexcept = 0; virtual TResult Locate(const TPart*, ui64 ref, ELargeObj lob) noexcept = 0; virtual const TSharedData* TryGetPage(const TPart* part, TPageId id, TGroupId groupId = { }) = 0; - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_part_iter_multi.h b/ydb/core/tablet_flat/flat_part_iter_multi.h index b26d83b378..97e534b65b 100644 --- a/ydb/core/tablet_flat/flat_part_iter_multi.h +++ b/ydb/core/tablet_flat/flat_part_iter_multi.h @@ -1,6 +1,6 @@ #pragma once -#include "flat_part_iface.h" +#include "flat_part_iface.h" #include "flat_table_part.h" #include "flat_row_eggs.h" #include "flat_row_state.h" @@ -1139,10 +1139,10 @@ namespace NTable { if (ref >> (sizeof(ui32) * 8)) Y_FAIL("Upper bits of ELargeObj ref now isn't used"); if (auto blob = Env->Locate(Part, ref, op)) { - const auto got = NPage::THello().Read(**blob); - - Y_VERIFY(got == NPage::ECodec::Plain && got.Version == 0); + const auto got = NPage::THello().Read(**blob); + Y_VERIFY(got == NPage::ECodec::Plain && got.Version == 0); + row.Set(pin.To, { ECellOp(op), ELargeObj::Inline }, TCell(*got)); } else if (op == ELargeObj::Outer) { op = TCellOp(blob.Need ? ECellOp::Null : ECellOp(op), ELargeObj::Outer); diff --git a/ydb/core/tablet_flat/flat_part_keys.h b/ydb/core/tablet_flat/flat_part_keys.h index 457e5c24fb..d372dce37b 100644 --- a/ydb/core/tablet_flat/flat_part_keys.h +++ b/ydb/core/tablet_flat/flat_part_keys.h @@ -1,257 +1,257 @@ -#pragma once -#include "flat_part_iface.h" -#include "flat_part_slice.h" -#include "flat_sausage_fetch.h" -#include "flat_sausagecache.h" -#include "util_fmt_abort.h" - -namespace NKikimr { -namespace NTable { - - class TKeysEnv : public IPages { - public: +#pragma once +#include "flat_part_iface.h" +#include "flat_part_slice.h" +#include "flat_sausage_fetch.h" +#include "flat_sausagecache.h" +#include "util_fmt_abort.h" + +namespace NKikimr { +namespace NTable { + + class TKeysEnv : public IPages { + public: using TCache = NTabletFlatExecutor::TPrivatePageCache::TInfo; - + TKeysEnv(const TPart *part, TIntrusivePtr<TCache> cache) - : Part(part) - , Cache(std::move(cache)) - { - } - + : Part(part) + , Cache(std::move(cache)) + { + } + TResult Locate(const TMemTable*, ui64, ui32) noexcept override - { + { Y_FAIL("IPages::Locate(TMemTable*, ...) shouldn't be used here"); - } - + } + TResult Locate(const TPart*, ui64, ELargeObj) noexcept override - { - Y_FAIL("IPages::Locate(TPart*, ...) shouldn't be used here"); - } - + { + Y_FAIL("IPages::Locate(TPart*, ...) shouldn't be used here"); + } + const TSharedData* TryGetPage(const TPart* part, TPageId id, TGroupId groupId) override - { - Y_VERIFY(part == Part, "Unsupported part"); + { + Y_VERIFY(part == Part, "Unsupported part"); Y_VERIFY(groupId.IsMain(), "Unsupported column group"); - - if (auto* extra = ExtraPages.FindPtr(id)) { - return extra; - } else if (auto* cached = Cache->Lookup(id)) { - // Save page in case it's evicted on the next iteration - ExtraPages[id] = *cached; - return cached; - } else { - NeedPages.insert(id); - return nullptr; - } - } - - void Check(bool has) const noexcept - { - Y_VERIFY(bool(NeedPages) == has, "Loader does not have some ne"); - } - + + if (auto* extra = ExtraPages.FindPtr(id)) { + return extra; + } else if (auto* cached = Cache->Lookup(id)) { + // Save page in case it's evicted on the next iteration + ExtraPages[id] = *cached; + return cached; + } else { + NeedPages.insert(id); + return nullptr; + } + } + + void Check(bool has) const noexcept + { + Y_VERIFY(bool(NeedPages) == has, "Loader does not have some ne"); + } + TAutoPtr<NPageCollection::TFetch> GetFetches() - { - if (NeedPages) { - TVector<TPageId> pages(NeedPages.begin(), NeedPages.end()); - std::sort(pages.begin(), pages.end()); + { + if (NeedPages) { + TVector<TPageId> pages(NeedPages.begin(), NeedPages.end()); + std::sort(pages.begin(), pages.end()); return new NPageCollection::TFetch{ 0, Cache->PageCollection, std::move(pages) }; - } else { - return nullptr; - } - } - + } else { + return nullptr; + } + } + void Save(ui32 cookie, NSharedCache::TEvResult::TLoaded&& loaded) noexcept - { + { if (cookie == 0 && NeedPages.erase(loaded.PageId)) { ExtraPages[loaded.PageId] = TPinnedPageRef(loaded.Page).GetData(); Cache->Fill(std::move(loaded)); - } - } - - private: - const TPart* Part; + } + } + + private: + const TPart* Part; TIntrusivePtr<TCache> Cache; THashMap<TPageId, TSharedData> ExtraPages; - THashSet<TPageId> NeedPages; - }; - - class TKeysLoader { - public: - explicit TKeysLoader(const TPart* part, IPages* env) - : Part(part) - , Env(env) - { - - } - + THashSet<TPageId> NeedPages; + }; + + class TKeysLoader { + public: + explicit TKeysLoader(const TPart* part, IPages* env) + : Part(part) + , Env(env) + { + + } + TIntrusivePtr<TSlices> Do(TIntrusiveConstPtr<TScreen> screen) - { - if (!screen) { - // Use a full screen to simplify logic below - screen = new TScreen({ TScreen::THole(true) }); - } - + { + if (!screen) { + // Use a full screen to simplify logic below + screen = new TScreen({ TScreen::THole(true) }); + } + TIntrusivePtr<TSlices> run = new TSlices; - - bool ok = SeekLastRow(); - - for (const auto& hole : *screen) { + + bool ok = SeekLastRow(); + + for (const auto& hole : *screen) { TSlice slice; - - if (ok &= SeekRow(hole.Begin)) { - if (GetRowId() == Max<TRowId>()) { - // all subsequent holes are out of range - break; - } + + if (ok &= SeekRow(hole.Begin)) { + if (GetRowId() == Max<TRowId>()) { + // all subsequent holes are out of range + break; + } slice.FirstRowId = GetRowId(); slice.FirstKey = GetKey(); slice.FirstInclusive = true; - } - if (ok &= SeekRow(hole.End)) { - if (GetRowId() == Max<TRowId>()) { - // Prefer a true inclusive last key - if (ok &= SeekLastRow()) { + } + if (ok &= SeekRow(hole.End)) { + if (GetRowId() == Max<TRowId>()) { + // Prefer a true inclusive last key + if (ok &= SeekLastRow()) { slice.LastRowId = GetRowId(); slice.LastKey = GetKey(); slice.LastInclusive = true; - } - } else { + } + } else { slice.LastRowId = GetRowId(); slice.LastKey = GetKey(); slice.LastInclusive = false; - } - } + } + } if (ok && slice.Rows() > 0) { run->push_back(std::move(slice)); - } - } - - return ok ? std::move(run) : nullptr; - } - - private: - TRowId GetRowId() const noexcept - { - return RowId; - } - - TSerializedCellVec GetKey() const noexcept - { - return TSerializedCellVec(TSerializedCellVec::Serialize(Key)); - } - - bool SeekRow(TRowId rowId) noexcept - { - if (RowId != rowId) { - if (rowId == Max<TRowId>()) { - RowId = rowId; - Key = { }; - return true; - } - if (const auto* lastKey = Part->Index.GetLastKeyRecord()) { + } + } + + return ok ? std::move(run) : nullptr; + } + + private: + TRowId GetRowId() const noexcept + { + return RowId; + } + + TSerializedCellVec GetKey() const noexcept + { + return TSerializedCellVec(TSerializedCellVec::Serialize(Key)); + } + + bool SeekRow(TRowId rowId) noexcept + { + if (RowId != rowId) { + if (rowId == Max<TRowId>()) { + RowId = rowId; + Key = { }; + return true; + } + if (const auto* lastKey = Part->Index.GetLastKeyRecord()) { if (lastKey->GetRowId() == rowId) { - LoadIndexKey(*lastKey); - return true; + LoadIndexKey(*lastKey); + return true; } else if (lastKey->GetRowId() < rowId) { - // Row is out of range for this part - RowId = Max<TRowId>(); - Key = { }; - return true; - } - } - SeekIndex(rowId); + // Row is out of range for this part + RowId = Max<TRowId>(); + Key = { }; + return true; + } + } + SeekIndex(rowId); if (Index->GetRowId() == rowId) { - LoadIndexKey(*Index); - return true; - } + LoadIndexKey(*Index); + return true; + } Y_VERIFY(Index->GetRowId() < rowId, "SeekIndex invariant failure"); if (!LoadPage(Index->GetPageId())) { - return false; - } + return false; + } Y_VERIFY(Page.BaseRow() == Index->GetRowId(), "Index and data are out of sync"); - auto lastRowId = Page.BaseRow() + (Page->Records - 1); - if (lastRowId < rowId) { - // Row is out of range for this page - RowId = Max<TRowId>(); - Key = { }; - return true; - } - LoadRow(rowId); - } - return true; - } - - bool SeekLastRow() noexcept - { - if (const auto* lastKey = Part->Index.GetLastKeyRecord()) { - LoadIndexKey(*lastKey); - return true; - } - auto it = Part->Index->End(); - Y_VERIFY(--it, "Unexpected failure to find the last index record"); + auto lastRowId = Page.BaseRow() + (Page->Records - 1); + if (lastRowId < rowId) { + // Row is out of range for this page + RowId = Max<TRowId>(); + Key = { }; + return true; + } + LoadRow(rowId); + } + return true; + } + + bool SeekLastRow() noexcept + { + if (const auto* lastKey = Part->Index.GetLastKeyRecord()) { + LoadIndexKey(*lastKey); + return true; + } + auto it = Part->Index->End(); + Y_VERIFY(--it, "Unexpected failure to find the last index record"); if (!LoadPage(it->GetPageId())) { - return false; - } + return false; + } Y_VERIFY(Page.BaseRow() == it->GetRowId(), "Index and data are out of sync"); - auto lastRowId = Page.BaseRow() + (Page->Records - 1); - LoadRow(lastRowId); - return true; - } - - void SeekIndex(TRowId rowId) noexcept - { + auto lastRowId = Page.BaseRow() + (Page->Records - 1); + LoadRow(lastRowId); + return true; + } + + void SeekIndex(TRowId rowId) noexcept + { Index = Part->Index.LookupRow(rowId, Index); - Y_VERIFY(Index, "SeekIndex called with an out of bounds row"); - } - - bool LoadPage(TPageId pageId) noexcept - { - Y_VERIFY(pageId != Max<TPageId>(), "Unexpected seek to an invalid page id"); - if (PageId != pageId) { - if (auto* data = Env->TryGetPage(Part, pageId)) { - Y_VERIFY(Page.Set(data), "Unexpected failure to load data page"); - PageId = pageId; - } else { - return false; - } - } - return true; - } - - void LoadRow(TRowId rowId) noexcept - { - if (RowId != rowId) { - auto it = Page->Begin() + (rowId - Page.BaseRow()); - Y_VERIFY(it, "Unexpected failure to find row on the data page"); - Key.clear(); + Y_VERIFY(Index, "SeekIndex called with an out of bounds row"); + } + + bool LoadPage(TPageId pageId) noexcept + { + Y_VERIFY(pageId != Max<TPageId>(), "Unexpected seek to an invalid page id"); + if (PageId != pageId) { + if (auto* data = Env->TryGetPage(Part, pageId)) { + Y_VERIFY(Page.Set(data), "Unexpected failure to load data page"); + PageId = pageId; + } else { + return false; + } + } + return true; + } + + void LoadRow(TRowId rowId) noexcept + { + if (RowId != rowId) { + auto it = Page->Begin() + (rowId - Page.BaseRow()); + Y_VERIFY(it, "Unexpected failure to find row on the data page"); + Key.clear(); for (const auto& info : Part->Scheme->Groups[0].ColsKeyData) { - Key.push_back(it->Cell(info)); - } - RowId = rowId; - } - } - - void LoadIndexKey(const NPage::TIndex::TRecord& record) noexcept - { + Key.push_back(it->Cell(info)); + } + RowId = rowId; + } + } + + void LoadIndexKey(const NPage::TIndex::TRecord& record) noexcept + { if (RowId != record.GetRowId()) { - Key.clear(); + Key.clear(); for (const auto& info : Part->Scheme->Groups[0].ColsKeyIdx) { - Key.push_back(record.Cell(info)); - } + Key.push_back(record.Cell(info)); + } RowId = record.GetRowId(); - } - } - - private: - const TPart* Part; - IPages* Env; - TRowId RowId = Max<TRowId>(); - TPageId PageId = Max<TPageId>(); - NPage::TIndex::TIter Index; + } + } + + private: + const TPart* Part; + IPages* Env; + TRowId RowId = Max<TRowId>(); + TPageId PageId = Max<TPageId>(); + NPage::TIndex::TIter Index; NPage::TDataPage Page; - TSmallVec<TCell> Key; - }; - -} -} + TSmallVec<TCell> Key; + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_part_laid.h b/ydb/core/tablet_flat/flat_part_laid.h index 50aec4bcb1..c3bc15570b 100644 --- a/ydb/core/tablet_flat/flat_part_laid.h +++ b/ydb/core/tablet_flat/flat_part_laid.h @@ -1,43 +1,43 @@ -#pragma once - -#include "flat_table_part.h" -#include "flat_part_screen.h" +#pragma once + +#include "flat_table_part.h" +#include "flat_part_screen.h" #include "flat_part_slice.h" #include "util_basics.h" - -namespace NKikimr { -namespace NTable { - + +namespace NKikimr { +namespace NTable { + using TBundleSlicesMap = THashMap<TLogoBlobID, TIntrusiveConstPtr<TSlices>>; struct TPartView { - explicit operator bool() const - { - return bool(Part); - } - - const TPart& operator*() const - { - return *Part; - } - - const TPart* operator->() const - { - return Part.Get(); - } - - template<typename TSub> - const TSub* As() const - { - return dynamic_cast<const TSub*>(Part.Get()); - } - - template<typename TSub> - TIntrusiveConstPtr<TSub> Ref() const - { - return const_cast<TSub*>(As<TSub>()); - } - + explicit operator bool() const + { + return bool(Part); + } + + const TPart& operator*() const + { + return *Part; + } + + const TPart* operator->() const + { + return Part.Get(); + } + + template<typename TSub> + const TSub* As() const + { + return dynamic_cast<const TSub*>(Part.Get()); + } + + template<typename TSub> + TIntrusiveConstPtr<TSub> Ref() const + { + return const_cast<TSub*>(As<TSub>()); + } + TEpoch Epoch() const { return Part ? Part->Epoch : TEpoch::Max(); @@ -50,24 +50,24 @@ namespace NTable { TIntrusiveConstPtr<TPart> Part; TIntrusiveConstPtr<TScreen> Screen; TIntrusiveConstPtr<TSlices> Slices; - }; - - struct TWritten { - explicit operator bool() const noexcept - { - return Rows > 0; - } - - /*_ Some writer stats collection */ - - ui64 Rows = 0; - ui64 Bytes = 0; /* Raw (unencoded) data pages size */ - ui64 Coded = 0; /* Data pages size after encoding */ + }; + + struct TWritten { + explicit operator bool() const noexcept + { + return Rows > 0; + } + + /*_ Some writer stats collection */ + + ui64 Rows = 0; + ui64 Bytes = 0; /* Raw (unencoded) data pages size */ + ui64 Coded = 0; /* Data pages size after encoding */ ui64 Drops = 0; /* Total rows with ERowOp::Erase code */ ui64 Parts = 0; /* Total number of produced parts */ ui64 HiddenRows = 0; /* Hidden (non-head) total rows */ ui64 HiddenDrops = 0; /* Hidden (non-head) rows with ERowOp::Erase */ - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_part_loader.cpp b/ydb/core/tablet_flat/flat_part_loader.cpp index 1e09175596..b1a37b2552 100644 --- a/ydb/core/tablet_flat/flat_part_loader.cpp +++ b/ydb/core/tablet_flat/flat_part_loader.cpp @@ -1,10 +1,10 @@ #include "flat_part_loader.h" -#include "flat_abi_check.h" -#include "flat_part_overlay.h" -#include "flat_part_keys.h" -#include "util_fmt_abort.h" +#include "flat_abi_check.h" +#include "flat_part_overlay.h" +#include "flat_part_keys.h" +#include "util_fmt_abort.h" -#include <typeinfo> +#include <typeinfo> namespace NKikimr { namespace NTable { @@ -15,32 +15,32 @@ TLoader::TLoader(TVector<TIntrusivePtr<TCache>> pageCollections, TVector<TString> deltas, TEpoch epoch) : Packs(std::move(pageCollections)) - , Legacy(std::move(legacy)) - , Opaque(std::move(opaque)) + , Legacy(std::move(legacy)) + , Opaque(std::move(opaque)) , Deltas(std::move(deltas)) , Epoch(epoch) -{ +{ if (Packs.size() < 1) { Y_Fail("Cannot load TPart from " << Packs.size() << " page collections"); } -} - -TLoader::~TLoader() { } - +} + +TLoader::~TLoader() { } + void TLoader::StageParseMeta() noexcept { auto* metaPacket = dynamic_cast<const NPageCollection::TPageCollection*>(Packs.at(0)->PageCollection.Get()); if (!metaPacket) { Y_Fail("Unexpected IPageCollection type " << TypeName(*Packs.at(0)->PageCollection)); - } + } auto &meta = metaPacket->Meta; - TPageId pageId = meta.TotalPages(); + TPageId pageId = meta.TotalPages(); Y_VERIFY(pageId > 0, "Got page collection without pages"); - if (EPage(meta.Page(pageId - 1).Type) == EPage::Schem2) { + if (EPage(meta.Page(pageId - 1).Type) == EPage::Schem2) { /* New styled page collection with layout meta. Later root meta will be placed in page collection metablob, now it is placed as inplace data for EPage::Schem2, have to be the last page. @@ -48,12 +48,12 @@ void TLoader::StageParseMeta() noexcept Rooted = true, SchemeId = pageId - 1; - ParseMeta(meta.GetPageInplaceData(SchemeId)); + ParseMeta(meta.GetPageInplaceData(SchemeId)); Y_VERIFY(Root.HasLayout(), "Rooted page collection has no layout"); if (auto *abi = Root.HasEvol() ? &Root.GetEvol() : nullptr) - TAbi().Check(abi->GetTail(), abi->GetHead(), "part"); + TAbi().Check(abi->GetTail(), abi->GetHead(), "part"); const auto &layout = Root.GetLayout(); @@ -79,7 +79,7 @@ void TLoader::StageParseMeta() noexcept } else { /* legacy page collection w/o layout data, (Evolution < 14) */ do { pageId--; - auto type = EPage(meta.Page(pageId).Type); + auto type = EPage(meta.Page(pageId).Type); switch (type) { case EPage::Scheme: SchemeId = pageId; break; @@ -94,7 +94,7 @@ void TLoader::StageParseMeta() noexcept } } while (pageId && !HasBasics()); - ParseMeta(meta.GetPageInplaceData(SchemeId)); + ParseMeta(meta.GetPageInplaceData(SchemeId)); } MinRowVersion.Step = Root.GetMinRowVersion().GetStep(); @@ -103,7 +103,7 @@ void TLoader::StageParseMeta() noexcept MaxRowVersion.Step = Root.GetMaxRowVersion().GetStep(); MaxRowVersion.TxId = Root.GetMaxRowVersion().GetTxId(); - if (!HasBasics() || (Rooted && SchemeId != meta.TotalPages() - 1) + if (!HasBasics() || (Rooted && SchemeId != meta.TotalPages() - 1) || (LargeId == Max<TPageId>()) != (GlobsId == Max<TPageId>()) || (1 + GroupIndexesIds.size() + (SmallId == Max<TPageId>() ? 0 : 1)) != Packs.size()) { @@ -121,13 +121,13 @@ void TLoader::StageParseMeta() noexcept TAutoPtr<NPageCollection::TFetch> TLoader::StageCreatePartView() noexcept { Y_VERIFY(!PartView, "PartView already initialized in CreatePartView stage"); - Y_VERIFY(Packs && Packs.front()); + Y_VERIFY(Packs && Packs.front()); TVector<TPageId> load; for (auto page: { SchemeId, IndexId, GlobsId, SmallId, LargeId, ByKeyId, GarbageStatsId, TxIdStatsId }) { - if (page != Max<TPageId>() && !Packs[0]->Lookup(page)) + if (page != Max<TPageId>() && !Packs[0]->Lookup(page)) load.push_back(page); } for (auto page : GroupIndexesIds) { @@ -225,12 +225,12 @@ TAutoPtr<NPageCollection::TFetch> TLoader::StageCreatePartView() noexcept partStore->Pseudo = new TCache(partStore->Blobs); } - auto overlay = TOverlay::Decode(Legacy, Opaque); + auto overlay = TOverlay::Decode(Legacy, Opaque); PartView = { partStore, std::move(overlay.Screen), std::move(overlay.Slices) }; KeysEnv = new TKeysEnv(PartView.Part.Get(), TPartStore::Storages(PartView).at(0)); - + return nullptr; } @@ -243,22 +243,22 @@ TAutoPtr<NPageCollection::TFetch> TLoader::StageSliceBounds() noexcept return nullptr; } - KeysEnv->Check(false); /* ensure there is no pending pages to load */ + KeysEnv->Check(false); /* ensure there is no pending pages to load */ TKeysLoader loader(PartView.Part.Get(), KeysEnv.Get()); if (auto run = loader.Do(PartView.Screen)) { - KeysEnv->Check(false); /* On success there shouldn't be left loads */ + KeysEnv->Check(false); /* On success there shouldn't be left loads */ PartView.Slices = std::move(run); TOverlay{ PartView.Screen, PartView.Slices }.Validate(); - return nullptr; - } else if (auto fetches = KeysEnv->GetFetches()) { - return fetches; - } else { - Y_FAIL("Screen keys loader stalled withoud result"); + return nullptr; + } else if (auto fetches = KeysEnv->GetFetches()) { + return fetches; + } else { + Y_FAIL("Screen keys loader stalled withoud result"); } -} +} void TLoader::StageDeltas() noexcept { @@ -276,19 +276,19 @@ void TLoader::StageDeltas() noexcept } void TLoader::Save(ui64 cookie, TArrayRef<NSharedCache::TEvResult::TLoaded> blocks) noexcept -{ - Y_VERIFY(cookie == 0, "Only the leader pack is used on load"); +{ + Y_VERIFY(cookie == 0, "Only the leader pack is used on load"); if (Stage == EStage::PartView) { for (auto& loaded : blocks) { Packs[0]->Fill(std::move(loaded), true); } - } else if (Stage == EStage::Slice) { + } else if (Stage == EStage::Slice) { for (auto& loaded : blocks) { KeysEnv->Save(cookie, std::move(loaded)); } } else { - Y_Fail("Unexpected pages save on stage " << int(Stage)); + Y_Fail("Unexpected pages save on stage " << int(Stage)); } } diff --git a/ydb/core/tablet_flat/flat_part_loader.h b/ydb/core/tablet_flat/flat_part_loader.h index ab3d02d1d1..eefab7ec5d 100644 --- a/ydb/core/tablet_flat/flat_part_loader.h +++ b/ydb/core/tablet_flat/flat_part_loader.h @@ -1,61 +1,61 @@ -#pragma once -#include "defs.h" -#include "flat_part_store.h" -#include "flat_sausagecache.h" +#pragma once +#include "defs.h" +#include "flat_part_store.h" +#include "flat_sausagecache.h" #include "shared_cache_events.h" -#include "util_fmt_abort.h" +#include "util_fmt_abort.h" #include "util_basics.h" #include <ydb/core/tablet_flat/protos/flat_table_part.pb.h> #include <ydb/core/util/pb.h> #include <util/generic/hash.h> #include <util/generic/hash_set.h> -#include <util/stream/mem.h> - -namespace NKikimr { -namespace NTable { - - class TKeysEnv; - - class TLoader { +#include <util/stream/mem.h> + +namespace NKikimr { +namespace NTable { + + class TKeysEnv; + + class TLoader { public: enum class EStage : ui8 { - Meta, + Meta, PartView, - Slice, + Slice, Deltas, Result, }; using TCache = NTabletFlatExecutor::TPrivatePageCache::TInfo; - + TLoader(TPartComponents ou) : TLoader(TPartStore::Construct(std::move(ou.PageCollectionComponents)), std::move(ou.Legacy), std::move(ou.Opaque), /* no deltas */ { }, ou.Epoch) - { - - } - + { + + } + TLoader(TVector<TIntrusivePtr<TCache>>, TString legacy, TString opaque, TVector<TString> deltas = { }, TEpoch epoch = NTable::TEpoch::Max()); - ~TLoader(); - + ~TLoader(); + TVector<TAutoPtr<NPageCollection::TFetch>> Run() - { + { while (Stage < EStage::Result) { TAutoPtr<NPageCollection::TFetch> fetch; - + switch (Stage) { - case EStage::Meta: + case EStage::Meta: StageParseMeta(); break; case EStage::PartView: fetch = StageCreatePartView(); break; - case EStage::Slice: + case EStage::Slice: fetch = StageSliceBounds(); break; case EStage::Deltas: @@ -64,36 +64,36 @@ namespace NTable { default: break; } - + if (fetch) { if (!fetch->Pages) { Y_Fail("TLoader is trying to fetch 0 pages"); - } + } if (++FetchAttempts > 1) { Y_Fail("TLoader needs multiple fetches in " << Stage << " stage"); } return { fetch }; } - + FetchAttempts = 0; Stage = EStage(ui8(Stage) + 1); - } - + } + return { }; - } - + } + void Save(ui64 cookie, TArrayRef<NSharedCache::TEvResult::TLoaded>) noexcept; - constexpr static bool NeedIn(EPage page) noexcept - { - return - page == EPage::Scheme || page == EPage::Index - || page == EPage::Frames || page == EPage::Globs + constexpr static bool NeedIn(EPage page) noexcept + { + return + page == EPage::Scheme || page == EPage::Index + || page == EPage::Frames || page == EPage::Globs || page == EPage::Schem2 || page == EPage::Bloom || page == EPage::GarbageStats || page == EPage::TxIdStats; - } - + } + TPartView Result() noexcept { Y_VERIFY(Stage == EStage::Result); @@ -103,41 +103,41 @@ namespace NTable { } static TEpoch GrabEpoch(const TPartComponents &pc) - { + { Y_VERIFY(pc.PageCollectionComponents, "PartComponents should have at least one pageCollectionComponent"); Y_VERIFY(pc.PageCollectionComponents[0].Packet, "PartComponents should have a parsed meta pageCollectionComponent"); - + const auto &meta = pc.PageCollectionComponents[0].Packet->Meta; - - for (ui32 page = meta.TotalPages(); page--;) { - if (meta.GetPageType(page) == ui32(EPage::Schem2) - || meta.GetPageType(page) == ui32(EPage::Scheme)) - { - TProtoBox<NProto::TRoot> root(meta.GetPageInplaceData(page)); - - Y_VERIFY(root.HasEpoch()); - + + for (ui32 page = meta.TotalPages(); page--;) { + if (meta.GetPageType(page) == ui32(EPage::Schem2) + || meta.GetPageType(page) == ui32(EPage::Scheme)) + { + TProtoBox<NProto::TRoot> root(meta.GetPageInplaceData(page)); + + Y_VERIFY(root.HasEpoch()); + return TEpoch(root.GetEpoch()); - } - } - + } + } + Y_FAIL("Cannot locate part metadata in page collections of PartComponents"); - } - - static TLogoBlobID BlobsLabelFor(const TLogoBlobID &base) noexcept - { + } + + static TLogoBlobID BlobsLabelFor(const TLogoBlobID &base) noexcept + { /* By convention IPageCollection blobs label for page collection has the same logo - as the meta logo but Cookie + 1. Blocks writer always make a + as the meta logo but Cookie + 1. Blocks writer always make a gap between two subsequent meta TLargeGlobIds thus this value does not overlap any real TLargeGlobId leader blob. - */ - - return - TLogoBlobID( - base.TabletID(), base.Generation(), base.Step(), - base.Channel(), 0 /* size */, base.Cookie() + 1); - } - + */ + + return + TLogoBlobID( + base.TabletID(), base.Generation(), base.Step(), + base.Channel(), 0 /* size */, base.Cookie() + 1); + } + private: bool HasBasics() const noexcept { @@ -146,7 +146,7 @@ namespace NTable { const TSharedData* GetPage(TPageId page) noexcept { - return page == Max<TPageId>() ? nullptr : Packs[0]->Lookup(page); + return page == Max<TPageId>() ? nullptr : Packs[0]->Lookup(page); } void ParseMeta(TArrayRef<const char> plain) noexcept @@ -154,7 +154,7 @@ namespace NTable { TMemoryInput stream(plain.data(), plain.size()); bool parsed = Root.ParseFromArcadiaStream(&stream); Y_VERIFY(parsed && stream.Skip(1) == 0, "Cannot parse TPart meta"); - Y_VERIFY(Root.HasEpoch(), "TPart meta has no epoch info"); + Y_VERIFY(Root.HasEpoch(), "TPart meta has no epoch info"); } void StageParseMeta() noexcept; @@ -162,29 +162,29 @@ namespace NTable { TAutoPtr<NPageCollection::TFetch> StageSliceBounds() noexcept; void StageDeltas() noexcept; - private: + private: TVector<TIntrusivePtr<TCache>> Packs; - const TString Legacy; - const TString Opaque; + const TString Legacy; + const TString Opaque; const TVector<TString> Deltas; const TEpoch Epoch; - EStage Stage = EStage::Meta; + EStage Stage = EStage::Meta; ui8 FetchAttempts = 0; - bool Rooted = false; /* Has full topology metablob */ - TPageId SchemeId = Max<TPageId>(); - TPageId IndexId = Max<TPageId>(); - TPageId GlobsId = Max<TPageId>(); - TPageId LargeId = Max<TPageId>(); - TPageId SmallId = Max<TPageId>(); - TPageId ByKeyId = Max<TPageId>(); + bool Rooted = false; /* Has full topology metablob */ + TPageId SchemeId = Max<TPageId>(); + TPageId IndexId = Max<TPageId>(); + TPageId GlobsId = Max<TPageId>(); + TPageId LargeId = Max<TPageId>(); + TPageId SmallId = Max<TPageId>(); + TPageId ByKeyId = Max<TPageId>(); TPageId GarbageStatsId = Max<TPageId>(); TPageId TxIdStatsId = Max<TPageId>(); TVector<TPageId> GroupIndexesIds; TVector<TPageId> HistoricIndexesIds; TRowVersion MinRowVersion; TRowVersion MaxRowVersion; - NProto::TRoot Root; + NProto::TRoot Root; TPartView PartView; TAutoPtr<TKeysEnv> KeysEnv; - }; -}} + }; +}} diff --git a/ydb/core/tablet_flat/flat_part_outset.h b/ydb/core/tablet_flat/flat_part_outset.h index 08ffc5925e..d751b7db5d 100644 --- a/ydb/core/tablet_flat/flat_part_outset.h +++ b/ydb/core/tablet_flat/flat_part_outset.h @@ -1,12 +1,12 @@ -#pragma once - +#pragma once + #include "defs.h" -#include "flat_sausage_packet.h" -#include "flat_sausage_fetch.h" - -namespace NKikimr { -namespace NTable { - +#include "flat_sausage_packet.h" +#include "flat_sausage_fetch.h" + +namespace NKikimr { +namespace NTable { + struct TPageCollectionComponents { // fully identified by this LargeGlobId NPageCollection::TLargeGlobId LargeGlobId; @@ -15,14 +15,14 @@ namespace NTable { TVector<NPageCollection::TLoadedPage> Sticky; void ParsePacket(TSharedData meta); - }; - + }; + struct TPartComponents { - explicit operator bool() const - { + explicit operator bool() const + { return bool(PageCollectionComponents); - } - + } + // All required data for part cooking TVector<TPageCollectionComponents> PageCollectionComponents; // Legacy overlay for TPart, use Opaque @@ -33,7 +33,7 @@ namespace NTable { TEpoch Epoch; TEpoch GetEpoch() const; - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_part_overlay.cpp b/ydb/core/tablet_flat/flat_part_overlay.cpp index d0e635e807..6e567775b0 100644 --- a/ydb/core/tablet_flat/flat_part_overlay.cpp +++ b/ydb/core/tablet_flat/flat_part_overlay.cpp @@ -1,5 +1,5 @@ #include "flat_part_overlay.h" -#include "util_fmt_abort.h" +#include "util_fmt_abort.h" #include <ydb/core/tablet_flat/protos/flat_table_part.pb.h> #include <ydb/core/util/pb.h> @@ -7,9 +7,9 @@ namespace NKikimr { namespace NTable { -namespace { +namespace { TVector<TSlice> SlicesFromProto(const NProtoBuf::RepeatedPtrField<NProto::TSliceBounds>& protos) - { + { TVector<TSlice> slices; slices.reserve(protos.size()); @@ -21,13 +21,13 @@ namespace { proto.GetLastRowId(), proto.GetFirstInclusive(), proto.GetLastInclusive()); - } + } return slices; - } - + } + void SlicesToProto(TConstArrayRef<TSlice> slices, NProtoBuf::RepeatedPtrField<NProto::TSliceBounds>* protos) - { + { protos->Reserve(protos->size() + slices.size()); for (const auto& slice : slices) { @@ -38,25 +38,25 @@ namespace { proto->SetLastRowId(slice.LastRowId); proto->SetFirstInclusive(slice.FirstInclusive); proto->SetLastInclusive(slice.LastInclusive); - } - } -} - -TString TOverlay::Encode() const noexcept + } + } +} + +TString TOverlay::Encode() const noexcept { if (!Screen && !Slices) { return { }; } - NProto::TOverlay plain; + NProto::TOverlay plain; - if (Screen) { - Y_VERIFY(Screen->Size() > 0, + if (Screen) { + Y_VERIFY(Screen->Size() > 0, "Cannot serialize a screen with 0 holes"); - Screen->Validate(); + Screen->Validate(); - for (auto &hole: *Screen) { + for (auto &hole: *Screen) { plain.AddScreen(hole.Begin); plain.AddScreen(hole.End); } @@ -78,7 +78,7 @@ TString TOverlay::Encode() const noexcept TOverlay TOverlay::Decode(TArrayRef<const char> opaque, TArrayRef<const char> opaqueExt) noexcept { - TOverlay overlay; + TOverlay overlay; if (opaque || opaqueExt) { bool ok = true; @@ -123,54 +123,54 @@ TOverlay TOverlay::Decode(TArrayRef<const char> opaque, TArrayRef<const char> op return overlay; } -void TOverlay::Validate() const noexcept -{ +void TOverlay::Validate() const noexcept +{ if (Screen) { Screen->Validate(); } - + if (Slices) { Slices->Validate(); - } - + } + if (!Screen || !Slices) { - // Cannot compare screen and bounds when one is missing - return; - } - + // Cannot compare screen and bounds when one is missing + return; + } + auto screen = TScreenRowsIterator(*Screen); auto slices = TSlicesRowsIterator(*Slices); - + while (screen) { if (!slices) { Y_FAIL("Found screen hole [%lu,%lu) that has no matching slices", screen->Begin, screen->End); - } - + } + if (screen->End == Max<TRowId>()) { if (slices.HasNext()) { auto mid = *slices; ++slices; - Y_FAIL("Found screen hole [%lu,+inf) that does not match slices [%lu,%lu) and [%lu,%lu)", + Y_FAIL("Found screen hole [%lu,+inf) that does not match slices [%lu,%lu) and [%lu,%lu)", screen->Begin, mid.Begin, mid.End, slices->Begin, slices->End); - } + } if (screen->Begin != slices->Begin) { - Y_FAIL("Found screen hole [%lu,+inf) that does not match slice [%lu,%lu)", + Y_FAIL("Found screen hole [%lu,+inf) that does not match slice [%lu,%lu)", screen->Begin, slices->Begin, slices->End); - } + } } else if (!(*screen == *slices)) { - Y_FAIL("Found screen hole [%lu,%lu) that does not match slice [%lu,%lu)", + Y_FAIL("Found screen hole [%lu,%lu) that does not match slice [%lu,%lu)", screen->Begin, screen->End, slices->Begin, slices->End); - } + } ++screen; ++slices; - } - + } + if (slices) { Y_FAIL("Found slice [%lu,%lu) that has no matching screen holes", slices->Begin, slices->End); - } + } } - + void TOverlay::ApplyDelta(TArrayRef<const char> rawDelta) noexcept { NProto::TOverlayDelta plain; @@ -210,7 +210,7 @@ TString TOverlay::EncodeRemoveSlices(const TIntrusiveConstPtr<TSlices>& slices) TString encoded; Y_PROTOBUF_SUPPRESS_NODISCARD plain.SerializeToString(&encoded); return encoded; -} +} TString TOverlay::EncodeChangeSlices(TConstArrayRef<TSlice> slices) noexcept { diff --git a/ydb/core/tablet_flat/flat_part_overlay.h b/ydb/core/tablet_flat/flat_part_overlay.h index 4c6cee0e5f..96349e7267 100644 --- a/ydb/core/tablet_flat/flat_part_overlay.h +++ b/ydb/core/tablet_flat/flat_part_overlay.h @@ -7,10 +7,10 @@ namespace NKikimr { namespace NTable { - struct TOverlay { + struct TOverlay { static TOverlay Decode(TArrayRef<const char> opaque, TArrayRef<const char> ext) noexcept; - TString Encode() const noexcept; - void Validate() const noexcept; + TString Encode() const noexcept; + void Validate() const noexcept; void ApplyDelta(TArrayRef<const char> delta) noexcept; @@ -26,7 +26,7 @@ namespace NTable { TIntrusiveConstPtr<TScreen> Screen; TIntrusiveConstPtr<TSlices> Slices; - }; + }; } } diff --git a/ydb/core/tablet_flat/flat_part_pinout.h b/ydb/core/tablet_flat/flat_part_pinout.h index 1f1774cd49..0bdb2dd1e8 100644 --- a/ydb/core/tablet_flat/flat_part_pinout.h +++ b/ydb/core/tablet_flat/flat_part_pinout.h @@ -1,50 +1,50 @@ -#pragma once - -#include <util/generic/array_ref.h> -#include <util/generic/vector.h> -#include <util/generic/ptr.h> - -namespace NKikimr { -namespace NTable { - +#pragma once + +#include <util/generic/array_ref.h> +#include <util/generic/vector.h> +#include <util/generic/ptr.h> + +namespace NKikimr { +namespace NTable { + class TPinout { - public: - struct TPin { - TPin() = default; - - TPin(ui32 from, ui32 to) - : From(from) - , To(to) - { - - } - + public: + struct TPin { + TPin() = default; + + TPin(ui32 from, ui32 to) + : From(from) + , To(to) + { + + } + ui32 From; ui32 To; }; - + using TPins = TVector<TPin>; using const_iterator = TPins::const_iterator; - - TPinout() = delete; - + + TPinout() = delete; + TPinout(TVector<TPin>&& pins, TVector<ui32>&& altGroups) : Pins_(std::move(pins)) , AltGroups_(std::move(altGroups)) - { - - } - - explicit operator bool() const noexcept - { + { + + } + + explicit operator bool() const noexcept + { return bool(Pins_); - } - + } + const_iterator begin() const noexcept - { + { return Pins_.begin(); - } - + } + const_iterator end() const noexcept { return Pins_.end(); @@ -68,9 +68,9 @@ namespace NTable { return AltGroups_; } - private: + private: TVector<TPin> Pins_; TVector<ui32> AltGroups_; - }; -} -} + }; +} +} diff --git a/ydb/core/tablet_flat/flat_part_scheme.h b/ydb/core/tablet_flat/flat_part_scheme.h index 06c3681ee2..5a563b7472 100644 --- a/ydb/core/tablet_flat/flat_part_scheme.h +++ b/ydb/core/tablet_flat/flat_part_scheme.h @@ -1,38 +1,38 @@ -#pragma once - +#pragma once + #include "util_basics.h" -#include "flat_page_iface.h" -#include "flat_row_eggs.h" -#include "flat_row_column.h" +#include "flat_page_iface.h" +#include "flat_row_eggs.h" +#include "flat_row_column.h" #include "flat_row_nulls.h" -#include "flat_part_pinout.h" - +#include "flat_part_pinout.h" + #include <ydb/core/base/shared_data.h> -#include <util/generic/ptr.h> -#include <util/generic/hash.h> - -namespace NKikimr { -namespace NTable { - - using TPgSize = NPage::TSize; - - class TPartScheme: public TAtomicRefCount<TPartScheme> { - public: - struct TColumn : public TColInfo { - TColumn() = default; - - TColumn(const TColInfo &info) - : TColInfo(info) - { - - } - - TPgSize Offset = 0; - TPgSize FixedSize = 0; - bool IsFixed = true; - }; - +#include <util/generic/ptr.h> +#include <util/generic/hash.h> + +namespace NKikimr { +namespace NTable { + + using TPgSize = NPage::TSize; + + class TPartScheme: public TAtomicRefCount<TPartScheme> { + public: + struct TColumn : public TColInfo { + TColumn() = default; + + TColumn(const TColInfo &info) + : TColInfo(info) + { + + } + + TPgSize Offset = 0; + TPgSize FixedSize = 0; + bool IsFixed = true; + }; + struct TGroupInfo { /* Data page layout settings */ TPgSize FixedSize; @@ -48,25 +48,25 @@ namespace NTable { TVector<TColumn> ColsKeyIdx; }; - TPartScheme(const TPartScheme &scheme) = delete; - explicit TPartScheme(TArrayRef<const TColInfo> cols); + TPartScheme(const TPartScheme &scheme) = delete; + explicit TPartScheme(TArrayRef<const TColInfo> cols); static TIntrusiveConstPtr<TPartScheme> Parse(TArrayRef<const char>, bool labeled); - + /** * Makes a sorted pin mapping for non-key columns */ TPinout MakePinout(const TTagsRef tags, ui32 group = Max<ui32>()) const - { + { TVector<TPinout::TPin> pins; TVector<ui32> groups; - + if (tags) { pins.reserve(tags.size()); groups.reserve(tags.size()); - + for (size_t on = 0; on < tags.size(); on++) { const TColumn* col = FindColumnByTag(tags[on]); - + if (col && !col->IsKey() && (group == Max<ui32>() || group == col->Group)) @@ -77,7 +77,7 @@ namespace NTable { } } } - + auto byGroupFirst = [this](const TPinout::TPin& a, const TPinout::TPin& b) -> bool { auto aGroup = AllColumns[a.From].Group; auto bGroup = AllColumns[b.From].Group; @@ -88,21 +88,21 @@ namespace NTable { std::sort(groups.begin(), groups.end()); groups.erase(std::unique(groups.begin(), groups.end()), groups.end()); - } - + } + return TPinout(std::move(pins), std::move(groups)); - } - + } + const TColumn* FindColumnByTag(TTag tag) const - { + { auto it = Tag2DataInfo.find(tag); if (it != Tag2DataInfo.end()) { return it->second; } else { return nullptr; } - } - + } + const TGroupInfo& GetLayout(NPage::TGroupId groupId) const noexcept { Y_VERIFY(groupId.Index < Groups.size(), "Group is out of range"); @@ -115,14 +115,14 @@ namespace NTable { } TSharedData Serialize() const; - - private: - void FillKeySlots(); + + private: + void FillKeySlots(); void FillHistoricSlots(); void InitGroup(TGroupInfo& group); size_t InitInfo(TVector<TColumn>& cols, TPgSize header); - - public: + + public: TVector<TGroupInfo> Groups; TVector<TColumn> AllColumns; @@ -132,6 +132,6 @@ namespace NTable { private: THashMap<TTag, const TColumn*> Tag2DataInfo; - }; -} -} + }; +} +} diff --git a/ydb/core/tablet_flat/flat_part_screen.h b/ydb/core/tablet_flat/flat_part_screen.h index d66ad4e387..9f64e2cdfa 100644 --- a/ydb/core/tablet_flat/flat_part_screen.h +++ b/ydb/core/tablet_flat/flat_part_screen.h @@ -1,248 +1,248 @@ -#pragma once - -#include "flat_row_eggs.h" +#pragma once + +#include "flat_row_eggs.h" #include "util_basics.h" -#include <util/generic/deque.h> -#include <util/generic/vector.h> -#include <util/generic/ptr.h> - +#include <util/generic/deque.h> +#include <util/generic/vector.h> +#include <util/generic/ptr.h> + #include <numeric> -namespace NKikimr { -namespace NTable { - - class TScreen : public TAtomicRefCount<TScreen> { - public: - struct THole { - explicit THole(bool all) - : Begin(all ? 0 : Max<TRowId>()) - { - - } - - THole(TRowId begin, TRowId end) - : Begin(begin) - , End(end) - { - - } - - explicit operator bool() const - { - return Begin < End; - } - - bool operator==(const THole &hole) const - { - return Begin == hole.Begin && End == hole.End; - } - - bool Has(TRowId rowId) const - { - return Begin <= rowId && rowId < End; - } - - THole Cut(THole hole) const - { - auto begin = Max(Begin, hole.Begin); - auto end = Min(End, hole.End); - - return begin > end ? THole(false) : THole(begin, end); - } - - TRowId Begin = 0; - TRowId End = Max<TRowId>(); - }; - - struct TCook { - TDeque<THole> Unwrap() noexcept - { - Pass(Max<TRowId>()); /* will flush current hole */ - - return std::exchange(Holes, TDeque<THole>{ }); - } - - void Pass(TRowId ref) noexcept - { - Y_VERIFY(Tail <= ref, "Got page ref from the past"); - - if (Open != Max<TRowId>() && Tail != ref) { - auto begin = std::exchange(Open, Max<TRowId>()); - - Holes.emplace_back(begin, Tail); - } - - Open = Min(Open, ref); - Tail = ref + 1; - } - - private: - TRowId Open = Max<TRowId>(); - TRowId Tail = 0; - TDeque<THole> Holes; - }; - - template<typename TVec> - static TRowId Sum(const TVec &vec) noexcept - { - return - std::accumulate(vec.begin(), vec.end(), TRowId(0), - [](TRowId rows, const THole &hole) { - return rows + (hole.End - hole.Begin); - }); - } - +namespace NKikimr { +namespace NTable { + + class TScreen : public TAtomicRefCount<TScreen> { + public: + struct THole { + explicit THole(bool all) + : Begin(all ? 0 : Max<TRowId>()) + { + + } + + THole(TRowId begin, TRowId end) + : Begin(begin) + , End(end) + { + + } + + explicit operator bool() const + { + return Begin < End; + } + + bool operator==(const THole &hole) const + { + return Begin == hole.Begin && End == hole.End; + } + + bool Has(TRowId rowId) const + { + return Begin <= rowId && rowId < End; + } + + THole Cut(THole hole) const + { + auto begin = Max(Begin, hole.Begin); + auto end = Min(End, hole.End); + + return begin > end ? THole(false) : THole(begin, end); + } + + TRowId Begin = 0; + TRowId End = Max<TRowId>(); + }; + + struct TCook { + TDeque<THole> Unwrap() noexcept + { + Pass(Max<TRowId>()); /* will flush current hole */ + + return std::exchange(Holes, TDeque<THole>{ }); + } + + void Pass(TRowId ref) noexcept + { + Y_VERIFY(Tail <= ref, "Got page ref from the past"); + + if (Open != Max<TRowId>() && Tail != ref) { + auto begin = std::exchange(Open, Max<TRowId>()); + + Holes.emplace_back(begin, Tail); + } + + Open = Min(Open, ref); + Tail = ref + 1; + } + + private: + TRowId Open = Max<TRowId>(); + TRowId Tail = 0; + TDeque<THole> Holes; + }; + + template<typename TVec> + static TRowId Sum(const TVec &vec) noexcept + { + return + std::accumulate(vec.begin(), vec.end(), TRowId(0), + [](TRowId rows, const THole &hole) { + return rows + (hole.End - hole.Begin); + }); + } + using TVec = TVector<THole>; - - TScreen(TVec holes) : Holes(std::move(holes)) { } - + + TScreen(TVec holes) : Holes(std::move(holes)) { } + static THole Iter(const TIntrusiveConstPtr<TScreen> &ref, size_t &on, TRowId rowId, int dir) - { - on = ref ? ref->Lookup(rowId, dir) : Max<size_t>(); - - return ref ? ref->Hole(on) : THole(true); - } - + { + on = ref ? ref->Lookup(rowId, dir) : Max<size_t>(); + + return ref ? ref->Hole(on) : THole(true); + } + static THole Next(const TIntrusiveConstPtr<TScreen> &ref, size_t &on, int dir) + { + return ref ? ref->Hole(on += dir) : THole(false); + } + + static bool Intersects(const TScreen *scr, THole hole) + { + return bool(hole.Cut(scr ? scr->Bounds() : THole(false))); + } + + size_t Size() const noexcept + { + return Holes.size(); + } + + TVec::const_iterator begin() const + { + return Holes.begin(); + } + + TVec::const_iterator end() const + { + return Holes.end(); + } + + bool Cmp(const TScreen &screen) const noexcept + { + return + screen.Size() == Size() + && std::equal(begin(), end(), screen.begin()); + } + + size_t Lookup(TRowId rowId, int dir) const noexcept + { + Y_VERIFY(dir == +1, "Only forward direction supported"); + + auto less = [](TRowId rowId, const THole &hole) { + return rowId < hole.End; + }; + + auto it = std::upper_bound(Holes.begin(), Holes.end(), rowId, less); + + return it == Holes.end() ? Max<size_t>() : (it - Holes.begin()); + } + + THole Hole(size_t on) const noexcept + { + return on < Holes.size() ? Holes[on] : THole(false); + } + + THole Bounds() const noexcept + { + return + THole( + Holes ? Holes[0].Begin : Max<TRowId>(), + Holes ? Holes.back().End : Max<TRowId>() ); + } + + void Validate() const noexcept { - return ref ? ref->Hole(on += dir) : THole(false); - } - - static bool Intersects(const TScreen *scr, THole hole) - { - return bool(hole.Cut(scr ? scr->Bounds() : THole(false))); - } - - size_t Size() const noexcept - { - return Holes.size(); - } - - TVec::const_iterator begin() const - { - return Holes.begin(); - } - - TVec::const_iterator end() const - { - return Holes.end(); - } - - bool Cmp(const TScreen &screen) const noexcept - { - return - screen.Size() == Size() - && std::equal(begin(), end(), screen.begin()); - } - - size_t Lookup(TRowId rowId, int dir) const noexcept - { - Y_VERIFY(dir == +1, "Only forward direction supported"); - - auto less = [](TRowId rowId, const THole &hole) { - return rowId < hole.End; - }; - - auto it = std::upper_bound(Holes.begin(), Holes.end(), rowId, less); - - return it == Holes.end() ? Max<size_t>() : (it - Holes.begin()); - } - - THole Hole(size_t on) const noexcept - { - return on < Holes.size() ? Holes[on] : THole(false); - } - - THole Bounds() const noexcept - { - return - THole( - Holes ? Holes[0].Begin : Max<TRowId>(), - Holes ? Holes.back().End : Max<TRowId>() ); - } - - void Validate() const noexcept - { - TRowId last = 0; + TRowId last = 0; for (const auto &hole : Holes) { - Y_VERIFY(std::exchange(last, hole.End) <= hole.Begin, - "Screen not sorted or has intersections"); + Y_VERIFY(std::exchange(last, hole.End) <= hole.Begin, + "Screen not sorted or has intersections"); } } static TIntrusiveConstPtr<TScreen> Cut(TIntrusiveConstPtr<TScreen> scr, THole hole) noexcept - { - if (hole == THole(true)) { - return scr; - } else if (scr == nullptr || !hole) { - return hole ? new TScreen({ hole }) : new TScreen({}); - } - - auto first = scr->Lookup(hole.Begin, +1); - - if (hole.Cut(scr->Hole(first))) { - auto last = scr->Lookup(hole.End, +1); - - last = Min(last, scr->Size() - 1); - - if (hole.End <= scr->Hole(last).Begin) { - last = Max(first, last - 1); - } - - TVec sub(last - first + 1, THole(false)); - - std::copy( - scr->begin() + first, scr->begin() + last + 1, sub.begin()); - - sub.front() = hole.Cut(sub.front()); - sub.back() = hole.Cut(sub.back()); - - if (!sub.front() || !sub.back()) { - Y_FAIL("Produced trival edges on screen cutting"); - } - - return new TScreen(std::move(sub)); - - } else { - return new TScreen({ /* opaque screen */}); - } - } - + { + if (hole == THole(true)) { + return scr; + } else if (scr == nullptr || !hole) { + return hole ? new TScreen({ hole }) : new TScreen({}); + } + + auto first = scr->Lookup(hole.Begin, +1); + + if (hole.Cut(scr->Hole(first))) { + auto last = scr->Lookup(hole.End, +1); + + last = Min(last, scr->Size() - 1); + + if (hole.End <= scr->Hole(last).Begin) { + last = Max(first, last - 1); + } + + TVec sub(last - first + 1, THole(false)); + + std::copy( + scr->begin() + first, scr->begin() + last + 1, sub.begin()); + + sub.front() = hole.Cut(sub.front()); + sub.back() = hole.Cut(sub.back()); + + if (!sub.front() || !sub.back()) { + Y_FAIL("Produced trival edges on screen cutting"); + } + + return new TScreen(std::move(sub)); + + } else { + return new TScreen({ /* opaque screen */}); + } + } + static TIntrusiveConstPtr<TScreen> Join(TIntrusiveConstPtr<TScreen> one, TIntrusiveConstPtr<TScreen> two) - { - if (one == nullptr || one->Size() == 0) { - return two; - } else if (two == nullptr || two->Size() == 0) { - return one; - } else if (one->Bounds().Cut(two->Bounds())) { - Y_FAIL("Cannot join two intersecting screens"); - } else if (one->Bounds().End > two->Bounds().Begin) { - std::swap(one, two); - } - - size_t glide = (one->Bounds().End == two->Bounds().Begin ? 1 : 0); - - TVec sub(one->Size() + two->Size() - glide, THole(false)); - - std::copy(one->begin(), one->end(), sub.begin()); - - if (glide) { - sub[one->Size() - 1].End = two->begin()->End; - } - - std::copy( - two->begin() + glide, two->end(), sub.begin() + one->Size()); - - if (sub.size() != 1 || !(sub[0] == THole(true))) { - return new TScreen(std::move(sub)); - } else { - return nullptr; /* transparent screen */ - } - } - - private: + { + if (one == nullptr || one->Size() == 0) { + return two; + } else if (two == nullptr || two->Size() == 0) { + return one; + } else if (one->Bounds().Cut(two->Bounds())) { + Y_FAIL("Cannot join two intersecting screens"); + } else if (one->Bounds().End > two->Bounds().Begin) { + std::swap(one, two); + } + + size_t glide = (one->Bounds().End == two->Bounds().Begin ? 1 : 0); + + TVec sub(one->Size() + two->Size() - glide, THole(false)); + + std::copy(one->begin(), one->end(), sub.begin()); + + if (glide) { + sub[one->Size() - 1].End = two->begin()->End; + } + + std::copy( + two->begin() + glide, two->end(), sub.begin() + one->Size()); + + if (sub.size() != 1 || !(sub[0] == THole(true))) { + return new TScreen(std::move(sub)); + } else { + return nullptr; /* transparent screen */ + } + } + + private: const TVector<THole> Holes; - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_part_shrink.h b/ydb/core/tablet_flat/flat_part_shrink.h index f6c7cc6485..369d1014fb 100644 --- a/ydb/core/tablet_flat/flat_part_shrink.h +++ b/ydb/core/tablet_flat/flat_part_shrink.h @@ -1,70 +1,70 @@ -#pragma once - -#include "defs.h" -#include "flat_row_nulls.h" -#include "flat_row_celled.h" +#pragma once + +#include "defs.h" +#include "flat_row_nulls.h" +#include "flat_row_celled.h" #include "flat_part_iter_multi.h" -#include "flat_part_screen.h" -#include "flat_part_laid.h" +#include "flat_part_screen.h" +#include "flat_part_laid.h" #include "flat_stat_part.h" - -namespace NKikimr { -namespace NTable { - - class TShrink { - public: - using TCells = TArrayRef<const TCell>; - + +namespace NKikimr { +namespace NTable { + + class TShrink { + public: + using TCells = TArrayRef<const TCell>; + TShrink(IPages *env, TIntrusiveConstPtr<TKeyNulls> nulls) - : Env(env) - , Nulls(nulls) - { - - } - + : Env(env) + , Nulls(nulls) + { + + } + TShrink& Put(const TPartView &partView, TRawVals from, TRawVals to) - { + { return Put({ &partView, 1 }, from, to); - } - + } + TShrink& Put(TArrayRef<const TPartView> all, TRawVals from_, TRawVals to_) - { - const TCelled from(from_, *Nulls, false); - const TCelled to(to_, *Nulls, false); - - return Put(all, from, to); - } - + { + const TCelled from(from_, *Nulls, false); + const TCelled to(to_, *Nulls, false); + + return Put(all, from, to); + } + TShrink& Put(TArrayRef<const TPartView> all, TCells from, TCells to) - { + { for (auto &partView: all) { Y_VERIFY(partView.Slices, "Shrink attempt on a part without slices"); - if (!from && !to) /* [-inf, +inf) */ { + if (!from && !to) /* [-inf, +inf) */ { PartView.emplace_back(partView); - } else { + } else { TPartSimpleIt first(partView.Part.Get(), { }, Nulls, Env); Skipped += EReady::Page == first.Seek(from, ESeek::Lower); - + TPartSimpleIt last(partView.Part.Get(), { }, Nulls, Env); Skipped += EReady::Page == last.Seek(to, to ? ESeek::Lower : ESeek::Upper); - + auto firstRowId = first.GetRowId(); auto lastRowId = last.GetRowId(); - + if (Skipped == 0 && firstRowId < lastRowId) { auto with = TScreen::THole{ firstRowId, lastRowId }; auto screen = TScreen::Cut(partView.Screen, with); - + if (!screen || screen->Size() > 0) { auto keys = partView.Part->Scheme->Groups[0].KeyTypes.size(); - + TArrayRef<const TCell> firstKey, lastKey; firstKey = first.GetKey().Cells().Slice(0, keys); if (last.IsValid()) { lastKey = last.GetKey().Cells().Slice(0, keys); } - + auto run = TSlices::Cut( partView.Slices, firstRowId, @@ -72,25 +72,25 @@ namespace NTable { firstKey, lastKey); Y_VERIFY_DEBUG(run, "Unexpected null result"); - + if (run->size() > 0) { run->Validate(); PartView.emplace_back(TPartView{ partView.Part, screen, std::move(run) }); } } - } - } - } - - return *this; - } - - public: - IPages * const Env = nullptr; + } + } + } + + return *this; + } + + public: + IPages * const Env = nullptr; TIntrusiveConstPtr<TKeyNulls> Nulls; - size_t Skipped = 0; + size_t Skipped = 0; TVector<TPartView> PartView; - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_part_slice.cpp b/ydb/core/tablet_flat/flat_part_slice.cpp index 48755d3bf4..4b5c04924f 100644 --- a/ydb/core/tablet_flat/flat_part_slice.cpp +++ b/ydb/core/tablet_flat/flat_part_slice.cpp @@ -1,5 +1,5 @@ #include "flat_part_slice.h" -#include "util_fmt_desc.h" +#include "util_fmt_desc.h" #include <ydb/core/util/yverify_stream.h> diff --git a/ydb/core/tablet_flat/flat_part_slice.h b/ydb/core/tablet_flat/flat_part_slice.h index d0f361ef58..c5ddd3bb92 100644 --- a/ydb/core/tablet_flat/flat_part_slice.h +++ b/ydb/core/tablet_flat/flat_part_slice.h @@ -2,8 +2,8 @@ #include "flat_table_part.h" #include "flat_part_screen.h" -#include "util_fmt_desc.h" - +#include "util_fmt_desc.h" + #include <util/generic/list.h> #include <util/generic/set.h> diff --git a/ydb/core/tablet_flat/flat_part_store.h b/ydb/core/tablet_flat/flat_part_store.h index ee0bc2324b..cb76b54041 100644 --- a/ydb/core/tablet_flat/flat_part_store.h +++ b/ydb/core/tablet_flat/flat_part_store.h @@ -1,17 +1,17 @@ -#pragma once - -#include "flat_part_iface.h" -#include "flat_part_outset.h" -#include "flat_part_laid.h" -#include "flat_table_part.h" -#include "flat_store_bundle.h" -#include "flat_sausage_packet.h" -#include "flat_sausagecache.h" -#include "util_fmt_abort.h" - -namespace NKikimr { -namespace NTable { - +#pragma once + +#include "flat_part_iface.h" +#include "flat_part_outset.h" +#include "flat_part_laid.h" +#include "flat_table_part.h" +#include "flat_store_bundle.h" +#include "flat_sausage_packet.h" +#include "flat_sausagecache.h" +#include "util_fmt_abort.h" + +namespace NKikimr { +namespace NTable { + class TColdPartStore : public TColdPart { public: TColdPartStore( @@ -45,31 +45,31 @@ protected: , Pseudo(src.Pseudo) { } -public: +public: using TCache = NTabletFlatExecutor::TPrivatePageCache::TInfo; - + TPartStore(const TLogoBlobID &label, TEgg egg, TStat stat) - : TPart(label, egg, stat) - { - - } - - const TLogoBlobID& BundleId() const override - { + : TPart(label, egg, stat) + { + + } + + const TLogoBlobID& BundleId() const override + { return PageCollections[0]->PageCollection->Label(); - } - - ui64 BackingSize() const override - { + } + + ui64 BackingSize() const override + { ui64 size = 0; for (const auto &cache : PageCollections) { size += cache->PageCollection->BackingSize(); } return size; - } - - ui64 DataSize() const override - { + } + + ui64 DataSize() const override + { return BackingSize() - IndexesRawSize; } @@ -85,61 +85,61 @@ public: } const NPageCollection::TPageCollection* Packet(ui32 room) const noexcept override - { + { auto *pageCollection = room < PageCollections.size() ? PageCollections[room]->PageCollection.Get() : nullptr; - + return dynamic_cast<const NPageCollection::TPageCollection*>(pageCollection); - } - + } + TCache* Locate(ELargeObj lob, ui64 ref) const noexcept - { + { if ((lob != ELargeObj::Extern && lob != ELargeObj::Outer) || (ref >> 32)) { Y_Fail("Invalid ref ELargeObj{" << int(lob) << ", " << ref << "}"); - } - + } + return (lob == ELargeObj::Extern ? Pseudo : PageCollections.at(Groups)).Get(); - } - + } + TAutoPtr<NPageCollection::TFetch> DataPages() const noexcept - { + { TVector<TPageId> pages; - - pages.reserve(Index->End() - Index->Begin()); - + + pages.reserve(Index->End() - Index->Begin()); + auto it = Index.LookupKey({ }, Scheme->Groups[0], ESeek::Lower, nullptr); - + for (; it; ++it) pages.emplace_back(it->GetPageId()); - + return new NPageCollection::TFetch{ 0, PageCollections[0]->PageCollection , std::move(pages) }; - } - + } + static TVector<TIntrusivePtr<TCache>> Construct(TVector<TPageCollectionComponents> components) noexcept - { + { TVector<TIntrusivePtr<TCache>> caches; - + for (auto &one: components) { - caches.emplace_back(new TCache(std::move(one.Packet))); - - for (auto &page: one.Sticky) - caches.back()->Fill(page, true); - } - - return caches; - } - + caches.emplace_back(new TCache(std::move(one.Packet))); + + for (auto &page: one.Sticky) + caches.back()->Fill(page, true); + } + + return caches; + } + static TArrayRef<const TIntrusivePtr<TCache>> Storages(const TPartView &partView) noexcept - { + { auto *part = partView.As<TPartStore>(); - + Y_VERIFY(!partView || part, "Got an unexpected type of TPart part"); - + return part ? part->PageCollections : TArrayRef<const TIntrusivePtr<TCache>> { }; - } - + } + TVector<TIntrusivePtr<TCache>> PageCollections; TIntrusivePtr<TCache> Pseudo; /* Cache for NPage::TBlobs */ -}; - +}; + class TTxStatusPartStore : public TTxStatusPart, public IBorrowBundle { public: TTxStatusPartStore(const NPageCollection::TLargeGlobId& dataId, TEpoch epoch, TSharedData data) @@ -169,5 +169,5 @@ private: const NPageCollection::TLargeGlobId DataId; }; -} -} +} +} diff --git a/ydb/core/tablet_flat/flat_part_writer.h b/ydb/core/tablet_flat/flat_part_writer.h index 4e04732cd9..8f0618430a 100644 --- a/ydb/core/tablet_flat/flat_part_writer.h +++ b/ydb/core/tablet_flat/flat_part_writer.h @@ -1,45 +1,45 @@ -#pragma once - -#include "flat_abi_evol.h" -#include "flat_page_conf.h" +#pragma once + +#include "flat_abi_evol.h" +#include "flat_page_conf.h" #include "flat_page_gstat.h" #include "flat_page_txidstat.h" #include "flat_page_txstatus.h" -#include "flat_page_writer.h" -#include "flat_page_other.h" -#include "flat_part_iface.h" +#include "flat_page_writer.h" +#include "flat_page_other.h" +#include "flat_part_iface.h" #include "flat_part_overlay.h" -#include "flat_part_screen.h" +#include "flat_part_screen.h" #include "flat_part_slice.h" -#include "flat_part_laid.h" -#include "flat_row_state.h" -#include "flat_bloom_writer.h" -#include "util_fmt_abort.h" +#include "flat_part_laid.h" +#include "flat_row_state.h" +#include "flat_bloom_writer.h" +#include "util_fmt_abort.h" #include "util_deref.h" - + #include <ydb/core/tablet_flat/protos/flat_table_part.pb.h> #include <ydb/core/util/intrusive_heap.h> -#include <util/system/sanitizers.h> - -namespace NKikimr { -namespace NTable { - - class TPartWriter final : protected ISaver { - using ECodec = NPage::ECodec; - using ICodec = NBlockCodecs::ICodec; - +#include <util/system/sanitizers.h> + +namespace NKikimr { +namespace NTable { + + class TPartWriter final : protected ISaver { + using ECodec = NPage::ECodec; + using ICodec = NBlockCodecs::ICodec; + enum : size_t { GarbageStatsMaxSize = 100, GarbageStatsMaxBuildSize = 10000, }; - public: - TPartWriter() = delete; - TPartWriter(const TPartWriter&) = delete; - + public: + TPartWriter() = delete; + TPartWriter(const TPartWriter&) = delete; + TPartWriter(TIntrusiveConstPtr<TPartScheme> scheme, TTagsRef tags, IPageWriter& pager, const NPage::TConf &conf, TEpoch epoch) - : Final(conf.Final) + : Final(conf.Final) , SmallEdge(conf.SmallEdge) , LargeEdge(conf.LargeEdge) , MaxLargeBlob(conf.MaxLargeBlob) @@ -51,12 +51,12 @@ namespace NTable { , SplitKeys(conf.SplitKeys) , MinRowVersion(conf.MinRowVersion) , Scheme(scheme) - , Pager(pager) + , Pager(pager) , FrameL(tags.size()) , FrameS(tags.size()) , EraseRowState(tags.size()) , SchemeData(scheme->Serialize()) - { + { for (ui32 group : xrange(conf.Groups.size())) { Groups.emplace_back(scheme, conf, tags, NPage::TGroupId(group)); Histories.emplace_back(scheme, conf, tags, NPage::TGroupId(group, true)); @@ -64,9 +64,9 @@ namespace NTable { if (conf.ByKeyFilter) { if (MainPageCollectionEdge || SmallPageCollectionEdge || !conf.MaxRows) { - ByKey.Reset(new NBloom::TQueue(0.0001)); + ByKey.Reset(new NBloom::TQueue(0.0001)); } else { - ByKey.Reset(new NBloom::TWriter(conf.MaxRows, 0.0001)); + ByKey.Reset(new NBloom::TWriter(conf.MaxRows, 0.0001)); } } @@ -80,8 +80,8 @@ namespace NTable { // This is used to write delayed erase markers EraseRowState.Touch(ERowOp::Erase); - } - + } + void BeginKey(TCellsRef key) noexcept { Y_VERIFY(Phase == 0, "BeginKey called after Finish"); @@ -117,7 +117,7 @@ namespace NTable { } void AddKeyVersion(const TRowState& row, TRowVersion version) noexcept - { + { Y_VERIFY_DEBUG(version < KeyState.LastVersion, "Key versions must be in descending order"); if (row != ERowOp::Erase) { @@ -152,8 +152,8 @@ namespace NTable { if (KeyState.Written == 0) { return ERowOp::Absent; - } - + } + return row.GetRowState(); } @@ -172,7 +172,7 @@ namespace NTable { } else { WriteHistoryRow(row, minVersion, maxVersion); } - + ++KeyState.Written; } @@ -262,14 +262,14 @@ namespace NTable { if (KeyState.WrittenDeltas == 0 && NeedFlush()) { Flush(false); - + // Next part would not have overflow for (auto& g : Groups) { g.NextDataSize.Overflow = false; } } - Current.Rows += 1; + Current.Rows += 1; Current.Drops += (row == ERowOp::Erase || maxVersion < TRowVersion::Max() ? 1 : 0); Current.HiddenRows += (maxVersion < TRowVersion::Max() ? 1 : 0); @@ -330,10 +330,10 @@ namespace NTable { NextSliceFirstRowId = Groups[0].Data.GetLastRowId(); NextSliceFirstKey = TSerializedCellVec(TSerializedCellVec::Serialize(KeyState.Key)); } - } - + } + void WriteHistoryRow(const TRowState& row, TRowVersion minVersion, TRowVersion maxVersion) noexcept - { + { Y_VERIFY(Phase == 0, "WriteHistoryRow called after Finish"); Y_VERIFY_DEBUG(minVersion < maxVersion); @@ -465,26 +465,26 @@ namespace NTable { void Flush(bool last) noexcept { // The first group must write the last key - Y_VERIFY(std::exchange(Phase, 1) == 0, "Called twice"); - + Y_VERIFY(std::exchange(Phase, 1) == 0, "Called twice"); + for (auto& g : Groups) { g.Data.Flush(*this); } - + for (auto& g : Histories) { g.Data.Flush(*this); } if (Current.Rows > 0) { - Y_VERIFY(Phase == 2, "Missed the last Save call"); - + Y_VERIFY(Phase == 2, "Missed the last Save call"); + Result.Rows += Current.Rows; Result.Drops += Current.Drops; Result.Bytes += Current.Bytes; Result.Coded += Current.Coded; Result.HiddenRows += Current.HiddenRows; Result.HiddenDrops += Current.HiddenDrops; - + if (Current.HistoryWritten > 0) { Current.HistoricIndexes.clear(); Current.HistoricIndexes.reserve(Histories.size()); @@ -508,7 +508,7 @@ namespace NTable { if (ByKey) { Current.ByKey = WriteIf(ByKey->Make(), EPage::Bloom); } - + if (Current.GarbageStatsBuilder) { Current.GarbageStatsBuilder.ShrinkTo(GarbageStatsMaxSize); Current.GarbageStats = WriteIf(Current.GarbageStatsBuilder.Finish(), EPage::GarbageStats); @@ -520,7 +520,7 @@ namespace NTable { Current.Scheme = WritePage(SchemeData, EPage::Schem2); WriteInplace(Current.Scheme, MakeMetaBlob(last)); - + Y_VERIFY(Slices && *Slices, "Flushing bundle without a run"); Pager.Finish(TOverlay{ nullptr, std::move(Slices) }.Encode()); @@ -541,7 +541,7 @@ namespace NTable { Globs.Reset(); if (ByKey) { ByKey->Reset(); - } + } Slices.Reset(); RegisteredGlobs.clear(); @@ -555,23 +555,23 @@ namespace NTable { NextSliceFirstKey = { }; LastSliceBytes = 0; - Phase = 0; + Phase = 0; Current = { }; - } - } - + } + } + TString MakeMetaBlob(bool last) const noexcept - { - NProto::TRoot proto; - + { + NProto::TRoot proto; + proto.SetEpoch(Epoch.ToProto()); - - if (auto *abi = proto.MutableEvol()) { + + if (auto *abi = proto.MutableEvol()) { ui32 head = ui32(NTable::ECompatibility::Head); - + if (Current.Small != Max<TPageId>()) head = Max(head, ui32(15) /* ELargeObj:Outer packed blobs */); - + if (!last || Result.Parts > 0) head = Max(head, ui32(20) /* Multiple part outputs */); @@ -584,11 +584,11 @@ namespace NTable { if (Current.TxIdStatsBuilder) head = Max(head, ui32(28) /* Uncommitted deltas present */); - abi->SetTail(head); + abi->SetTail(head); abi->SetHead(ui32(NTable::ECompatibility::Edge)); - } - - if (auto *stat = proto.MutableStat()) { + } + + if (auto *stat = proto.MutableStat()) { stat->SetBytes(Current.Bytes); stat->SetCoded(Current.Coded); stat->SetDrops(Current.Drops); @@ -597,12 +597,12 @@ namespace NTable { stat->SetHiddenRows(Current.HiddenRows); stat->SetHiddenDrops(Current.HiddenDrops); } - } - - if (auto *lay = proto.MutableLayout()) { + } + + if (auto *lay = proto.MutableLayout()) { lay->SetScheme(Current.Scheme); lay->SetIndex(Current.Index); - + if (Current.Globs != Max<TPageId>()) lay->SetGlobs(Current.Globs); if (Current.Large != Max<TPageId>()) @@ -627,8 +627,8 @@ namespace NTable { if (Current.TxIdStats != Max<TPageId>()) { lay->SetTxIdStats(Current.TxIdStats); } - } - + } + // There must have been at least one row Y_VERIFY_DEBUG(Current.MinRowVersion <= Current.MaxRowVersion); @@ -649,23 +649,23 @@ namespace NTable { Y_VERIFY_DEBUG(!Current.MaxRowVersion); } - TString blob; + TString blob; Y_PROTOBUF_SUPPRESS_NODISCARD proto.SerializeToString(&blob); - - return blob; - } - + + return blob; + } + TPageId WritePage(TSharedData page, EPage type, ui32 group = 0) noexcept - { - NSan::CheckMemIsInitialized(page.data(), page.size()); - + { + NSan::CheckMemIsInitialized(page.data(), page.size()); + if (group == 0) { Current.MainWritten += page.size(); } return Pager.Write(std::move(page), type, group); - } - + } + void WriteInplace(TPageId page, TArrayRef<const char> body) noexcept { NSan::CheckMemIsInitialized(body.data(), body.size()); @@ -679,25 +679,25 @@ namespace NTable { } void Save(TSharedData raw, NPage::TGroupId groupId) noexcept override - { + { auto& g = groupId.Historic ? Histories[groupId.Index] : Groups[groupId.Index]; if (groupId.IsMain()) { Y_VERIFY(Phase < 2, "Called twice on Finish(...)"); } - Y_VERIFY(raw, "Save(...) accepts only non-trivial blobs"); - + Y_VERIFY(raw, "Save(...) accepts only non-trivial blobs"); + if (auto dataPage = NPage::TDataPage(&raw)) { TSharedData keep; /* should preserve original data for Key */ - - /* Need to extract first key from page. Just written key - columns may not hold EOp::Reset cells (and now this - isn't possible technically), thus there isn't required - TNulls object for expanding defaults. - */ - + + /* Need to extract first key from page. Just written key + columns may not hold EOp::Reset cells (and now this + isn't possible technically), thus there isn't required + TNulls object for expanding defaults. + */ + Y_VERIFY(dataPage->Records, "Invalid EPage::DataPage blob"); - + if (groupId.IsMain()) { Y_VERIFY_DEBUG(NextSliceFirstRowId != Max<TRowId>()); @@ -709,21 +709,21 @@ namespace NTable { } Current.Bytes += raw.size(); /* before encoding */ - + if (g.Codec == NPage::ECodec::Plain) { - /* Ecoding was not enabled, keep as is */ + /* Ecoding was not enabled, keep as is */ } else if (keep = Encode(raw, g.Codec, g.ForceCompression)) { - std::swap(raw, keep); - } - + std::swap(raw, keep); + } + Current.Coded += raw.size(); /* after encoding */ - + auto page = WritePage(raw, EPage::DataPage, groupId.Index); - + // N.B. non-main groups have no key Y_VERIFY_DEBUG(g.Index.CalcSize(Key) == g.FirstKeyIndexSize); g.Index.Add(g.FirstKeyIndexSize, Key, dataPage.BaseRow(), page); - + // N.B. hack to save the last row/key for the main group // SliceSize is wrong, but it's a hack for tests right now if (groupId.IsMain() && (NextSliceForce || Phase == 1 || Current.Bytes - LastSliceBytes >= SliceSize)) { @@ -734,52 +734,52 @@ namespace NTable { SaveSlice(lastRowId, TSerializedCellVec(TSerializedCellVec::Serialize(Key))); - if (Phase == 1) { + if (Phase == 1) { Y_VERIFY_DEBUG(g.Index.CalcSize(Key) == g.LastKeyIndexSize); g.Index.Add(g.LastKeyIndexSize, Key, lastRowId, page); - ++Phase; + ++Phase; } } g.FirstKeyIndexSize = 0; g.LastKeyIndexSize = 0; - } - } - + } + } + TLargeObj Save(TRowId row, ui32 tag, const TGlobId &glob) noexcept override - { - return Register(row, tag, glob); - } - + { + return Register(row, tag, glob); + } + TLargeObj Save(TRowId row, ui32 tag, TArrayRef<const char> plain) noexcept override - { + { if (plain.size() >= LargeEdge && plain.size() <= MaxLargeBlob) { auto blob = NPage::THello::WrapString(plain, EPage::Opaque, 0); ui64 ref = Globs.Size(); /* is the current blob index */ - + return Register(row, tag, Pager.WriteLarge(std::move(blob), ref)); - + } else if (plain.size() >= SmallEdge) { auto blob = NPage::THello::Wrap(plain, EPage::Opaque, 0); Current.Bytes += blob.size(); Current.Coded += blob.size(); - - FrameS.Put(row, tag, blob.size()); - + + FrameS.Put(row, tag, blob.size()); + Current.SmallWritten += blob.size(); return { ELargeObj::Outer, Pager.WriteOuter(std::move(blob)) }; - - } else { + + } else { Y_Fail("Got ELargeObj blob " << plain.size() << "b out of limits" << " { " << SmallEdge << "b, " << LargeEdge << "b }"); - } - } - + } + } + TLargeObj Register(TRowId row, ui32 tag, const TGlobId &glob) noexcept - { + { ui32 ref; - + auto it = RegisteredGlobs.find(glob.Logo); if (it != RegisteredGlobs.end()) { // It's ok to reuse, as long as the glob is on the same row and column @@ -800,50 +800,50 @@ namespace NTable { } return { ELargeObj::Extern, ref }; - } - + } + TSharedData Encode(TArrayRef<const char> page, ECodec codec, bool force) noexcept - { + { Y_VERIFY(codec == ECodec::LZ4, "Only LZ4 encoding allowed"); - + auto got = NPage::THello().Read(page, EPage::DataPage); - - Y_VERIFY(got == ECodec::Plain, "Page is already encoded"); + + Y_VERIFY(got == ECodec::Plain, "Page is already encoded"); Y_VERIFY(got.Page.data() - page.data() == 16, "Page compression would change page header size"); - + if (!CodecImpl) { CodecImpl = NBlockCodecs::Codec("lz4fast"); } auto size = CodecImpl->MaxCompressedLength(got.Page); - + TSharedData out = TSharedData::Uninitialized(size + 16 /* label */); - + size = CodecImpl->Compress(got.Page, out.mutable_begin() + 16); - + auto trimmed = out.Trim(size + 16 /* label */); if (trimmed >= out.size()) { // Make a hard copy and avoid wasting space in caches out = TSharedData::Copy(out); } - + if (!force && out.size() + (page.size() >> 3) > page.size()) { - return { }; /* Compressed page is almost the same in size */ - } else { + return { }; /* Compressed page is almost the same in size */ + } else { std::copy(page.begin(), page.begin() + 16, out.mutable_begin()); - + auto *label = TDeref<NPage::TLabel>::At(out.mutable_begin(), 0); label->SetSize(out.size()); - + *TDeref<ui8>::At(label + 1, 0) = ui8(ECodec::LZ4); - - Y_VERIFY(label->Format & 0x8000, "Unexpected label version"); - + + Y_VERIFY(label->Format & 0x8000, "Unexpected label version"); + NSan::CheckMemIsInitialized(out.data(), out.size()); return out; - } - } - + } + } + void InitKey(const NPage::TDataPage::TRecord* record, NPage::TGroupId groupId) noexcept { const auto& layout = Scheme->GetLayout(groupId); @@ -871,8 +871,8 @@ namespace NTable { LastSliceBytes = Current.Bytes; } - private: - const bool Final = false; + private: + const bool Final = false; const ui32 SmallEdge; const ui32 LargeEdge; const ui32 MaxLargeBlob; @@ -884,16 +884,16 @@ namespace NTable { NPage::ISplitKeys* const SplitKeys; const TRowVersion MinRowVersion; const TIntrusiveConstPtr<TPartScheme> Scheme; - + const ICodec *CodecImpl = nullptr; - IPageWriter& Pager; - NPage::TFrameWriter FrameL; /* Large blobs inverted index */ - NPage::TFrameWriter FrameS; /* Packed blobs invertedi index */ + IPageWriter& Pager; + NPage::TFrameWriter FrameL; /* Large blobs inverted index */ + NPage::TFrameWriter FrameS; /* Packed blobs invertedi index */ NPage::TExtBlobsWriter Globs; THolder<NBloom::IWriter> ByKey; TWritten Result; - TStackVec<TCell, 16> Key; - ui32 Phase = 0; + TStackVec<TCell, 16> Key; + ui32 Phase = 0; struct TRegisteredGlob { TRowId Row; @@ -984,6 +984,6 @@ namespace NTable { TSerializedCellVec NextSliceFirstKey; ui64 LastSliceBytes = 0; bool NextSliceForce = false; - }; - -}} + }; + +}} diff --git a/ydb/core/tablet_flat/flat_redo_layout.h b/ydb/core/tablet_flat/flat_redo_layout.h index 7a2e65403d..2fbc5d11f6 100644 --- a/ydb/core/tablet_flat/flat_redo_layout.h +++ b/ydb/core/tablet_flat/flat_redo_layout.h @@ -1,93 +1,93 @@ -#pragma once - -#include "flat_row_eggs.h" - -namespace NKikimr { -namespace NTable { -namespace NRedo { - - enum class ERedo : ui8 { - Noop = 0, - Update = 1, +#pragma once + +#include "flat_row_eggs.h" + +namespace NKikimr { +namespace NTable { +namespace NRedo { + + enum class ERedo : ui8 { + Noop = 0, + Update = 1, Erase = 2, /* Legacy ERowOp::Erase operation */ - Begin = 5, /* ABI and API evolution label */ - Annex = 6, /* Array of used external blobs */ - Flush = 8, + Begin = 5, /* ABI and API evolution label */ + Annex = 6, /* Array of used external blobs */ + Flush = 8, UpdateV = 9, UpdateTx = 10, CommitTx = 11, RemoveTx = 12, - }; - - #pragma pack(push, 1) - - /*_ Legacy, ugly, log protocol */ - - struct TChunk_Legacy { - ui32 RootId; - ui32 Size; - ERedo Op; - } Y_PACKED; - - struct TEvUpdate_Legacy { - TChunk_Legacy OpHeader; - ui32 Keys; - ui32 Ops; - } Y_PACKED; - - struct TEvErase_Legacy { - TChunk_Legacy OpHeader; - ui32 Keys; - } Y_PACKED; - - struct TEvFlush_Legacy { - TChunk_Legacy Hdr; - - ui64 TxStamp; + }; + + #pragma pack(push, 1) + + /*_ Legacy, ugly, log protocol */ + + struct TChunk_Legacy { + ui32 RootId; + ui32 Size; + ERedo Op; + } Y_PACKED; + + struct TEvUpdate_Legacy { + TChunk_Legacy OpHeader; + ui32 Keys; + ui32 Ops; + } Y_PACKED; + + struct TEvErase_Legacy { + TChunk_Legacy OpHeader; + ui32 Keys; + } Y_PACKED; + + struct TEvFlush_Legacy { + TChunk_Legacy Hdr; + + ui64 TxStamp; i64 Epoch; - ui64 Unused1_; - } Y_PACKED; - - /*_ New generic, TLV based, log */ - - struct TChunk { - ERedo Event; - ui8 Pad0_; - ui16 Pad1_; - ui32 Size; - } Y_PACKED; - - struct TEvBegin_v0 { - TChunk Label; - - ui32 Tail; - ui32 Head; - } Y_PACKED; - - struct TEvBegin_v1 { - TChunk Label; - - ui32 Tail; - ui32 Head; - ui64 Serial; - ui64 Stamp; - } Y_PACKED; - - struct TEvAnnex { - TChunk Label; + ui64 Unused1_; + } Y_PACKED; + + /*_ New generic, TLV based, log */ + + struct TChunk { + ERedo Event; + ui8 Pad0_; + ui16 Pad1_; + ui32 Size; + } Y_PACKED; + + struct TEvBegin_v0 { + TChunk Label; + + ui32 Tail; + ui32 Head; + } Y_PACKED; + + struct TEvBegin_v1 { + TChunk Label; + + ui32 Tail; + ui32 Head; + ui64 Serial; + ui64 Stamp; + } Y_PACKED; + + struct TEvAnnex { + TChunk Label; ui32 Items; /* Followed by array of NPageCollection::TGlobId */ } Y_PACKED; - - struct TEvUpdate { - TChunk Label; - - ui32 Table; + + struct TEvUpdate { + TChunk Label; + + ui32 Table; ERowOp Rop; - ui8 Pad0_; - ui16 Keys; - ui16 Ops; + ui8 Pad0_; + ui16 Keys; + ui16 Ops; } Y_PACKED; - + struct TEvUpdateV { ui64 RowVersionStep; ui64 RowVersionTxId; @@ -97,15 +97,15 @@ namespace NRedo { ui64 TxId; } Y_PACKED; - struct TEvFlush { - TChunk Label; - - ui32 Table; - ui32 Pad0_; - ui64 Stamp; + struct TEvFlush { + TChunk Label; + + ui32 Table; + ui32 Pad0_; + ui64 Stamp; i64 Epoch; } Y_PACKED; - + struct TEvRemoveTx { TChunk Label; @@ -124,32 +124,32 @@ namespace NRedo { ui64 RowVersionTxId; } Y_PACKED; - struct TValue { - bool IsNull() const noexcept - { - return Size == 0 && TypeId == 0; - } - - ui16 TypeId; - ui32 Size; + struct TValue { + bool IsNull() const noexcept + { + return Size == 0 && TypeId == 0; + } + + ui16 TypeId; + ui32 Size; } Y_PACKED; - - struct TUpdate { + + struct TUpdate { NTable::TCellOp CellOp; - NTable::TTag Tag; - TValue Val; - } Y_PACKED; - - #pragma pack(pop) - - static_assert(sizeof(TChunk) == 8, ""); - static_assert(sizeof(TEvBegin_v0) == 16, ""); - static_assert(sizeof(TEvBegin_v1) == 32, ""); - static_assert(sizeof(TEvUpdate) == 18, ""); + NTable::TTag Tag; + TValue Val; + } Y_PACKED; + + #pragma pack(pop) + + static_assert(sizeof(TChunk) == 8, ""); + static_assert(sizeof(TEvBegin_v0) == 16, ""); + static_assert(sizeof(TEvBegin_v1) == 32, ""); + static_assert(sizeof(TEvUpdate) == 18, ""); static_assert(sizeof(TEvUpdateV) == 16, ""); static_assert(sizeof(TEvAnnex) == 12, ""); - static_assert(sizeof(TEvFlush) == 32, ""); - -} -} -} + static_assert(sizeof(TEvFlush) == 32, ""); + +} +} +} diff --git a/ydb/core/tablet_flat/flat_redo_player.h b/ydb/core/tablet_flat/flat_redo_player.h index 4662f972a7..4c80ed9aca 100644 --- a/ydb/core/tablet_flat/flat_redo_player.h +++ b/ydb/core/tablet_flat/flat_redo_player.h @@ -1,63 +1,63 @@ -#pragma once - -#include "flat_update_op.h" -#include "flat_redo_layout.h" -#include "flat_sausage_solid.h" -#include "util_fmt_abort.h" +#pragma once + +#include "flat_update_op.h" +#include "flat_redo_layout.h" +#include "flat_sausage_solid.h" +#include "util_fmt_abort.h" #include "util_basics.h" #include "util_deref.h" - -namespace NKikimr { -namespace NTable { -namespace NRedo { - - class TReader { - public: + +namespace NKikimr { +namespace NTable { +namespace NRedo { + + class TReader { + public: TReader(TArrayRef<const char> plain): Plain(plain), On(Plain.data()) { } - + TArrayRef<const char> Next() noexcept - { - if (On >= Plain.end()) { - return { nullptr, size_t(0) }; - } else if (size_t(Plain.end() - On) >= sizeof(TChunk_Legacy)) { - auto size = reinterpret_cast<const TChunk_Legacy*>(On)->Size; - - if (size >= sizeof(TChunk_Legacy) && (size <= Plain.end() - On)) - return { std::exchange(On, On + size), size }; - } - - Y_FAIL("Damaged or invalid plainfied db redo log"); - } - - private: + { + if (On >= Plain.end()) { + return { nullptr, size_t(0) }; + } else if (size_t(Plain.end() - On) >= sizeof(TChunk_Legacy)) { + auto size = reinterpret_cast<const TChunk_Legacy*>(On)->Size; + + if (size >= sizeof(TChunk_Legacy) && (size <= Plain.end() - On)) + return { std::exchange(On, On + size), size }; + } + + Y_FAIL("Damaged or invalid plainfied db redo log"); + } + + private: TArrayRef<const char> Plain; - const char *On = nullptr; - }; - - template<typename TBase> - class TPlayer { - public: - TPlayer(TBase &base) : Base(base) { } - + const char *On = nullptr; + }; + + template<typename TBase> + class TPlayer { + public: + TPlayer(TBase &base) : Base(base) { } + void Replay(TArrayRef<const char> plain) - { - TReader iter(plain); - - while (auto chunk = iter.Next()) { + { + TReader iter(plain); + + while (auto chunk = iter.Next()) { auto *legacy = reinterpret_cast<const TChunk_Legacy*>(chunk.data()); - + if (Y_LIKELY(legacy->RootId & (ui32(1) << 31))) { auto *label = reinterpret_cast<const TChunk*>(chunk.data()); - + Handle(label, chunk); } else { // legacy records, required for (Evolution < 12) HandleLegacy(legacy, chunk); - } - } - } - - private: + } + } + } + + private: void Handle(const TChunk* label, const TArrayRef<const char> chunk) { switch (label->Event) { @@ -116,51 +116,51 @@ namespace NRedo { private: void DoBegin(const TArrayRef<const char> chunk) - { - if (chunk.size() < sizeof(TEvBegin_v0)) { - Y_Fail("EvBegin event is tool small, " << chunk.size() << "b"); - } else if (chunk.size() < sizeof(TEvBegin_v1)) { + { + if (chunk.size() < sizeof(TEvBegin_v0)) { + Y_Fail("EvBegin event is tool small, " << chunk.size() << "b"); + } else if (chunk.size() < sizeof(TEvBegin_v1)) { auto *ev = reinterpret_cast<const TEvBegin_v0*>(chunk.data()); - - Base.DoBegin(ev->Tail, ev->Head, 0 /* scn */, 0 /* stamp */); - } else { + + Base.DoBegin(ev->Tail, ev->Head, 0 /* scn */, 0 /* stamp */); + } else { auto *ev = reinterpret_cast<const TEvBegin_v1*>(chunk.data()); - - Y_VERIFY(ev->Serial > 0, "Invalid serial in EvBegin record"); - - Base.DoBegin(ev->Tail, ev->Head, ev->Serial, ev->Stamp); - } - } - + + Y_VERIFY(ev->Serial > 0, "Invalid serial in EvBegin record"); + + Base.DoBegin(ev->Tail, ev->Head, ev->Serial, ev->Stamp); + } + } + void DoAnnex(const TArrayRef<const char> chunk) - { - Y_VERIFY(chunk.size() >= sizeof(TEvAnnex)); - + { + Y_VERIFY(chunk.size() >= sizeof(TEvAnnex)); + using TGlobId = TStdPad<NPageCollection::TGlobId>; - + auto *ev = reinterpret_cast<const TEvAnnex*>(chunk.data()); - auto *raw = reinterpret_cast<const TGlobId*>(ev + 1); - - Base.DoAnnex({ raw, ev->Items }); - } - + auto *raw = reinterpret_cast<const TGlobId*>(ev + 1); + + Base.DoAnnex({ raw, ev->Items }); + } + void DoFlush(const TArrayRef<const char> chunk) - { - Y_VERIFY(chunk.size() >= sizeof(TEvFlush)); - - auto *ev = reinterpret_cast<const TEvFlush*>(chunk.begin()); - - if (Base.NeedIn(ev->Table)) + { + Y_VERIFY(chunk.size() >= sizeof(TEvFlush)); + + auto *ev = reinterpret_cast<const TEvFlush*>(chunk.begin()); + + if (Base.NeedIn(ev->Table)) Base.DoFlush(ev->Table, ev->Stamp, TEpoch(ev->Epoch)); - } - + } + void DoUpdate(const TArrayRef<const char> chunk) - { + { auto *ev = reinterpret_cast<const TEvUpdate*>(chunk.data()); - - if (Base.NeedIn(ev->Table)) { - const char *buf = chunk.begin() + sizeof(*ev); - + + if (Base.NeedIn(ev->Table)) { + const char *buf = chunk.begin() + sizeof(*ev); + TRowVersion rowVersion; if (ev->Label.Event == ERedo::UpdateV) { auto *v = reinterpret_cast<const TEvUpdateV*>(buf); @@ -171,13 +171,13 @@ namespace NRedo { rowVersion = TRowVersion::Min(); } - buf += ReadKey(buf, chunk.end() - buf, ev->Keys); - buf += ReadOps(buf, chunk.end() - buf, ev->Ops); - + buf += ReadKey(buf, chunk.end() - buf, ev->Keys); + buf += ReadOps(buf, chunk.end() - buf, ev->Ops); + Base.DoUpdate(ev->Table, ev->Rop, KeyVec, OpsVec, rowVersion); - } - } - + } + } + void DoUpdateTx(const TArrayRef<const char> chunk) { auto *ev = reinterpret_cast<const TEvUpdate*>(chunk.data()); @@ -216,89 +216,89 @@ namespace NRedo { } void DoUpdateLegacy(const TArrayRef<const char> chunk) - { - const char *buf = chunk.begin(); - auto *op = (const TEvUpdate_Legacy*)buf; - buf += sizeof(*op); - buf += ReadKey(buf, chunk.end() - buf, op->Keys); - buf += ReadOps(buf, chunk.end() - buf, op->Ops); - + { + const char *buf = chunk.begin(); + auto *op = (const TEvUpdate_Legacy*)buf; + buf += sizeof(*op); + buf += ReadKey(buf, chunk.end() - buf, op->Keys); + buf += ReadOps(buf, chunk.end() - buf, op->Ops); + Base.DoUpdate(op->OpHeader.RootId, ERowOp::Upsert, KeyVec, OpsVec, TRowVersion::Min()); - } - + } + void DoEraseLegacy(const TArrayRef<const char> chunk) - { - const char *buf = chunk.begin(); - auto *op = (const TEvErase_Legacy*)buf; - buf += sizeof(*op); - buf += ReadKey(buf, chunk.end() - buf, op->Keys); - + { + const char *buf = chunk.begin(); + auto *op = (const TEvErase_Legacy*)buf; + buf += sizeof(*op); + buf += ReadKey(buf, chunk.end() - buf, op->Keys); + Base.DoUpdate(op->OpHeader.RootId, ERowOp::Erase, KeyVec, { }, TRowVersion::Min()); - } - + } + void DoFlushLegacy(const TArrayRef<const char> chunk) - { - Y_VERIFY(chunk.size() >= sizeof(TEvFlush_Legacy)); - - auto *op = reinterpret_cast<const TEvFlush_Legacy*>(chunk.begin()); - + { + Y_VERIFY(chunk.size() >= sizeof(TEvFlush_Legacy)); + + auto *op = reinterpret_cast<const TEvFlush_Legacy*>(chunk.begin()); + Base.DoFlush(op->Hdr.RootId, op->TxStamp, TEpoch(op->Epoch)); - } - - ui32 ReadKey(const char* buf, ui32 maxSz, ui32 count) - { - const char *bufStart = buf; - const char *end = buf + maxSz; - KeyVec.clear(); - KeyVec.resize(count); - - for (ui32 ki = 0; ki < count; ++ki) { - buf += ReadValue(buf, end - buf, KeyVec[ki]); - } - return buf - bufStart; - } - - ui32 ReadValue(const char* buf, ui32 maxSz, TRawTypeValue& val) - { - Y_VERIFY(maxSz >= sizeof(TValue), "Buffer to small"); - const TValue* vp = (const TValue*)buf; - Y_VERIFY(maxSz >= sizeof(TValue) + vp->Size, "Value size execeeds the buffer size"); - val = vp->IsNull() ? TRawTypeValue() : TRawTypeValue(vp + 1, vp->Size, vp->TypeId); - return sizeof(TValue) + vp->Size; - } - - ui32 ReadOps(const char* buf, ui32 maxSz, ui32 count) - { - const char *bufStart = buf; - const char *end = buf + maxSz; - OpsVec.clear(); - OpsVec.resize(count); - - for (ui32 ui = 0; ui < count; ++ui) { - buf += ReadOneOp(buf, end - buf, OpsVec[ui]); - } - return buf - bufStart; - } - - ui32 ReadOneOp(const char* buf, ui32 maxSz, TUpdateOp& uo) - { - Y_VERIFY(maxSz >= sizeof(TUpdate), "Buffer to small"); - const TUpdate* up = (const TUpdate*)buf; - Y_VERIFY(maxSz >= sizeof(TUpdate) + up->Val.Size, "Value size execeeds the buffer size"); + } + + ui32 ReadKey(const char* buf, ui32 maxSz, ui32 count) + { + const char *bufStart = buf; + const char *end = buf + maxSz; + KeyVec.clear(); + KeyVec.resize(count); + + for (ui32 ki = 0; ki < count; ++ki) { + buf += ReadValue(buf, end - buf, KeyVec[ki]); + } + return buf - bufStart; + } + + ui32 ReadValue(const char* buf, ui32 maxSz, TRawTypeValue& val) + { + Y_VERIFY(maxSz >= sizeof(TValue), "Buffer to small"); + const TValue* vp = (const TValue*)buf; + Y_VERIFY(maxSz >= sizeof(TValue) + vp->Size, "Value size execeeds the buffer size"); + val = vp->IsNull() ? TRawTypeValue() : TRawTypeValue(vp + 1, vp->Size, vp->TypeId); + return sizeof(TValue) + vp->Size; + } + + ui32 ReadOps(const char* buf, ui32 maxSz, ui32 count) + { + const char *bufStart = buf; + const char *end = buf + maxSz; + OpsVec.clear(); + OpsVec.resize(count); + + for (ui32 ui = 0; ui < count; ++ui) { + buf += ReadOneOp(buf, end - buf, OpsVec[ui]); + } + return buf - bufStart; + } + + ui32 ReadOneOp(const char* buf, ui32 maxSz, TUpdateOp& uo) + { + Y_VERIFY(maxSz >= sizeof(TUpdate), "Buffer to small"); + const TUpdate* up = (const TUpdate*)buf; + Y_VERIFY(maxSz >= sizeof(TUpdate) + up->Val.Size, "Value size execeeds the buffer size"); bool null = TCellOp::HaveNoPayload(up->CellOp) || up->Val.IsNull(); uo = TUpdateOp(up->Tag, up->CellOp, null ? TRawTypeValue() : TRawTypeValue(up + 1, up->Val.Size, up->Val.TypeId)); - + Y_VERIFY(up->CellOp == ELargeObj::Inline || (up->CellOp == ELargeObj::Extern && up->Val.Size == sizeof(ui32))); - - return sizeof(TUpdate) + up->Val.Size; - } - - private: - TBase &Base; - TVector<TRawTypeValue> KeyVec; - TVector<TUpdateOp> OpsVec; - }; - -} -} -} + + return sizeof(TUpdate) + up->Val.Size; + } + + private: + TBase &Base; + TVector<TRawTypeValue> KeyVec; + TVector<TUpdateOp> OpsVec; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_redo_writer.h b/ydb/core/tablet_flat/flat_redo_writer.h index dafeeb38e2..a25804d262 100644 --- a/ydb/core/tablet_flat/flat_redo_writer.h +++ b/ydb/core/tablet_flat/flat_redo_writer.h @@ -1,20 +1,20 @@ -#pragma once - -#include "flat_redo_layout.h" -#include "flat_update_op.h" -#include "flat_util_binary.h" -#include "flat_sausage_solid.h" +#pragma once + +#include "flat_redo_layout.h" +#include "flat_update_op.h" +#include "flat_util_binary.h" +#include "flat_sausage_solid.h" #include "util_basics.h" - -#include <util/stream/buffer.h> -#include <util/system/sanitizers.h> -#include <util/generic/list.h> - -namespace NKikimr { -namespace NTable { -namespace NRedo { - - struct IAnnex { + +#include <util/stream/buffer.h> +#include <util/system/sanitizers.h> +#include <util/generic/list.h> + +namespace NKikimr { +namespace NTable { +namespace NRedo { + + struct IAnnex { struct TLimit { ui32 MinExternSize; ui32 MaxExternSize; @@ -26,130 +26,130 @@ namespace NRedo { struct TResult { TResult() = default; - + TResult(ui32 ref) : Ref(ref) { } - - explicit operator bool() const noexcept - { - return Ref != Max<ui32>(); - } - - ui32 Ref = Max<ui32>(); - }; - - virtual ~IAnnex() = default; - - /* Limit(...) is the temporary hack required for calculation exact - space occupied by event in redo log buffer. It will work with - single family tables but it is not scaled to multiple families. - */ - + + explicit operator bool() const noexcept + { + return Ref != Max<ui32>(); + } + + ui32 Ref = Max<ui32>(); + }; + + virtual ~IAnnex() = default; + + /* Limit(...) is the temporary hack required for calculation exact + space occupied by event in redo log buffer. It will work with + single family tables but it is not scaled to multiple families. + */ + virtual TLimit Limit(ui32 table) noexcept = 0; virtual TResult Place(ui32 table, TTag, TArrayRef<const char>) noexcept = 0; - }; - - class TWriter { + }; + + class TWriter { private: struct TSizeInfo { ui32 Size; IAnnex::TLimit Limit; }; - public: - using TOpsRef = TArrayRef<const TUpdateOp>; - using IOut = IOutputStream; - - TWriter(IAnnex *annex = nullptr, ui32 edge = 1024) - : Edge(edge) - , Annex(annex) - { - - } - - explicit operator bool() const noexcept - { - return bool(Events); - } - - size_t Bytes() const noexcept - { - return TotalSize; - } - - TList<TString> Unwrap() noexcept - { - return TotalSize = 0, std::move(Events); - } - - TWriter& EvBegin(ui32 tail, ui32 head, ui64 serial, ui64 stamp) - { - Y_VERIFY(tail <= head, "Invalid ABI/API evolution span"); - Y_VERIFY(serial > 0, "Serial of EvBegin starts with 1"); - - const ui32 size = sizeof(TEvBegin_v1); - - TEvBegin_v1 ev{ { ERedo::Begin, 0, 0x8000, size }, - tail, head, serial, stamp }; - + public: + using TOpsRef = TArrayRef<const TUpdateOp>; + using IOut = IOutputStream; + + TWriter(IAnnex *annex = nullptr, ui32 edge = 1024) + : Edge(edge) + , Annex(annex) + { + + } + + explicit operator bool() const noexcept + { + return bool(Events); + } + + size_t Bytes() const noexcept + { + return TotalSize; + } + + TList<TString> Unwrap() noexcept + { + return TotalSize = 0, std::move(Events); + } + + TWriter& EvBegin(ui32 tail, ui32 head, ui64 serial, ui64 stamp) + { + Y_VERIFY(tail <= head, "Invalid ABI/API evolution span"); + Y_VERIFY(serial > 0, "Serial of EvBegin starts with 1"); + + const ui32 size = sizeof(TEvBegin_v1); + + TEvBegin_v1 ev{ { ERedo::Begin, 0, 0x8000, size }, + tail, head, serial, stamp }; + void* evBegin = &ev; return Push(TString(NUtil::NBin::ToByte(evBegin), size), size); - } - + } + TWriter& EvFlush(ui32 table, ui64 stamp, TEpoch epoch) - { - const ui32 size = sizeof(TEvFlush); - - TEvFlush ev{ { ERedo::Flush, 0, 0x8000, size }, + { + const ui32 size = sizeof(TEvFlush); + + TEvFlush ev{ { ERedo::Flush, 0, 0x8000, size }, table, 0, stamp, epoch.ToRedoLog() }; void* evBegin = &ev; return Push(TString(NUtil::NBin::ToByte(evBegin), size), size); - } - + } + TWriter& EvAnnex(TArrayRef<const NPageCollection::TGlobId> blobs) - { - using namespace NUtil::NBin; - + { + using namespace NUtil::NBin; + Y_VERIFY(blobs.size() <= Max<ui32>(), "Too large blobs catalog"); - - const ui32 size = sizeof(TEvAnnex) + SizeOf(blobs); - + + const ui32 size = sizeof(TEvAnnex) + SizeOf(blobs); + TEvAnnex ev{ { ERedo::Annex, 0, 0x8000, size }, ui32(blobs.size()) }; - - auto out = Begin(size); - - Write(out, &ev, sizeof(ev)); - Write(out, static_cast<const void*>(blobs.begin()), SizeOf(blobs)); - - return Push(std::move(out.Str()), size); - } - + + auto out = Begin(size); + + Write(out, &ev, sizeof(ev)); + Write(out, static_cast<const void*>(blobs.begin()), SizeOf(blobs)); + + return Push(std::move(out.Str()), size); + } + template<class TCallback> TWriter& EvUpdate(ui32 table, ERowOp rop, TRawVals key, TOpsRef ops, ERedo tag, ui32 tailSize, TCallback&& tailCallback, bool isDelta = false) - { + { if (TCellOp::HaveNoOps(rop) && ops) { Y_FAIL("Given ERowOp cannot have update operations"); - } else if (key.size() + ops.size() > Max<ui16>()) { - Y_FAIL("Too large key or too many operations in one ops"); - } - + } else if (key.size() + ops.size() > Max<ui16>()) { + Y_FAIL("Too large key or too many operations in one ops"); + } + const auto sizeInfo = CalcSize(key, ops, table, isDelta); const ui32 size = sizeof(TEvUpdate) + tailSize + sizeInfo.Size; - auto out = Begin(size); - + auto out = Begin(size); + TEvUpdate ev{ { tag, 0, 0x8000, size }, table, rop, 0, ui16(key.size()), ui16(ops.size()) }; - - Write(out, &ev, sizeof(ev)); + + Write(out, &ev, sizeof(ev)); tailCallback(out); - Write(out, key); + Write(out, key); Write(out, ops, table, sizeInfo.Limit); - - return Push(std::move(out.Str()), size); - } - + + return Push(std::move(out.Str()), size); + } + TWriter& EvUpdate(ui32 table, ERowOp rop, TRawVals key, TOpsRef ops, TRowVersion rowVersion) { if (rowVersion > TRowVersion::Min()) { @@ -194,49 +194,49 @@ namespace NRedo { return Push(TString(NUtil::NBin::ToByte(&ev), size), size); } - TWriter& Join(TWriter &log) - { - TotalSize += std::exchange(log.TotalSize, 0); - Events.splice(Events.end(), log.Events); - - return *this; - } - - TString Dump() const noexcept - { - auto out = Begin(TotalSize); - - for (auto one : Events) - out.Write(one); - - Y_VERIFY(out.Str().size() == TotalSize); - - NSan::CheckMemIsInitialized(out.Str().data(), out.Str().size()); - - return std::move(out.Str()); - } - - private: - static TStringStream Begin(size_t bytes) - { - TStringStream out; - - return out.Reserve(bytes), out; - } - - TWriter& Push(TString buf, size_t bytes) - { - Y_VERIFY(buf.size() == bytes, "Got an invalid redo entry buffer"); - - TotalSize += buf.size(); - - Events.emplace_back(std::move(buf)); - - return *this; - } - + TWriter& Join(TWriter &log) + { + TotalSize += std::exchange(log.TotalSize, 0); + Events.splice(Events.end(), log.Events); + + return *this; + } + + TString Dump() const noexcept + { + auto out = Begin(TotalSize); + + for (auto one : Events) + out.Write(one); + + Y_VERIFY(out.Str().size() == TotalSize); + + NSan::CheckMemIsInitialized(out.Str().data(), out.Str().size()); + + return std::move(out.Str()); + } + + private: + static TStringStream Begin(size_t bytes) + { + TStringStream out; + + return out.Reserve(bytes), out; + } + + TWriter& Push(TString buf, size_t bytes) + { + Y_VERIFY(buf.size() == bytes, "Got an invalid redo entry buffer"); + + TotalSize += buf.size(); + + Events.emplace_back(std::move(buf)); + + return *this; + } + IAnnex::TLimit GetLimit(ui32 table, bool isDelta) const noexcept - { + { IAnnex::TLimit limit; // FIXME: we cannot handle blob references during scans, so we // avoid creating large objects when they are in deltas @@ -248,112 +248,112 @@ namespace NRedo { limit.MinExternSize = Max(limit.MinExternSize, Edge); return limit; } - + TSizeInfo CalcSize(TRawVals key, TOpsRef ops, ui32 table, bool isDelta) const noexcept { auto limit = GetLimit(table, isDelta); - ui32 size = 0; - - for (const auto &one : ops) { - /* hack for annex blobs, its replaced by 4-byte reference */ + ui32 size = 0; + + for (const auto &one : ops) { + /* hack for annex blobs, its replaced by 4-byte reference */ auto valueSize = one.Value.Size(); if (Annex && table != Max<ui32>() && limit.IsExtern(valueSize)) { valueSize = 4; } - + size += sizeof(TUpdate) + valueSize; - } - + } + size += CalcSize(key); return TSizeInfo{ size, limit }; - } - - ui32 CalcSize(TRawVals key) const noexcept - { - ui32 size = 0; - - for (const auto &one: key) - size += sizeof(TValue) + one.Size(); - - return size; - } - - void Write(IOut &out, TRawVals key) const noexcept - { - for (const auto &one : key) { - /* The only way of converting nulls in keys now */ - - const ui16 type = one.IsEmpty() ? 0 : one.Type(); - - TValue keyEl = { type, one.Size() }; - - Write(out, &keyEl, sizeof(keyEl)); - Write(out, one.Data(), one.Size()); - } - } - + } + + ui32 CalcSize(TRawVals key) const noexcept + { + ui32 size = 0; + + for (const auto &one: key) + size += sizeof(TValue) + one.Size(); + + return size; + } + + void Write(IOut &out, TRawVals key) const noexcept + { + for (const auto &one : key) { + /* The only way of converting nulls in keys now */ + + const ui16 type = one.IsEmpty() ? 0 : one.Type(); + + TValue keyEl = { type, one.Size() }; + + Write(out, &keyEl, sizeof(keyEl)); + Write(out, one.Data(), one.Size()); + } + } + void Write(IOut &out, TOpsRef ops, ui32 table, const IAnnex::TLimit &limit) const noexcept - { - for (const auto &one: ops) { + { + for (const auto &one: ops) { /* Log enty cannot represent this ECellOp types with payload */ - + Y_VERIFY(!(one.Value && TCellOp::HaveNoPayload(one.Op))); - + /* Log entry cannot recover nulls written as ECellOp::Set with - null cell. Nulls was encoded with hacky TypeId = 0, but + null cell. Nulls was encoded with hacky TypeId = 0, but the correct way is to use ECellOp::Null. - */ - - const ui16 type = one.Value ? one.Value.Type() : 0; - + */ + + const ui16 type = one.Value ? one.Value.Type() : 0; + auto cellOp = one.NormalizedCellOp(); - + if (cellOp != ELargeObj::Inline) { Y_FAIL("User supplied cell value has an invalid ECellOp"); } else if (auto got = Place(table, limit, one.Tag, one.AsRef())) { - const auto payload = NUtil::NBin::ToRef(got.Ref); - + const auto payload = NUtil::NBin::ToRef(got.Ref); + Write(out, cellOp = ELargeObj::Extern, one.Tag, type, payload); - - } else { + + } else { Write(out, cellOp, one.Tag, type, one.Value.AsRef()); - } - } - } - + } + } + } + IAnnex::TResult Place(ui32 table, const IAnnex::TLimit &limit, TTag tag, TArrayRef<const char> raw) const noexcept - { + { if (Annex && table != Max<ui32>() && limit.IsExtern(raw.size())) { return Annex->Place(table, tag, raw); } else { - return { }; - } - } - + return { }; + } + } + static void Write(IOut &out, TCellOp cellOp, TTag tag, ui16 type, TArrayRef<const char> raw) - { + { TUpdate up = { cellOp, tag, { type , ui32(raw.size()) } }; - - Write(out, &up, sizeof(up)); - Write(out, raw.data(), raw.size()); - } - - static void Write(IOut &out, const void *ptr, size_t size) - { - NSan::CheckMemIsInitialized(ptr, size); - - out.Write(ptr, size); - } - - private: - const ui32 Edge = 1024; - IAnnex * const Annex = nullptr; + + Write(out, &up, sizeof(up)); + Write(out, raw.data(), raw.size()); + } + + static void Write(IOut &out, const void *ptr, size_t size) + { + NSan::CheckMemIsInitialized(ptr, size); + + out.Write(ptr, size); + } + + private: + const ui32 Edge = 1024; + IAnnex * const Annex = nullptr; size_t TotalSize = 0; - TList<TString> Events; - }; - -} -} -} + TList<TString> Events; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_row_celled.h b/ydb/core/tablet_flat/flat_row_celled.h index a45e943dd2..5cb39b1118 100644 --- a/ydb/core/tablet_flat/flat_row_celled.h +++ b/ydb/core/tablet_flat/flat_row_celled.h @@ -1,51 +1,51 @@ -#pragma once - -#include "flat_row_nulls.h" -#include <util/generic/vector.h> -#include <array> - -namespace NKikimr { -namespace NTable { - - struct TCelled { - using TRaw = TArrayRef<const TRawTypeValue>; - +#pragma once + +#include "flat_row_nulls.h" +#include <util/generic/vector.h> +#include <array> + +namespace NKikimr { +namespace NTable { + + struct TCelled { + using TRaw = TArrayRef<const TRawTypeValue>; + TCelled(TRaw key, const TKeyNulls &nulls, bool extend) : Size(extend ? nulls->size() : Min(nulls->size(), key.size())) - , Large(Size > Small.size() ? Size : 0) - , Cells(Large ? Large.begin() : Small.begin()) - { + , Large(Size > Small.size() ? Size : 0) + , Cells(Large ? Large.begin() : Small.begin()) + { Y_VERIFY(key.size() <= nulls->size(), "Key is tool large"); - - for (ui32 it = 0; it < Size; it++) { + + for (ui32 it = 0; it < Size; it++) { if (it >= key.size()) { - Cells[it] = nulls[it]; + Cells[it] = nulls[it]; } else if (key[it] && key[it].Type() != nulls.Types[it].GetTypeId()) { - Y_FAIL("Key does not comply table schema"); - } else { - Cells[it] = TCell((char*)key[it].Data(), key[it].Size()); - } - - Bytes += Cells[it].Size(); - } - } - - const TCell& operator[](size_t on) const noexcept - { - return Cells[on]; - } - - operator TArrayRef<const TCell>() const noexcept - { - return { Cells, Size }; - } - - const size_t Size = 0; - size_t Bytes = 0; - std::array<TCell, 16> Small; - TVector<TCell> Large; - TCell * const Cells = nullptr; - }; - -} -} + Y_FAIL("Key does not comply table schema"); + } else { + Cells[it] = TCell((char*)key[it].Data(), key[it].Size()); + } + + Bytes += Cells[it].Size(); + } + } + + const TCell& operator[](size_t on) const noexcept + { + return Cells[on]; + } + + operator TArrayRef<const TCell>() const noexcept + { + return { Cells, Size }; + } + + const size_t Size = 0; + size_t Bytes = 0; + std::array<TCell, 16> Small; + TVector<TCell> Large; + TCell * const Cells = nullptr; + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_row_column.h b/ydb/core/tablet_flat/flat_row_column.h index ff2887da8a..08464a8d61 100644 --- a/ydb/core/tablet_flat/flat_row_column.h +++ b/ydb/core/tablet_flat/flat_row_column.h @@ -1,31 +1,31 @@ -#pragma once - -#include "flat_row_eggs.h" +#pragma once + +#include "flat_row_eggs.h" #include <ydb/core/scheme/scheme_type_id.h> - -namespace NKikimr { -namespace NTable { - - struct TColInfo { - struct TByTag { - bool operator()(const TColInfo &le, const TColInfo &ri) const - { - return le.Tag < ri.Tag; - } - - bool operator()(const TColInfo *le, const TColInfo *ri) const - { - return le->Tag < ri->Tag; - } - }; - - struct TByKey { - bool operator()(const TColInfo &le, const TColInfo &ri) const - { - return le.Key < ri.Key; - } - }; - + +namespace NKikimr { +namespace NTable { + + struct TColInfo { + struct TByTag { + bool operator()(const TColInfo &le, const TColInfo &ri) const + { + return le.Tag < ri.Tag; + } + + bool operator()(const TColInfo *le, const TColInfo *ri) const + { + return le->Tag < ri->Tag; + } + }; + + struct TByKey { + bool operator()(const TColInfo &le, const TColInfo &ri) const + { + return le.Key < ri.Key; + } + }; + struct TByPos { bool operator()(const TColInfo& a, const TColInfo& b) const { @@ -33,19 +33,19 @@ namespace NTable { } }; - TColInfo() = default; - - TColInfo(const TColInfo&) = default; - - bool IsKey() const noexcept { - return Key != Max<TPos>(); - } - - NScheme::TTypeId TypeId = 0; - TTag Tag = Max<TTag>(); - TPos Pos = Max<TPos>(); /* Position in physical layout */ - TPos Key = Max<TPos>(); /* key column sequence number */ + TColInfo() = default; + + TColInfo(const TColInfo&) = default; + + bool IsKey() const noexcept { + return Key != Max<TPos>(); + } + + NScheme::TTypeId TypeId = 0; + TTag Tag = Max<TTag>(); + TPos Pos = Max<TPos>(); /* Position in physical layout */ + TPos Key = Max<TPos>(); /* key column sequence number */ TGroup Group = 0; /* Column group */ - }; -} -} + }; +} +} diff --git a/ydb/core/tablet_flat/flat_row_eggs.h b/ydb/core/tablet_flat/flat_row_eggs.h index aaf9e7f35c..1fa1743923 100644 --- a/ydb/core/tablet_flat/flat_row_eggs.h +++ b/ydb/core/tablet_flat/flat_row_eggs.h @@ -1,146 +1,146 @@ -#pragma once - +#pragma once + #include <ydb/core/base/row_version.h> -#include <util/system/types.h> -#include <util/generic/ylimits.h> -#include <util/generic/array_ref.h> - -namespace NKikimr { -namespace NTable { - - using TRowId = ui64; - using TTag = ui32; - using TPos = ui32; /* Column logical position */ - using TTagsRef = TArrayRef<const TTag>; +#include <util/system/types.h> +#include <util/generic/ylimits.h> +#include <util/generic/array_ref.h> + +namespace NKikimr { +namespace NTable { + + using TRowId = ui64; + using TTag = ui32; + using TPos = ui32; /* Column logical position */ + using TTagsRef = TArrayRef<const TTag>; using TGroup = ui32; /* Column logical group */ - - enum class ESeek { - Exact = 1, - Lower = 2, /* lower_bound, { } -> begin() */ - Upper = 3, /* upper_bound, { } -> end() */ - }; - - enum class EReady { - Page = 0, /* Need some pages to be loaded */ - Data = 1, - Gone = 2, /* Iterator finally invalidated */ - }; - + + enum class ESeek { + Exact = 1, + Lower = 2, /* lower_bound, { } -> begin() */ + Upper = 3, /* upper_bound, { } -> end() */ + }; + + enum class EReady { + Page = 0, /* Need some pages to be loaded */ + Data = 1, + Gone = 2, /* Iterator finally invalidated */ + }; + enum class EDirection { Forward, Reverse, }; enum class ERowOp : ui8 { /* row operation code */ - Absent = 0, - Upsert = 1, /* Set value or update row */ - Erase = 2, /* Explicit null or row drop */ - Reset = 3, /* Reset cell or row to default */ - }; - + Absent = 0, + Upsert = 1, /* Set value or update row */ + Erase = 2, /* Explicit null or row drop */ + Reset = 3, /* Reset cell or row to default */ + }; + enum class ECellOp : ui8 { /* cell operation code */ - Empty = 0, /* Cell has no any valid state */ - Set = 1, /* Set cell to exact value */ - Null = 2, /* Explicit cell null value */ - Reset = 3, /* Reset cell value to default */ - }; - + Empty = 0, /* Cell has no any valid state */ + Set = 1, /* Set cell to exact value */ + Null = 2, /* Explicit cell null value */ + Reset = 3, /* Reset cell value to default */ + }; + enum class ELargeObj : ui8 { - Inline = 0, /* Data stored within storage */ - Extern = 1, /* Data placed in external blob */ - GlobId = 2, /* Explicit TGlobId reference */ - Outer = 3, /* ~ is packed out of rows page */ - }; - + Inline = 0, /* Data stored within storage */ + Extern = 1, /* Data placed in external blob */ + GlobId = 2, /* Explicit TGlobId reference */ + Outer = 3, /* ~ is packed out of rows page */ + }; + enum EHint : ui64 { NoByKey = 0x1, }; struct TLargeObj { TLargeObj() = default; - + TLargeObj(ELargeObj lob, ui64 ref) : Lob(lob), Ref(ref) { } - - explicit operator bool() const noexcept - { + + explicit operator bool() const noexcept + { return Lob != ELargeObj::Inline && Ref != Max<ui64>(); - } - + } + ELargeObj Lob = ELargeObj::Inline; - ui64 Ref = Max<ui64>(); - }; - + ui64 Ref = Max<ui64>(); + }; + #pragma pack(push, 1) struct TCellOp { constexpr TCellOp() = default; - + static constexpr TCellOp By(ui8 raw) noexcept - { + { return { ECellOp(raw & 0x3f), ELargeObj(raw >> 6) }; - } - + } + constexpr TCellOp(ECellOp op, ELargeObj lob = ELargeObj::Inline) noexcept - : Value(ui8(op) | (ui8(lob) << 6)) - { - - } - - constexpr ui8 Raw() const noexcept - { - return Value; - } - + : Value(ui8(op) | (ui8(lob) << 6)) + { + + } + + constexpr ui8 Raw() const noexcept + { + return Value; + } + constexpr operator ECellOp() const noexcept - { + { return ECellOp(Value & 0x3f); - } - + } + constexpr operator ELargeObj() const noexcept - { + { return ELargeObj(Value >> 6); - } - - constexpr ui8 operator*() const noexcept - { - return Value; - } - + } + + constexpr ui8 operator*() const noexcept + { + return Value; + } + TCellOp& operator=(ECellOp op) noexcept - { - Value = (Value & ~0x3f) | ui8(op); - - return *this; - } - + { + Value = (Value & ~0x3f) | ui8(op); + + return *this; + } + TCellOp& operator=(ELargeObj lob) noexcept - { + { Value = TCellOp(ECellOp(*this), lob).Raw(); - - return *this; - } - + + return *this; + } + constexpr static bool HaveNoPayload(ECellOp cellOp) noexcept - { - return + { + return cellOp == ECellOp::Null || cellOp == ECellOp::Reset || cellOp == ECellOp::Empty; - } - + } + constexpr static bool HaveNoOps(ERowOp rop) noexcept - { + { return rop == ERowOp::Erase; - } - - private: - ui8 Value = 0; + } + + private: + ui8 Value = 0; } Y_PACKED; - + #pragma pack(pop) static_assert(sizeof(TCellOp) == 1, "Unexpected TCellOp unit size"); - -} -} + +} +} diff --git a/ydb/core/tablet_flat/flat_row_misc.h b/ydb/core/tablet_flat/flat_row_misc.h index d7730ff06d..a0115554e5 100644 --- a/ydb/core/tablet_flat/flat_row_misc.h +++ b/ydb/core/tablet_flat/flat_row_misc.h @@ -1,57 +1,57 @@ -#pragma once - -#include "flat_row_nulls.h" -#include "flat_row_remap.h" -#include "util_fmt_desc.h" - +#pragma once + +#include "flat_row_nulls.h" +#include "flat_row_remap.h" +#include "util_fmt_desc.h" + #include <ydb/core/scheme/scheme_tablecell.h> - -namespace NKikimr { -namespace NFmt { + +namespace NKikimr { +namespace NFmt { using TOut = IOutputStream; - - struct TCells { - using TReg = NScheme::TTypeRegistry; + + struct TCells { + using TReg = NScheme::TTypeRegistry; using TCellsRef = TArrayRef<const TCell>; using TTypesRef = TArrayRef<const NScheme::TTypeId>; - + TCells(TCellsRef cells, const NTable::TRemap &remap, const TReg *reg) - : TCells(cells, remap.Types(), reg) - { - - } - + : TCells(cells, remap.Types(), reg) + { + + } + TCells(TCellsRef cells, const NTable::TNulls &nulls, const TReg *reg) - : TCells(cells, nulls.Types, reg) - { - - } - + : TCells(cells, nulls.Types, reg) + { + + } + TCells(TCellsRef cells, TTypesRef types, const TReg *reg) - : Cells(cells) - , Types(types) - , Registry(reg) - { + : Cells(cells) + , Types(types) + , Registry(reg) + { Y_VERIFY(cells.size() == Types.size(), "Cells and types size missmatch"); - } - - TOut& Do(TOut &out) const noexcept - { + } + + TOut& Do(TOut &out) const noexcept + { TDbTupleRef tp{ Types.begin(), Cells.begin(), ui32(Cells.size()) }; - - return out << DbgPrintTuple(tp, *Registry); - } - - private: + + return out << DbgPrintTuple(tp, *Registry); + } + + private: const TCellsRef Cells; const TTypesRef Types; - const TReg *Registry = nullptr; - }; - - inline TOut& operator<<(TOut &out, const NFmt::TCells &print) - { - return print.Do(out); - } - -} -} + const TReg *Registry = nullptr; + }; + + inline TOut& operator<<(TOut &out, const NFmt::TCells &print) + { + return print.Do(out); + } + +} +} diff --git a/ydb/core/tablet_flat/flat_row_nulls.h b/ydb/core/tablet_flat/flat_row_nulls.h index f4e664b7cc..dc33f84061 100644 --- a/ydb/core/tablet_flat/flat_row_nulls.h +++ b/ydb/core/tablet_flat/flat_row_nulls.h @@ -1,105 +1,105 @@ -#pragma once - -#include "flat_util_misc.h" +#pragma once + +#include "flat_util_misc.h" #include "util_basics.h" - + #include <ydb/core/scheme/scheme_tablecell.h> #include <library/cpp/containers/stack_vector/stack_vec.h> -#include <util/generic/array_ref.h> - -namespace NKikimr { -namespace NTable { - - class TNulls: public TAtomicRefCount<TNulls, NUtil::TDtorDel<TNulls>> { +#include <util/generic/array_ref.h> + +namespace NKikimr { +namespace NTable { + + class TNulls: public TAtomicRefCount<TNulls, NUtil::TDtorDel<TNulls>> { protected: - using TType = NScheme::TTypeId; + using TType = NScheme::TTypeId; using TOrder = NScheme::TTypeIdOrder; - - TNulls(TArrayRef<const TType> types, TArrayRef<const TCell> defs) - : Types(types) - , Defs(defs) - { - Y_VERIFY(Defs.size() > 0 && Defs.size() == Types.size()); - } - - public: + + TNulls(TArrayRef<const TType> types, TArrayRef<const TCell> defs) + : Types(types) + , Defs(defs) + { + Y_VERIFY(Defs.size() > 0 && Defs.size() == Types.size()); + } + + public: virtual ~TNulls() = default; - + protected: template<class TSelf> static TIntrusiveConstPtr<TSelf> Make( TArrayRef<const TType> types, TArrayRef<const TOrder> order, TArrayRef<const TCell> defs) noexcept - { + { size_t offT = AlignUp(sizeof(TSelf)); size_t offO = offT + AlignUp(sizeof(TType) * types.size()); size_t offC = offO + AlignUp(sizeof(TOrder) * order.size()); size_t offD = offC + AlignUp(sizeof(TCell) * defs.size()); - - size_t tail = std::accumulate(defs.begin(), defs.end(), size_t(0), - [](size_t sum, const TCell &cell) { - auto size = cell.IsInline() ? 0 : cell.Size(); - - return sum + AlignUp(size_t(size)); - }); - - char * const raw = (char*)::operator new(offD + tail); - - TType *ptrT = reinterpret_cast<TType*>(raw + offT); - std::copy(types.begin(), types.end(), ptrT); - + + size_t tail = std::accumulate(defs.begin(), defs.end(), size_t(0), + [](size_t sum, const TCell &cell) { + auto size = cell.IsInline() ? 0 : cell.Size(); + + return sum + AlignUp(size_t(size)); + }); + + char * const raw = (char*)::operator new(offD + tail); + + TType *ptrT = reinterpret_cast<TType*>(raw + offT); + std::copy(types.begin(), types.end(), ptrT); + TOrder *ptrO = reinterpret_cast<TOrder*>(raw + offO); std::copy(order.begin(), order.end(), ptrO); TCell *ptrC = reinterpret_cast<TCell*>(raw + offC); - char *data = raw + offD; - - for (size_t it = 0; it < defs.size(); it++) { - if (defs[it].IsInline()) { - ptrC[it] = defs[it]; - } else if (auto * const src = defs[it].Data()) { - std::copy(src, src + defs[it].Size(), data); - - ptrC[it] = { data, defs[it].Size() }; - - data += AlignUp(size_t(defs[it].Size())); - } - } - - Y_VERIFY(data == raw + offD + tail); - + char *data = raw + offD; + + for (size_t it = 0; it < defs.size(); it++) { + if (defs[it].IsInline()) { + ptrC[it] = defs[it]; + } else if (auto * const src = defs[it].Data()) { + std::copy(src, src + defs[it].Size(), data); + + ptrC[it] = { data, defs[it].Size() }; + + data += AlignUp(size_t(defs[it].Size())); + } + } + + Y_VERIFY(data == raw + offD + tail); + return ::new(raw) TSelf( { ptrT, types.size() }, { ptrO, order.size() }, { ptrC, defs.size() }); - } - + } + public: - size_t Size() const noexcept - { - return Defs.size(); - } - - TArrayRef<const TCell> operator*() const noexcept - { - return Defs; - } - + size_t Size() const noexcept + { + return Defs.size(); + } + + TArrayRef<const TCell> operator*() const noexcept + { + return Defs; + } + const TArrayRef<const TCell>* operator->() const noexcept { return &Defs; } - const TCell& operator[](size_t on) const noexcept - { - return Defs[on]; - } - - public: - const TArrayRef<const TType> Types; - const TArrayRef<const TCell> Defs; - }; + const TCell& operator[](size_t on) const noexcept + { + return Defs[on]; + } + + public: + const TArrayRef<const TType> Types; + const TArrayRef<const TCell> Defs; + }; /** * Types and defaults for the complete row @@ -164,5 +164,5 @@ namespace NTable { const TArrayRef<const TOrder> Types; }; -} -} +} +} diff --git a/ydb/core/tablet_flat/flat_row_remap.h b/ydb/core/tablet_flat/flat_row_remap.h index 22f304131a..2072b43d02 100644 --- a/ydb/core/tablet_flat/flat_row_remap.h +++ b/ydb/core/tablet_flat/flat_row_remap.h @@ -1,98 +1,98 @@ -#pragma once - -#include "flat_row_eggs.h" -#include "flat_row_scheme.h" - +#pragma once + +#include "flat_row_eggs.h" +#include "flat_row_scheme.h" + #include <ydb/core/scheme/scheme_tablecell.h> #include <library/cpp/containers/stack_vector/stack_vec.h> -#include <util/generic/vector.h> - -namespace NKikimr { -namespace NTable { - - class TRemap { - public: - struct TPin { TPos Pos, Key; }; - - struct THas { - operator TPos() const noexcept - { - return Pos; - } - - explicit operator bool() const noexcept - { - return Pos != Max<TPos>(); - } - - TPos Pos; - }; - - static TRemap Full(const TRowScheme& scheme) - { +#include <util/generic/vector.h> + +namespace NKikimr { +namespace NTable { + + class TRemap { + public: + struct TPin { TPos Pos, Key; }; + + struct THas { + operator TPos() const noexcept + { + return Pos; + } + + explicit operator bool() const noexcept + { + return Pos != Max<TPos>(); + } + + TPos Pos; + }; + + static TRemap Full(const TRowScheme& scheme) + { TVector<ui32> tags(scheme.Cols.size()); - for (auto &col: scheme.Cols) - tags[col.Pos] = col.Tag; - - return TRemap(scheme, tags); - } - - TRemap(const TRowScheme& scheme, TTagsRef tags) - : Tags(tags.begin(), tags.end()) - , Types_(tags.size(), 0) - { - Tag2Pos.reserve(tags.size()); - Nulls_.reserve(tags.size()); - - for (TPos on = 0; on < tags.size(); on++) { - const auto *info = scheme.ColInfo(tags[on]); - Y_VERIFY(info, "Column %" PRIu32 " does not exist", tags[on]); - Types_[on] = info->TypeId; - - Nulls_.emplace_back((*scheme.Nulls)[info->Pos]); - - if (info->IsKey()) - KeyPins_.push_back({ on, info->Key }); - - if (!Tag2Pos.insert(std::make_pair(tags[on], on)).second) - Y_FAIL("Duplicated tag found in remap, isn't allowed"); - } - } - - TArrayRef<const NScheme::TTypeId> Types() const noexcept - { - return Types_; - } - - TPos Size() const - { - return Tags.size(); - } - - TArrayRef<const TPin> KeyPins() const noexcept - { - return KeyPins_; - } - - TArrayRef<const TCell> Nulls() const noexcept - { - return Nulls_; - } - - THas Has(TTag tag) const noexcept - { - const auto it = Tag2Pos.find(tag); - - return { it == Tag2Pos.end() ? Max<TPos>() : it->second }; - } - - public: - const TSmallVec<TTag> Tags; - private: - TSmallVec<TPin> KeyPins_; - TSmallVec<NScheme::TTypeId> Types_; - TSmallVec<TCell> Nulls_; + for (auto &col: scheme.Cols) + tags[col.Pos] = col.Tag; + + return TRemap(scheme, tags); + } + + TRemap(const TRowScheme& scheme, TTagsRef tags) + : Tags(tags.begin(), tags.end()) + , Types_(tags.size(), 0) + { + Tag2Pos.reserve(tags.size()); + Nulls_.reserve(tags.size()); + + for (TPos on = 0; on < tags.size(); on++) { + const auto *info = scheme.ColInfo(tags[on]); + Y_VERIFY(info, "Column %" PRIu32 " does not exist", tags[on]); + Types_[on] = info->TypeId; + + Nulls_.emplace_back((*scheme.Nulls)[info->Pos]); + + if (info->IsKey()) + KeyPins_.push_back({ on, info->Key }); + + if (!Tag2Pos.insert(std::make_pair(tags[on], on)).second) + Y_FAIL("Duplicated tag found in remap, isn't allowed"); + } + } + + TArrayRef<const NScheme::TTypeId> Types() const noexcept + { + return Types_; + } + + TPos Size() const + { + return Tags.size(); + } + + TArrayRef<const TPin> KeyPins() const noexcept + { + return KeyPins_; + } + + TArrayRef<const TCell> Nulls() const noexcept + { + return Nulls_; + } + + THas Has(TTag tag) const noexcept + { + const auto it = Tag2Pos.find(tag); + + return { it == Tag2Pos.end() ? Max<TPos>() : it->second }; + } + + public: + const TSmallVec<TTag> Tags; + private: + TSmallVec<TPin> KeyPins_; + TSmallVec<NScheme::TTypeId> Types_; + TSmallVec<TCell> Nulls_; THashMap<TTag, TPos> Tag2Pos; - }; - -}} + }; + +}} diff --git a/ydb/core/tablet_flat/flat_row_scheme.h b/ydb/core/tablet_flat/flat_row_scheme.h index fc750a1279..f3157601d9 100644 --- a/ydb/core/tablet_flat/flat_row_scheme.h +++ b/ydb/core/tablet_flat/flat_row_scheme.h @@ -1,162 +1,162 @@ -#pragma once - -#include "flat_row_column.h" -#include "flat_row_nulls.h" -#include "flat_table_column.h" - -#include <util/generic/vector.h> -#include <util/generic/hash.h> +#pragma once + +#include "flat_row_column.h" +#include "flat_row_nulls.h" +#include "flat_table_column.h" + +#include <util/generic/vector.h> +#include <util/generic/hash.h> #include <util/generic/map.h> #include <util/generic/set.h> - -namespace NKikimr { -namespace NTable { - - class TRowScheme : public TAtomicRefCount<TRowScheme> { + +namespace NKikimr { +namespace NTable { + + class TRowScheme : public TAtomicRefCount<TRowScheme> { template<class TNullsType, class TType> - struct TNullsCook { - TNullsCook(ui32 slots) - : Types(slots) - , Cells(slots) - { - - } - - void Set(ui32 idx, TType type, const TCell &cell) - { - Types[idx] = type; - Cells[idx] = cell; - } - + struct TNullsCook { + TNullsCook(ui32 slots) + : Types(slots) + , Cells(slots) + { + + } + + void Set(ui32 idx, TType type, const TCell &cell) + { + Types[idx] = type; + Cells[idx] = cell; + } + TIntrusiveConstPtr<TNullsType> operator*() const noexcept - { + { return TNullsType::Make(Types, Cells); - } - + } + TVector<TType> Types; TVector<TCell> Cells; - }; - + }; + TRowScheme( TVector<TColInfo> cols, TIntrusiveConstPtr<TKeyNulls> keys, TIntrusiveConstPtr<TRowNulls> nulls, TVector<ui32> families) - : Cols(std::move(cols)) - , Keys(std::move(keys)) - , Nulls(std::move(nulls)) + : Cols(std::move(cols)) + , Keys(std::move(keys)) + , Nulls(std::move(nulls)) , Families(std::move(families)) - { - for (const auto &col: Cols) - ByTag.emplace(col.Tag, col.Pos); - } - - public: - template<typename TGet, typename TSeq> + { + for (const auto &col: Cols) + ByTag.emplace(col.Tag, col.Pos); + } + + public: + template<typename TGet, typename TSeq> static TIntrusiveConstPtr<TRowScheme> Make(const TSeq &cols_, TGet) - { - size_t keyCount = 0; + { + size_t keyCount = 0; TSet<ui32> familySet; TMap<ui32, const TColumn*> cols; /* order by tag */ - - for (auto &it : cols_) { - auto &meta = TGet::Do(it); + + for (auto &it : cols_) { + auto &meta = TGet::Do(it); familySet.insert(meta.Family); - cols[meta.Id] = &meta; - keyCount += (meta.KeyOrder == Max<TPos>() ? 0 : 1); - } - + cols[meta.Id] = &meta; + keyCount += (meta.KeyOrder == Max<TPos>() ? 0 : 1); + } + TNullsCook<TKeyNulls, NScheme::TTypeIdOrder> keys(keyCount); TNullsCook<TRowNulls, NScheme::TTypeId> vals(cols.size()); - + TVector<TColInfo> info; - info.reserve(cols.size()); - + info.reserve(cols.size()); + TVector<ui32> families(familySet.begin(), familySet.end()); - for (auto &it: cols) { - auto &meta = *it.second; - auto &col = *info.emplace(info.end()); - + for (auto &it: cols) { + auto &meta = *it.second; + auto &col = *info.emplace(info.end()); + auto familyIt = std::lower_bound(families.begin(), families.end(), meta.Family); Y_VERIFY(familyIt != families.end() && *familyIt == meta.Family); - col.Tag = meta.Id; - col.TypeId = meta.PType; - col.Key = meta.KeyOrder; - col.Pos = info.size() - 1; + col.Tag = meta.Id; + col.TypeId = meta.PType; + col.Key = meta.KeyOrder; + col.Pos = info.size() - 1; col.Group = familyIt - families.begin(); - - vals.Set(col.Pos, col.TypeId, meta.Null); - - if (col.IsKey()) - keys.Set(col.Key, col.TypeId, meta.Null); - } - + + vals.Set(col.Pos, col.TypeId, meta.Null); + + if (col.IsKey()) + keys.Set(col.Key, col.TypeId, meta.Null); + } + return new TRowScheme(std::move(info), *keys, *vals, std::move(families)); - } - - static bool HasTag(TArrayRef<const ui32> array, ui32 tag) noexcept - { - return std::binary_search(array.begin(), array.end(), tag); - } - - const NTable::TColInfo* ColInfo(TTag tag) const - { - auto ci = ByTag.find(tag); - - return ci == ByTag.end() ? nullptr : &Cols[ci->second]; - } - - TVector<ui32> Tags(bool keysOnly = false) const noexcept - { - TVector<ui32> tags; /* ordered by value tags */ - - for (auto &col: Cols) - if (!keysOnly || col.IsKey()) - tags.push_back(col.Tag); - - return tags; - } - - void CheckCompatability(const TRowScheme &scheme) const - { - for (auto &col: Cols) { - auto *other = scheme.ColInfo(col.Tag); - - if (other == nullptr && col.IsKey()) { - Y_FAIL("Key column dropping ins't supported"); - } else if (other == nullptr) { - /* It is ok to drop non-key columns */ - } else if (col.TypeId != other->TypeId) { - Y_FAIL("Column type alteration is not supproted"); - } else if (col.Key != other->Key) { - Y_FAIL("Cannot alter keys order or move col to keys"); - - /* Existing string columns can't be altered to keys as - they may hold external blobs references which is not - supported for keys. Part iterators itself can extend - keys only with default values but not by column with - data. - */ - - } else { - auto &null = (*scheme.Nulls)[other->Pos]; - - if (CompareTypedCells(null, (*Nulls)[col.Pos], col.TypeId)) - Y_FAIL("Cannot alter existing columnt default value"); - } - } - } - - public: + } + + static bool HasTag(TArrayRef<const ui32> array, ui32 tag) noexcept + { + return std::binary_search(array.begin(), array.end(), tag); + } + + const NTable::TColInfo* ColInfo(TTag tag) const + { + auto ci = ByTag.find(tag); + + return ci == ByTag.end() ? nullptr : &Cols[ci->second]; + } + + TVector<ui32> Tags(bool keysOnly = false) const noexcept + { + TVector<ui32> tags; /* ordered by value tags */ + + for (auto &col: Cols) + if (!keysOnly || col.IsKey()) + tags.push_back(col.Tag); + + return tags; + } + + void CheckCompatability(const TRowScheme &scheme) const + { + for (auto &col: Cols) { + auto *other = scheme.ColInfo(col.Tag); + + if (other == nullptr && col.IsKey()) { + Y_FAIL("Key column dropping ins't supported"); + } else if (other == nullptr) { + /* It is ok to drop non-key columns */ + } else if (col.TypeId != other->TypeId) { + Y_FAIL("Column type alteration is not supproted"); + } else if (col.Key != other->Key) { + Y_FAIL("Cannot alter keys order or move col to keys"); + + /* Existing string columns can't be altered to keys as + they may hold external blobs references which is not + supported for keys. Part iterators itself can extend + keys only with default values but not by column with + data. + */ + + } else { + auto &null = (*scheme.Nulls)[other->Pos]; + + if (CompareTypedCells(null, (*Nulls)[col.Pos], col.TypeId)) + Y_FAIL("Cannot alter existing columnt default value"); + } + } + } + + public: const TVector<TColInfo> Cols; const TIntrusiveConstPtr<TKeyNulls> Keys; const TIntrusiveConstPtr<TRowNulls> Nulls; const TVector<ui32> Families; // per-group families - - private: + + private: THashMap<TTag, NTable::TPos> ByTag; - }; - -}} + }; + +}} diff --git a/ydb/core/tablet_flat/flat_row_state.h b/ydb/core/tablet_flat/flat_row_state.h index b51d732785..d76fdae09c 100644 --- a/ydb/core/tablet_flat/flat_row_state.h +++ b/ydb/core/tablet_flat/flat_row_state.h @@ -1,57 +1,57 @@ -#pragma once - -#include "flat_row_eggs.h" +#pragma once + +#include "flat_row_eggs.h" #include <ydb/core/scheme/scheme_tablecell.h> #include <library/cpp/containers/stack_vector/stack_vec.h> - -namespace NKikimr { -namespace NTable { - - class TRowState { - public: - TRowState(size_t slots = 0) - { - Init(slots); - } - - void Init(size_t slots) - { + +namespace NKikimr { +namespace NTable { + + class TRowState { + public: + TRowState(size_t slots = 0) + { + Init(slots); + } + + void Init(size_t slots) + { Rop = ERowOp::Absent; - Need_ = 0; - Left_ = slots; - Cells.assign(slots, { }); - State.assign(slots, { }); - } - - void Reset(TArrayRef<const TCell> nulls) - { + Need_ = 0; + Left_ = slots; + Cells.assign(slots, { }); + State.assign(slots, { }); + } + + void Reset(TArrayRef<const TCell> nulls) + { Rop = ERowOp::Absent; - Need_ = 0; - Left_ = nulls.size(); - State.assign(Left_, { }); - Cells.assign(nulls.begin(), nulls.end()); - } - - ui32 Need() const noexcept { return Need_; } - ui32 Left() const noexcept { return Left_; } - TPos Size() const noexcept { return Cells.size(); } - + Need_ = 0; + Left_ = nulls.size(); + State.assign(Left_, { }); + Cells.assign(nulls.begin(), nulls.end()); + } + + ui32 Need() const noexcept { return Need_; } + ui32 Left() const noexcept { return Left_; } + TPos Size() const noexcept { return Cells.size(); } + bool operator==(ERowOp rop) const noexcept - { - return Rop == rop; - } - + { + return Rop == rop; + } + bool operator!=(ERowOp rop) const noexcept { return Rop != rop; } ERowOp GetRowState() const { - return Rop; - } - + return Rop; + } + bool Touch(ERowOp op) noexcept - { + { Y_VERIFY(!(Rop == ERowOp::Erase || Rop == ERowOp::Reset), "Sequence for row state is already finalized"); @@ -65,11 +65,11 @@ namespace NTable { return false; /* current row shouldn't be processed */ default: Y_FAIL("Unexpected row rolling operation code: %" PRIu8, ui8(op)); - } - } - + } + } + void Set(TPos on, TCellOp code, const TCell &cell) noexcept - { + { Y_VERIFY(State[on] == ECellOp::Empty, "Updating cell that already has a value assigned"); if (Y_UNLIKELY(code == ECellOp::Empty)) { @@ -84,23 +84,23 @@ namespace NTable { if (Y_UNLIKELY(code == ECellOp::Reset)) { // Setting cell to a schema default value // N.B. doesn't really happen in practice - State[on] = code; + State[on] = code; } else if (code != ECellOp::Null || code != ELargeObj::Inline) { State[on] = code; - Cells[on] = cell; - - /* Required but not materialized external blobs are stored as + Cells[on] = cell; + + /* Required but not materialized external blobs are stored as ECellOp::Null with non-inline ELargeObj storage. Upper layers may - check completeness of loaded row later. - */ - + check completeness of loaded row later. + */ + Need_ += bool(code == ECellOp::Null && code != ELargeObj::Inline); - } else { + } else { State[on] = ECellOp::Set; - Cells[on] = { }; - } - } - + Cells[on] = { }; + } + } + void Merge(const TRowState& other) noexcept { Y_VERIFY(!(Rop == ERowOp::Erase || Rop == ERowOp::Reset), "Sequence for row state is already finalized"); @@ -120,40 +120,40 @@ namespace NTable { } } - TArrayRef<const TCell> operator*() const noexcept - { - return Cells; - } - - const TCell& Get(TPos pos) const noexcept - { - return Cells[pos]; - } - + TArrayRef<const TCell> operator*() const noexcept + { + return Cells; + } + + const TCell& Get(TPos pos) const noexcept + { + return Cells[pos]; + } + TCellOp GetOp(TPos pos) const noexcept - { - return State[pos]; - } - - bool IsFinalized() const noexcept - { + { + return State[pos]; + } + + bool IsFinalized() const noexcept + { return (Rop == ERowOp::Upsert && Left_ == 0) || Rop == ERowOp::Erase || Rop == ERowOp::Reset; - } - - bool IsFinalized(TPos pos) const noexcept - { + } + + bool IsFinalized(TPos pos) const noexcept + { return GetOp(pos) != ECellOp::Empty; - } - - private: + } + + private: ERowOp Rop = ERowOp::Absent; - ui32 Need_ = 0; /* Dangled cells state */ - ui32 Left_ = 0; /* Cells with unknown state */ + ui32 Need_ = 0; /* Dangled cells state */ + ui32 Left_ = 0; /* Cells with unknown state */ TStackVec<TCellOp, 64> State; - TSmallVec<TCell> Cells; - }; - -} -} + TSmallVec<TCell> Cells; + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_sausage_align.h b/ydb/core/tablet_flat/flat_sausage_align.h index 04c7992ef4..56ec1344a6 100644 --- a/ydb/core/tablet_flat/flat_sausage_align.h +++ b/ydb/core/tablet_flat/flat_sausage_align.h @@ -1,42 +1,42 @@ -#pragma once - -#include "flat_sausage_misc.h" -#include <util/generic/algorithm.h> - -namespace NKikimr { +#pragma once + +#include "flat_sausage_misc.h" +#include <util/generic/algorithm.h> + +namespace NKikimr { namespace NPageCollection { - - class TAlign { - public: + + class TAlign { + public: TAlign(TArrayRef<const ui64> steps) : Steps(steps) { } - - TBorder Lookup(ui64 offset, const ui64 sz) const noexcept - { - auto it = UpperBound(Steps.begin(), Steps.end(), offset); - Y_VERIFY(it != Steps.end(), "Lookup span is out of borders"); - - const ui32 first = std::distance(Steps.begin(), it); - const ui64 base = it == Steps.begin() ? 0 : *(it - 1); - const ui64 szoffset = offset + sz; - - ui32 last = first; - ui64 lastOffset = base; - - while (Steps[last] < szoffset) { - lastOffset = Steps[last++]; - Y_VERIFY(last < Steps.size(), "Lookup span is out of borders"); - } - - return - { - sz, - { first, ui32(offset - base) }, - { last, ui32(szoffset - lastOffset) } - }; - } - + + TBorder Lookup(ui64 offset, const ui64 sz) const noexcept + { + auto it = UpperBound(Steps.begin(), Steps.end(), offset); + Y_VERIFY(it != Steps.end(), "Lookup span is out of borders"); + + const ui32 first = std::distance(Steps.begin(), it); + const ui64 base = it == Steps.begin() ? 0 : *(it - 1); + const ui64 szoffset = offset + sz; + + ui32 last = first; + ui64 lastOffset = base; + + while (Steps[last] < szoffset) { + lastOffset = Steps[last++]; + Y_VERIFY(last < Steps.size(), "Lookup span is out of borders"); + } + + return + { + sz, + { first, ui32(offset - base) }, + { last, ui32(szoffset - lastOffset) } + }; + } + const TArrayRef<const ui64> Steps; - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_sausage_chop.h b/ydb/core/tablet_flat/flat_sausage_chop.h index c15d605e9b..53574f1f35 100644 --- a/ydb/core/tablet_flat/flat_sausage_chop.h +++ b/ydb/core/tablet_flat/flat_sausage_chop.h @@ -1,68 +1,68 @@ -#pragma once - -#include "flat_sausage_solid.h" -#include <util/generic/xrange.h> - -namespace NKikimr { +#pragma once + +#include "flat_sausage_solid.h" +#include <util/generic/xrange.h> + +namespace NKikimr { namespace NPageCollection { - + struct TGroupBlobsByCookie { using TArray = TArrayRef<const TLogoBlobID>; - + TGroupBlobsByCookie(TArray array) : Array(array) { } - - explicit operator bool() const noexcept - { - return Head < Array.size(); - } - - TArray Do() noexcept - { - auto left = Array.size() - Min(Head, Array.size()); - - for (size_t offset = 0; offset < left; Head++, offset++) - if (!Near(Array[Head - offset], Array[Head], offset)) - break; - - return { Array.end() - left, Array.begin() + Head }; - } - + + explicit operator bool() const noexcept + { + return Head < Array.size(); + } + + TArray Do() noexcept + { + auto left = Array.size() - Min(Head, Array.size()); + + for (size_t offset = 0; offset < left; Head++, offset++) + if (!Near(Array[Head - offset], Array[Head], offset)) + break; + + return { Array.end() - left, Array.begin() + Head }; + } + static bool Near(const TLogoBlobID &left, const TLogoBlobID &right, ui32 way) - { - return + { + return TGroupBlobsByCookie::IsInPlane(left, right) - && left.Cookie() + way == right.Cookie() - && left.Cookie() != TLogoBlobID::MaxCookie - way; - } - + && left.Cookie() + way == right.Cookie() + && left.Cookie() != TLogoBlobID::MaxCookie - way; + } + static TLargeGlobId ToLargeGlobId(TArray logo, ui32 group = TLargeGlobId::InvalidGroup) noexcept - { - if (logo) { - for (auto num : xrange(logo.size())) { - auto &base = logo[logo.size() - 1 == num ? num : 0]; - - Y_VERIFY(logo[num].BlobSize() == base.BlobSize()); - } - - const ui32 bulk = (logo.size() - 1) * logo[0].BlobSize(); - - return { group, logo[0], bulk + logo.back().BlobSize() }; - } else { + { + if (logo) { + for (auto num : xrange(logo.size())) { + auto &base = logo[logo.size() - 1 == num ? num : 0]; + + Y_VERIFY(logo[num].BlobSize() == base.BlobSize()); + } + + const ui32 bulk = (logo.size() - 1) * logo[0].BlobSize(); + + return { group, logo[0], bulk + logo.back().BlobSize() }; + } else { return { }; /* invalid TLargeGlobId object */ - } - } - - static bool IsInPlane(const TLogoBlobID &one, const TLogoBlobID &two) - { - return - one.TabletID() == two.TabletID() - && one.Generation() == two.Generation() - && one.Step() == two.Step(); - } - - private: - TArray Array; - size_t Head = 0; - }; -} -} + } + } + + static bool IsInPlane(const TLogoBlobID &one, const TLogoBlobID &two) + { + return + one.TabletID() == two.TabletID() + && one.Generation() == two.Generation() + && one.Step() == two.Step(); + } + + private: + TArray Array; + size_t Head = 0; + }; +} +} diff --git a/ydb/core/tablet_flat/flat_sausage_fetch.h b/ydb/core/tablet_flat/flat_sausage_fetch.h index 3654b9e745..bb883e165b 100644 --- a/ydb/core/tablet_flat/flat_sausage_fetch.h +++ b/ydb/core/tablet_flat/flat_sausage_fetch.h @@ -1,52 +1,52 @@ -#pragma once - -#include "flat_sausage_gut.h" - +#pragma once + +#include "flat_sausage_gut.h" + #include <ydb/core/base/shared_data.h> -namespace NKikimr { +namespace NKikimr { namespace NPageCollection { - - struct TFetch { + + struct TFetch { TFetch(ui64 cookie, TIntrusiveConstPtr<IPageCollection> pageCollection, TVector<ui32> pages) - : Cookie(cookie) + : Cookie(cookie) , PageCollection(std::move(pageCollection)) - , Pages(std::move(pages)) - { - - } - - void Describe(IOutputStream &out) const noexcept - { - out - << "Fetch{" << Pages.size() << " pages" + , Pages(std::move(pages)) + { + + } + + void Describe(IOutputStream &out) const noexcept + { + out + << "Fetch{" << Pages.size() << " pages" << " " << PageCollection->Label() << "}"; - } - - const ui64 Cookie = Max<ui64>(); - + } + + const ui64 Cookie = Max<ui64>(); + TIntrusiveConstPtr<IPageCollection> PageCollection; TVector<ui32> Pages; - }; - + }; + struct TLoadedPage { TLoadedPage() = default; - + TLoadedPage(ui32 page, TSharedData data) - : PageId(page) + : PageId(page) , Data(std::move(data)) - { - - } - - explicit operator bool() const noexcept - { - return Data && PageId != Max<ui32>(); - } - - ui32 PageId = Max<ui32>(); + { + + } + + explicit operator bool() const noexcept + { + return Data && PageId != Max<ui32>(); + } + + ui32 PageId = Max<ui32>(); TSharedData Data; - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_sausage_flow.h b/ydb/core/tablet_flat/flat_sausage_flow.h index 8dfb4f1e6b..918c9290e8 100644 --- a/ydb/core/tablet_flat/flat_sausage_flow.h +++ b/ydb/core/tablet_flat/flat_sausage_flow.h @@ -1,116 +1,116 @@ -#pragma once - -#include "flat_sausage_misc.h" -#include "flat_sausage_solid.h" -#include <util/generic/deque.h> - -namespace NKikimr { +#pragma once + +#include "flat_sausage_misc.h" +#include "flat_sausage_solid.h" +#include <util/generic/deque.h> + +namespace NKikimr { namespace NPageCollection { - + template<typename TPageCollectionClass> class TPagesToBlobsConverter { - public: + public: struct TReadPortion { - - void Describe(IOutputStream &out) const noexcept - { - out - << "{" << Slot << "p +" << Skip << "b " << Size << "b}"; - } - + + void Describe(IOutputStream &out) const noexcept + { + out + << "{" << Slot << "p +" << Skip << "b " << Size << "b}"; + } + bool operator==(const TReadPortion &br) const noexcept - { - return - Slot == br.Slot && Skip == br.Skip - && Size == br.Size && Blob == br.Blob; - } - - ui32 Slot; /* Page where to put data */ - ui32 Size; /* Bytes, may be more that page */ - ui32 Blob; /* Blobs storage group number */ - ui32 Skip; /* Request data offset in blob */ - }; - + { + return + Slot == br.Slot && Skip == br.Skip + && Size == br.Size && Blob == br.Blob; + } + + ui32 Slot; /* Page where to put data */ + ui32 Size; /* Bytes, may be more that page */ + ui32 Blob; /* Blobs storage group number */ + ui32 Skip; /* Request data offset in blob */ + }; + struct TReadPortionRange { - constexpr explicit operator bool() const - { - return +*this > 0; - } - - constexpr ui32 operator+() const - { - return To - From; - } - - ui32 From, To; - }; - + constexpr explicit operator bool() const + { + return +*this > 0; + } + + constexpr ui32 operator+() const + { + return To - From; + } + + ui32 From, To; + }; + TPagesToBlobsConverter(const TPageCollectionClass &pageCollection, TArrayRef<const ui32> pages) : PageCollection(pageCollection) , Slice(pages) {} - - bool Complete() const noexcept - { - return Tail >= Slice.size(); - } - + + bool Complete() const noexcept + { + return Tail >= Slice.size(); + } + TReadPortionRange Grow(ui64 bytes) noexcept - { + { const ui32 from = Queue.size(); - const ui64 limit = OnHold + Min(Max<ui64>() - OnHold, bytes); - - for (ui32 group = Glob.Group; Tail < Slice.size(); Tail++) { + const ui64 limit = OnHold + Min(Max<ui64>() - OnHold, bytes); + + for (ui32 group = Glob.Group; Tail < Slice.size(); Tail++) { const auto bound = PageCollection.Bounds(Slice[Tail]); - + if (OnHold + bound.Bytes > limit && from < Queue.size()) - break; - + break; + ui64 bucket = bound.Bytes; /* total bounded data size */ - - for (ui32 it = bound.Lo.Blob; it <= bound.Up.Blob; it++) { + + for (ui32 it = bound.Lo.Blob; it <= bound.Up.Blob; it++) { (std::exchange(Blob, it) != it) && (Glob = PageCollection.Glob(it)); - - auto was = std::exchange(group, Glob.Group); - + + auto was = std::exchange(group, Glob.Group); + if (was == Glob.Group || was == TLargeGlobId::InvalidGroup) { - - } else if (it != bound.Lo.Blob) { - Y_FAIL("Page placed over different groups"); + + } else if (it != bound.Lo.Blob) { + Y_FAIL("Page placed over different groups"); } else if (from < Queue.size()) { - /* Have to do each grow over the same group */ - + /* Have to do each grow over the same group */ + return { from, ui32(Queue.size()) }; - } - - ui32 skip = it > bound.Lo.Blob ? 0 : bound.Lo.Skip; + } + + ui32 skip = it > bound.Lo.Blob ? 0 : bound.Lo.Skip; ui32 left = Glob.Logo.BlobSize() - skip; ui32 chunk = bucket <= left ? bucket : left; - + Queue.emplace_back(TReadPortion{ Tail, chunk, it, skip }); - - (OnHold += chunk) && (bucket -= chunk); - } - } - + + (OnHold += chunk) && (bucket -= chunk); + } + } + return { from, ui32(Queue.size()) }; - } - + } + const TPageCollectionClass &PageCollection; const TArrayRef<const ui32> Slice; - - ui32 Head = 0; /* Slot Offset of the first entry */ - ui32 Tail = 0; /* Next page slot to process */ - ui64 OnHold = 0; /* Total bytes prepared in the flow */ - + + ui32 Head = 0; /* Slot Offset of the first entry */ + ui32 Tail = 0; /* Next page slot to process */ + ui64 OnHold = 0; /* Total bytes prepared in the flow */ + TDeque<TReadPortion> Queue; - - private: - /*_ Basic size lookup cache, omits frequent lookups */ - - ui32 Blob = Max<ui32>(); - TGlobId Glob; - }; - -} -} + + private: + /*_ Basic size lookup cache, omits frequent lookups */ + + ui32 Blob = Max<ui32>(); + TGlobId Glob; + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_sausage_grind.h b/ydb/core/tablet_flat/flat_sausage_grind.h index 31320773f5..cc36447504 100644 --- a/ydb/core/tablet_flat/flat_sausage_grind.h +++ b/ydb/core/tablet_flat/flat_sausage_grind.h @@ -1,50 +1,50 @@ -#pragma once - -#include "util_fmt_desc.h" -#include "util_fmt_abort.h" -#include "flat_sausage_solid.h" - -namespace NKikimr { +#pragma once + +#include "util_fmt_desc.h" +#include "util_fmt_abort.h" +#include "flat_sausage_solid.h" + +namespace NKikimr { namespace NPageCollection { - - struct TSlot { - TSlot(ui8 cnl, ui32 group) : Channel(cnl), Group(group) { } - - ui8 Channel = Max<ui8>(); + + struct TSlot { + TSlot(ui8 cnl, ui32 group) : Channel(cnl), Group(group) { } + + ui8 Channel = Max<ui8>(); ui32 Group = NPageCollection::TLargeGlobId::InvalidGroup; - }; - + }; + struct TCookieRange { - constexpr bool Has(ui32 ref) const noexcept - { - return Head <= ref && ref <= Tail; - } - - ui32 Head, Tail; /* [ Head, Tail], but Tail is used as a gap */ - }; - + constexpr bool Has(ui32 ref) const noexcept + { + return Head <= ref && ref <= Tail; + } + + ui32 Head, Tail; /* [ Head, Tail], but Tail is used as a gap */ + }; + class TCookieAllocator { - static constexpr ui32 Mask = Max<ui32>() >> 8; - static constexpr ui32 Spacer = ui32(1) << 31; - - public: + static constexpr ui32 Mask = Max<ui32>() >> 8; + static constexpr ui32 Spacer = ui32(1) << 31; + + public: TCookieAllocator(ui64 tablet, ui64 stamp, TCookieRange cookieRange, TArrayRef<const TSlot> row) - : Tablet(tablet) - , Gen(stamp >> 32) + : Tablet(tablet) + , Gen(stamp >> 32) , CookieRange(cookieRange) , Span(CookieRange.Tail - CookieRange.Head) - , Step(stamp) - , Slots(Max<ui8>(), Max<ui8>()) - { + , Step(stamp) + , Slots(Max<ui8>(), Max<ui8>()) + { if ((cookieRange.Head & ~Mask) || (cookieRange.Tail & ~Mask)) { Y_FAIL("CookieRange range can use only lower 24 bits"); } else if (cookieRange.Head > cookieRange.Tail) { Y_FAIL("Invalid TLogoBlobID cookieRange capacity range"); - } - - for (auto &one: row) { - auto &place = Slots[one.Channel]; - + } + + for (auto &one: row) { + auto &place = Slots[one.Channel]; + Y_VERIFY(one.Channel != Max<ui8>(), "Channel cannot be set to Max<ui8>() value"); @@ -53,114 +53,114 @@ namespace NPageCollection { Y_VERIFY(Group[place] == one.Group, "Channel assigned to different groups"); continue; - } - + } + place = Group.size(); - Group.emplace_back(one.Group); - } - - State.resize(Group.size(), 0); - } - - void Describe(IOutputStream &out) const noexcept - { - out - << "Cookies{" << Tablet << ":" << Gen << ":" << Step + Group.emplace_back(one.Group); + } + + State.resize(Group.size(), 0); + } + + void Describe(IOutputStream &out) const noexcept + { + out + << "Cookies{" << Tablet << ":" << Gen << ":" << Step << " cookieRange[" << CookieRange.Head << " +" << Span << "]}"; - } - - ui32 GroupBy(ui8 channel) const noexcept - { - return Group[Locate(channel)]; - } - - ui64 Stamp() const noexcept - { - return (ui64(Gen) << 32) | Step; - } - - TGlobId Do(ui8 channel, ui32 bytes) noexcept - { - const auto slot = Locate(channel); - - auto first = Allocate(slot, 1, false); - - TLogoBlobID lead(Tablet, Gen, Step, channel, bytes, first); - - return { lead, Group[slot] }; - } - + } + + ui32 GroupBy(ui8 channel) const noexcept + { + return Group[Locate(channel)]; + } + + ui64 Stamp() const noexcept + { + return (ui64(Gen) << 32) | Step; + } + + TGlobId Do(ui8 channel, ui32 bytes) noexcept + { + const auto slot = Locate(channel); + + auto first = Allocate(slot, 1, false); + + TLogoBlobID lead(Tablet, Gen, Step, channel, bytes, first); + + return { lead, Group[slot] }; + } + TLargeGlobId Do(ui8 cnl, ui32 bytes, ui32 lim) noexcept - { - const auto slot = Locate(cnl); - + { + const auto slot = Locate(cnl); + /* Eeach TLargeGlobId have to be gapped with a single unused TLogoBlobID items for ability to chop them with NPageCollection::TGroupBlobsByCookie tool. */ - - auto first = Allocate(slot, bytes / lim + (bytes % lim > 0), true); - - TLogoBlobID lead(Tablet, Gen, Step, cnl, Min(lim, bytes), first); - - return { Group[slot], lead, bytes }; - } - - private: - ui8 Locate(ui8 channel) const noexcept - { - auto slot = Slots[channel]; - + + auto first = Allocate(slot, bytes / lim + (bytes % lim > 0), true); + + TLogoBlobID lead(Tablet, Gen, Step, cnl, Min(lim, bytes), first); + + return { Group[slot], lead, bytes }; + } + + private: + ui8 Locate(ui8 channel) const noexcept + { + auto slot = Slots[channel]; + Y_VERIFY(slot != Max<ui8>(), "Requested unknown channel"); - - return slot; - } - - ui32 Allocate(ui8 slot, ui32 num, bool gap) noexcept - { - auto &value = State.at(slot); - - const ui32 left = value && (gap || (value & Spacer) ? 1 : 0); - - num += left; - - if (num > Span || Span - num <= (Mask & value)) - Y_Fail(NFmt::Do(*this) << " #" << slot << " was exhausted"); - - ui32 to = ((Mask & value) + num) | (gap ? Spacer : 0); - + + return slot; + } + + ui32 Allocate(ui8 slot, ui32 num, bool gap) noexcept + { + auto &value = State.at(slot); + + const ui32 left = value && (gap || (value & Spacer) ? 1 : 0); + + num += left; + + if (num > Span || Span - num <= (Mask & value)) + Y_Fail(NFmt::Do(*this) << " #" << slot << " was exhausted"); + + ui32 to = ((Mask & value) + num) | (gap ? Spacer : 0); + return CookieRange.Head + (Mask & std::exchange(value, to)) + left; - } - - public: - const ui64 Tablet = 0; - const ui32 Gen = Max<ui32>(); + } + + public: + const ui64 Tablet = 0; + const ui32 Gen = Max<ui32>(); const TCookieRange CookieRange; /* Cookie range row over channels slices*/ - - protected: - const ui32 Span = 0; - - ui32 Step = Max<ui32>(); - TVector<ui8> Slots; /* Mapping { channel -> slot (slice) } */ - TVector<ui32> Group; /* BS group for each channel slice */ - TVector<ui32> State; - }; - + + protected: + const ui32 Span = 0; + + ui32 Step = Max<ui32>(); + TVector<ui8> Slots; /* Mapping { channel -> slot (slice) } */ + TVector<ui32> Group; /* BS group for each channel slice */ + TVector<ui32> State; + }; + class TSteppedCookieAllocator : public TCookieAllocator { - public: + public: using TCookieAllocator::TCookieAllocator; - - void Switch(const ui32 step, bool strict) noexcept - { - if (step == Max<ui32>()) { - Y_Fail(NFmt::Do(*this) << " is out of steps capacity"); - } else if (Step + (strict ? 1 : 0) > step && Step != Max<ui32>()) { - Y_Fail( - NFmt::Do(*this) << " got stuck on step switch to " - << step << ", " << (strict ? "strict" : "weak")); - } else if (std::exchange(Step, step) != step) { - std::fill(State.begin(), State.end(), 0); - } - } - }; - -} -} + + void Switch(const ui32 step, bool strict) noexcept + { + if (step == Max<ui32>()) { + Y_Fail(NFmt::Do(*this) << " is out of steps capacity"); + } else if (Step + (strict ? 1 : 0) > step && Step != Max<ui32>()) { + Y_Fail( + NFmt::Do(*this) << " got stuck on step switch to " + << step << ", " << (strict ? "strict" : "weak")); + } else if (std::exchange(Step, step) != step) { + std::fill(State.begin(), State.end(), 0); + } + } + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_sausage_gut.h b/ydb/core/tablet_flat/flat_sausage_gut.h index 50ba86805e..2244683fed 100644 --- a/ydb/core/tablet_flat/flat_sausage_gut.h +++ b/ydb/core/tablet_flat/flat_sausage_gut.h @@ -1,24 +1,24 @@ -#pragma once - -#include "flat_sausage_misc.h" -#include "flat_sausage_solid.h" +#pragma once + +#include "flat_sausage_misc.h" +#include "flat_sausage_solid.h" #include "util_basics.h" - -namespace NKikimr { + +namespace NKikimr { namespace NPageCollection { - + class IPageCollection : public TAtomicRefCount<IPageCollection> { - public: + public: virtual ~IPageCollection() = default; - - virtual const TLogoBlobID& Label() const noexcept = 0; - virtual ui32 Total() const noexcept = 0; - virtual TInfo Page(ui32 page) const noexcept = 0; - virtual TBorder Bounds(ui32 page) const noexcept = 0; - virtual TGlobId Glob(ui32 blob) const noexcept = 0; + + virtual const TLogoBlobID& Label() const noexcept = 0; + virtual ui32 Total() const noexcept = 0; + virtual TInfo Page(ui32 page) const noexcept = 0; + virtual TBorder Bounds(ui32 page) const noexcept = 0; + virtual TGlobId Glob(ui32 blob) const noexcept = 0; virtual bool Verify(ui32 page, TArrayRef<const char>) const noexcept = 0; virtual size_t BackingSize() const noexcept = 0; - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_sausage_layout.h b/ydb/core/tablet_flat/flat_sausage_layout.h index 882f2b285b..1c5255ad15 100644 --- a/ydb/core/tablet_flat/flat_sausage_layout.h +++ b/ydb/core/tablet_flat/flat_sausage_layout.h @@ -1,54 +1,54 @@ -#pragma once - +#pragma once + #include <ydb/core/base/logoblob.h> - -namespace NKikimr { + +namespace NKikimr { namespace NPageCollection { - + /* Page collection binary layout (integers are little endian): - - RAW := THeader - , { Blobs * TBlobId } - , { Pages * TEntry } - , { Pages * TExtra } - , Inbound - , ui32_crc; - */ - - using TBlobId = TLogoBlobID; - - enum EMagic: ui64 { - Magic = 0x44320999F0037888ull, - }; - - struct THeader { - ui64 Magic = Max<ui64>(); - ui32 Blobs = 0; - ui32 Pages = 0; - }; - - struct TEntry { - TEntry(ui64 data, ui64 inPlace) - : Page(data) - , Inplace(inPlace) - { - - } - - ui64 Page = 0; /* Page end offset */ - ui64 Inplace = 0; /* Inplace end offset */ - }; - - struct TExtra { - TExtra(ui32 type, ui32 crc) - : Type(type) - , Crc32(crc) - { - - } - - ui32 Type = Max<ui32>(); - ui32 Crc32 = Max<ui32>(); - }; -} -} + + RAW := THeader + , { Blobs * TBlobId } + , { Pages * TEntry } + , { Pages * TExtra } + , Inbound + , ui32_crc; + */ + + using TBlobId = TLogoBlobID; + + enum EMagic: ui64 { + Magic = 0x44320999F0037888ull, + }; + + struct THeader { + ui64 Magic = Max<ui64>(); + ui32 Blobs = 0; + ui32 Pages = 0; + }; + + struct TEntry { + TEntry(ui64 data, ui64 inPlace) + : Page(data) + , Inplace(inPlace) + { + + } + + ui64 Page = 0; /* Page end offset */ + ui64 Inplace = 0; /* Inplace end offset */ + }; + + struct TExtra { + TExtra(ui32 type, ui32 crc) + : Type(type) + , Crc32(crc) + { + + } + + ui32 Type = Max<ui32>(); + ui32 Crc32 = Max<ui32>(); + }; +} +} diff --git a/ydb/core/tablet_flat/flat_sausage_meta.cpp b/ydb/core/tablet_flat/flat_sausage_meta.cpp index 6f708945a0..d2e25165d5 100644 --- a/ydb/core/tablet_flat/flat_sausage_meta.cpp +++ b/ydb/core/tablet_flat/flat_sausage_meta.cpp @@ -1,98 +1,98 @@ -#include "flat_sausage_align.h" -#include "flat_sausage_meta.h" +#include "flat_sausage_align.h" +#include "flat_sausage_meta.h" #include <library/cpp/digest/crc32c/crc32c.h> - -namespace NKikimr { + +namespace NKikimr { namespace NPageCollection { - + TMeta::TMeta(TSharedData raw, ui32 group) - : Raw(std::move(raw)) - , Group(group) -{ + : Raw(std::move(raw)) + , Group(group) +{ Y_VERIFY(Raw.size() >= sizeof(NPageCollection::THeader)); Header = (const NPageCollection::THeader *)Raw.data(); Y_VERIFY(Header->Magic == NPageCollection::Magic); - - if (Header->Pages == 0) - return; - - auto * const blobs = (const TLogoBlobID *)(Header + 1); - + + if (Header->Pages == 0) + return; + + auto * const blobs = (const TLogoBlobID *)(Header + 1); + Index = (const NPageCollection::TEntry*)(blobs + Header->Blobs); Extra = (const NPageCollection::TExtra*)(Index + Header->Pages); - InboundData = (const char *)(Extra + Header->Pages); - - if (const auto blobs = Blobs()) { - ui64 offset = 0; - - Steps.reserve(blobs.size()); - for (auto &one: blobs) - Steps.push_back(offset += one.BlobSize()); - } -} - -TMeta::~TMeta() -{ - -} - -size_t TMeta::BackingSize() const noexcept -{ - return Steps ? Steps.back() : 0; -} - -TBorder TMeta::Bounds(ui32 begin, ui32 end) const noexcept -{ - Y_VERIFY(begin <= end && Max(begin, end) < Header->Pages); - - const ui64 offset = (begin == 0) ? 0 : Index[begin - 1].Page; - - return TAlign(Steps).Lookup(offset, Index[end].Page - offset); -} - -TInfo TMeta::Page(ui32 page) const noexcept -{ + InboundData = (const char *)(Extra + Header->Pages); + + if (const auto blobs = Blobs()) { + ui64 offset = 0; + + Steps.reserve(blobs.size()); + for (auto &one: blobs) + Steps.push_back(offset += one.BlobSize()); + } +} + +TMeta::~TMeta() +{ + +} + +size_t TMeta::BackingSize() const noexcept +{ + return Steps ? Steps.back() : 0; +} + +TBorder TMeta::Bounds(ui32 begin, ui32 end) const noexcept +{ + Y_VERIFY(begin <= end && Max(begin, end) < Header->Pages); + + const ui64 offset = (begin == 0) ? 0 : Index[begin - 1].Page; + + return TAlign(Steps).Lookup(offset, Index[end].Page - offset); +} + +TInfo TMeta::Page(ui32 page) const noexcept +{ Y_VERIFY(page < Header->Pages, "Requested page %" PRIu32 " out of %" PRIu32 " total pages", page, Header->Pages); return { GetPageSize(page), Extra[page].Type }; -} - -ui32 TMeta::GetPageType(ui32 pageId) const noexcept -{ - Y_VERIFY_DEBUG(pageId < Header->Pages); - return Extra[pageId].Type; -} - -ui32 TMeta::GetPageChecksum(ui32 pageId) const noexcept -{ - Y_VERIFY_DEBUG(pageId < Header->Pages); - return Extra[pageId].Crc32; -} - +} + +ui32 TMeta::GetPageType(ui32 pageId) const noexcept +{ + Y_VERIFY_DEBUG(pageId < Header->Pages); + return Extra[pageId].Type; +} + +ui32 TMeta::GetPageChecksum(ui32 pageId) const noexcept +{ + Y_VERIFY_DEBUG(pageId < Header->Pages); + return Extra[pageId].Crc32; +} + ui64 TMeta::GetPageSize(ui32 pageId) const noexcept -{ - Y_VERIFY_DEBUG(pageId < Header->Pages); - - const ui64 begin = (pageId == 0) ? 0 : Index[pageId - 1].Page; - return Index[pageId].Page - begin; -} - -TStringBuf TMeta::GetPageInplaceData(ui32 pageId) const noexcept -{ - Y_VERIFY_DEBUG(pageId < Header->Pages); - - const ui64 end = Index[pageId].Inplace; - const ui64 begin = (pageId == 0) ? 0 : Index[pageId - 1].Inplace; - - return TStringBuf(InboundData + begin, InboundData + end); -} - +{ + Y_VERIFY_DEBUG(pageId < Header->Pages); + + const ui64 begin = (pageId == 0) ? 0 : Index[pageId - 1].Page; + return Index[pageId].Page - begin; +} + +TStringBuf TMeta::GetPageInplaceData(ui32 pageId) const noexcept +{ + Y_VERIFY_DEBUG(pageId < Header->Pages); + + const ui64 end = Index[pageId].Inplace; + const ui64 begin = (pageId == 0) ? 0 : Index[pageId - 1].Inplace; + + return TStringBuf(InboundData + begin, InboundData + end); +} + ui32 Checksum(TArrayRef<const char> body) noexcept -{ - return Crc32c(body.data(), body.size()); -} - -} -} +{ + return Crc32c(body.data(), body.size()); +} + +} +} diff --git a/ydb/core/tablet_flat/flat_sausage_meta.h b/ydb/core/tablet_flat/flat_sausage_meta.h index bb23adc824..659bca8f50 100644 --- a/ydb/core/tablet_flat/flat_sausage_meta.h +++ b/ydb/core/tablet_flat/flat_sausage_meta.h @@ -1,57 +1,57 @@ -#pragma once - -#include "flat_sausage_misc.h" -#include "flat_sausage_layout.h" -#include "flat_sausage_solid.h" +#pragma once +#include "flat_sausage_misc.h" +#include "flat_sausage_layout.h" +#include "flat_sausage_solid.h" + #include <ydb/core/base/shared_data.h> -namespace NKikimr { +namespace NKikimr { namespace NPageCollection { - - class TMeta { - public: + + class TMeta { + public: TMeta(TSharedData blob, ui32 group); - ~TMeta(); - - ui32 TotalPages() const { return Header->Pages; } - - inline TArrayRef<const TLogoBlobID> Blobs() const noexcept - { - auto *blobs = reinterpret_cast<const TLogoBlobID *>(Header + 1); - - return TArrayRef<const TLogoBlobID>(blobs, Header->Blobs); - } - - inline TBorder Bounds(ui32 page) const noexcept - { - return Bounds(page, page); - } - - inline TGlobId Glob(ui32 blob) const noexcept - { - return { Blobs()[blob], Group }; - } - - size_t BackingSize() const noexcept; - TBorder Bounds(ui32 begin, ui32 end) const noexcept; - TInfo Page(ui32 page) const noexcept; - ui32 GetPageType(ui32 pageId) const noexcept; - ui32 GetPageChecksum(ui32 pageId) const noexcept; + ~TMeta(); + + ui32 TotalPages() const { return Header->Pages; } + + inline TArrayRef<const TLogoBlobID> Blobs() const noexcept + { + auto *blobs = reinterpret_cast<const TLogoBlobID *>(Header + 1); + + return TArrayRef<const TLogoBlobID>(blobs, Header->Blobs); + } + + inline TBorder Bounds(ui32 page) const noexcept + { + return Bounds(page, page); + } + + inline TGlobId Glob(ui32 blob) const noexcept + { + return { Blobs()[blob], Group }; + } + + size_t BackingSize() const noexcept; + TBorder Bounds(ui32 begin, ui32 end) const noexcept; + TInfo Page(ui32 page) const noexcept; + ui32 GetPageType(ui32 pageId) const noexcept; + ui32 GetPageChecksum(ui32 pageId) const noexcept; ui64 GetPageSize(ui32 pageId) const noexcept; - TStringBuf GetPageInplaceData(ui32 pageId) const noexcept; - - public: + TStringBuf GetPageInplaceData(ui32 pageId) const noexcept; + + public: const TSharedData Raw; /* Page collection serialized meta blob */ const ui32 Group = TLargeGlobId::InvalidGroup; - - private: - const THeader *Header = nullptr; - const TEntry *Index = nullptr; - const TExtra *Extra = nullptr; - const char *InboundData = nullptr; + + private: + const THeader *Header = nullptr; + const TEntry *Index = nullptr; + const TExtra *Extra = nullptr; + const char *InboundData = nullptr; TVector<ui64> Steps; /* Pages boundaries vector */ - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_sausage_misc.h b/ydb/core/tablet_flat/flat_sausage_misc.h index 591273bced..1a7496f691 100644 --- a/ydb/core/tablet_flat/flat_sausage_misc.h +++ b/ydb/core/tablet_flat/flat_sausage_misc.h @@ -1,43 +1,43 @@ -#pragma once - -#include <util/system/types.h> -#include <util/generic/array_ref.h> - -namespace NKikimr { +#pragma once + +#include <util/system/types.h> +#include <util/generic/array_ref.h> + +namespace NKikimr { namespace NPageCollection { - + ui32 Checksum(TArrayRef<const char> body) noexcept; - - struct TBorder { - struct TOn { - ui32 Blob; - ui32 Skip; - }; - - constexpr explicit operator bool() const noexcept - { - return Lo.Blob != Max<ui32>(); - } - - constexpr ui32 Blobs() const noexcept - { - return 1 + (Up.Blob - Lo.Blob); - } - - ui64 Bytes; /* Total bounded bytes */ - TOn Lo; /* Lower edge point [ */ - TOn Up; /* Upper edge point ) */ - }; - - struct TInfo /* page meta info */ { - explicit operator bool() const - { - return Size > 0; - } - + + struct TBorder { + struct TOn { + ui32 Blob; + ui32 Skip; + }; + + constexpr explicit operator bool() const noexcept + { + return Lo.Blob != Max<ui32>(); + } + + constexpr ui32 Blobs() const noexcept + { + return 1 + (Up.Blob - Lo.Blob); + } + + ui64 Bytes; /* Total bounded bytes */ + TOn Lo; /* Lower edge point [ */ + TOn Up; /* Upper edge point ) */ + }; + + struct TInfo /* page meta info */ { + explicit operator bool() const + { + return Size > 0; + } + ui64 Size; - ui32 Type; - }; - -} -} + ui32 Type; + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_sausage_packet.h b/ydb/core/tablet_flat/flat_sausage_packet.h index 7b53ed6bc7..68c34975d9 100644 --- a/ydb/core/tablet_flat/flat_sausage_packet.h +++ b/ydb/core/tablet_flat/flat_sausage_packet.h @@ -1,74 +1,74 @@ -#pragma once - -#include "flat_sausage_meta.h" -#include "flat_sausage_solid.h" -#include "flat_sausage_gut.h" - -namespace NKikimr { +#pragma once + +#include "flat_sausage_meta.h" +#include "flat_sausage_solid.h" +#include "flat_sausage_gut.h" + +namespace NKikimr { namespace NPageCollection { - + class TPageCollection: public IPageCollection { - public: + public: TPageCollection() = delete; - + TPageCollection(TLargeGlobId largeGlobId, TSharedData raw) : LargeGlobId(largeGlobId) , Meta(std::move(raw), LargeGlobId.Group) - { + { if (!Meta.Raw || LargeGlobId.Bytes != Meta.Raw.size() || LargeGlobId.Group == TLargeGlobId::InvalidGroup) Y_FAIL("Invalid TLargeGlobId of page collection meta blob"); - } - - const TLogoBlobID& Label() const noexcept override - { + } + + const TLogoBlobID& Label() const noexcept override + { return LargeGlobId.Lead; - } - - ui32 Total() const noexcept override - { - return Meta.TotalPages(); - } - - TBorder Bounds(ui32 page) const noexcept override - { - return Meta.Bounds(page); - } - - TGlobId Glob(ui32 blob) const noexcept override - { - return Meta.Glob(blob); - } - - TInfo Page(ui32 page) const noexcept override - { - return Meta.Page(page); - } - + } + + ui32 Total() const noexcept override + { + return Meta.TotalPages(); + } + + TBorder Bounds(ui32 page) const noexcept override + { + return Meta.Bounds(page); + } + + TGlobId Glob(ui32 blob) const noexcept override + { + return Meta.Glob(blob); + } + + TInfo Page(ui32 page) const noexcept override + { + return Meta.Page(page); + } + bool Verify(ui32 page, TArrayRef<const char> body) const noexcept override - { - return - Meta.Page(page).Size == body.size() - && Meta.GetPageChecksum(page) == Checksum(body); - } - + { + return + Meta.Page(page).Size == body.size() + && Meta.GetPageChecksum(page) == Checksum(body); + } + size_t BackingSize() const noexcept override { return Meta.BackingSize(); } - template<typename TContainer> - void SaveAllBlobIdsTo(TContainer &vec) const - { + template<typename TContainer> + void SaveAllBlobIdsTo(TContainer &vec) const + { LargeGlobId.MaterializeTo(vec); - - { - const auto &blobs = Meta.Blobs(); - vec.insert(vec.end(), blobs.begin(), blobs.end()); - } - } - + + { + const auto &blobs = Meta.Blobs(); + vec.insert(vec.end(), blobs.begin(), blobs.end()); + } + } + const TLargeGlobId LargeGlobId; - const TMeta Meta; - }; -} -} + const TMeta Meta; + }; +} +} diff --git a/ydb/core/tablet_flat/flat_sausage_record.h b/ydb/core/tablet_flat/flat_sausage_record.h index 73badbcd0e..1f86a6e3ee 100644 --- a/ydb/core/tablet_flat/flat_sausage_record.h +++ b/ydb/core/tablet_flat/flat_sausage_record.h @@ -1,46 +1,46 @@ -#pragma once - -#include "flat_sausage_layout.h" -#include "flat_util_binary.h" +#pragma once + +#include "flat_sausage_layout.h" +#include "flat_util_binary.h" #include "util_basics.h" - -#include <util/generic/array_ref.h> -#include <util/system/sanitizers.h> - -namespace NKikimr { + +#include <util/generic/array_ref.h> +#include <util/system/sanitizers.h> + +namespace NKikimr { namespace NPageCollection { - - class TRecord { - public: - TRecord(ui32 group): Group(group) { } - - ui32 Pages() const - { - return Index.size(); - } - - TRecord& Push(TArrayRef<const TBlobId> blobs) - { - Blobs.reserve(Blobs.size() + blobs.size()); - - for (auto &one: blobs) Blobs.emplace_back(one); - - return *this; - } - - TRecord& Push(const TBlobId &one) - { - return Blobs.emplace_back(one), *this; - } - + + class TRecord { + public: + TRecord(ui32 group): Group(group) { } + + ui32 Pages() const + { + return Index.size(); + } + + TRecord& Push(TArrayRef<const TBlobId> blobs) + { + Blobs.reserve(Blobs.size() + blobs.size()); + + for (auto &one: blobs) Blobs.emplace_back(one); + + return *this; + } + + TRecord& Push(const TBlobId &one) + { + return Blobs.emplace_back(one), *this; + } + ui32 Push(ui32 type, TArrayRef<const char> body) - { - Index.push_back({ Offset += body.size(), Inbound.size() }); - Extra.push_back({ type, Checksum(body) }); - - return Index.size() - 1; - } - + { + Index.push_back({ Offset += body.size(), Inbound.size() }); + Extra.push_back({ type, Checksum(body) }); + + return Index.size() - 1; + } + void PushInplace(ui32 page, TArrayRef<const char> body) { Y_VERIFY(Index && page == Index.size() - 1); @@ -50,72 +50,72 @@ namespace NPageCollection { } TSharedData Finish() - { + { TSharedData raw = TSharedData::Uninitialized(Bytes()); char* ptr = raw.mutable_begin(); - - { + + { NPageCollection::THeader hdr; - + hdr.Magic = NPageCollection::Magic; - hdr.Blobs = Blobs.size(); - hdr.Pages = Index.size(); - + hdr.Blobs = Blobs.size(); + hdr.Pages = Index.size(); + ::memcpy(ptr, &hdr, sizeof(hdr)); ptr += sizeof(hdr); - } - + } + Add(ptr, Blobs), Add(ptr, Index), Add(ptr, Extra); - + ::memcpy(ptr, Inbound.data(), Inbound.size()); ptr += Inbound.size(); - - { + + { const ui32 crc = Checksum(raw.Slice(0, ptr - raw.begin())); - + ::memcpy(ptr, &crc, sizeof(crc)); ptr += sizeof(crc); - } - + } + Y_VERIFY(ptr == raw.mutable_end()); - NSan::CheckMemIsInitialized(raw.data(), raw.size()); - + NSan::CheckMemIsInitialized(raw.data(), raw.size()); + Blobs.clear(); Index.clear(); Extra.clear(); Offset = 0; Inbound = { }; - return raw; - } - - size_t Bytes() const - { - return - sizeof(THeader) + Inbound.size() + sizeof(ui32) - + NUtil::NBin::SizeOf(Blobs, Index, Extra); - } - + return raw; + } + + size_t Bytes() const + { + return + sizeof(THeader) + Inbound.size() + sizeof(ui32) + + NUtil::NBin::SizeOf(Blobs, Index, Extra); + } + private: - template<typename TVal> + template<typename TVal> static inline void Add(char* &ptr, const TVector<TVal> &vec) - { - const auto bytes = NUtil::NBin::SizeOf(vec); - + { + const auto bytes = NUtil::NBin::SizeOf(vec); + ::memcpy(ptr, vec.data(), bytes); ptr += bytes; - } - - public: + } + + public: const ui32 Group = TLargeGlobId::InvalidGroup; - - private: + + private: TVector<TBlobId> Blobs; TVector<TEntry> Index; TVector<TExtra> Extra; - - ui64 Offset = 0; + + ui64 Offset = 0; TString Inbound; - }; -} -} + }; +} +} diff --git a/ydb/core/tablet_flat/flat_sausage_slicer.h b/ydb/core/tablet_flat/flat_sausage_slicer.h index 0dd6230902..8404e046d3 100644 --- a/ydb/core/tablet_flat/flat_sausage_slicer.h +++ b/ydb/core/tablet_flat/flat_sausage_slicer.h @@ -1,82 +1,82 @@ -#pragma once - -#include "util_fmt_abort.h" -#include "flat_sausage_grind.h" -#include <util/thread/singleton.h> +#pragma once + +#include "util_fmt_abort.h" +#include "flat_sausage_grind.h" +#include <util/thread/singleton.h> #include <library/cpp/blockcodecs/codecs.h> - -namespace NKikimr { + +namespace NKikimr { namespace NPageCollection { - - struct TSlicer { - + + struct TSlicer { + TSlicer(ui8 channel, TCookieAllocator *cookieAllocator, ui32 block) - : Channel(channel) - , Block(block) + : Channel(channel) + , Block(block) , CookieAllocator(cookieAllocator) - { - - } - - TGlobId One(TVector<TLogoBlob> &refs, TString body, bool lz4) const - { - if (body.size() > Block) { - Y_Fail( + { + + } + + TGlobId One(TVector<TLogoBlob> &refs, TString body, bool lz4) const + { + if (body.size() > Block) { + Y_Fail( "Cannot put " << body.size() << "b to "<< NFmt::Do(*CookieAllocator) - << " as single blob, block limit is " << Block << "b"); - } - + << " as single blob, block limit is " << Block << "b"); + } + Y_VERIFY(body.size() < Block, "Too large blob to be a TGlobId"); - - if (lz4) std::exchange(body, Lz4()->Encode(body)); - + + if (lz4) std::exchange(body, Lz4()->Encode(body)); + auto glob = CookieAllocator->Do(Channel, body.size()); - - refs.push_back({ glob.Logo, std::move(body) }); - - return glob; - } - + + refs.push_back({ glob.Logo, std::move(body) }); + + return glob; + } + TLargeGlobId Do(TVector<TLogoBlob> &refs, TString body, bool lz4) const - { - if (body.size() >= Max<ui32>()) { - Y_Fail( + { + if (body.size() >= Max<ui32>()) { + Y_Fail( "Cannot put " << body.size() << "b to "<< NFmt::Do(*CookieAllocator) - << " as a TSloid, blob have to be less than 4GiB"); - } - - if (lz4) std::exchange(body, Lz4()->Encode(body)); - - const ui32 size = body.size(); + << " as a TSloid, blob have to be less than 4GiB"); + } + + if (lz4) std::exchange(body, Lz4()->Encode(body)); + + const ui32 size = body.size(); auto largeGlobId = CookieAllocator->Do(Channel, size, Block); - - if (size <= Block) { + + if (size <= Block) { refs.push_back({ largeGlobId.Lead, std::move(body) }); - } else { + } else { ui32 off = 0; for (auto blobId : largeGlobId.Blobs()) { const ui32 chunk = Min(Block, size - off); Y_VERIFY_DEBUG(chunk == blobId.BlobSize()); refs.push_back({ blobId, body.substr(off, chunk) }); - off += chunk; - } + off += chunk; + } Y_VERIFY_DEBUG(off == largeGlobId.Bytes); - } - + } + return largeGlobId; - } - - static inline const NBlockCodecs::ICodec* Lz4() noexcept - { - auto **lz4 = FastTlsSingleton<const NBlockCodecs::ICodec*>(); - - return *lz4 ? *lz4 : (*lz4 = NBlockCodecs::Codec("lz4fast")); - } - - private: - const ui8 Channel = Max<ui8>(); - const ui32 Block = Max<ui32>(); + } + + static inline const NBlockCodecs::ICodec* Lz4() noexcept + { + auto **lz4 = FastTlsSingleton<const NBlockCodecs::ICodec*>(); + + return *lz4 ? *lz4 : (*lz4 = NBlockCodecs::Codec("lz4fast")); + } + + private: + const ui8 Channel = Max<ui8>(); + const ui32 Block = Max<ui32>(); TCookieAllocator * const CookieAllocator = nullptr; - }; -} -} + }; +} +} diff --git a/ydb/core/tablet_flat/flat_sausage_solid.h b/ydb/core/tablet_flat/flat_sausage_solid.h index 32049333bb..109d2dbc51 100644 --- a/ydb/core/tablet_flat/flat_sausage_solid.h +++ b/ydb/core/tablet_flat/flat_sausage_solid.h @@ -1,59 +1,59 @@ -#pragma once - +#pragma once + #include <ydb/core/base/logoblob.h> #include <ydb/core/base/shared_data.h> - -namespace NKikimr { + +namespace NKikimr { namespace NPageCollection { - + struct TLargeGlobId { - /* ... is a piece of some data up to 4GiB placed on a continous - series of TLogoBlobs which IDs are differs only in cookie and - have the single upper chunk bytes limit. All blobs of span have - the same BS storage group. - */ - + /* ... is a piece of some data up to 4GiB placed on a continous + series of TLogoBlobs which IDs are differs only in cookie and + have the single upper chunk bytes limit. All blobs of span have + the same BS storage group. + */ + constexpr static ui32 InvalidGroup = (Max<ui32>() >> 1); - + TLargeGlobId() { }; - + TLargeGlobId(ui32 group, TLogoBlobID single) : TLargeGlobId(group, single, single.BlobSize()) - { - - } - + { + + } + TLargeGlobId(ui32 group, const TLogoBlobID &lead, ui64 bytes) - : Group(group) - , Bytes(bytes) - , Lead(lead) - { + : Group(group) + , Bytes(bytes) + , Lead(lead) + { //Y_VERIFY(Group != InvalidGroup, "Invalid TLargeGlobId storage group"); - Y_VERIFY(Lead && Lead.BlobSize() && Lead.BlobSize() <= Bytes); - } - - void Describe(IOutputStream &out) const noexcept - { - out + Y_VERIFY(Lead && Lead.BlobSize() && Lead.BlobSize() <= Bytes); + } + + void Describe(IOutputStream &out) const noexcept + { + out << "TLargeGlobId{" << Lead << " ~" << Bytes - << "b, grp " << Group << "}"; - } - - explicit operator bool() const noexcept - { - return Bytes > 0; - } - + << "b, grp " << Group << "}"; + } + + explicit operator bool() const noexcept + { + return Bytes > 0; + } + bool operator==(const TLargeGlobId &so) const noexcept - { - return Lead == so.Lead && Group == so.Group && Bytes == so.Bytes; - } - + { + return Lead == so.Lead && Group == so.Group && Bytes == so.Bytes; + } + class TBlobsEndIterator { public: TBlobsEndIterator() = default; }; - + class TBlobsIterator { public: TBlobsIterator(const TLogoBlobID& lead, ui32 bytes) @@ -63,7 +63,7 @@ namespace NPageCollection { const TLogoBlobID& operator*() const { return Current; - } + } const TLogoBlobID* operator->() const { return &Current; @@ -120,82 +120,82 @@ namespace NPageCollection { TBlobsRange Blobs() const noexcept { return TBlobsRange(Lead, Bytes); - } - + } + ui32 BlobCount() const noexcept - { - const auto limit = Lead.BlobSize(); - - return Bytes / limit + (Bytes % limit > 0); - } - - template<typename TOut> - void MaterializeTo(TOut &out) const noexcept - { + { + const auto limit = Lead.BlobSize(); + + return Bytes / limit + (Bytes % limit > 0); + } + + template<typename TOut> + void MaterializeTo(TOut &out) const noexcept + { for (auto blobId : Blobs()) { out.emplace_back(blobId); } - } - + } + ui32 Group = InvalidGroup; - ui32 Bytes = 0; /* Total bytes in sequence */ - TLogoBlobID Lead; /* First blob in sequence */ - }; - - struct TGlobId { /* Just single reference to TLogoBlob in group */ - TGlobId() { }; - - TGlobId(const TLogoBlobID &logo, ui32 group) - : Logo(logo) - , Group(group) - { - - } - - explicit operator bool() const noexcept - { - return bool(Logo); - } - - bool operator!=(const TGlobId &glob) const noexcept - { - return Group != glob.Group || Logo != glob.Logo; - } - - bool operator==(const TGlobId &glob) const noexcept - { - return Group == glob.Group && Logo == glob.Logo; - } - - ui32 Bytes() const noexcept - { - return Logo.BlobSize(); - } - - TLogoBlobID Logo; + ui32 Bytes = 0; /* Total bytes in sequence */ + TLogoBlobID Lead; /* First blob in sequence */ + }; + + struct TGlobId { /* Just single reference to TLogoBlob in group */ + TGlobId() { }; + + TGlobId(const TLogoBlobID &logo, ui32 group) + : Logo(logo) + , Group(group) + { + + } + + explicit operator bool() const noexcept + { + return bool(Logo); + } + + bool operator!=(const TGlobId &glob) const noexcept + { + return Group != glob.Group || Logo != glob.Logo; + } + + bool operator==(const TGlobId &glob) const noexcept + { + return Group == glob.Group && Logo == glob.Logo; + } + + ui32 Bytes() const noexcept + { + return Logo.BlobSize(); + } + + TLogoBlobID Logo; ui32 Group = TLargeGlobId::InvalidGroup; - ui32 Pad0_ = 0; /* Padding to 32 byte boundary, unused */ - }; - + ui32 Pad0_ = 0; /* Padding to 32 byte boundary, unused */ + }; + /** * Large blob that is written to blobstorage * * Data is stored in TString so there are less copies and conversions. */ - struct TGlob { + struct TGlob { TGlob(const TGlobId& id, TString data) - : GId(id) - , Data(std::move(data)) - { - - } - - ui32 Bytes() const noexcept - { - return GId.Logo.BlobSize(); - } - - TGlobId GId; + : GId(id) + , Data(std::move(data)) + { + + } + + ui32 Bytes() const noexcept + { + return GId.Logo.BlobSize(); + } + + TGlobId GId; TString Data; }; @@ -221,8 +221,8 @@ namespace NPageCollection { TGlobId GId; TSharedData Data; - }; - + }; + class TLargeGlobIdRestoreState { using TBlobs = TVector<TLogoBlobID>; using TBodies = TVector<TString>; @@ -304,5 +304,5 @@ namespace NPageCollection { size_t BytesLoaded = 0; }; -} -} +} +} diff --git a/ydb/core/tablet_flat/flat_sausage_writer.h b/ydb/core/tablet_flat/flat_sausage_writer.h index c7cda9e2a4..31c5a864d5 100644 --- a/ydb/core/tablet_flat/flat_sausage_writer.h +++ b/ydb/core/tablet_flat/flat_sausage_writer.h @@ -1,55 +1,55 @@ -#pragma once - -#include "flat_sausage_record.h" -#include "flat_sausage_grind.h" +#pragma once + +#include "flat_sausage_record.h" +#include "flat_sausage_grind.h" #include "util_basics.h" - -namespace NKikimr { + +namespace NKikimr { namespace NPageCollection { - - class TWriter { - public: + + class TWriter { + public: TWriter(TCookieAllocator &cookieAllocator, ui8 channel, ui32 block) - : Block(block) - , Channel(channel) + : Block(block) + , Channel(channel) , CookieAllocator(cookieAllocator) , Record(cookieAllocator.GroupBy(channel)) - { - - } - + { + + } + explicit operator bool() const { return Record.Pages() || Blobs || Buffer; } ui32 AddPage(const TArrayRef<const char> body, ui32 type) - { - for (size_t offset = 0; offset < body.size(); ) { - if (Buffer.capacity() == 0 && Block != Max<ui32>()) - Buffer.reserve(Min(Block, ui32(16 * 1024 * 1024))); - - auto piece = Min(body.size() - offset, Block - Buffer.size()); + { + for (size_t offset = 0; offset < body.size(); ) { + if (Buffer.capacity() == 0 && Block != Max<ui32>()) + Buffer.reserve(Min(Block, ui32(16 * 1024 * 1024))); + + auto piece = Min(body.size() - offset, Block - Buffer.size()); auto chunk = body.Slice(offset, piece); - + Buffer.append(chunk.data(), chunk.size()); - offset += piece; - - if (Buffer.size() >= Block) Flush(); - } - + offset += piece; + + if (Buffer.size() >= Block) Flush(); + } + return Record.Push(type, body); - } - + } + void AddInplace(ui32 page, TArrayRef<const char> body) { Record.PushInplace(page, body); } TSharedData Finish(bool empty) - { - Flush(); - + { + Flush(); + TSharedData meta; if (Record.Pages() || empty) { @@ -57,26 +57,26 @@ namespace NPageCollection { } return meta; - } - - TVector<TGlob> Grab() noexcept - { - return std::exchange(Blobs, TVector<TGlob>()); - } - - private: - void Flush() noexcept - { - if (Buffer) { + } + + TVector<TGlob> Grab() noexcept + { + return std::exchange(Blobs, TVector<TGlob>()); + } + + private: + void Flush() noexcept + { + if (Buffer) { auto glob = CookieAllocator.Do(Channel, Buffer.size()); - - Y_VERIFY(glob.Group == Record.Group, "Unexpected BS group"); - + + Y_VERIFY(glob.Group == Record.Group, "Unexpected BS group"); + Blobs.emplace_back(glob, TakeBuffer()); - Record.Push(glob.Logo); - } - } - + Record.Push(glob.Logo); + } + } + TString TakeBuffer() noexcept { TString data; @@ -94,15 +94,15 @@ namespace NPageCollection { return data; } - public: - const ui32 Block = Max<ui32>(); - const ui8 Channel = Max<ui8>(); - private: + public: + const ui32 Block = Max<ui32>(); + const ui8 Channel = Max<ui8>(); + private: TString Buffer; TCookieAllocator &CookieAllocator; - TVector<TGlob> Blobs; + TVector<TGlob> Blobs; NPageCollection::TRecord Record; - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_sausagecache.cpp b/ydb/core/tablet_flat/flat_sausagecache.cpp index 4d396e8f75..ae51854196 100644 --- a/ydb/core/tablet_flat/flat_sausagecache.cpp +++ b/ydb/core/tablet_flat/flat_sausagecache.cpp @@ -24,10 +24,10 @@ TPrivatePageCache::TInfo::TInfo(TIntrusiveConstPtr<NPageCollection::IPageCollect } TPrivatePageCache::TInfo::TInfo(const TInfo &info) - : Id(info.Id) + : Id(info.Id) , PageCollection(info.PageCollection) , Users(info.Users) -{ +{ PageMap.resize(info.PageMap.size()); for (const auto& kv : info.PageMap) { auto* src = kv.second.Get(); @@ -40,8 +40,8 @@ TPrivatePageCache::TInfo::TInfo(const TInfo &info) dst->Sticky = src->Sticky; } } -} - +} + TPrivatePageCache::TPrivatePageCache(const TCacheCacheConfig &cacheConfig, bool prepareForSharedCache) : Cache(cacheConfig) , PrepareForSharedCache(prepareForSharedCache) @@ -254,9 +254,9 @@ std::pair<ui32, ui64> TPrivatePageCache::Load(TVector<ui32> &pages, TPrivatePage ui32 blocksToRequest = 0; ui64 bytesToRequest = 0; - auto it = pages.begin(); - auto end = pages.end(); - + auto it = pages.begin(); + auto end = pages.end(); + while (it != end) { TPage *page = info->EnsurePage(*it); switch (page->LoadState) { @@ -265,12 +265,12 @@ std::pair<ui32, ui64> TPrivatePageCache::Load(TVector<ui32> &pages, TPrivatePage [[fallthrough]]; case TPage::LoadStateRequestedAsync: page->LoadState = TPage::LoadStateRequested; - bytesToRequest += page->Size; + bytesToRequest += page->Size; Y_VERIFY(!page->WaitQueue); - page->WaitQueue = new TPage::TWaitQueue(); - page->WaitQueue->Push(waitPad); - waitPad->Inc(); + page->WaitQueue = new TPage::TWaitQueue(); + page->WaitQueue->Push(waitPad); + waitPad->Inc(); ++blocksToRequest; ++it; @@ -278,11 +278,11 @@ std::pair<ui32, ui64> TPrivatePageCache::Load(TVector<ui32> &pages, TPrivatePage case TPage::LoadStateLoaded: Y_FAIL("must not request already loaded pages"); case TPage::LoadStateRequested: - if (!page->WaitQueue) - page->WaitQueue = new TPage::TWaitQueue(); + if (!page->WaitQueue) + page->WaitQueue = new TPage::TWaitQueue(); - page->WaitQueue->Push(waitPad); - waitPad->Inc(); + page->WaitQueue->Push(waitPad); + waitPad->Inc(); --end; if (end != it) @@ -290,7 +290,7 @@ std::pair<ui32, ui64> TPrivatePageCache::Load(TVector<ui32> &pages, TPrivatePage break; } } - pages.erase(end, pages.end()); + pages.erase(end, pages.end()); return std::make_pair(blocksToRequest, bytesToRequest); } @@ -396,7 +396,7 @@ THashMap<TLogoBlobID, TIntrusivePtr<TPrivatePageCache::TInfo>> TPrivatePageCache THashMap<TLogoBlobID, TIntrusivePtr<TPrivatePageCache::TInfo>> ret; for (const auto &xpair : PageCollections) { - TIntrusivePtr<TInfo> info(new TInfo(*xpair.second)); + TIntrusivePtr<TInfo> info(new TInfo(*xpair.second)); ret.insert(std::make_pair(xpair.first, info)); } diff --git a/ydb/core/tablet_flat/flat_sausagecache.h b/ydb/core/tablet_flat/flat_sausagecache.h index ac040eb017..56df92c521 100644 --- a/ydb/core/tablet_flat/flat_sausagecache.h +++ b/ydb/core/tablet_flat/flat_sausagecache.h @@ -1,7 +1,7 @@ #pragma once #include "defs.h" -#include "flat_sausage_gut.h" -#include "flat_sausage_fetch.h" +#include "flat_sausage_gut.h" +#include "flat_sausage_fetch.h" #include "shared_handle.h" #include "shared_cache_events.h" #include <ydb/core/util/cache_cache.h> @@ -12,7 +12,7 @@ namespace NTabletFlatExecutor { struct TPrivatePageCachePinPad : public TAtomicRefCount<TPrivatePageCachePinPad> { // no internal state -}; +}; struct TPrivatePageCacheWaitPad : public TExplicitSimpleCounter { // no internal state @@ -76,10 +76,10 @@ public: void Fill(TSharedData data, bool sticky = false) { Y_VERIFY_DEBUG(!SharedBody && !SharedPending, "Populating cache with shared data already present"); Sticky = sticky; - LoadState = LoadStateLoaded; + LoadState = LoadStateLoaded; PinnedBody = std::move(data); - } - + } + void Fill(TSharedPageRef shared, bool sticky = false) { Sticky = sticky; SharedPending = false; @@ -90,8 +90,8 @@ public: const TSharedData* GetBody() const noexcept { return LoadState == LoadStateLoaded ? &PinnedBody : nullptr; - } - + } + TSharedPageRef GetShared() const noexcept { if (LoadState == LoadStateLoaded) { if (SharedBody) { @@ -137,8 +137,8 @@ public: const TSharedData* Lookup(ui32 pageId) const noexcept { auto* page = GetPage(pageId); return page ? page->GetBody() : nullptr; - } - + } + TPage* GetPage(ui32 pageId) const noexcept { return PageMap[pageId].Get(); } @@ -153,8 +153,8 @@ public: void Fill(const NPageCollection::TLoadedPage &paged, bool sticky = false) noexcept { EnsurePage(paged.PageId)->Fill(paged.Data, sticky); - } - + } + void Fill(NSharedCache::TEvResult::TLoaded&& loaded, bool sticky = false) noexcept { EnsurePage(loaded.PageId)->Fill(std::move(loaded.Page), sticky); } @@ -231,7 +231,7 @@ public: ui64 Users; explicit TInfo(TIntrusiveConstPtr<NPageCollection::IPageCollection> pack); - TInfo(const TInfo &info); + TInfo(const TInfo &info); }; public: diff --git a/ydb/core/tablet_flat/flat_scan_actor.h b/ydb/core/tablet_flat/flat_scan_actor.h index 5cbf2797a0..0f7882e213 100644 --- a/ydb/core/tablet_flat/flat_scan_actor.h +++ b/ydb/core/tablet_flat/flat_scan_actor.h @@ -1,47 +1,47 @@ -#pragma once - -#include "flat_scan_feed.h" -#include "flat_scan_events.h" -#include "flat_scan_eggs.h" -#include "flat_scan_spent.h" -#include "flat_bio_events.h" -#include "flat_fwd_env.h" -#include "util_fmt_logger.h" -#include "util_fmt_desc.h" +#pragma once + +#include "flat_scan_feed.h" +#include "flat_scan_events.h" +#include "flat_scan_eggs.h" +#include "flat_scan_spent.h" +#include "flat_bio_events.h" +#include "flat_fwd_env.h" +#include "util_fmt_logger.h" +#include "util_fmt_desc.h" #include "shared_sausagecache.h" #include "flat_part_store.h" #include "flat_load_blob_queue.h" - + #include <ydb/core/base/appdata.h> #include <ydb/core/base/counters.h> #include <library/cpp/actors/core/actor.h> #include <library/cpp/actors/core/actor_bootstrapped.h> #include <library/cpp/actors/core/hfunc.h> -#include <util/generic/cast.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NOps { - - class TDriver final +#include <util/generic/cast.h> + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NOps { + + class TDriver final : public ::NActors::TActor<TDriver> - , private NTable::TFeed - , private NTable::IDriver + , private NTable::TFeed + , private NTable::IDriver , private ILoadBlob - { - public: - using TSubset = NTable::TSubset; + { + public: + using TSubset = NTable::TSubset; using TPartView = NTable::TPartView; using TPartStore = NTable::TPartStore; using TColdPart = NTable::TColdPart; using TColdPartStore = NTable::TColdPartStore; - using TEnv = NTable::NFwd::TEnv; - using TSpent = NTable::TSpent; + using TEnv = NTable::NFwd::TEnv; + using TSpent = NTable::TSpent; using IScan = NTable::IScan; - using EScan = NTable::EScan; - using EAbort = NTable::EAbort; - using ELnLev = NUtil::ELnLev; - + using EScan = NTable::EScan; + using EAbort = NTable::EAbort; + using ELnLev = NUtil::ELnLev; + static constexpr NKikimrServices::TActivity::EType ActorActivityType() { return NKikimrServices::TActivity::TABLET_OPS_HOST_A; } @@ -49,35 +49,35 @@ namespace NOps { TDriver(ui64 serial, TAutoPtr<IScan> scan, TConf args, THolder<TScanSnapshot> snapshot) : TActor(&TDriver::StateBoot) , NTable::TFeed(scan.Release(), *snapshot->Subset, snapshot->Snapshot) - , Serial(serial) + , Serial(serial) , Args(args) , Snapshot(std::move(snapshot)) , MaxCyclesPerIteration(/* 10ms */ (NHPTimer::GetCyclesPerSecond() + 99) / 100) - { - } - - ~TDriver() - { + { + } + + ~TDriver() + { /* Correct actors shutdown hasn't been implemented in - kikimr, thus actors may be destructed in incompleted state - and dtor cannot be used for completeness checkups. - - Moreover, special workaround is required in case of sudden - actor system shutdown happens before Bootstrap(...). - */ - + kikimr, thus actors may be destructed in incompleted state + and dtor cannot be used for completeness checkups. + + Moreover, special workaround is required in case of sudden + actor system shutdown happens before Bootstrap(...). + */ + if (Scan && Spent == nullptr) delete DetachScan(); - } - + } + void Describe(IOutputStream &out) const noexcept override - { + { out << "Scan{" << Serial << " on " << Snapshot->Table << ", " << NFmt::Do(*Scan) << "}"; - } - - private: + } + + private: struct TEvPrivate { enum EEv { EvLoadBlob = EventSpaceBegin(TKikimrEvents::ES_PRIVATE), @@ -240,10 +240,10 @@ namespace NOps { }; private: - void MakeCache() noexcept - { - NTable::NFwd::TConf conf; - + void MakeCache() noexcept + { + NTable::NFwd::TConf conf; + conf.AheadLo = Args.AheadLo; conf.AheadHi = Args.AheadHi; @@ -258,9 +258,9 @@ namespace NOps { conf.AheadLo = Min(conf.AheadLo, conf.AheadHi); conf.Trace = Args.Trace; - conf.Edge = Conf.LargeEdge; - conf.Tablet = Args.Tablet; - + conf.Edge = Conf.LargeEdge; + conf.Tablet = Args.Tablet; + Cache = new TEnv(conf, Subset); BlobQueue.Config.TabletID = Args.Tablet; @@ -278,10 +278,10 @@ namespace NOps { BlobQueue.Config.ReadPrio = NKikimrBlobStorage::LowRead; break; } - } - - NTable::IPages* MakeEnv() noexcept override - { + } + + NTable::IPages* MakeEnv() noexcept override + { if (Resets++ != 0) { Cache->Reset(); for (const auto& pr : ColdPartLoaded) { @@ -290,8 +290,8 @@ namespace NOps { } return Cache.Get(); - } - + } + TPartView LoadPart(const TIntrusiveConstPtr<TColdPart>& part) noexcept override { const auto label = part->Label; @@ -317,15 +317,15 @@ namespace NOps { return Cache->MayProgress() && ColdPartLoaders.empty(); } - void Touch(EScan scan) noexcept override - { - Y_VERIFY(Depth == 0, "Touch(..) is used from invalid context"); - + void Touch(EScan scan) noexcept override + { + Y_VERIFY(Depth == 0, "Touch(..) is used from invalid context"); + switch (scan) { case EScan::Feed: case EScan::Reset: Resume(scan); - + if (MayProgress()) { return React(); } @@ -337,22 +337,22 @@ namespace NOps { case EScan::Sleep: Y_FAIL("Scan actor got an unexpected EScan::Sleep"); - } + } Y_FAIL("Scan actor got an unexpected EScan value"); - } - + } + void Registered(TActorSystem *sys, const TActorId &owner) override - { - Owner = owner; - Logger = new NUtil::TLogger(sys, NKikimrServices::TABLET_OPS_HOST); - sys->Send(SelfId(), new TEvents::TEvBootstrap); - } - + { + Owner = owner; + Logger = new NUtil::TLogger(sys, NKikimrServices::TABLET_OPS_HOST); + sys->Send(SelfId(), new TEvents::TEvBootstrap); + } + STRICT_STFUNC(StateBoot, { cFunc(TEvents::TEvBootstrap::EventType, Bootstrap); }); - + STRICT_STFUNC(StateWork, { hFunc(TEvContinue, Handle); hFunc(TEvPrivate::TEvLoadBlob, Handle); @@ -367,35 +367,35 @@ namespace NOps { cFunc(TEvents::TEvPoison::EventType, HandlePoison); }); - void Bootstrap() noexcept - { - Y_VERIFY(!Spent, "Talble scan actor bootstrapped twice"); - - Spent = new TSpent(TAppData::TimeProvider.Get()); - - if (auto logl = Logger->Log(ELnLev::Info)) { - logl + void Bootstrap() noexcept + { + Y_VERIFY(!Spent, "Talble scan actor bootstrapped twice"); + + Spent = new TSpent(TAppData::TimeProvider.Get()); + + if (auto logl = Logger->Log(ELnLev::Info)) { + logl << NFmt::Do(*this) << " begin on " << NFmt::Do(Subset); - } - + } + Become(&TDriver::StateWork); - { - TGuard<ui64, NUtil::TIncDecOps<ui64>> guard(Depth); - + { + TGuard<ui64, NUtil::TIncDecOps<ui64>> guard(Depth); + auto hello = Scan->Prepare(this, Subset.Scheme); - - Conf = hello.Conf; - - guard.Release(); - - MakeCache(); - - if (hello.Scan != EScan::Sleep) - Touch(hello.Scan); - } - } - + + Conf = hello.Conf; + + guard.Release(); + + MakeCache(); + + if (hello.Scan != EScan::Sleep) + Touch(hello.Scan); + } + } + /** * Helper for calculating TEvScanStat */ @@ -440,13 +440,13 @@ namespace NOps { SendToOwner(new TEvScanStat(elapsedUs, stat.Seen, stat.Skipped)); } - void React() noexcept - { - TGuard<ui64, NUtil::TIncDecOps<ui64>> guard(Depth); - + void React() noexcept + { + TGuard<ui64, NUtil::TIncDecOps<ui64>> guard(Depth); + Y_VERIFY_DEBUG(MayProgress(), "React called with non-ready cache"); Y_VERIFY(Scan, "Table scan op has been finalized"); - + TStatState stat(Seen, Skipped); ui64 processed = 0; bool yield = false; @@ -467,10 +467,10 @@ namespace NOps { processed = 0; } - const auto ready = Process(); - + const auto ready = Process(); + processed += stat.UpdateRows(Seen, Skipped); - + if (ready == NTable::EReady::Gone) { Terminate(EAbort::None); stat.UpdateCycles(); @@ -478,10 +478,10 @@ namespace NOps { return; } - while (auto req = Cache->GrabFetches()) { - if (auto logl = Logger->Log(ELnLev::Debug)) - logl << NFmt::Do(*this) << " " << NFmt::Do(*req); - + while (auto req = Cache->GrabFetches()) { + if (auto logl = Logger->Log(ELnLev::Debug)) + logl << NFmt::Do(*this) << " " << NFmt::Do(*req); + const auto label = req->PageCollection->Label(); if (PrivateCollections.contains(label)) { Send(MakeSharedPageCacheId(), new NSharedCache::TEvRequest(Args.ReadPrio, req, SelfId())); @@ -489,10 +489,10 @@ namespace NOps { } else { SendToOwner(new NSharedCache::TEvRequest(Args.ReadPrio, req, Owner), true); } - } - - if (ready == NTable::EReady::Page) - break; /* pages required or just suspended */ + } + + if (ready == NTable::EReady::Page) + break; /* pages required or just suspended */ if (!MayProgress()) { // We must honor EReady::Gone from an implicit callback @@ -505,18 +505,18 @@ namespace NOps { break; } - } - + } + Spent->Alter(MayProgress()); if (!yield) { stat.UpdateCycles(); } SendStat(stat); - } - + } + void Handle(TEvContinue::TPtr&) noexcept - { + { Y_VERIFY(ContinueInFly); ContinueInFly = false; @@ -623,33 +623,33 @@ namespace NOps { { auto& msg = *ev->Get(); - auto lvl = msg.Status ? ELnLev::Error : ELnLev::Debug; - - if (auto logl = Logger->Log(lvl)) - logl << NFmt::Do(*this) << " " << NFmt::Do(msg); - + auto lvl = msg.Status ? ELnLev::Error : ELnLev::Debug; + + if (auto logl = Logger->Log(lvl)) + logl << NFmt::Do(*this) << " " << NFmt::Do(msg); + if (msg.Status != NKikimrProto::OK) { if (msg.Status == NKikimrProto::NODATA) { GetServiceCounters(AppData()->Counters, "tablets")->GetCounter("alerts_scan_nodata", true)->Inc(); } - return Terminate(EAbort::Host); + return Terminate(EAbort::Host); } - + // TODO: would want to postpone pinning until usage TVector<NPageCollection::TLoadedPage> pinned(Reserve(msg.Loaded.size())); for (auto& loaded : msg.Loaded) { pinned.emplace_back(loaded.PageId, TPinnedPageRef(loaded.Page).GetData()); } - + Cache->DoSave(std::move(msg.Origin), msg.Cookie, pinned); if (MayProgress()) { - Spent->Alter(true /* resource available again */); - React(); - } - } - + Spent->Alter(true /* resource available again */); + React(); + } + } + void HandleUndelivered() noexcept { Terminate(EAbort::Lost); @@ -660,39 +660,39 @@ namespace NOps { Terminate(EAbort::Term); } - void Terminate(EAbort abort) noexcept - { + void Terminate(EAbort abort) noexcept + { auto trace = Args.Trace ? Cache->GrabTraces() : nullptr; - - if (auto logl = Logger->Log(ELnLev::Info)) { - logl - << NFmt::Do(*this) << " end=" << ui32(abort) - << ", " << Seen << "r seen, " << NFmt::Do(Cache->Stats()) - << ", bio " << NFmt::If(Spent.Get()); - - if (trace) - logl - << ", trace " << trace->Seen << " of " << trace->Total - << " ~" << trace->Sieve.size() << "p"; - } - - /* Each Flatten should have its trace on the same position */ - + + if (auto logl = Logger->Log(ELnLev::Info)) { + logl + << NFmt::Do(*this) << " end=" << ui32(abort) + << ", " << Seen << "r seen, " << NFmt::Do(Cache->Stats()) + << ", bio " << NFmt::If(Spent.Get()); + + if (trace) + logl + << ", trace " << trace->Seen << " of " << trace->Total + << " ~" << trace->Sieve.size() << "p"; + } + + /* Each Flatten should have its trace on the same position */ + Y_VERIFY(!trace || trace->Sieve.size() == Subset.Flatten.size() + 1); - + /* After invocation of Finish(...) scan object is left on its own and it has to handle self deletion if required. */ - + auto prod = DetachScan()->Finish(abort); - - if (abort != EAbort::Lost) { + + if (abort != EAbort::Lost) { auto ev = new TEvResult(Serial, abort, std::move(Snapshot), prod); - - ev->Trace = std::move(trace); - + + ev->Trace = std::move(trace); + SendToOwner(ev); - } - + } + for (const auto& pr : ColdPartLoaders) { Send(pr.second, new TEvents::TEvPoison); } @@ -701,38 +701,38 @@ namespace NOps { Send(MakeSharedPageCacheId(), new NSharedCache::TEvUnregister); } - PassAway(); - } - + PassAway(); + } + void SendToSelf(THolder<IEventBase> event) noexcept - { + { Send(SelfId(), event.Release()); } void SendToOwner(TAutoPtr<IEventBase> event, bool nack = false) noexcept { - ui32 flags = nack ? NActors::IEventHandle::FlagTrackDelivery : 0; - + ui32 flags = nack ? NActors::IEventHandle::FlagTrackDelivery : 0; + Send(Owner, event.Release(), flags); - } - - private: + } + + private: struct TBlobQueueRequest { TActorId Sender; ui64 Cookie; }; private: - const ui64 Serial = 0; + const ui64 Serial = 0; const NOps::TConf Args; TAutoPtr<NUtil::ILogger> Logger; TActorId Owner; - + THolder<TScanSnapshot> Snapshot; TAutoPtr<TEnv> Cache; /* NFwd scan read ahead cache */ TAutoPtr<TSpent> Spent; /* NBlockIO read blockage stats */ - ui64 Depth = 0; - ui64 Resets = 0; + ui64 Depth = 0; + ui64 Resets = 0; THashMap<TLogoBlobID, TActorId> ColdPartLoaders; THashMap<TLogoBlobID, TPartView> ColdPartLoaded; @@ -747,8 +747,8 @@ namespace NOps { const NHPTimer::STime MaxCyclesPerIteration; static constexpr ui64 MinRowsPerCheck = 1000; - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_scan_eggs.h b/ydb/core/tablet_flat/flat_scan_eggs.h index fb1bbcd9c3..d25c11eee6 100644 --- a/ydb/core/tablet_flat/flat_scan_eggs.h +++ b/ydb/core/tablet_flat/flat_scan_eggs.h @@ -1,15 +1,15 @@ -#pragma once - +#pragma once + #include "flat_table_subset.h" -#include "flat_scan_iface.h" -#include "flat_executor_misc.h" +#include "flat_scan_iface.h" +#include "flat_executor_misc.h" #include "util_basics.h" - -namespace NKikimr { -namespace NTabletFlatExecutor { - + +namespace NKikimr { +namespace NTabletFlatExecutor { + namespace NOps { - + struct TConf { ui64 AheadHi = 0; ui64 AheadLo = 0; @@ -27,5 +27,5 @@ namespace NTabletFlatExecutor { TRowVersion Snapshot; }; -} -} +} +} diff --git a/ydb/core/tablet_flat/flat_scan_events.h b/ydb/core/tablet_flat/flat_scan_events.h index 730f94b075..a89c550a6d 100644 --- a/ydb/core/tablet_flat/flat_scan_events.h +++ b/ydb/core/tablet_flat/flat_scan_events.h @@ -1,47 +1,47 @@ -#pragma once - +#pragma once + #include "util_basics.h" -#include "flat_scan_iface.h" +#include "flat_scan_iface.h" #include "flat_scan_eggs.h" -#include "flat_part_outset.h" -#include "flat_fwd_sieve.h" -#include "flat_table_subset.h" -#include "flat_executor_misc.h" +#include "flat_part_outset.h" +#include "flat_fwd_sieve.h" +#include "flat_table_subset.h" +#include "flat_executor_misc.h" #include <library/cpp/actors/core/event_local.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NOps { - - enum class EEv : ui32 { - Base_ = EventSpaceBegin(TKikimrEvents::ES_FLAT_EXECUTOR) + 1024, - Result = Base_ + 0, + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NOps { + + enum class EEv : ui32 { + Base_ = EventSpaceBegin(TKikimrEvents::ES_FLAT_EXECUTOR) + 1024, + Result = Base_ + 0, ScanStat = Base_ + 1, Continue = Base_ + 2, - }; - - struct TEvResult: public TEventLocal<TEvResult, ui32(EEv::Result)> { - using EAbort = NTable::EAbort; - + }; + + struct TEvResult: public TEventLocal<TEvResult, ui32(EEv::Result)> { + using EAbort = NTable::EAbort; + TEvResult(ui64 serial, EAbort abort, THolder<TScanSnapshot> snapshot, TAutoPtr<IDestructable> result) - : Serial(serial) - , Status(abort) - , Result(result) + : Serial(serial) + , Status(abort) + , Result(result) , Barrier(std::move(snapshot->Barrier)) , Subset(std::move(snapshot->Subset)) - { - - } - - ui64 Serial = 0; - EAbort Status = EAbort::None; + { + + } + + ui64 Serial = 0; + EAbort Status = EAbort::None; TAutoPtr<IDestructable> Result; TIntrusivePtr<TBarrier> Barrier; TAutoPtr<NTable::TSubset> Subset; TAutoPtr<NTable::NFwd::TSeen> Trace; /* Seen blobs but not materialized */ - }; - + }; + struct TEvScanStat : public TEventLocal<TEvScanStat, ui32(EEv::ScanStat)> { ui64 ElapsedUs; ui64 ProcessedRows; @@ -58,6 +58,6 @@ namespace NOps { // nothing }; -} -} -} +} +} +} diff --git a/ydb/core/tablet_flat/flat_scan_feed.h b/ydb/core/tablet_flat/flat_scan_feed.h index c6784dac33..525dd4cd27 100644 --- a/ydb/core/tablet_flat/flat_scan_feed.h +++ b/ydb/core/tablet_flat/flat_scan_feed.h @@ -1,52 +1,52 @@ -#pragma once - -#include "flat_scan_iface.h" -#include "flat_scan_lead.h" -#include "flat_part_iface.h" -#include "flat_iterator.h" -#include "flat_table_subset.h" - -namespace NKikimr { -namespace NTable { - - class TFeed { - public: +#pragma once + +#include "flat_scan_iface.h" +#include "flat_scan_lead.h" +#include "flat_part_iface.h" +#include "flat_iterator.h" +#include "flat_table_subset.h" + +namespace NKikimr { +namespace NTable { + + class TFeed { + public: TFeed(IScan *scan, const TSubset &subset, TRowVersion snapshot = TRowVersion::Max()) : Scan(scan) , Subset(subset) , SnapshotVersion(snapshot) , VersionScan(dynamic_cast<IVersionScan*>(scan)) - { - - } - + { + + } + void Resume(EScan op) noexcept - { + { Y_VERIFY_DEBUG(op == EScan::Feed || op == EScan::Reset); - + OnPause = false; if (op == EScan::Reset) { Iter = nullptr; } - } - - EReady Process() noexcept - { - if (OnPause) { - return EReady::Page; - } else if (Iter == nullptr) { - Lead.Clear(); - + } + + EReady Process() noexcept + { + if (OnPause) { + return EReady::Page; + } else if (Iter == nullptr) { + Lead.Clear(); + if (Seeks == Max<ui64>()) { Seeks = 0; } - + auto op = Scan->Seek(Lead, Seeks); VersionState = EVersionState::BeginKey; - - OnPause = (op == EScan::Sleep); - + + OnPause = (op == EScan::Sleep); + switch (op) { case EScan::Feed: if (!Reset()) { @@ -65,14 +65,14 @@ namespace NTable { case EScan::Reset: Y_FAIL("Unexpected EScan::Reset from IScan::Seek(...)"); - } + } Y_FAIL("Unexpected EScan result from IScan::Seek(...)"); - } else if (Seek()) { + } else if (Seek()) { return NotifyPageFault(); - } else { + } else { EReady ready; - + switch (VersionState) { case EVersionState::BeginKey: ready = Iter->Next(Conf.NoErased ? ENext::Data : VersionScan ? ENext::Uncommitted : ENext::All); @@ -127,11 +127,11 @@ namespace NTable { break; } - if (ready == EReady::Page) { + if (ready == EReady::Page) { return NotifyPageFault(); - } else if (ready == EReady::Gone) { + } else if (ready == EReady::Gone) { return NotifyExhausted(); - } else { + } else { EScan op; switch (VersionState) { case EVersionState::BeginKey: @@ -148,7 +148,7 @@ namespace NTable { } } break; - + case EVersionState::BeginDeltas: Y_VERIFY_DEBUG(Iter->IsUncommitted()); op = VersionScan->BeginDeltas(); @@ -167,7 +167,7 @@ namespace NTable { VersionState = EVersionState::SkipUncommitted; break; } - + case EVersionState::EndDeltasThenFeed: op = VersionScan->EndDeltas(); VersionState = EVersionState::Feed; @@ -202,12 +202,12 @@ namespace NTable { Y_FAIL("Unexpected callback state SkipVersion"); } - OnPause = (op == EScan::Sleep); - + OnPause = (op == EScan::Sleep); + switch (op) { case EScan::Feed: return EReady::Data; - + case EScan::Sleep: return EReady::Page; @@ -218,13 +218,13 @@ namespace NTable { case EScan::Final: return EReady::Gone; - } + } Y_FAIL("Unexpected EScan result from IScan::Feed(...)"); - } - } - } - + } + } + } + protected: IScan* DetachScan() noexcept { @@ -249,9 +249,9 @@ namespace NTable { return EReady::Data; } - private: - virtual IPages* MakeEnv() noexcept = 0; - + private: + virtual IPages* MakeEnv() noexcept = 0; + virtual TPartView LoadPart(const TIntrusiveConstPtr<TColdPart>& part) noexcept = 0; EReady NotifyPageFault() noexcept @@ -302,15 +302,15 @@ namespace NTable { } bool Reset() noexcept - { - Seeks++; - - Y_VERIFY(Lead, "Cannot seek with invalid lead"); - + { + Seeks++; + + Y_VERIFY(Lead, "Cannot seek with invalid lead"); + auto nulls = Subset.Scheme->Keys; - + Y_VERIFY(Lead.Key.GetCells().size() <= nulls->Size(), "TLead key is too large"); - + Iter = new TTableIt(Subset.Scheme.Get(), Lead.Tags, -1, SnapshotVersion, Subset.CommittedTransactions); CurrentEnv = MakeEnv(); @@ -392,16 +392,16 @@ namespace NTable { MakeHolder<TRunIt>(run, Lead.Tags, nulls, CurrentEnv)); } } - } - + } + bool SeekBoots() noexcept - { - if (Boots) { + { + if (Boots) { auto saved = Boots.begin(); auto current = Boots.begin(); while (current != Boots.end()) { auto *iter = current->Get(); - + switch (iter->Seek(Lead.Key.GetCells(), Lead.Relation)) { case EReady::Page: if (saved != current) { @@ -410,7 +410,7 @@ namespace NTable { ++saved; ++current; break; - + case EReady::Data: Iter->Push(std::move(*current)); ++current; @@ -422,17 +422,17 @@ namespace NTable { default: Y_FAIL("Unexpected Seek result"); - } - } + } + } if (saved != Boots.end()) { Boots.erase(saved, Boots.end()); } - } - + } + return Boots.empty(); - } - + } + bool Seek() noexcept { switch (SeekState) { @@ -461,15 +461,15 @@ namespace NTable { return false; } - protected: + protected: IScan * const Scan; - ui64 Seen = 0; + ui64 Seen = 0; ui64 Skipped = 0; IScan::TConf Conf; const TSubset ⋐ const TRowVersion SnapshotVersion; - - private: + + private: enum class ESeekState { LoadColdParts, PrepareBoots, @@ -495,20 +495,20 @@ namespace NTable { private: using TBoots = TVector<THolder<TRunIt>>; - + IPages* CurrentEnv = nullptr; TVector<TPartView> LoadedParts; size_t LoadingParts = 0; THolder<TLevels> Levels; - TLead Lead; - TBoots Boots; + TLead Lead; + TBoots Boots; TAutoPtr<TTableIt> Iter; - ui64 Seeks = Max<ui64>(); + ui64 Seeks = Max<ui64>(); ESeekState SeekState; - bool OnPause = false; - }; - -} -} + bool OnPause = false; + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_scan_iface.h b/ydb/core/tablet_flat/flat_scan_iface.h index 6b0fa8e42d..8d3f493249 100644 --- a/ydb/core/tablet_flat/flat_scan_iface.h +++ b/ydb/core/tablet_flat/flat_scan_iface.h @@ -1,23 +1,23 @@ -#pragma once - +#pragma once + #include "util_basics.h" -#include "flat_scan_lead.h" -#include "flat_row_eggs.h" -#include "flat_row_scheme.h" - -namespace NKikimr { -namespace NTable { - class TRowState; - class TSpent; - +#include "flat_scan_lead.h" +#include "flat_row_eggs.h" +#include "flat_row_scheme.h" + +namespace NKikimr { +namespace NTable { + class TRowState; + class TSpent; + /*_ IScan, the generic scan interface. Scan life cycle starts with invocation of Prepare(..) method after which it has to progress - with IDriver::Touch(..). - - Once rows iterator invalidated Seek(..) method is called getting - next position for seeking followed by a series of Feed(..) + with IDriver::Touch(..). + + Once rows iterator invalidated Seek(..) method is called getting + next position for seeking followed by a series of Feed(..) with rows. Thus the next call after Prepare(..) is always Seek(, 0). - + If Seek call succeeded and return EScan::Feed, then Feed called to pass data to reader. When range supplied by Seek completed then Exhausted method is called. Default implementation of Exhausted method return EScan::Reset, @@ -27,96 +27,96 @@ namespace NTable { IScan may express its desire of futher IDriver env behaviour with EScan codes where applicable. - + At the end IDriver calls Finish() once requesting a product. After this IScan is left on its own and impl. have to take care of all - owned resources and self object in particular. It is allowed for + owned resources and self object in particular. It is allowed for IScan to return self as an IDestructable product. - - Limitations and caveats: - + + Limitations and caveats: + 1. Usage of IDriver object is not valid in contexts of any call of IScan iface including the initial Prepare(..). - + 2. IScan has to maintain its own functional state until Finish(..) is called. - + 3. Host env may stop progress with Finish(..) not triggered by IScan desires. In that case IScan may continue to work alone - taking care of owned resources. - - 4. Seek(..) will progress to Feed(..) on next wake if ::Sleep - was requested and TLead object is left in valid state on exit - from Seek(..). Otherwise Seek(..) will be recalled with the - same state later. - + taking care of owned resources. + + 4. Seek(..) will progress to Feed(..) on next wake if ::Sleep + was requested and TLead object is left in valid state on exit + from Seek(..). Otherwise Seek(..) will be recalled with the + same state later. + 5. All IScan calls may be spread over time with undefined delays ruled by IDriver host environment. Thus IScan should not rely on any particular delays. - + 6. It is unspecified by this inteface how IDriver activity has to be synchronized with IScan, left to host env design. - */ - - enum class EScan { - Feed = 0, /* Feed rows from current iterator state */ - Sleep = 1, /* Suspend execution until explicit resume */ - Reset = 3, /* Reconfigure iterator with new settings */ - Final = 8, /* Impl. isn't needed in more rows or seeks */ - }; - - enum class EAbort { - None = 0, /* Regular process termination */ - Lost = 1, /* Owner entity is lost, no way for product */ - Term = 2, /* Explicit process termination by owner */ - Host = 3, /* Terminated due to execution env. error */ - }; - - class IDriver { - public: - virtual void Touch(EScan) noexcept = 0; - }; - - + */ + + enum class EScan { + Feed = 0, /* Feed rows from current iterator state */ + Sleep = 1, /* Suspend execution until explicit resume */ + Reset = 3, /* Reconfigure iterator with new settings */ + Final = 8, /* Impl. isn't needed in more rows or seeks */ + }; + + enum class EAbort { + None = 0, /* Regular process termination */ + Lost = 1, /* Owner entity is lost, no way for product */ + Term = 2, /* Explicit process termination by owner */ + Host = 3, /* Terminated due to execution env. error */ + }; + + class IDriver { + public: + virtual void Touch(EScan) noexcept = 0; + }; + + class IScan : public IDestructable { - public: - using TRow = NTable::TRowState; - using IDriver = NTable::IDriver; - using TScheme = NTable::TRowScheme; - using TLead = NTable::TLead; - using TSpent = NTable::TSpent; - using EScan = NTable::EScan; - using EAbort = NTable::EAbort; - - struct TConf { - TConf() = default; - TConf(bool noe) : NoErased(noe) { } - + public: + using TRow = NTable::TRowState; + using IDriver = NTable::IDriver; + using TScheme = NTable::TRowScheme; + using TLead = NTable::TLead; + using TSpent = NTable::TSpent; + using EScan = NTable::EScan; + using EAbort = NTable::EAbort; + + struct TConf { + TConf() = default; + TConf(bool noe) : NoErased(noe) { } + bool NoErased = true; /* Skip ERowOp::Erase'ed rows */ - - /* External blobs below this bytes edge will be materialized + + /* External blobs below this bytes edge will be materialized and passed as a regular ELargeObj::Inline values in row TCells, - otherwise internal references will be expanded to TGlobId + otherwise internal references will be expanded to TGlobId unit (ELargeObj::GlobId) suitable for reads from BS. - */ - - ui32 LargeEdge = Max<ui32>(); + */ + + ui32 LargeEdge = Max<ui32>(); // Scan can override default read ahead settings ui64 ReadAheadLo = Max<ui64>(); ui64 ReadAheadHi = Max<ui64>(); - }; - - struct THello { - EScan Scan; /* Initial scan state */ - TConf Conf; /* Scan conveyer configuration */ - }; - + }; + + struct THello { + EScan Scan; /* Initial scan state */ + TConf Conf; /* Scan conveyer configuration */ + }; + virtual THello Prepare(IDriver*, TIntrusiveConstPtr<TScheme>) noexcept = 0; - virtual EScan Seek(TLead&, ui64 seq) noexcept = 0; - virtual EScan Feed(TArrayRef<const TCell>, const TRow&) noexcept = 0; + virtual EScan Seek(TLead&, ui64 seq) noexcept = 0; + virtual EScan Feed(TArrayRef<const TCell>, const TRow&) noexcept = 0; virtual TAutoPtr<IDestructable> Finish(EAbort) noexcept = 0; - virtual void Describe(IOutputStream&) const noexcept = 0; + virtual void Describe(IOutputStream&) const noexcept = 0; /** * Called on page faults during iteration @@ -137,8 +137,8 @@ namespace NTable { virtual EScan Exhausted() noexcept { return EScan::Reset; } - }; - + }; + class IVersionScan : public IScan { private: @@ -155,5 +155,5 @@ namespace NTable { virtual EScan EndKey() noexcept = 0; }; -} -} +} +} diff --git a/ydb/core/tablet_flat/flat_scan_lead.h b/ydb/core/tablet_flat/flat_scan_lead.h index 2a0c8123b3..e6e5800c9d 100644 --- a/ydb/core/tablet_flat/flat_scan_lead.h +++ b/ydb/core/tablet_flat/flat_scan_lead.h @@ -1,47 +1,47 @@ -#pragma once - -#include "flat_row_eggs.h" -#include "flat_row_nulls.h" +#pragma once + +#include "flat_row_eggs.h" +#include "flat_row_nulls.h" #include <ydb/core/scheme/scheme_tablecell.h> -#include <util/generic/xrange.h> - -namespace NKikimr { -namespace NTable { - - struct TLead { - void To(TTagsRef tags, TArrayRef<const TCell> key, ESeek seek) - { - Valid = true; - Tags.assign(tags.begin(), tags.end()); - Relation = seek; - Key = TSerializedCellVec(TSerializedCellVec::Serialize(key)); +#include <util/generic/xrange.h> + +namespace NKikimr { +namespace NTable { + + struct TLead { + void To(TTagsRef tags, TArrayRef<const TCell> key, ESeek seek) + { + Valid = true; + Tags.assign(tags.begin(), tags.end()); + Relation = seek; + Key = TSerializedCellVec(TSerializedCellVec::Serialize(key)); StopKey = { }; - } - + } + void Until(TArrayRef<const TCell> key, bool inclusive) - { + { Y_VERIFY(Valid, "Until must be called after To"); StopKey = TSerializedCellVec(TSerializedCellVec::Serialize(key)); StopKeyInclusive = inclusive; - } - + } + explicit operator bool() const noexcept - { + { return Valid; - } - - void Clear() - { - Valid = false; - } - - bool Valid = false; - ESeek Relation = ESeek::Exact; + } + + void Clear() + { + Valid = false; + } + + bool Valid = false; + ESeek Relation = ESeek::Exact; TVector<ui32> Tags; - TSerializedCellVec Key; + TSerializedCellVec Key; TSerializedCellVec StopKey; bool StopKeyInclusive = true; - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_scan_spent.h b/ydb/core/tablet_flat/flat_scan_spent.h index 25210ed2f5..d37c7d2c43 100644 --- a/ydb/core/tablet_flat/flat_scan_spent.h +++ b/ydb/core/tablet_flat/flat_scan_spent.h @@ -1,53 +1,53 @@ -#pragma once - -#include "util_fmt_basic.h" - +#pragma once + +#include "util_fmt_basic.h" + #include <library/cpp/time_provider/time_provider.h> - -namespace NKikimr { -namespace NTable { - - class TSpent { - public: - /* Basic helper tool for scan operations that helps to account time - spent for waiting some one resource. It is used by scan actor for + +namespace NKikimr { +namespace NTable { + + class TSpent { + public: + /* Basic helper tool for scan operations that helps to account time + spent for waiting some one resource. It is used by scan actor for counting blockage on NBlockIO reads and may be used by IScan impls. - */ - - TSpent(ITimeProvider *prov) - : Time(prov) - , Fired(Time->Now()) - { - - } - - void Describe(IOutputStream &out) const noexcept - { - const auto now = Time->Now(); - - out - << "Spent{" << NFmt::TDelay(now - Fired) - << " wa " << NFmt::TDelay(Waits + (now - Since)) << "}"; - } - - void Alter(bool available) noexcept - { - if (bool(available) == bool(Since == TInstant::Max())) { - /* State isn't changed since last Alter(...) */ - } else if (Since == TInstant::Max()) { - Since = Time->Now(); - } else { - Waits += Time->Now() - std::exchange(Since, TInstant::Max()); - } - } - - private: - ITimeProvider * const Time = nullptr; - - TInstant Fired = TInstant::Max(); - TInstant Since = TInstant::Max(); - TDuration Waits = TDuration::Zero(); - }; - -} -} + */ + + TSpent(ITimeProvider *prov) + : Time(prov) + , Fired(Time->Now()) + { + + } + + void Describe(IOutputStream &out) const noexcept + { + const auto now = Time->Now(); + + out + << "Spent{" << NFmt::TDelay(now - Fired) + << " wa " << NFmt::TDelay(Waits + (now - Since)) << "}"; + } + + void Alter(bool available) noexcept + { + if (bool(available) == bool(Since == TInstant::Max())) { + /* State isn't changed since last Alter(...) */ + } else if (Since == TInstant::Max()) { + Since = Time->Now(); + } else { + Waits += Time->Now() - std::exchange(Since, TInstant::Max()); + } + } + + private: + ITimeProvider * const Time = nullptr; + + TInstant Fired = TInstant::Max(); + TInstant Since = TInstant::Max(); + TDuration Waits = TDuration::Zero(); + }; + +} +} diff --git a/ydb/core/tablet_flat/flat_stat_part.h b/ydb/core/tablet_flat/flat_stat_part.h index 230f94f04c..f2ae8bb5d0 100644 --- a/ydb/core/tablet_flat/flat_stat_part.h +++ b/ydb/core/tablet_flat/flat_stat_part.h @@ -1,8 +1,8 @@ #pragma once -#include "flat_part_iface.h" +#include "flat_part_iface.h" #include "flat_part_laid.h" -#include "flat_page_frames.h" +#include "flat_page_frames.h" #include "util_basics.h" #include <library/cpp/containers/stack_vector/stack_vec.h> @@ -98,8 +98,8 @@ private: class TPartIndexIterator { public: TPartIndexIterator(TIntrusiveConstPtr<TPart> part, TIntrusiveConstPtr<TKeyNulls> keys) - : Part(std::move(part)) - , KeyColumns(std::move(keys)) + : Part(std::move(part)) + , KeyColumns(std::move(keys)) { Pos = Part->Index->Begin(); End = Part->Index->End(); @@ -138,10 +138,10 @@ public: return TDbTupleRef(KeyColumns->BasicTypes().data(), CurrentKey.data(), CurrentKey.size()); } - ui64 GetLastRowId() const { - return LastRowId; - } - + ui64 GetLastRowId() const { + return LastRowId; + } + ui64 GetCurrentRowId() const { if (IsValid()) { return Pos->GetRowId(); @@ -198,8 +198,8 @@ private: private: TIntrusiveConstPtr<TPart> Part; TIntrusiveConstPtr<TKeyNulls> KeyColumns; - NPage::TIndex::TIter Pos; - NPage::TIndex::TIter End; + NPage::TIndex::TIter Pos; + NPage::TIndex::TIter End; TSmallVec<TCell> CurrentKey; ui64 CurrentSize = 0; ui64 LastRowId = 0; @@ -216,7 +216,7 @@ public: TIntrusiveConstPtr<NPage::TFrames> small) : PartIter(partView.Part, keyColumns) , Screen(std::move(partView.Screen)) - , Small(std::move(small)) + , Small(std::move(small)) , CurrentHole(TScreen::Iter(Screen, CurrentHoleIdx, 0, 1)) { } @@ -284,27 +284,27 @@ private: return rowCount; } - ui64 CalcSmallBytes() noexcept { - ui64 bytes = 0; - - const auto row = PartIter.GetLastRowId(); - const auto end = PartIter.GetCurrentRowId(); - - PrevSmallPage = Small->Lower(row, PrevSmallPage, Max<ui32>()); - - while (auto &rel = Small->Relation(PrevSmallPage)) { - if (rel.Row < end) { - bytes += rel.Size, ++PrevSmallPage; - } else if (!rel.IsHead()) { - Y_FAIL("Got unaligned NPage::TFrames head record"); - } else { - break; - } - } - - return bytes; - } - + ui64 CalcSmallBytes() noexcept { + ui64 bytes = 0; + + const auto row = PartIter.GetLastRowId(); + const auto end = PartIter.GetCurrentRowId(); + + PrevSmallPage = Small->Lower(row, PrevSmallPage, Max<ui32>()); + + while (auto &rel = Small->Relation(PrevSmallPage)) { + if (rel.Row < end) { + bytes += rel.Size, ++PrevSmallPage; + } else if (!rel.IsHead()) { + Y_FAIL("Got unaligned NPage::TFrames head record"); + } else { + break; + } + } + + return bytes; + } + private: TPartIndexIterator PartIter; TIntrusiveConstPtr<TScreen> Screen; @@ -315,7 +315,7 @@ private: ui64 PrevRowCount = 0; ui64 CurrentSize = 0; ui64 PrevSize = 0; - ui32 PrevSmallPage = 0; + ui32 PrevSmallPage = 0; }; }} diff --git a/ydb/core/tablet_flat/flat_stat_table.cpp b/ydb/core/tablet_flat/flat_stat_table.cpp index dfbaab9da7..574172e849 100644 --- a/ydb/core/tablet_flat/flat_stat_table.cpp +++ b/ydb/core/tablet_flat/flat_stat_table.cpp @@ -11,7 +11,7 @@ void BuildStats(const TSubset& subset, TStats& stats, ui64 rowCountResolution, u stats.Clear(); - TStatsIterator stIter(subset.Scheme->Keys); + TStatsIterator stIter(subset.Scheme->Keys); // Make index iterators for all parts for (auto& pi : subset.Flatten) { diff --git a/ydb/core/tablet_flat/flat_store_bundle.h b/ydb/core/tablet_flat/flat_store_bundle.h index 97b9ea21eb..418eee3b5a 100644 --- a/ydb/core/tablet_flat/flat_store_bundle.h +++ b/ydb/core/tablet_flat/flat_store_bundle.h @@ -1,28 +1,28 @@ -#pragma once - -#include "flat_sausage_packet.h" - -#include <util/generic/ptr.h> +#pragma once + +#include "flat_sausage_packet.h" + +#include <util/generic/ptr.h> #include <ydb/core/base/logoblob.h> - -namespace NKikimr { -namespace NTable { - - class IBundle : public virtual TThrRefBase { - public: - virtual const TLogoBlobID& BundleId() const = 0; - virtual ui64 BackingSize() const = 0; + +namespace NKikimr { +namespace NTable { + + class IBundle : public virtual TThrRefBase { + public: + virtual const TLogoBlobID& BundleId() const = 0; + virtual ui64 BackingSize() const = 0; virtual const NPageCollection::TPageCollection* Packet(ui32 room) const noexcept = 0; - - template<typename TContainer> - void SaveAllBlobIdsTo(TContainer &vec) const - { - ui32 room = 0; - - while (auto *pack = Packet(room++)) - pack->SaveAllBlobIdsTo(vec); - } - }; + + template<typename TContainer> + void SaveAllBlobIdsTo(TContainer &vec) const + { + ui32 room = 0; + + while (auto *pack = Packet(room++)) + pack->SaveAllBlobIdsTo(vec); + } + }; /** * A more generic interface for bundles that may be borrowed @@ -35,5 +35,5 @@ namespace NTable { virtual void SaveAllBlobIdsTo(TVector<TLogoBlobID> &vec) const = 0; }; -} -} +} +} diff --git a/ydb/core/tablet_flat/flat_store_hotdog.cpp b/ydb/core/tablet_flat/flat_store_hotdog.cpp index 42a062cadf..f1c73f2578 100644 --- a/ydb/core/tablet_flat/flat_store_hotdog.cpp +++ b/ydb/core/tablet_flat/flat_store_hotdog.cpp @@ -1,25 +1,25 @@ -#include "flat_store_hotdog.h" -#include "flat_store_solid.h" -#include "flat_part_store.h" -#include "flat_part_loader.h" +#include "flat_store_hotdog.h" +#include "flat_store_solid.h" +#include "flat_part_store.h" +#include "flat_part_loader.h" #include "flat_part_overlay.h" - + #include <ydb/core/base/tablet.h> #include <ydb/core/tablet_flat/flat_executor.pb.h> #include <ydb/core/tablet_flat/protos/flat_table_part.pb.h> -#include <util/generic/xrange.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { - +#include <util/generic/xrange.h> + +namespace NKikimr { +namespace NTabletFlatExecutor { + void TPageCollectionProtoHelper::Snap(NKikimrExecutorFlat::TLogTableSnap *snap, const TPartView &partView, ui32 table, ui32 level) -{ - snap->SetTable(table); - snap->SetCompactionLevel(level); - +{ + snap->SetTable(table); + snap->SetCompactionLevel(level); + TPageCollectionProtoHelper(false, false).Do(snap->AddBundles(), partView); -} - +} + void TPageCollectionProtoHelper::Snap(NKikimrExecutorFlat::TLogTableSnap *snap, const TIntrusiveConstPtr<TColdPart> &part, ui32 table, ui32 level) { snap->SetTable(table); @@ -29,7 +29,7 @@ void TPageCollectionProtoHelper::Snap(NKikimrExecutorFlat::TLogTableSnap *snap, } void TPageCollectionProtoHelper::Snap(NKikimrExecutorFlat::TLogTableSnap *snap, const TPartComponents &pc, ui32 table, ui32 level) -{ +{ snap->SetTable(table); snap->SetCompactionLevel(level); @@ -37,46 +37,46 @@ void TPageCollectionProtoHelper::Snap(NKikimrExecutorFlat::TLogTableSnap *snap, } void TPageCollectionProtoHelper::Do(TBundle *bundle, const TPartComponents &pc) -{ +{ bundle->MutablePageCollections()->Reserve(pc.PageCollectionComponents.size()); for (auto &one : pc.PageCollectionComponents) Bundle(bundle->AddPageCollections(), one.LargeGlobId, one.Packet.Get(), one.Sticky); if (auto &legacy = pc.Legacy) - bundle->SetLegacy(legacy); + bundle->SetLegacy(legacy); if (auto &opaque = pc.Opaque) - bundle->SetOpaque(opaque); + bundle->SetOpaque(opaque); bundle->SetEpoch(pc.GetEpoch().ToProto()); } void TPageCollectionProtoHelper::Do(TBundle *bundle, const NTable::TPartView &partView) -{ +{ Y_VERIFY(partView, "Cannot make bundle dump from empty NTable::TPartView"); - + auto *part = partView.As<NTable::TPartStore>(); - + Y_VERIFY(part, "Cannot cast TPart to page collection backed up part"); Y_VERIFY(part->Label == part->PageCollections[0]->PageCollection->Label()); - + bundle->MutablePageCollections()->Reserve(part->PageCollections.size()); - + for (auto &cache : part->PageCollections) Bundle(bundle->AddPageCollections(), *cache); - + if (auto legacy = NTable::TOverlay{ partView.Screen, nullptr }.Encode()) { - bundle->SetLegacy(std::move(legacy)); + bundle->SetLegacy(std::move(legacy)); } - + if (auto opaque = NTable::TOverlay{ nullptr, partView.Slices }.Encode()) { - bundle->SetOpaque(std::move(opaque)); - } + bundle->SetOpaque(std::move(opaque)); + } bundle->SetEpoch(part->Epoch.ToProto()); -} - +} + void TPageCollectionProtoHelper::Do(TBundle *bundle, const TIntrusiveConstPtr<NTable::TColdPart> &part) { Y_VERIFY(part, "Cannot make bundle dump from empty NTable::TColdPart"); @@ -104,73 +104,73 @@ void TPageCollectionProtoHelper::Do(TBundle *bundle, const TIntrusiveConstPtr<NT } void TPageCollectionProtoHelper::Bundle(NKikimrExecutorFlat::TPageCollection *pageCollectionProto, const TPrivatePageCache::TInfo &cache) -{ +{ TVector<NPageCollection::TLoadedPage> pages; - + auto *pack = CheckedCast<const NPageCollection::TPageCollection*>(cache.PageCollection.Get()); - - if (PutPages) { - for (ui32 pageId : xrange(pack->Meta.TotalPages())) { - auto type = NTable::EPage(pack->Meta.GetPageType(pageId)); - - if (!NTable::TLoader::NeedIn(type)) { - + + if (PutPages) { + for (ui32 pageId : xrange(pack->Meta.TotalPages())) { + auto type = NTable::EPage(pack->Meta.GetPageType(pageId)); + + if (!NTable::TLoader::NeedIn(type)) { + } else if (auto* body = cache.Lookup(pageId)) { pages.emplace_back(pageId, *body); } else { Y_FAIL("index and page collection pages must be kept inmemory"); } - } - } - + } + } + return Bundle(pageCollectionProto, pack->LargeGlobId, pack, pages); -} - - +} + + void TPageCollectionProtoHelper::Bundle( NKikimrExecutorFlat::TPageCollection *pageCollectionProto, const TLargeGlobId &largeGlobId, const NPageCollection::TPageCollection *pack, TPages pages) -{ +{ TLargeGlobIdProto::Put(*pageCollectionProto->MutableLargeGlobId(), largeGlobId); - + if (PutMeta && pack) pageCollectionProto->SetMeta(pack->Meta.Raw.ToString()); - - for (auto &paged: pages) { + + for (auto &paged: pages) { auto *page = pageCollectionProto->AddPages(); - - page->SetId(paged.PageId); + + page->SetId(paged.PageId); page->SetBody(paged.Data.ToString()); - } -} - - + } +} + + NTable::TPartComponents TPageCollectionProtoHelper::MakePageCollectionComponents(const TBundle &proto, bool unsplit) -{ +{ TVector<NTable::TPageCollectionComponents> components; - + for (auto &pageCollection: proto.GetPageCollections()) { Y_VERIFY(pageCollection.HasLargeGlobId(), "Got page collection without TLargeGlobId"); - + TVector<NPageCollection::TLoadedPage> pages; - + for (auto &page: pageCollection.GetPages()) pages.emplace_back(page.GetId(), TSharedData::Copy(page.GetBody())); - + auto& item = components.emplace_back(); item.LargeGlobId = TLargeGlobIdProto::Get(pageCollection.GetLargeGlobId()); item.Sticky = std::move(pages); if (pageCollection.HasMeta()) { item.ParsePacket(TSharedData::Copy(pageCollection.GetMeta())); } - } - - TString opaque = proto.HasLegacy() ? proto.GetLegacy() : TString{ }; - TString opaqueExt = proto.HasOpaque() ? proto.GetOpaque() : TString{ }; + } + + TString opaque = proto.HasLegacy() ? proto.GetLegacy() : TString{ }; + TString opaqueExt = proto.HasOpaque() ? proto.GetOpaque() : TString{ }; NTable::TEpoch epoch = proto.HasEpoch() ? NTable::TEpoch(proto.GetEpoch()) : NTable::TEpoch::Max(); - + if (unsplit && !opaqueExt.empty()) { TString modified = NTable::TOverlay::MaybeUnsplitSlices(opaqueExt); if (!modified.empty()) { @@ -179,7 +179,7 @@ NTable::TPartComponents TPageCollectionProtoHelper::MakePageCollectionComponents } return NTable::TPartComponents{ std::move(components), std::move(opaque), std::move(opaqueExt), epoch }; -} - -} -} +} + +} +} diff --git a/ydb/core/tablet_flat/flat_store_hotdog.h b/ydb/core/tablet_flat/flat_store_hotdog.h index 1a2953bf40..7e3667b980 100644 --- a/ydb/core/tablet_flat/flat_store_hotdog.h +++ b/ydb/core/tablet_flat/flat_store_hotdog.h @@ -1,41 +1,41 @@ -#pragma once - -#include "flat_sausage_packet.h" -#include "flat_sausagecache.h" -#include "flat_part_outset.h" -#include "flat_part_laid.h" -#include "flat_store_bundle.h" -#include <functional> - -namespace NKikimrExecutorFlat { - class TLogTableSnap; +#pragma once + +#include "flat_sausage_packet.h" +#include "flat_sausagecache.h" +#include "flat_part_outset.h" +#include "flat_part_laid.h" +#include "flat_store_bundle.h" +#include <functional> + +namespace NKikimrExecutorFlat { + class TLogTableSnap; class TPageCollection; - class TBundle; -} - -namespace NKikimr { -namespace NTabletFlatExecutor { - + class TBundle; +} + +namespace NKikimr { +namespace NTabletFlatExecutor { + class TPageCollectionProtoHelper { - public: + public: using TLargeGlobId = NPageCollection::TLargeGlobId; using TPartView = NTable::TPartView; using TColdPart = NTable::TColdPart; using TPartComponents = NTable::TPartComponents; - using TBundle = NKikimrExecutorFlat::TBundle; + using TBundle = NKikimrExecutorFlat::TBundle; using TPages = TArrayRef<const NPageCollection::TLoadedPage>; using TScreen = NTable::TScreen; using TSlices = NTable::TSlices; - + TPageCollectionProtoHelper() = delete; - + TPageCollectionProtoHelper(bool meta, bool pages) - : PutMeta(meta) - , PutPages(pages) - { - - } - + : PutMeta(meta) + , PutPages(pages) + { + + } + static void Snap(NKikimrExecutorFlat::TLogTableSnap *snap, const TPartComponents &pc, ui32 table, ui32 level); static void Snap(NKikimrExecutorFlat::TLogTableSnap *snap, const TPartView &partView, ui32 table, ui32 level); static void Snap(NKikimrExecutorFlat::TLogTableSnap *snap, const TIntrusiveConstPtr<TColdPart> &part, ui32 table, ui32 level); @@ -45,7 +45,7 @@ namespace NTabletFlatExecutor { void Do(TBundle *bundle, const TPartComponents &pc); static TPartComponents MakePageCollectionComponents(const TBundle &proto, bool unsplit = false); - + private: void Bundle(NKikimrExecutorFlat::TPageCollection *pageCollectionProto, const TPrivatePageCache::TInfo &cache); void Bundle( @@ -53,10 +53,10 @@ namespace NTabletFlatExecutor { const TLargeGlobId &largeGlobId, const NPageCollection::TPageCollection *pack, TPages pages); - - private: + + private: const bool PutMeta = false; /* Save page collection metablob in bundle */ - const bool PutPages = false; /* Save special pages within bundle */ - }; -} -} + const bool PutPages = false; /* Save special pages within bundle */ + }; +} +} diff --git a/ydb/core/tablet_flat/flat_store_solid.h b/ydb/core/tablet_flat/flat_store_solid.h index ddc3cc643c..211d9b86ee 100644 --- a/ydb/core/tablet_flat/flat_store_solid.h +++ b/ydb/core/tablet_flat/flat_store_solid.h @@ -1,64 +1,64 @@ -#pragma once - -#include "flat_sausage_solid.h" +#pragma once + +#include "flat_sausage_solid.h" #include <ydb/core/tablet_flat/flat_executor.pb.h> -#include <functional> - -namespace NKikimr { -namespace NTabletFlatExecutor { - +#include <functional> + +namespace NKikimr { +namespace NTabletFlatExecutor { + struct TLargeGlobIdProto { using TLargeGlobId = NPageCollection::TLargeGlobId; using TProto = NKikimrExecutorFlat::TLargeGlobId; - using TArr = TArrayRef<NKikimrProto::TLogoBlobID*>; - using TRep = NProtoBuf::RepeatedPtrField<NKikimrProto::TLogoBlobID>; - - /* In the near future all blobs tracked by executor binary logs + using TArr = TArrayRef<NKikimrProto::TLogoBlobID*>; + using TRep = NProtoBuf::RepeatedPtrField<NKikimrProto::TLogoBlobID>; + + /* In the near future all blobs tracked by executor binary logs will use TLargeGlobId for keeping of serialized entities with full - blobs identifiers (i.e. with BS group). But this requires some + blobs identifiers (i.e. with BS group). But this requires some migration timespan within of TLargeGlobId will be faked from legacy - series of TLogoBlobIDs with external group lookup functor. - */ - - using TLookup = std::function<ui32(const TLogoBlobID&)>; - + series of TLogoBlobIDs with external group lookup functor. + */ + + using TLookup = std::function<ui32(const TLogoBlobID&)>; + static void Put(TProto &proto, const TLargeGlobId &largeGlobId) - { + { Y_VERIFY(largeGlobId.Group != TLargeGlobId::InvalidGroup, "Please, set BS group"); - + proto.SetGroup(largeGlobId.Group); proto.SetBytes(largeGlobId.Bytes); - + LogoBlobIDFromLogoBlobID(largeGlobId.Lead, proto.MutableLead()); - } - + } + static TLargeGlobId Get(const TProto &from) - { - auto lead = LogoBlobIDFromLogoBlobID(from.GetLead()); - - return { from.GetGroup(), lead, from.GetBytes() }; - } - + { + auto lead = LogoBlobIDFromLogoBlobID(from.GetLead()); + + return { from.GetGroup(), lead, from.GetBytes() }; + } + static TLargeGlobId Get(const TRep &rep, const TLookup &lookup) - { + { Y_VERIFY(rep.size(), "TLargeGlobId accepts only non-empty sequence"); - - const auto lead = LogoBlobIDFromLogoBlobID(rep.Get(0)); - ui32 bytes = lead.BlobSize(); - - for (int it = 1; it < rep.size(); it++) { - auto logo = LogoBlobIDFromLogoBlobID(rep.Get(it)); - - if (bytes > Max<ui32>() - logo.BlobSize()) + + const auto lead = LogoBlobIDFromLogoBlobID(rep.Get(0)); + ui32 bytes = lead.BlobSize(); + + for (int it = 1; it < rep.size(); it++) { + auto logo = LogoBlobIDFromLogoBlobID(rep.Get(it)); + + if (bytes > Max<ui32>() - logo.BlobSize()) Y_FAIL("Got too large TLargeGlobId in ids sequence"); - if (lead.Cookie() + it != logo.Cookie()) - Y_FAIL("Got an invalid sequence of logo ids"); - - bytes += logo.BlobSize(); - } - - return { lookup(lead), lead, bytes }; - } - }; -} -} + if (lead.Cookie() + it != logo.Cookie()) + Y_FAIL("Got an invalid sequence of logo ids"); + + bytes += logo.BlobSize(); + } + + return { lookup(lead), lead, bytes }; + } + }; +} +} diff --git a/ydb/core/tablet_flat/flat_table.cpp b/ydb/core/tablet_flat/flat_table.cpp index 686a404268..9ba59e7fa1 100644 --- a/ydb/core/tablet_flat/flat_table.cpp +++ b/ydb/core/tablet_flat/flat_table.cpp @@ -1,42 +1,42 @@ #include "flat_table.h" -#include "flat_row_celled.h" -#include "flat_row_remap.h" -#include "flat_bloom_hash.h" +#include "flat_row_celled.h" +#include "flat_row_remap.h" +#include "flat_bloom_hash.h" #include "flat_part_iter_multi.h" -#include "flat_part_laid.h" -#include "flat_part_shrink.h" -#include "flat_part_charge.h" -#include "flat_part_dump.h" +#include "flat_part_laid.h" +#include "flat_part_shrink.h" +#include "flat_part_charge.h" +#include "flat_part_dump.h" #include "flat_range_cache.h" -#include "flat_util_misc.h" -#include "util_fmt_abort.h" +#include "flat_util_misc.h" +#include "util_fmt_abort.h" #include <ydb/core/util/yverify_stream.h> namespace NKikimr { -namespace NTable { - -TTable::TTable(TEpoch epoch) : Epoch(epoch) { } - -TTable::~TTable() { } - -void TTable::SetScheme(const TScheme::TTableInfo &table) -{ - Snapshot(); - +namespace NTable { + +TTable::TTable(TEpoch epoch) : Epoch(epoch) { } + +TTable::~TTable() { } + +void TTable::SetScheme(const TScheme::TTableInfo &table) +{ + Snapshot(); + Levels.Reset(); ErasedKeysCache.Reset(); - Y_VERIFY(!Mutable && table.Columns); - - auto to = TRowScheme::Make(table.Columns, NUtil::TSecond()); - - if (auto was = std::exchange(Scheme, to)) - was->CheckCompatability(*Scheme); - - /* This restriction is required for external blobs inverted index, for - details read NPage::TFrames and NFwd blobs cache implementation. */ - + Y_VERIFY(!Mutable && table.Columns); + + auto to = TRowScheme::Make(table.Columns, NUtil::TSecond()); + + if (auto was = std::exchange(Scheme, to)) + was->CheckCompatability(*Scheme); + + /* This restriction is required for external blobs inverted index, for + details read NPage::TFrames and NFwd blobs cache implementation. */ + Y_VERIFY(Scheme->Cols.size() <= ui32(-Min<i16>()), "Too many columns in row"); EraseCacheEnabled = table.EraseCacheEnabled; @@ -47,19 +47,19 @@ void TTable::SetScheme(const TScheme::TTableInfo &table) if (table.EraseCacheMaxBytes) { EraseCacheConfig.MaxBytes = table.EraseCacheMaxBytes; } -} - +} + TIntrusiveConstPtr<TRowScheme> TTable::GetScheme() const noexcept { return Scheme; } TAutoPtr<TSubset> TTable::Subset(TArrayRef<const TLogoBlobID> bundle, TEpoch head) -{ - head = Min(head, Epoch); +{ + head = Min(head, Epoch); TAutoPtr<TSubset> subset = new TSubset(head, Scheme); - + if (head > TEpoch::Zero()) { for (auto &x : Frozen) { if (x->Epoch < head) { @@ -73,7 +73,7 @@ TAutoPtr<TSubset> TTable::Subset(TArrayRef<const TLogoBlobID> bundle, TEpoch hea } } - subset->Flatten.reserve(bundle.size()); + subset->Flatten.reserve(bundle.size()); for (const TLogoBlobID &token : bundle) { if (auto* c = ColdParts.FindPtr(token)) { subset->ColdParts.push_back(*c); @@ -87,15 +87,15 @@ TAutoPtr<TSubset> TTable::Subset(TArrayRef<const TLogoBlobID> bundle, TEpoch hea subset->CommittedTransactions = CommittedTransactions; subset->RemovedTransactions = RemovedTransactions; - return subset; + return subset; } TAutoPtr<TSubset> TTable::Subset(TEpoch head) const noexcept -{ - head = Min(head, Epoch); +{ + head = Min(head, Epoch); TAutoPtr<TSubset> subset = new TSubset(head, Scheme); - + for (const auto &it : TxStatus) { if (it.second->Epoch < head) { subset->TxStatus.emplace_back(it.second); @@ -106,22 +106,22 @@ TAutoPtr<TSubset> TTable::Subset(TEpoch head) const noexcept if (it.second->Epoch < head) subset->ColdParts.push_back(it.second); - for (auto &it: Flatten) - if (it.second->Epoch < head) - subset->Flatten.push_back(it.second); - - for (auto &it : Frozen) - if (it->Epoch < head) + for (auto &it: Flatten) + if (it.second->Epoch < head) + subset->Flatten.push_back(it.second); + + for (auto &it : Frozen) + if (it->Epoch < head) subset->Frozen.emplace_back(it, it->Immediate()); - + // This method is normally used when we want to take some state snapshot // However it can still theoretically be used for iteration or compaction subset->CommittedTransactions = CommittedTransactions; subset->RemovedTransactions = RemovedTransactions; - return subset; -} - + return subset; +} + TAutoPtr<TSubset> TTable::ScanSnapshot(TRowVersion snapshot) noexcept { TAutoPtr<TSubset> subset = new TSubset(Epoch, Scheme); @@ -154,21 +154,21 @@ TAutoPtr<TSubset> TTable::ScanSnapshot(TRowVersion snapshot) noexcept } TAutoPtr<TSubset> TTable::Unwrap() noexcept -{ - Snapshot(); - +{ + Snapshot(); + auto subset = Subset(TEpoch::Max()); - - Replace({ }, *subset); + + Replace({ }, *subset); ReplaceTxStatus({ }, *subset); - + Y_VERIFY(!(Flatten || Frozen || Mutable || TxStatus)); - - return subset; -} - + + return subset; +} + TBundleSlicesMap TTable::LookupSlices(TArrayRef<const TLogoBlobID> bundles) const noexcept -{ +{ TBundleSlicesMap slices; for (const TLogoBlobID &bundle : bundles) { auto it = Flatten.find(bundle); @@ -178,7 +178,7 @@ TBundleSlicesMap TTable::LookupSlices(TArrayRef<const TLogoBlobID> bundles) cons } return slices; } - + void TTable::ReplaceSlices(TBundleSlicesMap slices) noexcept { for (auto &kv : slices) { @@ -215,7 +215,7 @@ void TTable::Replace(TArrayRef<const TPartView> partViews, const TSubset &subset const auto found = Frozen.erase(memTable.MemTable); Y_VERIFY(found == 1, "Got an unknown TMemTable table in TSubset"); - + NUtil::SubSafe(Stat_.FrozenWaste, memTable->GetWastedMem()); NUtil::SubSafe(Stat_.FrozenSize, memTable->GetUsedMem()); NUtil::SubSafe(Stat_.FrozenOps, memTable->GetOpsCount()); @@ -232,14 +232,14 @@ void TTable::Replace(TArrayRef<const TPartView> partViews, const TSubset &subset } } - for (auto &part : subset.Flatten) { + for (auto &part : subset.Flatten) { Y_VERIFY(part.Slices && *part.Slices, "Got an empty TPart subset in TSubset"); auto it = Flatten.find(part->Label); Y_VERIFY(it != Flatten.end(), "Got an unknown TPart table in TSubset"); auto& existing = it->second; - + Y_VERIFY(existing.Slices && *existing.Slices, "Existing table part has an unexpected empty bounds run"); @@ -278,8 +278,8 @@ void TTable::Replace(TArrayRef<const TPartView> partViews, const TSubset &subset Stat_.Parts.Remove(part); if (!Stat_.PartsPerTablet[part->Label.TabletID()].Remove(part)) { Stat_.PartsPerTablet.erase(part->Label.TabletID()); - } - } + } + } for (auto &part : subset.ColdParts) { auto it = ColdParts.find(part->Label); @@ -349,35 +349,35 @@ void TTable::ReplaceTxStatus(TArrayRef<const TIntrusiveConstPtr<TTxStatusPart>> } void TTable::Merge(TPartView partView) noexcept -{ +{ Y_VERIFY(partView, "Merge(...) shouldn't get empty part"); Y_VERIFY(partView.Slices, "Merge(...) shouldn't get parts without slices"); if (Mutable && partView->Epoch >= Mutable->Epoch) { Y_Fail("Merge " << NFmt::Do(*partView) << " after mutable epoch " << Mutable->Epoch); - } - + } + if (Frozen && partView->Epoch >= (*Frozen.begin())->Epoch) { Y_Fail("Merge " << NFmt::Do(*partView) << " after frozen epoch " << (*Frozen.begin())->Epoch); } auto it = Flatten.find(partView->Label); - - if (it == Flatten.end()) { + + if (it == Flatten.end()) { Epoch = Max(Epoch, partView->Epoch + 1); - + AddSafe(std::move(partView)); } else if (it->second->Epoch != partView->Epoch) { - Y_FAIL("Got the same labeled parts with different epoch"); + Y_FAIL("Got the same labeled parts with different epoch"); } else { Levels.Reset(); it->second.Screen = TScreen::Join(it->second.Screen, partView.Screen); it->second.Slices = TSlices::Merge(it->second.Slices, partView.Slices); - } + } ErasedKeysCache.Reset(); -} - +} + void TTable::Merge(TIntrusiveConstPtr<TColdPart> part) noexcept { Y_VERIFY(part, "Merge(...) shouldn't get empty parts"); @@ -497,44 +497,44 @@ ui64 TTable::GetSearchHeight() const noexcept } TVector<TIntrusiveConstPtr<TMemTable>> TTable::GetMemTables() const noexcept -{ +{ TVector<TIntrusiveConstPtr<TMemTable>> vec(Frozen.begin(), Frozen.end()); - - if (Mutable) + + if (Mutable) vec.emplace_back(Mutable); - + return vec; -} - -TEpoch TTable::Snapshot() noexcept -{ - if (Mutable) { +} + +TEpoch TTable::Snapshot() noexcept +{ + if (Mutable) { Annexed = Mutable->GetBlobs()->Tail(); - - Frozen.insert(Mutable); + + Frozen.insert(Mutable); Stat_.FrozenWaste += Mutable->GetWastedMem(); - Stat_.FrozenSize += Mutable->GetUsedMem(); - Stat_.FrozenOps += Mutable->GetOpsCount(); - Stat_.FrozenRows += Mutable->GetRowCount(); - + Stat_.FrozenSize += Mutable->GetUsedMem(); + Stat_.FrozenOps += Mutable->GetOpsCount(); + Stat_.FrozenRows += Mutable->GetRowCount(); + Mutable = nullptr; /* have to make new TMemTable on next update */ - + if (++Epoch == TEpoch::Max()) { - Y_FAIL("Table epoch counter has reached infinity value"); - } - } - - return Epoch; -} - + Y_FAIL("Table epoch counter has reached infinity value"); + } + } + + return Epoch; +} + void TTable::AddSafe(TPartView partView) -{ +{ if (partView) { Y_VERIFY(partView->Epoch < Epoch, "Cannot add part above head epoch"); - + Stat_.Parts.Add(partView); Stat_.PartsPerTablet[partView->Label.TabletID()].Add(partView); - + if (partView->TxIdStats) { for (const auto& item : partView->TxIdStats->GetItems()) { const ui64 txId = item.GetTxId(); @@ -542,8 +542,8 @@ void TTable::AddSafe(TPartView partView) } } - using TVal = decltype(Flatten)::value_type; - + using TVal = decltype(Flatten)::value_type; + if (FlattenEpoch <= partView->Epoch) { FlattenEpoch = partView->Epoch; if (Levels) { @@ -555,20 +555,20 @@ void TTable::AddSafe(TPartView partView) } bool done = Flatten.insert(TVal(partView->Label, std::move(partView))).second; - Y_VERIFY(done); - } -} - + Y_VERIFY(done); + } +} + TTable::TReady TTable::Precharge(TRawVals minKey_, TRawVals maxKey_, TTagsRef tags, IPages* env, ui64 flg, ui64 items, ui64 bytes, EDirection direction, TRowVersion snapshot) const -{ - TReady res; - bool ready = true; +{ + TReady res; + bool ready = true; bool includeHistory = !snapshot.IsMax(); - + if (items == Max<ui64>()) { items = 0; // disable limits } @@ -579,8 +579,8 @@ TTable::TReady TTable::Precharge(TRawVals minKey_, TRawVals maxKey_, TTagsRef ta if (minKey_.size() && minKey_.data() == maxKey_.data()) { const TCelled key(minKey_, *Scheme->Keys, false); - const NBloom::TPrefix prefix(key); - + const NBloom::TPrefix prefix(key); + for (const auto& run : GetLevels()) { auto pos = run.Find(key); if (pos != run.end()) { @@ -613,16 +613,16 @@ TTable::TReady TTable::Precharge(TRawVals minKey_, TRawVals maxKey_, TTagsRef ta break; } } - } - - res.Ready = ready ? EReady::Data : EReady::Page; - return res; -} + } + res.Ready = ready ? EReady::Data : EReady::Page; + return res; +} + void TTable::Update(ERowOp rop, TRawVals key, TOpsRef ops, TArrayRef<TMemGlob> apart, TRowVersion rowVersion) -{ +{ Y_VERIFY(!(ops && TCellOp::HaveNoOps(rop)), "Given ERowOp can't have ops"); - + if (ErasedKeysCache && rop != ERowOp::Erase) { const TCelled cells(key, *Scheme->Keys, true); auto res = ErasedKeysCache->FindKey(cells); @@ -632,8 +632,8 @@ void TTable::Update(ERowOp rop, TRawVals key, TOpsRef ops, TArrayRef<TMemGlob> a } MemTable().Update(rop, key, ops, apart, rowVersion, CommittedTransactions); -} - +} + void TTable::UpdateTx(ERowOp rop, TRawVals key, TOpsRef ops, TArrayRef<TMemGlob> apart, ui64 txId) { // Use a special row version that marks this update as uncommitted @@ -674,39 +674,39 @@ void TTable::RemoveTx(ui64 txId) } TMemTable& TTable::MemTable() -{ - return +{ + return *(Mutable ? Mutable : (Mutable = new TMemTable(Scheme, Epoch, Annexed))); -} - +} + TAutoPtr<TTableIt> TTable::Iterate(TRawVals key_, TTagsRef tags, IPages* env, ESeek seek, TRowVersion snapshot) const noexcept -{ +{ Y_VERIFY(ColdParts.empty(), "Cannot iterate with cold parts"); - const TCelled key(key_, *Scheme->Keys, false); - const ui64 limit = seek == ESeek::Exact ? 1 : Max<ui64>(); - + const TCelled key(key_, *Scheme->Keys, false); + const ui64 limit = seek == ESeek::Exact ? 1 : Max<ui64>(); + TAutoPtr<TTableIt> dbIter(new TTableIt(Scheme.Get(), tags, limit, snapshot, CommittedTransactions)); - - if (Mutable) { + + if (Mutable) { dbIter->Push(TMemIt::Make(*Mutable, Mutable->Immediate(), key, seek, Scheme->Keys, &dbIter->Remap, env, EDirection::Forward)); - } - + } + for (auto& fti : Frozen) { const TMemTable* memTable = fti.Get(); dbIter->Push(TMemIt::Make(*memTable, memTable->Immediate(), key, seek, Scheme->Keys, &dbIter->Remap, env, EDirection::Forward)); - } - + } + if (Flatten) { for (const auto& run : GetLevels()) { auto iter = MakeHolder<TRunIt>(run, dbIter->Remap.Tags, Scheme->Keys, env); - + if (iter->Seek(key, seek) != EReady::Gone) dbIter->Push(std::move(iter)); } - } - + } + if (EraseCacheEnabled) { if (!ErasedKeysCache) { ErasedKeysCache = new TKeyRangeCache(*Scheme->Keys, EraseCacheConfig); @@ -714,9 +714,9 @@ TAutoPtr<TTableIt> TTable::Iterate(TRawVals key_, TTagsRef tags, IPages* env, ES dbIter->ErasedKeysCache = ErasedKeysCache; } - return dbIter; -} - + return dbIter; +} + TAutoPtr<TTableReverseIt> TTable::IterateReverse(TRawVals key_, TTagsRef tags, IPages* env, ESeek seek, TRowVersion snapshot) const noexcept { Y_VERIFY(ColdParts.empty(), "Cannot iterate with cold parts"); @@ -758,23 +758,23 @@ TAutoPtr<TTableReverseIt> TTable::IterateReverse(TRawVals key_, TTagsRef tags, I TTable::TReady TTable::Select(TRawVals key_, TTagsRef tags, IPages* env, TRowState& row, ui64 flg, TRowVersion snapshot, TDeque<TPartSimpleIt>& tempIterators) const noexcept -{ +{ Y_VERIFY(ColdParts.empty(), "Cannot select with cold parts"); - Y_VERIFY(key_.size() == Scheme->Keys->Types.size()); - - const TCelled key(key_, *Scheme->Keys, false); - - const TRemap remap(*Scheme, tags); - - row.Reset(remap.Nulls()); - - for (auto &pin: remap.KeyPins()) + Y_VERIFY(key_.size() == Scheme->Keys->Types.size()); + + const TCelled key(key_, *Scheme->Keys, false); + + const TRemap remap(*Scheme, tags); + + row.Reset(remap.Nulls()); + + for (auto &pin: remap.KeyPins()) row.Set(pin.Pos, { ECellOp::Set, ELargeObj::Inline }, key[pin.Key]); - - TReady result; - - const NBloom::TPrefix prefix(key); - + + TReady result; + + const NBloom::TPrefix prefix(key); + TEpoch lastEpoch = TEpoch::Max(); bool snapshotFound = (snapshot == TRowVersion::Max()); @@ -790,8 +790,8 @@ TTable::TReady TTable::Select(TRawVals key_, TTagsRef tags, IPages* env, TRowSta } result.Invisible += it->InvisibleRowSkips; } - } - + } + // Frozen are sorted by epoch, apply in reverse order for (auto pos = Frozen.rbegin(); !row.IsFinalized() && pos != Frozen.rend(); ++pos) { const auto& memTable = *pos; @@ -806,8 +806,8 @@ TTable::TReady TTable::Select(TRawVals key_, TTagsRef tags, IPages* env, TRowSta result.Invisible += it->InvisibleRowSkips; } } - - bool ready = true; + + bool ready = true; if (!row.IsFinalized() && Flatten) { // Levels are ordered from newest to oldest, apply in order for (const auto& run : GetLevels()) { @@ -843,38 +843,38 @@ TTable::TReady TTable::Select(TRawVals key_, TTagsRef tags, IPages* env, TRowSta ++result.NoKey; } } - } else { + } else { ++result.Weeded; - } - } - } - } - + } + } + } + } + Y_VERIFY_DEBUG(result.Invisible == 0 || !snapshot.IsMax()); - if (!ready || row.Need()) { - result.Ready = EReady::Page; + if (!ready || row.Need()) { + result.Ready = EReady::Page; } else if (row == ERowOp::Erase || row == ERowOp::Absent) { - result.Ready = EReady::Gone; - } else { - result.Ready = EReady::Data; - } - return result; -} - -void TTable::DebugDump(IOutputStream& str, IPages* env, const NScheme::TTypeRegistry& reg) const -{ + result.Ready = EReady::Gone; + } else { + result.Ready = EReady::Data; + } + return result; +} + +void TTable::DebugDump(IOutputStream& str, IPages* env, const NScheme::TTypeRegistry& reg) const +{ str << "Mutable: " << (Mutable ? Mutable->Epoch : TEpoch::Zero()) << Endl; - str << "Frozen: ["; - for (const auto& it : Frozen) { - str << it->Epoch; + str << "Frozen: ["; + for (const auto& it : Frozen) { + str << it->Epoch; } str << "]" << Endl - << "Parts: [" + << "Parts: [" << Endl; - for (const auto& fpIt: Flatten) { + for (const auto& fpIt: Flatten) { str << " "; - NFmt::Ln(*fpIt.second); + NFmt::Ln(*fpIt.second); } str << "]" << Endl; if (ColdParts) { @@ -885,18 +885,18 @@ void TTable::DebugDump(IOutputStream& str, IPages* env, const NScheme::TTypeRegi } str << "]" << Endl; } - str << "Mutable dump: " << Endl; - - if (Mutable) - Mutable->DebugDump(str, reg); - for (const auto& it : Frozen) { - str << "Frozen " << it->Epoch << " dump: " << Endl; - it->DebugDump(str, reg); + str << "Mutable dump: " << Endl; + + if (Mutable) + Mutable->DebugDump(str, reg); + for (const auto& it : Frozen) { + str << "Frozen " << it->Epoch << " dump: " << Endl; + it->DebugDump(str, reg); } - TDump dump(str, env, ®); - - for (const auto &it: Flatten) dump.Part(*it.second); + TDump dump(str, env, ®); + + for (const auto &it: Flatten) dump.Part(*it.second); } TKeyRangeCache* TTable::GetErasedKeysCache() const diff --git a/ydb/core/tablet_flat/flat_table.h b/ydb/core/tablet_flat/flat_table.h index a1fdeb9709..92fd07c0d8 100644 --- a/ydb/core/tablet_flat/flat_table.h +++ b/ydb/core/tablet_flat/flat_table.h @@ -1,85 +1,85 @@ #pragma once #include "defs.h" #include "flat_update_op.h" -#include "flat_dbase_scheme.h" -#include "flat_mem_warm.h" +#include "flat_dbase_scheme.h" +#include "flat_mem_warm.h" #include "flat_iterator.h" -#include "flat_row_scheme.h" +#include "flat_row_scheme.h" #include "flat_row_versions.h" -#include "flat_part_laid.h" +#include "flat_part_laid.h" #include "flat_part_slice.h" #include "flat_table_committed.h" #include "flat_table_part.h" #include "flat_table_stats.h" -#include "flat_table_subset.h" -#include "flat_table_misc.h" -#include "flat_sausage_solid.h" +#include "flat_table_subset.h" +#include "flat_table_misc.h" +#include "flat_sausage_solid.h" #include "util_basics.h" #include <ydb/core/scheme/scheme_tablecell.h> #include <library/cpp/containers/stack_vector/stack_vec.h> #include <util/generic/deque.h> -#include <util/generic/set.h> +#include <util/generic/set.h> #include <util/generic/hash.h> #include <util/generic/ptr.h> namespace NKikimr { -namespace NTable { +namespace NTable { class TTableEpochs; class TKeyRangeCache; -class TTable: public TAtomicRefCount<TTable> { +class TTable: public TAtomicRefCount<TTable> { public: using TOpsRef = TArrayRef<const TUpdateOp>; using TMemGlob = NPageCollection::TMemGlob; - struct TStat { - /*_ In memory (~memtable) data statistics */ - + struct TStat { + /*_ In memory (~memtable) data statistics */ + ui64 FrozenWaste = 0; - ui64 FrozenSize = 0; - ui64 FrozenOps = 0; - ui64 FrozenRows = 0; - - /*_ Already flatten data statistics (parts) */ - + ui64 FrozenSize = 0; + ui64 FrozenOps = 0; + ui64 FrozenRows = 0; + + /*_ Already flatten data statistics (parts) */ + TPartStats Parts; THashMap<ui64, TPartStats> PartsPerTablet; - }; - - struct TReady { - EReady Ready = EReady::Page; - - /* Per part operation statictics on Charge(...) or Select(...) - for ByKey bloom filter usage. The filter misses >= NoKey */ - - ui64 Weeded = 0; - ui64 Sieved = 0; - ui64 NoKey = 0; /* Examined TPart without the key */ + }; + + struct TReady { + EReady Ready = EReady::Page; + + /* Per part operation statictics on Charge(...) or Select(...) + for ByKey bloom filter usage. The filter misses >= NoKey */ + + ui64 Weeded = 0; + ui64 Sieved = 0; + ui64 NoKey = 0; /* Examined TPart without the key */ ui64 Invisible = 0; /* Skipped invisible versions */ - }; - - explicit TTable(TEpoch); - ~TTable(); + }; + + explicit TTable(TEpoch); + ~TTable(); void SetScheme(const TScheme::TTableInfo& tableScheme); TIntrusiveConstPtr<TRowScheme> GetScheme() const noexcept; - TEpoch Snapshot() noexcept; - - TEpoch Head() const noexcept - { - return Epoch; - } - + TEpoch Snapshot() noexcept; + + TEpoch Head() const noexcept + { + return Epoch; + } + TAutoPtr<TSubset> Subset(TArrayRef<const TLogoBlobID> bundle, TEpoch edge); TAutoPtr<TSubset> Subset(TEpoch edge) const noexcept; TAutoPtr<TSubset> ScanSnapshot(TRowVersion snapshot = TRowVersion::Max()) noexcept; TAutoPtr<TSubset> Unwrap() noexcept; /* full Subset(..) + final Replace(..) */ - + /** * Returns current slices for bundles * @@ -92,26 +92,26 @@ public: */ void ReplaceSlices(TBundleSlicesMap slices) noexcept; - /* Interface for redistributing data layout within the table. Take some - subset with Subset(...) call, do some work and then return result - with Replace(...) method. The result should hold the same set of rows - as original subset. Replace(...) may produce some garbage that have to - be displaced from table with Clean() method eventually. - */ - + /* Interface for redistributing data layout within the table. Take some + subset with Subset(...) call, do some work and then return result + with Replace(...) method. The result should hold the same set of rows + as original subset. Replace(...) may produce some garbage that have to + be displaced from table with Clean() method eventually. + */ + void Replace(TArrayRef<const TPartView>, const TSubset&) noexcept; void ReplaceTxStatus(TArrayRef<const TIntrusiveConstPtr<TTxStatusPart>>, const TSubset&) noexcept; - - /*_ Special interface for clonig flatten part of table for outer usage. + + /*_ Special interface for clonig flatten part of table for outer usage. Cook some TPartView with Subset(...) method and/or TShrink tool first and then merge produced TPartView to outer table. - */ - + */ + void Merge(TPartView partView) noexcept; void Merge(TIntrusiveConstPtr<TColdPart> part) noexcept; void Merge(TIntrusiveConstPtr<TTxStatusPart> txStatus) noexcept; void ProcessCheckTransactions() noexcept; - + /** * Returns constructed levels for slices */ @@ -123,14 +123,14 @@ public: ui64 GetSearchHeight() const noexcept; /* Hack for filling external blobs in TMemTable tables with data */ - + TVector<TIntrusiveConstPtr<TMemTable>> GetMemTables() const noexcept; - + TAutoPtr<TTableIt> Iterate(TRawVals key, TTagsRef tags, IPages* env, ESeek, TRowVersion snapshot) const noexcept; TAutoPtr<TTableReverseIt> IterateReverse(TRawVals key, TTagsRef tags, IPages* env, ESeek, TRowVersion snapshot) const noexcept; TReady Select(TRawVals key, TTagsRef tags, IPages* env, TRowState& row, ui64 flg, TRowVersion snapshot, TDeque<TPartSimpleIt>& tempIterators) const noexcept; - + TReady Precharge(TRawVals minKey, TRawVals maxKey, TTagsRef tags, IPages* env, ui64 flg, ui64 itemsLimit, ui64 bytesLimit, @@ -143,12 +143,12 @@ public: void RemoveTx(ui64 txId); TPartView GetPartView(const TLogoBlobID &bundle) const - { + { auto *partView = Flatten.FindPtr(bundle); - + return partView ? *partView : TPartView{ }; - } - + } + TVector<TPartView> GetAllParts() const { TVector<TPartView> parts(Reserve(Flatten.size())); @@ -192,13 +192,13 @@ public: } } - const TStat& Stat() const noexcept - { - return Stat_; - } - + const TStat& Stat() const noexcept + { + return Stat_; + } + ui64 GetMemSize(TEpoch epoch = TEpoch::Max()) const noexcept - { + { if (Y_LIKELY(epoch == TEpoch::Max())) { return Stat_.FrozenSize + (Mutable ? Mutable->GetUsedMem() : 0); } @@ -216,7 +216,7 @@ public: } return size; - } + } ui64 GetMemWaste() const noexcept { @@ -228,31 +228,31 @@ public: return Stat_.FrozenRows + (Mutable ? Mutable->GetRowCount() : 0); } - ui64 GetOpsCount() const noexcept - { - return Stat_.FrozenOps + (Mutable ? Mutable->GetOpsCount() : 0); - } - - ui64 GetPartsCount() const noexcept - { - return Flatten.size(); - } - - ui64 EstimateRowSize() const noexcept - { - ui64 size = Stat_.FrozenSize + (Mutable ? Mutable->GetUsedMem() : 0); - ui64 rows = Stat_.FrozenRows + (Mutable ? Mutable->GetRowCount() : 0); - - for (const auto& flat : Flatten) { + ui64 GetOpsCount() const noexcept + { + return Stat_.FrozenOps + (Mutable ? Mutable->GetOpsCount() : 0); + } + + ui64 GetPartsCount() const noexcept + { + return Flatten.size(); + } + + ui64 EstimateRowSize() const noexcept + { + ui64 size = Stat_.FrozenSize + (Mutable ? Mutable->GetUsedMem() : 0); + ui64 rows = Stat_.FrozenRows + (Mutable ? Mutable->GetRowCount() : 0); + + for (const auto& flat : Flatten) { if (const TPartView &partView = flat.second) { size += partView->DataSize(); rows += partView->Index.Rows(); - } - } - - return rows ? (size / rows) : 0; - } - + } + } + + return rows ? (size / rows) : 0; + } + void DebugDump(IOutputStream& str, IPages *env, const NScheme::TTypeRegistry& typeRegistry) const; TKeyRangeCache* GetErasedKeysCache() const; @@ -270,11 +270,11 @@ public: private: TMemTable& MemTable(); void AddSafe(TPartView partView); - + void AddStat(const TPartView& partView); void RemoveStat(const TPartView& partView); -private: +private: struct TOpenTransaction { THashSet<TIntrusiveConstPtr<TMemTable>> Mem; THashSet<TIntrusiveConstPtr<TPart>> Parts; @@ -282,7 +282,7 @@ private: private: TEpoch Epoch; /* Monotonic table change number, with holes */ - ui64 Annexed = 0; /* Monotonic serial of attached external blobs */ + ui64 Annexed = 0; /* Monotonic serial of attached external blobs */ TIntrusiveConstPtr<TRowScheme> Scheme; TIntrusivePtr<TMemTable> Mutable; TSet<TIntrusiveConstPtr<TMemTable>, TOrderByEpoch<TMemTable>> Frozen; @@ -290,7 +290,7 @@ private: THashMap<TLogoBlobID, TIntrusiveConstPtr<TColdPart>> ColdParts; THashMap<TLogoBlobID, TIntrusiveConstPtr<TTxStatusPart>> TxStatus; TEpoch FlattenEpoch = TEpoch::Min(); /* Current maximum flatten epoch */ - TStat Stat_; + TStat Stat_; mutable THolder<TLevels> Levels; mutable TIntrusivePtr<TKeyRangeCache> ErasedKeysCache; diff --git a/ydb/core/tablet_flat/flat_table_column.h b/ydb/core/tablet_flat/flat_table_column.h index 2f9791a636..4c5224de9c 100644 --- a/ydb/core/tablet_flat/flat_table_column.h +++ b/ydb/core/tablet_flat/flat_table_column.h @@ -1,59 +1,59 @@ -#pragma once - -#include "flat_row_column.h" - +#pragma once + +#include "flat_row_column.h" + #include <ydb/core/scheme/scheme_tablecell.h> - -namespace NKikimr { -namespace NTable { - - struct TColumn { - - enum EDefaults { - LeaderFamily = 0, - }; - - TColumn() = default; - + +namespace NKikimr { +namespace NTable { + + struct TColumn { + + enum EDefaults { + LeaderFamily = 0, + }; + + TColumn() = default; + TColumn(const TString& name, TTag tag, NScheme::TTypeId type, bool notNull = false) - : Id(tag) - , PType(type) - , Name(name) + : Id(tag) + , PType(type) + , Name(name) , NotNull(notNull) - { - - } - - bool IsTheSame(const TColumn &col) const noexcept - { - return - Id == col.Id - && PType == col.PType - && KeyOrder == col.KeyOrder - && Name == col.Name + { + + } + + bool IsTheSame(const TColumn &col) const noexcept + { + return + Id == col.Id + && PType == col.PType + && KeyOrder == col.KeyOrder + && Name == col.Name && Family == col.Family && NotNull == col.NotNull; - } - - void SetDefault(const TCell &null) - { - if (!null || TCell::CanInline(null.Size())) { - Storage = { }; - Null = null; - } else { - Storage.assign(null.Data(), null.Size()); - Null = TCell(Storage.data(), Storage.size()); - } - } - - NTable::TTag Id = Max<TTag>(); - NScheme::TTypeId PType = 0; - TString Name; - ui32 Family = LeaderFamily; - NTable::TPos KeyOrder = Max<TPos>(); - TCell Null; - TString Storage; + } + + void SetDefault(const TCell &null) + { + if (!null || TCell::CanInline(null.Size())) { + Storage = { }; + Null = null; + } else { + Storage.assign(null.Data(), null.Size()); + Null = TCell(Storage.data(), Storage.size()); + } + } + + NTable::TTag Id = Max<TTag>(); + NScheme::TTypeId PType = 0; + TString Name; + ui32 Family = LeaderFamily; + NTable::TPos KeyOrder = Max<TPos>(); + TCell Null; + TString Storage; bool NotNull = false; - }; -} -} + }; +} +} diff --git a/ydb/core/tablet_flat/flat_table_misc.cpp b/ydb/core/tablet_flat/flat_table_misc.cpp index 931a36a0e6..8f65f2ae34 100644 --- a/ydb/core/tablet_flat/flat_table_misc.cpp +++ b/ydb/core/tablet_flat/flat_table_misc.cpp @@ -1,17 +1,17 @@ -#include "flat_table_misc.h" -#include "flat_mem_warm.h" - -namespace NKikimr { -namespace NTable { - +#include "flat_table_misc.h" +#include "flat_mem_warm.h" + +namespace NKikimr { +namespace NTable { + IPages::TResult MemTableRefLookup(const TMemTable *memTable, ui64 ref, ui32) noexcept - { + { const auto &data = memTable->GetBlobs()->Get(ref).Data; - - Y_VERIFY(data, "Got external blob in NMem::TBlobs with no data"); - - return { true, &data }; - } - -} -} + + Y_VERIFY(data, "Got external blob in NMem::TBlobs with no data"); + + return { true, &data }; + } + +} +} diff --git a/ydb/core/tablet_flat/flat_table_misc.h b/ydb/core/tablet_flat/flat_table_misc.h index 9ffe2f3cd3..64604bbe83 100644 --- a/ydb/core/tablet_flat/flat_table_misc.h +++ b/ydb/core/tablet_flat/flat_table_misc.h @@ -1,19 +1,19 @@ -#pragma once -#include "flat_part_iface.h" - -namespace NKikimr { -namespace NTable { - - template<typename TItem> - struct TOrderByEpoch { +#pragma once +#include "flat_part_iface.h" + +namespace NKikimr { +namespace NTable { + + template<typename TItem> + struct TOrderByEpoch { using TUnit = TIntrusiveConstPtr<TItem>; - - bool operator()(const TUnit &left, const TUnit &right) const noexcept - { - return left->Epoch < right->Epoch; - } - }; - + + bool operator()(const TUnit &left, const TUnit &right) const noexcept + { + return left->Epoch < right->Epoch; + } + }; + IPages::TResult MemTableRefLookup(const TMemTable*, ui64 ref, ui32 tag) noexcept; -} -} +} +} diff --git a/ydb/core/tablet_flat/flat_table_part.cpp b/ydb/core/tablet_flat/flat_table_part.cpp index 235229cc35..3775615cea 100644 --- a/ydb/core/tablet_flat/flat_table_part.cpp +++ b/ydb/core/tablet_flat/flat_table_part.cpp @@ -1,18 +1,18 @@ -#include "flat_page_label.h" -#include "flat_part_iface.h" +#include "flat_page_label.h" +#include "flat_part_iface.h" #include "flat_table_part.h" #include "util_basics.h" - + #include <ydb/core/util/pb.h> #include <ydb/core/tablet_flat/protos/flat_table_part.pb.h> #include <library/cpp/containers/stack_vector/stack_vec.h> #include <util/generic/map.h> namespace NKikimr { -namespace NTable { +namespace NTable { -TPartScheme::TPartScheme(TArrayRef<const TColInfo> cols) -{ +TPartScheme::TPartScheme(TArrayRef<const TColInfo> cols) +{ ui32 maxGroup = 0; for (auto& col : cols) { maxGroup = Max(maxGroup, col.Group); @@ -25,60 +25,60 @@ TPartScheme::TPartScheme(TArrayRef<const TColInfo> cols) Groups[col.Group].Columns.back().Pos = pos++; } - FillKeySlots(); + FillKeySlots(); FillHistoricSlots(); } TIntrusiveConstPtr<TPartScheme> TPartScheme::Parse(TArrayRef<const char> raw, bool labeled) -{ - if (labeled) { - /* New styled scheme blob prepended with generic TLabel data */ - - auto got = NPage::THello().Read(raw, NPage::EPage::Schem2); - +{ + if (labeled) { + /* New styled scheme blob prepended with generic TLabel data */ + + auto got = NPage::THello().Read(raw, NPage::EPage::Schem2); + // Version 1 may have non-zero group columns Y_VERIFY(got.Version == 0 || got.Version == 1, "Unknown EPage::Schem2 version"); - - raw = got.Page; - } - - TProtoBox<NProto::TPartScheme> proto(raw); - - TMap<TTag, ui32> byTag; - TVector<TColInfo> cols; - - for (size_t i = 0; i < proto.ColumnsSize(); i++) { - auto &one = proto.GetColumns(i); - - cols.emplace_back(); - cols.back().Tag = one.GetTag(); - cols.back().TypeId = one.GetType(); - cols.back().Pos = cols.size() - 1; + + raw = got.Page; + } + + TProtoBox<NProto::TPartScheme> proto(raw); + + TMap<TTag, ui32> byTag; + TVector<TColInfo> cols; + + for (size_t i = 0; i < proto.ColumnsSize(); i++) { + auto &one = proto.GetColumns(i); + + cols.emplace_back(); + cols.back().Tag = one.GetTag(); + cols.back().TypeId = one.GetType(); + cols.back().Pos = cols.size() - 1; cols.back().Group = one.GetGroup(); - - if (one.HasKey()) - cols.back().Key = one.GetKey(); - - byTag[one.GetTag()] = cols.back().Pos; - } - - /* Compatability with legacy schemes */ - for (size_t pos = 0; pos < proto.KeyTagsSize(); pos++) { - auto it = byTag.find(proto.GetKeyTags(pos)); - - Y_VERIFY(it != byTag.end(), "Cannot find key tag plain scheme"); - - cols[it->second].Key = pos; - } - - return new TPartScheme(cols); + + if (one.HasKey()) + cols.back().Key = one.GetKey(); + + byTag[one.GetTag()] = cols.back().Pos; + } + + /* Compatability with legacy schemes */ + for (size_t pos = 0; pos < proto.KeyTagsSize(); pos++) { + auto it = byTag.find(proto.GetKeyTags(pos)); + + Y_VERIFY(it != byTag.end(), "Cannot find key tag plain scheme"); + + cols[it->second].Key = pos; + } + + return new TPartScheme(cols); } -void TPartScheme::FillKeySlots() -{ +void TPartScheme::FillKeySlots() +{ for (auto& group : Groups) { InitGroup(group); - + for (const auto& col : group.Columns) { AllColumns.push_back(col); } @@ -89,10 +89,10 @@ void TPartScheme::FillKeySlots() std::sort(AllColumns.begin(), AllColumns.end(), byPos); for (auto& col : AllColumns) { - Tag2DataInfo[col.Tag] = &col; + Tag2DataInfo[col.Tag] = &col; } } - + void TPartScheme::FillHistoricSlots() { // Synthetic (rowid, step, txid) key used during history searches @@ -131,7 +131,7 @@ void TPartScheme::FillHistoricSlots() // Remove incorrect key columns from history for (auto& col : HistoryColumns) { - if (col.IsKey()) { + if (col.IsKey()) { col = { }; } } @@ -148,52 +148,52 @@ void TPartScheme::InitGroup(TGroupInfo& group) Y_VERIFY(col.Group == 0, "Key columns must be in the main column group"); group.ColsKeyData.push_back(col); - } - } - + } + } + if (group.ColsKeyData) { auto byKey = NTable::TColInfo::TByKey(); - + std::sort(group.ColsKeyData.begin(), group.ColsKeyData.end(), byKey); - + for (auto& col : group.ColsKeyData) { group.KeyTypes.push_back(col.TypeId); } - + group.ColsKeyIdx = group.ColsKeyData; group.IdxRecFixedSize = InitInfo(group.ColsKeyIdx, TPgSizeOf<TIndex::TItem>::Value); } else { group.IdxRecFixedSize = 0; } -} - +} + size_t TPartScheme::InitInfo(TVector<TColumn>& cols, TPgSize headerSize) -{ +{ size_t offset = 0; - - for (auto &col: cols) { - const ui32 fixed = NScheme::GetFixedSize(col.TypeId); - - col.Offset = offset; - col.IsFixed = fixed > 0; - col.FixedSize = fixed > 0 ? fixed : sizeof(NPage::TDataRef); - - offset += col.FixedSize + headerSize; - } - - return offset; -} - + + for (auto &col: cols) { + const ui32 fixed = NScheme::GetFixedSize(col.TypeId); + + col.Offset = offset; + col.IsFixed = fixed > 0; + col.FixedSize = fixed > 0 ? fixed : sizeof(NPage::TDataRef); + + offset += col.FixedSize + headerSize; + } + + return offset; +} + TSharedData TPartScheme::Serialize() const -{ - NProto::TPartScheme proto; - +{ + NProto::TPartScheme proto; + for (const auto& col : AllColumns) { - auto* pb = proto.AddColumns(); + auto* pb = proto.AddColumns(); pb->SetTag(col.Tag); pb->SetType(col.TypeId); pb->SetGroup(col.Group); - + if (col.IsKey()) { pb->SetKey(col.Key); } @@ -201,7 +201,7 @@ TSharedData TPartScheme::Serialize() const TStringStream ss; proto.SerializeToArcadiaStream(&ss); - + return NPage::THello::Wrap(ss.Str(), EPage::Schem2, Groups.size() > 1 ? 1 : 0); } diff --git a/ydb/core/tablet_flat/flat_table_part.h b/ydb/core/tablet_flat/flat_table_part.h index aa555c515b..93f770c5a6 100644 --- a/ydb/core/tablet_flat/flat_table_part.h +++ b/ydb/core/tablet_flat/flat_table_part.h @@ -1,20 +1,20 @@ #pragma once - + #include "defs.h" -#include "flat_part_scheme.h" -#include "flat_page_index.h" -#include "flat_page_data.h" -#include "flat_page_blobs.h" -#include "flat_page_frames.h" -#include "flat_page_bloom.h" +#include "flat_part_scheme.h" +#include "flat_page_index.h" +#include "flat_page_data.h" +#include "flat_page_blobs.h" +#include "flat_page_frames.h" +#include "flat_page_bloom.h" #include "flat_page_gstat.h" #include "flat_page_txidstat.h" #include "flat_page_txstatus.h" #include "util_basics.h" namespace NKikimr { -namespace NTable { - struct IPages; +namespace NTable { + struct IPages; /** * Cold parts are parts that don't have any metadata loaded into memory, @@ -40,14 +40,14 @@ namespace NTable { const TEpoch Epoch; }; - class TPart : public virtual TThrRefBase { - public: - enum ELimits : ui32 { - Trace = 2, /* how many last data pages to keep while seq scans */ - }; - - struct TEgg { - TEpoch Epoch; + class TPart : public virtual TThrRefBase { + public: + enum ELimits : ui32 { + Trace = 2, /* how many last data pages to keep while seq scans */ + }; + + struct TEgg { + TEpoch Epoch; TIntrusiveConstPtr<TPartScheme> Scheme; TSharedData Index; TIntrusiveConstPtr<NPage::TExtBlobs> Blobs; @@ -60,68 +60,68 @@ namespace NTable { TRowVersion MaxRowVersion; TIntrusiveConstPtr<NPage::TGarbageStats> GarbageStats; TIntrusiveConstPtr<NPage::TTxIdStatsPage> TxIdStats; - }; - - struct TStat { - ui64 Bytes; /* Part raw data (unencoded) bytes */ - ui64 Coded; /* Encoded data pages in part bytes */ + }; + + struct TStat { + ui64 Bytes; /* Part raw data (unencoded) bytes */ + ui64 Coded; /* Encoded data pages in part bytes */ ui64 Drops; /* Total rows with ERowOp::Erase code */ - ui64 Rows; /* Total rows count in the TPart */ + ui64 Rows; /* Total rows count in the TPart */ ui64 HiddenRows; /* Hidden (non-main) total rows */ ui64 HiddenDrops; /* Hidden (non-main) rows with ERowOp::Erase */ - }; - - TPart(const TLogoBlobID &label, TEgg egg, TStat stat) - : Label(label) - , Epoch(egg.Epoch) - , Scheme(std::move(egg.Scheme)) - , Blobs(std::move(egg.Blobs)) - , Large(std::move(egg.Large)) - , Small(std::move(egg.Small)) - , Index(std::move(egg.Index)) + }; + + TPart(const TLogoBlobID &label, TEgg egg, TStat stat) + : Label(label) + , Epoch(egg.Epoch) + , Scheme(std::move(egg.Scheme)) + , Blobs(std::move(egg.Blobs)) + , Large(std::move(egg.Large)) + , Small(std::move(egg.Small)) + , Index(std::move(egg.Index)) , GroupIndexes( std::make_move_iterator(egg.GroupIndexes.begin()), std::make_move_iterator(egg.GroupIndexes.end())) , HistoricIndexes( std::make_move_iterator(egg.HistoricIndexes.begin()), std::make_move_iterator(egg.HistoricIndexes.end())) - , ByKey(std::move(egg.ByKey)) + , ByKey(std::move(egg.ByKey)) , GarbageStats(std::move(egg.GarbageStats)) , TxIdStats(std::move(egg.TxIdStats)) - , Stat(stat) + , Stat(stat) , Groups(1 + GroupIndexes.size()) , IndexesRawSize(Index.RawSize() + SumRawSize(GroupIndexes)) , MinRowVersion(egg.MinRowVersion) , MaxRowVersion(egg.MaxRowVersion) - { + { Y_VERIFY(Scheme->Groups.size() == Groups, "Part has scheme with %" PRISZT " groups, but %" PRISZT " indexes", Scheme->Groups.size(), Groups); Y_VERIFY(HistoricIndexes.empty() || HistoricIndexes.size() == Groups, "Part has %" PRISZT " indexes, but %" PRISZT " historic indexes", Groups, HistoricIndexes.size()); - } - - virtual ~TPart() = default; - - void Describe(IOutputStream &out) const noexcept - { - out - << "Part{" << Label << " eph " << Epoch << ", " - << Stat.Coded << "b " << Stat.Rows << "r}"; - } - - bool MightHaveKey(TStringBuf serializedKey) const - { - return ByKey ? ByKey->MightHave(serializedKey) : true; - } - + } + + virtual ~TPart() = default; + + void Describe(IOutputStream &out) const noexcept + { + out + << "Part{" << Label << " eph " << Epoch << ", " + << Stat.Coded << "b " << Stat.Rows << "r}"; + } + + bool MightHaveKey(TStringBuf serializedKey) const + { + return ByKey ? ByKey->MightHave(serializedKey) : true; + } + /** * Returns a cloned part with Epoch changed to the specified epoch */ virtual TIntrusiveConstPtr<TPart> CloneWithEpoch(TEpoch epoch) const = 0; - virtual ui64 DataSize() const = 0; + virtual ui64 DataSize() const = 0; virtual ui64 BackingSize() const = 0; virtual ui64 GetPageSize(NPage::TPageId id, NPage::TGroupId groupId = { }) const = 0; @@ -173,25 +173,25 @@ namespace NTable { return ret; } - public: - const TLogoBlobID Label; + public: + const TLogoBlobID Label; const TEpoch Epoch; const TIntrusiveConstPtr<TPartScheme> Scheme; const TIntrusiveConstPtr<NPage::TExtBlobs> Blobs; const TIntrusiveConstPtr<NPage::TFrames> Large; const TIntrusiveConstPtr<NPage::TFrames> Small; - const NPage::TIndex Index; + const NPage::TIndex Index; const TVector<NPage::TIndex> GroupIndexes; const TVector<NPage::TIndex> HistoricIndexes; const TIntrusiveConstPtr<NPage::TBloom> ByKey; const TIntrusiveConstPtr<NPage::TGarbageStats> GarbageStats; const TIntrusiveConstPtr<NPage::TTxIdStatsPage> TxIdStats; - const TStat Stat; + const TStat Stat; const size_t Groups; const size_t IndexesRawSize; const TRowVersion MinRowVersion; const TRowVersion MaxRowVersion; - }; + }; /** * This class represents a loaded part of tx status table, identified by its label @@ -220,5 +220,5 @@ namespace NTable { const TIntrusiveConstPtr<NPage::TTxStatusPage> TxStatusPage; }; -} -} +} +} diff --git a/ydb/core/tablet_flat/flat_table_part_ut.cpp b/ydb/core/tablet_flat/flat_table_part_ut.cpp index 185265a95e..9106763396 100644 --- a/ydb/core/tablet_flat/flat_table_part_ut.cpp +++ b/ydb/core/tablet_flat/flat_table_part_ut.cpp @@ -2,40 +2,40 @@ #include <ydb/core/tablet_flat/test/libs/rows/layout.h> #include <ydb/core/tablet_flat/test/libs/table/test_part.h> #include <ydb/core/tablet_flat/test/libs/table/test_writer.h> - + #include "flat_stat_part.h" #include "flat_stat_table.h" -#include "flat_page_other.h" +#include "flat_page_other.h" #include <library/cpp/testing/unittest/registar.h> #include <util/stream/null.h> -#include <util/random/mersenne.h> +#include <util/random/mersenne.h> namespace NKikimr { -namespace NTable { -namespace NTest { +namespace NTable { +namespace NTest { Y_UNIT_TEST_SUITE(TLegacy) { - /* This is legacy place for UT, do not put here more tests */ - + /* This is legacy place for UT, do not put here more tests */ + static TIntrusiveConstPtr<NPage::TFrames> CookFrames() - { - NPage::TFrameWriter writer(3); - - writer.Put(100, 0, 100); - writer.Put(120, 2, 200); - writer.Put(169, 1, 300); - writer.Put(200, 0, 400); - writer.Put(200, 1, 500); - writer.Put(210, 2, 600); - writer.Put(338, 2, 700); - writer.Put(700, 2, 800); - - return new NPage::TFrames(writer.Make()); - } - + { + NPage::TFrameWriter writer(3); + + writer.Put(100, 0, 100); + writer.Put(120, 2, 200); + writer.Put(169, 1, 300); + writer.Put(200, 0, 400); + writer.Put(200, 1, 500); + writer.Put(210, 2, 600); + writer.Put(338, 2, 700); + writer.Put(700, 2, 800); + + return new NPage::TFrames(writer.Make()); + } + Y_UNIT_TEST(IndexIter) { TNullOutput devNull; IOutputStream& dbgOut = devNull; //*/ Cerr; @@ -49,7 +49,7 @@ Y_UNIT_TEST_SUITE(TLegacy) { .Col(0, 2, NScheme::NTypeIds::Uint32) .Key({ 0, 1}); - TPartCook cook(lay, { true, 4096 }); + TPartCook cook(lay, { true, 4096 }); const ui64 X1 = 0, X2 = 3000; @@ -59,8 +59,8 @@ Y_UNIT_TEST_SUITE(TLegacy) { } TPartEggs eggs = cook.Finish(); - UNIT_ASSERT_C(eggs.Parts.size() == 1, - "Unexpected " << eggs.Parts.size() << " results"); + UNIT_ASSERT_C(eggs.Parts.size() == 1, + "Unexpected " << eggs.Parts.size() << " results"); auto fnIterate = [&dbgOut, &typeRegistry] (TIntrusiveConstPtr<TPartStore> part, TIntrusiveConstPtr<TRowScheme> scheme) { TPartIndexIterator idxIter(part, scheme->Keys); @@ -73,7 +73,7 @@ Y_UNIT_TEST_SUITE(TLegacy) { }; dbgOut << "Iterate with the matching row scheme" << Endl; - fnIterate(eggs.At(0), eggs.Scheme); + fnIterate(eggs.At(0), eggs.Scheme); // Add a column with default value to the key ui32 def10 = 121212; @@ -86,7 +86,7 @@ Y_UNIT_TEST_SUITE(TLegacy) { .Key({ 0, 1, 10}); dbgOut << "Iterate with added key column with default value" << Endl; - fnIterate(eggs.At(0), newLay.RowScheme()); + fnIterate(eggs.At(0), newLay.RowScheme()); } Y_UNIT_TEST(ScreenedIndexIter) { @@ -103,7 +103,7 @@ Y_UNIT_TEST_SUITE(TLegacy) { .Key({ 0, 1}); const ui64 DATA_PAGE_SIZE = 4096; - TPartCook cook(lay, NPage::TConf(true, DATA_PAGE_SIZE)); + TPartCook cook(lay, NPage::TConf(true, DATA_PAGE_SIZE)); const ui64 X1 = 0, X2 = 3000; @@ -113,8 +113,8 @@ Y_UNIT_TEST_SUITE(TLegacy) { } TPartEggs eggs = cook.Finish(); - UNIT_ASSERT_C(eggs.Parts.size() == 1, - "Unexpected " << eggs.Parts.size() << " results"); + UNIT_ASSERT_C(eggs.Parts.size() == 1, + "Unexpected " << eggs.Parts.size() << " results"); auto fnIterate = [&dbgOut, &typeRegistry] (TIntrusiveConstPtr<TPartStore> part, TIntrusiveConstPtr<TScreen> screen, TIntrusiveConstPtr<TRowScheme> scheme, TIntrusiveConstPtr<NPage::TFrames> frames) -> std::pair<ui64, ui64> { @@ -141,7 +141,7 @@ Y_UNIT_TEST_SUITE(TLegacy) { dbgOut << "Hide all" << Endl; { TIntrusiveConstPtr<TScreen> screen = new TScreen({}); - auto res = fnIterate(eggs.At(0), screen, eggs.Scheme, nullptr); + auto res = fnIterate(eggs.At(0), screen, eggs.Scheme, nullptr); UNIT_ASSERT_VALUES_EQUAL_C(res.first, 0, "RowCount should be 0"); UNIT_ASSERT_VALUES_EQUAL_C(res.second, 0, "DataSize should be 0"); } @@ -158,7 +158,7 @@ Y_UNIT_TEST_SUITE(TLegacy) { dbgOut << "Hide none" << Endl; { TIntrusiveConstPtr<TScreen> screen = new TScreen({TScreen::THole(true)}); - auto res = fnIterate(eggs.At(0), screen, eggs.Scheme, nullptr); + auto res = fnIterate(eggs.At(0), screen, eggs.Scheme, nullptr); UNIT_ASSERT_VALUES_EQUAL_C(res.first, expectedRowCount, "RowCount doesn't match"); UNIT_ASSERT_VALUES_EQUAL_C(res.second, expectedTotalSize, "DataSize doesn't match"); } @@ -166,7 +166,7 @@ Y_UNIT_TEST_SUITE(TLegacy) { dbgOut << "Hide 2 pages" << Endl; { TIntrusiveConstPtr<TScreen> screen = new TScreen({TScreen::THole(0,150), TScreen::THole(550, 10000)}); - auto res = fnIterate(eggs.At(0), screen, eggs.Scheme, nullptr); + auto res = fnIterate(eggs.At(0), screen, eggs.Scheme, nullptr); UNIT_ASSERT_VALUES_EQUAL_C(res.first, expectedRowCount - 400, "RowCount doesn't match"); UNIT_ASSERT_VALUES_EQUAL_C(res.second, expectedTotalSize - REAL_PAGE_SIZE*2, "DataSize doesn't match"); } @@ -174,7 +174,7 @@ Y_UNIT_TEST_SUITE(TLegacy) { dbgOut << "Hide all except 3 pages" << Endl; { TIntrusiveConstPtr<TScreen> screen = new TScreen({TScreen::THole(150, 400)}); - auto res = fnIterate(eggs.At(0), screen, eggs.Scheme, nullptr); + auto res = fnIterate(eggs.At(0), screen, eggs.Scheme, nullptr); UNIT_ASSERT_VALUES_EQUAL_C(res.first, 250, "RowCount doesn't match"); UNIT_ASSERT_VALUES_EQUAL_C(res.second, REAL_PAGE_SIZE*3, "DataSize doesn't match"); } @@ -182,7 +182,7 @@ Y_UNIT_TEST_SUITE(TLegacy) { dbgOut << "Hide 2 rows in one page - we just ignore this" << Endl; { TIntrusiveConstPtr<TScreen> screen = new TScreen({TScreen::THole(0,150), TScreen::THole(152, 10000)}); - auto res = fnIterate(eggs.At(0), screen, eggs.Scheme, nullptr); + auto res = fnIterate(eggs.At(0), screen, eggs.Scheme, nullptr); UNIT_ASSERT_VALUES_EQUAL_C(res.first, expectedRowCount - 2, "RowCount doesn't match"); UNIT_ASSERT_VALUES_EQUAL_C(res.second, expectedTotalSize, "DataSize doesn't match"); } @@ -194,26 +194,26 @@ Y_UNIT_TEST_SUITE(TLegacy) { TScreen::THole(850, 950), TScreen::THole(1200, 10000) }); - auto res = fnIterate(eggs.At(0), screen, eggs.Scheme, nullptr); + auto res = fnIterate(eggs.At(0), screen, eggs.Scheme, nullptr); UNIT_ASSERT_VALUES_EQUAL_C(res.first, expectedRowCount - 400 - 250 - 250, "RowCount doesn't match"); UNIT_ASSERT_VALUES_EQUAL_C(res.second, expectedTotalSize - REAL_PAGE_SIZE*4, "DataSize doesn't match"); } - - dbgOut << "Attach outer pages to index with screen" << Endl; - { - auto frames = CookFrames(); - + + dbgOut << "Attach outer pages to index with screen" << Endl; + { + auto frames = CookFrames(); + // This screen takes two pages, one of them has 4 small blobs, 1800 total bytes TIntrusiveConstPtr<TScreen> screen = new TScreen({ - TScreen::THole(169, 338), - TScreen::THole(845, 1014) - }); - - auto res0 = fnIterate(eggs.At(0), nullptr, eggs.Scheme, frames); + TScreen::THole(169, 338), + TScreen::THole(845, 1014) + }); + + auto res0 = fnIterate(eggs.At(0), nullptr, eggs.Scheme, frames); UNIT_ASSERT_VALUES_EQUAL_C(res0.second, expectedTotalSize + 3600, "DataSize doesn't match without a screen"); - auto res1 = fnIterate(eggs.At(0), screen, eggs.Scheme, frames); + auto res1 = fnIterate(eggs.At(0), screen, eggs.Scheme, frames); UNIT_ASSERT_VALUES_EQUAL_C(res1.second, REAL_PAGE_SIZE*2 + 1800, "DataSize doesn't match with a screen"); - } + } } Y_UNIT_TEST(StatsIter) { @@ -229,7 +229,7 @@ Y_UNIT_TEST_SUITE(TLegacy) { .Col(0, 2, NScheme::NTypeIds::Uint32) .Key({ 0, 1}); - TPartCook cook1(lay1, { true, 4096 }); + TPartCook cook1(lay1, { true, 4096 }); { const ui64 X1 = 0, X2 = 3000; @@ -241,8 +241,8 @@ Y_UNIT_TEST_SUITE(TLegacy) { } TPartEggs eggs1 = cook1.Finish(); - UNIT_ASSERT_C(eggs1.Parts.size() == 1, - "Unexpected " << eggs1.Parts.size() << " results"); + UNIT_ASSERT_C(eggs1.Parts.size() == 1, + "Unexpected " << eggs1.Parts.size() << " results"); // Add a column with default value to the key ui32 def10 = 3; @@ -255,7 +255,7 @@ Y_UNIT_TEST_SUITE(TLegacy) { .Key({ 0, 1, 10}); - TPartCook cook2(lay2, { true, 4096 }); + TPartCook cook2(lay2, { true, 4096 }); { const ui64 X1 = 2000, X2 = 5000; @@ -267,8 +267,8 @@ Y_UNIT_TEST_SUITE(TLegacy) { } TPartEggs eggs2 = cook2.Finish(); - UNIT_ASSERT_C(eggs2.Parts.size() == 1, - "Unexpected " << eggs2.Parts.size() << " results"); + UNIT_ASSERT_C(eggs2.Parts.size() == 1, + "Unexpected " << eggs2.Parts.size() << " results"); TIntrusiveConstPtr<TScreen> screen1 = new TScreen({ TScreen::THole(400, 600), @@ -314,8 +314,8 @@ Y_UNIT_TEST_SUITE(TLegacy) { } -} // namespace NTest -} // namspace NTable +} // namespace NTest +} // namspace NTable } // namespace NKikimr diff --git a/ydb/core/tablet_flat/flat_table_subset.h b/ydb/core/tablet_flat/flat_table_subset.h index bffbf5a127..43659214ba 100644 --- a/ydb/core/tablet_flat/flat_table_subset.h +++ b/ydb/core/tablet_flat/flat_table_subset.h @@ -1,34 +1,34 @@ -#pragma once - -#include "flat_mem_warm.h" +#pragma once + +#include "flat_mem_warm.h" #include "flat_mem_snapshot.h" -#include "flat_table_part.h" -#include "flat_part_laid.h" +#include "flat_table_part.h" +#include "flat_part_laid.h" #include "flat_table_committed.h" - -#include <util/generic/vector.h> - -namespace NKikimr { -namespace NTable { - - struct TSubset { - explicit operator bool() const - { + +#include <util/generic/vector.h> + +namespace NKikimr { +namespace NTable { + + struct TSubset { + explicit operator bool() const + { return bool(Frozen) || bool(Flatten) || bool(ColdParts); - } - - TEpoch Epoch() const noexcept - { + } + + TEpoch Epoch() const noexcept + { TEpoch epoch = TEpoch::Min(); - - for (auto &mem: Frozen) { - epoch = Max(epoch, mem->Epoch); - } - - for (auto &hunk: Flatten) { - epoch = Max(epoch, hunk.Part->Epoch); - } - + + for (auto &mem: Frozen) { + epoch = Max(epoch, mem->Epoch); + } + + for (auto &hunk: Flatten) { + epoch = Max(epoch, hunk.Part->Epoch); + } + for (auto &part: ColdParts) { epoch = Max(epoch, part->Epoch); } @@ -37,40 +37,40 @@ namespace NTable { epoch = Max(epoch, part->Epoch); } - return epoch; - } - - bool IsStickedToHead() const - { + return epoch; + } + + bool IsStickedToHead() const + { return Head == TEpoch::Zero() || Head == Epoch() + 1; - } - + } + void Describe(IOutputStream &out) const noexcept - { - out - << "TSubset{" << "head " << Head - << ", " << Frozen.size() << "m" - << " " << Flatten.size() << "p" + { + out + << "TSubset{" << "head " << Head + << ", " << Frozen.size() << "m" + << " " << Flatten.size() << "p" << " " << ColdParts.size() << "c" - << "}"; - } - - ui64 MaxRows() const noexcept + << "}"; + } + + ui64 MaxRows() const noexcept { - ui64 rows = 0; - + ui64 rows = 0; + for (const auto &memTable : Frozen) rows += memTable->GetRowCount(); - - for (const auto &part : Flatten) - rows += part->Stat.Rows; - + + for (const auto &part : Flatten) + rows += part->Stat.Rows; + if (ColdParts) { // We don't know, signal it to bloom filter rows = 0; } - return rows; + return rows; } TRowVersion MinRowVersion() const noexcept @@ -110,8 +110,8 @@ namespace NTable { , Flatten(std::move(flatten)) { } - const TEpoch Head; - + const TEpoch Head; + TIntrusiveConstPtr<TRowScheme> Scheme; TVector<TMemTableSnapshot> Frozen; TVector<TPartView> Flatten; @@ -119,8 +119,8 @@ namespace NTable { TTransactionMap<TRowVersion> CommittedTransactions; TTransactionSet RemovedTransactions; TVector<TIntrusiveConstPtr<TTxStatusPart>> TxStatus; - }; - + }; + using TGarbage = TVector<TAutoPtr<TSubset>>; /* data of deleted tables */ -} -} +} +} diff --git a/ydb/core/tablet_flat/flat_update_op.h b/ydb/core/tablet_flat/flat_update_op.h index 9d7cb269ef..6260a19abf 100644 --- a/ydb/core/tablet_flat/flat_update_op.h +++ b/ydb/core/tablet_flat/flat_update_op.h @@ -1,60 +1,60 @@ #pragma once - -#include "flat_row_eggs.h" -#include "flat_row_column.h" + +#include "flat_row_eggs.h" +#include "flat_row_column.h" #include <ydb/core/scheme/scheme_tablecell.h> #include <ydb/core/scheme_types/scheme_raw_type_value.h> #include <util/string/printf.h> namespace NKikimr { -namespace NTable { +namespace NTable { inline const char* EOpToStr(const ECellOp op) { - switch (op) { + switch (op) { case ECellOp::Empty: - return "Empty"; + return "Empty"; case ECellOp::Set: - return "Set"; + return "Set"; case ECellOp::Null: - return "Null"; + return "Null"; case ECellOp::Reset: - return "Reset"; - default: - return "!!unexpected op!!"; - } + return "Reset"; + default: + return "!!unexpected op!!"; + } } - struct TUpdateOp { - TUpdateOp() = default; + struct TUpdateOp { + TUpdateOp() = default; TUpdateOp(TTag tag, TCellOp op, TRawTypeValue value) - : Tag(tag) - , Op(op) - , Value(value) - { - - } - - TArrayRef<const char> AsRef() const noexcept - { - return { static_cast<const char*>(Value.Data()), Value.Size() }; - } - - TCell AsCell() const noexcept - { - return { static_cast<const char*>(Value.Data()), Value.Size() }; - } - + : Tag(tag) + , Op(op) + , Value(value) + { + + } + + TArrayRef<const char> AsRef() const noexcept + { + return { static_cast<const char*>(Value.Data()), Value.Size() }; + } + + TCell AsCell() const noexcept + { + return { static_cast<const char*>(Value.Data()), Value.Size() }; + } + TCellOp NormalizedCellOp() const noexcept - { + { return Value || Op != ECellOp::Set ? Op : TCellOp(ECellOp::Null); - } - - TTag Tag = Max<TTag>(); + } + + TTag Tag = Max<TTag>(); TCellOp Op = ECellOp::Empty; - TRawTypeValue Value; - }; - + TRawTypeValue Value; + }; + } -} +} diff --git a/ydb/core/tablet_flat/flat_util_binary.h b/ydb/core/tablet_flat/flat_util_binary.h index 7a6ee78c13..2a7587be2c 100644 --- a/ydb/core/tablet_flat/flat_util_binary.h +++ b/ydb/core/tablet_flat/flat_util_binary.h @@ -1,108 +1,108 @@ -#pragma once - +#pragma once + #include "util_deref.h" -#include <util/stream/output.h> -#include <util/generic/array_ref.h> - -namespace NKikimr { -namespace NUtil { -namespace NBin { - - template<typename L, typename = decltype(std::declval<L>().begin())> - static inline size_t SizeOfOne_(const L &list) noexcept - { - auto num = std::distance(list.begin(), list.end()); - - return sizeof(decltype(*list.begin())) * num; - } - - static inline size_t SizeOf() noexcept { return 0; } - - template<typename T, typename ... Tail> - inline size_t SizeOf(const T &left, Tail && ... tail) noexcept - { - return SizeOfOne_<T>(left) + SizeOf(std::forward<Tail>(tail)...); - } - +#include <util/stream/output.h> +#include <util/generic/array_ref.h> + +namespace NKikimr { +namespace NUtil { +namespace NBin { + + template<typename L, typename = decltype(std::declval<L>().begin())> + static inline size_t SizeOfOne_(const L &list) noexcept + { + auto num = std::distance(list.begin(), list.end()); + + return sizeof(decltype(*list.begin())) * num; + } + + static inline size_t SizeOf() noexcept { return 0; } + + template<typename T, typename ... Tail> + inline size_t SizeOf(const T &left, Tail && ... tail) noexcept + { + return SizeOfOne_<T>(left) + SizeOf(std::forward<Tail>(tail)...); + } + template<typename T, typename = TStdLayoutOrVoid<T>> - static inline char* ToByte(T *ptr) - { - return static_cast<char*>(static_cast<void*>(ptr)); - } - + static inline char* ToByte(T *ptr) + { + return static_cast<char*>(static_cast<void*>(ptr)); + } + template<typename T, typename = TStdLayoutOrVoid<T>> - static inline const char* ToByte(const T *ptr) - { - return static_cast<char*>(static_cast<void*>(ptr)); - } - - template<typename T, typename = TStdLayout<T>> - static inline TArrayRef<const char> ToRef(T &value) - { - return { ToByte(&value), sizeof(value) }; - } - - struct TPut { - TPut(void *ptr) : Ptr(static_cast<char*>(ptr)) { } - - char* operator*() const noexcept - { - return Ptr; - } - - template<typename L, class V = decltype(&*std::declval<L>().begin())> - TPut& Put(const L &list) noexcept - { - auto *array = reinterpret_cast<V>(Ptr); - - Ptr = ToByte(std::copy(list.begin(), list.end(), array)); - - return *this; - } - - template<typename T, typename = TStdLayout<T>> - T* Skip() noexcept - { - return reinterpret_cast<T*>(std::exchange(Ptr, Ptr + sizeof(T))); - } - - private: - char *Ptr = nullptr; - }; - - struct TOut { - TOut(IOutputStream &out) : Out(out) { } - - template<typename T, typename = TStdLayout<T>> - inline TOut& Put(const T &val) - { - Out.Write(static_cast<const void*>(&val), sizeof(val)); - - return *this; - } - - inline TOut& Array(TStringBuf array) - { - return Array<const char>(array); - } - - template<typename T, typename = TStdLayout<T>> - inline TOut& Array(const TVector<T> &array) - { - return Array(TArrayRef<const T>(array.begin(), array.end())); - } - - template<typename T, typename = TStdLayout<T>> - inline TOut& Array(TArrayRef<const T> array) - { - auto *ptr = static_cast<const void*>(array.begin()); - - return Out.Write(ptr, array.size() * sizeof(T)), *this; - } - - private: - IOutputStream &Out; - }; -} -} -} + static inline const char* ToByte(const T *ptr) + { + return static_cast<char*>(static_cast<void*>(ptr)); + } + + template<typename T, typename = TStdLayout<T>> + static inline TArrayRef<const char> ToRef(T &value) + { + return { ToByte(&value), sizeof(value) }; + } + + struct TPut { + TPut(void *ptr) : Ptr(static_cast<char*>(ptr)) { } + + char* operator*() const noexcept + { + return Ptr; + } + + template<typename L, class V = decltype(&*std::declval<L>().begin())> + TPut& Put(const L &list) noexcept + { + auto *array = reinterpret_cast<V>(Ptr); + + Ptr = ToByte(std::copy(list.begin(), list.end(), array)); + + return *this; + } + + template<typename T, typename = TStdLayout<T>> + T* Skip() noexcept + { + return reinterpret_cast<T*>(std::exchange(Ptr, Ptr + sizeof(T))); + } + + private: + char *Ptr = nullptr; + }; + + struct TOut { + TOut(IOutputStream &out) : Out(out) { } + + template<typename T, typename = TStdLayout<T>> + inline TOut& Put(const T &val) + { + Out.Write(static_cast<const void*>(&val), sizeof(val)); + + return *this; + } + + inline TOut& Array(TStringBuf array) + { + return Array<const char>(array); + } + + template<typename T, typename = TStdLayout<T>> + inline TOut& Array(const TVector<T> &array) + { + return Array(TArrayRef<const T>(array.begin(), array.end())); + } + + template<typename T, typename = TStdLayout<T>> + inline TOut& Array(TArrayRef<const T> array) + { + auto *ptr = static_cast<const void*>(array.begin()); + + return Out.Write(ptr, array.size() * sizeof(T)), *this; + } + + private: + IOutputStream &Out; + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_util_misc.h b/ydb/core/tablet_flat/flat_util_misc.h index 06b9fcaa73..ecbe268bca 100644 --- a/ydb/core/tablet_flat/flat_util_misc.h +++ b/ydb/core/tablet_flat/flat_util_misc.h @@ -1,67 +1,67 @@ -#pragma once - -#include <util/generic/ptr.h> +#pragma once + +#include <util/generic/ptr.h> #include <util/generic/vector.h> -#include <typeinfo> - -namespace NKikimr { -namespace NUtil { - - struct TAsIs { - template<typename TWrap> - static constexpr auto Do(TWrap &wrap) noexcept -> decltype(*&wrap) - { - return wrap; - } - }; - - struct TSecond { - template<typename TWrap> - static constexpr auto Do(TWrap &wrap) noexcept -> decltype(*&wrap.second) - { - return wrap.second; - } - }; - - template<typename T> - struct TDtorDel { - static inline void Destroy(T* ptr) noexcept - { - ptr->~T(); - - ::operator delete(ptr); - } - }; - - - template <class T, class = std::enable_if_t<std::is_integral<T>::value>> - struct TIncDecOps { - static inline void Acquire(T* value) noexcept - { - ++*value; - } - - static inline void Release(T* value) noexcept - { - --*value; - } - }; - - template <typename TVal> - TVal SubSafe(TVal &val, TVal sub) noexcept - { - Y_VERIFY(val >= sub, "Counter is underflowed"); - - return val -= Min(val, sub); - } - - template<typename TVal, typename TBase> - TVal* ExactCast(TBase *base) noexcept - { - bool same = (typeid(*base) == typeid(TVal)); - - return !same ? nullptr: static_cast<TVal*>(base); - } - -} -} +#include <typeinfo> + +namespace NKikimr { +namespace NUtil { + + struct TAsIs { + template<typename TWrap> + static constexpr auto Do(TWrap &wrap) noexcept -> decltype(*&wrap) + { + return wrap; + } + }; + + struct TSecond { + template<typename TWrap> + static constexpr auto Do(TWrap &wrap) noexcept -> decltype(*&wrap.second) + { + return wrap.second; + } + }; + + template<typename T> + struct TDtorDel { + static inline void Destroy(T* ptr) noexcept + { + ptr->~T(); + + ::operator delete(ptr); + } + }; + + + template <class T, class = std::enable_if_t<std::is_integral<T>::value>> + struct TIncDecOps { + static inline void Acquire(T* value) noexcept + { + ++*value; + } + + static inline void Release(T* value) noexcept + { + --*value; + } + }; + + template <typename TVal> + TVal SubSafe(TVal &val, TVal sub) noexcept + { + Y_VERIFY(val >= sub, "Counter is underflowed"); + + return val -= Min(val, sub); + } + + template<typename TVal, typename TBase> + TVal* ExactCast(TBase *base) noexcept + { + bool same = (typeid(*base) == typeid(TVal)); + + return !same ? nullptr: static_cast<TVal*>(base); + } + +} +} diff --git a/ydb/core/tablet_flat/flat_writer_banks.h b/ydb/core/tablet_flat/flat_writer_banks.h index bd9115184a..59d18e6260 100644 --- a/ydb/core/tablet_flat/flat_writer_banks.h +++ b/ydb/core/tablet_flat/flat_writer_banks.h @@ -1,40 +1,40 @@ -#pragma once - -#include "flat_sausage_grind.h" -#include "flat_writer_conf.h" -#include "flat_boot_cookie.h" - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NWriter { - - class ICone { - public: +#pragma once + +#include "flat_sausage_grind.h" +#include "flat_writer_conf.h" +#include "flat_boot_cookie.h" + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NWriter { + + class ICone { + public: virtual NPageCollection::TCookieAllocator& CookieRange(ui32 cookieRange) noexcept = 0; virtual void Put(NPageCollection::TGlob&&) noexcept = 0; virtual NPageCollection::TLargeGlobId Put(ui32 cookieRange, ui8 channel, TArrayRef<const char> body, ui32 block) noexcept = 0; - }; - - class TBanks { - public: - using TCookie = NBoot::TCookie; - using EIdx = NBoot::TCookie::EIdx; - - TBanks(const TLogoBlobID &base, TArrayRef<const TConf::TSlot> row) + }; + + class TBanks { + public: + using TCookie = NBoot::TCookie; + using EIdx = NBoot::TCookie::EIdx; + + TBanks(const TLogoBlobID &base, TArrayRef<const TConf::TSlot> row) : Meta(base.TabletID(), Stamp(base), TCookie::CookieRange(EIdx::Pack), row) , Data(base.TabletID(), Stamp(base), TCookie::CookieRangeRaw(), row) - { - - } - - static ui64 Stamp(const TLogoBlobID &logo) noexcept - { - return (ui64(logo.Generation()) << 32) | logo.Step(); - } - + { + + } + + static ui64 Stamp(const TLogoBlobID &logo) noexcept + { + return (ui64(logo.Generation()) << 32) | logo.Step(); + } + NPageCollection::TCookieAllocator Meta; /* PageCollections meta blobs */ NPageCollection::TCookieAllocator Data; /* PageCollections body and blobs */ - }; -} -} -} + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_writer_blocks.h b/ydb/core/tablet_flat/flat_writer_blocks.h index b35da85e16..9cd5b8a9c8 100644 --- a/ydb/core/tablet_flat/flat_writer_blocks.h +++ b/ydb/core/tablet_flat/flat_writer_blocks.h @@ -1,115 +1,115 @@ -#pragma once - -#include "flat_sausagecache.h" -#include "flat_sausage_packet.h" -#include "flat_sausage_writer.h" -#include "flat_sausage_solid.h" -#include "flat_part_iface.h" -#include "flat_part_loader.h" +#pragma once + +#include "flat_sausagecache.h" +#include "flat_sausage_packet.h" +#include "flat_sausage_writer.h" +#include "flat_sausage_solid.h" +#include "flat_part_iface.h" +#include "flat_part_loader.h" #include "util_basics.h" - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NWriter { - - class TBlocks { - public: - using ECache = NTable::NPage::ECache; - using EPage = NTable::NPage::EPage; - using TPageId = NTable::NPage::TPageId; + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NWriter { + + class TBlocks { + public: + using ECache = NTable::NPage::ECache; + using EPage = NTable::NPage::EPage; + using TPageId = NTable::NPage::TPageId; using TCache = TPrivatePageCache::TInfo; - - TBlocks(ICone *cone, ui8 channel, ECache cache, ui32 block) - : Cone(cone) - , Channel(channel) - , Cache(cache) + + TBlocks(ICone *cone, ui8 channel, ECache cache, ui32 block) + : Cone(cone) + , Channel(channel) + , Cache(cache) , Writer(Cone->CookieRange(1), Channel, block) - { - - } - - ~TBlocks() - { + { + + } + + ~TBlocks() + { Y_VERIFY(!Writer.Grab(), "Block writer still has some blobs"); - } - + } + explicit operator bool() const noexcept { return Writer || Regular || Sticky; } TIntrusivePtr<TCache> Finish() noexcept - { + { TIntrusivePtr<TCache> pageCollection; if (auto meta = Writer.Finish(false /* omit empty page collection */)) { - for (auto &glob : Writer.Grab()) - Cone->Put(std::move(glob)); - + for (auto &glob : Writer.Grab()) + Cone->Put(std::move(glob)); + pageCollection = MakePageCollection(std::move(meta)); } - + Y_VERIFY(!Writer, "Block writer is not empty after Finish"); Y_VERIFY(!Regular && !Sticky, "Unexpected non-empty page lists"); return pageCollection; - } - + } + TPageId Write(TSharedData raw, EPage type) - { + { auto pageId = Writer.AddPage(raw, (ui32)type); - - for (auto &glob : Writer.Grab()) - Cone->Put(std::move(glob)); - - if (NTable::TLoader::NeedIn(type)) { - Sticky.emplace_back(pageId, std::move(raw)); + + for (auto &glob : Writer.Grab()) + Cone->Put(std::move(glob)); + + if (NTable::TLoader::NeedIn(type)) { + Sticky.emplace_back(pageId, std::move(raw)); } else if (bool(Cache) && type == EPage::DataPage) { - Regular.emplace_back(pageId, std::move(raw)); - } - - return pageId; - } - + Regular.emplace_back(pageId, std::move(raw)); + } + + return pageId; + } + void WriteInplace(TPageId page, TArrayRef<const char> body) { Writer.AddInplace(page, body); } - private: + private: TIntrusivePtr<TCache> MakePageCollection(TSharedData body) noexcept - { + { auto largeGlobId = CutToChunks(body); - + auto *pack = new NPageCollection::TPageCollection(largeGlobId, std::move(body)); - + TIntrusivePtr<TCache> cache = new TCache(pack); - - const bool sticky = (Cache == ECache::Ever); - - for (auto &paged : Sticky) cache->Fill(paged, true); - for (auto &paged : Regular) cache->Fill(paged, sticky); - + + const bool sticky = (Cache == ECache::Ever); + + for (auto &paged : Sticky) cache->Fill(paged, true); + for (auto &paged : Regular) cache->Fill(paged, sticky); + Sticky.clear(); Regular.clear(); - return cache; - } - + return cache; + } + NPageCollection::TLargeGlobId CutToChunks(TArrayRef<const char> body) - { + { return Cone->Put(0, Channel, body, Writer.Block); - } - - private: - ICone * const Cone = nullptr; - const ui8 Channel = Max<ui8>(); - const ECache Cache = ECache::None; - + } + + private: + ICone * const Cone = nullptr; + const ui8 Channel = Max<ui8>(); + const ECache Cache = ECache::None; + NPageCollection::TWriter Writer; TVector<NPageCollection::TLoadedPage> Regular; TVector<NPageCollection::TLoadedPage> Sticky; - }; -} -} -} + }; +} +} +} diff --git a/ydb/core/tablet_flat/flat_writer_bundle.h b/ydb/core/tablet_flat/flat_writer_bundle.h index d489e51e9d..3c22a3dafd 100644 --- a/ydb/core/tablet_flat/flat_writer_bundle.h +++ b/ydb/core/tablet_flat/flat_writer_bundle.h @@ -1,35 +1,35 @@ -#pragma once - -#include "flat_part_iface.h" -#include "flat_writer_conf.h" -#include "flat_writer_banks.h" -#include "flat_writer_blocks.h" +#pragma once + +#include "flat_part_iface.h" +#include "flat_writer_conf.h" +#include "flat_writer_banks.h" +#include "flat_writer_blocks.h" #include "util_basics.h" - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NWriter { - - class TBundle : public NTable::IPageWriter, protected ICone { - public: - struct TResult { + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NWriter { + + class TBundle : public NTable::IPageWriter, protected ICone { + public: + struct TResult { using TCache = TPrivatePageCache::TInfo; - + TVector<TIntrusivePtr<TCache>> PageCollections; TDeque<NTable::TScreen::THole> Growth; TString Overlay; - }; - - TBundle(const TLogoBlobID &base, const TConf &conf) + }; + + TBundle(const TLogoBlobID &base, const TConf &conf) : Groups(conf.Groups) , BlobsChannel(conf.BlobsChannel) , ExtraChannel(conf.ExtraChannel) - , Banks(base, conf.Slots) - { + , Banks(base, conf.Slots) + { Y_VERIFY(Groups.size() >= 1, "There must be at least one page collection group"); - const auto none = NTable::NPage::ECache::None; - + const auto none = NTable::NPage::ECache::None; + Blocks.resize(Groups.size() + 1); for (size_t group : xrange(Groups.size())) { Blocks[group].Reset(new TBlocks(this, Groups[group].Channel, Groups[group].Cache, Groups[group].Block)); @@ -37,59 +37,59 @@ namespace NWriter { Blocks[Groups.size()].Reset(new TBlocks(this, conf.OuterChannel, none, Groups[0].Block)); Growth = new NTable::TScreen::TCook; - } - - ~TBundle() - { + } + + ~TBundle() + { Y_VERIFY(!Blobs, "Bundle writer still has some blobs"); - } - + } + TVector<NPageCollection::TGlob> GetBlobsToSave() noexcept - { - return std::exchange(Blobs, { }); - } - + { + return std::exchange(Blobs, { }); + } + TVector<TResult> Results() noexcept - { + { for (auto &blocks : Blocks) { Y_VERIFY(!*blocks, "Bundle writer has unflushed data"); - } - + } + return std::move(Results_); - } - + } + NPageCollection::TLargeGlobId WriteExtra(TArrayRef<const char> body) noexcept { return Put(/* data cookieRange */ 1, ExtraChannel, body, Groups[0].Block); } - private: + private: TPageId Write(TSharedData page, EPage type, ui32 group) override - { + { return Blocks.at(group)->Write(std::move(page), type); - } - + } + TPageId WriteOuter(TSharedData page) noexcept override - { + { return Blocks.back()->Write(std::move(page), EPage::Opaque); - } - + } + void WriteInplace(TPageId page, TArrayRef<const char> body) override { Blocks[0]->WriteInplace(page, body); } NPageCollection::TGlobId WriteLarge(TString blob, ui64 ref) noexcept override - { + { auto glob = Banks.Data.Do(BlobsChannel, blob.size()); - - Blobs.emplace_back(glob, std::move(blob)); + + Blobs.emplace_back(glob, std::move(blob)); Growth->Pass(ref); - - return glob; - } - + + return glob; + } + void Finish(TString overlay) noexcept override { auto &result = Results_.emplace_back(); @@ -111,17 +111,17 @@ namespace NWriter { } NPageCollection::TCookieAllocator& CookieRange(ui32 cookieRange) noexcept override - { + { Y_VERIFY(cookieRange == 0 || cookieRange == 1, "Invalid cookieRange requested"); - + return cookieRange == 0 ? Banks.Meta : Banks.Data; - } - + } + void Put(NPageCollection::TGlob&& glob) noexcept override - { - Blobs.emplace_back(std::move(glob)); - } - + { + Blobs.emplace_back(std::move(glob)); + } + NPageCollection::TLargeGlobId Put(ui32 cookieRange, ui8 channel, TArrayRef<const char> body, ui32 block) noexcept override { const auto largeGlobId = CookieRange(cookieRange).Do(channel, body.size(), block); @@ -146,17 +146,17 @@ namespace NWriter { return largeGlobId; } - private: + private: const TVector<TConf::TGroup> Groups; const ui8 BlobsChannel; const ui8 ExtraChannel; - TBanks Banks; + TBanks Banks; TVector<NPageCollection::TGlob> Blobs; TVector<THolder<TBlocks>> Blocks; TAutoPtr<NTable::TScreen::TCook> Growth; TVector<TResult> Results_; - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/flat_writer_conf.h b/ydb/core/tablet_flat/flat_writer_conf.h index 02dfdfdfda..ccbd978293 100644 --- a/ydb/core/tablet_flat/flat_writer_conf.h +++ b/ydb/core/tablet_flat/flat_writer_conf.h @@ -1,20 +1,20 @@ -#pragma once - -#include "flat_sausage_solid.h" -#include "flat_sausage_grind.h" -#include "flat_page_iface.h" - -#include <util/system/types.h> -#include <util/generic/vector.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NWriter { - - struct TConf { - using ECache = NTable::NPage::ECache; +#pragma once + +#include "flat_sausage_solid.h" +#include "flat_sausage_grind.h" +#include "flat_page_iface.h" + +#include <util/system/types.h> +#include <util/generic/vector.h> + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NWriter { + + struct TConf { + using ECache = NTable::NPage::ECache; using TSlot = NPageCollection::TSlot; - + TConf() { // Always include at least 1 group Groups.emplace_back(); @@ -24,15 +24,15 @@ namespace NWriter { ui8 Channel = 1; /* Data channel for page collection */ ECache Cache = ECache::None; /* Keep data pages in memory */ ui32 Block = 8 * 1024 * 1024; /* Page collection max blob size */ - }; - + }; + ui8 BlobsChannel = 1; /* Channel for external blobs */ ui8 OuterChannel = 1; /* Channel for packed cell values */ ui8 ExtraChannel = 1; /* Channel for storing additional data */ TVector<TGroup> Groups; /* Per-group page collection settings */ TVector<TSlot> Slots; /* Storage slots, referred by rooms */ }; - -} -} -} + +} +} +} diff --git a/ydb/core/tablet_flat/logic_alter_main.h b/ydb/core/tablet_flat/logic_alter_main.h index 8fc4ba024c..9e150f00d7 100644 --- a/ydb/core/tablet_flat/logic_alter_main.h +++ b/ydb/core/tablet_flat/logic_alter_main.h @@ -1,61 +1,61 @@ -#pragma once - -#include "flat_exec_commit.h" -#include "flat_sausage_solid.h" -#include "flat_sausage_slicer.h" -#include "flat_bio_eggs.h" - +#pragma once + +#include "flat_exec_commit.h" +#include "flat_sausage_solid.h" +#include "flat_sausage_slicer.h" +#include "flat_bio_eggs.h" + #include <ydb/core/tablet_flat/flat_executor.pb.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { - - class TLogicAlter { - public: + +namespace NKikimr { +namespace NTabletFlatExecutor { + + class TLogicAlter { + public: TLogicAlter(TAutoPtr<NPageCollection::TSteppedCookieAllocator> cookies) - : Cookies(cookies) + : Cookies(cookies) , Slicer(1, Cookies.Get(), NBlockIO::BlockSize) - { - - } - - void Describe(IOutputStream &out) const noexcept - { - out << "LAlter{log " << Log.size() << ", " << Bytes << "b}"; - } - - ui64 LogBytes() const noexcept { return Bytes; } - + { + + } + + void Describe(IOutputStream &out) const noexcept + { + out << "LAlter{log " << Log.size() << ", " << Bytes << "b}"; + } + + ui64 LogBytes() const noexcept { return Bytes; } + void RestoreLog(const NPageCollection::TLargeGlobId &largeGlobId) noexcept - { + { largeGlobId.MaterializeTo(Log), Bytes += largeGlobId.Bytes; - } - - void SnapToLog(NKikimrExecutorFlat::TLogSnapshot &snap) noexcept - { - auto items = snap.MutableSchemeInfoBodies(); - for (const auto &logo : Log) - LogoBlobIDFromLogoBlobID(logo, items->Add()); - } - - void WriteLog(TLogCommit &commit, TString alter) noexcept - { - Cookies->Switch(commit.Step, true /* require step switch */); - - if (alter) { + } + + void SnapToLog(NKikimrExecutorFlat::TLogSnapshot &snap) noexcept + { + auto items = snap.MutableSchemeInfoBodies(); + for (const auto &logo : Log) + LogoBlobIDFromLogoBlobID(logo, items->Add()); + } + + void WriteLog(TLogCommit &commit, TString alter) noexcept + { + Cookies->Switch(commit.Step, true /* require step switch */); + + if (alter) { auto largeGlobId = Slicer.Do(commit.Refs, std::move(alter), false); - + largeGlobId.MaterializeTo(commit.GcDelta.Created); RestoreLog(largeGlobId); - } - } - - protected: + } + } + + protected: TAutoPtr<NPageCollection::TSteppedCookieAllocator> Cookies; NPageCollection::TSlicer Slicer; - ui64 Bytes = 0; - TList<TLogoBlobID> Log; - }; - -} -} + ui64 Bytes = 0; + TList<TLogoBlobID> Log; + }; + +} +} diff --git a/ydb/core/tablet_flat/logic_redo_batch.h b/ydb/core/tablet_flat/logic_redo_batch.h index 4ddf977ddb..a2dca21cc1 100644 --- a/ydb/core/tablet_flat/logic_redo_batch.h +++ b/ydb/core/tablet_flat/logic_redo_batch.h @@ -1,54 +1,54 @@ -#pragma once - +#pragma once + #include "util_basics.h" -#include "flat_exec_commit.h" -#include <util/generic/string.h> -#include <util/generic/vector.h> -#include <util/generic/hash_set.h> +#include "flat_exec_commit.h" +#include <util/generic/string.h> +#include <util/generic/vector.h> +#include <util/generic/hash_set.h> #include <library/cpp/containers/stack_vector/stack_vec.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NRedo { - - struct TBatch { - - void Add(TString redo, TArrayRef<const ui32> affects) - { - Bytes += redo.size(); - Bodies.emplace_back(std::move(redo)); - Tables.insert(affects.begin(), affects.end()); - } - - TArrayRef<const ui32> Affects() noexcept - { - Affects_.assign(Tables.begin(), Tables.end()); - return Affects_; - } - - TString Flush() - { - TString out(Reserve(Bytes)); - - for (const auto &x : Bodies) - out.append(x); - - Bytes = 0; - Bodies.clear(); - Tables.clear(); - - return out; - } - + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NRedo { + + struct TBatch { + + void Add(TString redo, TArrayRef<const ui32> affects) + { + Bytes += redo.size(); + Bodies.emplace_back(std::move(redo)); + Tables.insert(affects.begin(), affects.end()); + } + + TArrayRef<const ui32> Affects() noexcept + { + Affects_.assign(Tables.begin(), Tables.end()); + return Affects_; + } + + TString Flush() + { + TString out(Reserve(Bytes)); + + for (const auto &x : Bodies) + out.append(x); + + Bytes = 0; + Bodies.clear(); + Tables.clear(); + + return out; + } + TAutoPtr<TLogCommit> Commit; - ui64 Bytes = 0; - TVector<TString> Bodies; - - private: - THashSet<ui32> Tables; - TStackVec<ui32> Affects_; - }; - -} -} -} + ui64 Bytes = 0; + TVector<TString> Bodies; + + private: + THashSet<ui32> Tables; + TStackVec<ui32> Affects_; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/logic_redo_eggs.h b/ydb/core/tablet_flat/logic_redo_eggs.h index 398ade6562..c117174f2b 100644 --- a/ydb/core/tablet_flat/logic_redo_eggs.h +++ b/ydb/core/tablet_flat/logic_redo_eggs.h @@ -1,23 +1,23 @@ -#pragma once - -#include <util/system/types.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NRedo { - - struct TUsage { - ui32 Table; - ui64 Items; - ui64 Bytes; - }; - - struct TStats { - ui64 Items; - ui64 Memory; /* Memory consumed by entry states */ +#pragma once + +#include <util/system/types.h> + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NRedo { + + struct TUsage { + ui32 Table; + ui64 Items; + ui64 Bytes; + }; + + struct TStats { + ui64 Items; + ui64 Memory; /* Memory consumed by entry states */ ui64 LargeGlobIds; /* Storage space consumed by redo */ - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/logic_redo_entry.h b/ydb/core/tablet_flat/logic_redo_entry.h index 8d80c4f332..c763c398f6 100644 --- a/ydb/core/tablet_flat/logic_redo_entry.h +++ b/ydb/core/tablet_flat/logic_redo_entry.h @@ -1,95 +1,95 @@ -#pragma once - -#include "defs.h" -#include "util_fmt_flat.h" -#include <util/generic/string.h> -#include <util/generic/hash.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NRedo { - - struct TEntry { - template<typename ... Args> - static TEntry* Create(NTable::TTxStamp stamp, TArrayRef<const ui32> affects, Args&& ... args) - { - auto *ptr = malloc(sizeof(TEntry) + affects.size() * sizeof(ui32)); - - return ::new(ptr) TEntry(stamp, affects, std::forward<Args>(args)...); - } - - void operator delete (void *p) - { - free(p); - } - - void Describe(IOutputStream &out) const noexcept - { - out +#pragma once + +#include "defs.h" +#include "util_fmt_flat.h" +#include <util/generic/string.h> +#include <util/generic/hash.h> + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NRedo { + + struct TEntry { + template<typename ... Args> + static TEntry* Create(NTable::TTxStamp stamp, TArrayRef<const ui32> affects, Args&& ... args) + { + auto *ptr = malloc(sizeof(TEntry) + affects.size() * sizeof(ui32)); + + return ::new(ptr) TEntry(stamp, affects, std::forward<Args>(args)...); + } + + void operator delete (void *p) + { + free(p); + } + + void Describe(IOutputStream &out) const noexcept + { + out << "Redo{" << NFmt::TStamp(Stamp) << " (" << Embedded.size() << " +" << LargeGlobId.Bytes << ")b, ~" << NFmt::Arr(Tables()) - << "}"; - } - - ui32 BytesMem() const noexcept - { - return sizeof(TEntry) + sizeof(ui32) * Affects + Embedded.size(); - } - - ui64 BytesData() const noexcept - { + << "}"; + } + + ui32 BytesMem() const noexcept + { + return sizeof(TEntry) + sizeof(ui32) * Affects + Embedded.size(); + } + + ui64 BytesData() const noexcept + { return Embedded.size() + LargeGlobId.Bytes; - } - + } + ui64 BytesLargeGlobId() const noexcept - { + { return LargeGlobId.Bytes; - } - - TArrayRef<const ui32> Tables() const noexcept - { - return { (const ui32*)((const TLogoBlobID*)(this + 1)), Affects }; - } - - ui32 FilterTables(const THashMap<ui32, NTable::TSnapEdge> &edges) - { - ui32 *begin = (ui32*)((TLogoBlobID*)(this + 1)); - ui32 * const end = begin + Affects; - - for (ui32 *write = begin, *read = begin; ; ++read) { - if (read == end) { - return Affects = write - begin; - } else { - const auto *sn = edges.FindPtr(*read); - if (!sn || sn->TxStamp < Stamp) - *write++ = *read; - } - } - } - - const NTable::TTxStamp Stamp; + } + + TArrayRef<const ui32> Tables() const noexcept + { + return { (const ui32*)((const TLogoBlobID*)(this + 1)), Affects }; + } + + ui32 FilterTables(const THashMap<ui32, NTable::TSnapEdge> &edges) + { + ui32 *begin = (ui32*)((TLogoBlobID*)(this + 1)); + ui32 * const end = begin + Affects; + + for (ui32 *write = begin, *read = begin; ; ++read) { + if (read == end) { + return Affects = write - begin; + } else { + const auto *sn = edges.FindPtr(*read); + if (!sn || sn->TxStamp < Stamp) + *write++ = *read; + } + } + } + + const NTable::TTxStamp Stamp; const NPageCollection::TLargeGlobId LargeGlobId; - const TString Embedded; - ui32 Affects = 0; - ui32 References = 0; - - private: + const TString Embedded; + ui32 Affects = 0; + ui32 References = 0; + + private: TEntry(NTable::TTxStamp stamp, TArrayRef<const ui32> affects, const NPageCollection::TLargeGlobId &largeGlobId) - : Stamp(stamp) + : Stamp(stamp) , LargeGlobId(largeGlobId) - , Affects(affects.size()) - { - std::copy(affects.begin(), affects.end(), (ui32*)(this + 1)); - } - - TEntry(NTable::TTxStamp stamp, TArrayRef<const ui32> affects, TString embedded) - : Stamp(stamp) - , Embedded(std::move(embedded)) - , Affects(affects.size()) - { - std::copy(affects.begin(), affects.end(), (ui32*)(this + 1)); - } - }; -} -} -} + , Affects(affects.size()) + { + std::copy(affects.begin(), affects.end(), (ui32*)(this + 1)); + } + + TEntry(NTable::TTxStamp stamp, TArrayRef<const ui32> affects, TString embedded) + : Stamp(stamp) + , Embedded(std::move(embedded)) + , Affects(affects.size()) + { + std::copy(affects.begin(), affects.end(), (ui32*)(this + 1)); + } + }; +} +} +} diff --git a/ydb/core/tablet_flat/logic_redo_queue.h b/ydb/core/tablet_flat/logic_redo_queue.h index c8851bba64..241d4b94de 100644 --- a/ydb/core/tablet_flat/logic_redo_queue.h +++ b/ydb/core/tablet_flat/logic_redo_queue.h @@ -1,150 +1,150 @@ -#pragma once - -#include "util_fmt_flat.h" -#include "flat_util_misc.h" -#include "logic_redo_eggs.h" -#include "logic_redo_entry.h" -#include "logic_redo_table.h" -#include "flat_exec_commit.h" -#include <util/generic/hash.h> -#include <util/generic/intrlist.h> +#pragma once + +#include "util_fmt_flat.h" +#include "flat_util_misc.h" +#include "logic_redo_eggs.h" +#include "logic_redo_entry.h" +#include "logic_redo_table.h" +#include "flat_exec_commit.h" +#include <util/generic/hash.h> +#include <util/generic/intrlist.h> #include <ydb/core/util/queue_inplace.h> #include <ydb/core/tablet_flat/flat_executor.pb.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NRedo { - - struct TQueue { - using TStamp = NTable::TTxStamp; - using TAffects = TArrayRef<const ui32>; - - TQueue(THashMap<ui32, NTable::TSnapEdge> edges) - : Log(new TLog) - , Edges(std::move(edges)) - { - - } - + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NRedo { + + struct TQueue { + using TStamp = NTable::TTxStamp; + using TAffects = TArrayRef<const ui32>; + + TQueue(THashMap<ui32, NTable::TSnapEdge> edges) + : Log(new TLog) + , Edges(std::move(edges)) + { + + } + void Push(TStamp stamp, TAffects affects, const NPageCollection::TLargeGlobId &largeGlobId) - { + { Push(TEntry::Create(stamp, affects, largeGlobId)); - } - - void Push(TStamp stamp, TAffects affects, TString embedded) - { + } + + void Push(TStamp stamp, TAffects affects, TString embedded) + { NSan::CheckMemIsInitialized(embedded.data(), embedded.size()); - Push(TEntry::Create(stamp, affects, std::move(embedded))); - } - - void Describe(IOutputStream &out) const noexcept - { - out - << "LRedo{" << Overhead.size() << "t" << ", " << Items + Push(TEntry::Create(stamp, affects, std::move(embedded))); + } + + void Describe(IOutputStream &out) const noexcept + { + out + << "LRedo{" << Overhead.size() << "t" << ", " << Items << " (" << Memory << " mem" << ", " << LargeGlobIdsBytes << " raw)b }"; - } - - void Push(TEntry *entry) noexcept - { + } + + void Push(TEntry *entry) noexcept + { if (bool(entry->Embedded) == bool(entry->LargeGlobId)) { - Y_Fail(NFmt::Do(*entry) << " has incorrect payload"); - } - - Log->Push(entry); - + Y_Fail(NFmt::Do(*entry) << " has incorrect payload"); + } + + Log->Push(entry); + Items++; Memory += entry->BytesMem(); LargeGlobIdsBytes += entry->BytesLargeGlobId(); - - for (ui32 table : entry->Tables()) { - const auto *edge = Edges.FindPtr(table); - - if (edge && edge->TxStamp >= entry->Stamp) { - Y_Fail( - "Entry " << NFmt::Do(*entry) << " queued below table" - << table << " edge " << NFmt::TStamp(edge->TxStamp)); + + for (ui32 table : entry->Tables()) { + const auto *edge = Edges.FindPtr(table); + + if (edge && edge->TxStamp >= entry->Stamp) { + Y_Fail( + "Entry " << NFmt::Do(*entry) << " queued below table" + << table << " edge " << NFmt::TStamp(edge->TxStamp)); } else if (auto *over = Overhead[table].Push(table, entry)) { - Changes.PushBack(over); - } - } - - if (entry->References == 0) - Y_Fail(NFmt::Do(*entry) << " has no effects on data"); - } - - void Cut(ui32 table, NTable::TSnapEdge edge, TGCBlobDelta &gc) noexcept - { - Y_VERIFY(edge.TxStamp != Max<ui64>(), "Undefined TxStamp of edge"); - - auto &cur = Edges[table]; - - cur.TxStamp = Max(cur.TxStamp, edge.TxStamp); - cur.Head = Max(cur.Head, edge.Head); - + Changes.PushBack(over); + } + } + + if (entry->References == 0) + Y_Fail(NFmt::Do(*entry) << " has no effects on data"); + } + + void Cut(ui32 table, NTable::TSnapEdge edge, TGCBlobDelta &gc) noexcept + { + Y_VERIFY(edge.TxStamp != Max<ui64>(), "Undefined TxStamp of edge"); + + auto &cur = Edges[table]; + + cur.TxStamp = Max(cur.TxStamp, edge.TxStamp); + cur.Head = Max(cur.Head, edge.Head); + if (auto *over = Overhead[table].Cut(cur.TxStamp, gc, LargeGlobIdsBytes)) - Changes.PushBack(over); - } - - void Flush(NKikimrExecutorFlat::TLogSnapshot &snap) - { + Changes.PushBack(over); + } + + void Flush(NKikimrExecutorFlat::TLogSnapshot &snap) + { for (auto &it : Overhead) it.second.Clear(); - - auto was = std::exchange(Log, new TLog); - + + auto was = std::exchange(Log, new TLog); + Items = 0; Memory = 0; LargeGlobIdsBytes = 0; - - auto logos = snap.MutableNonSnapLogBodies(); - + + auto logos = snap.MutableNonSnapLogBodies(); + while (TAutoPtr<TEntry> entry = was->Pop()) { - if (entry->FilterTables(Edges)) { + if (entry->FilterTables(Edges)) { for (auto blobId : entry->LargeGlobId.Blobs()) { LogoBlobIDFromLogoBlobID(blobId, logos->Add()); - } - - if (entry->Embedded) { - auto *body = snap.AddEmbeddedLogBodies(); - - body->SetGeneration(entry->Stamp.Gen()); - body->SetStep(entry->Stamp.Step()); - body->SetBody(entry->Embedded); - } - - entry->References = 0; - - Push(entry.Release()); - } else { - Y_VERIFY(entry->References == 0); - } - } - } - - TArrayRef<const TUsage> GrabUsage() noexcept - { - Usage.clear(); - - while (auto *one = Changes ? Changes.PopFront() : nullptr) { + } + + if (entry->Embedded) { + auto *body = snap.AddEmbeddedLogBodies(); + + body->SetGeneration(entry->Stamp.Gen()); + body->SetStep(entry->Stamp.Step()); + body->SetBody(entry->Embedded); + } + + entry->References = 0; + + Push(entry.Release()); + } else { + Y_VERIFY(entry->References == 0); + } + } + } + + TArrayRef<const TUsage> GrabUsage() noexcept + { + Usage.clear(); + + while (auto *one = Changes ? Changes.PopFront() : nullptr) { Usage.push_back({ one->Table, one->Trace.size(), one->Bytes }); - } - - return Usage; - } - - using TLog = TOneOneQueueInplace<NRedo::TEntry *, 4096>; - - TAutoPtr<TLog, TLog::TPtrCleanInplaceMallocDestructor> Log; - THashMap<ui32, NTable::TSnapEdge> Edges; - THashMap<ui32, TOverhead> Overhead; - TIntrusiveList<TOverhead> Changes; - TVector<TUsage> Usage; - - ui64 Items = 0; - ui64 Memory = 0; /* Bytes consumed memory by records */ + } + + return Usage; + } + + using TLog = TOneOneQueueInplace<NRedo::TEntry *, 4096>; + + TAutoPtr<TLog, TLog::TPtrCleanInplaceMallocDestructor> Log; + THashMap<ui32, NTable::TSnapEdge> Edges; + THashMap<ui32, TOverhead> Overhead; + TIntrusiveList<TOverhead> Changes; + TVector<TUsage> Usage; + + ui64 Items = 0; + ui64 Memory = 0; /* Bytes consumed memory by records */ ui64 LargeGlobIdsBytes = 0; /* Bytes acquired in redo TLargeGlobId-s */ - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/logic_redo_table.h b/ydb/core/tablet_flat/logic_redo_table.h index acb7ba8510..57186d1431 100644 --- a/ydb/core/tablet_flat/logic_redo_table.h +++ b/ydb/core/tablet_flat/logic_redo_table.h @@ -1,69 +1,69 @@ -#pragma once - -#include "logic_redo_entry.h" -#include "flat_exec_commit.h" -#include <util/generic/deque.h> -#include <util/generic/intrlist.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NRedo { - - struct TOverhead : public TIntrusiveListItem<TOverhead> { - using TTxStamp = NTable::TTxStamp; - - void Clear() noexcept - { +#pragma once + +#include "logic_redo_entry.h" +#include "flat_exec_commit.h" +#include <util/generic/deque.h> +#include <util/generic/intrlist.h> + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NRedo { + + struct TOverhead : public TIntrusiveListItem<TOverhead> { + using TTxStamp = NTable::TTxStamp; + + void Clear() noexcept + { Trace.clear(); Bytes = 0; - } - - TOverhead* Push(ui32 table, TEntry* entry) noexcept - { - if (Trace && Trace.back() == entry) { - Y_Fail(NFmt::Do(*entry) << " is dublicated in table trace"); - } else if (Trace && entry->Stamp < Trace.back()->Stamp) { - Y_Fail(NFmt::Do(*entry) << " is in the past of table trace"); - } - - Trace.emplace_back(entry); - Bytes += entry->BytesData(); - Table = table; - entry->References += 1; - - return this; - } - + } + + TOverhead* Push(ui32 table, TEntry* entry) noexcept + { + if (Trace && Trace.back() == entry) { + Y_Fail(NFmt::Do(*entry) << " is dublicated in table trace"); + } else if (Trace && entry->Stamp < Trace.back()->Stamp) { + Y_Fail(NFmt::Do(*entry) << " is in the past of table trace"); + } + + Trace.emplace_back(entry); + Bytes += entry->BytesData(); + Table = table; + entry->References += 1; + + return this; + } + TOverhead* Cut(TTxStamp stamp, TGCBlobDelta &gc, ui64 &largeGlobIds) noexcept - { - if (!Trace || stamp < Trace.front()->Stamp) { - return nullptr; - } - - const auto end = std::upper_bound(Trace.begin(), Trace.end(), stamp, - [](TTxStamp stamp, const TEntry *entry) { - return stamp < entry->Stamp; - }); - - Y_VERIFY(end != Trace.begin()); - - for (auto it = Trace.begin(); it != end; ++it) { - NUtil::SubSafe(Bytes, (*it)->BytesData()); - - if (NUtil::SubSafe((*it)->References, ui32(1)) == 0) { + { + if (!Trace || stamp < Trace.front()->Stamp) { + return nullptr; + } + + const auto end = std::upper_bound(Trace.begin(), Trace.end(), stamp, + [](TTxStamp stamp, const TEntry *entry) { + return stamp < entry->Stamp; + }); + + Y_VERIFY(end != Trace.begin()); + + for (auto it = Trace.begin(); it != end; ++it) { + NUtil::SubSafe(Bytes, (*it)->BytesData()); + + if (NUtil::SubSafe((*it)->References, ui32(1)) == 0) { (*it)->LargeGlobId.MaterializeTo(gc.Deleted); NUtil::SubSafe(largeGlobIds, (*it)->BytesLargeGlobId()); - } - } - Trace.erase(Trace.begin(), end); - return this; - } - - ui32 Table = Max<ui32>(); - TDeque<TEntry*> Trace; - ui64 Bytes = 0; /* Bytes of redo logs touched by this table */ - }; - -} -} -} + } + } + Trace.erase(Trace.begin(), end); + return this; + } + + ui32 Table = Max<ui32>(); + TDeque<TEntry*> Trace; + ui64 Bytes = 0; /* Bytes of redo logs touched by this table */ + }; + +} +} +} diff --git a/ydb/core/tablet_flat/logic_snap_main.h b/ydb/core/tablet_flat/logic_snap_main.h index 89e1ea7487..b036947df1 100644 --- a/ydb/core/tablet_flat/logic_snap_main.h +++ b/ydb/core/tablet_flat/logic_snap_main.h @@ -1,98 +1,98 @@ -#pragma once - +#pragma once + #include "util_basics.h" -#include "util_fmt_abort.h" -#include "util_fmt_line.h" -#include "flat_sausage_slicer.h" -#include "flat_bio_eggs.h" -#include "flat_exec_commit.h" -#include "logic_snap_waste.h" - +#include "util_fmt_abort.h" +#include "util_fmt_line.h" +#include "flat_sausage_slicer.h" +#include "flat_bio_eggs.h" +#include "flat_exec_commit.h" +#include "logic_snap_waste.h" + #include <ydb/core/tablet_flat/flat_executor.pb.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { - - class TLogicSnap { - public: - using TSnap = NKikimrExecutorFlat::TLogSnapshot; - + +namespace NKikimr { +namespace NTabletFlatExecutor { + + class TLogicSnap { + public: + using TSnap = NKikimrExecutorFlat::TLogSnapshot; + TLogicSnap(TAutoPtr<NPageCollection::TSteppedCookieAllocator> cookies, TIntrusivePtr<NSnap::TWaste> waste, NPageCollection::TLargeGlobId last) - : Cookies(cookies) + : Cookies(cookies) , Slicer(1, Cookies.Get(), NBlockIO::BlockSize) - , Waste_(std::move(waste)) - , Last(last) - { - - } - - void Describe(IOutputStream &out) const noexcept - { - out - << "LSnap{" << Cookies->Tablet << ":" << Cookies->Gen - << ", on " << Last.Lead.Generation() << ":" << Last.Lead.Step() - << ", " << Last.Bytes << "b, " << (Pending ? "wait" : "ready") - << "}"; - } - - ui64 LogBytes() const noexcept { return Last.Bytes; } - - bool MayFlush(bool force) const noexcept - { - return - !Pending - && (force - || Waste_->Trace >= 300 - || Waste_->Items >= 300 + , Waste_(std::move(waste)) + , Last(last) + { + + } + + void Describe(IOutputStream &out) const noexcept + { + out + << "LSnap{" << Cookies->Tablet << ":" << Cookies->Gen + << ", on " << Last.Lead.Generation() << ":" << Last.Lead.Step() + << ", " << Last.Bytes << "b, " << (Pending ? "wait" : "ready") + << "}"; + } + + ui64 LogBytes() const noexcept { return Last.Bytes; } + + bool MayFlush(bool force) const noexcept + { + return + !Pending + && (force + || Waste_->Trace >= 300 + || Waste_->Items >= 300 || Waste_->Bytes >= 128*1024*1024); - } - - const NSnap::TWaste& Waste() const noexcept { return *Waste_; } - - void Confirm(ui32 step) noexcept - { - if (Pending == 0 || Pending != step) - Y_Fail( - NFmt::Do(*this) << " got unexpected confirm for " << step); - - Pending = 0; - } - - void MakeSnap(TSnap &snap, TLogCommit &commit, NUtil::ILogger *logger) - { - if (Pending != 0) { - Y_Fail( - NFmt::Do(*this) << " cannot make snap on " << commit.Step); - } - - if (auto *proto = snap.MutableWaste()) { - proto->SetSince(Waste_->Since); - proto->SetLevel(Max(Waste_->Level, i64(0))); - proto->SetKeep(Waste_->Keep); - proto->SetDrop(Waste_->Drop); - } - - Pending = commit.Step; - Cookies->Switch(commit.Step, true /* require step switch */); - - Last = Slicer.Do(commit.Refs, snap.SerializeAsString(), true); - - if (auto logl = logger->Log(NUtil::ELnLev::Info)) { - logl - << NFmt::Do(*this) << " done, " << NFmt::Do(*Waste_); - } - - Waste_->Flush(); - } - - private: - ui32 Pending = 0; + } + + const NSnap::TWaste& Waste() const noexcept { return *Waste_; } + + void Confirm(ui32 step) noexcept + { + if (Pending == 0 || Pending != step) + Y_Fail( + NFmt::Do(*this) << " got unexpected confirm for " << step); + + Pending = 0; + } + + void MakeSnap(TSnap &snap, TLogCommit &commit, NUtil::ILogger *logger) + { + if (Pending != 0) { + Y_Fail( + NFmt::Do(*this) << " cannot make snap on " << commit.Step); + } + + if (auto *proto = snap.MutableWaste()) { + proto->SetSince(Waste_->Since); + proto->SetLevel(Max(Waste_->Level, i64(0))); + proto->SetKeep(Waste_->Keep); + proto->SetDrop(Waste_->Drop); + } + + Pending = commit.Step; + Cookies->Switch(commit.Step, true /* require step switch */); + + Last = Slicer.Do(commit.Refs, snap.SerializeAsString(), true); + + if (auto logl = logger->Log(NUtil::ELnLev::Info)) { + logl + << NFmt::Do(*this) << " done, " << NFmt::Do(*Waste_); + } + + Waste_->Flush(); + } + + private: + ui32 Pending = 0; TAutoPtr<NPageCollection::TSteppedCookieAllocator> Cookies; NPageCollection::TSlicer Slicer; TIntrusivePtr<NSnap::TWaste> Waste_; NPageCollection::TLargeGlobId Last; - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/logic_snap_waste.h b/ydb/core/tablet_flat/logic_snap_waste.h index 257ff08b9e..f7f9ee6a1a 100644 --- a/ydb/core/tablet_flat/logic_snap_waste.h +++ b/ydb/core/tablet_flat/logic_snap_waste.h @@ -1,60 +1,60 @@ -#pragma once - +#pragma once + #include "util_basics.h" -#include "util_fmt_flat.h" -#include "flat_exec_commit.h" -#include "flat_boot_cookie.h" - -namespace NKikimr { -namespace NTabletFlatExecutor { -namespace NSnap { - - struct TWaste : public TSimpleRefCount<TWaste> { - using EIdx = NBoot::TCookie::EIdx; - - TWaste(ui32 gen) : Since(ui64(gen) << 32) { } - - void Describe(IOutputStream &out, bool full = false) const noexcept - { - out - << "Waste{" << NFmt::TStamp(Since) << ", " << Level << "b" - << " +(" << Items << ", " << Bytes << "b), " << Trace << " trc"; - - (full ? (out <<", -" << Drop << "b acc") : out) << "}"; - } - - void Account(const TGCBlobDelta &delta) noexcept - { - Trace += 1; - - for (auto &one : delta.Created) { - Level += one.BlobSize(), Keep += one.BlobSize(); - } - - for (auto &one : delta.Deleted) { - Level -= one.BlobSize(), Drop += one.BlobSize(); - - Items += 1, Bytes += one.BlobSize(); - } - } - - void Flush() noexcept - { - Trace = 0, Items = 0, Bytes = 0; - } - - ui64 Since = 0; /* stamp of start accounting age */ +#include "util_fmt_flat.h" +#include "flat_exec_commit.h" +#include "flat_boot_cookie.h" + +namespace NKikimr { +namespace NTabletFlatExecutor { +namespace NSnap { + + struct TWaste : public TSimpleRefCount<TWaste> { + using EIdx = NBoot::TCookie::EIdx; + + TWaste(ui32 gen) : Since(ui64(gen) << 32) { } + + void Describe(IOutputStream &out, bool full = false) const noexcept + { + out + << "Waste{" << NFmt::TStamp(Since) << ", " << Level << "b" + << " +(" << Items << ", " << Bytes << "b), " << Trace << " trc"; + + (full ? (out <<", -" << Drop << "b acc") : out) << "}"; + } + + void Account(const TGCBlobDelta &delta) noexcept + { + Trace += 1; + + for (auto &one : delta.Created) { + Level += one.BlobSize(), Keep += one.BlobSize(); + } + + for (auto &one : delta.Deleted) { + Level -= one.BlobSize(), Drop += one.BlobSize(); + + Items += 1, Bytes += one.BlobSize(); + } + } + + void Flush() noexcept + { + Trace = 0, Items = 0, Bytes = 0; + } + + ui64 Since = 0; /* stamp of start accounting age */ i64 Level = 0; /* Total bytes kept by commit manager */ - ui64 Trace = 0; /* Redo log commits since last snap */ - ui64 Items = 0; - ui64 Bytes = 0; /* Waste grown since last snapshot */ - - /* Total KEEPed and DROPed blobs by tablet since birth or pollution - collection age. Pre-age tablets may have (Keep - Drop) < 0. */ - - ui64 Keep = 0; - ui64 Drop = 0; - }; -} -} -} + ui64 Trace = 0; /* Redo log commits since last snap */ + ui64 Items = 0; + ui64 Bytes = 0; /* Waste grown since last snapshot */ + + /* Total KEEPed and DROPed blobs by tablet since birth or pollution + collection age. Pre-age tablets may have (Keep - Drop) < 0. */ + + ui64 Keep = 0; + ui64 Drop = 0; + }; +} +} +} diff --git a/ydb/core/tablet_flat/protos/flat_table_part.proto b/ydb/core/tablet_flat/protos/flat_table_part.proto index 61fa39e957..36d9e1cd67 100644 --- a/ydb/core/tablet_flat/protos/flat_table_part.proto +++ b/ydb/core/tablet_flat/protos/flat_table_part.proto @@ -1,59 +1,59 @@ import "ydb/core/protos/base.proto"; -package NKikimr.NTable.NProto; +package NKikimr.NTable.NProto; option java_package = "ru.yandex.kikimr.proto"; -message TEvol { - required uint32 Tail = 1; - required uint32 Head = 2; -} - -message TPartColumn { +message TEvol { + required uint32 Tail = 1; + required uint32 Head = 2; +} + +message TPartColumn { optional uint32 Tag = 1; optional uint32 Type = 2; - optional uint32 Key = 3; + optional uint32 Key = 3; optional uint32 Group = 4; } -message TPartScheme { - repeated TPartColumn Columns = 1; +message TPartScheme { + repeated TPartColumn Columns = 1; repeated uint32 KeyTags = 2; - optional uint32 Legacy0_ = 3; + optional uint32 Legacy0_ = 3; } -message TLayout { - optional uint32 Index = 1; - optional uint32 Globs = 2; // EPage::Globs, external blobs catalog - optional uint32 Large = 3; // EPage::Frames index for globs catalog - optional uint32 Small = 6; // EPage::Frames index for packed blobs - optional uint32 ByKey = 4; // EPage::ByKey bloom filter page - optional uint32 Scheme = 5; // EPage::Schem2 with data pages scheme +message TLayout { + optional uint32 Index = 1; + optional uint32 Globs = 2; // EPage::Globs, external blobs catalog + optional uint32 Large = 3; // EPage::Frames index for globs catalog + optional uint32 Small = 6; // EPage::Frames index for packed blobs + optional uint32 ByKey = 4; // EPage::ByKey bloom filter page + optional uint32 Scheme = 5; // EPage::Schem2 with data pages scheme repeated uint32 GroupIndexes = 7; // EPage::Index for alt column groups repeated uint32 HistoricIndexes = 8; // EPage::Index for historic data optional uint32 GarbageStats = 9; // EPage::GarbageStats for historic data optional uint32 TxIdStats = 10; // EPage::TxIdStats for uncommitted deltas -} - -message TStat { - optional uint64 Bytes = 1; // Acrual raw data pages size in part - optional uint64 Coded = 2; // Observable (encoded) data pages size +} + +message TStat { + optional uint64 Bytes = 1; // Acrual raw data pages size in part + optional uint64 Coded = 2; // Observable (encoded) data pages size optional uint64 Drops = 3; // Rows with ERowOp::Erase code - optional uint64 Rows = 4; // All rows count in the TPart + optional uint64 Rows = 4; // All rows count in the TPart optional uint64 HiddenRows = 5; // Hidden (non-head) total rows optional uint64 HiddenDrops = 6; // Hidden (non-main) rows with ERowOp::Erase -} - +} + message TRoot { // NTable::TPart page collection metablob optional int64 Epoch = 2; optional uint64 Bytes = 3; // Actual raw data pages size in part - optional uint64 Coded = 4; // Observable (encoded) data pages size - optional TEvol Evol = 6; - optional TStat Stat = 7; // Some stats collected on compaction - optional TLayout Layout = 8;// Non-data pages layout information + optional uint64 Coded = 4; // Observable (encoded) data pages size + optional TEvol Evol = 6; + optional TStat Stat = 7; // Some stats collected on compaction + optional TLayout Layout = 8;// Non-data pages layout information optional NKikimrProto.TRowVersion MinRowVersion = 9; optional NKikimrProto.TRowVersion MaxRowVersion = 10; } - + message TSliceBounds { optional bytes FirstKey = 1; optional bytes LastKey = 2; @@ -64,10 +64,10 @@ message TSliceBounds { reserved 7; // uint64 DataSize no longer used or stored } -message TOverlay { - repeated uint64 Screen = 1; // Set of [begin, end) rowId ranges +message TOverlay { + repeated uint64 Screen = 1; // Set of [begin, end) rowId ranges repeated TSliceBounds Slices = 2; // Set of extended range slices -} +} message TOverlayDelta { repeated TSliceBounds RemovedSlices = 1; // set of slices that are removed diff --git a/ydb/core/tablet_flat/shared_cache_events.h b/ydb/core/tablet_flat/shared_cache_events.h index e7ed55be96..a7e8be8a44 100644 --- a/ydb/core/tablet_flat/shared_cache_events.h +++ b/ydb/core/tablet_flat/shared_cache_events.h @@ -1,7 +1,7 @@ -#pragma once - -#include "defs.h" -#include "flat_bio_events.h" +#pragma once + +#include "defs.h" +#include "flat_bio_events.h" #include "shared_handle.h" #include <util/generic/map.h> @@ -9,50 +9,50 @@ #include <util/generic/hash.h> #include <util/generic/hash_set.h> -#include <memory> - -namespace NKikimr { +#include <memory> + +namespace NKikimr { namespace NSharedCache { - + using EPriority = NTabletFlatExecutor::NBlockIO::EPriority; - - enum EEv { + + enum EEv { EvBegin = EventSpaceBegin(TKikimrEvents::ES_FLAT_EXECUTOR), - + EvTouch = EvBegin + 512, - EvUnregister, - EvInvalidate, + EvUnregister, + EvInvalidate, EvAttach, - EvRequest, + EvRequest, EvResult, EvUpdated, - - EvEnd - - /* +1024 range is reserved for scan events */ - }; - - static_assert(EvEnd < EventSpaceEnd(TKikimrEvents::ES_FLAT_EXECUTOR), ""); - - struct TEvUnregister : public TEventLocal<TEvUnregister, EvUnregister> { - }; - - struct TEvInvalidate : public TEventLocal<TEvInvalidate, EvInvalidate> { + + EvEnd + + /* +1024 range is reserved for scan events */ + }; + + static_assert(EvEnd < EventSpaceEnd(TKikimrEvents::ES_FLAT_EXECUTOR), ""); + + struct TEvUnregister : public TEventLocal<TEvUnregister, EvUnregister> { + }; + + struct TEvInvalidate : public TEventLocal<TEvInvalidate, EvInvalidate> { const TLogoBlobID PageCollectionId; - + TEvInvalidate(const TLogoBlobID &pageCollectionId) : PageCollectionId(pageCollectionId) - {} - }; - - struct TEvTouch : public TEventLocal<TEvTouch, EvTouch> { + {} + }; + + struct TEvTouch : public TEventLocal<TEvTouch, EvTouch> { THashMap<TLogoBlobID, THashMap<ui32, TSharedData>> Touched; - + TEvTouch(THashMap<TLogoBlobID, THashMap<ui32, TSharedData>> &&touched) - : Touched(std::move(touched)) - {} - }; - + : Touched(std::move(touched)) + {} + }; + struct TEvAttach : public TEventLocal<TEvAttach, EvAttach> { TIntrusiveConstPtr<NPageCollection::IPageCollection> PageCollection; TActorId Owner; @@ -65,23 +65,23 @@ namespace NSharedCache { } }; - struct TEvRequest : public TEventLocal<TEvRequest, EvRequest> { + struct TEvRequest : public TEventLocal<TEvRequest, EvRequest> { const EPriority Priority; TAutoPtr<NPageCollection::TFetch> Fetch; TActorId Owner; - + TEvRequest(EPriority priority, TAutoPtr<NPageCollection::TFetch> fetch, TActorId owner) : Priority(priority) , Fetch(fetch) - , Owner(owner) - { - Y_VERIFY(Owner, "Cannot sent request with empty owner"); - } - }; - + , Owner(owner) + { + Y_VERIFY(Owner, "Cannot sent request with empty owner"); + } + }; + struct TEvResult : public TEventLocal<TEvResult, EvResult> { using EStatus = NKikimrProto::EReplyStatus; - + TEvResult(TIntrusiveConstPtr<NPageCollection::IPageCollection> origin, ui64 cookie, EStatus status) : Status(status) , Cookie(cookie) @@ -119,8 +119,8 @@ namespace NSharedCache { const ui64 Cookie; const TIntrusiveConstPtr<NPageCollection::IPageCollection> Origin; TVector<TLoaded> Loaded; - }; - + }; + struct TEvUpdated : public TEventLocal<TEvUpdated, EvUpdated> { struct TActions { THashMap<ui32, TSharedPageRef> Accepted; @@ -130,26 +130,26 @@ namespace NSharedCache { THashMap<TLogoBlobID, TActions> Actions; }; -} -} - -template<> inline +} +} + +template<> inline void Out<NKikimr::NTabletFlatExecutor::NBlockIO::EPriority>( IOutputStream& o, NKikimr::NTabletFlatExecutor::NBlockIO::EPriority value) -{ - switch (value) { +{ + switch (value) { case NKikimr::NTabletFlatExecutor::NBlockIO::EPriority::Fast: - o << "Online"; - break; + o << "Online"; + break; case NKikimr::NTabletFlatExecutor::NBlockIO::EPriority::Bkgr: - o << "AsyncLoad"; - break; + o << "AsyncLoad"; + break; case NKikimr::NTabletFlatExecutor::NBlockIO::EPriority::Bulk: - o << "Scan"; - break; - default: - o << static_cast<ui32>(value); - break; - } -} + o << "Scan"; + break; + default: + o << static_cast<ui32>(value); + break; + } +} diff --git a/ydb/core/tablet_flat/shared_sausagecache.cpp b/ydb/core/tablet_flat/shared_sausagecache.cpp index c60c30202b..42f02a5781 100644 --- a/ydb/core/tablet_flat/shared_sausagecache.cpp +++ b/ydb/core/tablet_flat/shared_sausagecache.cpp @@ -1,14 +1,14 @@ #include "shared_sausagecache.h" -#include "shared_cache_events.h" -#include "flat_bio_events.h" -#include "flat_bio_actor.h" -#include "util_fmt_logger.h" +#include "shared_cache_events.h" +#include "flat_bio_events.h" +#include "flat_bio_actor.h" +#include "util_fmt_logger.h" #include <ydb/core/util/cache_cache.h> #include <ydb/core/util/page_map.h> #include <ydb/core/base/blobstorage.h> #include <library/cpp/actors/core/hfunc.h> #include <library/cpp/containers/stack_vector/stack_vec.h> -#include <util/generic/set.h> +#include <util/generic/set.h> namespace NKikimr { @@ -42,9 +42,9 @@ static bool Satisfies(NLog::EPriority priority = NLog::PRI_DEBUG) { class TSharedPageCache : public TActor<TSharedPageCache> { TIntrusiveConstPtr<TSharedPageCacheConfig> Config; - using ELnLev = NUtil::ELnLev; + using ELnLev = NUtil::ELnLev; using TBlocks = TVector<NSharedCache::TEvResult::TLoaded>; - + enum EPageState { PageStateNo, PageStateLoaded, @@ -103,15 +103,15 @@ class TSharedPageCache : public TActor<TSharedPageCache> { }; }; - struct TRequest : public TSimpleRefCount<TRequest> { + struct TRequest : public TSimpleRefCount<TRequest> { TRequest(TIntrusiveConstPtr<NPageCollection::IPageCollection> pageCollection) : Label(pageCollection->Label()) , PageCollection(std::move(pageCollection)) - { - - } - - const TLogoBlobID Label; + { + + } + + const TLogoBlobID Label; TActorId Source; /* receiver of read results */ TActorId Owner; /* receiver of NBlockIO::TEvStat*/ NBlockIO::EPriority Priority; @@ -119,8 +119,8 @@ class TSharedPageCache : public TActor<TSharedPageCache> { ui64 EventCookie = 0; ui64 RequestCookie = 0; ui64 PendingBlocks = 0; - TBlocks ReadyBlocks; - TDeque<ui32> PagesToRequest; + TBlocks ReadyBlocks; + TDeque<ui32> PagesToRequest; }; struct TExpectant { @@ -171,37 +171,37 @@ class TSharedPageCache : public TActor<TSharedPageCache> { TControlWrapper SizeOverride; - ui64 StatBioReqs = 0; - ui64 StatHitPages = 0; - ui64 StatHitBytes = 0; - ui64 StatMissPages = 0; - ui64 StatMissBytes = 0; - + ui64 StatBioReqs = 0; + ui64 StatHitPages = 0; + ui64 StatHitBytes = 0; + ui64 StatMissPages = 0; + ui64 StatMissBytes = 0; + bool GCScheduled = false; void Registered(TActorSystem *sys, const TActorId &owner) - { - Owner = owner; - - Logger = new NUtil::TLogger(sys, NKikimrServices::TABLET_SAUSAGECACHE); + { + Owner = owner; + + Logger = new NUtil::TLogger(sys, NKikimrServices::TABLET_SAUSAGECACHE); sys->AppData<TAppData>()->Icb->RegisterSharedControl(SizeOverride, Config->CacheName + "_Size"); - } - + } + void TakePoison() - { - if (auto logl = Logger->Log(ELnLev::Info)) { - logl + { + if (auto logl = Logger->Log(ELnLev::Info)) { + logl << "Page collection cache gone, serviced " << StatBioReqs << " reqs" - << " hit {" << StatHitPages << " " << StatHitBytes << "b}" - << " miss {" << StatMissPages << " " << StatMissBytes << "b}"; - } - - if (auto owner = std::exchange(Owner, { })) - Send(owner, new TEvents::TEvGone); - - PassAway(); - } - + << " hit {" << StatHitPages << " " << StatHitBytes << "b}" + << " miss {" << StatMissPages << " " << StatMissBytes << "b}"; + } + + if (auto owner = std::exchange(Owner, { })) + Send(owner, new TEvents::TEvGone); + + PassAway(); + } + TCollection& AttachCollection(const TLogoBlobID &metaId, const NPageCollection::IPageCollection &pageCollection, const TActorId &owner) { TCollection &collection = Collections[metaId]; if (!collection.MetaId) { @@ -245,8 +245,8 @@ class TSharedPageCache : public TActor<TSharedPageCache> { TStackVec<std::pair<ui32, ui32>> pendingPages; // pageId, reqIdx ui32 pagesToLoad = 0; - - TBlocks readyBlocks; + + TBlocks readyBlocks; readyBlocks.reserve(msg->Fetch->Pages.size()); TVector<ui32> pagesToWait; if (logsat) @@ -290,7 +290,7 @@ class TSharedPageCache : public TActor<TSharedPageCache> { AddActivePage(page); [[fallthrough]]; case PageStateLoaded: - StatHitPages += 1; + StatHitPages += 1; StatHitBytes += page->Size; readyBlocks.emplace_back(pageId, TSharedPageRef::MakeUsed(page, GCList)); if (logsat) @@ -318,14 +318,14 @@ class TSharedPageCache : public TActor<TSharedPageCache> { } auto waitingRequest = MakeIntrusive<TRequest>(std::move(msg->Fetch->PageCollection)); - - waitingRequest->Source = ev->Sender; - waitingRequest->Owner = msg->Owner; + + waitingRequest->Source = ev->Sender; + waitingRequest->Owner = msg->Owner; waitingRequest->Priority = msg->Priority; - waitingRequest->EventCookie = ev->Cookie; + waitingRequest->EventCookie = ev->Cookie; waitingRequest->RequestCookie = msg->Fetch->Cookie; - waitingRequest->ReadyBlocks = std::move(readyBlocks); - + waitingRequest->ReadyBlocks = std::move(readyBlocks); + if (pendingPages) { TVector<ui32> pagesToKeep; TVector<ui32> pagesToRequest; @@ -339,12 +339,12 @@ class TSharedPageCache : public TActor<TSharedPageCache> { if (queue) { // register for loading regardless of pending state, to simplify actor deregister logic // would be filtered on actual request - auto &owner = queue->Requests[msg->Owner]; + auto &owner = queue->Requests[msg->Owner]; auto &list = owner.Index[metaId]; qpages = &list.emplace_back(); - qpages->Request = waitingRequest; + qpages->Request = waitingRequest; owner.Listed.PushBack(qpages); } @@ -358,7 +358,7 @@ class TSharedPageCache : public TActor<TSharedPageCache> { Y_VERIFY(page); if (qpages) - qpages->Request->PagesToRequest.push_back(pageId); + qpages->Request->PagesToRequest.push_back(pageId); switch (page->State) { case PageStateNo: @@ -390,13 +390,13 @@ class TSharedPageCache : public TActor<TSharedPageCache> { } } - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl << "PageCollection " << metaId << " class " << waitingRequest->Priority - << " from cache " << pagesToKeep - << " already requested " << pagesToWait - << " to request " << pagesToRequest; - } + << " from cache " << pagesToKeep + << " already requested " << pagesToWait + << " to request " << pagesToRequest; + } if (pagesToRequest) { if (queue) { @@ -411,12 +411,12 @@ class TSharedPageCache : public TActor<TSharedPageCache> { } } } else { - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl << "PageCollection " << metaId << " class " << msg->Priority << " from cache " << msg->Fetch->Pages; - } - SendReadyBlocks(*waitingRequest); + } + SendReadyBlocks(*waitingRequest); } ProcessGCList(); @@ -445,13 +445,13 @@ class TSharedPageCache : public TActor<TSharedPageCache> { ui32 nthToLoad = 0; ui64 sizeToLoad = 0; - auto &wa = *owner.Listed.Front()->Request; + auto &wa = *owner.Listed.Front()->Request; - if (wa.Source) { // is request already served? - auto *collection = Collections.FindPtr(wa.Label); + if (wa.Source) { // is request already served? + auto *collection = Collections.FindPtr(wa.Label); Y_VERIFY(collection); - for (ui32 pageId : wa.PagesToRequest) { + for (ui32 pageId : wa.PagesToRequest) { ++nthToRequest; auto* page = collection->PageMap[pageId].Get(); @@ -459,8 +459,8 @@ class TSharedPageCache : public TActor<TSharedPageCache> { continue; ++nthToLoad; - queue.InFly += page->Size; - sizeToLoad += page->Size; + queue.InFly += page->Size; + sizeToLoad += page->Size; if (queue.InFly > queue.Limit) break; } @@ -469,7 +469,7 @@ class TSharedPageCache : public TActor<TSharedPageCache> { if (nthToLoad != 0) { TVector<ui32> toLoad; toLoad.reserve(nthToLoad); - for (ui32 pageId : wa.PagesToRequest) { + for (ui32 pageId : wa.PagesToRequest) { auto* page = collection->PageMap[pageId].Get(); if (!page || page->State != PageStatePending) continue; @@ -480,12 +480,12 @@ class TSharedPageCache : public TActor<TSharedPageCache> { break; } - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl << "queue pageCollection " << wa.Label << " q: " - << (&queue == &AsyncRequests ? "async" : "scan") - << " pages " << toLoad; - } + << (&queue == &AsyncRequests ? "async" : "scan") + << " pages " << toLoad; + } // fetch cookie -> requested size; // event cookie -> ptr to queue @@ -496,9 +496,9 @@ class TSharedPageCache : public TActor<TSharedPageCache> { } // cleanup - if (!wa.Source || nthToRequest == wa.PagesToRequest.size()) { + if (!wa.Source || nthToRequest == wa.PagesToRequest.size()) { { - auto reqit = owner.Index.find(wa.Label); + auto reqit = owner.Index.find(wa.Label); Y_VERIFY(reqit != owner.Index.end()); reqit->second.pop_front(); @@ -507,13 +507,13 @@ class TSharedPageCache : public TActor<TSharedPageCache> { } Y_VERIFY(bool(owner.Listed) == bool(owner.Index)); - + if (owner.Listed.Empty()) it = queue.Requests.erase(it); else ++it; } else { - wa.PagesToRequest.erase(wa.PagesToRequest.begin(), wa.PagesToRequest.begin() + nthToRequest); + wa.PagesToRequest.erase(wa.PagesToRequest.begin(), wa.PagesToRequest.begin() + nthToRequest); ++it; } @@ -622,20 +622,20 @@ class TSharedPageCache : public TActor<TSharedPageCache> { void Handle(NSharedCache::TEvInvalidate::TPtr &ev) { const TLogoBlobID pageCollectionId = ev->Get()->PageCollectionId; auto collectionIt = Collections.find(pageCollectionId); - - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl + + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl << "invalidate pageCollection " << pageCollectionId - << (collectionIt == Collections.end() ? " unknown" : ""); + << (collectionIt == Collections.end() ? " unknown" : ""); } - if (collectionIt == Collections.end()) - return; + if (collectionIt == Collections.end()) + return; auto &collection = collectionIt->second; - + DropRequestsFor(ev->Sender, pageCollectionId); - + if (collection.Owners.erase(ev->Sender)) { auto ownerIt = CollectionsOwners.find(ev->Sender); if (ownerIt != CollectionsOwners.end() && @@ -654,7 +654,7 @@ class TSharedPageCache : public TActor<TSharedPageCache> { } void Handle(NBlockIO::TEvData::TPtr &ev) { - auto *msg = ev->Get(); + auto *msg = ev->Get(); if (TRequestQueue *queue = (TRequestQueue *)ev->Cookie) { Y_VERIFY(queue == &ScanRequests || queue == &AsyncRequests); @@ -663,18 +663,18 @@ class TSharedPageCache : public TActor<TSharedPageCache> { RequestFromQueue(*queue); } - auto collectionIt = Collections.find(msg->Origin->Label()); + auto collectionIt = Collections.find(msg->Origin->Label()); if (collectionIt == Collections.end()) return; - if (msg->Status != NKikimrProto::OK) { - DropCollection(collectionIt, msg->Status); + if (msg->Status != NKikimrProto::OK) { + DropCollection(collectionIt, msg->Status); } else { TCollection &collection = collectionIt->second; for (auto &paged : msg->Blocks) { - StatMissPages += 1; - StatMissBytes += paged.Data.size(); - + StatMissPages += 1; + StatMissBytes += paged.Data.size(); + Y_VERIFY(paged.PageId < collection.PageMap.size()); auto* page = collection.PageMap[paged.PageId].Get(); if (!page || !page->HasMissingBody()) @@ -768,7 +768,7 @@ class TSharedPageCache : public TActor<TSharedPageCache> { } } - void BodyProvided(TCollection &collection, ui32 pageId, TPage *page) { + void BodyProvided(TCollection &collection, ui32 pageId, TPage *page) { AddActivePage(page); auto expectantIt = collection.Expectants.find(pageId); if (expectantIt == collection.Expectants.end()) @@ -779,30 +779,30 @@ class TSharedPageCache : public TActor<TSharedPageCache> { Y_VERIFY(rblock.PageId == pageId); rblock.Page = TSharedPageRef::MakeUsed(page, GCList); - if (--r->PendingBlocks == 0) - SendReadyBlocks(*r); + if (--r->PendingBlocks == 0) + SendReadyBlocks(*r); } collection.Expectants.erase(expectantIt); } - void SendReadyBlocks(TRequest &wa) { + void SendReadyBlocks(TRequest &wa) { /* Do not hold my NPageCollection::IPageCollection, leave std::move(wa.PageCollection) */ - + TAutoPtr<NSharedCache::TEvResult> result = new NSharedCache::TEvResult(std::move(wa.PageCollection), wa.RequestCookie, NKikimrProto::OK); result->Loaded = std::move(wa.ReadyBlocks); - - Send(wa.Source, result.Release(), 0, wa.EventCookie); + + Send(wa.Source, result.Release(), 0, wa.EventCookie); wa.Source = TActorId(); - StatBioReqs += 1; - } - + StatBioReqs += 1; + } + void DropCollection(THashMap<TLogoBlobID, TCollection>::iterator collectionIt, NKikimrProto::EReplyStatus blobStorageError) { // decline all pending requests TCollection &collection = collectionIt->second; const TLogoBlobID &pageCollectionId = collectionIt->first; - if (auto logl = Logger->Log(ELnLev::Debug)) + if (auto logl = Logger->Log(ELnLev::Debug)) logl << "droping pageCollection " << pageCollectionId; for (auto &expe : collection.Expectants) { @@ -877,10 +877,10 @@ class TSharedPageCache : public TActor<TSharedPageCache> { } void DropRequestsFor(TActorId owner, const TLogoBlobID &metaId) { - DropFromQueue(ScanRequests, owner, metaId); - DropFromQueue(AsyncRequests, owner, metaId); - } - + DropFromQueue(ScanRequests, owner, metaId); + DropFromQueue(AsyncRequests, owner, metaId); + } + void DropFromQueue(TRequestQueue &queue, TActorId ownerId, const TLogoBlobID &metaId) { auto ownerIt = queue.Requests.find(ownerId); if (ownerIt == queue.Requests.end()) @@ -902,12 +902,12 @@ class TSharedPageCache : public TActor<TSharedPageCache> { void DropFromQueue(TRequestQueue &queue, TActorId ownerId) { auto it = queue.Requests.find(ownerId); if (it != queue.Requests.end()) { - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << " drop from queue for " << ownerId + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << " drop from queue for " << ownerId << " pageCollections " << it->second.Index.size(); - } - + } + queue.Requests.erase(it); } } diff --git a/ydb/core/tablet_flat/tablet_flat_executed.cpp b/ydb/core/tablet_flat/tablet_flat_executed.cpp index 4b3c15490c..b173db57a2 100644 --- a/ydb/core/tablet_flat/tablet_flat_executed.cpp +++ b/ydb/core/tablet_flat/tablet_flat_executed.cpp @@ -1,5 +1,5 @@ #include "tablet_flat_executed.h" -#include "flat_executor.h" +#include "flat_executor.h" #include "flat_executor_counters.h" #include <ydb/core/base/appdata.h> #include <library/cpp/monlib/service/pages/templates.h> @@ -7,16 +7,16 @@ namespace NKikimr { namespace NTabletFlatExecutor { -using IExecutor = NFlatExecutorSetup::IExecutor; - +using IExecutor = NFlatExecutorSetup::IExecutor; + TTabletExecutedFlat::TTabletExecutedFlat(TTabletStorageInfo *info, const TActorId &tablet, IMiniKQLFactory *factory) : ITablet(info, tablet) - , Factory(factory) + , Factory(factory) , Executor0(nullptr) , StartTime0(TAppData::TimeProvider->Now()) {} -IExecutor* TTabletExecutedFlat::CreateExecutor(const TActorContext &ctx) { +IExecutor* TTabletExecutedFlat::CreateExecutor(const TActorContext &ctx) { if (!Executor()) { IActor *executor = NFlatExecutorSetup::CreateExecutor(this, ctx.SelfID); const TActorId executorID = ctx.RegisterWithSameMailbox(executor); @@ -35,10 +35,10 @@ void TTabletExecutedFlat::Execute(TAutoPtr<ITransaction> transaction, const TAct } void TTabletExecutedFlat::Execute(TAutoPtr<ITransaction> transaction) { - if (transaction) + if (transaction) static_cast<TExecutor*>(Executor())->Execute(transaction, ExecutorCtx(*TlsActivationContext)); -} - +} + const NTable::TScheme& TTabletExecutedFlat::Scheme() const noexcept { return static_cast<TExecutor*>(Executor())->Scheme(); } @@ -88,9 +88,9 @@ void TTabletExecutedFlat::Handle(TEvTablet::TEvFollowerGcApplied::TPtr &ev) { Executor()->FollowerGcApplied(msg->Step, msg->FollowerSyncDelay); } -void TTabletExecutedFlat::Handle(TEvTablet::TEvUpdateConfig::TPtr &ev) { +void TTabletExecutedFlat::Handle(TEvTablet::TEvUpdateConfig::TPtr &ev) { if (Executor()) - Executor()->UpdateConfig(ev); + Executor()->UpdateConfig(ev); } void TTabletExecutedFlat::OnTabletStop(TEvTablet::TEvTabletStop::TPtr &ev, const TActorContext &ctx) { @@ -117,15 +117,15 @@ void TTabletExecutedFlat::HandleTabletDead(TEvTablet::TEvTabletDead::TPtr &ev, c } void TTabletExecutedFlat::HandleLocalMKQL(TEvTablet::TEvLocalMKQL::TPtr &ev, const TActorContext &ctx) { - Y_VERIFY(Factory, "Need IMiniKQLFactory to execute MKQL query"); - - Execute(Factory->Make(ev), ctx); + Y_VERIFY(Factory, "Need IMiniKQLFactory to execute MKQL query"); + + Execute(Factory->Make(ev), ctx); } void TTabletExecutedFlat::HandleLocalSchemeTx(TEvTablet::TEvLocalSchemeTx::TPtr &ev, const TActorContext &ctx) { - Y_VERIFY(Factory, "Need IMiniKQLFactory to execute scheme query"); - - Execute(Factory->Make(ev), ctx); + Y_VERIFY(Factory, "Need IMiniKQLFactory to execute scheme query"); + + Execute(Factory->Make(ev), ctx); } void TTabletExecutedFlat::HandleLocalReadColumns(TEvTablet::TEvLocalReadColumns::TPtr &ev, const TActorContext &ctx) { @@ -154,7 +154,7 @@ void TTabletExecutedFlat::ActivateExecutor(const TActorContext &ctx) { void TTabletExecutedFlat::Detach(const TActorContext &ctx) { Executor0 = nullptr; - ctx.Send(Tablet(), new TEvents::TEvPoison()); + ctx.Send(Tablet(), new TEvents::TEvPoison()); OnDetach(ctx); } @@ -177,10 +177,10 @@ void TTabletExecutedFlat::RenderHtmlPage(NMon::TEvRemoteHttpInfo::TPtr &ev, cons OnRenderAppHtmlPage(ev, ctx); return; } else if (path == "/executorInternals") { - Executor()->RenderHtmlPage(ev); + Executor()->RenderHtmlPage(ev); return; } else if (path == "/counters") { - Executor()->RenderHtmlCounters(ev); + Executor()->RenderHtmlCounters(ev); return; } else if (path == "/db") { Executor()->RenderHtmlDb(ev, ExecutorCtx(ctx)); @@ -236,8 +236,8 @@ void TTabletExecutedFlat::RenderHtmlPage(NMon::TEvRemoteHttpInfo::TPtr &ev, cons } } -void TTabletExecutedFlat::HandleGetCounters(TEvTablet::TEvGetCounters::TPtr &ev) { - Executor()->GetTabletCounters(ev); +void TTabletExecutedFlat::HandleGetCounters(TEvTablet::TEvGetCounters::TPtr &ev) { + Executor()->GetTabletCounters(ev); } bool TTabletExecutedFlat::HandleDefaultEvents(STFUNC_SIG) { @@ -255,8 +255,8 @@ bool TTabletExecutedFlat::HandleDefaultEvents(STFUNC_SIG) { HFunc(TEvTablet::TEvLocalMKQL, HandleLocalMKQL); HFunc(TEvTablet::TEvLocalSchemeTx, HandleLocalSchemeTx); HFunc(TEvTablet::TEvLocalReadColumns, HandleLocalReadColumns); - hFunc(TEvTablet::TEvGetCounters, HandleGetCounters); - hFunc(TEvTablet::TEvUpdateConfig, Handle); + hFunc(TEvTablet::TEvGetCounters, HandleGetCounters); + hFunc(TEvTablet::TEvUpdateConfig, Handle); HFunc(NMon::TEvRemoteHttpInfo, RenderHtmlPage); default: return false; @@ -275,7 +275,7 @@ void TTabletExecutedFlat::StateInitImpl(STFUNC_SIG) { HFunc(TEvTablet::TEvTabletStop, HandleTabletStop); HFunc(TEvTablet::TEvTabletDead, HandleTabletDead); hFunc(TEvTablet::TEvFollowerSyncComplete, Handle); - hFunc(TEvTablet::TEvUpdateConfig, Handle); + hFunc(TEvTablet::TEvUpdateConfig, Handle); HFunc(NMon::TEvRemoteHttpInfo, RenderHtmlPage); default: return Enqueue(ev, ctx); diff --git a/ydb/core/tablet_flat/tablet_flat_executed.h b/ydb/core/tablet_flat/tablet_flat_executed.h index 117d7532bb..ff4975a864 100644 --- a/ydb/core/tablet_flat/tablet_flat_executed.h +++ b/ydb/core/tablet_flat/tablet_flat_executed.h @@ -1,26 +1,26 @@ #pragma once #include "defs.h" -#include "tablet_flat_executor.h" +#include "tablet_flat_executor.h" namespace NKikimr { namespace NTabletFlatExecutor { -class TExecutor; - -struct IMiniKQLFactory { - virtual ~IMiniKQLFactory() = default; - +class TExecutor; + +struct IMiniKQLFactory { + virtual ~IMiniKQLFactory() = default; + virtual TAutoPtr<ITransaction> Make(TEvTablet::TEvLocalMKQL::TPtr&) = 0; virtual TAutoPtr<ITransaction> Make(TEvTablet::TEvLocalSchemeTx::TPtr&) = 0; virtual TAutoPtr<ITransaction> Make(TEvTablet::TEvLocalReadColumns::TPtr&) = 0; -}; - +}; + class TTabletExecutedFlat : public NFlatExecutorSetup::ITablet { protected: - using IExecutor = NFlatExecutorSetup::IExecutor; - + using IExecutor = NFlatExecutorSetup::IExecutor; + TTabletExecutedFlat(TTabletStorageInfo *info, const TActorId &tablet, IMiniKQLFactory *factory); - IExecutor* Executor() const { return Executor0; } + IExecutor* Executor() const { return Executor0; } const TInstant StartTime() const { return StartTime0; } void Execute(TAutoPtr<ITransaction> transaction, const TActorContext &ctx); @@ -51,14 +51,14 @@ protected: void Handle(TEvTablet::TEvFAuxUpdate::TPtr&); void Handle(TEvTablet::TEvFollowerGcApplied::TPtr&); void Handle(TEvTablet::TEvNewFollowerAttached::TPtr&); - void Handle(TEvTablet::TEvUpdateConfig::TPtr&); + void Handle(TEvTablet::TEvUpdateConfig::TPtr&); void HandleTabletStop(TEvTablet::TEvTabletStop::TPtr &ev, const TActorContext &ctx); void HandleTabletDead(TEvTablet::TEvTabletDead::TPtr &ev, const TActorContext &ctx); void HandleLocalMKQL(TEvTablet::TEvLocalMKQL::TPtr &ev, const TActorContext &ctx); void HandleLocalSchemeTx(TEvTablet::TEvLocalSchemeTx::TPtr &ev, const TActorContext &ctx); void HandleLocalReadColumns(TEvTablet::TEvLocalReadColumns::TPtr &ev, const TActorContext &ctx); - void HandleGetCounters(TEvTablet::TEvGetCounters::TPtr &ev); + void HandleGetCounters(TEvTablet::TEvGetCounters::TPtr &ev); STFUNC(StateInitImpl); @@ -66,7 +66,7 @@ protected: void Detach(const TActorContext &ctx) override; // executor is dead after this point bool HandleDefaultEvents(STFUNC_SIG); - virtual void RenderHtmlPage(NMon::TEvRemoteHttpInfo::TPtr&, const TActorContext &ctx); + virtual void RenderHtmlPage(NMon::TEvRemoteHttpInfo::TPtr&, const TActorContext &ctx); bool TryCaptureTxCache(ui64 size) { if (!TxCacheQuota) @@ -79,12 +79,12 @@ protected: } private: - IExecutor* CreateExecutor(const TActorContext &ctx); + IExecutor* CreateExecutor(const TActorContext &ctx); -private: +private: TAutoPtr<IMiniKQLFactory> Factory; - - IExecutor *Executor0; + + IExecutor *Executor0; TInstant StartTime0; TSharedQuotaPtr TxCacheQuota; }; diff --git a/ydb/core/tablet_flat/tablet_flat_executor.cpp b/ydb/core/tablet_flat/tablet_flat_executor.cpp index f69991ece9..34ef0916cb 100644 --- a/ydb/core/tablet_flat/tablet_flat_executor.cpp +++ b/ydb/core/tablet_flat/tablet_flat_executor.cpp @@ -26,8 +26,8 @@ namespace NFlatExecutorSetup { void ITablet::ScanComplete(NTable::EAbort status, TAutoPtr<IDestructable> prod, ui64 cookie, const TActorContext &ctx) { - Y_UNUSED(status); - Y_UNUSED(prod); + Y_UNUSED(status); + Y_UNUSED(prod); Y_UNUSED(cookie); Y_UNUSED(ctx); } diff --git a/ydb/core/tablet_flat/tablet_flat_executor.h b/ydb/core/tablet_flat/tablet_flat_executor.h index 075ebce354..697c3a2c1a 100644 --- a/ydb/core/tablet_flat/tablet_flat_executor.h +++ b/ydb/core/tablet_flat/tablet_flat_executor.h @@ -1,7 +1,7 @@ #pragma once #include "defs.h" -#include "flat_scan_iface.h" +#include "flat_scan_iface.h" #include <ydb/core/base/tablet.h> #include <ydb/core/base/blobstorage.h> @@ -14,11 +14,11 @@ namespace NKikimr { class TTabletCountersBase; -namespace NTable { - class TDatabase; +namespace NTable { + class TDatabase; class TScheme; -} - +} + namespace NTabletFlatExecutor { class TTransactionContext; @@ -55,19 +55,19 @@ public: AtomicStore(&Dropped, true); } - void Describe(IOutputStream &out) const noexcept - { - out << "Res{"; - - if (TaskId) { - out << TaskId; - } else { - out << "static"; - } - - out << " " << Size << "b}"; - } - + void Describe(IOutputStream &out) const noexcept + { + out << "Res{"; + + if (TaskId) { + out << TaskId; + } else { + out << "static"; + } + + out << " " << Size << "b}"; + } + const ui64 Size; const ui64 TaskId; @@ -88,20 +88,20 @@ public: const TIntrusivePtr<TMemoryGCToken> GCToken; }; -struct IExecuting { - /* Functionality available only in tx execution contextt */ - - virtual ~IExecuting() = default; - +struct IExecuting { + /* Functionality available only in tx execution contextt */ + + virtual ~IExecuting() = default; + virtual void MakeSnapshot(TIntrusivePtr<TTableSnapshotContext>) = 0; virtual void DropSnapshot(TIntrusivePtr<TTableSnapshotContext>) = 0; virtual void MoveSnapshot(const TTableSnapshotContext&, ui32 src, ui32 dst) = 0; - virtual void ClearSnapshot(const TTableSnapshotContext&) = 0; - virtual void LoanTable(ui32 tableId, const TString &partsInfo) = 0; // attach table parts to table (called on part destination) - virtual void CleanupLoan(const TLogoBlobID &bundleId, ui64 from) = 0; // mark loan completion (called on part source) - virtual void ConfirmLoan(const TLogoBlobID &bundleId, const TLogoBlobID &borrowId) = 0; // confirm loan update delivery (called on part destination) -}; - + virtual void ClearSnapshot(const TTableSnapshotContext&) = 0; + virtual void LoanTable(ui32 tableId, const TString &partsInfo) = 0; // attach table parts to table (called on part destination) + virtual void CleanupLoan(const TLogoBlobID &bundleId, ui64 from) = 0; // mark loan completion (called on part source) + virtual void ConfirmLoan(const TLogoBlobID &bundleId, const TLogoBlobID &borrowId) = 0; // confirm loan update delivery (called on part destination) +}; + class TTxMemoryProviderBase : TNonCopyable { public: TTxMemoryProviderBase(ui64 memoryLimit, ui64 taskId) @@ -254,18 +254,18 @@ enum class ETerminationReason { MemoryLimitExceeded = 1, }; - -class ITransaction : TNonCopyable { + +class ITransaction : TNonCopyable { public: - using TTransactionContext = NTabletFlatExecutor::TTransactionContext; - + using TTransactionContext = NTabletFlatExecutor::TTransactionContext; + ITransaction() = default; ITransaction(NLWTrace::TOrbit &&orbit) : Orbit(std::move(orbit)) { } - virtual ~ITransaction() = default; + virtual ~ITransaction() = default; /// @return true if execution complete and transaction is ready for commit virtual bool Execute(TTransactionContext &txc, const TActorContext &ctx) = 0; virtual void Complete(const TActorContext &ctx) = 0; @@ -274,18 +274,18 @@ public: } virtual void ReleaseTxData(TTxMemoryProvider &/*provider*/, const TActorContext &/*ctx*/) {} virtual TTxType GetTxType() const { return UnknownTxType; } - - virtual void Describe(IOutputStream &out) const noexcept - { + + virtual void Describe(IOutputStream &out) const noexcept + { out << TypeName(*this); - } + } public: NLWTrace::TOrbit Orbit; }; template<typename T> -class TTransactionBase : public ITransaction { +class TTransactionBase : public ITransaction { protected: typedef T TSelf; typedef TTransactionBase<TSelf> TBase; @@ -470,7 +470,7 @@ namespace NFlatExecutorSetup { TIntrusivePtr<TTabletStorageInfo> TabletInfo; }; - + //////////////////////////////////////////// // tablet -> executor struct IExecutor : TNonCopyable { @@ -496,20 +496,20 @@ namespace NFlatExecutorSetup { virtual void Execute(TAutoPtr<ITransaction> transaction, const TActorContext &ctx) = 0; - /* Make blob with data required for table bootstapping. Note: - 1. Once non-trivial blob obtained and commited in tx all of its - borrowed bundles have to be eventually released (see db). - 2. Call accepts subset range in form [from, to). - 3. [-inf, +inf), the complete set, is encoded as ({ }, { }). - 4. May return empty blob on lack of some vital pages in cache. - */ + /* Make blob with data required for table bootstapping. Note: + 1. Once non-trivial blob obtained and commited in tx all of its + borrowed bundles have to be eventually released (see db). + 2. Call accepts subset range in form [from, to). + 3. [-inf, +inf), the complete set, is encoded as ({ }, { }). + 4. May return empty blob on lack of some vital pages in cache. + */ virtual TString BorrowSnapshot(ui32 tableId, const TTableSnapshotContext&, TRawVals from, TRawVals to, ui64 loaner) const = 0; // Prepare snapshot which can later be used for scan task. - virtual ui64 MakeScanSnapshot(ui32 table) = 0; - virtual void DropScanSnapshot(ui64 snapId) = 0; + virtual ui64 MakeScanSnapshot(ui32 table) = 0; + virtual void DropScanSnapshot(ui64 snapId) = 0; virtual ui64 QueueScan(ui32 tableId, TAutoPtr<NTable::IScan> scan, ui64 cookie, const TScanOptions& options = TScanOptions()) = 0; virtual bool CancelScan(ui32 tableId, ui64 taskId) = 0; - + // edge and ts of last full compaction virtual TFinishedCompactionInfo GetFinishedCompactionInfo(ui32 tableId) const = 0; @@ -520,13 +520,13 @@ namespace NFlatExecutorSetup { virtual ui64 CompactTable(ui32 tableId) = 0; virtual bool CompactTables() = 0; - virtual void RenderHtmlPage(NMon::TEvRemoteHttpInfo::TPtr&) const = 0; - virtual void RenderHtmlCounters(NMon::TEvRemoteHttpInfo::TPtr&) const = 0; + virtual void RenderHtmlPage(NMon::TEvRemoteHttpInfo::TPtr&) const = 0; + virtual void RenderHtmlCounters(NMon::TEvRemoteHttpInfo::TPtr&) const = 0; virtual void RenderHtmlDb(NMon::TEvRemoteHttpInfo::TPtr &ev, const TActorContext &ctx) const = 0; virtual void RegisterExternalTabletCounters(TAutoPtr<TTabletCountersBase> appCounters) = 0; - virtual void GetTabletCounters(TEvTablet::TEvGetCounters::TPtr&) = 0; + virtual void GetTabletCounters(TEvTablet::TEvGetCounters::TPtr&) = 0; - virtual void UpdateConfig(TEvTablet::TEvUpdateConfig::TPtr&) = 0; + virtual void UpdateConfig(TEvTablet::TEvUpdateConfig::TPtr&) = 0; virtual void SendUserAuxUpdateToFollowers(TString upd, const TActorContext &ctx) = 0; @@ -537,12 +537,12 @@ namespace NFlatExecutorSetup { virtual void OnYellowChannels(TVector<ui32> yellowMoveChannels, TVector<ui32> yellowStopChannels) = 0; virtual const TExecutorStats& GetStats() const = 0; - virtual NMetrics::TResourceMetrics* GetResourceMetrics() const = 0; - - /* This stange looking functionallity probably should be dropped */ - - virtual float GetRejectProbability() const = 0; + virtual NMetrics::TResourceMetrics* GetResourceMetrics() const = 0; + /* This stange looking functionallity probably should be dropped */ + + virtual float GetRejectProbability() const = 0; + // Returns current database scheme (executor must be active) virtual const NTable::TScheme& Scheme() const noexcept = 0; diff --git a/ydb/core/tablet_flat/test/data/002_full_part.pages b/ydb/core/tablet_flat/test/data/002_full_part.pages Binary files differdeleted file mode 100644 index fe80e57df1..0000000000 --- a/ydb/core/tablet_flat/test/data/002_full_part.pages +++ /dev/null diff --git a/ydb/core/tablet_flat/test/data/008_basics_db.redo b/ydb/core/tablet_flat/test/data/008_basics_db.redo Binary files differdeleted file mode 100644 index f7118a82c1..0000000000 --- a/ydb/core/tablet_flat/test/data/008_basics_db.redo +++ /dev/null diff --git a/ydb/core/tablet_flat/test/libs/exec/config.h b/ydb/core/tablet_flat/test/libs/exec/config.h index 2300064d69..051f91e8dd 100644 --- a/ydb/core/tablet_flat/test/libs/exec/config.h +++ b/ydb/core/tablet_flat/test/libs/exec/config.h @@ -1,15 +1,15 @@ -#pragma once - -#include <util/system/types.h> - -namespace NKikimr { -namespace NFake { - - struct TConf { - ui64 Shared = 32 * (ui64(1) << 20); // Shared cache limit, bytes - ui64 ScanQueue = 256 * 1024; // Scan queue flight bytes - ui64 AsyncQueue = 256 * 1024; // Async queue flight bytes - }; - -} -} +#pragma once + +#include <util/system/types.h> + +namespace NKikimr { +namespace NFake { + + struct TConf { + ui64 Shared = 32 * (ui64(1) << 20); // Shared cache limit, bytes + ui64 ScanQueue = 256 * 1024; // Scan queue flight bytes + ui64 AsyncQueue = 256 * 1024; // Async queue flight bytes + }; + +} +} diff --git a/ydb/core/tablet_flat/test/libs/exec/dummy.h b/ydb/core/tablet_flat/test/libs/exec/dummy.h index 5c6e2f5b4f..f1d540c46c 100644 --- a/ydb/core/tablet_flat/test/libs/exec/dummy.h +++ b/ydb/core/tablet_flat/test/libs/exec/dummy.h @@ -1,52 +1,52 @@ -#pragma once - -#include "events.h" +#pragma once + +#include "events.h" #include <ydb/core/base/tablet_pipe.h> #include <ydb/core/tablet_flat/tablet_flat_executed.h> #include <library/cpp/actors/core/actor.h> #include <util/system/type_name.h> - -namespace NKikimr { -namespace NFake { - using TExecuted = NTabletFlatExecutor::TTabletExecutedFlat; - + +namespace NKikimr { +namespace NFake { + using TExecuted = NTabletFlatExecutor::TTabletExecutedFlat; + class TDummySnapshotContext : public NTabletFlatExecutor::TTableSnapshotContext { public: virtual NFake::TEvExecute* OnFinished() = 0; }; - class TDummy : public ::NActors::IActor, public TExecuted { - enum EState { - Boot = 1, - Work = 2, - Stop = 3, - }; - - public: + class TDummy : public ::NActors::IActor, public TExecuted { + enum EState { + Boot = 1, + Work = 2, + Stop = 3, + }; + + public: using TEventHandlePtr = TAutoPtr<::NActors::IEventHandle>; - using ELnLev = NUtil::ELnLev; - using TInfo = TTabletStorageInfo; - using TEvDead = TEvTablet::TEvTabletDead; - - enum class EFlg : ui32 { - Comp = 0x01, - }; - + using ELnLev = NUtil::ELnLev; + using TInfo = TTabletStorageInfo; + using TEvDead = TEvTablet::TEvTabletDead; + + enum class EFlg : ui32 { + Comp = 0x01, + }; + TDummy(const TActorId &tablet, TInfo *info, const TActorId& owner, - ui32 flags = 0 /* ORed EFlg enum */) + ui32 flags = 0 /* ORed EFlg enum */) : ::NActors::IActor(static_cast<TReceiveFunc>(&TDummy::Inbox), NKikimrServices::TActivity::FAKE_ENV_A) - , TTabletExecutedFlat(info, tablet, nullptr) - , Owner(owner) - , Flags(flags) - { - } - - private: + , TTabletExecutedFlat(info, tablet, nullptr) + , Owner(owner) + , Flags(flags) + { + } + + private: void Inbox(TEventHandlePtr &eh, const ::NActors::TActorContext &ctx) - { - if (auto *ev = eh->CastAsLocal<NFake::TEvExecute>()) { - Y_VERIFY(State == EState::Work, "Cannot handle TX now"); - + { + if (auto *ev = eh->CastAsLocal<NFake::TEvExecute>()) { + Y_VERIFY(State == EState::Work, "Cannot handle TX now"); + for (auto& f : ev->Funcs) { Execute(f.Release(), ctx); } @@ -59,63 +59,63 @@ namespace NFake { Executor()->CompactTable(ev->Table); } Send(Owner, new TEvents::TEvWakeup); - } else if (eh->CastAsLocal<NFake::TEvReturn>()) { - Send(Owner, new TEvents::TEvWakeup); + } else if (eh->CastAsLocal<NFake::TEvReturn>()) { + Send(Owner, new TEvents::TEvWakeup); } else if (auto *ev = eh->CastAsLocal<NFake::TEvCall>()) { ev->Callback(Executor(), ctx); - } else if (eh->CastAsLocal<TEvents::TEvPoison>()) { - if (std::exchange(State, EState::Stop) != EState::Stop) { - /* This hack stops TExecutor before TOwner death. TOwner - unbale to wait for tablet death and may yield false + } else if (eh->CastAsLocal<TEvents::TEvPoison>()) { + if (std::exchange(State, EState::Stop) != EState::Stop) { + /* This hack stops TExecutor before TOwner death. TOwner + unbale to wait for tablet death and may yield false TEvGone to leader actor on handling its own TEvPoison. - */ - - Executor()->DetachTablet(ctx), Detach(ctx); - } - } else if (State == EState::Boot) { - TTabletExecutedFlat::StateInitImpl(eh, ctx); - - } else if (eh->CastAsLocal<TEvTabletPipe::TEvServerConnected>()) { - - } else if (eh->CastAsLocal<TEvTabletPipe::TEvServerDisconnected>()){ - - } else if (!TTabletExecutedFlat::HandleDefaultEvents(eh, ctx)) { + */ + + Executor()->DetachTablet(ctx), Detach(ctx); + } + } else if (State == EState::Boot) { + TTabletExecutedFlat::StateInitImpl(eh, ctx); + + } else if (eh->CastAsLocal<TEvTabletPipe::TEvServerConnected>()) { + + } else if (eh->CastAsLocal<TEvTabletPipe::TEvServerDisconnected>()){ + + } else if (!TTabletExecutedFlat::HandleDefaultEvents(eh, ctx)) { Y_Fail("Unexpected event " << TypeName(*eh->GetBase())); - } - } - + } + } + void Enqueue(TEventHandlePtr &eh, const ::NActors::TActorContext&) override - { + { const auto *name = TypeName(*eh->GetBase()).c_str(); - - Y_FAIL("Got unexpected event %s on tablet booting", name); - } - - void OnActivateExecutor(const TActorContext&) override - { - if (std::exchange(State, EState::Work) != EState::Work) { - Send(Owner, new NFake::TEvReady(TabletID(), SelfId())); - } else { - Y_FAIL("Received unexpected TExecutor activation"); - } - } - - void OnTabletDead(TEvDead::TPtr&, const TActorContext &ctx) override - { - OnDetach(ctx); - } - - void OnDetach(const TActorContext&) override - { - PassAway(); - } - - void CompactionComplete(ui32 table, const TActorContext&) override - { - if (Flags & ui32(EFlg::Comp)) - Send(Owner, new NFake::TEvCompacted(table)); - } - + + Y_FAIL("Got unexpected event %s on tablet booting", name); + } + + void OnActivateExecutor(const TActorContext&) override + { + if (std::exchange(State, EState::Work) != EState::Work) { + Send(Owner, new NFake::TEvReady(TabletID(), SelfId())); + } else { + Y_FAIL("Received unexpected TExecutor activation"); + } + } + + void OnTabletDead(TEvDead::TPtr&, const TActorContext &ctx) override + { + OnDetach(ctx); + } + + void OnDetach(const TActorContext&) override + { + PassAway(); + } + + void CompactionComplete(ui32 table, const TActorContext&) override + { + if (Flags & ui32(EFlg::Comp)) + Send(Owner, new NFake::TEvCompacted(table)); + } + void SnapshotComplete( TIntrusivePtr<NTabletFlatExecutor::TTableSnapshotContext> rawSnapContext, const TActorContext&) override @@ -127,11 +127,11 @@ namespace NFake { } } - private: + private: TActorId Owner; - const ui32 Flags = 0; - EState State = EState::Boot; - }; - -} -} + const ui32 Flags = 0; + EState State = EState::Boot; + }; + +} +} diff --git a/ydb/core/tablet_flat/test/libs/exec/events.h b/ydb/core/tablet_flat/test/libs/exec/events.h index b6aeb3e82f..f227429ed3 100644 --- a/ydb/core/tablet_flat/test/libs/exec/events.h +++ b/ydb/core/tablet_flat/test/libs/exec/events.h @@ -1,81 +1,81 @@ -#pragma once - -#include "tablet_flat_executor.h" +#pragma once + +#include "tablet_flat_executor.h" #include <library/cpp/actors/core/events.h> #include <library/cpp/actors/core/actorsystem.h> - -namespace NKikimr { -namespace NFake { - - enum EEv { - Base_ = EventSpaceBegin(TKikimrEvents::ES_TABLET) + 2015, - - EvTerm = Base_ + 0, /* Terminates test in runtime env */ - EvGone = Base_ + 1, - EvFire = Base_ + 2, /* Start new actor under root model */ - - EvReady = Base_ + 10, - EvExecute = Base_ + 11, - EvResult = Base_ + 12, - EvReturn = Base_ + 13, - EvCompacted = Base_ + 14, + +namespace NKikimr { +namespace NFake { + + enum EEv { + Base_ = EventSpaceBegin(TKikimrEvents::ES_TABLET) + 2015, + + EvTerm = Base_ + 0, /* Terminates test in runtime env */ + EvGone = Base_ + 1, + EvFire = Base_ + 2, /* Start new actor under root model */ + + EvReady = Base_ + 10, + EvExecute = Base_ + 11, + EvResult = Base_ + 12, + EvReturn = Base_ + 13, + EvCompacted = Base_ + 14, EvCompact = Base_ + 15, EvCall = Base_ + 16, - }; - - struct TEvTerm : public TEventLocal<TEvTerm, EvTerm> { }; - - struct TEvFire : public TEventLocal<TEvFire, EvFire> { + }; + + struct TEvTerm : public TEventLocal<TEvTerm, EvTerm> { }; + + struct TEvFire : public TEventLocal<TEvFire, EvFire> { TEvFire(ui32 level, const TActorId &alias, TActorSetupCmd cmd) - : Level(level) - , Alias(alias) - , Cmd(cmd) - { - - } - - const ui32 Level = Max<ui32>(); + : Level(level) + , Alias(alias) + , Cmd(cmd) + { + + } + + const ui32 Level = Max<ui32>(); const TActorId Alias; - TActorSetupCmd Cmd; - }; - - struct TEvReady : public TEventLocal<TEvReady, EvReady> { + TActorSetupCmd Cmd; + }; + + struct TEvReady : public TEventLocal<TEvReady, EvReady> { TEvReady(ui64 tabletId, const TActorId& tabletActorID) - : TabletID(tabletId) - , ActorId(tabletActorID) - {} - ui64 TabletID; + : TabletID(tabletId) + , ActorId(tabletActorID) + {} + ui64 TabletID; TActorId ActorId; - }; - - struct TEvExecute : public TEventLocal<TEvExecute, EvExecute> { - using ITransaction = NTabletFlatExecutor::ITransaction; - + }; + + struct TEvExecute : public TEventLocal<TEvExecute, EvExecute> { + using ITransaction = NTabletFlatExecutor::ITransaction; + TEvExecute(TAutoPtr<ITransaction> func) { THolder<ITransaction> h(func.Release()); Funcs.push_back(std::move(h)); } - + TEvExecute(TVector<THolder<ITransaction>> funcs) : Funcs(std::move(funcs)) { } TVector<THolder<ITransaction>> Funcs; - }; - - struct TEvResult : public TEventLocal<TEvResult, EvResult> { - ui64 TabletID; - bool Success; - }; - - struct TEvReturn : public TEventLocal<TEvReturn, EvReturn> { }; - - struct TEvCompacted : public TEventLocal<TEvCompacted, EvCompacted> { - TEvCompacted(ui32 table) : Table(table) { } - - ui64 Table; - }; - + }; + + struct TEvResult : public TEventLocal<TEvResult, EvResult> { + ui64 TabletID; + bool Success; + }; + + struct TEvReturn : public TEventLocal<TEvReturn, EvReturn> { }; + + struct TEvCompacted : public TEventLocal<TEvCompacted, EvCompacted> { + TEvCompacted(ui32 table) : Table(table) { } + + ui64 Table; + }; + struct TEvCompact : public TEventLocal<TEvCompact, EvCompact> { TEvCompact(ui32 table, bool memOnly = false) : Table(table) @@ -95,5 +95,5 @@ namespace NFake { TCallback Callback; }; -} -} +} +} diff --git a/ydb/core/tablet_flat/test/libs/exec/fuzzy.h b/ydb/core/tablet_flat/test/libs/exec/fuzzy.h index 1523dc0b39..e1fc524eec 100644 --- a/ydb/core/tablet_flat/test/libs/exec/fuzzy.h +++ b/ydb/core/tablet_flat/test/libs/exec/fuzzy.h @@ -1,151 +1,151 @@ -#pragma once - +#pragma once + #include <ydb/core/tablet_flat/flat_dbase_scheme.h> #include <ydb/core/tablet_flat/ut/flat_test_db.h> #include <ydb/core/tablet_flat/ut/flat_test_db_helpers.h> - -namespace NKikimr { -namespace NFake { - - class TFuzzySet { - using TContext = NTabletFlatExecutor::TTransactionContext; - using ITestDb = NTable::ITestDb; - - public: - TFuzzySet(bool compress = false) : Compress(compress) { } - - void CreateTableIfNotExist(NTable::TDbWrapper &db, ui32 table) - { - const static ui32 KeyId = 2; - - if (RegisterTable(table)) { - using namespace NTable; - - NTable::TAlter delta; - - delta.SetRedo(8000 /* always put blobs below to redo log */); - delta.AddTable("test" + ToString(table), table); - delta.SetRoom(table, 0 /* default room */, 1, 3, 2); - - if (Compress) { /* setup default family for page compression */ - delta.AddFamily(table, 0, 0); - delta.SetFamily(table, 0, NPage::ECache::None, NPage::ECodec::LZ4); - } else { - delta.AddFamily(table, 0, 0); + +namespace NKikimr { +namespace NFake { + + class TFuzzySet { + using TContext = NTabletFlatExecutor::TTransactionContext; + using ITestDb = NTable::ITestDb; + + public: + TFuzzySet(bool compress = false) : Compress(compress) { } + + void CreateTableIfNotExist(NTable::TDbWrapper &db, ui32 table) + { + const static ui32 KeyId = 2; + + if (RegisterTable(table)) { + using namespace NTable; + + NTable::TAlter delta; + + delta.SetRedo(8000 /* always put blobs below to redo log */); + delta.AddTable("test" + ToString(table), table); + delta.SetRoom(table, 0 /* default room */, 1, 3, 2); + + if (Compress) { /* setup default family for page compression */ + delta.AddFamily(table, 0, 0); + delta.SetFamily(table, 0, NPage::ECache::None, NPage::ECodec::LZ4); + } else { + delta.AddFamily(table, 0, 0); delta.SetFamilyBlobs(table, 0, 6500, 7000); - } - + } + delta.AddColumn(table, "key", KeyId, NScheme::TInt64::TypeId, false); delta.AddColumn(table, "value", 200, NScheme::TString::TypeId, false); - delta.AddColumnToKey(table, KeyId); - - if (table >= 2) { /* used { 0, 1, 2, 3 } tables */ - const auto comp_g0 = NLocalDb::LegacyQueueIdToTaskName(0); - const auto comp_g1 = NLocalDb::LegacyQueueIdToTaskName(1); - - NLocalDb::TCompactionPolicy policy; - - policy.InMemSizeToSnapshot = 40 * 1024; - policy.InMemStepsToSnapshot = 100; - policy.InMemForceStepsToSnapshot = 200; - policy.InMemForceSizeToSnapshot = 640 * 1024; - policy.InMemResourceBrokerTask = comp_g0; - policy.ReadAheadHiThreshold = 100000; - policy.ReadAheadLoThreshold = 50000; - - policy.Generations = { - { 100 * 1024, 3, 3, 200 * 1024, comp_g0, true }, - { 400 * 1024, 3, 3, 800 * 1024, comp_g1, false } - }; - - delta.SetCompactionPolicy(table, policy); - } - - db.Apply(*delta.Flush()); - } - } - - bool UpdateRowTx(ITestDb &wrap, TContext&, ui32 table, ui32 key, ui32 bytes) - { - NTable::TDbWrapper db(wrap); - CreateTableIfNotExist(db, table); - db.Apply(db.Update(table).Key(key).Set("value", TString(bytes, 'b'))); - - return true; - } - - bool EraseRowTx(ITestDb &wrap, TContext&, ui32 table, ui32 key) - { - NTable::TDbWrapper db(wrap); - CreateTableIfNotExist(db, table); - db.Apply(db.Erase(table).Key(key)); - - return true; - } - - bool MutipleTablesTx(ITestDb &wrap, TContext&, ui32 table, ui32 key) - { - const ui32 other = (table + (table + key) % 3) % 4; - - NTable::TDbWrapper db(wrap); - CreateTableIfNotExist(db, table); - CreateTableIfNotExist(db, other); - - const auto size1 = 10 + RandomNumber<ui32>(9123); - const auto size2 = 10 + RandomNumber<ui32>(9123); - - db.Apply(db.Update(table).Key(key).Set("value", TString(size1, 'a'))); - db.Apply(db.Erase(other).Key(key+1)); - db.Apply(db.Update(other).Key(key+3).Set("value", TString(size2, 'a'))); - - return true; - } - - bool ReadTx(ITestDb &wrap, TContext &txc, ui32 table) - { - const auto mode = NTable::ELookup::GreaterOrEqualThan; - - if (!wrap.GetScheme().GetTableInfo(table)) - return true; - - const std::array<ui32,2> cols{{ 200, 2 }}; - - auto it = txc.DB.Iterate(table, { }, cols, mode); - + delta.AddColumnToKey(table, KeyId); + + if (table >= 2) { /* used { 0, 1, 2, 3 } tables */ + const auto comp_g0 = NLocalDb::LegacyQueueIdToTaskName(0); + const auto comp_g1 = NLocalDb::LegacyQueueIdToTaskName(1); + + NLocalDb::TCompactionPolicy policy; + + policy.InMemSizeToSnapshot = 40 * 1024; + policy.InMemStepsToSnapshot = 100; + policy.InMemForceStepsToSnapshot = 200; + policy.InMemForceSizeToSnapshot = 640 * 1024; + policy.InMemResourceBrokerTask = comp_g0; + policy.ReadAheadHiThreshold = 100000; + policy.ReadAheadLoThreshold = 50000; + + policy.Generations = { + { 100 * 1024, 3, 3, 200 * 1024, comp_g0, true }, + { 400 * 1024, 3, 3, 800 * 1024, comp_g1, false } + }; + + delta.SetCompactionPolicy(table, policy); + } + + db.Apply(*delta.Flush()); + } + } + + bool UpdateRowTx(ITestDb &wrap, TContext&, ui32 table, ui32 key, ui32 bytes) + { + NTable::TDbWrapper db(wrap); + CreateTableIfNotExist(db, table); + db.Apply(db.Update(table).Key(key).Set("value", TString(bytes, 'b'))); + + return true; + } + + bool EraseRowTx(ITestDb &wrap, TContext&, ui32 table, ui32 key) + { + NTable::TDbWrapper db(wrap); + CreateTableIfNotExist(db, table); + db.Apply(db.Erase(table).Key(key)); + + return true; + } + + bool MutipleTablesTx(ITestDb &wrap, TContext&, ui32 table, ui32 key) + { + const ui32 other = (table + (table + key) % 3) % 4; + + NTable::TDbWrapper db(wrap); + CreateTableIfNotExist(db, table); + CreateTableIfNotExist(db, other); + + const auto size1 = 10 + RandomNumber<ui32>(9123); + const auto size2 = 10 + RandomNumber<ui32>(9123); + + db.Apply(db.Update(table).Key(key).Set("value", TString(size1, 'a'))); + db.Apply(db.Erase(other).Key(key+1)); + db.Apply(db.Update(other).Key(key+3).Set("value", TString(size2, 'a'))); + + return true; + } + + bool ReadTx(ITestDb &wrap, TContext &txc, ui32 table) + { + const auto mode = NTable::ELookup::GreaterOrEqualThan; + + if (!wrap.GetScheme().GetTableInfo(table)) + return true; + + const std::array<ui32,2> cols{{ 200, 2 }}; + + auto it = txc.DB.Iterate(table, { }, cols, mode); + while (it->Next(NTable::ENext::All) == NTable::EReady::Data) { } - - return it->Last() != NTable::EReady::Page; - } - - bool DropTables(ITestDb &wrap, TContext&) - { - NTable::TAlter delta; - - for (ui32 table: xrange(8 * sizeof(ui64))) - if (Tables & (ui64(1) << table)) - delta.DropTable(table); - - Tables = 0; - - wrap.Apply(*delta.Flush()); - - return true; - } - - protected: - bool RegisterTable(ui32 table) noexcept - { - Y_VERIFY(table < 8 * sizeof(Tables)); - - auto slot = Tables | (ui64(1) << table); - - return std::exchange(Tables, slot) != slot; - } - - private: - const bool Compress = false; /* Configure page compression */ - ui64 Tables = 0; - }; - -} -} + + return it->Last() != NTable::EReady::Page; + } + + bool DropTables(ITestDb &wrap, TContext&) + { + NTable::TAlter delta; + + for (ui32 table: xrange(8 * sizeof(ui64))) + if (Tables & (ui64(1) << table)) + delta.DropTable(table); + + Tables = 0; + + wrap.Apply(*delta.Flush()); + + return true; + } + + protected: + bool RegisterTable(ui32 table) noexcept + { + Y_VERIFY(table < 8 * sizeof(Tables)); + + auto slot = Tables | (ui64(1) << table); + + return std::exchange(Tables, slot) != slot; + } + + private: + const bool Compress = false; /* Configure page compression */ + ui64 Tables = 0; + }; + +} +} diff --git a/ydb/core/tablet_flat/test/libs/exec/helper.h b/ydb/core/tablet_flat/test/libs/exec/helper.h index 09fe4e0f54..9fa62de7b6 100644 --- a/ydb/core/tablet_flat/test/libs/exec/helper.h +++ b/ydb/core/tablet_flat/test/libs/exec/helper.h @@ -1,47 +1,47 @@ -#pragma once - +#pragma once + #include <ydb/core/base/blobstorage.h> #include <ydb/core/tablet/tablet_setup.h> - -namespace NKikimr { -namespace NFake { - - using TStorageInfo = TTabletStorageInfo; - - struct TStarter { - using TMake = TTabletSetupInfo::TTabletCreationFunc; - + +namespace NKikimr { +namespace NFake { + + using TStorageInfo = TTabletStorageInfo; + + struct TStarter { + using TMake = TTabletSetupInfo::TTabletCreationFunc; + IActor* Do(TActorId user, ui32 retry, ui32 tablet, TMake make, ui32 followerId = 0) noexcept - { - const auto simple = TMailboxType::Simple; - - auto *info = MakeTabletInfo(tablet); - auto *setup = new TTabletSetupInfo(make, simple, 0, simple, 0); - + { + const auto simple = TMailboxType::Simple; + + auto *info = MakeTabletInfo(tablet); + auto *setup = new TTabletSetupInfo(make, simple, 0, simple, 0); + return new NFake::TOwner(user, retry, info, setup, followerId); - } - - static TStorageInfo* MakeTabletInfo(ui64 tablet) noexcept - { - const auto none = TErasureType::ErasureNone; - - auto *info = new TStorageInfo; - - info->TabletID = tablet; - info->TabletType = TTabletTypes::TX_DUMMY; - info->Channels.resize(4); - - for (auto num: xrange(info->Channels.size())) { - info->Channels[num].Channel = num; - info->Channels[num].Type = TBlobStorageGroupType(none); - info->Channels[num].History.resize(1); - info->Channels[num].History[0].FromGeneration = 0; - info->Channels[num].History[0].GroupID = num; - } - - return info; - } - }; - -} -} + } + + static TStorageInfo* MakeTabletInfo(ui64 tablet) noexcept + { + const auto none = TErasureType::ErasureNone; + + auto *info = new TStorageInfo; + + info->TabletID = tablet; + info->TabletType = TTabletTypes::TX_DUMMY; + info->Channels.resize(4); + + for (auto num: xrange(info->Channels.size())) { + info->Channels[num].Channel = num; + info->Channels[num].Type = TBlobStorageGroupType(none); + info->Channels[num].History.resize(1); + info->Channels[num].History[0].FromGeneration = 0; + info->Channels[num].History[0].GroupID = num; + } + + return info; + } + }; + +} +} diff --git a/ydb/core/tablet_flat/test/libs/exec/leader.h b/ydb/core/tablet_flat/test/libs/exec/leader.h index f964c4b33c..86b7172e50 100644 --- a/ydb/core/tablet_flat/test/libs/exec/leader.h +++ b/ydb/core/tablet_flat/test/libs/exec/leader.h @@ -1,187 +1,187 @@ -#pragma once - -#include "world.h" -#include "events.h" +#pragma once + +#include "world.h" +#include "events.h" #include <ydb/core/tablet_flat/util_fmt_logger.h> #include <ydb/core/tablet_flat/util_fmt_abort.h> #include <ydb/core/tablet_flat/util_fmt_desc.h> #include <ydb/core/tablet_flat/util_fmt_basic.h> #include <library/cpp/actors/core/actor.h> - -namespace NKikimr { -namespace NFake { - + +namespace NKikimr { +namespace NFake { + class TLeader: public ::NActors::IActor { - enum class EState { - Lock = 0, /* Do not start shutdown process */ - Free = 1, /* Start to shut as Head will gone */ - Shut = 2, /* In progress, waiting for EvGone */ - Gone = 8, - }; - - public: - using ELnLev = NUtil::ELnLev; - + enum class EState { + Lock = 0, /* Do not start shutdown process */ + Free = 1, /* Start to shut as Head will gone */ + Shut = 2, /* In progress, waiting for EvGone */ + Gone = 8, + }; + + public: + using ELnLev = NUtil::ELnLev; + TLeader(ui32 head, TAtomic &stopped) : ::NActors::IActor(static_cast<TReceiveFunc>(&TLeader::Inbox), NKikimrServices::TActivity::FAKE_ENV_A) - , Time(TAppData::TimeProvider.Get()) - , Edge(head) /* Live until this runlevel exists */ - , Stopped(stopped) - { - Y_VERIFY(Edge < Levels.size(), "Out of runlevels slots"); - } - - private: + , Time(TAppData::TimeProvider.Get()) + , Edge(head) /* Live until this runlevel exists */ + , Stopped(stopped) + { + Y_VERIFY(Edge < Levels.size(), "Out of runlevels slots"); + } + + private: void Registered(TActorSystem *sys, const TActorId&) override - { - Sys = sys, Start = Time->Now(); - - Logger = new NUtil::TLogger(sys, NKikimrServices::FAKE_ENV); - - /* This actor takes functions of NFake root actor that should - perform correct system shutdown on test scene completion. */ - - Sys->RegisterLocalService(TWorld::Where(EPath::Root), SelfId()); - } - + { + Sys = sys, Start = Time->Now(); + + Logger = new NUtil::TLogger(sys, NKikimrServices::FAKE_ENV); + + /* This actor takes functions of NFake root actor that should + perform correct system shutdown on test scene completion. */ + + Sys->RegisterLocalService(TWorld::Where(EPath::Root), SelfId()); + } + void Inbox(TAutoPtr<::NActors::IEventHandle> &eh, const ::NActors::TActorContext&) - { - if (auto *fire = eh->CastAsLocal<NFake::TEvFire>()) { - DoFire(fire->Level, fire->Alias, fire->Cmd); - } else if (eh->CastAsLocal<TEvents::TEvGone>()) { - HandleGone(eh->Sender); - } else if (eh->CastAsLocal<TEvents::TEvPoison>()) { - State = Max(State, EState::Free); - - DoShutDown(true); - } else if (eh->CastAsLocal<TEvents::TEvWakeup>()) { - - if (Last == TInstant::Max()) { - Wait = false; /* Do not expect more TEvGone */ - } else if (Time->Now() - Last < Delay) { - Schedule(Gran, new TEvents::TEvWakeup); - } else if (auto logl = Logger->Log(ELnLev::Abort)) { - logl - << "Model shutdown stucked at level " << Head - << ", left " << Levels.at(Head).Left << " actors" - << ", spent " << NFmt::TDelay(Time->Now() - Last); - } - - } else if (eh->CastAsLocal<NFake::TEvTerm>()) { - - } else { + { + if (auto *fire = eh->CastAsLocal<NFake::TEvFire>()) { + DoFire(fire->Level, fire->Alias, fire->Cmd); + } else if (eh->CastAsLocal<TEvents::TEvGone>()) { + HandleGone(eh->Sender); + } else if (eh->CastAsLocal<TEvents::TEvPoison>()) { + State = Max(State, EState::Free); + + DoShutDown(true); + } else if (eh->CastAsLocal<TEvents::TEvWakeup>()) { + + if (Last == TInstant::Max()) { + Wait = false; /* Do not expect more TEvGone */ + } else if (Time->Now() - Last < Delay) { + Schedule(Gran, new TEvents::TEvWakeup); + } else if (auto logl = Logger->Log(ELnLev::Abort)) { + logl + << "Model shutdown stucked at level " << Head + << ", left " << Levels.at(Head).Left << " actors" + << ", spent " << NFmt::TDelay(Time->Now() - Last); + } + + } else if (eh->CastAsLocal<NFake::TEvTerm>()) { + + } else { Y_Fail("Unexpected event " << TypeName(*eh->GetBase())); - } - } - + } + } + void HandleGone(const TActorId &actor) noexcept - { - auto it = Childs.find(actor); - - if (it != Childs.end()) { - const auto level = it->second; - - NUtil::SubSafe(Levels.at(level).Left, ui32(1)); - Childs.erase(it); - - if (level == Head && State >= EState::Free) - DoShutDown(false); - - } else if (auto logl = Logger->Log(ELnLev::Abort)) { - logl + { + auto it = Childs.find(actor); + + if (it != Childs.end()) { + const auto level = it->second; + + NUtil::SubSafe(Levels.at(level).Left, ui32(1)); + Childs.erase(it); + + if (level == Head && State >= EState::Free) + DoShutDown(false); + + } else if (auto logl = Logger->Log(ELnLev::Abort)) { + logl << "Leader got gone event from actor " << actor - << ", but it hasn't been registered in runlevels"; - } - } - + << ", but it hasn't been registered in runlevels"; + } + } + void DoFire(ui32 level, const TActorId &alias, TActorSetupCmd &cmd) - { - if (level <= Edge && Levels[level].Alive) { - auto actor = Register(cmd.Actor, cmd.MailboxType, 0); - auto result = Childs.emplace(actor, level); - - Y_VERIFY(result.second, "Cannot register same actor twice"); - - Levels[level].Left += 1, Total += 1, Head = Max(Head, level); - - if (alias) - Sys->RegisterLocalService(alias, actor); - - if (level == Edge && State == EState::Lock) - State = EState::Free; - - } else if (auto logl = Logger->Log(ELnLev::Abort)) { - logl + { + if (level <= Edge && Levels[level].Alive) { + auto actor = Register(cmd.Actor, cmd.MailboxType, 0); + auto result = Childs.emplace(actor, level); + + Y_VERIFY(result.second, "Cannot register same actor twice"); + + Levels[level].Left += 1, Total += 1, Head = Max(Head, level); + + if (alias) + Sys->RegisterLocalService(alias, actor); + + if (level == Edge && State == EState::Lock) + State = EState::Free; + + } else if (auto logl = Logger->Log(ELnLev::Abort)) { + logl << "Cannot register " << TypeName(*cmd.Actor) << " on " - << " level " << level << ", head " << Head << ".." << Edge; - } - } - - void DoShutDown(bool force) noexcept - { - force = force && (State < EState::Shut); - - if (std::exchange(State, Max(State, EState::Shut)) < EState::Shut) { - if (auto logl = Logger->Log(ELnLev::Info)) { - logl - << "Model starts " << (force ? "hard" : "soft") - << " shutdown on level " << Head << " of " << Edge - << ", left " << Childs.size() << " actors"; - } - } - - while (State != EState::Gone) { - if (Levels.at(Head).Left && !std::exchange(force, false)) { - break; - } else if (Levels.at(Head).Left == 0 && Head == 0) { - if (auto logl = Logger->Log(ELnLev::Info)) { - logl - << "Model stopped, hosted " << Total << " actors" - << ", spent " << NFmt::TDelay(Time->Now() - Start); - } - - State = EState::Gone, Last = TInstant::Max(), Stopped = 1; - - Send(SelfId(), new NFake::TEvTerm); /* stops the world */ - - } else if (std::exchange(Levels[Head].Alive, false)) { - Last = Time->Now(); - - for (auto &it : Childs) { - if (it.second == Head) { - Send(it.first, new TEvents::TEvPoison); - - if (!std::exchange(Wait, true)) - Schedule(Gran, new TEvents::TEvWakeup); - } - } - } else if (Levels[Head].Left == 0 && Head > 0) { - Head -= 1, force = true; /* Try to shutdown next level */ - } - } - } - - private: - struct TLevel { - ui32 Left = 0; - bool Alive = true; - }; - - ITimeProvider * const Time = nullptr; - TActorSystem * Sys = nullptr; - const TDuration Gran{ TDuration::Seconds(1) }; - const TDuration Delay{ TDuration::Seconds(32) }; + << " level " << level << ", head " << Head << ".." << Edge; + } + } + + void DoShutDown(bool force) noexcept + { + force = force && (State < EState::Shut); + + if (std::exchange(State, Max(State, EState::Shut)) < EState::Shut) { + if (auto logl = Logger->Log(ELnLev::Info)) { + logl + << "Model starts " << (force ? "hard" : "soft") + << " shutdown on level " << Head << " of " << Edge + << ", left " << Childs.size() << " actors"; + } + } + + while (State != EState::Gone) { + if (Levels.at(Head).Left && !std::exchange(force, false)) { + break; + } else if (Levels.at(Head).Left == 0 && Head == 0) { + if (auto logl = Logger->Log(ELnLev::Info)) { + logl + << "Model stopped, hosted " << Total << " actors" + << ", spent " << NFmt::TDelay(Time->Now() - Start); + } + + State = EState::Gone, Last = TInstant::Max(), Stopped = 1; + + Send(SelfId(), new NFake::TEvTerm); /* stops the world */ + + } else if (std::exchange(Levels[Head].Alive, false)) { + Last = Time->Now(); + + for (auto &it : Childs) { + if (it.second == Head) { + Send(it.first, new TEvents::TEvPoison); + + if (!std::exchange(Wait, true)) + Schedule(Gran, new TEvents::TEvWakeup); + } + } + } else if (Levels[Head].Left == 0 && Head > 0) { + Head -= 1, force = true; /* Try to shutdown next level */ + } + } + } + + private: + struct TLevel { + ui32 Left = 0; + bool Alive = true; + }; + + ITimeProvider * const Time = nullptr; + TActorSystem * Sys = nullptr; + const TDuration Gran{ TDuration::Seconds(1) }; + const TDuration Delay{ TDuration::Seconds(32) }; TAutoPtr<NUtil::ILogger> Logger; - EState State = EState::Lock; - bool Wait = false; - TInstant Start = TInstant::Max(); - TInstant Last = TInstant::Max(); - const ui32 Edge = Max<ui32>(); - ui32 Head = 0; - ui64 Total = 0; - TAtomic &Stopped; + EState State = EState::Lock; + bool Wait = false; + TInstant Start = TInstant::Max(); + TInstant Last = TInstant::Max(); + const ui32 Edge = Max<ui32>(); + ui32 Head = 0; + ui64 Total = 0; + TAtomic &Stopped; std::map<TActorId, ui32> Childs; - std::array<TLevel, 9> Levels; - }; -} -} + std::array<TLevel, 9> Levels; + }; +} +} diff --git a/ydb/core/tablet_flat/test/libs/exec/logger.h b/ydb/core/tablet_flat/test/libs/exec/logger.h index 471f00b844..cf79895284 100644 --- a/ydb/core/tablet_flat/test/libs/exec/logger.h +++ b/ydb/core/tablet_flat/test/libs/exec/logger.h @@ -1,145 +1,145 @@ -#pragma once - -#include "world.h" - +#pragma once + +#include "world.h" + #include <ydb/core/tablet_flat/util_basics.h> #include <ydb/core/tablet_flat/util_fmt_line.h> #include <library/cpp/actors/core/actor.h> #include <library/cpp/actors/core/log_iface.h> - -namespace NKikimr { -namespace NFake { - - struct TSink : public TAtomicRefCount<TSink> { - - using EComp = NActors::NLog::EComponent; - - TSink(TInstant start, TVector<TString> names) - : Start(start) - , Names(std::move(names)) - { - - } - + +namespace NKikimr { +namespace NFake { + + struct TSink : public TAtomicRefCount<TSink> { + + using EComp = NActors::NLog::EComponent; + + TSink(TInstant start, TVector<TString> names) + : Start(start) + , Names(std::move(names)) + { + + } + void Put(TInstant stamp, ui32 level, EComp comp, TArrayRef<const char> line) noexcept - { + { Y_VERIFY(line.size() < 8192 * 16, "Too large log line"); - - static const char scaleMajor[] = "^^*CEWNIDT."; - static const char scaleMinor[] = "0123456789."; - - ++Stats_[Min(ui32(level) >> 8, ui32(10))]; - - const auto left = (stamp - Start).SecondsFloat(); - const auto major = scaleMajor[Min(ui32(level >> 8), ui32(10))]; - const auto minor = level & 0xff; - - TString cname; - - if (ui32(comp) < Names.size() && Names[comp]) { - cname = Names[comp]; - } else { - cname = Sprintf("?COMP_%04u", comp); - } - - auto raw = Sprintf("%09.3f %c%c| %s: %.*s\n", - left, - major, - minor ? scaleMinor[Min(minor, ui32(10))] : major, - cname.data(), + + static const char scaleMajor[] = "^^*CEWNIDT."; + static const char scaleMinor[] = "0123456789."; + + ++Stats_[Min(ui32(level) >> 8, ui32(10))]; + + const auto left = (stamp - Start).SecondsFloat(); + const auto major = scaleMajor[Min(ui32(level >> 8), ui32(10))]; + const auto minor = level & 0xff; + + TString cname; + + if (ui32(comp) < Names.size() && Names[comp]) { + cname = Names[comp]; + } else { + cname = Sprintf("?COMP_%04u", comp); + } + + auto raw = Sprintf("%09.3f %c%c| %s: %.*s\n", + left, + major, + minor ? scaleMinor[Min(minor, ui32(10))] : major, + cname.data(), int(line.size()), line.data()); - - while (true) { - try { - Cerr.Write(raw.data(), raw.size()); - break; - } catch (TSystemError) { - /* interrupted syscall */ - } - } - } - - TArrayRef<const ui64> Stats() const noexcept - { - return Stats_; - } - - public: - const TInstant Start = TInstant::Max(); - const TVector<TString> Names; /* { componnet -> name } */ - - private: - std::array<ui64, 11> Stats_{ }; - }; - - - class TLogEnv : private NUtil::ILogged, public NUtil::ILogger { - public: - using EPrio = ::NActors::NLog::EPriority; - using ELnLev = NUtil::ELnLev; - + + while (true) { + try { + Cerr.Write(raw.data(), raw.size()); + break; + } catch (TSystemError) { + /* interrupted syscall */ + } + } + } + + TArrayRef<const ui64> Stats() const noexcept + { + return Stats_; + } + + public: + const TInstant Start = TInstant::Max(); + const TVector<TString> Names; /* { componnet -> name } */ + + private: + std::array<ui64, 11> Stats_{ }; + }; + + + class TLogEnv : private NUtil::ILogged, public NUtil::ILogger { + public: + using EPrio = ::NActors::NLog::EPriority; + using ELnLev = NUtil::ELnLev; + TLogEnv(ITimeProvider *time, ELnLev level,TIntrusivePtr<TSink> sink) - : Time(time) - , Level(level) - , Sink(std::move(sink)) - { - - } - + : Time(time) + , Level(level) + , Sink(std::move(sink)) + { + + } + NUtil::TLogLn Log(ELnLev prio) const noexcept override - { - return { prio <= Level ? this : nullptr, prio }; - } - - private: - void LogLn(ELnLev prio, const TString &line) const noexcept override - { - const auto comp = NKikimrServices::FAKE_ENV; - - /* Usage of time provider will be possible on complete migration - of all logging clients to provider aware code. - */ - - auto stamp = false ? Time->Now() : TInstant::Now(); - - Sink->Put(stamp, ui32(prio), comp, line); - } - - private: - ITimeProvider * const Time = nullptr; - const ELnLev Level = ELnLev::Warn; + { + return { prio <= Level ? this : nullptr, prio }; + } + + private: + void LogLn(ELnLev prio, const TString &line) const noexcept override + { + const auto comp = NKikimrServices::FAKE_ENV; + + /* Usage of time provider will be possible on complete migration + of all logging clients to provider aware code. + */ + + auto stamp = false ? Time->Now() : TInstant::Now(); + + Sink->Put(stamp, ui32(prio), comp, line); + } + + private: + ITimeProvider * const Time = nullptr; + const ELnLev Level = ELnLev::Warn; const TIntrusivePtr<TSink> Sink; - }; - - - class TLogFwd : public ::NActors::IActor { - public: + }; + + + class TLogFwd : public ::NActors::IActor { + public: using TEventHandlePtr = TAutoPtr<::NActors::IEventHandle>; - using ELnLev = NUtil::ELnLev; - + using ELnLev = NUtil::ELnLev; + TLogFwd(TIntrusivePtr<TSink> sink) : ::NActors::IActor(static_cast<TReceiveFunc>(&TLogFwd::Inbox), IActor::LOG_ACTOR) - , Sink(std::move(sink)) - { - } - - private: + , Sink(std::move(sink)) + { + } + + private: void Inbox(TEventHandlePtr &eh, const ::NActors::TActorContext&) - { - if (auto *ev = eh->CastAsLocal<NActors::NLog::TEvLog>()) { - Sink->Put(ev->Stamp, ev->Level.Raw, ev->Component, ev->Line); - - if (ev->Level.IsUrgentAbortion()) - Send(TWorld::Where(EPath::Root), new NFake::TEvTerm); - - } else { - Y_FAIL("Test runtime env logger got an unknown event"); - } - } - - private: + { + if (auto *ev = eh->CastAsLocal<NActors::NLog::TEvLog>()) { + Sink->Put(ev->Stamp, ev->Level.Raw, ev->Component, ev->Line); + + if (ev->Level.IsUrgentAbortion()) + Send(TWorld::Where(EPath::Root), new NFake::TEvTerm); + + } else { + Y_FAIL("Test runtime env logger got an unknown event"); + } + } + + private: TIntrusivePtr<TSink> Sink; - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/test/libs/exec/nanny.h b/ydb/core/tablet_flat/test/libs/exec/nanny.h index 9b00928c8e..0b3a2bd76b 100644 --- a/ydb/core/tablet_flat/test/libs/exec/nanny.h +++ b/ydb/core/tablet_flat/test/libs/exec/nanny.h @@ -1,207 +1,207 @@ -#pragma once - -#include "world.h" -#include "events.h" -#include "helper.h" +#pragma once + +#include "world.h" +#include "events.h" +#include "helper.h" #include <ydb/core/tablet_flat/util_fmt_logger.h> #include <ydb/core/tablet_flat/tablet_flat_executed.h> #include <ydb/core/tablet_flat/ut/flat_test_db.h> #include <ydb/core/tablet_flat/ut/flat_test_db_helpers.h> #include <library/cpp/actors/core/actor.h> - -namespace NKikimr { -namespace NFake { - - class TFuncTx final : public NTabletFlatExecutor::ITransaction { - public: - using TContext = NTabletFlatExecutor::TTransactionContext; - using TCall = std::function<bool(NTable::ITestDb&, TContext&)>; - + +namespace NKikimr { +namespace NFake { + + class TFuncTx final : public NTabletFlatExecutor::ITransaction { + public: + using TContext = NTabletFlatExecutor::TTransactionContext; + using TCall = std::function<bool(NTable::ITestDb&, TContext&)>; + TFuncTx(NTable::ITestDb &fake, const TActorId& owner, TCall func) - : Owner(owner) - , Func(std::move(func)) - , Fake(fake) - , Pair(Local, Fake) - { - - } - - ~TFuncTx() - { - Y_VERIFY(Completed, "Destroying incomplted transaction"); - } - - private: - bool Execute(TTransactionContext &txc, const TActorContext&) override - { - Y_VERIFY(!Completed, "TFuncTx is already completed"); - - Local.SetDb(&txc.DB); - - try { - Completed = Func(Pair, txc); - } catch (NTable::TIteratorNotReady&) { - - } - - Fake.FinishTransaction(Completed); - return Completed; - } - - void Complete(const TActorContext &ctx) override - { - Y_VERIFY(Completed, "Finalizing incomplteted transaction"); - - ctx.Send(Owner, new NFake::TEvResult); - Local.SetDb(nullptr); - } - - private: + : Owner(owner) + , Func(std::move(func)) + , Fake(fake) + , Pair(Local, Fake) + { + + } + + ~TFuncTx() + { + Y_VERIFY(Completed, "Destroying incomplted transaction"); + } + + private: + bool Execute(TTransactionContext &txc, const TActorContext&) override + { + Y_VERIFY(!Completed, "TFuncTx is already completed"); + + Local.SetDb(&txc.DB); + + try { + Completed = Func(Pair, txc); + } catch (NTable::TIteratorNotReady&) { + + } + + Fake.FinishTransaction(Completed); + return Completed; + } + + void Complete(const TActorContext &ctx) override + { + Y_VERIFY(Completed, "Finalizing incomplteted transaction"); + + ctx.Send(Owner, new NFake::TEvResult); + Local.SetDb(nullptr); + } + + private: const TActorId Owner; - TCall Func; - bool Completed = false; - NTable::ITestDb &Fake; - NTable::TFlatDbWrapper Local; - NTable::TDbPair Pair; - }; - - - class TNanny : public ::NActors::IActor { + TCall Func; + bool Completed = false; + NTable::ITestDb &Fake; + NTable::TFlatDbWrapper Local; + NTable::TDbPair Pair; + }; + + + class TNanny : public ::NActors::IActor { using TEventHandlePtr = TAutoPtr<::NActors::IEventHandle>; - - public: - - enum class EDo { - More = 1, - Born = 2, - Stop = 3, - Gone = 8, - }; - - TNanny() - : ::NActors::IActor(static_cast<TReceiveFunc>(&TNanny::Inbox)) - , Fake(NTable::CreateFakeDb()) - { - Fake->Init(NTable::TScheme()); - } - - virtual ~TNanny() = default; - - static bool CompareDbs(NTable::ITestDb &test, TFuncTx::TContext&) - { - auto &pair = dynamic_cast<NTable::TDbPair&>(test); - - bool cmpRes = pair.CompareDBs(); - UNIT_ASSERT_C(cmpRes, "Test DB differs from the reference DB!"); - return true; - } - - protected: - void QueueTx(TFuncTx::TCall func) noexcept - { - TxInFlight++; - - auto *tx = new TFuncTx(*Fake, SelfId(), func); - - Send(Tablet, new NFake::TEvExecute(tx)); - } - - private: - virtual EDo Run() = 0; - + + public: + + enum class EDo { + More = 1, + Born = 2, + Stop = 3, + Gone = 8, + }; + + TNanny() + : ::NActors::IActor(static_cast<TReceiveFunc>(&TNanny::Inbox)) + , Fake(NTable::CreateFakeDb()) + { + Fake->Init(NTable::TScheme()); + } + + virtual ~TNanny() = default; + + static bool CompareDbs(NTable::ITestDb &test, TFuncTx::TContext&) + { + auto &pair = dynamic_cast<NTable::TDbPair&>(test); + + bool cmpRes = pair.CompareDBs(); + UNIT_ASSERT_C(cmpRes, "Test DB differs from the reference DB!"); + return true; + } + + protected: + void QueueTx(TFuncTx::TCall func) noexcept + { + TxInFlight++; + + auto *tx = new TFuncTx(*Fake, SelfId(), func); + + Send(Tablet, new NFake::TEvExecute(tx)); + } + + private: + virtual EDo Run() = 0; + void Registered(TActorSystem *sys, const TActorId &owner) override - { - Logger = new NUtil::TLogger(sys, NKikimrServices::FAKE_ENV); - - Owner = owner, StartTablet(); - } - + { + Logger = new NUtil::TLogger(sys, NKikimrServices::FAKE_ENV); + + Owner = owner, StartTablet(); + } + void Inbox(TEventHandlePtr &eh, const ::NActors::TActorContext&) - { - if (auto *ev = eh->CastAsLocal<NFake::TEvResult>()) { - Handle(*ev); - } else if (auto *ev = eh->CastAsLocal<NFake::TEvReady>()) { - Handle(*ev); - } else if (eh->CastAsLocal<TEvents::TEvGone>()) { - - if (State == EDo::Born) { - StartTablet(); - } else if (State == EDo::Stop) { - DoSuicide(); - } else if (auto logl = Logger->Log(NUtil::ELnLev::Abort)) { - logl << "TNanny tablet " << MyId << " suddenly died"; - } - } else if (eh->CastAsLocal<TEvents::TEvPoison>()) { - DoSuicide(); - } else { + { + if (auto *ev = eh->CastAsLocal<NFake::TEvResult>()) { + Handle(*ev); + } else if (auto *ev = eh->CastAsLocal<NFake::TEvReady>()) { + Handle(*ev); + } else if (eh->CastAsLocal<TEvents::TEvGone>()) { + + if (State == EDo::Born) { + StartTablet(); + } else if (State == EDo::Stop) { + DoSuicide(); + } else if (auto logl = Logger->Log(NUtil::ELnLev::Abort)) { + logl << "TNanny tablet " << MyId << " suddenly died"; + } + } else if (eh->CastAsLocal<TEvents::TEvPoison>()) { + DoSuicide(); + } else { Y_Fail("Unexpected event " << TypeName(*eh->GetBase())); - } - } - - void Handle(NFake::TEvReady &ev) noexcept - { - if (std::exchange(State, EDo::More) != EDo::Born) { - Y_FAIL("Got an unexpected TEvReady{ } event"); - } else if (std::exchange(Tablet, ev.ActorId)) { - Y_FAIL("Child tablet actor is still alive"); - } else if (TxInFlight > 0) { - Y_FAIL("Just bron(rebooted) tablet has pending tx"); - } - - QueueTx(CompareDbs); - } - - void Handle(NFake::TEvResult&) noexcept - { - Y_VERIFY(TxInFlight-- > 0, "Tx counter is underflowed"); - - if (State == EDo::More) State = Run(); - - if (TxInFlight > 0) { - /* Should wait for pending tx completion before tablet kill */ - } else if (State == EDo::Born) { - Y_VERIFY(Tablet, "Tabled has been already restarted"); - - Send(std::exchange(Tablet, { }), new TEvents::TEvPoison); - } else if (State == EDo::Stop) { - Send(std::exchange(Tablet, { }), new TEvents::TEvPoison); - } else { - Y_FAIL("TNanny actor cannot progress: no tx, no EDo"); - } - } - - void StartTablet() noexcept - { - if (auto logl = Logger->Log(NUtil::ELnLev::Info)) { - logl << "TNanny initiates TDummy tablet " << MyId << " birth"; - } - + } + } + + void Handle(NFake::TEvReady &ev) noexcept + { + if (std::exchange(State, EDo::More) != EDo::Born) { + Y_FAIL("Got an unexpected TEvReady{ } event"); + } else if (std::exchange(Tablet, ev.ActorId)) { + Y_FAIL("Child tablet actor is still alive"); + } else if (TxInFlight > 0) { + Y_FAIL("Just bron(rebooted) tablet has pending tx"); + } + + QueueTx(CompareDbs); + } + + void Handle(NFake::TEvResult&) noexcept + { + Y_VERIFY(TxInFlight-- > 0, "Tx counter is underflowed"); + + if (State == EDo::More) State = Run(); + + if (TxInFlight > 0) { + /* Should wait for pending tx completion before tablet kill */ + } else if (State == EDo::Born) { + Y_VERIFY(Tablet, "Tabled has been already restarted"); + + Send(std::exchange(Tablet, { }), new TEvents::TEvPoison); + } else if (State == EDo::Stop) { + Send(std::exchange(Tablet, { }), new TEvents::TEvPoison); + } else { + Y_FAIL("TNanny actor cannot progress: no tx, no EDo"); + } + } + + void StartTablet() noexcept + { + if (auto logl = Logger->Log(NUtil::ELnLev::Info)) { + logl << "TNanny initiates TDummy tablet " << MyId << " birth"; + } + auto make = [this](const TActorId &tablet, TStorageInfo *info) { - return new NFake::TDummy(tablet, info, SelfId()); - }; - - auto *actor = TStarter().Do(SelfId(), 1, MyId, std::move(make)); - auto *event = new TEvFire{ 7, { }, { actor, EMail::Simple, 0 } }; - - Send(TWorld::Where(EPath::Root), event); - } - - void DoSuicide() noexcept - { - Send(std::exchange(Owner, { }), new TEvents::TEvGone); - State = EDo::Gone; - PassAway(); - } - - private: - const ui64 MyId = MakeTabletID(0, 0, 1); + return new NFake::TDummy(tablet, info, SelfId()); + }; + + auto *actor = TStarter().Do(SelfId(), 1, MyId, std::move(make)); + auto *event = new TEvFire{ 7, { }, { actor, EMail::Simple, 0 } }; + + Send(TWorld::Where(EPath::Root), event); + } + + void DoSuicide() noexcept + { + Send(std::exchange(Owner, { }), new TEvents::TEvGone); + State = EDo::Gone; + PassAway(); + } + + private: + const ui64 MyId = MakeTabletID(0, 0, 1); TAutoPtr<NUtil::ILogger> Logger; TActorId Owner; TActorId Tablet; - ui64 TxInFlight = 0; - EDo State = EDo::Born; + ui64 TxInFlight = 0; + EDo State = EDo::Born; TAutoPtr<NTable::ITestDb> Fake; - }; - -} -} + }; + +} +} diff --git a/ydb/core/tablet_flat/test/libs/exec/owner.h b/ydb/core/tablet_flat/test/libs/exec/owner.h index f3e3d7363c..c172da9e31 100644 --- a/ydb/core/tablet_flat/test/libs/exec/owner.h +++ b/ydb/core/tablet_flat/test/libs/exec/owner.h @@ -1,7 +1,7 @@ -#pragma once - -#include "world.h" -#include "events.h" +#pragma once + +#include "world.h" +#include "events.h" #include <util/system/type_name.h> #include <library/cpp/actors/core/actor.h> #include <ydb/core/base/appdata.h> @@ -12,119 +12,119 @@ #include <ydb/core/tablet_flat/util_fmt_logger.h> #include <ydb/core/tablet_flat/util_fmt_abort.h> #include <library/cpp/testing/unittest/registar.h> - -namespace NKikimr { -namespace NFake { - - class TOwner final : public ::NActors::IActor { - public: + +namespace NKikimr { +namespace NFake { + + class TOwner final : public ::NActors::IActor { + public: using TEventHandlePtr = TAutoPtr<::NActors::IEventHandle>; - using ELnLev = NUtil::ELnLev; - using TInfo = TTabletStorageInfo; - using TSetup = TTabletSetupInfo; - + using ELnLev = NUtil::ELnLev; + using TInfo = TTabletStorageInfo; + using TSetup = TTabletSetupInfo; + TOwner(TActorId user, ui32 limit, TIntrusivePtr<TInfo> info, TIntrusivePtr<TSetup> setup, ui32 followerId) : ::NActors::IActor(static_cast<TReceiveFunc>(&TOwner::Inbox), NKikimrServices::TActivity::FAKE_ENV_A) - , Info(std::move(info)) - , Setup(std::move(setup)) - , User(user) - , Limit(Max(ui32(1), limit)) + , Info(std::move(info)) + , Setup(std::move(setup)) + , User(user) + , Limit(Max(ui32(1), limit)) , FollowerId(followerId) - { - Y_VERIFY(TTabletTypes::TYPE_INVALID != Info->TabletType); - } - - private: + { + Y_VERIFY(TTabletTypes::TYPE_INVALID != Info->TabletType); + } + + private: void Registered(TActorSystem *sys, const TActorId &owner) override - { - Owner = owner; - Logger = new NUtil::TLogger(sys, NKikimrServices::FAKE_ENV); - - sys->Send(SelfId(), new TEvents::TEvBootstrap); - } - + { + Owner = owner; + Logger = new NUtil::TLogger(sys, NKikimrServices::FAKE_ENV); + + sys->Send(SelfId(), new TEvents::TEvBootstrap); + } + void Inbox(TEventHandlePtr &eh, const ::NActors::TActorContext &ctx) - { - if (auto *ev = eh->CastAsLocal<TEvTablet::TEvTabletDead>()) { - - if (ev->Reason != TEvTablet::TEvTabletDead::ReasonPill) { - if (auto logl = Logger->Log(ELnLev::Emerg)) { - logl - << "Tablet " << Info->TabletID << " suddenly died" - << ", " << (Alive ? "alive" : "dead") - << ", borns " << Borns << ", reason " << ev->Reason; - } - - Send(TWorld::Where(EPath::Root), new TEvents::TEvPoison); - - DoSuicide(); - - } else if (Borns >= Limit) { - DoSuicide(); - } else { - Alive = false, Agent = { }, Start(ctx); - } - - } else if (eh->CastAsLocal<TEvTablet::TEvRestored>()) { - Alive = true; - } else if (eh->CastAsLocal<TEvLocal::TEvTabletMetrics>()) { - - } else if (eh->CastAsLocal<TEvents::TEvBootstrap>()) { - Start(ctx); - } else if (eh->CastAsLocal<TEvents::TEvPoison>()) { - if (auto logl = Logger->Log(ELnLev::Debug)) - logl << "Got kill req for Tablet " << Info->TabletID; - - Send(Agent, new TEvents::TEvPoison); - } else { + { + if (auto *ev = eh->CastAsLocal<TEvTablet::TEvTabletDead>()) { + + if (ev->Reason != TEvTablet::TEvTabletDead::ReasonPill) { + if (auto logl = Logger->Log(ELnLev::Emerg)) { + logl + << "Tablet " << Info->TabletID << " suddenly died" + << ", " << (Alive ? "alive" : "dead") + << ", borns " << Borns << ", reason " << ev->Reason; + } + + Send(TWorld::Where(EPath::Root), new TEvents::TEvPoison); + + DoSuicide(); + + } else if (Borns >= Limit) { + DoSuicide(); + } else { + Alive = false, Agent = { }, Start(ctx); + } + + } else if (eh->CastAsLocal<TEvTablet::TEvRestored>()) { + Alive = true; + } else if (eh->CastAsLocal<TEvLocal::TEvTabletMetrics>()) { + + } else if (eh->CastAsLocal<TEvents::TEvBootstrap>()) { + Start(ctx); + } else if (eh->CastAsLocal<TEvents::TEvPoison>()) { + if (auto logl = Logger->Log(ELnLev::Debug)) + logl << "Got kill req for Tablet " << Info->TabletID; + + Send(Agent, new TEvents::TEvPoison); + } else { Y_Fail("Unexpected event " << TypeName(*eh->GetBase())); - } - } - - void Start(const TActorContext &ctx) noexcept - { - Y_VERIFY(!Agent, "Tablet actor is already started"); - - if (auto logl = Logger->Log(ELnLev::Debug)) { - logl - << "Starting tablet " << Info->TabletID - << ", hope " << Borns << " of " << Limit; - } - - auto &profile = AppData(ctx)->ResourceProfiles; - + } + } + + void Start(const TActorContext &ctx) noexcept + { + Y_VERIFY(!Agent, "Tablet actor is already started"); + + if (auto logl = Logger->Log(ELnLev::Debug)) { + logl + << "Starting tablet " << Info->TabletID + << ", hope " << Borns << " of " << Limit; + } + + auto &profile = AppData(ctx)->ResourceProfiles; + if (FollowerId == 0) { Agent = Setup->Tablet(Info.Get(), SelfId(), ctx, 0, profile); } else { Agent = Setup->Follower(Info.Get(), SelfId(), ctx, FollowerId, profile); } - - Y_VERIFY(Agent, "Failed to start new tablet actor"); - - Borns += 1; - } - - void DoSuicide() noexcept - { - Send(std::exchange(Owner, { }), new TEvents::TEvGone); - Send(std::exchange(User, { }), new TEvents::TEvGone); - - PassAway(); - } - - private: + + Y_VERIFY(Agent, "Failed to start new tablet actor"); + + Borns += 1; + } + + void DoSuicide() noexcept + { + Send(std::exchange(Owner, { }), new TEvents::TEvGone); + Send(std::exchange(User, { }), new TEvents::TEvGone); + + PassAway(); + } + + private: TIntrusivePtr<TInfo> Info; TIntrusivePtr<TSetup> Setup; TAutoPtr<NUtil::ILogger> Logger; - + TActorId Owner; TActorId Agent; TActorId User; - ui32 Borns = 0; - ui32 Limit = 1; + ui32 Borns = 0; + ui32 Limit = 1; const ui32 FollowerId; - bool Alive = false; - }; - -} -} + bool Alive = false; + }; + +} +} diff --git a/ydb/core/tablet_flat/test/libs/exec/runner.h b/ydb/core/tablet_flat/test/libs/exec/runner.h index 3b58ab814b..19f6d70395 100644 --- a/ydb/core/tablet_flat/test/libs/exec/runner.h +++ b/ydb/core/tablet_flat/test/libs/exec/runner.h @@ -1,226 +1,226 @@ -#pragma once - -#include "config.h" +#pragma once + +#include "config.h" #include "leader.h" -#include "owner.h" -#include "events.h" -#include "logger.h" -#include "warden.h" -#include "helper.h" - +#include "owner.h" +#include "events.h" +#include "logger.h" +#include "warden.h" +#include "helper.h" + #include <ydb/core/base/statestorage_impl.h> #include <ydb/core/base/tablet_resolver.h> #include <ydb/core/tablet/resource_broker.h> #include <ydb/core/tablet_flat/shared_sausagecache.h> #include <ydb/core/protos/services.pb.h> #include <library/cpp/time_provider/time_provider.h> - + #include <ydb/core/tablet_flat/test/libs/rows/tool.h> #include <ydb/core/testlib/actors/test_runtime.h> - -#include <util/generic/xrange.h> - -namespace NKikimr { -namespace NFake { - - struct TRunner { - using ELnLev = NUtil::ELnLev; - - TRunner() - : Time(TAppData::TimeProvider.Get()) - , NodeId(Env.GetNodeId()) - , Names(MakeComponentsNames()) - , Sink(new TSink(false ? Time->Now() : TInstant::Now(), Names)) - , Logger(new TLogEnv(Time, ELnLev::Info, Sink)) - { - if (auto logl = Logger->Log(ELnLev::Info)) { - logl << "Born at "<< TInstant::Now(); - } - - auto *logger = new NFake::TLogFwd(Sink); - + +#include <util/generic/xrange.h> + +namespace NKikimr { +namespace NFake { + + struct TRunner { + using ELnLev = NUtil::ELnLev; + + TRunner() + : Time(TAppData::TimeProvider.Get()) + , NodeId(Env.GetNodeId()) + , Names(MakeComponentsNames()) + , Sink(new TSink(false ? Time->Now() : TInstant::Now(), Names)) + , Logger(new TLogEnv(Time, ELnLev::Info, Sink)) + { + if (auto logl = Logger->Log(ELnLev::Info)) { + logl << "Born at "<< TInstant::Now(); + } + + auto *logger = new NFake::TLogFwd(Sink); + AddService(TActorId(NodeId, "logger"), logger, EMail::Simple); - - SetupStaticServices(); - - auto *types = NTable::NTest::DbgRegistry(); + + SetupStaticServices(); + + auto *types = NTable::NTest::DbgRegistry(); auto *app = new TAppData(0, 0, 0, 0, { }, types, nullptr, nullptr, nullptr); - + Env.Initialize({ app, nullptr, nullptr }); - Env.SetDispatchTimeout(DEFAULT_DISPATCH_TIMEOUT); - Env.SetLogPriority(NKikimrServices::FAKE_ENV, NActors::NLog::PRI_INFO); - + Env.SetDispatchTimeout(DEFAULT_DISPATCH_TIMEOUT); + Env.SetLogPriority(NKikimrServices::FAKE_ENV, NActors::NLog::PRI_INFO); + Leader = Env.Register(new NFake::TLeader(8, Stopped), 0); - - NFake::TConf conf; - + + NFake::TConf conf; + conf.Shared = 8 * (1 << 20); - conf.ScanQueue = 256 * 1024; - conf.AsyncQueue = 256 * 1024; - - SetupModelServices(conf); - } - - TTestActorRuntime* operator->() noexcept - { - return &Env; - } - + conf.ScanQueue = 256 * 1024; + conf.AsyncQueue = 256 * 1024; + + SetupModelServices(conf); + } + + TTestActorRuntime* operator->() noexcept + { + return &Env; + } + void FireTablet(TActorId user, ui32 tablet, TStarter::TMake make, ui32 followerId = 0) - { - const auto mbx = EMail::Simple; - + { + const auto mbx = EMail::Simple; + RunOn(7, { }, TStarter().Do(user, 1, tablet, std::move(make), followerId), mbx); - } - + } + void FireFollower(TActorId user, ui32 tablet, TStarter::TMake make, ui32 followerId) { FireTablet(user, tablet, make, followerId); } void AddService(TActorId service, IActor *actor, EMail box) - { - Env.AddLocalService(service, TActorSetupCmd(actor, box, 0), 0); - } - + { + Env.AddLocalService(service, TActorSetupCmd(actor, box, 0), 0); + } + void RunTest(TAutoPtr<IActor> actor) noexcept - { - return RunOn(8, { }, actor.Release(), EMail::Simple); - } - + { + return RunOn(8, { }, actor.Release(), EMail::Simple); + } + void RunOn(ui32 lvl, TActorId alias, IActor* actor, EMail box) - { - auto *event = new NFake::TEvFire{ lvl, alias, { actor, box, 0 } }; - + { + auto *event = new NFake::TEvFire{ lvl, alias, { actor, box, 0 } }; + Env.SingleSys()->Send(Leader, event); - } - - void Finalize() - { - /* Test scene should either get off any events in all actors - queue or send special NFake::TEvTerm in order to terminate. - On regular flow the EPath::Root actor emits this event but - on urgent error termination is performed by TLogFwd logger. - */ - - TDispatchOptions options; - options.FinalEvents.push_back({ NFake::EvTerm }); - Env.SetDispatchTimeout(TDuration::Seconds(15)); - - try { - Env.DispatchEvents(options); - } catch (TEmptyEventQueueException&) { - - } - - const auto stat = Sink->Stats(); - const bool fail = (stat[0] + stat[1] > 0) || Stopped == 0; - - if (auto logl = Logger->Log(fail ? ELnLev::Emerg : ELnLev::Info)) { - ui64 other = std::accumulate(&stat[5], stat.end(), ui64(0)); - - logl - << "Logged {Emerg " << (stat[0] + stat[1]) - << " Alert " << stat[2] << " Crit " << stat[3] - << " Error " << stat[4] << " Left " << other << "}" - << ", " << (Stopped ? "stopped" : "dangled"); - } - - UNIT_ASSERT_C(!fail, "Critical events has been logged (see ^^)"); - } - - void SetupStaticServices() - { - { - const auto replica = MakeStateStorageReplicaID(NodeId, 0, 0); - - TIntrusivePtr<TStateStorageInfo> info(new TStateStorageInfo()); - - info->StateStorageGroup = 0; + } + + void Finalize() + { + /* Test scene should either get off any events in all actors + queue or send special NFake::TEvTerm in order to terminate. + On regular flow the EPath::Root actor emits this event but + on urgent error termination is performed by TLogFwd logger. + */ + + TDispatchOptions options; + options.FinalEvents.push_back({ NFake::EvTerm }); + Env.SetDispatchTimeout(TDuration::Seconds(15)); + + try { + Env.DispatchEvents(options); + } catch (TEmptyEventQueueException&) { + + } + + const auto stat = Sink->Stats(); + const bool fail = (stat[0] + stat[1] > 0) || Stopped == 0; + + if (auto logl = Logger->Log(fail ? ELnLev::Emerg : ELnLev::Info)) { + ui64 other = std::accumulate(&stat[5], stat.end(), ui64(0)); + + logl + << "Logged {Emerg " << (stat[0] + stat[1]) + << " Alert " << stat[2] << " Crit " << stat[3] + << " Error " << stat[4] << " Left " << other << "}" + << ", " << (Stopped ? "stopped" : "dangled"); + } + + UNIT_ASSERT_C(!fail, "Critical events has been logged (see ^^)"); + } + + void SetupStaticServices() + { + { + const auto replica = MakeStateStorageReplicaID(NodeId, 0, 0); + + TIntrusivePtr<TStateStorageInfo> info(new TStateStorageInfo()); + + info->StateStorageGroup = 0; info->NToSelect = 1; info->Rings.resize(1); info->Rings[0].Replicas.push_back(replica); - - { - auto *actor = CreateStateStorageReplica(info, 0); - - AddService(replica, actor, TMailboxType::Revolving); - } - - { + + { + auto *actor = CreateStateStorageReplica(info, 0); + + AddService(replica, actor, TMailboxType::Revolving); + } + + { auto *actor = CreateStateStorageProxy(info, nullptr, nullptr); - - AddService(MakeStateStorageProxyID(0), actor, TMailboxType::Revolving); - } - } - - { /*_ Tablet resolver, need for pipes ? */ - auto *actor = CreateTabletResolver(new TTabletResolverConfig); - - AddService(MakeTabletResolverID(), actor, EMail::Revolving); - } - - { /*_ Resource broker service, used for generic scans */ - using namespace NResourceBroker; - + + AddService(MakeStateStorageProxyID(0), actor, TMailboxType::Revolving); + } + } + + { /*_ Tablet resolver, need for pipes ? */ + auto *actor = CreateTabletResolver(new TTabletResolverConfig); + + AddService(MakeTabletResolverID(), actor, EMail::Revolving); + } + + { /*_ Resource broker service, used for generic scans */ + using namespace NResourceBroker; + auto *actor = CreateResourceBrokerActor(MakeDefaultConfig(), Env.GetDynamicCounters(0)); - - AddService(MakeResourceBrokerID(), actor, EMail::Revolving); - } - } - - void SetupModelServices(NFake::TConf conf) - { - { /*_ Blob storage proxies mock factory */ - auto *actor = new NFake::TWarden(4); - - RunOn(2, MakeBlobStorageNodeWardenID(NodeId), actor, EMail::Simple); - } - + + AddService(MakeResourceBrokerID(), actor, EMail::Revolving); + } + } + + void SetupModelServices(NFake::TConf conf) + { + { /*_ Blob storage proxies mock factory */ + auto *actor = new NFake::TWarden(4); + + RunOn(2, MakeBlobStorageNodeWardenID(NodeId), actor, EMail::Simple); + } + { /*_ Shared page collection cache service, used by executor */ auto egg = MakeIntrusive<TSharedPageCacheConfig>(); - - egg->CacheConfig = new TCacheCacheConfig(conf.Shared, nullptr, nullptr, nullptr); - egg->TotalAsyncQueueInFlyLimit = conf.AsyncQueue; - egg->TotalScanQueueInFlyLimit = conf.ScanQueue; - + + egg->CacheConfig = new TCacheCacheConfig(conf.Shared, nullptr, nullptr, nullptr); + egg->TotalAsyncQueueInFlyLimit = conf.AsyncQueue; + egg->TotalScanQueueInFlyLimit = conf.ScanQueue; + auto *actor = CreateSharedPageCache(egg.Get()); - + RunOn(3, MakeSharedPageCacheId(0), actor, EMail::ReadAsFilled); - } - } - - static TVector<TString> MakeComponentsNames() noexcept - { + } + } + + static TVector<TString> MakeComponentsNames() noexcept + { const auto begin = ui32(NKikimrServices::EServiceKikimr_MIN); - const auto end = ui32(NKikimrServices::EServiceKikimr_MAX) + 1; - - Y_VERIFY(end < 8192, "Looks like there is too many services"); - - TVector<TString> names(end); - - for (auto num : xrange(begin, end)) { - auto token = NKikimrServices::EServiceKikimr(num); - - names[num] = NKikimrServices::EServiceKikimr_Name(token); - } - - return names; - } - - public: - TTestActorRuntime Env{ NActors::THeSingleSystemEnv{ } }; - - ITimeProvider * const Time = nullptr; - const ui32 NodeId = Max<ui32>(); - const TVector<TString> Names; /* { Component -> Name } */ + const auto end = ui32(NKikimrServices::EServiceKikimr_MAX) + 1; + + Y_VERIFY(end < 8192, "Looks like there is too many services"); + + TVector<TString> names(end); + + for (auto num : xrange(begin, end)) { + auto token = NKikimrServices::EServiceKikimr(num); + + names[num] = NKikimrServices::EServiceKikimr_Name(token); + } + + return names; + } + + public: + TTestActorRuntime Env{ NActors::THeSingleSystemEnv{ } }; + + ITimeProvider * const Time = nullptr; + const ui32 NodeId = Max<ui32>(); + const TVector<TString> Names; /* { Component -> Name } */ const TIntrusivePtr<TSink> Sink; const TAutoPtr<TLogEnv> Logger; - - private: + + private: TActorId Leader; - TAtomic Stopped = 0; - }; - -} -} + TAtomic Stopped = 0; + }; + +} +} diff --git a/ydb/core/tablet_flat/test/libs/exec/storage.h b/ydb/core/tablet_flat/test/libs/exec/storage.h index 76a937c4f8..397f08172b 100644 --- a/ydb/core/tablet_flat/test/libs/exec/storage.h +++ b/ydb/core/tablet_flat/test/libs/exec/storage.h @@ -1,108 +1,108 @@ -#pragma once - +#pragma once + #include <ydb/core/tablet_flat/flat_sausage_solid.h> #include <ydb/core/blobstorage/dsproxy/mock/model.h> #include <ydb/core/base/blobstorage.h> - -namespace NKikimr { -namespace NFake { - - class TStorage : public ::NActors::IActor { - public: + +namespace NKikimr { +namespace NFake { + + class TStorage : public ::NActors::IActor { + public: using TEventHandlePtr = TAutoPtr<::NActors::IEventHandle>; - using ELnLev = NUtil::ELnLev; - using NStore = TEvBlobStorage; - - TStorage(ui32 group) + using ELnLev = NUtil::ELnLev; + using NStore = TEvBlobStorage; + + TStorage(ui32 group) : ::NActors::IActor(static_cast<TReceiveFunc>(&TStorage::Inbox), NKikimrServices::TActivity::FAKE_ENV_A) - , Group(group) - , Model(new NFake::TProxyDS) - { - Y_UNUSED(Group); - } - - private: + , Group(group) + , Model(new NFake::TProxyDS) + { + Y_UNUSED(Group); + } + + private: void Registered(TActorSystem *sys, const TActorId &owner) override - { - Owner = owner; - - Logger = new NUtil::TLogger(sys, NKikimrServices::FAKE_ENV); - } - + { + Owner = owner; + + Logger = new NUtil::TLogger(sys, NKikimrServices::FAKE_ENV); + } + void Inbox(TEventHandlePtr &eh, const ::NActors::TActorContext&) - { - if (auto *ev = eh->CastAsLocal<NStore::TEvPut>()) { - - if (ev->Buffer.size() == ev->Id.BlobSize()) { - - } else if (auto logl = Logger->Log(ELnLev::Abort)) { - logl - << "DS." << Group << " got TEvPut { " << ev->Id - << " blob " << ev->Buffer.size() << "b" << "}" - << " with missmatched data size"; - } - + { + if (auto *ev = eh->CastAsLocal<NStore::TEvPut>()) { + + if (ev->Buffer.size() == ev->Id.BlobSize()) { + + } else if (auto logl = Logger->Log(ELnLev::Abort)) { + logl + << "DS." << Group << " got TEvPut { " << ev->Id + << " blob " << ev->Buffer.size() << "b" << "}" + << " with missmatched data size"; + } + ++PutItems, PutBytes += ev->Buffer.size(); - - Reply(eh, Model->Handle(ev)); - - } else if (auto *ev = eh->CastAsLocal<NStore::TEvGet>()) { - Reply(eh, Model->Handle(ev)); - } else if (auto *ev = eh->CastAsLocal<NStore::TEvBlock>()) { - Reply(eh, Model->Handle(ev)); - } else if (auto *ev = eh->CastAsLocal<NStore::TEvDiscover>()) { - Reply(eh, Model->Handle(ev)); - } else if (auto *ev = eh->CastAsLocal<NStore::TEvRange>()) { - Reply(eh, Model->Handle(ev)); - } else if (auto *ev = eh->CastAsLocal<NStore::TEvCollectGarbage>()) { - Reply(eh, Model->Handle(ev)); - } else if (eh->CastAsLocal<NStore::TEvStatus>()) { - auto flg = Model->GetStorageStatusFlags(); - - Reply(eh, new NStore::TEvStatusResult(NKikimrProto::OK, flg)); - - } else if (eh->CastAsLocal<TEvents::TEvPoison>()) { - ReportUsage(); - - Send(std::exchange(Owner, { }), new TEvents::TEvGone, 0, Group); - - PassAway(); - } else { - Y_FAIL("DS proxy model got an unexpected event"); - } - } - + + Reply(eh, Model->Handle(ev)); + + } else if (auto *ev = eh->CastAsLocal<NStore::TEvGet>()) { + Reply(eh, Model->Handle(ev)); + } else if (auto *ev = eh->CastAsLocal<NStore::TEvBlock>()) { + Reply(eh, Model->Handle(ev)); + } else if (auto *ev = eh->CastAsLocal<NStore::TEvDiscover>()) { + Reply(eh, Model->Handle(ev)); + } else if (auto *ev = eh->CastAsLocal<NStore::TEvRange>()) { + Reply(eh, Model->Handle(ev)); + } else if (auto *ev = eh->CastAsLocal<NStore::TEvCollectGarbage>()) { + Reply(eh, Model->Handle(ev)); + } else if (eh->CastAsLocal<NStore::TEvStatus>()) { + auto flg = Model->GetStorageStatusFlags(); + + Reply(eh, new NStore::TEvStatusResult(NKikimrProto::OK, flg)); + + } else if (eh->CastAsLocal<TEvents::TEvPoison>()) { + ReportUsage(); + + Send(std::exchange(Owner, { }), new TEvents::TEvGone, 0, Group); + + PassAway(); + } else { + Y_FAIL("DS proxy model got an unexpected event"); + } + } + void Reply(TEventHandlePtr &eh, IEventBase *ev) - { - Send(eh->Sender, ev, 0, eh->Cookie); - } - - void ReportUsage() const noexcept - { - if (auto logl = Logger->Log(ELnLev::Info)) { - - auto &blobs = Model->AllMyBlobs(); - size_t bytes = 0; - - for (auto &one: blobs) bytes += one.first.BlobSize(); - - logl - << "DS." << Group << " gone" - << ", left {" << bytes << "b, " << blobs.size() << "}" - << ", put {" << PutBytes << "b, " << PutItems << "}"; - } - } - - private: + { + Send(eh->Sender, ev, 0, eh->Cookie); + } + + void ReportUsage() const noexcept + { + if (auto logl = Logger->Log(ELnLev::Info)) { + + auto &blobs = Model->AllMyBlobs(); + size_t bytes = 0; + + for (auto &one: blobs) bytes += one.first.BlobSize(); + + logl + << "DS." << Group << " gone" + << ", left {" << bytes << "b, " << blobs.size() << "}" + << ", put {" << PutBytes << "b, " << PutItems << "}"; + } + } + + private: const ui32 Group = NPageCollection::TLargeGlobId::InvalidGroup; - + TActorId Owner; TAutoPtr<NUtil::ILogger> Logger; - TAutoPtr<NFake::TProxyDS> Model; - - ui64 PutItems = 0; - ui64 PutBytes = 0; - }; - -} -} + TAutoPtr<NFake::TProxyDS> Model; + + ui64 PutItems = 0; + ui64 PutBytes = 0; + }; + +} +} diff --git a/ydb/core/tablet_flat/test/libs/exec/warden.h b/ydb/core/tablet_flat/test/libs/exec/warden.h index cc2afbde88..f0b7030a80 100644 --- a/ydb/core/tablet_flat/test/libs/exec/warden.h +++ b/ydb/core/tablet_flat/test/libs/exec/warden.h @@ -1,168 +1,168 @@ -#pragma once - -#include "world.h" -#include "storage.h" +#pragma once + +#include "world.h" +#include "storage.h" #include <library/cpp/actors/core/actor.h> #include <ydb/core/base/blobstorage.h> #include <ydb/core/protos/services.pb.h> #include <ydb/core/tablet_flat/util_fmt_logger.h> #include <util/system/type_name.h> - -#include <array> - -namespace NKikimr { -namespace NFake { - - class TWarden : public ::NActors::IActor { - - enum class EState : ui8 { - Forbid = 0, - Allow = 1, - Fired = 2, - Shut = 3, - Gone = 8, - }; - - public: + +#include <array> + +namespace NKikimr { +namespace NFake { + + class TWarden : public ::NActors::IActor { + + enum class EState : ui8 { + Forbid = 0, + Allow = 1, + Fired = 2, + Shut = 3, + Gone = 8, + }; + + public: using TEventHandlePtr = TAutoPtr<::NActors::IEventHandle>; - using ELnLev = NUtil::ELnLev; - - TWarden(ui32 groups) + using ELnLev = NUtil::ELnLev; + + TWarden(ui32 groups) : ::NActors::IActor(static_cast<TReceiveFunc>(&TWarden::Inbox), NKikimrServices::TActivity::FAKE_ENV_A) - { - Y_VERIFY(groups < State.size(), "Too many groups requested"); - - for (auto group: xrange(groups)) - State[group] = EState::Allow; - } - - private: + { + Y_VERIFY(groups < State.size(), "Too many groups requested"); + + for (auto group: xrange(groups)) + State[group] = EState::Allow; + } + + private: void Registered(TActorSystem *sys, const TActorId &owner) override - { - Sys = sys, Owner = owner; - - Logger = new NUtil::TLogger(sys, NKikimrServices::FAKE_ENV); - } - + { + Sys = sys, Owner = owner; + + Logger = new NUtil::TLogger(sys, NKikimrServices::FAKE_ENV); + } + void Inbox(TEventHandlePtr &eh, const ::NActors::TActorContext&) - { - if (ShouldForward(eh->GetTypeRewrite())) { - auto proxy = eh.Get()->GetForwardOnNondeliveryRecipient(); - auto group = GroupIDFromBlobStorageProxyID(proxy); - - if (group >= State.size() || State[group] == EState::Forbid) { - if (auto logl = Logger->Log(ELnLev::Abort)) { - logl - << "BS group " << group << " is not configured" + { + if (ShouldForward(eh->GetTypeRewrite())) { + auto proxy = eh.Get()->GetForwardOnNondeliveryRecipient(); + auto group = GroupIDFromBlobStorageProxyID(proxy); + + if (group >= State.size() || State[group] == EState::Forbid) { + if (auto logl = Logger->Log(ELnLev::Abort)) { + logl + << "BS group " << group << " is not configured" << ", ev " << TypeName(*eh->GetBase()); - } - - return; /* cannot process unknown groups */ - - } else if (State[group] == EState::Allow) { - State[group] = EState::Fired; - - Y_VERIFY(++Alive <= State.size(), "Out of group states"); - - StartGroup(group); - - } else if (State[group] >= EState::Shut) { - if (auto logl = Logger->Log(ELnLev::Crit)) { - logl - << "BS group " << group << " is unavailable" + } + + return; /* cannot process unknown groups */ + + } else if (State[group] == EState::Allow) { + State[group] = EState::Fired; + + Y_VERIFY(++Alive <= State.size(), "Out of group states"); + + StartGroup(group); + + } else if (State[group] >= EState::Shut) { + if (auto logl = Logger->Log(ELnLev::Crit)) { + logl + << "BS group " << group << " is unavailable" << ", ev " << TypeName(*eh->GetBase()); - } - - auto why = TEvents::TEvUndelivered::ReasonActorUnknown; - - TlsActivationContext->Send(eh->ForwardOnNondelivery(why)); - - return; - } - - TlsActivationContext->Send(eh->Forward(proxy)); - - } else if (eh->CastAsLocal<TEvents::TEvPoison>()) { - if (std::exchange(Shutting, true)) { - Y_FAIL("Got double BS storage shut order"); - } else if (auto logl = Logger->Log(ELnLev::Info)) - logl << "Shut order, stopping " << Alive << " BS groups"; - - for (auto group: xrange(State.size())) { - if (State[group] == EState::Fired) { - auto to = MakeBlobStorageProxyID(group); - - Send(to, new TEvents::TEvPoison); - - State[group] = EState::Shut; - } else { - State[group] = EState::Gone; - } - } - - TryToDie(); - - } else if (eh->CastAsLocal<TEvents::TEvGone>()) { - const auto group = eh->Cookie; - - if (group >= State.size() || State[group] < EState::Fired) { - Y_FAIL("Got an TEvGone event form unknown BS group"); - } else if (!Shutting || State[group] != EState::Shut) { - Y_FAIL("Got unexpected TEvGone from BS group mock"); - } - - --Alive, State[group] = EState::Gone; - - TryToDie(); - - } else if (eh->CastAsLocal<NFake::TEvTerm>()) { - - } else { - Y_FAIL("Got unexpected message"); - } - } - - void StartGroup(ui32 group) noexcept - { - if (auto logl = Logger->Log(ELnLev::Info)) - logl << "Starting storage for BS group " << group; - - auto actor = Register(new NFake::TStorage(group)); - - Sys->RegisterLocalService(MakeBlobStorageProxyID(group), actor); - } - - void TryToDie() noexcept - { - if (Shutting && Alive == 0) { - if (auto logl = Logger->Log(ELnLev::Info)) - logl << "All BS storage groups are stopped"; - - Send(Owner, new TEvents::TEvGone); - PassAway(); - } - } - - static constexpr bool ShouldForward(ui32 ev) noexcept - { - return - ev == TEvBlobStorage::EvPut - || ev == TEvBlobStorage::EvGet - || ev == TEvBlobStorage::EvBlock - || ev == TEvBlobStorage::EvDiscover - || ev == TEvBlobStorage::EvRange - || ev == TEvBlobStorage::EvCollectGarbage - || ev == TEvBlobStorage::EvStatus; - } - - public: - TActorSystem * Sys = nullptr; + } + + auto why = TEvents::TEvUndelivered::ReasonActorUnknown; + + TlsActivationContext->Send(eh->ForwardOnNondelivery(why)); + + return; + } + + TlsActivationContext->Send(eh->Forward(proxy)); + + } else if (eh->CastAsLocal<TEvents::TEvPoison>()) { + if (std::exchange(Shutting, true)) { + Y_FAIL("Got double BS storage shut order"); + } else if (auto logl = Logger->Log(ELnLev::Info)) + logl << "Shut order, stopping " << Alive << " BS groups"; + + for (auto group: xrange(State.size())) { + if (State[group] == EState::Fired) { + auto to = MakeBlobStorageProxyID(group); + + Send(to, new TEvents::TEvPoison); + + State[group] = EState::Shut; + } else { + State[group] = EState::Gone; + } + } + + TryToDie(); + + } else if (eh->CastAsLocal<TEvents::TEvGone>()) { + const auto group = eh->Cookie; + + if (group >= State.size() || State[group] < EState::Fired) { + Y_FAIL("Got an TEvGone event form unknown BS group"); + } else if (!Shutting || State[group] != EState::Shut) { + Y_FAIL("Got unexpected TEvGone from BS group mock"); + } + + --Alive, State[group] = EState::Gone; + + TryToDie(); + + } else if (eh->CastAsLocal<NFake::TEvTerm>()) { + + } else { + Y_FAIL("Got unexpected message"); + } + } + + void StartGroup(ui32 group) noexcept + { + if (auto logl = Logger->Log(ELnLev::Info)) + logl << "Starting storage for BS group " << group; + + auto actor = Register(new NFake::TStorage(group)); + + Sys->RegisterLocalService(MakeBlobStorageProxyID(group), actor); + } + + void TryToDie() noexcept + { + if (Shutting && Alive == 0) { + if (auto logl = Logger->Log(ELnLev::Info)) + logl << "All BS storage groups are stopped"; + + Send(Owner, new TEvents::TEvGone); + PassAway(); + } + } + + static constexpr bool ShouldForward(ui32 ev) noexcept + { + return + ev == TEvBlobStorage::EvPut + || ev == TEvBlobStorage::EvGet + || ev == TEvBlobStorage::EvBlock + || ev == TEvBlobStorage::EvDiscover + || ev == TEvBlobStorage::EvRange + || ev == TEvBlobStorage::EvCollectGarbage + || ev == TEvBlobStorage::EvStatus; + } + + public: + TActorSystem * Sys = nullptr; TAutoPtr<NUtil::ILogger> Logger; TActorId Owner; /* ActorID of the leader proceess */ - ui32 Alive = 0; /* Groups in EState::{Fired,Shut} */ - bool Shutting = false; /* Storages is being in shutted */ - std::array<EState, 32> State{ }; - }; - -} -} + ui32 Alive = 0; /* Groups in EState::{Fired,Shut} */ + bool Shutting = false; /* Storages is being in shutted */ + std::array<EState, 32> State{ }; + }; + +} +} diff --git a/ydb/core/tablet_flat/test/libs/exec/world.h b/ydb/core/tablet_flat/test/libs/exec/world.h index 576ff162f2..7b927a4929 100644 --- a/ydb/core/tablet_flat/test/libs/exec/world.h +++ b/ydb/core/tablet_flat/test/libs/exec/world.h @@ -1,30 +1,30 @@ -#pragma once - +#pragma once + #include <library/cpp/actors/core/actorid.h> -#include <util/system/types.h> -#include <array> - -namespace NKikimr { -namespace NFake { - - using EMail = NActors::TMailboxType::EType; - - enum class EPath : ui16 { +#include <util/system/types.h> +#include <array> + +namespace NKikimr { +namespace NFake { + + using EMail = NActors::TMailboxType::EType; + + enum class EPath : ui16 { Root = 0, /* The leader actor, shuts the system */ - }; - - struct TWorld { - + }; + + struct TWorld { + static NActors::TActorId Where(EPath path) noexcept - { - std::array<char,13> token{ "NFakeWorld??" }; - - token[10] = 0xff & ui16(path); - token[11] = 0xff & (ui16(path) >> 8); - + { + std::array<char,13> token{ "NFakeWorld??" }; + + token[10] = 0xff & ui16(path); + token[11] = 0xff & (ui16(path) >> 8); + return NActors::TActorId(0, TStringBuf(token.begin(), 12)); - } - }; - -} -} + } + }; + +} +} diff --git a/ydb/core/tablet_flat/test/libs/exec/ya.make b/ydb/core/tablet_flat/test/libs/exec/ya.make index 7557219985..6d50db83aa 100644 --- a/ydb/core/tablet_flat/test/libs/exec/ya.make +++ b/ydb/core/tablet_flat/test/libs/exec/ya.make @@ -1,14 +1,14 @@ -LIBRARY() - +LIBRARY() + OWNER(g:kikimr) - + SRCS() - -PEERDIR( + +PEERDIR( ydb/core/base ydb/core/blobstorage/dsproxy/mock ydb/core/tablet_flat ydb/core/testlib/actors -) - -END() +) + +END() diff --git a/ydb/core/tablet_flat/test/libs/rows/all.cpp b/ydb/core/tablet_flat/test/libs/rows/all.cpp index 796b82e003..abdf6c36d5 100644 --- a/ydb/core/tablet_flat/test/libs/rows/all.cpp +++ b/ydb/core/tablet_flat/test/libs/rows/all.cpp @@ -1,27 +1,27 @@ -#include "tool.h" -#include "cook.h" -#include "mass.h" - +#include "tool.h" +#include "cook.h" +#include "mass.h" + #include <ydb/core/tablet_flat/flat_row_scheme.h> #include <ydb/core/tablet_flat/flat_row_misc.h> #include <ydb/core/scheme/scheme_type_registry.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - -NScheme::TKikimrTypeRegistry TypeRegistry; - -const NScheme::TTypeRegistry* DbgRegistry() -{ - return &TypeRegistry; -} - -TString PrintValue(const TCell& r, NScheme::TTypeId typeId) -{ - return DbgPrintCell(r, typeId, TypeRegistry); -} - -} -} -} + +namespace NKikimr { +namespace NTable { +namespace NTest { + +NScheme::TKikimrTypeRegistry TypeRegistry; + +const NScheme::TTypeRegistry* DbgRegistry() +{ + return &TypeRegistry; +} + +TString PrintValue(const TCell& r, NScheme::TTypeId typeId) +{ + return DbgPrintCell(r, typeId, TypeRegistry); +} + +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/rows/cook.h b/ydb/core/tablet_flat/test/libs/rows/cook.h index a6fb2b4808..f216c31774 100644 --- a/ydb/core/tablet_flat/test/libs/rows/cook.h +++ b/ydb/core/tablet_flat/test/libs/rows/cook.h @@ -1,81 +1,81 @@ -#pragma once - -#include "rows.h" -#include "tails.h" - +#pragma once + +#include "rows.h" +#include "tails.h" + #include <ydb/core/tablet_flat/flat_row_scheme.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - - struct TCookRow { - TCookRow() = default; - TCookRow(const TCookRow&) = delete; - - ~TCookRow() - { - Y_VERIFY(!*row, "Cooked row hasn't been grabbed to TRow"); - } - - template<typename ...TArgs> - inline TCookRow& Do(NTable::TTag tag, TArgs&& ...args) - { - return row.Do(tag, std::forward<TArgs>(args)...), *this; - } - - TRow operator *() noexcept - { - return std::move(row); - } - - private: - TRow row; - }; - - class TNatural { - public: - TNatural(const TRowScheme &scheme, TPos skip = 0) - : On(skip), Scheme(scheme) { } - - inline TRow operator*() noexcept - { - return std::move(Row); - } - - TNatural& To(TPos to) noexcept - { - if(to < On || to >= Scheme.Cols.size()) { - - Y_FAIL("TNatural row builder skip position is out of range"); - } - - return On = to, *this; - } - - template<typename TVal, typename ...TArgs> - inline TNatural& Col(const TVal &val, TArgs&&...args) - { - if (On >= Scheme.Cols.size()) { - Y_FAIL("NO more columns left in row scheme"); - } else { - Row.Do(Scheme.Cols[On++].Tag, val); - - Col(std::forward<TArgs>(args)...); - } - - return *this; - } - - private: - inline void Col() { /* just stub for args expansion */ } - - private: - TPos On = 0; - TRow Row; - const TRowScheme &Scheme; - }; - -} -} -} + +namespace NKikimr { +namespace NTable { +namespace NTest { + + struct TCookRow { + TCookRow() = default; + TCookRow(const TCookRow&) = delete; + + ~TCookRow() + { + Y_VERIFY(!*row, "Cooked row hasn't been grabbed to TRow"); + } + + template<typename ...TArgs> + inline TCookRow& Do(NTable::TTag tag, TArgs&& ...args) + { + return row.Do(tag, std::forward<TArgs>(args)...), *this; + } + + TRow operator *() noexcept + { + return std::move(row); + } + + private: + TRow row; + }; + + class TNatural { + public: + TNatural(const TRowScheme &scheme, TPos skip = 0) + : On(skip), Scheme(scheme) { } + + inline TRow operator*() noexcept + { + return std::move(Row); + } + + TNatural& To(TPos to) noexcept + { + if(to < On || to >= Scheme.Cols.size()) { + + Y_FAIL("TNatural row builder skip position is out of range"); + } + + return On = to, *this; + } + + template<typename TVal, typename ...TArgs> + inline TNatural& Col(const TVal &val, TArgs&&...args) + { + if (On >= Scheme.Cols.size()) { + Y_FAIL("NO more columns left in row scheme"); + } else { + Row.Do(Scheme.Cols[On++].Tag, val); + + Col(std::forward<TArgs>(args)...); + } + + return *this; + } + + private: + inline void Col() { /* just stub for args expansion */ } + + private: + TPos On = 0; + TRow Row; + const TRowScheme &Scheme; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/rows/heap.h b/ydb/core/tablet_flat/test/libs/rows/heap.h index c50decaa2d..2b794644b7 100644 --- a/ydb/core/tablet_flat/test/libs/rows/heap.h +++ b/ydb/core/tablet_flat/test/libs/rows/heap.h @@ -1,87 +1,87 @@ -#pragma once - -#include "rows.h" - +#pragma once + +#include "rows.h" + #include <util/generic/deque.h> -namespace NKikimr { -namespace NTable { -namespace NTest { - - class TRowsHeap { - public: - using TIter = TDeque<TRow>::const_iterator; - - template<typename Fn, typename ...TArgs> - TRowsHeap(size_t heap, Fn fn, size_t num, TArgs&& ... args) - : TRowsHeap(heap) - { - for (size_t it = 0; it < num; it++) { - Put(fn(it, std::forward<TArgs>(args)...)); - } - } - - TRowsHeap(size_t heap) : Heap(new TGrowHeap(heap)) { } - +namespace NKikimr { +namespace NTable { +namespace NTest { + + class TRowsHeap { + public: + using TIter = TDeque<TRow>::const_iterator; + + template<typename Fn, typename ...TArgs> + TRowsHeap(size_t heap, Fn fn, size_t num, TArgs&& ... args) + : TRowsHeap(heap) + { + for (size_t it = 0; it < num; it++) { + Put(fn(it, std::forward<TArgs>(args)...)); + } + } + + TRowsHeap(size_t heap) : Heap(new TGrowHeap(heap)) { } + TRowsHeap(TIntrusivePtr<TGrowHeap> heap) : Heap(std::move(heap)) { } - - template<typename TRand> - TIter Any(TRand &rnd) const noexcept - { - return begin() + rnd.Uniform(Rows.size()); - } - - template<typename TRand> - TIter AnyIn(TRand &rnd, TIter it, const TIter end) const noexcept - { - return it + rnd.Uniform(std::distance(it, end)); - } - - template<typename TRand> - TIter AnyOff(TRand &rnd, TIter it, const TIter end) const noexcept - { - size_t on = rnd.Uniform(Size() - std::distance(it, end)); - - auto left = ui64(std::distance(begin(), it)); - - return on < left ? begin() + on : end + (on - left); - } - - TIter begin() const noexcept - { - return Rows.begin(); - } - - TIter end() const noexcept - { - return Rows.end(); - } - - size_t Size() const noexcept - { - return Rows.size(); - } - - const TRow& operator[](size_t on) const noexcept - { - Y_VERIFY(on < Rows.size(), "Row index is out of hole scope"); - - return Rows[on]; - } - - const TRow& Put(const TRow &row) - { - Rows.emplace_back(Heap.Get()); - Rows.back().Add(row); - - return Rows.back(); - } - - private: + + template<typename TRand> + TIter Any(TRand &rnd) const noexcept + { + return begin() + rnd.Uniform(Rows.size()); + } + + template<typename TRand> + TIter AnyIn(TRand &rnd, TIter it, const TIter end) const noexcept + { + return it + rnd.Uniform(std::distance(it, end)); + } + + template<typename TRand> + TIter AnyOff(TRand &rnd, TIter it, const TIter end) const noexcept + { + size_t on = rnd.Uniform(Size() - std::distance(it, end)); + + auto left = ui64(std::distance(begin(), it)); + + return on < left ? begin() + on : end + (on - left); + } + + TIter begin() const noexcept + { + return Rows.begin(); + } + + TIter end() const noexcept + { + return Rows.end(); + } + + size_t Size() const noexcept + { + return Rows.size(); + } + + const TRow& operator[](size_t on) const noexcept + { + Y_VERIFY(on < Rows.size(), "Row index is out of hole scope"); + + return Rows[on]; + } + + const TRow& Put(const TRow &row) + { + Rows.emplace_back(Heap.Get()); + Rows.back().Add(row); + + return Rows.back(); + } + + private: TIntrusivePtr<TGrowHeap> Heap; - TDeque<TRow> Rows; - }; - -} -} -} + TDeque<TRow> Rows; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/rows/layout.h b/ydb/core/tablet_flat/test/libs/rows/layout.h index 36e64feac0..ce88d6c6a6 100644 --- a/ydb/core/tablet_flat/test/libs/rows/layout.h +++ b/ydb/core/tablet_flat/test/libs/rows/layout.h @@ -1,81 +1,81 @@ -#pragma once - +#pragma once + #include <ydb/core/tablet_flat/flat_row_column.h> #include <ydb/core/tablet_flat/flat_row_scheme.h> #include <ydb/core/tablet_flat/flat_row_remap.h> #include <ydb/core/tablet_flat/flat_table_column.h> #include <ydb/core/tablet_flat/flat_util_misc.h> - -#include <util/generic/vector.h> - -#include <initializer_list> - -namespace NKikimr { -namespace NTable { -namespace NTest{ - - class TLayoutCook { - public: - using TTid = NScheme::TTypeId; - - TLayoutCook& Col(ui32 group, TTag tag, TTid type, TCell null = { }) - { - Tags_.push_back(tag); - - Cols.emplace_back("", tag, type); - Cols.back().Family = group; - Cols.back().SetDefault(null); - - return *this; - } - - TLayoutCook& Key(std::initializer_list<NTable::TTag> keys) - { - Y_VERIFY(!Scheme, "Keys are already assigned for layout cook"); - - TPos keyOrder = 0; - - for (auto tag: keys) { + +#include <util/generic/vector.h> + +#include <initializer_list> + +namespace NKikimr { +namespace NTable { +namespace NTest{ + + class TLayoutCook { + public: + using TTid = NScheme::TTypeId; + + TLayoutCook& Col(ui32 group, TTag tag, TTid type, TCell null = { }) + { + Tags_.push_back(tag); + + Cols.emplace_back("", tag, type); + Cols.back().Family = group; + Cols.back().SetDefault(null); + + return *this; + } + + TLayoutCook& Key(std::initializer_list<NTable::TTag> keys) + { + Y_VERIFY(!Scheme, "Keys are already assigned for layout cook"); + + TPos keyOrder = 0; + + for (auto tag: keys) { auto pred = [tag](const TColumn &col) { - return tag == col.Id; - }; - - auto it = std::find_if(Cols.begin(), Cols.end(), pred); - - if (it == Cols.end()) { - Y_FAIL("Not all key tags found in columns registery"); - } else if (it->KeyOrder != Max<NTable::TPos>()) { - Y_FAIL("Non-unique key column tags supplied for layout"); - } else { - it->KeyOrder = keyOrder++; - } - } - - Scheme = TRowScheme::Make(Cols, NUtil::TAsIs()); - - return *this; - } - - const TRowScheme& operator*() const noexcept - { - return *Scheme; - } - + return tag == col.Id; + }; + + auto it = std::find_if(Cols.begin(), Cols.end(), pred); + + if (it == Cols.end()) { + Y_FAIL("Not all key tags found in columns registery"); + } else if (it->KeyOrder != Max<NTable::TPos>()) { + Y_FAIL("Non-unique key column tags supplied for layout"); + } else { + it->KeyOrder = keyOrder++; + } + } + + Scheme = TRowScheme::Make(Cols, NUtil::TAsIs()); + + return *this; + } + + const TRowScheme& operator*() const noexcept + { + return *Scheme; + } + TIntrusiveConstPtr<TRowScheme> RowScheme() const noexcept - { - return Scheme; - } - - TRemap FullRemap() const - { - return TRemap(*Scheme, Tags_); - } - - private: + { + return Scheme; + } + + TRemap FullRemap() const + { + return TRemap(*Scheme, Tags_); + } + + private: TVector<NTable::TColumn> Cols; TVector<NTable::TTag> Tags_; TIntrusiveConstPtr<TRowScheme> Scheme; - }; -} -} -} + }; +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/rows/mass.h b/ydb/core/tablet_flat/test/libs/rows/mass.h index 3997a46ee0..beca8bfbc0 100644 --- a/ydb/core/tablet_flat/test/libs/rows/mass.h +++ b/ydb/core/tablet_flat/test/libs/rows/mass.h @@ -1,88 +1,88 @@ -#pragma once - -#include "rows.h" -#include "heap.h" - +#pragma once + +#include "rows.h" +#include "heap.h" + #include <ydb/core/tablet_flat/flat_row_scheme.h> #include <ydb/core/tablet_flat/util_basics.h> - -#include <util/random/mersenne.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - - class IModel { - public: + +#include <util/random/mersenne.h> + +namespace NKikimr { +namespace NTable { +namespace NTest { + + class IModel { + public: IModel(TIntrusiveConstPtr<TRowScheme> scheme) : Scheme(scheme) { } - - virtual ~IModel() = default; - virtual TRow Make(ui64 seq, bool hole) noexcept = 0; - virtual ui64 Base(const TRow &row) const noexcept = 0; - virtual void Check(TArrayRef<const ui64>) const = 0; + + virtual ~IModel() = default; + virtual TRow Make(ui64 seq, bool hole) noexcept = 0; + virtual ui64 Base(const TRow &row) const noexcept = 0; + virtual void Check(TArrayRef<const ui64>) const = 0; virtual void Describe(IOutputStream&) const noexcept = 0; - + const TIntrusiveConstPtr<TRowScheme> Scheme; - }; - - class TMass { - public: + }; + + class TMass { + public: TMass(TAutoPtr<IModel> model, ui64 caps, ui64 seed = 0, float holes = 0.1) - : Model(model) - , Heap(new TGrowHeap(64 * 1024)) - , Saved(Heap) - , Holes(Heap) - { - TMersenne<ui64> rnd(seed); - ui64 overrun = 0; /* omitted holes, should write */ - bool last = false; /* last written row is a hole */ - - for (ui64 it = 0, rows = 0; rows < caps; it++) { - bool hole = rnd.GenRandReal4() <= holes; - - if (last) { - overrun += ui64(std::exchange(hole, false)); - } else if (overrun > 0) { - overrun -= ui64(!std::exchange(hole, true)); - } - - auto row = Model->Make(it, hole); - - (hole ? Holes : Saved).Put(std::move(row)); - - rows += (last = hole) ? 0 : 1; - } - } - + : Model(model) + , Heap(new TGrowHeap(64 * 1024)) + , Saved(Heap) + , Holes(Heap) + { + TMersenne<ui64> rnd(seed); + ui64 overrun = 0; /* omitted holes, should write */ + bool last = false; /* last written row is a hole */ + + for (ui64 it = 0, rows = 0; rows < caps; it++) { + bool hole = rnd.GenRandReal4() <= holes; + + if (last) { + overrun += ui64(std::exchange(hole, false)); + } else if (overrun > 0) { + overrun -= ui64(!std::exchange(hole, true)); + } + + auto row = Model->Make(it, hole); + + (hole ? Holes : Saved).Put(std::move(row)); + + rows += (last = hole) ? 0 : 1; + } + } + void Describe(IOutputStream &out) const noexcept - { - out - << "Mass{" - << Saved.Size() << " ~" << Holes.Size() - << " rows, " << Heap->Used() << "b}"; - } - + { + out + << "Mass{" + << Saved.Size() << " ~" << Holes.Size() + << " rows, " << Heap->Used() << "b}"; + } + const TRow* SnapBy(const TRow &row, bool next, bool hole) const noexcept - { - auto it = Model->Base(row); - - if (it > Saved.Size()) { - Y_FAIL("Last saved TMass row slot is out of store range"); - } else if (next) { - return it >= Saved.Size() ? nullptr : &Saved[it]; + { + auto it = Model->Base(row); + + if (it > Saved.Size()) { + Y_FAIL("Last saved TMass row slot is out of store range"); + } else if (next) { + return it >= Saved.Size() ? nullptr : &Saved[it]; } else if (hole) { return it == 0 ? nullptr : &Saved[it - 1]; - } else { + } else { return it <= 1 ? nullptr : &Saved[it - 2]; - } - } - + } + } + const TAutoPtr<IModel> Model; TIntrusivePtr<TGrowHeap> Heap; - TRowsHeap Saved; - TRowsHeap Holes; - }; - -} -} -} + TRowsHeap Saved; + TRowsHeap Holes; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/rows/misc.h b/ydb/core/tablet_flat/test/libs/rows/misc.h index 955a34d4a7..8f96765e92 100644 --- a/ydb/core/tablet_flat/test/libs/rows/misc.h +++ b/ydb/core/tablet_flat/test/libs/rows/misc.h @@ -1,57 +1,57 @@ -#pragma once - +#pragma once + #include <ydb/core/tablet_flat/util_basics.h> -#include <util/generic/vector.h> -#include <util/generic/utility.h> -#include <util/memory/pool.h> - -namespace NKikimr { -namespace NTable { -namespace NTest{ - - class TGrowHeap: public TAtomicRefCount<TGrowHeap> { - public: +#include <util/generic/vector.h> +#include <util/generic/utility.h> +#include <util/memory/pool.h> + +namespace NKikimr { +namespace NTable { +namespace NTest{ + + class TGrowHeap: public TAtomicRefCount<TGrowHeap> { + public: explicit TGrowHeap(size_t bytes) : Pool(bytes, TMemoryPool::TLinearGrow::Instance()) - { - - } - - TGrowHeap(const TGrowHeap&) = delete; - - void* Alloc(size_t bytes) - { - return Pool.Allocate(bytes); - } - - size_t Used() const noexcept - { - return Pool.MemoryAllocated(); - } - - private: - TMemoryPool Pool; - }; - - template<typename TGen> - struct TRandomString { - TRandomString(TGen &gen): Gen(gen) { } - + { + + } + + TGrowHeap(const TGrowHeap&) = delete; + + void* Alloc(size_t bytes) + { + return Pool.Allocate(bytes); + } + + size_t Used() const noexcept + { + return Pool.MemoryAllocated(); + } + + private: + TMemoryPool Pool; + }; + + template<typename TGen> + struct TRandomString { + TRandomString(TGen &gen): Gen(gen) { } + TString Do(const size_t len) noexcept - { + { TString line; - - line.reserve(len); - - for (size_t it = 0; it < len; it++) { - line.push_back(char(Gen.Uniform(65, 90))); - } - - return line; - } - - TGen &Gen; - }; -} -} -} + + line.reserve(len); + + for (size_t it = 0; it < len; it++) { + line.push_back(char(Gen.Uniform(65, 90))); + } + + return line; + } + + TGen &Gen; + }; +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/rows/rows.h b/ydb/core/tablet_flat/test/libs/rows/rows.h index 8bde29ceac..4ca9304847 100644 --- a/ydb/core/tablet_flat/test/libs/rows/rows.h +++ b/ydb/core/tablet_flat/test/libs/rows/rows.h @@ -1,186 +1,186 @@ -#pragma once - -#include "misc.h" - +#pragma once + +#include "misc.h" + #include <ydb/core/tablet_flat/flat_row_eggs.h> #include <ydb/core/tablet_flat/flat_row_column.h> #include <ydb/core/tablet_flat/flat_sausage_solid.h> #include <ydb/core/scheme/scheme_tablecell.h> - -#include <util/generic/vector.h> -#include <util/generic/utility.h> - -namespace NKikimr { - -namespace NScheme { - template<typename TVal> struct TTypeFor; - - template<> struct TTypeFor<ui64> { enum { Type = NTypeIds::Uint64 }; }; - template<> struct TTypeFor<ui32> { enum { Type = NTypeIds::Uint32 }; }; - template<> struct TTypeFor<i64> { enum { Type = NTypeIds::Int64 }; }; - template<> struct TTypeFor<i32> { enum { Type = NTypeIds::Int32 }; }; - template<> struct TTypeFor<ui8> { enum { Type = NTypeIds::Byte }; }; - template<> struct TTypeFor<bool> { enum { Type = NTypeIds::Bool }; }; - template<> struct TTypeFor<double> { enum { Type = NTypeIds::Double }; }; - template<> struct TTypeFor<float> { enum { Type = NTypeIds::Float }; }; - template<> struct TTypeFor<::TString> { enum { Type = NTypeIds::String }; }; -} - -namespace NTable { - -namespace NTest { - namespace ETypes = NScheme::NTypeIds; - - template<typename TVal> - inline TCell Cimple(const TVal &val) - { - static_assert(TCell::CanInline(sizeof(val)), ""); - - return { (const char*)(&val), sizeof(val) }; - } - - struct TOmit{ }; - - class TRow { - public: - using TType = NScheme::TTypeId; - - template<typename TVal> using TTypeFor = NScheme::TTypeFor<TVal>; - - struct TUpdate { + +#include <util/generic/vector.h> +#include <util/generic/utility.h> + +namespace NKikimr { + +namespace NScheme { + template<typename TVal> struct TTypeFor; + + template<> struct TTypeFor<ui64> { enum { Type = NTypeIds::Uint64 }; }; + template<> struct TTypeFor<ui32> { enum { Type = NTypeIds::Uint32 }; }; + template<> struct TTypeFor<i64> { enum { Type = NTypeIds::Int64 }; }; + template<> struct TTypeFor<i32> { enum { Type = NTypeIds::Int32 }; }; + template<> struct TTypeFor<ui8> { enum { Type = NTypeIds::Byte }; }; + template<> struct TTypeFor<bool> { enum { Type = NTypeIds::Bool }; }; + template<> struct TTypeFor<double> { enum { Type = NTypeIds::Double }; }; + template<> struct TTypeFor<float> { enum { Type = NTypeIds::Float }; }; + template<> struct TTypeFor<::TString> { enum { Type = NTypeIds::String }; }; +} + +namespace NTable { + +namespace NTest { + namespace ETypes = NScheme::NTypeIds; + + template<typename TVal> + inline TCell Cimple(const TVal &val) + { + static_assert(TCell::CanInline(sizeof(val)), ""); + + return { (const char*)(&val), sizeof(val) }; + } + + struct TOmit{ }; + + class TRow { + public: + using TType = NScheme::TTypeId; + + template<typename TVal> using TTypeFor = NScheme::TTypeFor<TVal>; + + struct TUpdate { TUpdate(TTag tag, TType type, TCellOp op) - : Tag(tag), Type(type), Op(op) { } - - TRawTypeValue Raw() const - { - return { Cell.Data(), Cell.Size(), Type }; - } - - NTable::TTag Tag = Max<TTag>(); - TType Type = 0; + : Tag(tag), Type(type), Op(op) { } + + TRawTypeValue Raw() const + { + return { Cell.Data(), Cell.Size(), Type }; + } + + NTable::TTag Tag = Max<TTag>(); + TType Type = 0; TCellOp Op = ECellOp::Set; - TCell Cell; - }; - + TCell Cell; + }; + TRow(TIntrusivePtr<TGrowHeap> heap = new TGrowHeap(512)) - : Heap(heap) - { - Cols.reserve(8); - } - - TRow(TRow &&row) noexcept - : Heap(std::move(row.Heap)) - , Cols(std::move(row.Cols)) - { - - } - - TArrayRef<const TUpdate> operator*() const noexcept - { - return Cols; - } - - template<typename TVal> - TRow& Do(NTable::TTag tag, const TVal &val) - { - return Put(tag, TTypeFor<TVal>::Type, &val, sizeof(val)); - } - - TRow& Do(NTable::TTag, const TOmit&) noexcept - { + : Heap(heap) + { + Cols.reserve(8); + } + + TRow(TRow &&row) noexcept + : Heap(std::move(row.Heap)) + , Cols(std::move(row.Cols)) + { + + } + + TArrayRef<const TUpdate> operator*() const noexcept + { + return Cols; + } + + template<typename TVal> + TRow& Do(NTable::TTag tag, const TVal &val) + { + return Put(tag, TTypeFor<TVal>::Type, &val, sizeof(val)); + } + + TRow& Do(NTable::TTag, const TOmit&) noexcept + { return *this; /* implicit ECellOp::Empty */ - } - + } + TRow& Do(NTable::TTag tag, ECellOp op) - { + { Y_VERIFY(TCellOp::HaveNoPayload(op), "Allowed only payloadless ops"); - - Cols.emplace_back(tag, 0, op); - - return *this; - } - - TRow& Do(NTable::TTag tag, std::nullptr_t) - { - return Put(tag, 0, nullptr, 0); - } - - TRow& Do(NTable::TTag tag, const char *data) - { - return Put(tag, TTypeFor<TString>::Type, data, std::strlen(data)); - } - - TRow& Do(NTable::TTag tag, TStringBuf buf) - { - return Put(tag, TTypeFor<TString>::Type, buf.data(), buf.length()); - } - - TRow& Do(NTable::TTag tag, const TString &buf) - { - return Put(tag, TTypeFor<TString>::Type, buf.data(), buf.size()); - } - + + Cols.emplace_back(tag, 0, op); + + return *this; + } + + TRow& Do(NTable::TTag tag, std::nullptr_t) + { + return Put(tag, 0, nullptr, 0); + } + + TRow& Do(NTable::TTag tag, const char *data) + { + return Put(tag, TTypeFor<TString>::Type, data, std::strlen(data)); + } + + TRow& Do(NTable::TTag tag, TStringBuf buf) + { + return Put(tag, TTypeFor<TString>::Type, buf.data(), buf.length()); + } + + TRow& Do(NTable::TTag tag, const TString &buf) + { + return Put(tag, TTypeFor<TString>::Type, buf.data(), buf.size()); + } + TRow& Do(NTable::TTag tag, const NPageCollection::TGlobId &glob) - { - auto *data = static_cast<const void*>(&glob); - - Put(tag, TTypeFor<TString>::Type, data, sizeof(glob)); - + { + auto *data = static_cast<const void*>(&glob); + + Put(tag, TTypeFor<TString>::Type, data, sizeof(glob)); + Cols.back().Op = TCellOp{ ECellOp::Set, ELargeObj::GlobId }; - - return *this; - } - - TRow& Add(const TRow &tagged) - { - for (const auto &va: *tagged) { + + return *this; + } + + TRow& Add(const TRow &tagged) + { + for (const auto &va: *tagged) { if (va.Op == ECellOp::Set) { - Put(va.Tag, va.Type, va.Cell.Data(), va.Cell.Size()); - } else { - Cols.emplace_back(va.Tag, 0, va.Op); - } - } - - return *this; - } - - const TUpdate* Get(NTable::TTag tag) const noexcept - { - auto pred = [tag] (const TUpdate &up) { return up.Tag == tag; }; - - auto it = std::find_if(Cols.begin(), Cols.end(), pred); - - return it == Cols.end() ? nullptr : &*it; - } - - private: - TRow& Put(TTag tag, TType type, const void* ptr_, ui32 len) - { - auto *ptr = static_cast<const char*>(ptr_); - + Put(va.Tag, va.Type, va.Cell.Data(), va.Cell.Size()); + } else { + Cols.emplace_back(va.Tag, 0, va.Op); + } + } + + return *this; + } + + const TUpdate* Get(NTable::TTag tag) const noexcept + { + auto pred = [tag] (const TUpdate &up) { return up.Tag == tag; }; + + auto it = std::find_if(Cols.begin(), Cols.end(), pred); + + return it == Cols.end() ? nullptr : &*it; + } + + private: + TRow& Put(TTag tag, TType type, const void* ptr_, ui32 len) + { + auto *ptr = static_cast<const char*>(ptr_); + Cols.emplace_back(tag, type, ECellOp::Set); - - if (TCell::CanInline(len)) { - Cols.back().Cell = { ptr, len }; - - } else { - auto *place = Heap->Alloc(len); - - std::copy(ptr, ptr + len, static_cast<char*>(place)); - - Cols.back().Cell = { static_cast<const char*>(place), len }; - } - - Y_VERIFY(Cols.back().Cell.IsInline() == TCell::CanInline(len)); - - return *this; - } - - private: + + if (TCell::CanInline(len)) { + Cols.back().Cell = { ptr, len }; + + } else { + auto *place = Heap->Alloc(len); + + std::copy(ptr, ptr + len, static_cast<char*>(place)); + + Cols.back().Cell = { static_cast<const char*>(place), len }; + } + + Y_VERIFY(Cols.back().Cell.IsInline() == TCell::CanInline(len)); + + return *this; + } + + private: TIntrusivePtr<TGrowHeap> Heap; - TVector<TUpdate> Cols; - }; - -} -} -} + TVector<TUpdate> Cols; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/rows/tails.h b/ydb/core/tablet_flat/test/libs/rows/tails.h index ac427cd3d4..e02d6bde5e 100644 --- a/ydb/core/tablet_flat/test/libs/rows/tails.h +++ b/ydb/core/tablet_flat/test/libs/rows/tails.h @@ -1,29 +1,29 @@ -#pragma once - -namespace NKikimr { -namespace NTable { -namespace NTest{ - - constexpr ui32 operator"" _u32(unsigned long long val) noexcept - { - return static_cast<ui32>(val); - } - - constexpr i32 operator"" _s32(unsigned long long val) noexcept - { - return static_cast<i32>(val); - } - - constexpr ui64 operator"" _u64(unsigned long long val) noexcept - { - return static_cast<ui64>(val); - } - - constexpr i64 operator"" _s64(unsigned long long val) noexcept - { - return static_cast<i64>(val); - } - -} -} -} +#pragma once + +namespace NKikimr { +namespace NTable { +namespace NTest{ + + constexpr ui32 operator"" _u32(unsigned long long val) noexcept + { + return static_cast<ui32>(val); + } + + constexpr i32 operator"" _s32(unsigned long long val) noexcept + { + return static_cast<i32>(val); + } + + constexpr ui64 operator"" _u64(unsigned long long val) noexcept + { + return static_cast<ui64>(val); + } + + constexpr i64 operator"" _s64(unsigned long long val) noexcept + { + return static_cast<i64>(val); + } + +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/rows/tool.h b/ydb/core/tablet_flat/test/libs/rows/tool.h index b02aa443bf..bd81c6c4d2 100644 --- a/ydb/core/tablet_flat/test/libs/rows/tool.h +++ b/ydb/core/tablet_flat/test/libs/rows/tool.h @@ -1,192 +1,192 @@ -#pragma once - -#include "rows.h" - +#pragma once + +#include "rows.h" + #include <ydb/core/tablet_flat/flat_row_state.h> #include <ydb/core/tablet_flat/flat_row_misc.h> #include <ydb/core/tablet_flat/flat_row_column.h> #include <ydb/core/tablet_flat/flat_row_celled.h> #include <ydb/core/tablet_flat/flat_update_op.h> #include <library/cpp/containers/stack_vector/stack_vec.h> - -#include <util/generic/vector.h> -#include <util/generic/utility.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - - const NScheme::TTypeRegistry* DbgRegistry(); - TString PrintValue(const TCell& r, NScheme::TTypeId typeId); - - class TRowTool { - public: - using TState = TRowState; - - struct TSplit { - explicit TSplit(ui32 items) - { - Key.reserve(items); - } - - TVector<TRawTypeValue> Key; - TVector<TUpdateOp> Ops; - }; - - TRowTool(const TRowScheme &scheme) - : Scheme(scheme) - { - - } - - TVector<TRawTypeValue> LookupKey(const TRow &tagged) const - { - return Split(tagged, true, false).Key; - } - - TVector<TCell> KeyCells(const TRow &tagged) const - { + +#include <util/generic/vector.h> +#include <util/generic/utility.h> + +namespace NKikimr { +namespace NTable { +namespace NTest { + + const NScheme::TTypeRegistry* DbgRegistry(); + TString PrintValue(const TCell& r, NScheme::TTypeId typeId); + + class TRowTool { + public: + using TState = TRowState; + + struct TSplit { + explicit TSplit(ui32 items) + { + Key.reserve(items); + } + + TVector<TRawTypeValue> Key; + TVector<TUpdateOp> Ops; + }; + + TRowTool(const TRowScheme &scheme) + : Scheme(scheme) + { + + } + + TVector<TRawTypeValue> LookupKey(const TRow &tagged) const + { + return Split(tagged, true, false).Key; + } + + TVector<TCell> KeyCells(const TRow &tagged) const + { TCelled celled(LookupKey(tagged), *Scheme.Keys, false); - - return { celled.Cells, celled.Cells + celled.Size }; - } - - TSplit Split(const TRow &tagged, bool weak, bool values) const - { - TSplit pair((*tagged) ? Scheme.Keys->Size() : 0); - - ui32 foundKeyCols = 0; - - /* For lookups (lookup = true) absense of tail columns in key is - interpreted as +inf, thus to support this semantic grow key - with nulls only when need to store new value from TRow. But - empty key has special meanings in context of ESeek modes. - */ - - for (auto &value: *tagged) { - auto * const info = ColFor(value); - - TRawTypeValue raw(value.Cell.AsRef(), value.Type); - - if (info->IsKey()) { + + return { celled.Cells, celled.Cells + celled.Size }; + } + + TSplit Split(const TRow &tagged, bool weak, bool values) const + { + TSplit pair((*tagged) ? Scheme.Keys->Size() : 0); + + ui32 foundKeyCols = 0; + + /* For lookups (lookup = true) absense of tail columns in key is + interpreted as +inf, thus to support this semantic grow key + with nulls only when need to store new value from TRow. But + empty key has special meanings in context of ESeek modes. + */ + + for (auto &value: *tagged) { + auto * const info = ColFor(value); + + TRawTypeValue raw(value.Cell.AsRef(), value.Type); + + if (info->IsKey()) { Y_VERIFY(value.Op == ECellOp::Set || value.Op == ECellOp::Null); - - if (info->Key >= Scheme.Keys->Size()) { - ythrow yexception() - << "Cell at " << info->Key << " is out of" - << " key size " << Scheme.Keys->Size(); + + if (info->Key >= Scheme.Keys->Size()) { + ythrow yexception() + << "Cell at " << info->Key << " is out of" + << " key size " << Scheme.Keys->Size(); } else if (info->Key >= pair.Key.size()) { - pair.Key.resize(info->Key + 1); - } - - pair.Key.at(info->Key) = raw, foundKeyCols++; - } else if (values) { - pair.Ops.emplace_back(value.Tag, value.Op, raw); - } - } - - Y_VERIFY(weak || foundKeyCols == Scheme.Keys->Size()); - - return pair; - } - - bool Compare( - const TRow &row, const TState &state, const TRemap &re) const - { - return Cmp(row, state, re, false); - } - - bool CmpKeys( - const TRow &row, const TState &state, const TRemap &re) const - { - return Cmp(row, state, re, true); - } - - bool Cmp( - const TRow &row,const TState &state, - const TRemap &remap, bool keys) const - { - TStackVec<bool, 64> Seen(state.Size(), false); - - for (const auto &val: *row) { - const auto pos = remap.Has(val.Tag); - const auto *info = ColFor(val); - const auto &cell = state.Get(pos); - - if (keys && !info->IsKey()) { - continue; /* Skip non-keys columns */ + pair.Key.resize(info->Key + 1); + } + + pair.Key.at(info->Key) = raw, foundKeyCols++; + } else if (values) { + pair.Ops.emplace_back(value.Tag, value.Op, raw); + } + } + + Y_VERIFY(weak || foundKeyCols == Scheme.Keys->Size()); + + return pair; + } + + bool Compare( + const TRow &row, const TState &state, const TRemap &re) const + { + return Cmp(row, state, re, false); + } + + bool CmpKeys( + const TRow &row, const TState &state, const TRemap &re) const + { + return Cmp(row, state, re, true); + } + + bool Cmp( + const TRow &row,const TState &state, + const TRemap &remap, bool keys) const + { + TStackVec<bool, 64> Seen(state.Size(), false); + + for (const auto &val: *row) { + const auto pos = remap.Has(val.Tag); + const auto *info = ColFor(val); + const auto &cell = state.Get(pos); + + if (keys && !info->IsKey()) { + continue; /* Skip non-keys columns */ } else if (ELargeObj(val.Op) != ELargeObj(state.GetOp(pos))) { - return false; /* Missmatched value storage method */ + return false; /* Missmatched value storage method */ } else if (val.Op != ELargeObj::Inline) { - if (!(val.Cell.AsRef() == cell.AsRef())) - return false; + if (!(val.Cell.AsRef() == cell.AsRef())) + return false; } else if (val.Op == ECellOp::Empty || val.Op == ECellOp::Reset) { if (ECellOp(val.Op) != state.GetOp(pos)) - return false; - } else if (CompareTypedCells(val.Cell, cell, info->TypeId)) { - return false; /* Literal comparison has been failed */ - } - - Seen.at(pos) = true; - } - - if (keys) { - for (auto &pin: remap.KeyPins()) - if (!Seen.at(pin.Pos)) return false; - - } else { - for (TPos on = 0; on < state.Size(); on++) - if (!Seen[on] && !state.Get(on).IsNull()) - return false; /* Has absent in row non-null value */ - } - - return true; - } - - TString Describe(const TRow &tagged) const - { - TStringStream ss; - - return Describe(ss, tagged), ss.Str(); - } - - void Describe(IOutputStream &out, const TRow &tagged) const - { - TVector<TCell> cells(Scheme.Cols.size()); - - for (const auto &value: *tagged) { - cells.at(ColFor(value)->Pos) = value.Cell; - } - - out << NFmt::TCells(cells, *Scheme.Nulls, DbgRegistry()); - } - - const TColInfo* ColFor(const TRow::TUpdate &value) const - { - auto *info = Scheme.ColInfo(value.Tag); - - if (!info || info->Pos == Max<NTable::TPos>()) { - ythrow - yexception() - << "Cannot find tag=" << value.Tag << " in scheme"; - - } else if (value.Cell.IsNull() && value.Type == 0) { - /* null values should be passed without type */ - } else if (info->TypeId != value.Type) { - ythrow - yexception() - << "Col{" << info->Pos << ", Tag " << info->Tag - << ", type " << info->TypeId << "}" - << ", got type " << value.Type << " { " - << PrintValue(value.Cell, value.Type) << " }"; - } - - return info; - } - - public: - const TRowScheme &Scheme; - }; -} -} -} + return false; + } else if (CompareTypedCells(val.Cell, cell, info->TypeId)) { + return false; /* Literal comparison has been failed */ + } + + Seen.at(pos) = true; + } + + if (keys) { + for (auto &pin: remap.KeyPins()) + if (!Seen.at(pin.Pos)) return false; + + } else { + for (TPos on = 0; on < state.Size(); on++) + if (!Seen[on] && !state.Get(on).IsNull()) + return false; /* Has absent in row non-null value */ + } + + return true; + } + + TString Describe(const TRow &tagged) const + { + TStringStream ss; + + return Describe(ss, tagged), ss.Str(); + } + + void Describe(IOutputStream &out, const TRow &tagged) const + { + TVector<TCell> cells(Scheme.Cols.size()); + + for (const auto &value: *tagged) { + cells.at(ColFor(value)->Pos) = value.Cell; + } + + out << NFmt::TCells(cells, *Scheme.Nulls, DbgRegistry()); + } + + const TColInfo* ColFor(const TRow::TUpdate &value) const + { + auto *info = Scheme.ColInfo(value.Tag); + + if (!info || info->Pos == Max<NTable::TPos>()) { + ythrow + yexception() + << "Cannot find tag=" << value.Tag << " in scheme"; + + } else if (value.Cell.IsNull() && value.Type == 0) { + /* null values should be passed without type */ + } else if (info->TypeId != value.Type) { + ythrow + yexception() + << "Col{" << info->Pos << ", Tag " << info->Tag + << ", type " << info->TypeId << "}" + << ", got type " << value.Type << " { " + << PrintValue(value.Cell, value.Type) << " }"; + } + + return info; + } + + public: + const TRowScheme &Scheme; + }; +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/rows/ya.make b/ydb/core/tablet_flat/test/libs/rows/ya.make index b8185eac60..33ea6fcf31 100644 --- a/ydb/core/tablet_flat/test/libs/rows/ya.make +++ b/ydb/core/tablet_flat/test/libs/rows/ya.make @@ -1,13 +1,13 @@ -LIBRARY() - +LIBRARY() + OWNER(g:kikimr) - -SRCS( - all.cpp -) - -PEERDIR( + +SRCS( + all.cpp +) + +PEERDIR( ydb/core/tablet_flat -) - -END() +) + +END() diff --git a/ydb/core/tablet_flat/test/libs/table/misc.cpp b/ydb/core/tablet_flat/test/libs/table/misc.cpp index 1a2a678fcc..39e76b5bc2 100644 --- a/ydb/core/tablet_flat/test/libs/table/misc.cpp +++ b/ydb/core/tablet_flat/test/libs/table/misc.cpp @@ -1,5 +1,5 @@ -#include "test_pretty.h" - +#include "test_pretty.h" + #include <ydb/core/tablet_flat/test/libs/rows/tool.h> #include <ydb/core/tablet_flat/test/libs/table/test_part.h> #include <ydb/core/tablet_flat/flat_row_scheme.h> @@ -9,63 +9,63 @@ #include <ydb/core/tablet_flat/flat_part_dump.h> #include <ydb/core/tablet_flat/flat_table_part.h> #include <ydb/core/scheme/scheme_type_registry.h> - -namespace NKikimr { -namespace NTable { - + +namespace NKikimr { +namespace NTable { + void TMemTable::DebugDump() const -{ - DebugDump(Cout, *NTest::DbgRegistry()); -} - -template <class TIterator> -TString PrintRowImpl(const TRemap& remap, const TIterator& it) -{ - TRowState state(remap.Size()); - - { - TDbTupleRef key = it.GetKey(); - - for (auto &pin: remap.KeyPins()) +{ + DebugDump(Cout, *NTest::DbgRegistry()); +} + +template <class TIterator> +TString PrintRowImpl(const TRemap& remap, const TIterator& it) +{ + TRowState state(remap.Size()); + + { + TDbTupleRef key = it.GetKey(); + + for (auto &pin: remap.KeyPins()) state.Set(pin.Pos, ECellOp::Set, key.Columns[pin.Key]); - } - + } + it.Apply(state, /* committed */ {}); - - { - TStringStream ss; - - ss << NFmt::TCells(*state, remap, NTest::DbgRegistry()); - - return ss.Str(); - } -} - -TString PrintRow(const TDbTupleRef& row) -{ - return DbgPrintTuple(row, *NTest::DbgRegistry()); -} - -TString PrintRow(const TMemIt& it) -{ - return PrintRowImpl(*it.Remap, it); -} - -namespace NTest { - + + { + TStringStream ss; + + ss << NFmt::TCells(*state, remap, NTest::DbgRegistry()); + + return ss.Str(); + } +} + +TString PrintRow(const TDbTupleRef& row) +{ + return DbgPrintTuple(row, *NTest::DbgRegistry()); +} + +TString PrintRow(const TMemIt& it) +{ + return PrintRowImpl(*it.Remap, it); +} + +namespace NTest { + TString DumpPart(const TPartStore &partStore, ui32 depth) noexcept - { - TStringStream out; - TTestEnv env; - - out.Reserve(2030); - + { + TStringStream out; + TTestEnv env; + + out.Reserve(2030); + TDump(out, &env, DbgRegistry()).Part(partStore, depth); - - return out.Str(); - } - -} - -} // namspace NTable -} // namespace NKikimr + + return out.Str(); + } + +} + +} // namspace NTable +} // namespace NKikimr diff --git a/ydb/core/tablet_flat/test/libs/table/model/keys.h b/ydb/core/tablet_flat/test/libs/table/model/keys.h index 7dec47e39b..2e019f170d 100644 --- a/ydb/core/tablet_flat/test/libs/table/model/keys.h +++ b/ydb/core/tablet_flat/test/libs/table/model/keys.h @@ -1,73 +1,73 @@ -#pragma once - +#pragma once + #include <ydb/core/tablet_flat/test/libs/rows/layout.h> #include <ydb/core/tablet_flat/test/libs/rows/mass.h> - -#include <util/random/mersenne.h> -#include <util/digest/city.h> -#include <util/generic/xrange.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - - class TModelS3Hash : public IModel { - public: - using TStrGen = TRandomString<TMersenne<ui64>>; - - TModelS3Hash(size_t buckets = 10) - : IModel( - TLayoutCook() - .Col(0, 0, NScheme::NTypeIds::Uint64) - .Col(0, 1, NScheme::NTypeIds::String) - .Col(0, 2, NScheme::NTypeIds::String) - .Col(0, 8, NScheme::NTypeIds::Uint32) - .Key({ 0, 1, 2 }).RowScheme()) - { - for (size_t num : xrange(buckets)) { - Buckets.push_back(Sprintf("Bucket_%" PRISZT, num)); - } - } - - TRow Make(ui64 seq, bool hole) noexcept override - { - TNatural row(*Scheme); - - auto &bucket = Buckets[seq % Buckets.size()]; - auto name = TStrGen(Rnd).Do(20 + Rnd.GenRand64() % 30); - ui64 hash = CityHash64(bucket + name); - - return *row.Col(hash, bucket, name, ui32(Saved += hole ? 0 : 1)); - } - - void Describe(IOutputStream &out) const noexcept override - { - out << "ModelS3Hash"; - } - - ui64 Base(const TRow &row) const noexcept override - { - auto *up = row.Get(NTable::TTag(8)); - - if (up == nullptr || up->Type != NScheme::NTypeIds::Uint32) { - Y_FAIL("Probably got row not from the TMass instance"); - } else if (up->Cell.Size() != sizeof(ui32) || !up->Cell.Data()) { - Y_FAIL("Last saved tow reference TCell is invalid in TRow"); - } else { - return *reinterpret_cast<const ui32*>(up->Cell.Data()); - } - } - - void Check(TArrayRef<const ui64>) const override - { - - } - - private: - TMersenne<ui64> Rnd = 7500; - TVector<TString> Buckets; - ui64 Saved = 0; - }; -} -} -} + +#include <util/random/mersenne.h> +#include <util/digest/city.h> +#include <util/generic/xrange.h> + +namespace NKikimr { +namespace NTable { +namespace NTest { + + class TModelS3Hash : public IModel { + public: + using TStrGen = TRandomString<TMersenne<ui64>>; + + TModelS3Hash(size_t buckets = 10) + : IModel( + TLayoutCook() + .Col(0, 0, NScheme::NTypeIds::Uint64) + .Col(0, 1, NScheme::NTypeIds::String) + .Col(0, 2, NScheme::NTypeIds::String) + .Col(0, 8, NScheme::NTypeIds::Uint32) + .Key({ 0, 1, 2 }).RowScheme()) + { + for (size_t num : xrange(buckets)) { + Buckets.push_back(Sprintf("Bucket_%" PRISZT, num)); + } + } + + TRow Make(ui64 seq, bool hole) noexcept override + { + TNatural row(*Scheme); + + auto &bucket = Buckets[seq % Buckets.size()]; + auto name = TStrGen(Rnd).Do(20 + Rnd.GenRand64() % 30); + ui64 hash = CityHash64(bucket + name); + + return *row.Col(hash, bucket, name, ui32(Saved += hole ? 0 : 1)); + } + + void Describe(IOutputStream &out) const noexcept override + { + out << "ModelS3Hash"; + } + + ui64 Base(const TRow &row) const noexcept override + { + auto *up = row.Get(NTable::TTag(8)); + + if (up == nullptr || up->Type != NScheme::NTypeIds::Uint32) { + Y_FAIL("Probably got row not from the TMass instance"); + } else if (up->Cell.Size() != sizeof(ui32) || !up->Cell.Data()) { + Y_FAIL("Last saved tow reference TCell is invalid in TRow"); + } else { + return *reinterpret_cast<const ui32*>(up->Cell.Data()); + } + } + + void Check(TArrayRef<const ui64>) const override + { + + } + + private: + TMersenne<ui64> Rnd = 7500; + TVector<TString> Buckets; + ui64 Saved = 0; + }; +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/model/large.h b/ydb/core/tablet_flat/test/libs/table/model/large.h index 6dfb4d6af9..6da31212b0 100644 --- a/ydb/core/tablet_flat/test/libs/table/model/large.h +++ b/ydb/core/tablet_flat/test/libs/table/model/large.h @@ -1,112 +1,112 @@ -#pragma once - +#pragma once + #include <ydb/core/tablet_flat/test/libs/rows/mass.h> #include <ydb/core/tablet_flat/test/libs/rows/cook.h> #include <ydb/core/tablet_flat/test/libs/rows/layout.h> - -#include <util/random/mersenne.h> -#include <array> - -namespace NKikimr { -namespace NTable { -namespace NTest { - - class TModelStd : public IModel { - public: - using TRnd = TMersenne<ui64>; - - TModelStd(bool groups) - : IModel(CookLayout(groups).RowScheme()) - { - - } - - TRow Make(ui64, bool hole) noexcept override - { - const ui64 up = hole ? 0 : 1; - - TNatural row(*Scheme); - - { - Sub[0] += up, row.Col(Seq * 3 + 7, ui32(Seq + 10), Sub[0]); - } - - if (Entropy.GenRandReal4() < 0.500) { - auto ln = TRandomString<TRnd>(Entropy).Do(1 + (Seq & 0x1f)); - - Sub[1] += up, row.To(3).Col<TString, bool>(ln, bool(Seq & 2)); - } - - if (Entropy.GenRandReal4() < 0.250) { - auto shift = Seq & 0xf; - - Sub[2] += up, row.To(5).Col<ui32, ui32>(shift, Seq << shift); - } - - if (Entropy.GenRandReal4() < 0.125) { - auto ln = TRandomString<TRnd>(Entropy).Do(7 + (Seq & 0x7f)); - - Sub[3] += up, row.To(7).Col<TString, ui64>(ln, ln.size()); - } - - return Seq++, *row; - } - + +#include <util/random/mersenne.h> +#include <array> + +namespace NKikimr { +namespace NTable { +namespace NTest { + + class TModelStd : public IModel { + public: + using TRnd = TMersenne<ui64>; + + TModelStd(bool groups) + : IModel(CookLayout(groups).RowScheme()) + { + + } + + TRow Make(ui64, bool hole) noexcept override + { + const ui64 up = hole ? 0 : 1; + + TNatural row(*Scheme); + + { + Sub[0] += up, row.Col(Seq * 3 + 7, ui32(Seq + 10), Sub[0]); + } + + if (Entropy.GenRandReal4() < 0.500) { + auto ln = TRandomString<TRnd>(Entropy).Do(1 + (Seq & 0x1f)); + + Sub[1] += up, row.To(3).Col<TString, bool>(ln, bool(Seq & 2)); + } + + if (Entropy.GenRandReal4() < 0.250) { + auto shift = Seq & 0xf; + + Sub[2] += up, row.To(5).Col<ui32, ui32>(shift, Seq << shift); + } + + if (Entropy.GenRandReal4() < 0.125) { + auto ln = TRandomString<TRnd>(Entropy).Do(7 + (Seq & 0x7f)); + + Sub[3] += up, row.To(7).Col<TString, ui64>(ln, ln.size()); + } + + return Seq++, *row; + } + void Describe(IOutputStream &out) const noexcept override - { - out - << "Std{" - << Sub[0] << ", " << Sub[1] << ", " - << Sub[2] << ", " << Sub[3] << "}"; - } - - static TLayoutCook CookLayout(bool groups) - { - return - TLayoutCook() - .Col(groups ? 0 : 0, 0, NScheme::NTypeIds::Uint64) - .Col(groups ? 0 : 0, 1, NScheme::NTypeIds::Uint32) - .Col(groups ? 0 : 0, 2, NScheme::NTypeIds::Uint64) + { + out + << "Std{" + << Sub[0] << ", " << Sub[1] << ", " + << Sub[2] << ", " << Sub[3] << "}"; + } + + static TLayoutCook CookLayout(bool groups) + { + return + TLayoutCook() + .Col(groups ? 0 : 0, 0, NScheme::NTypeIds::Uint64) + .Col(groups ? 0 : 0, 1, NScheme::NTypeIds::Uint32) + .Col(groups ? 0 : 0, 2, NScheme::NTypeIds::Uint64) .Col(groups ? 1 : 0, 3, NScheme::NTypeIds::String) - .Col(groups ? 1 : 0, 4, NScheme::NTypeIds::Bool) - .Col(groups ? 5 : 0, 5, NScheme::NTypeIds::Uint32) - .Col(groups ? 5 : 0, 6, NScheme::NTypeIds::Uint32) + .Col(groups ? 1 : 0, 4, NScheme::NTypeIds::Bool) + .Col(groups ? 5 : 0, 5, NScheme::NTypeIds::Uint32) + .Col(groups ? 5 : 0, 6, NScheme::NTypeIds::Uint32) .Col(groups ? 8 : 0, 7, NScheme::NTypeIds::String) - .Col(groups ? 8 : 0, 8, NScheme::NTypeIds::Uint64) - .Key({ 0, 1 }); - } - - ui64 Base(const TRow &row) const noexcept override - { - auto *up = row.Get(NTable::TTag(2)); - - if (up == nullptr || up->Type != NScheme::NTypeIds::Uint64) { - Y_FAIL("Probably got row not from the TMass instance"); - } else if (up->Cell.Size() != sizeof(ui64) || !up->Cell.Data()) { - Y_FAIL("Last saved tow reference TCell is invalid in TRow"); - } else { + .Col(groups ? 8 : 0, 8, NScheme::NTypeIds::Uint64) + .Key({ 0, 1 }); + } + + ui64 Base(const TRow &row) const noexcept override + { + auto *up = row.Get(NTable::TTag(2)); + + if (up == nullptr || up->Type != NScheme::NTypeIds::Uint64) { + Y_FAIL("Probably got row not from the TMass instance"); + } else if (up->Cell.Size() != sizeof(ui64) || !up->Cell.Data()) { + Y_FAIL("Last saved tow reference TCell is invalid in TRow"); + } else { return up->Cell.AsValue<ui64>(); - } - } - - void Check(TArrayRef<const ui64> rows) const override - { - Y_VERIFY(rows.size() == 1); - - if (rows[0] != Sub[0]) { - throw - yexception() - << "TMass part has " << rows[0] << " rows" - << ", but should be " << Sub[0] << " rows"; - } - } - - private: - TRnd Entropy = 7500; - ui64 Seq = 0; - std::array<ui64, 4> Sub {{ 0, 0, 0, 0 }}; - }; - -} -} -} + } + } + + void Check(TArrayRef<const ui64> rows) const override + { + Y_VERIFY(rows.size() == 1); + + if (rows[0] != Sub[0]) { + throw + yexception() + << "TMass part has " << rows[0] << " rows" + << ", but should be " << Sub[0] << " rows"; + } + } + + private: + TRnd Entropy = 7500; + ui64 Seq = 0; + std::array<ui64, 4> Sub {{ 0, 0, 0, 0 }}; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/model/small.h b/ydb/core/tablet_flat/test/libs/table/model/small.h index d1b0cdfca2..ae7f2db35e 100644 --- a/ydb/core/tablet_flat/test/libs/table/model/small.h +++ b/ydb/core/tablet_flat/test/libs/table/model/small.h @@ -1,62 +1,62 @@ -#pragma once - +#pragma once + #include <ydb/core/tablet_flat/test/libs/rows/layout.h> #include <ydb/core/tablet_flat/test/libs/rows/mass.h> - -#include <util/random/mersenne.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - - class TModel2Cols : public IModel { - public: - TModel2Cols() - : IModel( - TLayoutCook() - .Col(0, 0, NScheme::NTypeIds::Uint64) - .Col(0, 1, NScheme::NTypeIds::Uint64) - .Key({ 0 }).RowScheme()) - { - - } - - TRow Make(ui64 seq, bool hole) noexcept override - { - TNatural row(*Scheme); - - row.Col(seq, (Saved += hole ? 0 : 1)); - - return *row; - } - + +#include <util/random/mersenne.h> + +namespace NKikimr { +namespace NTable { +namespace NTest { + + class TModel2Cols : public IModel { + public: + TModel2Cols() + : IModel( + TLayoutCook() + .Col(0, 0, NScheme::NTypeIds::Uint64) + .Col(0, 1, NScheme::NTypeIds::Uint64) + .Key({ 0 }).RowScheme()) + { + + } + + TRow Make(ui64 seq, bool hole) noexcept override + { + TNatural row(*Scheme); + + row.Col(seq, (Saved += hole ? 0 : 1)); + + return *row; + } + void Describe(IOutputStream &out) const noexcept override - { - out << "Model2Cols"; - } - - ui64 Base(const TRow &row) const noexcept override - { - auto *up = row.Get(NTable::TTag(1)); - - if (up == nullptr || up->Type != NScheme::NTypeIds::Uint64) { - Y_FAIL("Probably got row not from the TMass instance"); - } else if (up->Cell.Size() != sizeof(ui64) || !up->Cell.Data()) { - Y_FAIL("Last saved tow reference TCell is invalid in TRow"); - } else { - return *reinterpret_cast<const ui64*>(up->Cell.Data()); - } - } - - void Check(TArrayRef<const ui64>) const override - { - - } - - private: - TMersenne<ui64> Entropy = 7500; - ui64 Saved = 0; - }; -} -} -} + { + out << "Model2Cols"; + } + + ui64 Base(const TRow &row) const noexcept override + { + auto *up = row.Get(NTable::TTag(1)); + + if (up == nullptr || up->Type != NScheme::NTypeIds::Uint64) { + Y_FAIL("Probably got row not from the TMass instance"); + } else if (up->Cell.Size() != sizeof(ui64) || !up->Cell.Data()) { + Y_FAIL("Last saved tow reference TCell is invalid in TRow"); + } else { + return *reinterpret_cast<const ui64*>(up->Cell.Data()); + } + } + + void Check(TArrayRef<const ui64>) const override + { + + } + + private: + TMersenne<ui64> Entropy = 7500; + ui64 Saved = 0; + }; +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/model/ya.make b/ydb/core/tablet_flat/test/libs/table/model/ya.make index dab9796656..e624e27460 100644 --- a/ydb/core/tablet_flat/test/libs/table/model/ya.make +++ b/ydb/core/tablet_flat/test/libs/table/model/ya.make @@ -1,9 +1,9 @@ -LIBRARY() - +LIBRARY() + OWNER(g:kikimr) - -PEERDIR( + +PEERDIR( ydb/core/tablet_flat/test/libs/rows -) - -END() +) + +END() diff --git a/ydb/core/tablet_flat/test/libs/table/test_comp.h b/ydb/core/tablet_flat/test/libs/table/test_comp.h index d6095c2a78..0f3907f518 100644 --- a/ydb/core/tablet_flat/test/libs/table/test_comp.h +++ b/ydb/core/tablet_flat/test/libs/table/test_comp.h @@ -1,150 +1,150 @@ -#pragma once - -#include "test_part.h" -#include "test_writer.h" - +#pragma once + +#include "test_part.h" +#include "test_writer.h" + #include <ydb/core/tablet_flat/util_basics.h> #include <ydb/core/tablet_flat/flat_table_subset.h> #include <ydb/core/tablet_flat/flat_scan_feed.h> #include <ydb/core/tablet_flat/test/libs/rows/layout.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - + +namespace NKikimr { +namespace NTable { +namespace NTest { + class TCompaction final : protected IVersionScan { - class TMyScan : public TFeed { - public: + class TMyScan : public TFeed { + public: TMyScan(IScan *scan, const TSubset &subset, IPages *env) : TFeed(scan, subset) - , Env(env) - { - Conf.NoErased = false; /* Need all technical rows */ - } - - IPages* MakeEnv() noexcept override - { - return Env; - } - + , Env(env) + { + Conf.NoErased = false; /* Need all technical rows */ + } + + IPages* MakeEnv() noexcept override + { + return Env; + } + TPartView LoadPart(const TIntrusiveConstPtr<TColdPart>&) noexcept override { Y_FAIL("not supported in test scans"); } - IPages * const Env = nullptr; - }; - - public: - using TConf = NPage::TConf; - - TCompaction() : TCompaction(nullptr) { } - + IPages * const Env = nullptr; + }; + + public: + using TConf = NPage::TConf; + + TCompaction() : TCompaction(nullptr) { } + TCompaction(TAutoPtr<IPages> env, TConf conf = { }, ui32 ret = Max<ui32>()) - : Conf(conf) - , Retries(ret) - , Env(env ? env : new TTestEnv) - { - - } - + : Conf(conf) + , Retries(ret) + , Env(env ? env : new TTestEnv) + { + + } + TPartEggs Do(TIntrusiveConstPtr<TMemTable> table) - { + { return Do(TSubset(TEpoch::Zero(), table->Scheme, { TMemTableSnapshot{ table, table->Immediate() } })); - } - - TPartEggs Do(const TPartEggs &eggs) - { + } + + TPartEggs Do(const TPartEggs &eggs) + { return Do(eggs.Scheme, { &eggs } ); - } - + } + TPartEggs Do(TIntrusiveConstPtr<TRowScheme> scheme, TVector<const TPartEggs*> eggs) - { + { TVector<TPartView> partView; - + for (auto &one: eggs) { - for (const auto &part : one->Parts) { + for (const auto &part : one->Parts) { Y_VERIFY(part->Slices, "Missing part slices"); partView.push_back({ part, nullptr, part->Slices }); } } - + return Do(TSubset(TEpoch::Zero(), std::move(scheme), std::move(partView))); - } - - TPartEggs Do(const TSubset &subset) - { - return Do(subset, TLogoBlobID(0, 0, ++Serial, 0, 0, 0)); - } - - TPartEggs Do(const TSubset &subset, TLogoBlobID logo) - { - auto *scheme = new TPartScheme(subset.Scheme->Cols); - + } + + TPartEggs Do(const TSubset &subset) + { + return Do(subset, TLogoBlobID(0, 0, ++Serial, 0, 0, 0)); + } + + TPartEggs Do(const TSubset &subset, TLogoBlobID logo) + { + auto *scheme = new TPartScheme(subset.Scheme->Cols); + TWriterBundle blocks(scheme->Groups.size(), logo); - Tags = subset.Scheme->Tags(); - NPage::TConf conf = Conf; - conf.MaxRows = subset.MaxRows(); + Tags = subset.Scheme->Tags(); + NPage::TConf conf = Conf; + conf.MaxRows = subset.MaxRows(); conf.MinRowVersion = subset.MinRowVersion(); Writer = new TPartWriter(scheme, Tags, blocks, conf, subset.Epoch()); - - TMyScan scanner(this, subset, Env.Get()); - - while (true) { - const auto ready = scanner.Process(); - - if (ready == EReady::Data) { - /* Just scan iterruption for unknown reason, go on */ - } else if (ready == EReady::Gone) { - auto eggs = blocks.Flush(subset.Scheme, Writer->Finish()); - - Y_VERIFY(eggs.Written->Rows <= conf.MaxRows); - - return eggs; - } else if (ready != EReady::Page) { - Y_FAIL("Subset scanner give unexpected cycle result"); - } else if (Failed++ > Retries) { - - /* Early termination without any complete result, event - an ommited empty part. Used for scan abort tests. */ - + + TMyScan scanner(this, subset, Env.Get()); + + while (true) { + const auto ready = scanner.Process(); + + if (ready == EReady::Data) { + /* Just scan iterruption for unknown reason, go on */ + } else if (ready == EReady::Gone) { + auto eggs = blocks.Flush(subset.Scheme, Writer->Finish()); + + Y_VERIFY(eggs.Written->Rows <= conf.MaxRows); + + return eggs; + } else if (ready != EReady::Page) { + Y_FAIL("Subset scanner give unexpected cycle result"); + } else if (Failed++ > Retries) { + + /* Early termination without any complete result, event + an ommited empty part. Used for scan abort tests. */ + return { nullptr, nullptr, { } }; - - } else if (Failed > 32 && Retries == Max<ui32>()) { - - /* Can happen on EScan::Sleep and on real page fail. Our + + } else if (Failed > 32 && Retries == Max<ui32>()) { + + /* Can happen on EScan::Sleep and on real page fail. Our IScan impl never yields EScan::Sleep and this case - is always page fail of some supplied Env. So, go on - until there is some progress. - */ - - Y_FAIL("Mocked compaction failied to make any progress"); - } - } - } - - private: + is always page fail of some supplied Env. So, go on + until there is some progress. + */ + + Y_FAIL("Mocked compaction failied to make any progress"); + } + } + } + + private: virtual THello Prepare(IDriver*, TIntrusiveConstPtr<TScheme>) noexcept override - { + { Y_FAIL("IScan::Prepare(...) isn't used in test env compaction"); - } - - EScan Seek(TLead &lead, ui64 seq) noexcept override - { + } + + EScan Seek(TLead &lead, ui64 seq) noexcept override + { Y_VERIFY(seq < 2, "Test IScan impl Got too many Seek() calls"); - - lead.To(Tags, { }, ESeek::Lower); - - return seq == 0 ? EScan::Feed : EScan::Final; - } - + + lead.To(Tags, { }, ESeek::Lower); + + return seq == 0 ? EScan::Feed : EScan::Final; + } + EScan BeginKey(TArrayRef<const TCell> key) noexcept override - { + { Writer->BeginKey(key); - - return Failed = 0, EScan::Feed; - } - + + return Failed = 0, EScan::Feed; + } + EScan BeginDeltas() noexcept override { return Failed = 0, EScan::Feed; @@ -177,25 +177,25 @@ namespace NTest { } TAutoPtr<IDestructable> Finish(EAbort) noexcept override - { + { Y_FAIL("IScan::Finish(...) shouldn't be called in test env"); - } - - void Describe(IOutputStream &out) const noexcept override - { - out << "Compact{test env}"; - } - - private: - const NPage::TConf Conf { true, 7 * 1024 }; - const ui32 Retries = Max<ui32>(); - ui32 Serial = 0; - ui32 Failed = 0; + } + + void Describe(IOutputStream &out) const noexcept override + { + out << "Compact{test env}"; + } + + private: + const NPage::TConf Conf { true, 7 * 1024 }; + const ui32 Retries = Max<ui32>(); + ui32 Serial = 0; + ui32 Failed = 0; TAutoPtr<IPages> Env; TVector<ui32> Tags; TAutoPtr<TPartWriter> Writer; - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/test_cooker.h b/ydb/core/tablet_flat/test/libs/table/test_cooker.h index d6a6426a97..4ebb540ac4 100644 --- a/ydb/core/tablet_flat/test/libs/table/test_cooker.h +++ b/ydb/core/tablet_flat/test/libs/table/test_cooker.h @@ -1,59 +1,59 @@ -#pragma once - +#pragma once + #include <ydb/core/tablet_flat/test/libs/rows/tool.h> #include <ydb/core/tablet_flat/test/libs/rows/heap.h> #include <ydb/core/tablet_flat/test/libs/rows/layout.h> - + #include <ydb/core/tablet_flat/flat_mem_warm.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - - struct TCooker { - + +namespace NKikimr { +namespace NTable { +namespace NTest { + + struct TCooker { + TCooker(const TLayoutCook &lay, TEpoch epoch = TEpoch::Zero()) - : TCooker(lay.RowScheme(), epoch) - { - - } - + : TCooker(lay.RowScheme(), epoch) + { + + } + TCooker(TIntrusiveConstPtr<TRowScheme> scheme, TEpoch epoch = TEpoch::Zero()) : Table(new TMemTable(std::move(scheme), epoch, 0)) - , Tool(*Table->Scheme) - { - - } - + , Tool(*Table->Scheme) + { + + } + TIntrusivePtr<TMemTable> operator*() const noexcept - { - return Table; - } - + { + return Table; + } + TIntrusivePtr<TMemTable> Unwrap() const noexcept - { + { return std::move(const_cast<TIntrusivePtr<TMemTable>&>(Table)); - } - + } + const TCooker& Add(const TRowsHeap &heap, ERowOp rop) const - { - for (auto &row: heap) Add(row, rop); - - return *this; - } - + { + for (auto &row: heap) Add(row, rop); + + return *this; + } + const TCooker& Add(const TRow &tagged, ERowOp rop = ERowOp::Upsert) const - { + { auto pair = Tool.Split(tagged, true, rop != ERowOp::Erase); - + return Table->Update(rop, pair.Key, pair.Ops, { }, /* TODO: rowVersion */ TRowVersion::Min(), /* committed */ {}), *this; - } - - private: + } + + private: TIntrusivePtr<TMemTable> Table; - const NTest::TRowTool Tool; - }; - -} -} -} + const NTest::TRowTool Tool; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/test_curtain.h b/ydb/core/tablet_flat/test/libs/table/test_curtain.h index 3c85a4e1ef..e6f17fbb09 100644 --- a/ydb/core/tablet_flat/test/libs/table/test_curtain.h +++ b/ydb/core/tablet_flat/test/libs/table/test_curtain.h @@ -1,111 +1,111 @@ -#pragma once - -#include "test_part.h" -#include "wrap_part.h" - +#pragma once + +#include "test_part.h" +#include "wrap_part.h" + #include <ydb/core/tablet_flat/test/libs/rows/rows.h> #include <ydb/core/tablet_flat/flat_part_screen.h> #include <ydb/core/tablet_flat/flat_part_iter_multi.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - - struct TCurtain { - struct TRes { - TRowsHeap::TIter Begin; - TRowsHeap::TIter End; - + +namespace NKikimr { +namespace NTable { +namespace NTest { + + struct TCurtain { + struct TRes { + TRowsHeap::TIter Begin; + TRowsHeap::TIter End; + TIntrusiveConstPtr<TScreen> Screen; - }; - - TCurtain(const TPartEggs &eggs): Wrap(eggs, { new TTestEnv, 0 }) { } - - TRes Make(const TRowsHeap &heap, TMersenne<ui64> &rnd, size_t max) - { - auto len = rnd.Uniform(17, max); - - return Make(heap, rnd.Uniform(heap.Size()), len); - } - - TRes Make(const TRowsHeap &heap, size_t offset, size_t len) - { - Y_VERIFY(offset < heap.Size(), "Hole offset is out of the heap"); - - const auto on = heap.begin() + offset; - - auto end = on + Min(len, size_t(std::distance(on, heap.end()))); - - TRowId h2, h1 = Wrap.Seek(*on, ESeek::Lower)->GetRowId(); - - if (end == heap.end()) { - h2 = Wrap.Seek({}, ESeek::Upper)->GetRowId(); - } else { - h2 = Wrap.Seek(*end, ESeek::Lower)->GetRowId(); - } - - if (h1 == Max<TRowId>() || h1 >= h2) { - ythrow yexception() << "Cannot make screen hole for mass part"; - } - - TScreen::TVec holes = { { h1, h2 } }; - - return TRes{ on, end, new TScreen(std::move(holes)) }; - } - - private: - TCheckIt Wrap; - }; - - - struct TSlicer { - TSlicer(const TRowScheme &scheme) : Scheme(scheme) { } - + }; + + TCurtain(const TPartEggs &eggs): Wrap(eggs, { new TTestEnv, 0 }) { } + + TRes Make(const TRowsHeap &heap, TMersenne<ui64> &rnd, size_t max) + { + auto len = rnd.Uniform(17, max); + + return Make(heap, rnd.Uniform(heap.Size()), len); + } + + TRes Make(const TRowsHeap &heap, size_t offset, size_t len) + { + Y_VERIFY(offset < heap.Size(), "Hole offset is out of the heap"); + + const auto on = heap.begin() + offset; + + auto end = on + Min(len, size_t(std::distance(on, heap.end()))); + + TRowId h2, h1 = Wrap.Seek(*on, ESeek::Lower)->GetRowId(); + + if (end == heap.end()) { + h2 = Wrap.Seek({}, ESeek::Upper)->GetRowId(); + } else { + h2 = Wrap.Seek(*end, ESeek::Lower)->GetRowId(); + } + + if (h1 == Max<TRowId>() || h1 >= h2) { + ythrow yexception() << "Cannot make screen hole for mass part"; + } + + TScreen::TVec holes = { { h1, h2 } }; + + return TRes{ on, end, new TScreen(std::move(holes)) }; + } + + private: + TCheckIt Wrap; + }; + + + struct TSlicer { + TSlicer(const TRowScheme &scheme) : Scheme(scheme) { } + TIntrusiveConstPtr<TSlices> Cut(const TPartStore &partStore, const TScreen &screen) noexcept - { - TTestEnv env; + { + TTestEnv env; TPartSimpleIt first(&partStore, { }, Scheme.Keys, &env); TPartSimpleIt last(&partStore, { }, Scheme.Keys, &env); TVector<TSlice> slices; - - TRowId lastEnd = 0; - - for (const auto &hole : screen) { - Y_VERIFY(lastEnd <= hole.Begin, "Screen is not sorted correctly"); - Y_VERIFY(first.Seek(hole.Begin) != EReady::Page); - Y_VERIFY(last.Seek(hole.End) != EReady::Page); - if (first.GetRowId() < last.GetRowId()) { - TArrayRef<const TCell> firstKey; - if (first.IsValid()) { - firstKey = first.GetRawKey(); - } - - TArrayRef<const TCell> lastKey; - if (last.IsValid()) { - lastKey = last.GetRawKey(); - } - + + TRowId lastEnd = 0; + + for (const auto &hole : screen) { + Y_VERIFY(lastEnd <= hole.Begin, "Screen is not sorted correctly"); + Y_VERIFY(first.Seek(hole.Begin) != EReady::Page); + Y_VERIFY(last.Seek(hole.End) != EReady::Page); + if (first.GetRowId() < last.GetRowId()) { + TArrayRef<const TCell> firstKey; + if (first.IsValid()) { + firstKey = first.GetRawKey(); + } + + TArrayRef<const TCell> lastKey; + if (last.IsValid()) { + lastKey = last.GetRawKey(); + } + auto cut = TSlices::Cut( partStore.Slices, - first.GetRowId(), - last.GetRowId(), - firstKey, - lastKey); - + first.GetRowId(), + last.GetRowId(), + firstKey, + lastKey); + for (const auto& slice : *cut) { slices.emplace_back(slice); - } - } - lastEnd = hole.End; - } - + } + } + lastEnd = hole.End; + } + TIntrusiveConstPtr<TSlices> result = new TSlices(std::move(slices)); result->Validate(); return result; - } - - const TRowScheme Scheme; - }; -} -} -} + } + + const TRowScheme Scheme; + }; +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/test_dbase.h b/ydb/core/tablet_flat/test/libs/table/test_dbase.h index fd931a5483..275356fcaf 100644 --- a/ydb/core/tablet_flat/test/libs/table/test_dbase.h +++ b/ydb/core/tablet_flat/test/libs/table/test_dbase.h @@ -1,8 +1,8 @@ -#pragma once - -#include "test_steps.h" -#include "test_comp.h" - +#pragma once + +#include "test_steps.h" +#include "test_comp.h" + #include <ydb/core/tablet_flat/flat_database.h> #include <ydb/core/tablet_flat/flat_dbase_naked.h> #include <ydb/core/tablet_flat/flat_dbase_apply.h> @@ -10,78 +10,78 @@ #include <ydb/core/tablet_flat/flat_sausage_grind.h> #include <ydb/core/tablet_flat/flat_util_binary.h> #include <ydb/core/tablet_flat/util_fmt_desc.h> - + #include <ydb/core/tablet_flat/test/libs/rows/cook.h> #include <ydb/core/tablet_flat/test/libs/rows/tool.h> #include <ydb/core/tablet_flat/test/libs/table/test_iter.h> #include <ydb/core/tablet_flat/test/libs/table/test_envs.h> #include <ydb/core/tablet_flat/test/libs/table/wrap_dbase.h> #include <ydb/core/tablet_flat/test/libs/table/wrap_select.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - - enum class EPlay { - Boot = 1, /* Apply redo log through base booter */ + +namespace NKikimr { +namespace NTable { +namespace NTest { + + enum class EPlay { + Boot = 1, /* Apply redo log through base booter */ Redo = 2, /* Roll up redo log through follower iface */ - }; - - struct TDbExec : public TSteps<TDbExec> { - using TRow = NTest::TRow; + }; + + struct TDbExec : public TSteps<TDbExec> { + using TRow = NTest::TRow; using TRedoLog = TDeque<TAutoPtr<TChange>>; using TSteppedCookieAllocator = NPageCollection::TSteppedCookieAllocator; - - using TCheckIter = TChecker<NTest::TWrapDbIter, TDatabase&>; - using TCheckSelect = TChecker<NTest::TWrapDbSelect, TDatabase&>; - - enum class EOnTx { - None = 0, - Auto = 1, /* Automatic read only transaction */ - Real = 2, /* Explicitly prepared user rw tx */ - }; - - struct THeader { - ui64 Serial; /* Change serial stamp data */ - ui32 Alter; /* Bytes of scheme delta block */ - ui32 Redo; /* Bytes of redo log block */ - ui32 Affects; /* Items in affects array */ - ui32 Pad0; - }; - + + using TCheckIter = TChecker<NTest::TWrapDbIter, TDatabase&>; + using TCheckSelect = TChecker<NTest::TWrapDbSelect, TDatabase&>; + + enum class EOnTx { + None = 0, + Auto = 1, /* Automatic read only transaction */ + Real = 2, /* Explicitly prepared user rw tx */ + }; + + struct THeader { + ui64 Serial; /* Change serial stamp data */ + ui32 Alter; /* Bytes of scheme delta block */ + ui32 Redo; /* Bytes of redo log block */ + ui32 Affects; /* Items in affects array */ + ui32 Pad0; + }; + static TAutoPtr<TDatabase> Make(TAutoPtr<TSchemeChanges> delta) - { + { TAutoPtr<TScheme> scheme = new TScheme; - - TSchemeModifier(*scheme).Apply(*delta); - + + TSchemeModifier(*scheme).Apply(*delta); + return new TDatabase(new TDatabaseImpl(0, scheme, nullptr)); - } - - TDbExec() : Base(new TDatabase) { Birth(); } - + } + + TDbExec() : Base(new TDatabase) { Birth(); } + TDbExec(TAutoPtr<TSchemeChanges> delta) : Base(Make(delta)) { } - - const TRedoLog& GetLog() const noexcept { return RedoLog; } - - const TChange& BackLog() const noexcept - { - Y_VERIFY(RedoLog, "Redo log is empty, cannot get last entry"); - - return *RedoLog.back(); - } - - TDatabase* operator->() const noexcept { return Base.Get(); } - - TDbExec& Begin() noexcept - { - return DoBegin(true); - } - - TDbExec& Commit() { return DoCommit(true, true); } - TDbExec& Reject() { return DoCommit(true, false); } - TDbExec& Relax() { return DoCommit(false, true); } - + + const TRedoLog& GetLog() const noexcept { return RedoLog; } + + const TChange& BackLog() const noexcept + { + Y_VERIFY(RedoLog, "Redo log is empty, cannot get last entry"); + + return *RedoLog.back(); + } + + TDatabase* operator->() const noexcept { return Base.Get(); } + + TDbExec& Begin() noexcept + { + return DoBegin(true); + } + + TDbExec& Commit() { return DoCommit(true, true); } + TDbExec& Reject() { return DoCommit(true, false); } + TDbExec& Relax() { return DoCommit(false, true); } + TDbExec& ReadVer(TRowVersion readVersion) { DoBegin(false); @@ -99,330 +99,330 @@ namespace NTest { } TDbExec& Add(ui32 table, const TRow &row, ERowOp rop = ERowOp::Upsert) - { - const NTest::TRowTool tool(RowSchemeFor(table)); + { + const NTest::TRowTool tool(RowSchemeFor(table)); auto pair = tool.Split(row, true, rop != ERowOp::Erase); - + Base->Update(table, rop, pair.Key, pair.Ops, WriteVersion); - - return *this; - } - - template<typename ... Args> - inline TDbExec& Put(ui32 table, const TRow &row, const Args& ... left) - { + + return *this; + } + + template<typename ... Args> + inline TDbExec& Put(ui32 table, const TRow &row, const Args& ... left) + { return Add(table, row, ERowOp::Upsert), Put(table, left...); - } - - inline TDbExec& Put(ui32 table, const TRow &row) - { + } + + inline TDbExec& Put(ui32 table, const TRow &row) + { return Add(table, row, ERowOp::Upsert); - } - - TDbExec& Apply(const TSchemeChanges &delta) - { - Last = Max<ui32>(), Altered = true; - - return Base->Alter().Merge(delta), *this; - } - - TDbExec& Snapshot(ui32 table) - { - return Base->TxSnapTable(table), *this; - } - - NTest::TNatural Natural(ui32 table) noexcept - { - return { RowSchemeFor(table) }; - } - - TCheckIter Iter(ui32 table, bool erased = true) noexcept - { - DoBegin(false), RowSchemeFor(table); - + } + + TDbExec& Apply(const TSchemeChanges &delta) + { + Last = Max<ui32>(), Altered = true; + + return Base->Alter().Merge(delta), *this; + } + + TDbExec& Snapshot(ui32 table) + { + return Base->TxSnapTable(table), *this; + } + + NTest::TNatural Natural(ui32 table) noexcept + { + return { RowSchemeFor(table) }; + } + + TCheckIter Iter(ui32 table, bool erased = true) noexcept + { + DoBegin(false), RowSchemeFor(table); + TCheckIter check{ *Base, { nullptr, 0, erased }, table, Scheme, ReadVersion }; - - return check.To(CurrentStep()), check; - } - - TCheckSelect Select(ui32 table, bool erased = true) noexcept - { - DoBegin(false), RowSchemeFor(table); - + + return check.To(CurrentStep()), check; + } + + TCheckSelect Select(ui32 table, bool erased = true) noexcept + { + DoBegin(false), RowSchemeFor(table); + TCheckSelect check{ *Base, { nullptr, 0, erased }, table, Scheme, ReadVersion }; - - return check.To(CurrentStep()), check; - } - - TDbExec& Snap(ui32 table) - { - const auto scn = Base->Head().Serial + 1; - - RedoLog.emplace_back(new TChange({ Gen, ++Step }, scn)); - RedoLog.back()->Redo = Base->SnapshotToLog(table, { Gen, Step }); - RedoLog.back()->Affects = { table }; - - Y_VERIFY(scn == Base->Head().Serial); - - return *this; - } - - TDbExec& Compact(ui32 table, bool last = true) - { + + return check.To(CurrentStep()), check; + } + + TDbExec& Snap(ui32 table) + { + const auto scn = Base->Head().Serial + 1; + + RedoLog.emplace_back(new TChange({ Gen, ++Step }, scn)); + RedoLog.back()->Redo = Base->SnapshotToLog(table, { Gen, Step }); + RedoLog.back()->Affects = { table }; + + Y_VERIFY(scn == Base->Head().Serial); + + return *this; + } + + TDbExec& Compact(ui32 table, bool last = true) + { TAutoPtr<TSubset> subset; - - if (last /* make full subset */) { + + if (last /* make full subset */) { subset = Base->Subset(table, TEpoch::Max(), { }, { }); - } else /* only flush memtables */ { + } else /* only flush memtables */ { subset = Base->Subset(table, { }, TEpoch::Max()); - } - - TLogoBlobID logo(1, Gen, ++Step, 1, 0, 0); - - auto *family = Base->GetScheme().DefaultFamilyFor(table); - - NPage::TConf conf{ last, 8291, family->Large }; - - conf.ByKeyFilter = Base->GetScheme().GetTableInfo(table)->ByKeyFilter; - conf.MaxRows = subset->MaxRows(); + } + + TLogoBlobID logo(1, Gen, ++Step, 1, 0, 0); + + auto *family = Base->GetScheme().DefaultFamilyFor(table); + + NPage::TConf conf{ last, 8291, family->Large }; + + conf.ByKeyFilter = Base->GetScheme().GetTableInfo(table)->ByKeyFilter; + conf.MaxRows = subset->MaxRows(); conf.MinRowVersion = subset->MinRowVersion(); - conf.SmallEdge = family->Small; - - auto keys = subset->Scheme->Tags(true /* only keys */); - - /* Mocked NFwd emulates real compaction partially: it cannot pass + conf.SmallEdge = family->Small; + + auto keys = subset->Scheme->Tags(true /* only keys */); + + /* Mocked NFwd emulates real compaction partially: it cannot pass external blobs from TMemTable to TPart by reference, so need to - materialize it on this compaction. - */ - + materialize it on this compaction. + */ + TAutoPtr<IPages> env = new TForwardEnv(128, 256, keys, Max<ui32>()); - - auto eggs = TCompaction(env, conf).Do(*subset, logo); - - Y_VERIFY(!eggs.NoResult(), "Unexpected early termination"); - + + auto eggs = TCompaction(env, conf).Do(*subset, logo); + + Y_VERIFY(!eggs.NoResult(), "Unexpected early termination"); + TVector<TPartView> partViews; - for (auto &part : eggs.Parts) + for (auto &part : eggs.Parts) partViews.push_back({ part, nullptr, part->Slices }); - + Base->Replace(table, std::move(partViews), *subset); - return *this; - } - - TDbExec& Replay(EPlay play) - { - Y_VERIFY(OnTx != EOnTx::Real, "Commit TX before replaying"); - - const ui64 serial = Base->Head().Serial; - - Birth(), Base = nullptr, OnTx = EOnTx::None; - + return *this; + } + + TDbExec& Replay(EPlay play) + { + Y_VERIFY(OnTx != EOnTx::Real, "Commit TX before replaying"); + + const ui64 serial = Base->Head().Serial; + + Birth(), Base = nullptr, OnTx = EOnTx::None; + ReadVersion = TRowVersion::Max(); WriteVersion = TRowVersion::Min(); - if (play == EPlay::Boot) { + if (play == EPlay::Boot) { TAutoPtr<TScheme> scheme = new TScheme; - - for (auto &change: RedoLog) { - if (auto &raw = change->Scheme) { - TSchemeChanges delta; - bool ok = delta.ParseFromString(raw); - - Y_VERIFY(ok, "Cannot read serialized scheme delta"); - - TSchemeModifier(*scheme).Apply(delta); - } - } - + + for (auto &change: RedoLog) { + if (auto &raw = change->Scheme) { + TSchemeChanges delta; + bool ok = delta.ParseFromString(raw); + + Y_VERIFY(ok, "Cannot read serialized scheme delta"); + + TSchemeModifier(*scheme).Apply(delta); + } + } + TAutoPtr<TDatabaseImpl> naked = new TDatabaseImpl({Gen, Step}, scheme, nullptr); - - for (auto &change: RedoLog) - if (auto &redo = change->Redo) { - naked->Switch(change->Stamp); - naked->Assign(change->Annex); - naked->ApplyRedo(redo); - naked->GrabAnnex(); - } - - UNIT_ASSERT(serial == naked->Serial()); - - Base = new TDatabase(naked.Release()); - - } else if (play == EPlay::Redo) { - - Base = new TDatabase{ }; - - for (const auto &it: RedoLog) - Base->RollUp(it->Stamp, it->Scheme, it->Redo, it->Annex); - - UNIT_ASSERT(serial == Base->Head().Serial); - } - - return *this; - } - - const TRowScheme& RowSchemeFor(ui32 table) noexcept - { - if (std::exchange(Last, table) == table) { - /* Safetly can use row scheme from cache */ - } else if (Altered) { - TScheme temp(Base->GetScheme()); - TSchemeModifier(temp).Apply(*Base->Alter()); - - const auto *info = temp.GetTableInfo(table); - - Scheme = TRowScheme::Make(info->Columns, NUtil::TSecond()); - } else { + + for (auto &change: RedoLog) + if (auto &redo = change->Redo) { + naked->Switch(change->Stamp); + naked->Assign(change->Annex); + naked->ApplyRedo(redo); + naked->GrabAnnex(); + } + + UNIT_ASSERT(serial == naked->Serial()); + + Base = new TDatabase(naked.Release()); + + } else if (play == EPlay::Redo) { + + Base = new TDatabase{ }; + + for (const auto &it: RedoLog) + Base->RollUp(it->Stamp, it->Scheme, it->Redo, it->Annex); + + UNIT_ASSERT(serial == Base->Head().Serial); + } + + return *this; + } + + const TRowScheme& RowSchemeFor(ui32 table) noexcept + { + if (std::exchange(Last, table) == table) { + /* Safetly can use row scheme from cache */ + } else if (Altered) { + TScheme temp(Base->GetScheme()); + TSchemeModifier(temp).Apply(*Base->Alter()); + + const auto *info = temp.GetTableInfo(table); + + Scheme = TRowScheme::Make(info->Columns, NUtil::TSecond()); + } else { Scheme = Base->Subset(table, { }, TEpoch::Zero())->Scheme; - } - - return *Scheme; - } - - TDbExec& Affects(ui32 back, std::initializer_list<ui32> tables) - { - Y_VERIFY(back < RedoLog.size(), "Out of redo log entries"); - + } + + return *Scheme; + } + + TDbExec& Affects(ui32 back, std::initializer_list<ui32> tables) + { + Y_VERIFY(back < RedoLog.size(), "Out of redo log entries"); + const auto &have = RedoLog[RedoLog.size() - (1 + back)]->Affects; - - if (have.size() == tables.size() - && std::equal(have.begin(), have.end(), tables.begin())) { - - } else { - TSteps<TDbExec>::Log() + + if (have.size() == tables.size() + && std::equal(have.begin(), have.end(), tables.begin())) { + + } else { + TSteps<TDbExec>::Log() << "For " << NFmt::Do(*RedoLog[RedoLog.size() - (1 + back)]) - << " expected affects " << NFmt::Arr(tables) - << Endl; - - UNIT_ASSERT(false); - } - - return *this; - } - - void DumpChanges(IOutputStream &stream) const noexcept - { - for (auto &one: RedoLog) { - NUtil::NBin::TOut(stream) - .Put<ui64>(one->Serial) - .Put<ui32>(one->Scheme.size()) - .Put<ui32>(one->Redo.size()) - .Put<ui32>(one->Affects.size()) - .Put<ui32>(0 /* paddings */) - .Array(one->Scheme) - .Array(one->Redo) - .Array(one->Affects); - } - } - - static TRedoLog RestoreChanges(IInputStream &in) - { - TRedoLog changes; - THeader header; - - while (auto got = in.Load(&header, sizeof(header))) { - Y_VERIFY(got == sizeof(header), "Invalid changes stream"); - - const auto abytes = sizeof(ui32) * header.Affects; - - TString alter = TString::TUninitialized(header.Alter); - + << " expected affects " << NFmt::Arr(tables) + << Endl; + + UNIT_ASSERT(false); + } + + return *this; + } + + void DumpChanges(IOutputStream &stream) const noexcept + { + for (auto &one: RedoLog) { + NUtil::NBin::TOut(stream) + .Put<ui64>(one->Serial) + .Put<ui32>(one->Scheme.size()) + .Put<ui32>(one->Redo.size()) + .Put<ui32>(one->Affects.size()) + .Put<ui32>(0 /* paddings */) + .Array(one->Scheme) + .Array(one->Redo) + .Array(one->Affects); + } + } + + static TRedoLog RestoreChanges(IInputStream &in) + { + TRedoLog changes; + THeader header; + + while (auto got = in.Load(&header, sizeof(header))) { + Y_VERIFY(got == sizeof(header), "Invalid changes stream"); + + const auto abytes = sizeof(ui32) * header.Affects; + + TString alter = TString::TUninitialized(header.Alter); + if (in.Load((void*)alter.data(), alter.size()) != alter.size()) - Y_FAIL("Cannot read alter chunk data in change page"); - - TString redo = TString::TUninitialized(header.Redo); - + Y_FAIL("Cannot read alter chunk data in change page"); + + TString redo = TString::TUninitialized(header.Redo); + if (in.Load((void*)redo.data(), redo.size()) != redo.size()) - Y_FAIL("Cannot read redo log data in change page"); - - if (in.Skip(abytes) != abytes) - Y_FAIL("Cannot read affects array in change page"); - - changes.push_back(new TChange{ header.Serial, header.Serial }); - changes.back()->Scheme = std::move(alter); - changes.back()->Redo = std::move(redo); - } - - return changes; - } - - private: - void Birth() noexcept - { + Y_FAIL("Cannot read redo log data in change page"); + + if (in.Skip(abytes) != abytes) + Y_FAIL("Cannot read affects array in change page"); + + changes.push_back(new TChange{ header.Serial, header.Serial }); + changes.back()->Scheme = std::move(alter); + changes.back()->Redo = std::move(redo); + } + + return changes; + } + + private: + void Birth() noexcept + { Annex = new TSteppedCookieAllocator(1, ui64(++Gen) << 32, { 0, 999 }, {{ 1, 7 }}); - } - - TDbExec& DoBegin(bool real) noexcept - { - if (OnTx == EOnTx::Real && real) { - Y_FAIL("Cannot run multiple tx at the same time"); - } else if (OnTx == EOnTx::Auto && real) { - DoCommit(false, false); - } - - if (OnTx == EOnTx::None || real) { - Annex->Switch(++Step, true /* require step switch */); + } + + TDbExec& DoBegin(bool real) noexcept + { + if (OnTx == EOnTx::Real && real) { + Y_FAIL("Cannot run multiple tx at the same time"); + } else if (OnTx == EOnTx::Auto && real) { + DoCommit(false, false); + } + + if (OnTx == EOnTx::None || real) { + Annex->Switch(++Step, true /* require step switch */); Base->Begin({ Gen, Step }, Env.emplace()); - - OnTx = (real ? EOnTx::Real : EOnTx::Auto); - } - - return *this; - } - - TDbExec& DoCommit(bool real, bool apply) - { - const auto was = std::exchange(OnTx, EOnTx::None); - - if (was != (real ? EOnTx::Real : EOnTx::Auto)) - Y_FAIL("There is no active dbase tx"); - - auto up = Base->Commit({ Gen, Step }, apply, Annex.Get()).Change; + + OnTx = (real ? EOnTx::Real : EOnTx::Auto); + } + + return *this; + } + + TDbExec& DoCommit(bool real, bool apply) + { + const auto was = std::exchange(OnTx, EOnTx::None); + + if (was != (real ? EOnTx::Real : EOnTx::Auto)) + Y_FAIL("There is no active dbase tx"); + + auto up = Base->Commit({ Gen, Step }, apply, Annex.Get()).Change; Env.reset(); - - Last = Max<ui32>(), Altered = false; - - UNIT_ASSERT(!up->HasAny() || apply); - UNIT_ASSERT(!up->HasAny() || was != EOnTx::Auto); - UNIT_ASSERT(!up->Annex || up->Redo); - - if (apply) { - std::sort(up->Affects.begin(), up->Affects.end()); - - auto end = std::unique(up->Affects.begin(), up->Affects.end()); - - if (end != up->Affects.end()) { - TSteps<TDbExec>::Log() - << NFmt::Do(*up) << " has denormalized affects" << Endl; - - UNIT_ASSERT(false); - } - - RedoLog.emplace_back(std::move(up)); - } - + + Last = Max<ui32>(), Altered = false; + + UNIT_ASSERT(!up->HasAny() || apply); + UNIT_ASSERT(!up->HasAny() || was != EOnTx::Auto); + UNIT_ASSERT(!up->Annex || up->Redo); + + if (apply) { + std::sort(up->Affects.begin(), up->Affects.end()); + + auto end = std::unique(up->Affects.begin(), up->Affects.end()); + + if (end != up->Affects.end()) { + TSteps<TDbExec>::Log() + << NFmt::Do(*up) << " has denormalized affects" << Endl; + + UNIT_ASSERT(false); + } + + RedoLog.emplace_back(std::move(up)); + } + ReadVersion = TRowVersion::Max(); WriteVersion = TRowVersion::Min(); - return *this; - } - - private: + return *this; + } + + private: TAutoPtr<TDatabase> Base; std::optional<TTestEnv> Env; - ui32 Gen = 0; - ui32 Step = 0; - ui32 Last = Max<ui32>(); - bool Altered = false; - EOnTx OnTx = EOnTx::None; + ui32 Gen = 0; + ui32 Step = 0; + ui32 Last = Max<ui32>(); + bool Altered = false; + EOnTx OnTx = EOnTx::None; TIntrusiveConstPtr<TRowScheme> Scheme; - TRedoLog RedoLog; + TRedoLog RedoLog; TAutoPtr<TSteppedCookieAllocator> Annex; TRowVersion ReadVersion = TRowVersion::Max(); TRowVersion WriteVersion = TRowVersion::Min(); - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/test_dummy.h b/ydb/core/tablet_flat/test/libs/table/test_dummy.h index 01ecae1deb..b6fcc4673c 100644 --- a/ydb/core/tablet_flat/test/libs/table/test_dummy.h +++ b/ydb/core/tablet_flat/test/libs/table/test_dummy.h @@ -1,28 +1,28 @@ -#pragma once - +#pragma once + #include <ydb/core/tablet_flat/flat_part_iface.h> #include <ydb/core/tablet_flat/flat_table_misc.h> - -namespace NKikimr { -namespace NTable { - - class TDummyEnv: public IPages { - public: + +namespace NKikimr { +namespace NTable { + + class TDummyEnv: public IPages { + public: TResult Locate(const TMemTable *memTable, ui64 ref, ui32 tag) noexcept override - { + { return MemTableRefLookup(memTable, ref, tag); - } - + } + TResult Locate(const TPart*, ui64, ELargeObj) noexcept override - { - Y_FAIL("Dummy env cannot deal with storage"); - } - + { + Y_FAIL("Dummy env cannot deal with storage"); + } + const TSharedData* TryGetPage(const TPart*, TPageId, TGroupId) override - { - Y_FAIL("Dummy env cannot deal with storage"); - } - }; - -} -} + { + Y_FAIL("Dummy env cannot deal with storage"); + } + }; + +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/test_envs.h b/ydb/core/tablet_flat/test/libs/table/test_envs.h index 52066ddd33..25b33acf7b 100644 --- a/ydb/core/tablet_flat/test/libs/table/test_envs.h +++ b/ydb/core/tablet_flat/test/libs/table/test_envs.h @@ -1,247 +1,247 @@ -#pragma once - -#include "test_part.h" +#pragma once + +#include "test_part.h" #include <ydb/core/tablet_flat/flat_table_misc.h> #include <ydb/core/tablet_flat/flat_fwd_cache.h> #include <ydb/core/tablet_flat/flat_fwd_blobs.h> #include <ydb/core/tablet_flat/flat_fwd_warmed.h> #include <ydb/core/tablet_flat/flat_row_scheme.h> #include <ydb/core/tablet_flat/util_fmt_abort.h> - -#include <util/generic/cast.h> -#include <util/generic/set.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - + +#include <util/generic/cast.h> +#include <util/generic/set.h> + +namespace NKikimr { +namespace NTable { +namespace NTest { + enum class ELargeObjNeed { - Has = 0, - Yes = 1, - No = 2, - }; - - struct TNoEnv : public TTestEnv { - TNoEnv() = default; - + Has = 0, + Yes = 1, + No = 2, + }; + + struct TNoEnv : public TTestEnv { + TNoEnv() = default; + TNoEnv(bool pages, ELargeObjNeed lobs) : Pages(pages) , Lobs(lobs) { } - + TResult Locate(const TMemTable *memTable, ui64 ref, ui32 tag) noexcept override - { + { return TTestEnv::Locate(memTable, ref, tag); - } - + } + TResult Locate(const TPart *part, ui64 ref, ELargeObj lob) noexcept override - { + { const bool pass = Lobs == ELargeObjNeed::Has; const bool need = Lobs == ELargeObjNeed::Yes; - - return + + return pass ? TTestEnv::Locate(part, ref, lob) : TResult{need, nullptr }; - } - + } + const TSharedData* TryGetPage(const TPart *part, TPageId ref, TGroupId groupId) override - { + { return Pages ? TTestEnv::TryGetPage(part, ref, groupId) : nullptr; - } - - bool Pages = false; + } + + bool Pages = false; ELargeObjNeed Lobs = ELargeObjNeed::Yes; - }; - - template<typename TRandom> - class TFailEnv: public TTestEnv { - struct TSeen { - TSeen() = default; - - TSeen(const void *token, ui64 ref) noexcept - : Token(token) , Ref(ref) { } - - bool operator==(const TSeen &seen) const noexcept - { - return Token == seen.Token && Ref == seen.Ref; - } - - const void *Token = nullptr; - ui64 Ref = Max<ui64>(); - }; - - public: - TFailEnv(TRandom &rnd, double rate = 1.) - : Rate(rate) - , Rnd(rnd) - , Trace(8) - { - - } - - ~TFailEnv() - { - if (Touches == 0 || (Rate < 1. && Success == Touches)) { - Y_Fail("Fail env was touched " << Touches << " times w/o fails"); - } - } - + }; + + template<typename TRandom> + class TFailEnv: public TTestEnv { + struct TSeen { + TSeen() = default; + + TSeen(const void *token, ui64 ref) noexcept + : Token(token) , Ref(ref) { } + + bool operator==(const TSeen &seen) const noexcept + { + return Token == seen.Token && Ref == seen.Ref; + } + + const void *Token = nullptr; + ui64 Ref = Max<ui64>(); + }; + + public: + TFailEnv(TRandom &rnd, double rate = 1.) + : Rate(rate) + , Rnd(rnd) + , Trace(8) + { + + } + + ~TFailEnv() + { + if (Touches == 0 || (Rate < 1. && Success == Touches)) { + Y_Fail("Fail env was touched " << Touches << " times w/o fails"); + } + } + TResult Locate(const TMemTable *memTable, ui64 ref, ui32 tag) noexcept override - { + { return TTestEnv::Locate(memTable, ref, tag); - } - + } + TResult Locate(const TPart *part, ui64 ref, ELargeObj lob) noexcept override - { - if (ShouldPass((const void*)part->Large.Get(), ref)) { - return TTestEnv::Locate(part, ref, lob); - } else { - return { true, nullptr }; - } - } - + { + if (ShouldPass((const void*)part->Large.Get(), ref)) { + return TTestEnv::Locate(part, ref, lob); + } else { + return { true, nullptr }; + } + } + const TSharedData* TryGetPage(const TPart* part, TPageId ref, TGroupId groupId) override - { + { auto pass = ShouldPass((const void*)part, ref | (ui64(groupId.Raw()) << 32)); - + return pass ? TTestEnv::TryGetPage(part, ref, groupId) : nullptr; - } - + } + bool ShouldPass(const void *token, ui64 id) - { - const auto pass = IsRecent({ token, id }) || AmILucky(); - - Touches++, Success += pass ? 1 : 0; - - if (!pass) { - Offset = (Offset + 1) % Trace.size(); - - Trace[Offset] = { token, id }; - } - - return pass; - } - - bool IsRecent(TSeen seen) const noexcept - { - return std::find(Trace.begin(), Trace.end(), seen) != Trace.end(); - } - - bool AmILucky() noexcept - { - return Rate >= 1. || Rnd.GenRandReal4() <= Rate; - } - - const double Rate = 1.; - TRandom &Rnd; - ui64 Touches = 0; - ui64 Success = 0; - TVector<TSeen> Trace; - ui32 Offset = Max<ui32>(); - }; - - class TForwardEnv : public IPages { - using TSlot = ui32; + { + const auto pass = IsRecent({ token, id }) || AmILucky(); + + Touches++, Success += pass ? 1 : 0; + + if (!pass) { + Offset = (Offset + 1) % Trace.size(); + + Trace[Offset] = { token, id }; + } + + return pass; + } + + bool IsRecent(TSeen seen) const noexcept + { + return std::find(Trace.begin(), Trace.end(), seen) != Trace.end(); + } + + bool AmILucky() noexcept + { + return Rate >= 1. || Rnd.GenRandReal4() <= Rate; + } + + const double Rate = 1.; + TRandom &Rnd; + ui64 Touches = 0; + ui64 Success = 0; + TVector<TSeen> Trace; + ui32 Offset = Max<ui32>(); + }; + + class TForwardEnv : public IPages { + using TSlot = ui32; using TSlotVec = TSmallVec<TSlot>; - + struct TPageLoadingQueue : private NFwd::IPageLoadingQueue { TPageLoadingQueue(TIntrusiveConstPtr<TStore> store, ui32 room, TAutoPtr<NFwd::IPageLoadingLogic> line) - : Room(room) - , Store(std::move(store)) + : Room(room) + , Store(std::move(store)) , PageLoadingLogic(line) - { - - } - + { + + } + TResult DoLoad(ui32 page, ui64 lower, ui64 upper) noexcept - { - if (std::exchange(Grow, false)) + { + if (std::exchange(Grow, false)) PageLoadingLogic->Forward(this, upper); - - for (auto &seq: Fetch) { + + for (auto &seq: Fetch) { NPageCollection::TLoadedPage page(seq, *Store->GetPage(Room, seq)); - + PageLoadingLogic->Apply({ &page, 1 }); /* will move data */ - } - - Fetch.clear(); - + } + + Fetch.clear(); + auto got = PageLoadingLogic->Handle(this, page, lower); - - Y_VERIFY((Grow = got.Grow) || Fetch || got.Page); - - return { got.Need, got.Page }; - } - - private: + + Y_VERIFY((Grow = got.Grow) || Fetch || got.Page); + + return { got.Need, got.Page }; + } + + private: ui64 AddToQueue(TPageId pageId, ui16 /* type */) noexcept override - { - Fetch.push_back(pageId); - + { + Fetch.push_back(pageId); + return Store->GetPage(Room, pageId)->size(); - } - - private: - const ui32 Room = Max<ui32>(); - TVector<TPageId> Fetch; + } + + private: + const ui32 Room = Max<ui32>(); + TVector<TPageId> Fetch; TIntrusiveConstPtr<TStore> Store; TAutoPtr<NFwd::IPageLoadingLogic> PageLoadingLogic; - bool Grow = false; - }; - - public: - using TTags = TArrayRef<const ui32>; - - TForwardEnv(ui64 raLo, ui64 raHi) - : AheadLo(raLo) - , AheadHi(raHi) - { - - } - - TForwardEnv(ui64 raLo, ui64 raHi, TTags keys, ui32 edge) - : AheadLo(raLo) - , AheadHi(raHi) - , Edge(edge) + bool Grow = false; + }; + + public: + using TTags = TArrayRef<const ui32>; + + TForwardEnv(ui64 raLo, ui64 raHi) + : AheadLo(raLo) + , AheadHi(raHi) + { + + } + + TForwardEnv(ui64 raLo, ui64 raHi, TTags keys, ui32 edge) + : AheadLo(raLo) + , AheadHi(raHi) + , Edge(edge) , MemTable(new NFwd::TMemTableHandler(keys, edge, nullptr)) - { - - } - + { + + } + TResult Locate(const TMemTable *memTable, ui64 ref, ui32 tag) noexcept override - { - return + { + return MemTable ? MemTable->Locate(memTable, ref, tag) : MemTableRefLookup(memTable, ref, tag); - } - + } + TResult Locate(const TPart *part, ui64 ref, ELargeObj lob) noexcept override - { + { auto* partStore = CheckedCast<const TPartStore*>(part); if ((lob != ELargeObj::Extern && lob != ELargeObj::Outer) || (ref >> 32)) { Y_Fail("Invalid ref ELargeObj{" << int(lob) << ", " << ref << "}"); - } - + } + const auto room = (lob == ELargeObj::Extern) ? partStore->Store->GetExternRoom() : partStore->Store->GetOuterRoom(); - - return Get(part, room).DoLoad(ref, AheadLo, AheadHi); - } - + + return Get(part, room).DoLoad(ref, AheadLo, AheadHi); + } + const TSharedData* TryGetPage(const TPart* part, TPageId pageId, TGroupId groupId) override - { + { auto* partStore = CheckedCast<const TPartStore*>(part); Y_VERIFY(groupId.Index < partStore->Store->GetGroupCount()); ui32 room = (groupId.Historic ? partStore->Store->GetRoomCount() : 0) + groupId.Index; return Get(part, room).DoLoad(pageId, AheadLo, AheadHi).Page; - } - - private: + } + + private: TPageLoadingQueue& Get(const TPart *part, ui32 room) noexcept - { + { auto* partStore = CheckedCast<const TPartStore*>(part); - + auto& slots = Parts[part]; if (slots.empty()) { slots.reserve(partStore->Store->GetRoomCount() + part->HistoricIndexes.size()); @@ -262,54 +262,54 @@ namespace NTest { slots.push_back(Settle(partStore, group, new NFwd::TCache(partStore->GetGroupIndex(groupId)))); } } - + Y_VERIFY(room < slots.size()); - + return Queues.at(slots[room]); - } - + } + TSlot Settle(const TPartStore *part, ui16 room, NFwd::IPageLoadingLogic *line) - { - if (line) { + { + if (line) { Queues.emplace_back(part->Store, room, line); - + return Queues.size() - 1; - } else { - return Max<TSlot>(); /* Will fail on access in Head(...) */ - } - } - + } else { + return Max<TSlot>(); /* Will fail on access in Head(...) */ + } + } + NFwd::IPageLoadingLogic* MakeExtern(const TPartStore *part) const noexcept - { - if (auto &large = part->Large) { - Y_VERIFY(part->Blobs, "Part has frames but not blobs"); - - TVector<ui32> edges(large->Stats().Tags.size(), Edge); - + { + if (auto &large = part->Large) { + Y_VERIFY(part->Blobs, "Part has frames but not blobs"); + + TVector<ui32> edges(large->Stats().Tags.size(), Edge); + return new NFwd::TBlobs(large, TSlices::All(), edges, false); - } else - return nullptr; - } - + } else + return nullptr; + } + NFwd::IPageLoadingLogic* MakeOuter(const TPart *part) const noexcept - { - if (auto &small = part->Small) { + { + if (auto &small = part->Small) { TVector<ui32> edge(small->Stats().Tags.size(), Max<ui32>()); - + return new NFwd::TBlobs(small, TSlices::All(), edge, false); - } else - return nullptr; - } - - private: - const ui64 AheadLo = 0; - const ui64 AheadHi = 0; - const ui32 Edge = Max<ui32>(); + } else + return nullptr; + } + + private: + const ui64 AheadLo = 0; + const ui64 AheadHi = 0; + const ui32 Edge = Max<ui32>(); TDeque<TPageLoadingQueue> Queues; TMap<const TPart*, TSlotVec> Parts; TAutoPtr<NFwd::TMemTableHandler> MemTable; /* Wrapper for memable blobs */ - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/test_iter.h b/ydb/core/tablet_flat/test/libs/table/test_iter.h index f4010ab2b6..192befbfb3 100644 --- a/ydb/core/tablet_flat/test/libs/table/test_iter.h +++ b/ydb/core/tablet_flat/test/libs/table/test_iter.h @@ -1,134 +1,134 @@ -#pragma once - -#include "test_steps.h" -#include "test_pretty.h" -#include "test_part.h" +#pragma once + +#include "test_steps.h" +#include "test_pretty.h" +#include "test_part.h" #include <ydb/core/tablet_flat/test/libs/rows/cook.h> #include <ydb/core/tablet_flat/test/libs/rows/tool.h> - + #include <library/cpp/testing/unittest/registar.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - - template<typename TWrap, typename TEggs> - class TChecker: public TSteps<TChecker<TWrap, TEggs>> { - public: - using TBase = TSteps<TChecker<TWrap, TEggs>>; - using TSub = decltype(std::declval<TWrap>().Get()); - - struct TConf { - TConf() = default; - + +namespace NKikimr { +namespace NTable { +namespace NTest { + + template<typename TWrap, typename TEggs> + class TChecker: public TSteps<TChecker<TWrap, TEggs>> { + public: + using TBase = TSteps<TChecker<TWrap, TEggs>>; + using TSub = decltype(std::declval<TWrap>().Get()); + + struct TConf { + TConf() = default; + TConf(TAutoPtr<IPages> env, ui64 retry = 0, bool erased = true) - : Env(env) - , Retry(retry) - , Erased(erased) - { - - } - + : Env(env) + , Retry(retry) + , Erased(erased) + { + + } + TAutoPtr<IPages> Env; - ui64 Retry = 0; + ui64 Retry = 0; bool Erased = true; /* do not hide ERowOp::Erase */ - }; - - template<typename ... TArgs> - TChecker(const TEggs &eggs, TConf conf, TArgs && ...args) + }; + + template<typename ... TArgs> + TChecker(const TEggs &eggs, TConf conf, TArgs && ...args) : Retries(Max(conf.Retry, ui64(1) + conf.Retry)) - , Erased(conf.Erased) - , Env(conf.Env ? conf.Env : new TTestEnv) - , Wrap(eggs, std::forward<TArgs>(args)...) - , Scheme(*Wrap.Scheme) - { - - } - - const TSub operator->() const noexcept - { - return Wrap.Get(); - } - - TWrap& operator*() noexcept - { - return Wrap; - } - - template<typename TEnv> + , Erased(conf.Erased) + , Env(conf.Env ? conf.Env : new TTestEnv) + , Wrap(eggs, std::forward<TArgs>(args)...) + , Scheme(*Wrap.Scheme) + { + + } + + const TSub operator->() const noexcept + { + return Wrap.Get(); + } + + TWrap& operator*() noexcept + { + return Wrap; + } + + template<typename TEnv> TAutoPtr<TEnv> Displace(TAutoPtr<IPages> env) noexcept - { - auto *origin = std::exchange(Env, env).Release(); - auto *casted = dynamic_cast<TEnv*>(origin); - - Y_VERIFY(!origin || casted, "Cannot cast IPages to given env"); - - return casted; - } - + { + auto *origin = std::exchange(Env, env).Release(); + auto *casted = dynamic_cast<TEnv*>(origin); + + Y_VERIFY(!origin || casted, "Cannot cast IPages to given env"); + + return casted; + } + TChecker& ReplaceEnv(TAutoPtr<IPages> env) - { - return Displace<IPages>(env), *this; - } - - template<typename ...TArgs> - inline TChecker& IsN(TArgs&&...args) - { + { + return Displace<IPages>(env), *this; + } + + template<typename ...TArgs> + inline TChecker& IsN(TArgs&&...args) + { return IsOpN(ERowOp::Absent, std::forward<TArgs>(args)...); - } - - template<typename ...TArgs> + } + + template<typename ...TArgs> inline TChecker& IsOpN(ERowOp op, TArgs&&...args) - { - auto row = *TNatural(Scheme).Col(std::forward<TArgs>(args)...); - - return Is(row, true, op); - } - - template<typename ...TArgs> - inline TChecker& HasN(TArgs&&...args) - { - return Has(*TNatural(Scheme).Col(std::forward<TArgs>(args)...)); - } - - template<typename ...TArgs> - TChecker& Has(const TRow &row, const TArgs& ... left) - { - return Has(row), Has(left...); - } - - TChecker& Has(const TRow &row) - { + { + auto row = *TNatural(Scheme).Col(std::forward<TArgs>(args)...); + + return Is(row, true, op); + } + + template<typename ...TArgs> + inline TChecker& HasN(TArgs&&...args) + { + return Has(*TNatural(Scheme).Col(std::forward<TArgs>(args)...)); + } + + template<typename ...TArgs> + TChecker& Has(const TRow &row, const TArgs& ... left) + { + return Has(row), Has(left...); + } + + TChecker& Has(const TRow &row) + { return Seek(row, ESeek::Exact).Is(row, true, ERowOp::Absent); - } - - TChecker& NoVal(const TRow &row) - { + } + + TChecker& NoVal(const TRow &row) + { return Seek(row, ESeek::Exact).Is(row, false, ERowOp::Absent); - } - - template<typename ...TArgs> - TChecker& NoKey(const TRow &row, const TArgs& ... left) - { - return NoKey(row, true), NoKey(left...); - } - - TChecker& NoKey(const TRow &row, bool erased = true) - { - Seek(row, ESeek::Exact); - + } + + template<typename ...TArgs> + TChecker& NoKey(const TRow &row, const TArgs& ... left) + { + return NoKey(row, true), NoKey(left...); + } + + TChecker& NoKey(const TRow &row, bool erased = true) + { + Seek(row, ESeek::Exact); + return erased ? Is(EReady::Gone) : Is(row, true, ERowOp::Erase); - } - + } + template<typename TListType> TChecker& IsTheSame(const TListType &list) - { - Seek({ } , ESeek::Lower); - - return Is(list.begin(), list.end()); - } - - template<typename TIter> + { + Seek({ } , ESeek::Lower); + + return Is(list.begin(), list.end()); + } + + template<typename TIter> TChecker& IsTheSame(const TIter begin, const TIter end) { Seek({ }, ESeek::Lower); @@ -137,69 +137,69 @@ namespace NTest { } template<typename TIter> - TChecker& Is(TIter it, const TIter end) - { + TChecker& Is(TIter it, const TIter end) + { for (; it != end; ++it) Is(*it, true, ERowOp::Absent).Next(); - - return *this; - } - - TChecker& Seek(const TRow &tagged, ESeek seek) - { - return Make(TRowTool(Scheme).LookupKey(tagged), seek); - } - + + return *this; + } + + TChecker& Seek(const TRow &tagged, ESeek seek) + { + return Make(TRowTool(Scheme).LookupKey(tagged), seek); + } + TChecker& SeekAgain(const TRow &tagged, ESeek seek) - { + { return Make(TRowTool(Scheme).LookupKey(tagged), seek, /* make = */ false); } - + TChecker& Make(const TRawVals rawkey, const ESeek seek, bool make = true) { if (make) { Wrap.Make(Env.Get()); } - for (bool first = true; ; first = false) { - for (Hoped = 0; Hoped < Retries; Hoped++) { - Ready = first ? Wrap.Seek(rawkey, seek) : Wrap.Next(); - - if (Ready != EReady::Page) break; - } - - if (Ready != EReady::Data || Erased) { - break; + for (bool first = true; ; first = false) { + for (Hoped = 0; Hoped < Retries; Hoped++) { + Ready = first ? Wrap.Seek(rawkey, seek) : Wrap.Next(); + + if (Ready != EReady::Page) break; + } + + if (Ready != EReady::Data || Erased) { + break; } else if (Wrap.Apply().GetRowState() != ERowOp::Erase) { - break; /* Skip technical rows */ - } else if (seek == ESeek::Exact) { - Ready = EReady::Gone; - - break; /* emulation of absent row */ - } - } - - return *this; - } - - TChecker& Next() - { - while (true) { - for (Hoped = 0; Hoped < Retries; Hoped++) { - Ready = Wrap.Next(); - - if (Ready != EReady::Page) break; - } - - if (Ready != EReady::Data || Erased) { - break; + break; /* Skip technical rows */ + } else if (seek == ESeek::Exact) { + Ready = EReady::Gone; + + break; /* emulation of absent row */ + } + } + + return *this; + } + + TChecker& Next() + { + while (true) { + for (Hoped = 0; Hoped < Retries; Hoped++) { + Ready = Wrap.Next(); + + if (Ready != EReady::Page) break; + } + + if (Ready != EReady::Data || Erased) { + break; } else if (Wrap.Apply().GetRowState() != ERowOp::Erase) { - break; /* Skip technical rows */ - } - } - - return *this; - } - + break; /* Skip technical rows */ + } + } + + return *this; + } + TChecker& Ver(TRowVersion rowVersion) { Y_VERIFY(Erased, "Working with versions needs Erased == true"); @@ -249,49 +249,49 @@ namespace NTest { } TChecker& Is(const TRow &row, bool same = true, ERowOp op = ERowOp::Absent) - { - if (EReady::Gone == Ready) { - TBase::Log() - << "No row: " << TRowTool(Scheme).Describe(row) << Endl; - - UNIT_ASSERT(false); - } - - Is(EReady::Data); - - const auto &state = Wrap.Apply(); - const auto &remap = Wrap.Remap(); + { + if (EReady::Gone == Ready) { + TBase::Log() + << "No row: " << TRowTool(Scheme).Describe(row) << Endl; + + UNIT_ASSERT(false); + } + + Is(EReady::Data); + + const auto &state = Wrap.Apply(); + const auto &remap = Wrap.Remap(); const bool keys = (op == ERowOp::Erase); - - bool success = true; - + + bool success = true; + if (op != ERowOp::Absent && op != state.GetRowState()) { - TBase::Log() - << "Row state is " << (int)state.GetRowState() + TBase::Log() + << "Row state is " << (int)state.GetRowState() << ", expected ERowOp " << (int)op - << Endl; - - success = false; - - } else if (TRowTool(Scheme).Cmp(row, state, remap, keys) != same) { - TBase::Log() - << "Row missmatch, got " - << (int)state.GetRowState() - << ": " << NFmt::TCells(*state, remap, DbgRegistry()) - << ", expect " << TRowTool(Scheme).Describe(row) - << Endl; - - success = false; - } - - UNIT_ASSERT(success); - - return *this; - } - - TChecker& Is(EReady ready) - { - if (ready != Ready) { + << Endl; + + success = false; + + } else if (TRowTool(Scheme).Cmp(row, state, remap, keys) != same) { + TBase::Log() + << "Row missmatch, got " + << (int)state.GetRowState() + << ": " << NFmt::TCells(*state, remap, DbgRegistry()) + << ", expect " << TRowTool(Scheme).Describe(row) + << Endl; + + success = false; + } + + UNIT_ASSERT(success); + + return *this; + } + + TChecker& Is(EReady ready) + { + if (ready != Ready) { if (Ready == EReady::Data) { const auto &state = Wrap.Apply(); const auto &remap = Wrap.Remap(); @@ -302,29 +302,29 @@ namespace NTest { << Endl; } - TBase::Log() - << "Iterator has " - << " EReady " << static_cast<int>(Ready) - << ", expected " << static_cast<int>(ready) - << " after " << Hoped << " hopes of " << Retries - << Endl; - - UNIT_ASSERT(false); - } - - return *this; - } - - private: - const ui64 Retries = 1; - const ui64 Erased = true; - ui64 Hoped = 0; - EReady Ready = EReady::Gone; + TBase::Log() + << "Iterator has " + << " EReady " << static_cast<int>(Ready) + << ", expected " << static_cast<int>(ready) + << " after " << Hoped << " hopes of " << Retries + << Endl; + + UNIT_ASSERT(false); + } + + return *this; + } + + private: + const ui64 Retries = 1; + const ui64 Erased = true; + ui64 Hoped = 0; + EReady Ready = EReady::Gone; TAutoPtr<IPages> Env; - TWrap Wrap; - const TRowScheme &Scheme; - }; - -} -} -} + TWrap Wrap; + const TRowScheme &Scheme; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/test_make.h b/ydb/core/tablet_flat/test/libs/table/test_make.h index 8bd0e14d6d..67f49d43c7 100644 --- a/ydb/core/tablet_flat/test/libs/table/test_make.h +++ b/ydb/core/tablet_flat/test/libs/table/test_make.h @@ -1,132 +1,132 @@ -#pragma once - -#include "test_part.h" -#include "test_writer.h" -#include "test_cooker.h" +#pragma once + +#include "test_part.h" +#include "test_writer.h" +#include "test_cooker.h" #include <ydb/core/tablet_flat/test/libs/rows/mass.h> - + #include <ydb/core/tablet_flat/flat_mem_warm.h> #include <ydb/core/tablet_flat/flat_row_nulls.h> #include <ydb/core/tablet_flat/flat_table_subset.h> - -#include <util/generic/xrange.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - - struct TMake { - using TScheme = TRowScheme; - - struct IBand { - virtual ~IBand() = default; - virtual void Add(const TRow&) noexcept = 0; - }; - - struct TPart : IBand { + +#include <util/generic/xrange.h> + +namespace NKikimr { +namespace NTable { +namespace NTest { + + struct TMake { + using TScheme = TRowScheme; + + struct IBand { + virtual ~IBand() = default; + virtual void Add(const TRow&) noexcept = 0; + }; + + struct TPart : IBand { TPart(TIntrusiveConstPtr<TScheme> scheme, TEpoch epoch, ui32, NPage::TConf conf, const TLogoBlobID &token) - : Epoch(epoch) + : Epoch(epoch) , Cook(std::move(scheme), conf, token, epoch) - { - - } - - void Add(const TRow &row) noexcept override - { - Cook.Add(row); - } - + { + + } + + void Add(const TRow &row) noexcept override + { + Cook.Add(row); + } + const TEpoch Epoch; - TPartCook Cook; - }; - - struct TMem : IBand { + TPartCook Cook; + }; + + struct TMem : IBand { TMem(TIntrusiveConstPtr<TScheme> scheme, TEpoch epoch, ui32) - : Cooker(std::move(scheme), epoch) - { - - } - - void Add(const TRow &row) noexcept override - { + : Cooker(std::move(scheme), epoch) + { + + } + + void Add(const TRow &row) noexcept override + { Cooker.Add(row, ERowOp::Upsert); - } - - TCooker Cooker; - }; - - using THash = std::function<ui32(const TRow&)>; - - TMake(const NTest::TMass &mass, NPage::TConf pages = { }) - : Pages(pages) - , Saved(mass.Saved) - , Scheme(mass.Model->Scheme) - { - - } - + } + + TCooker Cooker; + }; + + using THash = std::function<ui32(const TRow&)>; + + TMake(const NTest::TMass &mass, NPage::TConf pages = { }) + : Pages(pages) + , Saved(mass.Saved) + , Scheme(mass.Model->Scheme) + { + + } + TIntrusivePtr<TMemTable> Mem() - { + { return TCooker(Scheme, TEpoch::Zero()).Add(Saved, ERowOp::Upsert).Unwrap(); - } - - TPartEggs Part() - { - TPartCook cook(Scheme, Pages); - - return cook.Add(Saved.begin(), Saved.end()).Finish(); - } - + } + + TPartEggs Part() + { + TPartCook cook(Scheme, Pages); + + return cook.Add(Saved.begin(), Saved.end()).Finish(); + } + TAutoPtr<TSubset> Mixed(ui32 frozen, ui32 flatten, THash hash) - { + { TDeque<TAutoPtr<IBand>> bands; - + for (auto it: xrange(flatten)) { TLogoBlobID token(0, 0, ++Serial, 0, 0, 0); bands.emplace_back(new TPart(Scheme, TEpoch::FromIndex(bands.size()), it, Pages, token)); } - - for (auto it: xrange(frozen)) + + for (auto it: xrange(frozen)) bands.emplace_back(new TMem(Scheme, TEpoch::FromIndex(bands.size()), it)); - - if (const auto slots = bands.size()) { - for (auto &row: Saved) - bands[hash(row) % slots]->Add(row); - } - + + if (const auto slots = bands.size()) { + for (auto &row: Saved) + bands[hash(row) % slots]->Add(row); + } + TAutoPtr<TSubset> subset = new TSubset(TEpoch::FromIndex(bands.size()), Scheme); - - for (auto &one: bands) { - if (auto *mem = dynamic_cast<TMem*>(one.Get())) { - auto table = mem->Cooker.Unwrap(); - - Y_VERIFY(table->GetRowCount(), "Got empty IBand"); - + + for (auto &one: bands) { + if (auto *mem = dynamic_cast<TMem*>(one.Get())) { + auto table = mem->Cooker.Unwrap(); + + Y_VERIFY(table->GetRowCount(), "Got empty IBand"); + subset->Frozen.emplace_back(std::move(table), table->Immediate()); - } else if (auto *part_ = dynamic_cast<TPart*>(one.Get())) { + } else if (auto *part_ = dynamic_cast<TPart*>(one.Get())) { auto eggs = part_->Cook.Finish(); - - if (eggs.Parts.size() != 1) { - Y_Fail("Unexpected " << eggs.Parts.size() << " parts"); + + if (eggs.Parts.size() != 1) { + Y_Fail("Unexpected " << eggs.Parts.size() << " parts"); } - - subset->Flatten.push_back( + + subset->Flatten.push_back( { eggs.At(0), nullptr, eggs.At(0)->Slices }); - } else { - Y_FAIL("Unknown IBand writer type, internal error"); - } - } - - return subset; - } - - private: - const NPage::TConf Pages { true, 7 * 1024 }; - ui32 Serial = 0; - const TRowsHeap &Saved; + } else { + Y_FAIL("Unknown IBand writer type, internal error"); + } + } + + return subset; + } + + private: + const NPage::TConf Pages { true, 7 * 1024 }; + ui32 Serial = 0; + const TRowsHeap &Saved; TIntrusiveConstPtr<TScheme> Scheme; - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/test_mixer.h b/ydb/core/tablet_flat/test/libs/table/test_mixer.h index f14ab33212..aff94d5703 100644 --- a/ydb/core/tablet_flat/test/libs/table/test_mixer.h +++ b/ydb/core/tablet_flat/test/libs/table/test_mixer.h @@ -1,61 +1,61 @@ -#pragma once - -#include <util/random/mersenne.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - - class TRow; - - struct TMixerOne { - ui32 operator()(const TRow&) noexcept - { - return 0; - } - }; - - struct TMixerRnd { - TMixerRnd(ui32 num) : Num(num) { } - - ui32 operator()(const TRow&) noexcept - { - return Random.Uniform(Num); - } - - private: - const ui32 Num = 1; - TMersenne<ui64> Random; - }; - - struct TMixerSeq { - TMixerSeq(ui32 num, ui64 rows) - : Num(num) - , Base(rows / num) - , Skip(rows % num) - { - - } - - ui32 operator()(const TRow&) noexcept - { - if (Buck-- == 0) { - ui64 one = (Skip && Skip > Random.Uniform(Num) ? 1 : 0); - - Buck = Base + one, Skip -= one, Hash++; - } - - return Min(Hash, Num - 1); - } - - private: - const ui32 Num = 1; - ui64 Base = Max<ui64>(); - ui64 Skip = 0; - ui64 Buck = 0; - ui32 Hash = Max<ui32>(); - TMersenne<ui64> Random; - }; -} -} -} +#pragma once + +#include <util/random/mersenne.h> + +namespace NKikimr { +namespace NTable { +namespace NTest { + + class TRow; + + struct TMixerOne { + ui32 operator()(const TRow&) noexcept + { + return 0; + } + }; + + struct TMixerRnd { + TMixerRnd(ui32 num) : Num(num) { } + + ui32 operator()(const TRow&) noexcept + { + return Random.Uniform(Num); + } + + private: + const ui32 Num = 1; + TMersenne<ui64> Random; + }; + + struct TMixerSeq { + TMixerSeq(ui32 num, ui64 rows) + : Num(num) + , Base(rows / num) + , Skip(rows % num) + { + + } + + ui32 operator()(const TRow&) noexcept + { + if (Buck-- == 0) { + ui64 one = (Skip && Skip > Random.Uniform(Num) ? 1 : 0); + + Buck = Base + one, Skip -= one, Hash++; + } + + return Min(Hash, Num - 1); + } + + private: + const ui32 Num = 1; + ui64 Base = Max<ui64>(); + ui64 Skip = 0; + ui64 Buck = 0; + ui32 Hash = Max<ui32>(); + TMersenne<ui64> Random; + }; +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/test_part.h b/ydb/core/tablet_flat/test/libs/table/test_part.h index e1dde28eea..6c7eb5146a 100644 --- a/ydb/core/tablet_flat/test/libs/table/test_part.h +++ b/ydb/core/tablet_flat/test/libs/table/test_part.h @@ -1,6 +1,6 @@ -#pragma once - -#include "test_store.h" +#pragma once + +#include "test_store.h" #include <ydb/core/tablet_flat/flat_table_misc.h> #include <ydb/core/tablet_flat/flat_table_part.h> #include <ydb/core/tablet_flat/flat_table_subset.h> @@ -10,14 +10,14 @@ #include <ydb/core/tablet_flat/flat_fwd_blobs.h> #include <ydb/core/tablet_flat/flat_row_scheme.h> #include <ydb/core/tablet_flat/util_fmt_abort.h> - -#include <util/generic/cast.h> -#include <util/generic/set.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - + +#include <util/generic/cast.h> +#include <util/generic/set.h> + +namespace NKikimr { +namespace NTable { +namespace NTest { + class TPartStore : public NTable::TPart { protected: TPartStore(const TPartStore& src, NTable::TEpoch epoch) @@ -26,21 +26,21 @@ namespace NTest { , Slices(src.Slices) { } - public: + public: TPartStore(TIntrusiveConstPtr<TStore> store, TLogoBlobID label, TEgg egg, TStat stat, TIntrusiveConstPtr<TSlices> slices) - : TPart(label, egg, stat) - , Store(std::move(store)) + : TPart(label, egg, stat) + , Store(std::move(store)) , Slices(std::move(slices)) - { - - } - - ui64 DataSize() const override - { + { + + } + + ui64 DataSize() const override + { return Store->PageCollectionBytes(0); - } - + } + ui64 BackingSize() const override { return Store->PageCollectionBytes(0) + Store->PageCollectionBytes(Store->GetOuterRoom()); @@ -58,72 +58,72 @@ namespace NTest { const TIntrusiveConstPtr<TStore> Store; const TIntrusiveConstPtr<TSlices> Slices; - }; - - class TTestEnv: public IPages { - public: + }; + + class TTestEnv: public IPages { + public: TResult Locate(const TMemTable *memTable, ui64 ref, ui32 tag) noexcept override - { + { return MemTableRefLookup(memTable, ref, tag); - } - + } + TResult Locate(const TPart *part, ui64 ref, ELargeObj lob) noexcept override - { + { auto* partStore = CheckedCast<const TPartStore*>(part); if ((lob != ELargeObj::Extern && lob != ELargeObj::Outer) || (ref >> 32)) { Y_Fail("Invalid ref ELargeObj{" << int(lob) << ", " << ref << "}"); - } - + } + ui32 room = (lob == ELargeObj::Extern) ? partStore->Store->GetExternRoom() : partStore->Store->GetOuterRoom(); return { true, Get(part, room, ref) }; - } + } const TSharedData* TryGetPage(const TPart *part, TPageId ref, TGroupId groupId) override { return Get(part, groupId.Index, ref); } - + private: const TSharedData* Get(const TPart *part, ui32 room, ui32 ref) const - { - Y_VERIFY(ref != Max<ui32>(), "Got invalid page reference"); - + { + Y_VERIFY(ref != Max<ui32>(), "Got invalid page reference"); + return CheckedCast<const TPartStore*>(part)->Store->GetPage(room, ref); - } - }; - - struct TPartEggs { + } + }; + + struct TPartEggs { const TIntrusiveConstPtr<TPartStore>& At(size_t num) const noexcept - { - return Parts.at(num); - } + { + return Parts.at(num); + } const TIntrusiveConstPtr<TPartStore>& Lone() const noexcept - { - Y_VERIFY(Parts.size() == 1, "Need egg with one part inside"); - - return Parts[0]; - } - - bool NoResult() const noexcept - { - return Written == nullptr; /* compaction was aborted */ - } - + { + Y_VERIFY(Parts.size() == 1, "Need egg with one part inside"); + + return Parts[0]; + } + + bool NoResult() const noexcept + { + return Written == nullptr; /* compaction was aborted */ + } + TPartView ToPartView() const noexcept - { + { return { Lone(), nullptr, Lone()->Slices }; - } - + } + TAutoPtr<TWritten> Written; TIntrusiveConstPtr<TRowScheme> Scheme; TVector<TIntrusiveConstPtr<TPartStore>> Parts; - }; - + }; + TString DumpPart(const TPartStore&, ui32 depth = 10) noexcept; - -}}} + +}}} diff --git a/ydb/core/tablet_flat/test/libs/table/test_pretty.h b/ydb/core/tablet_flat/test/libs/table/test_pretty.h index e5f5287d24..7546790aa3 100644 --- a/ydb/core/tablet_flat/test/libs/table/test_pretty.h +++ b/ydb/core/tablet_flat/test/libs/table/test_pretty.h @@ -1,15 +1,15 @@ -#pragma once - +#pragma once + #include <ydb/core/tablet_flat/flat_dbase_scheme.h> #include <ydb/core/tablet_flat/flat_row_remap.h> #include <ydb/core/tablet_flat/flat_mem_warm.h> #include <ydb/core/scheme/scheme_type_id.h> - -namespace NKikimr { -namespace NTable { - + +namespace NKikimr { +namespace NTable { + TString PrintRow(const TDbTupleRef& row); - TString PrintRow(const TMemIt&); - -} -} + TString PrintRow(const TMemIt&); + +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/test_steps.h b/ydb/core/tablet_flat/test/libs/table/test_steps.h index d4972ec94f..163c93efba 100644 --- a/ydb/core/tablet_flat/test/libs/table/test_steps.h +++ b/ydb/core/tablet_flat/test/libs/table/test_steps.h @@ -1,36 +1,36 @@ -#pragma once - -#include <util/system/yassert.h> -#include <util/stream/output.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - - template<typename TImpl> - class TSteps { - public: - TImpl& To(size_t seq) noexcept - { - Y_VERIFY(seq >= Seq, "Invalid sequence flow"); - - Seq = seq; - - return static_cast<TImpl&>(*this); - } - +#pragma once + +#include <util/system/yassert.h> +#include <util/stream/output.h> + +namespace NKikimr { +namespace NTable { +namespace NTest { + + template<typename TImpl> + class TSteps { + public: + TImpl& To(size_t seq) noexcept + { + Y_VERIFY(seq >= Seq, "Invalid sequence flow"); + + Seq = seq; + + return static_cast<TImpl&>(*this); + } + IOutputStream& Log() const noexcept - { - Cerr << "On " << Seq << ": "; - - return Cerr; - } - - size_t CurrentStep() const noexcept { return Seq; } - - private: - size_t Seq = 0; - }; -} -} -} + { + Cerr << "On " << Seq << ": "; + + return Cerr; + } + + size_t CurrentStep() const noexcept { return Seq; } + + private: + size_t Seq = 0; + }; +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/test_store.h b/ydb/core/tablet_flat/test/libs/table/test_store.h index bdd506663a..d06cc579e9 100644 --- a/ydb/core/tablet_flat/test/libs/table/test_store.h +++ b/ydb/core/tablet_flat/test/libs/table/test_store.h @@ -1,95 +1,95 @@ -#pragma once - +#pragma once + #include <ydb/core/tablet_flat/flat_page_label.h> #include <ydb/core/tablet_flat/flat_part_iface.h> #include <ydb/core/tablet_flat/flat_sausage_misc.h> #include <ydb/core/tablet_flat/flat_util_binary.h> #include <ydb/core/tablet_flat/util_deref.h> - -#include <util/generic/xrange.h> -#include <array> - -namespace NKikimr { -namespace NTable { -namespace NTest { - + +#include <util/generic/xrange.h> +#include <array> + +namespace NKikimr { +namespace NTable { +namespace NTest { + class TStore : public TAtomicRefCount<TStore> { enum : ui32 { MainPageCollection = 0, }; - public: + public: using TData = const TSharedData; - - struct TEggs { - bool Rooted; - TData *Index; - TData *Scheme; - TData *Blobs; - TData *ByKey; - TData *Large; - TData *Small; + + struct TEggs { + bool Rooted; + TData *Index; + TData *Scheme; + TData *Blobs; + TData *ByKey; + TData *Large; + TData *Small; TVector<TSharedData> GroupIndexes; TVector<TSharedData> HistoricIndexes; TData *GarbageStats; TData *TxIdStats; - }; - + }; + ui32 GetGroupCount() const noexcept { return Groups; } - + ui32 GetRoomCount() const noexcept { return PageCollections.size(); - } - + } + ui32 GetOuterRoom() const noexcept { return Groups; } - + ui32 GetExternRoom() const noexcept { return Groups + 1; - } - + } + const TSharedData* GetPage(ui32 room, ui32 page) const noexcept - { + { Y_VERIFY(room < PageCollections.size(), "Room is out of bounds"); - + if (page == Max<TPageId>()) return nullptr; return &PageCollections.at(room).at(page); - } - + } + TArrayRef<const TSharedData> PageCollectionArray(ui32 room) const noexcept - { + { Y_VERIFY(room < PageCollections.size(), "Only regular rooms can be used as arr"); return PageCollections[room]; - } - + } + NPageCollection::TGlobId GlobForBlob(ui64 ref) const noexcept - { + { const auto& blob = PageCollections[GetExternRoom()].at(ref); - + return { TLogoBlobID(1, 2, 3, 7, blob.size(), GlobOffset + ref), /* fake group */ 123 }; - } - + } + ui32 PageCollectionPagesCount(ui32 room) const noexcept - { + { return PageCollections.at(room).size(); } - + ui64 PageCollectionBytes(ui32 room) const noexcept { auto &pages = PageCollections.at(room); - return + return std::accumulate(pages.begin(), pages.end(), ui64(0), [](ui64 bytes, const TSharedData &page) { - return bytes + page.size(); - }); - } - + return bytes + page.size(); + }); + } + TData* GetMeta() const noexcept { return Meta ? &Meta : nullptr; @@ -124,86 +124,86 @@ namespace NTest { }; } - void Dump(IOutputStream &stream) const noexcept - { - NUtil::NBin::TOut out(stream); - + void Dump(IOutputStream &stream) const noexcept + { + NUtil::NBin::TOut out(stream); + if (Groups > 1) { Y_FAIL("Cannot dump TStore with multiple column groups"); } else if (!PageCollections[MainPageCollection]) { Y_FAIL("Cannot dump TStore with empty leader page collection"); } else if (PageCollections[GetOuterRoom()] || PageCollections[GetExternRoom()]) { Y_FAIL("TStore has auxillary rooms, cannot be dumped"); - } - - /* Dump pages as is, without any special markup as it already + } + + /* Dump pages as is, without any special markup as it already has generic labels with sufficient data to restore page collection */ - + const auto& pages = PageCollections.at(MainPageCollection); - + for (auto it: xrange(pages.size())) { auto got = NPage::THello().Read(pages[it], EPage::Undef); - + Y_VERIFY(got.Page.end() == pages[it].end()); out.Put(pages[it]); - } - } - + } + } + static TIntrusivePtr<TStore> Restore(IInputStream &in) - { + { TIntrusivePtr<TStore> storage(new TStore(1)); - NPage::TLabel label; - - while (auto got = in.Load(&label, sizeof(label))) { - Y_VERIFY(got == sizeof(label), "Invalid pages stream"); - + NPage::TLabel label; + + while (auto got = in.Load(&label, sizeof(label))) { + Y_VERIFY(got == sizeof(label), "Invalid pages stream"); + TSharedData to = TSharedData::Uninitialized(label.Size); - + *TDeref<NPage::TLabel>::At(to.mutable_begin(), 0) = label; - + auto *begin = TDeref<char>::At(to.mutable_begin(), sizeof(label)); - + got = in.Load(begin, to.mutable_end() - begin); - - if (got + sizeof(NPage::TLabel) != label.Size) { - Y_FAIL("Stausage loading stalled in middle of page"); - } else if (label.Type == EPage::Scheme) { - /* Required for Read(Evolution < 16), hack for old style - scheme pages without leading label. It was ecoded in - sample blobs with artificial label. - */ + + if (got + sizeof(NPage::TLabel) != label.Size) { + Y_FAIL("Stausage loading stalled in middle of page"); + } else if (label.Type == EPage::Scheme) { + /* Required for Read(Evolution < 16), hack for old style + scheme pages without leading label. It was ecoded in + sample blobs with artificial label. + */ to = TSharedData::Copy(to.Slice(sizeof(NPage::TLabel))); - } - + } + storage->Write(std::move(to), label.Type, 0); - } - + } + storage->Finish(); - return storage; - } - + return storage; + } + TPageId WriteOuter(TSharedData page) noexcept - { + { Y_VERIFY(!Finished, "This store is already finished"); - + auto& pages = PageCollections[GetOuterRoom()]; - + pages.emplace_back(std::move(page)); return pages.size() - 1; - } - + } + TPageId Write(TSharedData page, EPage type, ui32 group) noexcept - { + { Y_VERIFY(group < PageCollections.size() - 1, "Invalid column group"); Y_VERIFY(!Finished, "This store is already finished"); NPageCollection::Checksum(page); /* will catch uninitialised values */ - + TPageId id = PageCollections[group].size(); PageCollections[group].push_back(std::move(page)); - + if (group == 0) { switch (type) { case EPage::Index: @@ -226,11 +226,11 @@ namespace NTest { default: break; } - } - - return id; - } - + } + + return id; + } + void WriteInplace(TPageId page, TArrayRef<const char> body) noexcept { Y_VERIFY(page == Scheme); @@ -239,16 +239,16 @@ namespace NTest { } NPageCollection::TGlobId WriteLarge(TSharedData data) noexcept - { + { Y_VERIFY(!Finished, "This store is already finished"); - + auto& pages = PageCollections[GetExternRoom()]; pages.emplace_back(std::move(data)); return GlobForBlob(pages.size() - 1); - } - + } + void Finish() noexcept { Y_VERIFY(!Finished, "Cannot finish test store more than once"); @@ -266,23 +266,23 @@ namespace NTest { return GlobOffset + pages.size(); } - private: + private: const size_t Groups; const ui32 GlobOffset; TVector<TVector<TSharedData>> PageCollections; - - /*_ Sometimes will be replaced just with one root TPageId */ - + + /*_ Sometimes will be replaced just with one root TPageId */ + TVector<TPageId> Indexes; - TPageId Scheme = Max<TPageId>(); - TPageId Large = Max<TPageId>(); - TPageId Globs = Max<TPageId>(); - TPageId ByKey = Max<TPageId>(); + TPageId Scheme = Max<TPageId>(); + TPageId Large = Max<TPageId>(); + TPageId Globs = Max<TPageId>(); + TPageId ByKey = Max<TPageId>(); TSharedData Meta; - bool Rooted = false; + bool Rooted = false; bool Finished = false; - }; - -} -} -} + }; + +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/test_wreck.h b/ydb/core/tablet_flat/test/libs/table/test_wreck.h index ae611653be..ef0479574d 100644 --- a/ydb/core/tablet_flat/test/libs/table/test_wreck.h +++ b/ydb/core/tablet_flat/test/libs/table/test_wreck.h @@ -1,127 +1,127 @@ -#pragma once - -#include "test_envs.h" +#pragma once + +#include "test_envs.h" #include <ydb/core/tablet_flat/test/libs/rows/mass.h> - -#include <util/random/mersenne.h> -#include <functional> - -namespace NKikimr { -namespace NTable { -namespace NTest { - - enum class EWreck { - Cached = 0, /* take all pages cached in env */ - Evicted = 1, /* simulate random page loads */ - Forward = 2, /* use forward cache loads */ - }; - + +#include <util/random/mersenne.h> +#include <functional> + +namespace NKikimr { +namespace NTable { +namespace NTest { + + enum class EWreck { + Cached = 0, /* take all pages cached in env */ + Evicted = 1, /* simulate random page loads */ + Forward = 2, /* use forward cache loads */ + }; + template<typename TWrap, typename TEggs, EDirection Direction = EDirection::Forward> - class TWreck { - public: - TWreck(const TMass &mass, ui64 seed = 666) - : Mass(mass) - , Rnd(seed) - { - - } - + class TWreck { + public: + TWreck(const TMass &mass, ui64 seed = 666) + : Mass(mass) + , Rnd(seed) + { + + } + template<class... TArgs> void Do(EWreck cache, const TEggs &eggs, TArgs&&... args) - { - if (cache == EWreck::Cached) { - auto make = []() { return new TTestEnv; }; - + { + if (cache == EWreck::Cached) { + auto make = []() { return new TTestEnv; }; + TWrap wrap(eggs, { make(), 0 /* no retries allowed */, false }, std::forward<TArgs>(args)...); - - DoPointReads(wrap), DoRangedScans(wrap, make, true); - - } else if (cache == EWreck::Evicted) { + + DoPointReads(wrap), DoRangedScans(wrap, make, true); + + } else if (cache == EWreck::Evicted) { TWrap wrap(eggs, { nullptr, 66 /* try at most */, false }, std::forward<TArgs>(args)...); - - auto make = [this]() { - return new TFailEnv<decltype(Rnd)>(Rnd, 0.25); - }; - - wrap.template Displace<IPages>(make()); - - DoPointReads(wrap), DoRangedScans(wrap, make, true); - - } else if (cache == EWreck::Forward) { + + auto make = [this]() { + return new TFailEnv<decltype(Rnd)>(Rnd, 0.25); + }; + + wrap.template Displace<IPages>(make()); + + DoPointReads(wrap), DoRangedScans(wrap, make, true); + + } else if (cache == EWreck::Forward) { Y_VERIFY(Direction == EDirection::Forward, "ForwardEnv may only be used with forward iteration"); TWrap wrap(eggs, { nullptr, 4 /* worst case: main, next, groups, blobs */, false }, std::forward<TArgs>(args)...); - - auto make = []() { return new TForwardEnv(512, 1024); }; - - DoRangedScans(wrap, make, false /* only for scans */); - } - } - - void DoPointReads(TWrap &wrap) - { - { /*_ Before test check for existance of all saved rows */ - wrap.To(10); - - for (auto &row: Mass.Saved) wrap.Has(row); - } - - { /*_ ... and absense of skipped keys in produced part */ - wrap.To(12); - - for (auto &row: Mass.Holes) wrap.NoKey(row); - } - - /*_ ... and lower-upper bounds lookups on holes keys */ - for (size_t it = 0; it < 1024; it++) { - wrap.To(10000 + it); - - auto &row = *Mass.Holes.Any(Rnd); - + + auto make = []() { return new TForwardEnv(512, 1024); }; + + DoRangedScans(wrap, make, false /* only for scans */); + } + } + + void DoPointReads(TWrap &wrap) + { + { /*_ Before test check for existance of all saved rows */ + wrap.To(10); + + for (auto &row: Mass.Saved) wrap.Has(row); + } + + { /*_ ... and absense of skipped keys in produced part */ + wrap.To(12); + + for (auto &row: Mass.Holes) wrap.NoKey(row); + } + + /*_ ... and lower-upper bounds lookups on holes keys */ + for (size_t it = 0; it < 1024; it++) { + wrap.To(10000 + it); + + auto &row = *Mass.Holes.Any(Rnd); + if (auto *after = Mass.SnapBy(row, Direction == EDirection::Forward, true)) { - wrap.Seek(row, ESeek::Upper).Is(*after); - wrap.Seek(row, ESeek::Lower).Is(*after); - } else { - wrap.Seek(row, ESeek::Upper).Is(EReady::Gone); - wrap.Seek(row, ESeek::Lower).Is(EReady::Gone); - } - } - - /*_ ... and lower-upper bounds lookups on saved keys */ - for (size_t it = 0; it < 1024; it++) { - auto &row = *Mass.Saved.Any(Rnd); - - wrap.To(20000 + it).Seek(row, ESeek::Lower).Is(row); - + wrap.Seek(row, ESeek::Upper).Is(*after); + wrap.Seek(row, ESeek::Lower).Is(*after); + } else { + wrap.Seek(row, ESeek::Upper).Is(EReady::Gone); + wrap.Seek(row, ESeek::Lower).Is(EReady::Gone); + } + } + + /*_ ... and lower-upper bounds lookups on saved keys */ + for (size_t it = 0; it < 1024; it++) { + auto &row = *Mass.Saved.Any(Rnd); + + wrap.To(20000 + it).Seek(row, ESeek::Lower).Is(row); + if (auto *after = Mass.SnapBy(row, Direction == EDirection::Forward, false)) { - wrap.Seek(row, ESeek::Upper).Is(*after); - } else { - wrap.Seek(row, ESeek::Upper).Is(EReady::Gone); - } - } - - /*_ 3x_xxx Lookups of existing rows, saved collection */ - for (size_t it = 0; it < 8192; it++) - wrap.To(30000 + it).Has(*Mass.Saved.Any(Rnd)); - - /*_ 4x_xxx Lookups of absents rows, holes collection */ - for (size_t it = 0; it < 1024; it++) - wrap.To(40000 + it).NoKey(*Mass.Holes.Any(Rnd)); - - /*_ 5x_xxx +inf lookups logic. It could seem test has lack of it - but inf logic completely implemented in key cmp functions and - isn't related to iterators. Each key cmp functon should have - special tests for its +inf. - */ - } - - void DoRangedScans(TWrap &wrap, std::function<IPages*()> make, bool rnd) - { - auto originEnv = wrap.template Displace<IPages>(make()); - - { /*_ 60_000 Full sequence scan of all saved records */ - wrap.To(60000).Seek({}, ESeek::Lower); - + wrap.Seek(row, ESeek::Upper).Is(*after); + } else { + wrap.Seek(row, ESeek::Upper).Is(EReady::Gone); + } + } + + /*_ 3x_xxx Lookups of existing rows, saved collection */ + for (size_t it = 0; it < 8192; it++) + wrap.To(30000 + it).Has(*Mass.Saved.Any(Rnd)); + + /*_ 4x_xxx Lookups of absents rows, holes collection */ + for (size_t it = 0; it < 1024; it++) + wrap.To(40000 + it).NoKey(*Mass.Holes.Any(Rnd)); + + /*_ 5x_xxx +inf lookups logic. It could seem test has lack of it + but inf logic completely implemented in key cmp functions and + isn't related to iterators. Each key cmp functon should have + special tests for its +inf. + */ + } + + void DoRangedScans(TWrap &wrap, std::function<IPages*()> make, bool rnd) + { + auto originEnv = wrap.template Displace<IPages>(make()); + + { /*_ 60_000 Full sequence scan of all saved records */ + wrap.To(60000).Seek({}, ESeek::Lower); + if constexpr (Direction == EDirection::Reverse) { auto it = Mass.Saved.end(); while (it != Mass.Saved.begin()) { @@ -130,22 +130,22 @@ namespace NTest { } else { for (auto &row: Mass.Saved) wrap.Is(row).Next(); } - - wrap.Is(EReady::Gone); /* should have no more rows */ - } - - /*_ 61_xxx Sequentional reads with random starts */ - - if (rnd) wrap.template Displace<IPages>(make()); - - for (size_t seq = 0; seq < 60; seq++) { - if (!rnd) wrap.template Displace<IPages>(make()); - - ui64 len = Rnd.Uniform(256, 999); - auto it = Mass.Saved.Any(Rnd); - - wrap.To(61000 + seq).Seek(*it, ESeek::Lower); - + + wrap.Is(EReady::Gone); /* should have no more rows */ + } + + /*_ 61_xxx Sequentional reads with random starts */ + + if (rnd) wrap.template Displace<IPages>(make()); + + for (size_t seq = 0; seq < 60; seq++) { + if (!rnd) wrap.template Displace<IPages>(make()); + + ui64 len = Rnd.Uniform(256, 999); + auto it = Mass.Saved.Any(Rnd); + + wrap.To(61000 + seq).Seek(*it, ESeek::Lower); + if constexpr (Direction == EDirection::Reverse) { while (len-- > 0) { wrap.Is(*it).Next(); @@ -158,15 +158,15 @@ namespace NTest { while (len-- > 0 && it != Mass.Saved.end()) wrap.Is(*it++).Next(); } - } - - wrap.template Displace<IPages>(originEnv); - } - - private: - const TMass &Mass; - TMersenne<ui64> Rnd; - }; -} -} -} + } + + wrap.template Displace<IPages>(originEnv); + } + + private: + const TMass &Mass; + TMersenne<ui64> Rnd; + }; +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/test_writer.h b/ydb/core/tablet_flat/test/libs/table/test_writer.h index 5df2014cd6..8ee0fea675 100644 --- a/ydb/core/tablet_flat/test/libs/table/test_writer.h +++ b/ydb/core/tablet_flat/test/libs/table/test_writer.h @@ -1,13 +1,13 @@ -#pragma once - -#include "test_pretty.h" -#include "test_part.h" - +#pragma once + +#include "test_pretty.h" +#include "test_part.h" + #include <ydb/core/tablet_flat/test/libs/rows/cook.h> #include <ydb/core/tablet_flat/test/libs/rows/tool.h> #include <ydb/core/tablet_flat/test/libs/rows/mass.h> #include <ydb/core/tablet_flat/test/libs/rows/layout.h> - + #include <ydb/core/tablet_flat/flat_sausage_grind.h> #include <ydb/core/tablet_flat/flat_abi_check.h> #include <ydb/core/tablet_flat/flat_table_part.h> @@ -15,100 +15,100 @@ #include <ydb/core/tablet_flat/flat_part_scheme.h> #include <ydb/core/tablet_flat/flat_part_writer.h> #include <ydb/core/tablet_flat/protos/flat_table_part.pb.h> - -#include <util/generic/cast.h> -#include <util/stream/mem.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - - class TLoader { /* Test env clone for NTable::TLoader */ - public: + +#include <util/generic/cast.h> +#include <util/stream/mem.h> + +namespace NKikimr { +namespace NTable { +namespace NTest { + + class TLoader { /* Test env clone for NTable::TLoader */ + public: TLoader(TIntrusiveConstPtr<TStore> store, TString overlay) : Store(std::move(store)) - , Overlay(std::move(overlay)) - { - - } - + , Overlay(std::move(overlay)) + { + + } + TIntrusiveConstPtr<TPartStore> Load(const TLogoBlobID token) noexcept - { - using NPage::TFrames; + { + using NPage::TFrames; using NPage::TExtBlobs; - using NPage::TBloom; - + using NPage::TBloom; + Y_VERIFY(Store, "Cannot load from an empty store"); if (Store->PageCollectionPagesCount(0 /* primary room */) == 0) { return nullptr; } - NProto::TRoot root; - + NProto::TRoot root; + if (auto *raw = Store->GetMeta()) { TMemoryInput stream(raw->data(), raw->size()); Y_VERIFY(root.ParseFromArcadiaStream(&stream)); - } else { - root.SetEpoch(0); /* for loading from abi blobs */ - } - - if (auto *abi = root.HasEvol() ? &root.GetEvol() : nullptr) - TAbi().Check(abi->GetTail(), abi->GetHead(), "part"); - + } else { + root.SetEpoch(0); /* for loading from abi blobs */ + } + + if (auto *abi = root.HasEvol() ? &root.GetEvol() : nullptr) + TAbi().Check(abi->GetTail(), abi->GetHead(), "part"); + TStore::TEggs eggs; if (auto *lay = (root.HasLayout() ? &root.GetLayout() : nullptr)) { - eggs = RootedEggs(*lay); + eggs = RootedEggs(*lay); } else { eggs = Store->LegacyEggs(); } - + auto run = TOverlay::Decode({ }, Overlay).Slices; - - const auto &stat = root.GetStat(); - + + const auto &stat = root.GetStat(); + const auto &minRowVersion = root.GetMinRowVersion(); const auto &maxRowVersion = root.GetMaxRowVersion(); TEpoch epoch = TEpoch(root.GetEpoch()); - return + return new TPartStore( - std::move(Store), - token, - { + std::move(Store), + token, + { epoch, - TPartScheme::Parse(*eggs.Scheme, eggs.Rooted), - *eggs.Index, + TPartScheme::Parse(*eggs.Scheme, eggs.Rooted), + *eggs.Index, eggs.Blobs ? new TExtBlobs(*eggs.Blobs, { }) : nullptr, - eggs.ByKey ? new TBloom(*eggs.ByKey) : nullptr, - eggs.Large ? new TFrames(*eggs.Large) : nullptr, - eggs.Small ? new TFrames(*eggs.Small) : nullptr, + eggs.ByKey ? new TBloom(*eggs.ByKey) : nullptr, + eggs.Large ? new TFrames(*eggs.Large) : nullptr, + eggs.Small ? new TFrames(*eggs.Small) : nullptr, std::move(eggs.GroupIndexes), std::move(eggs.HistoricIndexes), TRowVersion(minRowVersion.GetStep(), minRowVersion.GetTxId()), TRowVersion(maxRowVersion.GetStep(), maxRowVersion.GetTxId()), eggs.GarbageStats ? new NPage::TGarbageStats(*eggs.GarbageStats) : nullptr, eggs.TxIdStats ? new NPage::TTxIdStatsPage(*eggs.TxIdStats) : nullptr, - }, - { - stat.HasBytes() ? stat.GetBytes() : 0, - stat.HasCoded() ? stat.GetCoded() : 0, - stat.HasDrops() ? stat.GetDrops() : 0, - stat.HasRows() ? stat.GetRows() : 0, + }, + { + stat.HasBytes() ? stat.GetBytes() : 0, + stat.HasCoded() ? stat.GetCoded() : 0, + stat.HasDrops() ? stat.GetDrops() : 0, + stat.HasRows() ? stat.GetRows() : 0, stat.HasHiddenRows() ? stat.GetHiddenRows() : 0, stat.HasHiddenDrops() ? stat.GetHiddenDrops() : 0, - }, + }, run ? std::move(run) : TSlices::All() - ); - } - - private: - TStore::TEggs RootedEggs(const NProto::TLayout &lay) const noexcept - { - const auto undef = Max<NPage::TPageId>(); - + ); + } + + private: + TStore::TEggs RootedEggs(const NProto::TLayout &lay) const noexcept + { + const auto undef = Max<NPage::TPageId>(); + TVector<TSharedData> groupIndexes; for (ui32 pageId : lay.GetGroupIndexes()) { groupIndexes.emplace_back(*Store->GetPage(0, pageId)); @@ -119,7 +119,7 @@ namespace NTest { historicIndexes.emplace_back(*Store->GetPage(0, pageId)); } - return { + return { true /* rooted page collection */, Store->GetPage(0, lay.HasIndex() ? lay.GetIndex() : undef), Store->GetPage(0, lay.HasScheme() ? lay.GetScheme() : undef), @@ -131,22 +131,22 @@ namespace NTest { std::move(historicIndexes), Store->GetPage(0, lay.HasGarbageStats() ? lay.GetGarbageStats() : undef), Store->GetPage(0, lay.HasTxIdStats() ? lay.GetTxIdStats() : undef), - }; - } - - private: + }; + } + + private: TIntrusiveConstPtr<TStore> Store; - const TString Overlay; + const TString Overlay; }; - class TWriterBundle : public IPageWriter { + class TWriterBundle : public IPageWriter { public: TWriterBundle(size_t groups, const TLogoBlobID token) : Groups(groups) , CookieAllocator(new NPageCollection::TCookieAllocator(token.TabletID(), - (ui64(token.Generation()) << 32) | token.Step(), - { token.Cookie(), token.Cookie() + 1000 }, - {{ ui8(0) /* channel */, ui32(0) /* grpup*/ }} )) + (ui64(token.Generation()) << 32) | token.Step(), + { token.Cookie(), token.Cookie() + 1000 }, + {{ ui8(0) /* channel */, ui32(0) /* grpup*/ }} )) { } @@ -154,10 +154,10 @@ namespace NTest { TPartEggs Flush(TIntrusiveConstPtr<TRowScheme> scheme, const TWritten &written) { Y_VERIFY(!Store, "Writer has not been flushed"); - Y_VERIFY(written.Parts == Parts.size()); - - return - { new TWritten(written), std::move(scheme), std::move(Parts) }; + Y_VERIFY(written.Parts == Parts.size()); + + return + { new TWritten(written), std::move(scheme), std::move(Parts) }; } private: @@ -182,20 +182,20 @@ namespace NTest { return Back().WriteLarge(TSharedData::Copy(blob)); } - TStore& Back() noexcept - { + TStore& Back() noexcept + { return Store ? *Store : *(Store = new TStore(Groups, NextGlobOffset)); - } - + } + void Finish(TString overlay) noexcept override { Y_VERIFY(Store, "Finish called without any writes"); - Growth->Unwrap(); + Growth->Unwrap(); Store->Finish(); NextGlobOffset = Store->NextGlobOffset(); - NTest::TLoader loader(std::exchange(Store,{ }), std::move(overlay)); + NTest::TLoader loader(std::exchange(Store,{ }), std::move(overlay)); Parts.emplace_back(loader.Load(CookieAllocator->Do(0 /* channel */, 0).Logo)); } @@ -207,44 +207,44 @@ namespace NTest { TAutoPtr<NPageCollection::TCookieAllocator> CookieAllocator; TAutoPtr<TScreen::TCook> Growth = new TScreen::TCook; TVector<TIntrusiveConstPtr<TPartStore>> Parts; - }; - - class TPartCook { - public: - TPartCook() = delete; - + }; + + class TPartCook { + public: + TPartCook() = delete; + TPartCook( const TLayoutCook &lay, const NPage::TConf &opts, const TLogoBlobID &token = TLogoBlobID(1, 2, 3, 1, 0, 0), TEpoch epoch = TEpoch::Zero()) : TPartCook(lay.RowScheme(), opts, token, epoch) - { - - } - + { + + } + NPageCollection::TGlobId PutBlob(TString data, ui64 ref) - { + { return static_cast<IPageWriter&>(Pages).WriteLarge(std::move(data), ref); - } - + } + TPartCook( TIntrusiveConstPtr<TRowScheme> rows, const NPage::TConf &opts, const TLogoBlobID &token = TLogoBlobID(1, 2, 3, 1, 0, 0), TEpoch epoch = TEpoch::Zero()) - : Scheme(rows) + : Scheme(rows) , Pages(Scheme->Families.size(), token) - { - auto tags = Scheme->Tags(); - auto *scheme = new TPartScheme(Scheme->Cols); - + { + auto tags = Scheme->Tags(); + auto *scheme = new TPartScheme(Scheme->Cols); + Writer = new TPartWriter(scheme, tags, Pages, opts, epoch); - - for (TPos on = 0; on < tags.size(); on++) - Remap[tags[on]] = on; - } - + + for (TPos on = 0; on < tags.size(); on++) + Remap[tags[on]] = on; + } + static TPartEggs Make( const TMass &mass, NPage::TConf conf = { }, @@ -252,20 +252,20 @@ namespace NTest { TEpoch epoch = TEpoch::Zero(), TRowVersion rowVersion = TRowVersion::Min(), ERowOp op = ERowOp::Upsert) - { + { TPartCook cook(mass.Model->Scheme, conf, token, epoch); - + auto eggs = cook.Ver(rowVersion).AddOp(op, mass.Saved.begin(), mass.Saved.end()).Finish(); - - if (const auto *written = eggs.Written.Get()) { - mass.Model->Check({ &written->Rows, 1 }); - } else { - Y_FAIL("Got part eggs without TWritten result"); - } - - return eggs; - } - + + if (const auto *written = eggs.Written.Get()) { + mass.Model->Check({ &written->Rows, 1 }); + } else { + Y_FAIL("Got part eggs without TWritten result"); + } + + return eggs; + } + inline TPartCook& Ver(TRowVersion rowVersion = TRowVersion::Min()) { NextVersion = rowVersion; @@ -282,23 +282,23 @@ namespace NTest { return *this; } - template<typename ...TArgs> + template<typename ...TArgs> inline TPartCook& AddOpN(ERowOp op, TArgs&&...args) - { - auto row = *TNatural(*Scheme).Col(std::forward<TArgs>(args)...); - - return Add(std::move(row), op); - } - - template<typename ...TArgs> + { + auto row = *TNatural(*Scheme).Col(std::forward<TArgs>(args)...); + + return Add(std::move(row), op); + } + + template<typename ...TArgs> inline TPartCook& AddN(TArgs&&...args) - { - auto row = *TNatural(*Scheme).Col(std::forward<TArgs>(args)...); - + { + auto row = *TNatural(*Scheme).Col(std::forward<TArgs>(args)...); + return Add(std::move(row), ERowOp::Upsert); - } - - template<typename TIter> + } + + template<typename TIter> TPartCook& AddOp(ERowOp op, TIter it, const TIter end) { while (it != end) Add(*it++, op); @@ -308,28 +308,28 @@ namespace NTest { template<typename TIter> TPartCook& Add(TIter it, const TIter end) - { + { while (it != end) Add(*it++, ERowOp::Upsert); - - return *this; - } - + + return *this; + } + TPartCook& Add(const TRow &tagged, ERowOp rop = ERowOp::Upsert) - { + { TVector<TCell> key(Scheme->Keys->Types.size()); - TRowState row(Remap.size()); - row.Touch(rop); - - for (auto &value: *tagged) { - auto *info = TRowTool(*Scheme).ColFor(value); - - if (info->IsKey()) { - key[info->Key] = value.Cell; - } else { - row.Set(Remap.at(value.Tag), value.Op, value.Cell); - } - } - + TRowState row(Remap.size()); + row.Touch(rop); + + for (auto &value: *tagged) { + auto *info = TRowTool(*Scheme).ColFor(value); + + if (info->IsKey()) { + key[info->Key] = value.Cell; + } else { + row.Set(Remap.at(value.Tag), value.Op, value.Cell); + } + } + if (LastKey && CompareTypedCellVectors( LastKey.data(), key.data(), @@ -358,22 +358,22 @@ namespace NTest { } return *this; - } - + } + TPartEggs Finish() - { + { if (LastKey) { // End the last key before finishing Writer->EndKey(); LastKey = { }; } - return Pages.Flush(std::move(Scheme), Writer->Finish()); - } - - private: + return Pages.Flush(std::move(Scheme), Writer->Finish()); + } + + private: TIntrusiveConstPtr<TRowScheme> Scheme; - TWriterBundle Pages; + TWriterBundle Pages; TMap<TTag, TPos> Remap; TAutoPtr<TPartWriter> Writer; TOwnedCellVec LastKey; @@ -381,5 +381,5 @@ namespace NTest { ui64 NextTxId = 0; ui64 CurrentDeltas = 0; ui64 CurrentVersions = 0; - }; -}}} + }; +}}} diff --git a/ydb/core/tablet_flat/test/libs/table/wrap_dbase.h b/ydb/core/tablet_flat/test/libs/table/wrap_dbase.h index aa162bf0f1..f7a920d004 100644 --- a/ydb/core/tablet_flat/test/libs/table/wrap_dbase.h +++ b/ydb/core/tablet_flat/test/libs/table/wrap_dbase.h @@ -1,49 +1,49 @@ -#pragma once - +#pragma once + #include <ydb/core/tablet_flat/flat_database.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - + +namespace NKikimr { +namespace NTable { +namespace NTest { + template<class TIter> struct TWrapDbIterImpl { - + TWrapDbIterImpl(TDatabase &base, ui32 table, TIntrusiveConstPtr<TRowScheme> scheme, TRowVersion snapshot = TRowVersion::Max()) - : Scheme(std::move(scheme)) - , Base(base) - , Table(table) + : Scheme(std::move(scheme)) + , Base(base) + , Table(table) , Snapshot(snapshot) - { - - } - - explicit operator bool() const noexcept - { - return Iter && Iter->Last() == EReady::Data; - } - + { + + } + + explicit operator bool() const noexcept + { + return Iter && Iter->Last() == EReady::Data; + } + TIter* Get() const noexcept - { - return Iter.Get(); - } - - const TRemap& Remap() const noexcept - { - return Iter->Remap; - } - - void Make(IPages*) noexcept - { - Iter = nullptr; - } - - EReady Seek(TRawVals key, ESeek seek) noexcept - { + { + return Iter.Get(); + } + + const TRemap& Remap() const noexcept + { + return Iter->Remap; + } + + void Make(IPages*) noexcept + { + Iter = nullptr; + } + + EReady Seek(TRawVals key, ESeek seek) noexcept + { if (seek == ESeek::Upper && !key) Y_FAIL("Cannot cast ESeek::Upper with empty key to ELookup"); - + TKeyRange range; range.MinKey = key; switch (seek) { @@ -58,42 +58,42 @@ namespace NTest { range.MinInclusive = true; range.MaxInclusive = true; break; - } - + } + if constexpr (TIter::Direction == EDirection::Reverse) { using namespace std; swap(range.MinKey, range.MaxKey); swap(range.MinInclusive, range.MaxInclusive); } - + Iter = Base.IterateRangeGeneric<TIter>(Table, range, Scheme->Tags(), Snapshot); - + return Iter->Next(ENext::All); - } - - EReady Next() noexcept - { + } + + EReady Next() noexcept + { return Iter->Next(ENext::All); - } - - const TRowState& Apply() noexcept - { - return Iter->Row(); - } - - public: + } + + const TRowState& Apply() noexcept + { + return Iter->Row(); + } + + public: const TIntrusiveConstPtr<TRowScheme> Scheme; - TDatabase &Base; - - private: - const ui32 Table = Max<ui32>(); + TDatabase &Base; + + private: + const ui32 Table = Max<ui32>(); const TRowVersion Snapshot; TAutoPtr<TIter> Iter; - }; - + }; + using TWrapDbIter = TWrapDbIterImpl<TTableIt>; using TWrapDbReverseIter = TWrapDbIterImpl<TTableReverseIt>; -} -} -} +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/wrap_iter.h b/ydb/core/tablet_flat/test/libs/table/wrap_iter.h index 9cd855141f..75baae8d4f 100644 --- a/ydb/core/tablet_flat/test/libs/table/wrap_iter.h +++ b/ydb/core/tablet_flat/test/libs/table/wrap_iter.h @@ -1,26 +1,26 @@ -#pragma once - +#pragma once + #include <ydb/core/tablet_flat/flat_table_subset.h> #include <ydb/core/tablet_flat/flat_iterator.h> #include <ydb/core/tablet_flat/flat_row_scheme.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - + +namespace NKikimr { +namespace NTable { +namespace NTest { + template<class TIter> struct TWrapIterImpl { - using TFrozen = decltype(TSubset::Frozen); - using TFlatten = decltype(TSubset::Flatten); - + using TFrozen = decltype(TSubset::Frozen); + using TFlatten = decltype(TSubset::Flatten); + TWrapIterImpl(const TSubset &subset, TRowVersion snapshot = TRowVersion::Max()) - : Scheme(subset.Scheme) - , Nulls(Scheme->Keys) - , Frozen(subset.Frozen) - , Flatten(subset.Flatten) + : Scheme(subset.Scheme) + , Nulls(Scheme->Keys) + , Frozen(subset.Frozen) + , Flatten(subset.Flatten) , Snapshot(snapshot) , Levels(Scheme->Keys) - { + { TVector<const TPartView*> parts; parts.reserve(Flatten.size()); for (auto &partView: Flatten) { @@ -36,44 +36,44 @@ namespace NTest { for (auto *p: parts) { Levels.Add(p->Part, p->Slices); } - } - - explicit operator bool() const noexcept - { - return Iter && Iter->Last() == EReady::Data; - } - + } + + explicit operator bool() const noexcept + { + return Iter && Iter->Last() == EReady::Data; + } + TIter* Get() const noexcept - { - return Iter.Get(); - } - - const TRemap& Remap() const noexcept - { - return Iter->Remap; - } - - void Make(IPages *env) noexcept - { - Iter = nullptr, Env = env; /* Have to make on each Seek(...) */ - } - - EReady Seek(TRawVals key_, ESeek seek) noexcept - { - const TCelled key(key_, *Scheme->Keys, false); - - ui64 limit = seek == ESeek::Exact ? 1 : Max<ui64>(); - + { + return Iter.Get(); + } + + const TRemap& Remap() const noexcept + { + return Iter->Remap; + } + + void Make(IPages *env) noexcept + { + Iter = nullptr, Env = env; /* Have to make on each Seek(...) */ + } + + EReady Seek(TRawVals key_, ESeek seek) noexcept + { + const TCelled key(key_, *Scheme->Keys, false); + + ui64 limit = seek == ESeek::Exact ? 1 : Max<ui64>(); + Iter = new TIter(&*Scheme, Scheme->Tags(), limit, Snapshot); - - for (auto &mem: Frozen) - Iter->Push( + + for (auto &mem: Frozen) + Iter->Push( TMemIt::Make(*mem, mem.Snapshot, key, seek, Nulls, &Iter->Remap, Env, TIter::Direction)); - + for (auto &run: Levels) { auto one = MakeHolder<TRunIt>(run, Remap().Tags, Nulls, Env); - + EReady status; if constexpr (TIter::Direction == EDirection::Reverse) { status = one->SeekReverse(key, seek); @@ -83,37 +83,37 @@ namespace NTest { if (status != EReady::Gone) Iter->Push(std::move(one)); - } - + } + return Iter->Next(ENext::All); - } - - EReady Next() noexcept - { + } + + EReady Next() noexcept + { return Iter->Next(ENext::All); - } - - const TRowState& Apply() noexcept - { - return Iter->Row(); - } - - public: + } + + const TRowState& Apply() noexcept + { + return Iter->Row(); + } + + public: const TIntrusiveConstPtr<TRowScheme> Scheme; const TIntrusiveConstPtr<TKeyNulls> Nulls; - const TFrozen Frozen; - const TFlatten Flatten; + const TFrozen Frozen; + const TFlatten Flatten; const TRowVersion Snapshot; - - private: - IPages *Env = nullptr; + + private: + IPages *Env = nullptr; TLevels Levels; TAutoPtr<TIter> Iter; - }; - + }; + using TWrapIter = TWrapIterImpl<TTableIt>; using TWrapReverseIter = TWrapIterImpl<TTableReverseIt>; -} -} -} +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/wrap_part.h b/ydb/core/tablet_flat/test/libs/table/wrap_part.h index 2cf16dae9e..11223f791a 100644 --- a/ydb/core/tablet_flat/test/libs/table/wrap_part.h +++ b/ydb/core/tablet_flat/test/libs/table/wrap_part.h @@ -1,75 +1,75 @@ -#pragma once - -#include "test_part.h" -#include "test_iter.h" - +#pragma once + +#include "test_part.h" +#include "test_iter.h" + #include <ydb/core/tablet_flat/test/libs/rows/rows.h> #include <ydb/core/tablet_flat/flat_table_part.h> #include <ydb/core/tablet_flat/flat_part_screen.h> #include <ydb/core/tablet_flat/flat_part_iter_multi.h> #include <ydb/core/tablet_flat/flat_stat_part.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - + +namespace NKikimr { +namespace NTable { +namespace NTest { + template<EDirection Direction> struct TWrapPartImpl { TWrapPartImpl(const TPartEggs &eggs, TIntrusiveConstPtr<TSlices> slices = nullptr, - bool defaults = true) - : Eggs(eggs) - , Scheme(eggs.Scheme) - , Remap_(TRemap::Full(*Scheme)) - , Defaults(defaults) - , State(Remap_.Size()) - , Run(*Scheme->Keys) - { + bool defaults = true) + : Eggs(eggs) + , Scheme(eggs.Scheme) + , Remap_(TRemap::Full(*Scheme)) + , Defaults(defaults) + , State(Remap_.Size()) + , Run(*Scheme->Keys) + { if (slices || Eggs.Parts.size() == 1) { - /* Allowed to override part slice only for lone eggs */ + /* Allowed to override part slice only for lone eggs */ AddPart(Eggs.Lone(), slices ? *slices : *Eggs.Lone()->Slices); } else { for (const auto &part : Eggs.Parts) { AddPart(part, *part->Slices); } } - } - - private: + } + + private: void AddPart(TIntrusiveConstPtr<TPart> part, const TSlices &slices) - { + { for (const auto &slice : slices) { auto got = Run.FindInsertHint(part.Get(), slice); Y_VERIFY(got.second, "Unexpected slices intersection"); Run.Insert(got.first, part, slice); } - } - - public: - explicit operator bool() const noexcept - { - return Iter && Iter->IsValid() && Ready == EReady::Data; - } - + } + + public: + explicit operator bool() const noexcept + { + return Iter && Iter->IsValid() && Ready == EReady::Data; + } + TRunIt* Get() const noexcept - { - return Iter.Get(); - } - - const TRemap& Remap() const noexcept - { - return Remap_; - } - - void Make(IPages *env) noexcept - { - Ready = EReady::Gone; + { + return Iter.Get(); + } + + const TRemap& Remap() const noexcept + { + return Remap_; + } + + void Make(IPages *env) noexcept + { + Ready = EReady::Gone; Iter = MakeHolder<TRunIt>(Run, Remap_.Tags, Scheme->Keys, env); - } - - EReady Seek(TRawVals key_, ESeek seek) noexcept - { - const TCelled key(key_, *Scheme->Keys, false); - + } + + EReady Seek(TRawVals key_, ESeek seek) noexcept + { + const TCelled key(key_, *Scheme->Keys, false); + if constexpr (Direction == EDirection::Reverse) { Ready = Iter->SeekReverse(key, seek); } else { @@ -77,13 +77,13 @@ namespace NTest { } if (Ready == EReady::Data) - Ready = RollUp(); - - Y_VERIFY(Ready != EReady::Data || Iter->IsValid()); - - return Ready; - } - + Ready = RollUp(); + + Y_VERIFY(Ready != EReady::Data || Iter->IsValid()); + + return Ready; + } + EReady SkipToRowVersion(TRowVersion rowVersion) noexcept { Ready = Iter->SkipToRowVersion(rowVersion, /* committed */ {}); @@ -112,61 +112,61 @@ namespace NTest { } } - EReady Next() noexcept - { - if (std::exchange(NoBlobs, false)) { - Ready = RollUp(); + EReady Next() noexcept + { + if (std::exchange(NoBlobs, false)) { + Ready = RollUp(); } else if (EReady::Data == (Ready = DoIterNext())) - Ready = RollUp(); - - Y_VERIFY(Ready != EReady::Data || Iter->IsValid()); - - return Ready; - } - - const TRowState& Apply() noexcept - { - Y_VERIFY(Ready == EReady::Data, "Row state isn't ready"); - - return State; - } - - EReady RollUp() - { - if (Defaults) { - State.Reset(Remap_.Nulls()); - } else { - State.Init(Remap_.Size()); - } - - TDbTupleRef key = Iter->GetKey(); - - for (auto &pin: Remap_.KeyPins()) + Ready = RollUp(); + + Y_VERIFY(Ready != EReady::Data || Iter->IsValid()); + + return Ready; + } + + const TRowState& Apply() noexcept + { + Y_VERIFY(Ready == EReady::Data, "Row state isn't ready"); + + return State; + } + + EReady RollUp() + { + if (Defaults) { + State.Reset(Remap_.Nulls()); + } else { + State.Init(Remap_.Size()); + } + + TDbTupleRef key = Iter->GetKey(); + + for (auto &pin: Remap_.KeyPins()) State.Set(pin.Pos, ECellOp::Set, key.Columns[pin.Key]); - + Iter->Apply(State, /* committed */ {}); - - return (NoBlobs = State.Need() > 0) ? EReady::Page : EReady::Data; - } - - const TPartEggs Eggs; + + return (NoBlobs = State.Need() > 0) ? EReady::Page : EReady::Data; + } + + const TPartEggs Eggs; const TIntrusiveConstPtr<TRowScheme> Scheme; - const TRemap Remap_; - const bool Defaults = true; - - private: - EReady Ready = EReady::Gone; - bool NoBlobs = false; - TRowState State; + const TRemap Remap_; + const bool Defaults = true; + + private: + EReady Ready = EReady::Gone; + bool NoBlobs = false; + TRowState State; TRun Run; THolder<TRunIt> Iter; - }; - + }; + using TWrapPart = TWrapPartImpl<EDirection::Forward>; using TWrapReversePart = TWrapPartImpl<EDirection::Reverse>; - using TCheckIt = TChecker<TWrapPart, TPartEggs>; + using TCheckIt = TChecker<TWrapPart, TPartEggs>; using TCheckReverseIt = TChecker<TWrapReversePart, TPartEggs>; -} -} -} +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/wrap_select.h b/ydb/core/tablet_flat/test/libs/table/wrap_select.h index 06069a8d01..912ed7158e 100644 --- a/ydb/core/tablet_flat/test/libs/table/wrap_select.h +++ b/ydb/core/tablet_flat/test/libs/table/wrap_select.h @@ -1,74 +1,74 @@ -#pragma once - +#pragma once + #include <ydb/core/tablet_flat/flat_database.h> #include <ydb/core/tablet_flat/flat_row_state.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - - struct TWrapDbSelect { - + +namespace NKikimr { +namespace NTable { +namespace NTest { + + struct TWrapDbSelect { + TWrapDbSelect(TDatabase &base, ui32 table, TIntrusiveConstPtr<TRowScheme> scheme, TRowVersion snapshot = TRowVersion::Max()) - : Scheme(std::move(scheme)) - , Remap_(TRemap::Full(*Scheme)) - , Base(base) - , Table(table) + : Scheme(std::move(scheme)) + , Remap_(TRemap::Full(*Scheme)) + , Base(base) + , Table(table) , Snapshot(snapshot) - { - - } - - explicit operator bool() const noexcept - { - return Ready == EReady::Data; - } - - const TRowState* Get() const noexcept - { - return &State; - } - - const TRemap& Remap() const noexcept - { - return Remap_; - } - - void Make(IPages*) noexcept - { - State.Init(0); - } - - EReady Seek(TRawVals key, ESeek seek) noexcept - { - Y_VERIFY(seek == ESeek::Exact, "Db Select(...) is a point lookup"); - + { + + } + + explicit operator bool() const noexcept + { + return Ready == EReady::Data; + } + + const TRowState* Get() const noexcept + { + return &State; + } + + const TRemap& Remap() const noexcept + { + return Remap_; + } + + void Make(IPages*) noexcept + { + State.Init(0); + } + + EReady Seek(TRawVals key, ESeek seek) noexcept + { + Y_VERIFY(seek == ESeek::Exact, "Db Select(...) is a point lookup"); + return (Ready = Base.Select(Table, key, Scheme->Tags(), State, /* readFlags */ 0, Snapshot)); - } - - EReady Next() noexcept - { - return (Ready = EReady::Gone); - } - - const TRowState& Apply() noexcept - { - return State; - } - - public: + } + + EReady Next() noexcept + { + return (Ready = EReady::Gone); + } + + const TRowState& Apply() noexcept + { + return State; + } + + public: const TIntrusiveConstPtr<TRowScheme> Scheme; - const TRemap Remap_; - TDatabase &Base; - - private: - const ui32 Table = Max<ui32>(); + const TRemap Remap_; + TDatabase &Base; + + private: + const ui32 Table = Max<ui32>(); const TRowVersion Snapshot; - EReady Ready = EReady::Gone; - TRowState State; - }; - -} -} -} + EReady Ready = EReady::Gone; + TRowState State; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/wrap_warm.h b/ydb/core/tablet_flat/test/libs/table/wrap_warm.h index 059cac1a21..78d809e0ca 100644 --- a/ydb/core/tablet_flat/test/libs/table/wrap_warm.h +++ b/ydb/core/tablet_flat/test/libs/table/wrap_warm.h @@ -1,107 +1,107 @@ -#pragma once - +#pragma once + #include <ydb/core/tablet_flat/test/libs/rows/rows.h> - + #include <ydb/core/tablet_flat/flat_mem_warm.h> #include <ydb/core/tablet_flat/flat_mem_iter.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - + +namespace NKikimr { +namespace NTable { +namespace NTest { + template<EDirection Direction> struct TWrapMemtableImpl { TWrapMemtableImpl(TIntrusiveConstPtr<TMemTable> egg, bool defaults = true) - : Table(egg) - , Scheme(Table->Scheme) - , Remap_(TRemap::Full(*Scheme)) - , Defaults(defaults) - , State(Remap_.Size()) - { - - } - - explicit operator bool() const noexcept - { - return Iter && Iter->IsValid(); - } - - TMemIt* Get() const noexcept - { - return Iter.Get(); - } - - const TRemap& Remap() const noexcept - { - return Remap_; - } - - void Make(IPages *env) noexcept - { - Iter = nullptr, Env = env; /* Have to make on each Seek(...) */ - } - - EReady Seek(TRawVals key_, ESeek seek) noexcept - { - const TCelled key(key_, *Scheme->Keys, false); - + : Table(egg) + , Scheme(Table->Scheme) + , Remap_(TRemap::Full(*Scheme)) + , Defaults(defaults) + , State(Remap_.Size()) + { + + } + + explicit operator bool() const noexcept + { + return Iter && Iter->IsValid(); + } + + TMemIt* Get() const noexcept + { + return Iter.Get(); + } + + const TRemap& Remap() const noexcept + { + return Remap_; + } + + void Make(IPages *env) noexcept + { + Iter = nullptr, Env = env; /* Have to make on each Seek(...) */ + } + + EReady Seek(TRawVals key_, ESeek seek) noexcept + { + const TCelled key(key_, *Scheme->Keys, false); + Iter = TMemIt::Make(*Table, Table->Immediate(), key, seek, Scheme->Keys, &Remap_, Env, Direction); - - return RollUp(); - } - - EReady Next() noexcept - { + + return RollUp(); + } + + EReady Next() noexcept + { if constexpr (Direction == EDirection::Reverse) { Iter->Prev(); } else { Iter->Next(); } - - return RollUp(); - } - - const TRowState& Apply() noexcept - { - Y_VERIFY(*this, "Iterator isn't ready"); - - return State; - } - - EReady RollUp() - { - if (Iter->IsValid()) { - if (Defaults) { - State.Reset(Remap_.Nulls()); - } else { - State.Init(Remap_.Size()); - } - - TDbTupleRef key = Iter->GetKey(); - - for (auto &pin: Remap_.KeyPins()) + + return RollUp(); + } + + const TRowState& Apply() noexcept + { + Y_VERIFY(*this, "Iterator isn't ready"); + + return State; + } + + EReady RollUp() + { + if (Iter->IsValid()) { + if (Defaults) { + State.Reset(Remap_.Nulls()); + } else { + State.Init(Remap_.Size()); + } + + TDbTupleRef key = Iter->GetKey(); + + for (auto &pin: Remap_.KeyPins()) State.Set(pin.Pos, ECellOp::Set, key.Columns[pin.Key]); - + Iter->Apply(State, /* committed */ {}); - } - - return Iter->IsValid() ? EReady::Data : EReady::Gone; - } - + } + + return Iter->IsValid() ? EReady::Data : EReady::Gone; + } + const TIntrusiveConstPtr<TMemTable> Table; const TIntrusiveConstPtr<TRowScheme> Scheme; - const TRemap Remap_; - const bool Defaults = true; - - private: - IPages *Env = nullptr; - TRowState State; + const TRemap Remap_; + const bool Defaults = true; + + private: + IPages *Env = nullptr; + TRowState State; TAutoPtr<TMemIt> Iter; - }; - + }; + using TWrapMemtable = TWrapMemtableImpl<EDirection::Forward>; using TWrapReverseMemtable = TWrapMemtableImpl<EDirection::Reverse>; -} -} -} +} +} +} diff --git a/ydb/core/tablet_flat/test/libs/table/ya.make b/ydb/core/tablet_flat/test/libs/table/ya.make index 53d6ab494b..7750bbad8e 100644 --- a/ydb/core/tablet_flat/test/libs/table/ya.make +++ b/ydb/core/tablet_flat/test/libs/table/ya.make @@ -1,15 +1,15 @@ -LIBRARY() - +LIBRARY() + OWNER(g:kikimr) - -SRCS( - misc.cpp -) - -PEERDIR( + +SRCS( + misc.cpp +) + +PEERDIR( ydb/core/tablet_flat/test/libs/rows ydb/core/tablet_flat/test/libs/table/model ydb/core/tablet_flat -) - -END() +) + +END() diff --git a/ydb/core/tablet_flat/test/tool/perf/app.h b/ydb/core/tablet_flat/test/tool/perf/app.h index 96f1e81d5a..39f9fc4e28 100644 --- a/ydb/core/tablet_flat/test/tool/perf/app.h +++ b/ydb/core/tablet_flat/test/tool/perf/app.h @@ -1,164 +1,164 @@ -#pragma once - +#pragma once + #include "colons.h" -#include "do_zero.h" -#include "do_mem.h" -#include "do_part.h" -#include "do_iter.h" +#include "do_zero.h" +#include "do_mem.h" +#include "do_part.h" +#include "do_iter.h" #include "logger.h" -#include "sponge.h" -#include "runner.h" - +#include "sponge.h" +#include "runner.h" + #include <ydb/core/tablet_flat/util_fmt_desc.h> #include <ydb/core/tablet_flat/test/libs/rows/mass.h> #include <ydb/core/tablet_flat/test/libs/table/model/small.h> #include <ydb/core/tablet_flat/test/libs/table/model/large.h> - -namespace NKikimr { -namespace NTable { -namespace NPerf { - - class TApp { - public: - using ESponge = NTest::ESponge; - - int Execute() - { - Logger = new TLogger(LLev, LLev, nullptr); - - if (Mass == nullptr) SetMass("32768:2cols"); - - NTest::TSponge sponge(Sponge); - - if (auto logl = Logger->Log(NKikiSched::ELnLev::INFO)) { - logl << "Using " << NFmt::Do(*Mass); - } - - if (auto logl = Logger->Log(NKikiSched::ELnLev::INFO)) { - logl << "Modelled by " << NFmt::Do(*Mass->Model); - } - - TRunner env(Logger.Get(), *Mass, sponge, Conf); - - if (Test & 0x0001) { - Cout << "zero "; env.Do<TDoZero>(); Cout << Endl; - } - if (Test & 0x0002) { - Cout << "warm-tree "; env.Do<TDoMem>(); Cout << Endl; - } - if (Test & 0x0004) { - Cout << "flat-32.lz4"; env.Do<TDoPart>(true); Cout << Endl; - } - if (Test & 0x0008) { - Cout << "flat-7KiB "; env.Do<TDoPart>(false); Cout << Endl; - } - if (Test & 0x0010) { - Cout << "it-1.0.seq "; env.Do<TDoIter>(0, false); Cout << Endl; - } - if (Test & 0x0020) { - Cout << "it-0.2.rnd "; env.Do<TDoIter>(2, true); Cout << Endl; - } - if (Test & 0x0040) { - Cout << "it-0.4.rnd "; env.Do<TDoIter>(4, true); Cout << Endl; - } - if (Test & 0x0080) { - Cout << "it-0.8.rnd "; env.Do<TDoIter>(8, true); Cout << Endl; - } - if (Test & 0x0100) { - Cout << "it-0.8.seq "; env.Do<TDoIter>(8, false); Cout << Endl; - } - - if (auto logl = Logger->Log(NKikiSched::ELnLev::INFO)) { - logl << NFmt::Do(sponge); - } - - return 0; - } - - void SetLogger(const TString line) - { - NKikiSched::TColons args(line); - - args.Put(LLev); - } - - void SetTests(const TString line) - { - Test = 0; - - NKikiSched::TColons args(line); - - while (auto name = args.Next()) { - if (name == "zero") { Test |= 0x0001; - } else if (name == "warm") { Test |= 0x0002; - } else if (name == "flz4") { Test |= 0x0004; - } else if (name == "7kib") { Test |= 0x0008; - } else if (name == "s1.0") { Test |= 0x0010; - } else if (name == "r0.2") { Test |= 0x0020; - } else if (name == "r0.4") { Test |= 0x0040; - } else if (name == "r0.4") { Test |= 0x0080; - } else if (name == "s0.8") { Test |= 0x0100; - } else { - throw yexception() << "Unknown test code " << name; - } - } - } - - void SetMass(const TString line) - { - NKikiSched::TColons args(line); - - auto rows = args.Value<ui64>(32768); - const TString kind = args.Token("small"); - + +namespace NKikimr { +namespace NTable { +namespace NPerf { + + class TApp { + public: + using ESponge = NTest::ESponge; + + int Execute() + { + Logger = new TLogger(LLev, LLev, nullptr); + + if (Mass == nullptr) SetMass("32768:2cols"); + + NTest::TSponge sponge(Sponge); + + if (auto logl = Logger->Log(NKikiSched::ELnLev::INFO)) { + logl << "Using " << NFmt::Do(*Mass); + } + + if (auto logl = Logger->Log(NKikiSched::ELnLev::INFO)) { + logl << "Modelled by " << NFmt::Do(*Mass->Model); + } + + TRunner env(Logger.Get(), *Mass, sponge, Conf); + + if (Test & 0x0001) { + Cout << "zero "; env.Do<TDoZero>(); Cout << Endl; + } + if (Test & 0x0002) { + Cout << "warm-tree "; env.Do<TDoMem>(); Cout << Endl; + } + if (Test & 0x0004) { + Cout << "flat-32.lz4"; env.Do<TDoPart>(true); Cout << Endl; + } + if (Test & 0x0008) { + Cout << "flat-7KiB "; env.Do<TDoPart>(false); Cout << Endl; + } + if (Test & 0x0010) { + Cout << "it-1.0.seq "; env.Do<TDoIter>(0, false); Cout << Endl; + } + if (Test & 0x0020) { + Cout << "it-0.2.rnd "; env.Do<TDoIter>(2, true); Cout << Endl; + } + if (Test & 0x0040) { + Cout << "it-0.4.rnd "; env.Do<TDoIter>(4, true); Cout << Endl; + } + if (Test & 0x0080) { + Cout << "it-0.8.rnd "; env.Do<TDoIter>(8, true); Cout << Endl; + } + if (Test & 0x0100) { + Cout << "it-0.8.seq "; env.Do<TDoIter>(8, false); Cout << Endl; + } + + if (auto logl = Logger->Log(NKikiSched::ELnLev::INFO)) { + logl << NFmt::Do(sponge); + } + + return 0; + } + + void SetLogger(const TString line) + { + NKikiSched::TColons args(line); + + args.Put(LLev); + } + + void SetTests(const TString line) + { + Test = 0; + + NKikiSched::TColons args(line); + + while (auto name = args.Next()) { + if (name == "zero") { Test |= 0x0001; + } else if (name == "warm") { Test |= 0x0002; + } else if (name == "flz4") { Test |= 0x0004; + } else if (name == "7kib") { Test |= 0x0008; + } else if (name == "s1.0") { Test |= 0x0010; + } else if (name == "r0.2") { Test |= 0x0020; + } else if (name == "r0.4") { Test |= 0x0040; + } else if (name == "r0.4") { Test |= 0x0080; + } else if (name == "s0.8") { Test |= 0x0100; + } else { + throw yexception() << "Unknown test code " << name; + } + } + } + + void SetMass(const TString line) + { + NKikiSched::TColons args(line); + + auto rows = args.Value<ui64>(32768); + const TString kind = args.Token("small"); + TAutoPtr<NTest::IModel> model; - - if (kind == "2cols") { - model = new NTest::TModel2Cols; - } else if (kind == "mixed") { - model = new NTest::TModelStd(false); - } else { - throw yexception() << "Unknown rows model " << kind; - } - - Mass = new NTest::TMass(model, rows); - } - - void SetSponge(const TString line) - { - Sponge = ESpongeBy(line); - } - - void SetSampling(const TString line) - { - NKikiSched::TColons args(line); - - Conf.Least = args.Large(Conf.Least); - Conf.Limit = args.Large(Conf.Limit); - args.Put(Conf.Spent); - } - - private: - static ESponge ESpongeBy(const TString &sponge) - { - if (sponge == "none") return ESponge::None; - if (sponge == "mur") return ESponge::Murmur; - if (sponge == "city") return ESponge::City; - if (sponge == "fnv") return ESponge::Fnv; - if (sponge == "xor") return ESponge::Xor; - - throw yexception() << "Unknown sponge " << sponge; - } - - private: - int LLev = 1; + + if (kind == "2cols") { + model = new NTest::TModel2Cols; + } else if (kind == "mixed") { + model = new NTest::TModelStd(false); + } else { + throw yexception() << "Unknown rows model " << kind; + } + + Mass = new NTest::TMass(model, rows); + } + + void SetSponge(const TString line) + { + Sponge = ESpongeBy(line); + } + + void SetSampling(const TString line) + { + NKikiSched::TColons args(line); + + Conf.Least = args.Large(Conf.Least); + Conf.Limit = args.Large(Conf.Limit); + args.Put(Conf.Spent); + } + + private: + static ESponge ESpongeBy(const TString &sponge) + { + if (sponge == "none") return ESponge::None; + if (sponge == "mur") return ESponge::Murmur; + if (sponge == "city") return ESponge::City; + if (sponge == "fnv") return ESponge::Fnv; + if (sponge == "xor") return ESponge::Xor; + + throw yexception() << "Unknown sponge " << sponge; + } + + private: + int LLev = 1; TAutoPtr<TLogger> Logger; - ui64 Test = 0xffffffff; /* Bitmask of tests to perform */ - NPerf::TConf Conf; + ui64 Test = 0xffffffff; /* Bitmask of tests to perform */ + NPerf::TConf Conf; TAutoPtr<NTest::TMass> Mass; - NTest::ESponge Sponge = ESponge::Murmur; - }; - -} -} -} + NTest::ESponge Sponge = ESponge::Murmur; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/test/tool/perf/defs.h b/ydb/core/tablet_flat/test/tool/perf/defs.h index 90f55b89e4..2404e46c75 100644 --- a/ydb/core/tablet_flat/test/tool/perf/defs.h +++ b/ydb/core/tablet_flat/test/tool/perf/defs.h @@ -1,26 +1,26 @@ -#pragma once - -namespace NKikiSched { - class ILogger; -} - -namespace NKikimr { -namespace NTable { - -namespace NTest { - - enum class ESponge { - None = 0, - Murmur = 1, - City = 2, - Fnv = 3, - Xor = 4, - }; -} - -namespace NPerf { - using ILogger = NKikiSched::ILogger; -} - -} -} +#pragma once + +namespace NKikiSched { + class ILogger; +} + +namespace NKikimr { +namespace NTable { + +namespace NTest { + + enum class ESponge { + None = 0, + Murmur = 1, + City = 2, + Fnv = 3, + Xor = 4, + }; +} + +namespace NPerf { + using ILogger = NKikiSched::ILogger; +} + +} +} diff --git a/ydb/core/tablet_flat/test/tool/perf/do_iter.h b/ydb/core/tablet_flat/test/tool/perf/do_iter.h index d30b9cb16a..9f1d9f4d32 100644 --- a/ydb/core/tablet_flat/test/tool/perf/do_iter.h +++ b/ydb/core/tablet_flat/test/tool/perf/do_iter.h @@ -1,7 +1,7 @@ -#pragma once - -#include "iface.h" - +#pragma once + +#include "iface.h" + #include <ydb/core/tablet_flat/flat_mem_warm.h> #include <ydb/core/tablet_flat/flat_row_state.h> #include <ydb/core/tablet_flat/flat_row_scheme.h> @@ -10,62 +10,62 @@ #include <ydb/core/tablet_flat/test/libs/table/test_mixer.h> #include <ydb/core/tablet_flat/test/libs/table/test_make.h> #include <ydb/core/tablet_flat/test/libs/table/wrap_iter.h> - -namespace NKikimr { -namespace NTable { -namespace NPerf { - - class TDoIter : public IPerfTable { - public: - TDoIter(ILogger*, const TMass &mass, ui32 parts, bool mixed) - : Iter(*Make(mass, parts, mixed)) - { - - } - + +namespace NKikimr { +namespace NTable { +namespace NPerf { + + class TDoIter : public IPerfTable { + public: + TDoIter(ILogger*, const TMass &mass, ui32 parts, bool mixed) + : Iter(*Make(mass, parts, mixed)) + { + + } + static TAutoPtr<TSubset> Make(const TMass &mass, ui32 parts, bool mixed) - { - using namespace NTest; - - if (parts == 0) { - return TMake(mass).Mixed(1, 0, TMixerOne{ }); - } else if (mixed) { - return TMake(mass).Mixed(0, parts, TMixerRnd(parts)); - } else /* sequential parts */ { - TMixerSeq mixer(parts, mass.Saved.Size()); - - return TMake(mass).Mixed(0, parts, mixer); - } - } - - void Seek(TRawVals key, ESeek seek) override - { - Iter.Make(&Env); - auto ready = Iter.Seek(key, seek); - - Y_VERIFY(ready != EReady::Page); - } - - ui64 Scan(ui64 items, TSponge &aggr) override - { - for (; items-- && Iter; Iter.Next()) - aggr(Iter.Apply()); - - return items + 1; - } - - void Once(TRawVals key, TSponge &aggr) override - { - Seek(key, ESeek::Exact); - - if (Iter) - aggr(Iter.Apply()); - } - - private: - NTest::TTestEnv Env; - NTest::TWrapIter Iter; - }; -} -} -} + { + using namespace NTest; + + if (parts == 0) { + return TMake(mass).Mixed(1, 0, TMixerOne{ }); + } else if (mixed) { + return TMake(mass).Mixed(0, parts, TMixerRnd(parts)); + } else /* sequential parts */ { + TMixerSeq mixer(parts, mass.Saved.Size()); + + return TMake(mass).Mixed(0, parts, mixer); + } + } + + void Seek(TRawVals key, ESeek seek) override + { + Iter.Make(&Env); + auto ready = Iter.Seek(key, seek); + + Y_VERIFY(ready != EReady::Page); + } + + ui64 Scan(ui64 items, TSponge &aggr) override + { + for (; items-- && Iter; Iter.Next()) + aggr(Iter.Apply()); + + return items + 1; + } + + void Once(TRawVals key, TSponge &aggr) override + { + Seek(key, ESeek::Exact); + + if (Iter) + aggr(Iter.Apply()); + } + + private: + NTest::TTestEnv Env; + NTest::TWrapIter Iter; + }; +} +} +} diff --git a/ydb/core/tablet_flat/test/tool/perf/do_mem.h b/ydb/core/tablet_flat/test/tool/perf/do_mem.h index 1a83c4f762..507ca16098 100644 --- a/ydb/core/tablet_flat/test/tool/perf/do_mem.h +++ b/ydb/core/tablet_flat/test/tool/perf/do_mem.h @@ -1,81 +1,81 @@ -#pragma once - -#include "iface.h" - +#pragma once + +#include "iface.h" + #include <ydb/core/tablet_flat/flat_mem_warm.h> #include <ydb/core/tablet_flat/flat_mem_iter.h> #include <ydb/core/tablet_flat/flat_row_state.h> #include <ydb/core/tablet_flat/flat_row_scheme.h> #include <ydb/core/tablet_flat/test/libs/table/test_make.h> - -namespace NKikimr { -namespace NTable { -namespace NPerf { - - class TDoMem : public IPerfTable { - public: - TDoMem(ILogger *logger, const TMass &mass) - : Table(NTest::TMake(mass).Mem()) - , Nulls(Table->Scheme->Keys) - , Remap(TRemap::Full(*Table->Scheme)) - { - if (auto logl = logger->Log(NKikiSched::ELnLev::INF1)) { + +namespace NKikimr { +namespace NTable { +namespace NPerf { + + class TDoMem : public IPerfTable { + public: + TDoMem(ILogger *logger, const TMass &mass) + : Table(NTest::TMake(mass).Mem()) + , Nulls(Table->Scheme->Keys) + , Remap(TRemap::Full(*Table->Scheme)) + { + if (auto logl = logger->Log(NKikiSched::ELnLev::INF1)) { const auto raw = Table->GetUsedMem(); const auto waste = Table->GetWastedMem(); - - logl - << "mem-tree has " << Table->GetOpsCount() << " ops" - << " in " << NKikiSched::NFmt::TLarge(raw) << "b" + + logl + << "mem-tree has " << Table->GetOpsCount() << " ops" + << " in " << NKikiSched::NFmt::TLarge(raw) << "b" << ", " << NKikiSched::NFmt::TLarge(waste) << "b" << " waste"; - } - } - - void Seek(TRawVals key_, ESeek seek) override - { - const TCelled key(key_, *Table->Scheme->Keys, false); - + } + } + + void Seek(TRawVals key_, ESeek seek) override + { + const TCelled key(key_, *Table->Scheme->Keys, false); + Iter = TMemIt::Make(*Table, Table->Immediate(), key, seek, Nulls, &Remap, nullptr); - } - - ui64 Scan(ui64 items, TSponge &aggr) override - { - for (; items-- && Iter->IsValid(); Iter->Next()) - Apply(aggr); - - return items + 1; - } - - void Once(TRawVals key, TSponge &aggr) override - { - Seek(key, ESeek::Exact); - - if (Iter->IsValid()) - Apply(aggr); - } - - private: - void Apply(TSponge &aggr) noexcept - { - State.Reset(Remap.Nulls()); - - const auto key = Iter->GetKey(); - - for (auto &pin: Remap.KeyPins()) + } + + ui64 Scan(ui64 items, TSponge &aggr) override + { + for (; items-- && Iter->IsValid(); Iter->Next()) + Apply(aggr); + + return items + 1; + } + + void Once(TRawVals key, TSponge &aggr) override + { + Seek(key, ESeek::Exact); + + if (Iter->IsValid()) + Apply(aggr); + } + + private: + void Apply(TSponge &aggr) noexcept + { + State.Reset(Remap.Nulls()); + + const auto key = Iter->GetKey(); + + for (auto &pin: Remap.KeyPins()) State.Set(pin.Pos, ECellOp::Set, key.Columns[pin.Key]); - + Iter->Apply(State, /* committed */ {}); - aggr(State); - } - - private: + aggr(State); + } + + private: TIntrusivePtr<TMemTable> Table; TIntrusiveConstPtr<TKeyNulls> Nulls; - TRemap Remap; + TRemap Remap; TAutoPtr<TMemIt> Iter; - TRowState State; - }; - -} -} -} + TRowState State; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/test/tool/perf/do_part.h b/ydb/core/tablet_flat/test/tool/perf/do_part.h index 5c33c63964..0d4e59fc98 100644 --- a/ydb/core/tablet_flat/test/tool/perf/do_part.h +++ b/ydb/core/tablet_flat/test/tool/perf/do_part.h @@ -1,109 +1,109 @@ -#pragma once - -#include "iface.h" - +#pragma once + +#include "iface.h" + #include <ydb/core/tablet_flat/flat_row_state.h> #include <ydb/core/tablet_flat/flat_row_scheme.h> #include <ydb/core/tablet_flat/test/libs/table/wrap_part.h> #include <ydb/core/tablet_flat/test/libs/table/test_writer.h> #include <ydb/core/tablet_flat/test/libs/table/test_make.h> - -namespace NKikimr { -namespace NTable { -namespace NPerf { - - class TDoPart : public IPerfTable { - struct TStats { - ui64 Pages() const noexcept - { - return Plain + Encoded; - } - + +namespace NKikimr { +namespace NTable { +namespace NPerf { + + class TDoPart : public IPerfTable { + struct TStats { + ui64 Pages() const noexcept + { + return Plain + Encoded; + } + ui64 Bytes = 0; /* Total bytes obtained by rows */ - ui64 Plain = 0; - ui64 Encoded = 0; - }; - - public: - TDoPart(ILogger *logger, const TMass &mass, bool compress) - : Eggs(NTest::TMake(mass, Config(compress)).Part()) - , Wrap(Eggs, nullptr, true) - { - if (auto logl = logger->Log(NKikiSched::ELnLev::INF1)) { - const auto &part = *Eggs.Lone(); - const auto st = Stats(part); - - logl - << "part has { " << st.Plain << " " << st.Encoded << "e }" - << " pages in " << NFmt::TLarge(st.Bytes) << "b" - << " avg " - << NFmt::TAverage(st.Pages(), st.Bytes, false) << "b" + ui64 Plain = 0; + ui64 Encoded = 0; + }; + + public: + TDoPart(ILogger *logger, const TMass &mass, bool compress) + : Eggs(NTest::TMake(mass, Config(compress)).Part()) + , Wrap(Eggs, nullptr, true) + { + if (auto logl = logger->Log(NKikiSched::ELnLev::INF1)) { + const auto &part = *Eggs.Lone(); + const auto st = Stats(part); + + logl + << "part has { " << st.Plain << " " << st.Encoded << "e }" + << " pages in " << NFmt::TLarge(st.Bytes) << "b" + << " avg " + << NFmt::TAverage(st.Pages(), st.Bytes, false) << "b" << ", " << NFmt::TLarge(part.IndexesRawSize) << "b index"; - } - } - - static NPage::TConf Config(bool compress) noexcept - { - NPage::TConf conf; - - if (compress) { + } + } + + static NPage::TConf Config(bool compress) noexcept + { + NPage::TConf conf; + + if (compress) { conf.Group(0).PageSize = 32 * 1024; conf.Group(0).Codec = NPage::ECodec::LZ4; - } - - return conf; - } - - static TStats Stats(const TPart &part_) noexcept - { + } + + return conf; + } + + static TStats Stats(const TPart &part_) noexcept + { auto &part = dynamic_cast<const NTest::TPartStore&>(part_); - - TStats stats; - + + TStats stats; + for (auto &page: part.Store->PageCollectionArray(0 /* main room */)) { - auto got = NPage::THello().Read(page, EPage::Undef); - + auto got = NPage::THello().Read(page, EPage::Undef); + if (got == NPage::EPage::DataPage) { - stats.Bytes += page.size(); - - if (got == NPage::ECodec::Plain) { - stats.Plain++; - } else { - stats.Encoded++; - } - } - } - - return stats; - } - - void Seek(TRawVals key, ESeek seek) override - { - Wrap.Make(&Env); - Wrap.Seek(key, seek); - } - - ui64 Scan(ui64 items, TSponge &aggr) override - { - for (; items-- && Wrap; Wrap.Next()) - aggr(Wrap.Apply()); - - return items + 1; - } - - void Once(TRawVals key, TSponge &aggr) override - { - Seek(key, ESeek::Exact); - - if (Wrap) - aggr(Wrap.Apply()); - } - - private: - NTest::TPartEggs Eggs; - NTest::TTestEnv Env; - NTest::TWrapPart Wrap; - }; -} -} -} + stats.Bytes += page.size(); + + if (got == NPage::ECodec::Plain) { + stats.Plain++; + } else { + stats.Encoded++; + } + } + } + + return stats; + } + + void Seek(TRawVals key, ESeek seek) override + { + Wrap.Make(&Env); + Wrap.Seek(key, seek); + } + + ui64 Scan(ui64 items, TSponge &aggr) override + { + for (; items-- && Wrap; Wrap.Next()) + aggr(Wrap.Apply()); + + return items + 1; + } + + void Once(TRawVals key, TSponge &aggr) override + { + Seek(key, ESeek::Exact); + + if (Wrap) + aggr(Wrap.Apply()); + } + + private: + NTest::TPartEggs Eggs; + NTest::TTestEnv Env; + NTest::TWrapPart Wrap; + }; +} +} +} diff --git a/ydb/core/tablet_flat/test/tool/perf/do_writes.h b/ydb/core/tablet_flat/test/tool/perf/do_writes.h index 3e94106b24..536ff73153 100644 --- a/ydb/core/tablet_flat/test/tool/perf/do_writes.h +++ b/ydb/core/tablet_flat/test/tool/perf/do_writes.h @@ -1,51 +1,51 @@ -#pragma once - -#include "util.h" -#include "meter.h" - +#pragma once + +#include "util.h" +#include "meter.h" + #include <ydb/core/tablet_flat/flat_mem_warm.h> #include <ydb/core/tablet_flat/flat_row_state.h> #include <ydb/core/tablet_flat/flat_row_scheme.h> #include <ydb/core/tablet_flat/test/libs/rows/layout.h> - -namespace NKikimr { -namespace NTable { - - class TPerfMemUp { - public: - void DoUpdate(bool insert) - { - NTest::TLayoutCook lay; - - lay - .Col(0, 0, NScheme::NTypeIds::Uint64) - .Col(0, 1, NScheme::NTypeIds::Double) - .Key({ 0 }); - + +namespace NKikimr { +namespace NTable { + + class TPerfMemUp { + public: + void DoUpdate(bool insert) + { + NTest::TLayoutCook lay; + + lay + .Col(0, 0, NScheme::NTypeIds::Uint64) + .Col(0, 1, NScheme::NTypeIds::Double) + .Key({ 0 }); + TMemTable table(lay.RowScheme(), 0); - + TVector<TRawTypeValue> key; TVector<TUpdateOp> ops; - - ui64 keyUi64 = 42; - key.emplace_back(&keyUi64, sizeof(keyUi64), NScheme::NTypeIds::Uin> - - double dblVal = 2015.1027; + + ui64 keyUi64 = 42; + key.emplace_back(&keyUi64, sizeof(keyUi64), NScheme::NTypeIds::Uin> + + double dblVal = 2015.1027; ops.emplace_back(1, ECellOp::Set, TRawTypeValue(&dblVal, sizeof(dblVa> - - NTest::TMeter meter(TDuration::Seconds(10)); - - for (;meter.More();) { - keyUi64 = meter.Count(); - if (!insert) - keyUi64 %= 0x010000; - + + NTest::TMeter meter(TDuration::Seconds(10)); + + for (;meter.More();) { + keyUi64 = meter.Count(); + if (!insert) + keyUi64 %= 0x010000; + table.Update(ERowOp::Upsert, key, ops); - } - - Cout << "rps " << meter.Report() << Endl; - } - }; - -} -} + } + + Cout << "rps " << meter.Report() << Endl; + } + }; + +} +} diff --git a/ydb/core/tablet_flat/test/tool/perf/do_zero.h b/ydb/core/tablet_flat/test/tool/perf/do_zero.h index 304418cc78..4222784359 100644 --- a/ydb/core/tablet_flat/test/tool/perf/do_zero.h +++ b/ydb/core/tablet_flat/test/tool/perf/do_zero.h @@ -1,42 +1,42 @@ -#pragma once - -#include "iface.h" - -namespace NKikimr { -namespace NTable { -namespace NPerf { - - class TDoZero : public IPerfTable { - public: - TDoZero(ILogger*, const NTest::TMass&) - { - - } - - void Seek(TRawVals, ESeek) override - { - - } - - ui64 Scan(ui64 items, TSponge &aggr) override - { - for (ui64 it = 0; it < items; ++it) - aggr(&it, sizeof(it)); - - return 0; - } - - void Once(TRawVals key, TSponge &aggr) override - { - Seek(key, ESeek::Exact); - aggr(&Salt, sizeof(Salt)); - Salt++; - } - - private: - ui64 Salt = 0; - }; - -} -} -} +#pragma once + +#include "iface.h" + +namespace NKikimr { +namespace NTable { +namespace NPerf { + + class TDoZero : public IPerfTable { + public: + TDoZero(ILogger*, const NTest::TMass&) + { + + } + + void Seek(TRawVals, ESeek) override + { + + } + + ui64 Scan(ui64 items, TSponge &aggr) override + { + for (ui64 it = 0; it < items; ++it) + aggr(&it, sizeof(it)); + + return 0; + } + + void Once(TRawVals key, TSponge &aggr) override + { + Seek(key, ESeek::Exact); + aggr(&Salt, sizeof(Salt)); + Salt++; + } + + private: + ui64 Salt = 0; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/test/tool/perf/iface.h b/ydb/core/tablet_flat/test/tool/perf/iface.h index e8258a20b8..1342b0386b 100644 --- a/ydb/core/tablet_flat/test/tool/perf/iface.h +++ b/ydb/core/tablet_flat/test/tool/perf/iface.h @@ -1,27 +1,27 @@ -#pragma once - -#include "sponge.h" -#include "logger.h" - +#pragma once + +#include "sponge.h" +#include "logger.h" + #include <ydb/core/tablet_flat/defs.h> #include <ydb/core/tablet_flat/test/libs/rows/mass.h> - -namespace NKikimr { -namespace NTable { -namespace NPerf { - - class IPerfTable { - public: - using TSponge = NTest::TSponge; - using TMass = NTest::TMass; - - virtual ~IPerfTable() = default; - - virtual void Seek(TRawVals key, ESeek seek) = 0; - virtual ui64 Scan(ui64 items, TSponge &aggr) = 0; - virtual void Once(TRawVals key, TSponge &aggr) = 0; - }; - -} -} -} + +namespace NKikimr { +namespace NTable { +namespace NPerf { + + class IPerfTable { + public: + using TSponge = NTest::TSponge; + using TMass = NTest::TMass; + + virtual ~IPerfTable() = default; + + virtual void Seek(TRawVals key, ESeek seek) = 0; + virtual ui64 Scan(ui64 items, TSponge &aggr) = 0; + virtual void Once(TRawVals key, TSponge &aggr) = 0; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/test/tool/perf/logger.h b/ydb/core/tablet_flat/test/tool/perf/logger.h index 979b5fead4..df690be3e5 100644 --- a/ydb/core/tablet_flat/test/tool/perf/logger.h +++ b/ydb/core/tablet_flat/test/tool/perf/logger.h @@ -1,78 +1,78 @@ -#pragma once - +#pragma once + #include "iface_logger.h" #include "format.h" - -#include <util/datetime/base.h> - -namespace NKikimr { - -namespace NFmt { - using namespace NKikiSched::NFmt; -} - -namespace NTable { -namespace NPerf { - - using TLogLn = NKikiSched::TLogLn; - using ELnLev = NKikiSched::ELnLev; - - class TLogger - : public NKikiSched::ILogged - , public NKikiSched::ILogger { - - public: + +#include <util/datetime/base.h> + +namespace NKikimr { + +namespace NFmt { + using namespace NKikiSched::NFmt; +} + +namespace NTable { +namespace NPerf { + + using TLogLn = NKikiSched::TLogLn; + using ELnLev = NKikiSched::ELnLev; + + class TLogger + : public NKikiSched::ILogged + , public NKikiSched::ILogger { + + public: TLogger(int level = 0, int relev = -1, IOutputStream *redir = nullptr) - : Start(Now()) - , Level(level) - , Relev(redir ? relev : -1) - , Redir(redir) - { - - } - - TLogLn operator ()(ELnLev lev) const noexcept - { - return Log(lev); - } - - TLogLn Log(ELnLev lev) const noexcept override - { - return { ShouldLog(lev) ? this : nullptr, lev }; - } - - protected: - bool ShouldLog(ELnLev level) const noexcept - { - return (int)level <= Max(Level, Relev); - } - - void LogLn(ELnLev level, const TString &line) const noexcept override - { - auto left = (Now() - Start).SecondsFloat(); - - auto *label = Lev2Label(level); - - auto out = Sprintf("%08.3f %2s| %s\n", left, label, line.c_str()); - - if ((int)level <= Level) Cerr << out; - if ((int)level <= Relev) *Redir << out; - } - - static const char* Lev2Label(ELnLev level) noexcept - { - static const char *line[] = { "??", "**", "EE", "WW", "I0", - "I1", "I2", "I3", "D0", "D1", "D2", "D3" }; - - return int(level) < 12 ? line[int(level)] : "DG"; - } - - private: - const TInstant Start; - const int Level = 0; - const int Relev = 0; + : Start(Now()) + , Level(level) + , Relev(redir ? relev : -1) + , Redir(redir) + { + + } + + TLogLn operator ()(ELnLev lev) const noexcept + { + return Log(lev); + } + + TLogLn Log(ELnLev lev) const noexcept override + { + return { ShouldLog(lev) ? this : nullptr, lev }; + } + + protected: + bool ShouldLog(ELnLev level) const noexcept + { + return (int)level <= Max(Level, Relev); + } + + void LogLn(ELnLev level, const TString &line) const noexcept override + { + auto left = (Now() - Start).SecondsFloat(); + + auto *label = Lev2Label(level); + + auto out = Sprintf("%08.3f %2s| %s\n", left, label, line.c_str()); + + if ((int)level <= Level) Cerr << out; + if ((int)level <= Relev) *Redir << out; + } + + static const char* Lev2Label(ELnLev level) noexcept + { + static const char *line[] = { "??", "**", "EE", "WW", "I0", + "I1", "I2", "I3", "D0", "D1", "D2", "D3" }; + + return int(level) < 12 ? line[int(level)] : "DG"; + } + + private: + const TInstant Start; + const int Level = 0; + const int Relev = 0; IOutputStream *Redir = nullptr; - }; -} -} -} + }; +} +} +} diff --git a/ydb/core/tablet_flat/test/tool/perf/main.cpp b/ydb/core/tablet_flat/test/tool/perf/main.cpp index 326e18ac2b..1435ced579 100644 --- a/ydb/core/tablet_flat/test/tool/perf/main.cpp +++ b/ydb/core/tablet_flat/test/tool/perf/main.cpp @@ -1,36 +1,36 @@ -#include "app.h" - +#include "app.h" + #include <library/cpp/getopt/last_getopt.h> -#include <util/generic/yexception.h> - -int main(int argc, char* argv[]) -{ - using namespace NLastGetopt; - - TOpts opts; - - opts.AddLongOption("llev", "log level").RequiredArgument("NUM"); - opts.AddLongOption("mass", "rows mass args").RequiredArgument("STR"); - opts.AddLongOption("aggr", "data sponge model").RequiredArgument("STR"); - opts.AddLongOption("smp", "sampling settings").RequiredArgument("STR"); - opts.AddLongOption("test", "tests to perform").RequiredArgument("STR"); - - THolder<TOptsParseResult> res(new TOptsParseResult(&opts, argc, argv)); - - NKikimr::NTable::NPerf::TApp app; - - try { - if (res->Has("llev")) app.SetLogger(res->Get("llev")); - if (res->Has("mass")) app.SetMass(res->Get("mass")); - if (res->Has("aggr")) app.SetSponge(res->Get("aggr")); - if (res->Has("smp")) app.SetSampling(res->Get("smp")); - if (res->Has("test")) app.SetTests(res->Get("test")); - - return app.Execute(); - - } catch (yexception &ex) { - Cerr << ex.what() << Endl; - - return -1; - } -} +#include <util/generic/yexception.h> + +int main(int argc, char* argv[]) +{ + using namespace NLastGetopt; + + TOpts opts; + + opts.AddLongOption("llev", "log level").RequiredArgument("NUM"); + opts.AddLongOption("mass", "rows mass args").RequiredArgument("STR"); + opts.AddLongOption("aggr", "data sponge model").RequiredArgument("STR"); + opts.AddLongOption("smp", "sampling settings").RequiredArgument("STR"); + opts.AddLongOption("test", "tests to perform").RequiredArgument("STR"); + + THolder<TOptsParseResult> res(new TOptsParseResult(&opts, argc, argv)); + + NKikimr::NTable::NPerf::TApp app; + + try { + if (res->Has("llev")) app.SetLogger(res->Get("llev")); + if (res->Has("mass")) app.SetMass(res->Get("mass")); + if (res->Has("aggr")) app.SetSponge(res->Get("aggr")); + if (res->Has("smp")) app.SetSampling(res->Get("smp")); + if (res->Has("test")) app.SetTests(res->Get("test")); + + return app.Execute(); + + } catch (yexception &ex) { + Cerr << ex.what() << Endl; + + return -1; + } +} diff --git a/ydb/core/tablet_flat/test/tool/perf/meter.h b/ydb/core/tablet_flat/test/tool/perf/meter.h index cb6a76fd5a..032a4d5312 100644 --- a/ydb/core/tablet_flat/test/tool/perf/meter.h +++ b/ydb/core/tablet_flat/test/tool/perf/meter.h @@ -1,65 +1,65 @@ -#pragma once - +#pragma once + #include "format.h" - -namespace NKikimr { -namespace NTable { -namespace NTest { - - class TMeter { - public: - TMeter() = delete; - - TMeter(const TMeter&) = delete; - - TMeter(TDuration spent, ui64 least, ui64 limit) - : Least(least) - , Limit(Max(least,limit)) - , Start(TInstant::Now()) - , Edge(Start + spent) - { - - } - - ui64 Count() const - { - return Count_; - } - - ui64 Take(ui64 samples) - { - Stop = ((Count_ += samples) >= Limit) || Stop; - - if ((Last += samples) >= 4096 && Count_ > Least) { - Stop = Stop || Now() >= Edge; - Last = 0; - } - - return Stop ? 0 : 4096; - } - - TString Report() const noexcept - { - TStringStream out; - - double rate = double(Count_) / (Now() - Start).SecondsFloat(); - - out << NKikiSched::NFmt::TLarge(rate); - - return out.Str(); - } - - private: - const ui64 Least = 1024; - const ui64 Limit = Max<ui64>(); - const TInstant Start; - const TInstant Edge; - - bool Stop = false; - ui64 Count_ = 0; - ui64 Last = 0; - }; - -} -} -} + +namespace NKikimr { +namespace NTable { +namespace NTest { + + class TMeter { + public: + TMeter() = delete; + + TMeter(const TMeter&) = delete; + + TMeter(TDuration spent, ui64 least, ui64 limit) + : Least(least) + , Limit(Max(least,limit)) + , Start(TInstant::Now()) + , Edge(Start + spent) + { + + } + + ui64 Count() const + { + return Count_; + } + + ui64 Take(ui64 samples) + { + Stop = ((Count_ += samples) >= Limit) || Stop; + + if ((Last += samples) >= 4096 && Count_ > Least) { + Stop = Stop || Now() >= Edge; + Last = 0; + } + + return Stop ? 0 : 4096; + } + + TString Report() const noexcept + { + TStringStream out; + + double rate = double(Count_) / (Now() - Start).SecondsFloat(); + + out << NKikiSched::NFmt::TLarge(rate); + + return out.Str(); + } + + private: + const ui64 Least = 1024; + const ui64 Limit = Max<ui64>(); + const TInstant Start; + const TInstant Edge; + + bool Stop = false; + ui64 Count_ = 0; + ui64 Last = 0; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/test/tool/perf/names.h b/ydb/core/tablet_flat/test/tool/perf/names.h index 52a1b22c10..7968a5d82d 100644 --- a/ydb/core/tablet_flat/test/tool/perf/names.h +++ b/ydb/core/tablet_flat/test/tool/perf/names.h @@ -1,30 +1,30 @@ -#pragma once - -#include "defs.h" +#pragma once + +#include "defs.h" #include <ydb/core/tablet_flat/util_fmt_desc.h> -#include <util/system/yassert.h> - -namespace NKikimr { -namespace NFmt { - - template<> struct TPut<NTable::NTest::ESponge> { - using ESponge = NTable::NTest::ESponge; - - static void Do(TOut &out, const ESponge *sponge) - { - out << By(*sponge); - } - - static const char* By(ESponge sponge) - { - if (sponge == ESponge::None) return "none"; - if (sponge == ESponge::Murmur)return "murmur"; - if (sponge == ESponge::City) return "city"; - if (sponge == ESponge::Fnv) return "fnv"; - if (sponge == ESponge::Xor) return "xor"; - - Y_FAIL("Unreachable code"); - } - }; -} -} +#include <util/system/yassert.h> + +namespace NKikimr { +namespace NFmt { + + template<> struct TPut<NTable::NTest::ESponge> { + using ESponge = NTable::NTest::ESponge; + + static void Do(TOut &out, const ESponge *sponge) + { + out << By(*sponge); + } + + static const char* By(ESponge sponge) + { + if (sponge == ESponge::None) return "none"; + if (sponge == ESponge::Murmur)return "murmur"; + if (sponge == ESponge::City) return "city"; + if (sponge == ESponge::Fnv) return "fnv"; + if (sponge == ESponge::Xor) return "xor"; + + Y_FAIL("Unreachable code"); + } + }; +} +} diff --git a/ydb/core/tablet_flat/test/tool/perf/runner.h b/ydb/core/tablet_flat/test/tool/perf/runner.h index 6b9d335be6..f0dee20865 100644 --- a/ydb/core/tablet_flat/test/tool/perf/runner.h +++ b/ydb/core/tablet_flat/test/tool/perf/runner.h @@ -1,104 +1,104 @@ -#pragma once - -#include "defs.h" -#include "iface.h" -#include "meter.h" -#include "sponge.h" - +#pragma once + +#include "defs.h" +#include "iface.h" +#include "meter.h" +#include "sponge.h" + #include <ydb/core/tablet_flat/test/libs/rows/tool.h> #include <ydb/core/tablet_flat/test/libs/rows/mass.h> - -namespace NKikimr { -namespace NTable { -namespace NPerf { - - struct TConf { - ui64 Span = 1; - TDuration Spent = TDuration::Seconds(5); - ui64 Least = 1024; - ui64 Limit = Max<ui64>(); - }; - - class TRunner { - public: - using TMeter = NTest::TMeter; - - TRunner(ILogger *logger, const NTest::TMass &mass, - NTest::TSponge &sponge, const TConf &conf) - : Logger(logger) - , Conf(conf) - , Mass(mass) - , Sponge(sponge) - { - if (auto logl = Logger->Log(NKikiSched::ELnLev::INFO)) { - logl - << "Collect [" << NFmt::TLarge(Conf.Least) - << ", " << NFmt::TLarge(Conf.Limit) << "]" - << " samples over " << NFmt::TDelay(Conf.Spent) - << " per test"; - } - } - - template<typename TOne, typename ... TArgs> - void Do(TArgs&& ... args) - { - TOne one(Logger, Mass, std::forward<TArgs>(args)...); - - Run(&TRunner::DoScan, static_cast<IPerfTable&>(one)); - Run(&TRunner::DoOnce, static_cast<IPerfTable&>(one), ui64(3), true); - Run(&TRunner::DoOnce, static_cast<IPerfTable&>(one), ui64(-1), true); - Run(&TRunner::DoOnce, static_cast<IPerfTable&>(one), ui64(-1), false); - } - - private: - template<typename ... TArgs> - void Run(void(TRunner::*fn)(TMeter&, TArgs...), TArgs&& ... args) - { - TMeter meter(Conf.Spent, Conf.Least, Conf.Limit); - - (this->*fn)(meter, std::forward<TArgs>(args)...); - - Cout << " " << meter.Report(); - } - - void DoScan(TMeter &meter, IPerfTable &test) - { - ui64 last = 0; - - test.Seek({ }, ESeek::Lower); - - while (const auto once = meter.Take(last)) { - if (last = test.Scan(once, Sponge)) { - test.Seek({ }, ESeek::Lower); - } - - last = once - last; - } - } - - void DoOnce(TMeter &meter, IPerfTable &test, ui64 span_, bool exists) - { - TMersenne<ui64> rnd; - - const NTest::TRowTool tool(*Mass.Model->Scheme); - const auto &heap = exists ? Mass.Saved : Mass.Holes; - const auto span = Min(span_, heap.Size()); - - for (ui64 off = 0; meter.Take(1);) { - const auto key = tool.LookupKey(*(heap.begin() + off)); - - test.Once(key, Sponge); - - off = (off + rnd.Uniform(0, span)) % heap.Size(); - } - } - - private: - ILogger * const Logger = nullptr; - const NPerf::TConf Conf; - const NTest::TMass &Mass; - NTest::TSponge &Sponge; - }; -} -} -} + +namespace NKikimr { +namespace NTable { +namespace NPerf { + + struct TConf { + ui64 Span = 1; + TDuration Spent = TDuration::Seconds(5); + ui64 Least = 1024; + ui64 Limit = Max<ui64>(); + }; + + class TRunner { + public: + using TMeter = NTest::TMeter; + + TRunner(ILogger *logger, const NTest::TMass &mass, + NTest::TSponge &sponge, const TConf &conf) + : Logger(logger) + , Conf(conf) + , Mass(mass) + , Sponge(sponge) + { + if (auto logl = Logger->Log(NKikiSched::ELnLev::INFO)) { + logl + << "Collect [" << NFmt::TLarge(Conf.Least) + << ", " << NFmt::TLarge(Conf.Limit) << "]" + << " samples over " << NFmt::TDelay(Conf.Spent) + << " per test"; + } + } + + template<typename TOne, typename ... TArgs> + void Do(TArgs&& ... args) + { + TOne one(Logger, Mass, std::forward<TArgs>(args)...); + + Run(&TRunner::DoScan, static_cast<IPerfTable&>(one)); + Run(&TRunner::DoOnce, static_cast<IPerfTable&>(one), ui64(3), true); + Run(&TRunner::DoOnce, static_cast<IPerfTable&>(one), ui64(-1), true); + Run(&TRunner::DoOnce, static_cast<IPerfTable&>(one), ui64(-1), false); + } + + private: + template<typename ... TArgs> + void Run(void(TRunner::*fn)(TMeter&, TArgs...), TArgs&& ... args) + { + TMeter meter(Conf.Spent, Conf.Least, Conf.Limit); + + (this->*fn)(meter, std::forward<TArgs>(args)...); + + Cout << " " << meter.Report(); + } + + void DoScan(TMeter &meter, IPerfTable &test) + { + ui64 last = 0; + + test.Seek({ }, ESeek::Lower); + + while (const auto once = meter.Take(last)) { + if (last = test.Scan(once, Sponge)) { + test.Seek({ }, ESeek::Lower); + } + + last = once - last; + } + } + + void DoOnce(TMeter &meter, IPerfTable &test, ui64 span_, bool exists) + { + TMersenne<ui64> rnd; + + const NTest::TRowTool tool(*Mass.Model->Scheme); + const auto &heap = exists ? Mass.Saved : Mass.Holes; + const auto span = Min(span_, heap.Size()); + + for (ui64 off = 0; meter.Take(1);) { + const auto key = tool.LookupKey(*(heap.begin() + off)); + + test.Once(key, Sponge); + + off = (off + rnd.Uniform(0, span)) % heap.Size(); + } + } + + private: + ILogger * const Logger = nullptr; + const NPerf::TConf Conf; + const NTest::TMass &Mass; + NTest::TSponge &Sponge; + }; +} +} +} diff --git a/ydb/core/tablet_flat/test/tool/perf/sponge.h b/ydb/core/tablet_flat/test/tool/perf/sponge.h index 4fcce7a6bd..8bcf384c59 100644 --- a/ydb/core/tablet_flat/test/tool/perf/sponge.h +++ b/ydb/core/tablet_flat/test/tool/perf/sponge.h @@ -1,101 +1,101 @@ -#pragma once - -#include "defs.h" -#include "names.h" -#include "logger.h" - +#pragma once + +#include "defs.h" +#include "names.h" +#include "logger.h" + #include <ydb/core/tablet_flat/flat_row_state.h> -#include <util/stream/format.h> -#include <util/digest/murmur.h> -#include <util/digest/city.h> -#include <util/digest/fnv.h> - -namespace NKikimr { -namespace NTable { -namespace NTest { - - struct TSponge { - TSponge(ESponge kind) : Kind(kind) { } - +#include <util/stream/format.h> +#include <util/digest/murmur.h> +#include <util/digest/city.h> +#include <util/digest/fnv.h> + +namespace NKikimr { +namespace NTable { +namespace NTest { + + struct TSponge { + TSponge(ESponge kind) : Kind(kind) { } + void Describe(IOutputStream &out) const noexcept - { - out - << "Sponge{" - << NFmt::TLarge(Rows) << "r " << NFmt::TLarge(Cells) << "c" - << " in " << NFmt::TLarge(Bytes) << "b" - << " max " << NFmt::TLarge(Upper) - << ", " << NFmt::Do(Kind) << " " << Hex(Value, HF_FULL) - << "}"; - } - - void operator()(const TRowState &row) noexcept - { - Rows += 1; - - const auto op = row.GetRowState(); - - if (Kind == ESponge::None) { - + { + out + << "Sponge{" + << NFmt::TLarge(Rows) << "r " << NFmt::TLarge(Cells) << "c" + << " in " << NFmt::TLarge(Bytes) << "b" + << " max " << NFmt::TLarge(Upper) + << ", " << NFmt::Do(Kind) << " " << Hex(Value, HF_FULL) + << "}"; + } + + void operator()(const TRowState &row) noexcept + { + Rows += 1; + + const auto op = row.GetRowState(); + + if (Kind == ESponge::None) { + } else if (op != ERowOp::Upsert && op != ERowOp::Reset) { - Value += 1; - - } else if (const ui32 cols = row.Size()) { - for (ui32 it = 0; it < cols; it++) { - auto &cell = row.Get(it); - - (*this)(cell.Data(), cell.Size()); - } - } - } - - void operator()(const void *ptr_, ui64 bytes) noexcept - { - Bytes += bytes, Cells += 1, Upper = Max(Upper, bytes); - - auto *ptr = static_cast<const char*>(ptr_); - - if (Kind == ESponge::Fnv) { - Value = FnvHash(ptr, bytes, Value); - } else if (Kind == ESponge::Murmur) { - Value = MurmurHash(ptr, bytes, Value); - } else if (Kind == ESponge::City) { - Value = CityHash64WithSeed(ptr, bytes, Value); - } else if (Kind == ESponge::Xor) { - Value = XorHash(ptr, bytes, Value); - } - } - - static ui64 XorHash(const char *ptr, size_t bytes, ui64 val) - { - while (bytes) { - if (bytes >= 8) { - val ^= *reinterpret_cast<const ui64*>(ptr); - ptr += 8, bytes -= 8; - } else if (bytes >= 4) { - val ^= *reinterpret_cast<const ui32*>(ptr); - ptr += 4, bytes -= 4; - } else if (bytes >= 2) { - val ^= *reinterpret_cast<const ui16*>(ptr); - ptr += 2, bytes -= 2; - } else { - val ^= *reinterpret_cast<const ui8*>(ptr); - ptr += 1, bytes -= 1; - } - } - - return val; - } - - const ESponge Kind = ESponge::None; - - private: - ui64 Bytes = 0; - ui64 Rows = 0; - ui64 Cells = 0; - ui64 Upper = 0; - ui64 Value = 0; - }; - -} -} -} + Value += 1; + + } else if (const ui32 cols = row.Size()) { + for (ui32 it = 0; it < cols; it++) { + auto &cell = row.Get(it); + + (*this)(cell.Data(), cell.Size()); + } + } + } + + void operator()(const void *ptr_, ui64 bytes) noexcept + { + Bytes += bytes, Cells += 1, Upper = Max(Upper, bytes); + + auto *ptr = static_cast<const char*>(ptr_); + + if (Kind == ESponge::Fnv) { + Value = FnvHash(ptr, bytes, Value); + } else if (Kind == ESponge::Murmur) { + Value = MurmurHash(ptr, bytes, Value); + } else if (Kind == ESponge::City) { + Value = CityHash64WithSeed(ptr, bytes, Value); + } else if (Kind == ESponge::Xor) { + Value = XorHash(ptr, bytes, Value); + } + } + + static ui64 XorHash(const char *ptr, size_t bytes, ui64 val) + { + while (bytes) { + if (bytes >= 8) { + val ^= *reinterpret_cast<const ui64*>(ptr); + ptr += 8, bytes -= 8; + } else if (bytes >= 4) { + val ^= *reinterpret_cast<const ui32*>(ptr); + ptr += 4, bytes -= 4; + } else if (bytes >= 2) { + val ^= *reinterpret_cast<const ui16*>(ptr); + ptr += 2, bytes -= 2; + } else { + val ^= *reinterpret_cast<const ui8*>(ptr); + ptr += 1, bytes -= 1; + } + } + + return val; + } + + const ESponge Kind = ESponge::None; + + private: + ui64 Bytes = 0; + ui64 Rows = 0; + ui64 Cells = 0; + ui64 Upper = 0; + ui64 Value = 0; + }; + +} +} +} diff --git a/ydb/core/tablet_flat/test/tool/perf/ya.make b/ydb/core/tablet_flat/test/tool/perf/ya.make index dc0e8ca728..e6d3d128ea 100644 --- a/ydb/core/tablet_flat/test/tool/perf/ya.make +++ b/ydb/core/tablet_flat/test/tool/perf/ya.make @@ -1,17 +1,17 @@ -PROGRAM(table-perf) - +PROGRAM(table-perf) + OWNER(g:kikimr) - -SRCS( + +SRCS( colons.cpp - main.cpp -) - -PEERDIR( + main.cpp +) + +PEERDIR( ydb/core/tablet_flat/test/libs/table library/cpp/charset library/cpp/getopt ydb/core/tablet_flat -) - -END() +) + +END() diff --git a/ydb/core/tablet_flat/test/tool/surg/main.cpp b/ydb/core/tablet_flat/test/tool/surg/main.cpp index c196de6a7e..701f7987eb 100644 --- a/ydb/core/tablet_flat/test/tool/surg/main.cpp +++ b/ydb/core/tablet_flat/test/tool/surg/main.cpp @@ -6,34 +6,34 @@ #include <ydb/core/protos/scheme_log.pb.h> #include <ydb/core/protos/tablet.pb.h> #include <ydb/core/util/pb.h> - + #include <library/cpp/getopt/last_getopt.h> #include <library/cpp/blockcodecs/codecs.h> -#include <util/generic/yexception.h> -#include <util/stream/file.h> -#include <array> - -namespace NKikimr { -namespace NTable { -namespace NTest { - - struct TNames { - +#include <util/generic/yexception.h> +#include <util/stream/file.h> +#include <array> + +namespace NKikimr { +namespace NTable { +namespace NTest { + + struct TNames { + static const char* Do(ERowOp rop) - { - static const std::array<const char*, 6> names { { - "Absent", - "Upsert", - "Erase", - "Reset", - "Update", - "Insert" - }}; - - return ui8(rop) < names.size() ? names[ui8(rop)] : "?error"; - } - }; - + { + static const std::array<const char*, 6> names { { + "Absent", + "Upsert", + "Erase", + "Reset", + "Update", + "Insert" + }}; + + return ui8(rop) < names.size() ? names[ui8(rop)] : "?error"; + } + }; + class TDumpValue { public: TDumpValue(const TRawTypeValue& value) @@ -66,50 +66,50 @@ namespace NTest { const TRawTypeValue& Value; }; - struct TDump { - using TKeys = TArrayRef<const TRawTypeValue>; - using TOps = TArrayRef<const TUpdateOp>; - - TDump(IOutputStream &out) : Out(out) { } - - bool NeedIn(ui32) noexcept - { - return true; - } - - void DoBegin(ui32 tail, ui32 head, ui64 serial, ui64 stamp) noexcept - { - Out - << " +Begin ABI[" << tail << ", " << head << "]" - << " {" << serial << " " << NFmt::TStamp(stamp) << "}" - << Endl; - } - + struct TDump { + using TKeys = TArrayRef<const TRawTypeValue>; + using TOps = TArrayRef<const TUpdateOp>; + + TDump(IOutputStream &out) : Out(out) { } + + bool NeedIn(ui32) noexcept + { + return true; + } + + void DoBegin(ui32 tail, ui32 head, ui64 serial, ui64 stamp) noexcept + { + Out + << " +Begin ABI[" << tail << ", " << head << "]" + << " {" << serial << " " << NFmt::TStamp(stamp) << "}" + << Endl; + } + void DoAnnex(TArrayRef<const TStdPad<NPageCollection::TGlobId>> annex) noexcept - { - Out << " | Annex " << annex.size() << " items" << Endl; - - for (auto &one: annex) - Out << " | " << (*one).Group << " : " << (*one).Logo << Endl; - } - + { + Out << " | Annex " << annex.size() << " items" << Endl; + + for (auto &one: annex) + Out << " | " << (*one).Group << " : " << (*one).Logo << Endl; + } + void DoUpdate(ui32 tid, ERowOp rop, TKeys key, TOps ops, TRowVersion rowVersion) noexcept - { - ui32 keyBytes = 0, opsBytes = 0; - - for (auto &one: key) keyBytes += one.Size(); + { + ui32 keyBytes = 0, opsBytes = 0; + + for (auto &one: key) keyBytes += one.Size(); for (auto &one: ops) opsBytes += one.AsRef().size(); - - Updates++, KeyBytes += keyBytes, OpsBytes += opsBytes; - KeyItems += key.size(), OpsItems += ops.size(); - - Out - << " | Update " << tid - << ": " << TNames::Do(rop) << "." << unsigned(rop) + + Updates++, KeyBytes += keyBytes, OpsBytes += opsBytes; + KeyItems += key.size(), OpsItems += ops.size(); + + Out + << " | Update " << tid + << ": " << TNames::Do(rop) << "." << unsigned(rop) << ", " << key.size() << " keys (" << keyBytes << "b)" << " " << ops.size() << " ops (" << opsBytes << "b)" << " " << rowVersion - << Endl; + << Endl; for (const auto& keyValue : key) { Out << " > key: " << TDumpValue(keyValue) << " <" << Endl; @@ -117,8 +117,8 @@ namespace NTest { for (const auto& op : ops) { Out << " > col " << op.Tag << ": " << TDumpValue(op.Value) << " <" << Endl; } - } - + } + void DoUpdateTx(ui32 tid, ERowOp rop, TKeys key, TOps ops, ui64 txId) noexcept { ui32 keyBytes = 0, opsBytes = 0; @@ -156,49 +156,49 @@ namespace NTest { } void DoFlush(ui32 tid, ui64 stamp, TEpoch epoch) noexcept - { - Out - << " | Flush " << tid << ", " << epoch << " eph" - << ", stamp " << NFmt::TStamp(stamp) << Endl; - } - - void Finalize() const noexcept - { - Out - << " ' Stats: " << Updates << " ups" - << ", keys " << KeyItems << " " << KeyBytes << "b" - << ", ops " << OpsItems << " " << OpsBytes << "b" - << Endl; - } - - private: - IOutputStream &Out; - - ui64 Updates = 0; - ui64 KeyItems = 0; - ui64 KeyBytes = 0; - ui64 OpsItems = 0; - ui64 OpsBytes = 0; - }; - - template<typename TProto> - struct TProtoDump { - TProtoDump(IOutputStream &out) : Out(out) { } - - void Do(TArrayRef<const char> plain) - { - TProto proto; - - if (!ParseFromStringNoSizeLimit(proto, plain)) { - throw yexception() << "Failed to parse proto blob"; - } else { - Out << proto.DebugString(); - } - } - - private: - IOutputStream &Out; - }; + { + Out + << " | Flush " << tid << ", " << epoch << " eph" + << ", stamp " << NFmt::TStamp(stamp) << Endl; + } + + void Finalize() const noexcept + { + Out + << " ' Stats: " << Updates << " ups" + << ", keys " << KeyItems << " " << KeyBytes << "b" + << ", ops " << OpsItems << " " << OpsBytes << "b" + << Endl; + } + + private: + IOutputStream &Out; + + ui64 Updates = 0; + ui64 KeyItems = 0; + ui64 KeyBytes = 0; + ui64 OpsItems = 0; + ui64 OpsBytes = 0; + }; + + template<typename TProto> + struct TProtoDump { + TProtoDump(IOutputStream &out) : Out(out) { } + + void Do(TArrayRef<const char> plain) + { + TProto proto; + + if (!ParseFromStringNoSizeLimit(proto, plain)) { + throw yexception() << "Failed to parse proto blob"; + } else { + Out << proto.DebugString(); + } + } + + private: + IOutputStream &Out; + }; void DumpPart(const NKikimrExecutorFlat::TLogTableSnap& part) { Cerr << " | Table " << part.GetTable() << " level " << part.GetCompactionLevel() << Endl; @@ -243,50 +243,50 @@ namespace NTest { } } -} -} -} - -int main(int argc, char *argv[]) -{ - using namespace NLastGetopt; - using namespace NKikimr; - using namespace NKikimr::NTable; - - TOpts opts; - - opts.AddLongOption("path", "path to blob") - .RequiredArgument("FILE").Required(); - opts.AddLongOption("blob", "type of blob to read") - .RequiredArgument("STR").Required(); - opts.AddLongOption("codec", "blob encoding: lz4, plain") - .RequiredArgument("STR").DefaultValue("plain"); - - THolder<TOptsParseResult> res(new TOptsParseResult(&opts, argc, argv)); - - auto raw = TFileInput(res->Get("path")).ReadAll(); - - if (!res->Has("codec") || !strcmp(res->Get("codec"), "plain")) { - /* Blob is already decoded, nothing to do */ - } else if (!strcmp(res->Get("codec"), "lz4")) { - raw = NBlockCodecs::Codec("lz4fast")->Decode(raw); - } else { - throw yexception() << "Unknown blob encoding " << res->Get("codec"); - } - - Cerr << " decoded blob has " << raw.size() << " bytes" << Endl; - - if (!strcmp(res->Get("blob"), "redo")) { - NTest::TDump dump(Cerr); - - NRedo::TPlayer<NTest::TDump>(dump).Replay(raw); - - dump.Finalize(); - - } else if (!strcmp(res->Get("blob"), "alter")) { - NTest::TProtoDump<NTabletFlatScheme::TSchemeChanges>(Cerr).Do(raw); - } else if (!strcmp(res->Get("blob"), "snap")) { - NTest::TProtoDump<NKikimrExecutorFlat::TLogSnapshot>(Cerr).Do(raw); +} +} +} + +int main(int argc, char *argv[]) +{ + using namespace NLastGetopt; + using namespace NKikimr; + using namespace NKikimr::NTable; + + TOpts opts; + + opts.AddLongOption("path", "path to blob") + .RequiredArgument("FILE").Required(); + opts.AddLongOption("blob", "type of blob to read") + .RequiredArgument("STR").Required(); + opts.AddLongOption("codec", "blob encoding: lz4, plain") + .RequiredArgument("STR").DefaultValue("plain"); + + THolder<TOptsParseResult> res(new TOptsParseResult(&opts, argc, argv)); + + auto raw = TFileInput(res->Get("path")).ReadAll(); + + if (!res->Has("codec") || !strcmp(res->Get("codec"), "plain")) { + /* Blob is already decoded, nothing to do */ + } else if (!strcmp(res->Get("codec"), "lz4")) { + raw = NBlockCodecs::Codec("lz4fast")->Decode(raw); + } else { + throw yexception() << "Unknown blob encoding " << res->Get("codec"); + } + + Cerr << " decoded blob has " << raw.size() << " bytes" << Endl; + + if (!strcmp(res->Get("blob"), "redo")) { + NTest::TDump dump(Cerr); + + NRedo::TPlayer<NTest::TDump>(dump).Replay(raw); + + dump.Finalize(); + + } else if (!strcmp(res->Get("blob"), "alter")) { + NTest::TProtoDump<NTabletFlatScheme::TSchemeChanges>(Cerr).Do(raw); + } else if (!strcmp(res->Get("blob"), "snap")) { + NTest::TProtoDump<NKikimrExecutorFlat::TLogSnapshot>(Cerr).Do(raw); TProtoBox<NKikimrExecutorFlat::TLogSnapshot> proto(raw); @@ -338,33 +338,33 @@ int main(int argc, char *argv[]) Cerr << " --------------------" << Endl; } - } else if (!strcmp(res->Get("blob"), "switch")) { - NTest::TProtoDump<NKikimrExecutorFlat::TTablePartSwitch>(Cerr).Do(raw); + } else if (!strcmp(res->Get("blob"), "switch")) { + NTest::TProtoDump<NKikimrExecutorFlat::TTablePartSwitch>(Cerr).Do(raw); TProtoBox<NKikimrExecutorFlat::TTablePartSwitch> proto(raw); if (proto.HasIntroducedParts()) { NTest::DumpPart(proto.GetIntroducedParts()); } - } else if (!strcmp(res->Get("blob"), "borrow")) { - NTest::TProtoDump<NKikimrExecutorFlat::TBorrowedPart>(Cerr).Do(raw); - } else if (!strcmp(res->Get("blob"), "tablet")) { - NTest::TProtoDump<NKikimrTabletBase::TTabletLogEntry>(Cerr).Do(raw); - - TProtoBox<NKikimrTabletBase::TTabletLogEntry> proto(raw); - - for (const auto &ref : proto.GetReferences()) { - auto logo = LogoBlobIDFromLogoBlobID(ref); - - Cerr << " | Ref " << logo << Endl; - } - - for (const auto &ref : proto.GetGcDiscovered()) { - auto logo = LogoBlobIDFromLogoBlobID(ref); - - Cerr << " | GC+ " << logo << Endl; - } - + } else if (!strcmp(res->Get("blob"), "borrow")) { + NTest::TProtoDump<NKikimrExecutorFlat::TBorrowedPart>(Cerr).Do(raw); + } else if (!strcmp(res->Get("blob"), "tablet")) { + NTest::TProtoDump<NKikimrTabletBase::TTabletLogEntry>(Cerr).Do(raw); + + TProtoBox<NKikimrTabletBase::TTabletLogEntry> proto(raw); + + for (const auto &ref : proto.GetReferences()) { + auto logo = LogoBlobIDFromLogoBlobID(ref); + + Cerr << " | Ref " << logo << Endl; + } + + for (const auto &ref : proto.GetGcDiscovered()) { + auto logo = LogoBlobIDFromLogoBlobID(ref); + + Cerr << " | GC+ " << logo << Endl; + } + for (const auto &ref : proto.GetGcLeft()) { auto logo = LogoBlobIDFromLogoBlobID(ref); @@ -379,11 +379,11 @@ int main(int argc, char *argv[]) dump.Finalize(); } - } else if (!strcmp(res->Get("blob"), "unlog")) { - TProtoBox<NKikimrTabletBase::TTabletLogEntry> proto(raw); - - if (proto.HasEmbeddedLogBody()) Cout << proto.GetEmbeddedLogBody(); - } else { - throw yexception() << "Unknown blob type " << res->Get("blob"); - } -} + } else if (!strcmp(res->Get("blob"), "unlog")) { + TProtoBox<NKikimrTabletBase::TTabletLogEntry> proto(raw); + + if (proto.HasEmbeddedLogBody()) Cout << proto.GetEmbeddedLogBody(); + } else { + throw yexception() << "Unknown blob type " << res->Get("blob"); + } +} diff --git a/ydb/core/tablet_flat/test/tool/surg/ya.make b/ydb/core/tablet_flat/test/tool/surg/ya.make index 18495b00b9..e2590d3ff8 100644 --- a/ydb/core/tablet_flat/test/tool/surg/ya.make +++ b/ydb/core/tablet_flat/test/tool/surg/ya.make @@ -1,14 +1,14 @@ -PROGRAM() - +PROGRAM() + OWNER(g:kikimr) - -SRCS( - main.cpp -) - -PEERDIR( + +SRCS( + main.cpp +) + +PEERDIR( library/cpp/getopt ydb/core/tablet_flat -) - -END() +) + +END() diff --git a/ydb/core/tablet_flat/test/tool/ya.make b/ydb/core/tablet_flat/test/tool/ya.make index e3f445cf0b..bcee245bf5 100644 --- a/ydb/core/tablet_flat/test/tool/ya.make +++ b/ydb/core/tablet_flat/test/tool/ya.make @@ -1,6 +1,6 @@ OWNER(g:kikimr) - -RECURSE( - surg - perf -) + +RECURSE( + surg + perf +) diff --git a/ydb/core/tablet_flat/ut/flat_database_ut_common.h b/ydb/core/tablet_flat/ut/flat_database_ut_common.h index 966dc0ba35..7a4ec9f00a 100644 --- a/ydb/core/tablet_flat/ut/flat_database_ut_common.h +++ b/ydb/core/tablet_flat/ut/flat_database_ut_common.h @@ -1,7 +1,7 @@ #pragma once -#include "flat_test_db_helpers.h" - +#include "flat_test_db_helpers.h" + #include <ydb/core/tablet_flat/flat_dbase_scheme.h> #include <ydb/core/tablet_flat/flat_row_scheme.h> #include <ydb/core/tablet_flat/flat_mem_warm.h> diff --git a/ydb/core/tablet_flat/ut/flat_test_db.cpp b/ydb/core/tablet_flat/ut/flat_test_db.cpp index b65757d4bb..df391aaf89 100644 --- a/ydb/core/tablet_flat/ut/flat_test_db.cpp +++ b/ydb/core/tablet_flat/ut/flat_test_db.cpp @@ -9,7 +9,7 @@ #include <library/cpp/testing/unittest/registar.h> namespace NKikimr { -namespace NTable { +namespace NTable { struct TFakeKey { TVector<TFakeTableCell> Columns; @@ -38,26 +38,26 @@ struct TFakeVal { bool IsDeleted; TMap<TTag, TFakeTableCell> Columns; - void ApplyUpdate(const TFakeVal& other) - { - if (IsDeleted = other.IsDeleted) { + void ApplyUpdate(const TFakeVal& other) + { + if (IsDeleted = other.IsDeleted) { Columns.clear(); - } else { - for (auto &val: other.Columns) - Columns[val.first] = val.second; + } else { + for (auto &val: other.Columns) + Columns[val.first] = val.second; } - } - - TCell Read( - TArrayRef<const TFakeTableCell> key, const TColumn &col) - const noexcept - { - if (col.KeyOrder != Max<ui32>()) { - return *key[col.KeyOrder]; /* has no default values */ - } else { - auto *val = Columns.FindPtr(col.Id); - - return val ? **val : col.Null; + } + + TCell Read( + TArrayRef<const TFakeTableCell> key, const TColumn &col) + const noexcept + { + if (col.KeyOrder != Max<ui32>()) { + return *key[col.KeyOrder]; /* has no default values */ + } else { + auto *val = Columns.FindPtr(col.Id); + + return val ? **val : col.Null; } } @@ -72,7 +72,7 @@ typedef TMap<TFakeKey, TFakeVal, TFakeKeyComparator> TFakeTable; class TFakeDbIterator : public ITestIterator { TVector<ui32> ValueTags; - TVector<const TColumn*> Cols; + TVector<const TColumn*> Cols; TFakeTable::const_iterator RowIt; TFakeTable::const_iterator RowEnd; @@ -81,23 +81,23 @@ class TFakeDbIterator : public ITestIterator { TVector<NScheme::TTypeId> ValueTypes; TVector<TCell> ValueCells; - bool First = true; + bool First = true; public: - explicit TFakeDbIterator(const TScheme& scheme, ui32 root, TTagsRef tags, TFakeTable::const_iterator rowIt, TFakeTable::const_iterator rowEnd) - : ValueTags(tags.begin(), tags.end()) + explicit TFakeDbIterator(const TScheme& scheme, ui32 root, TTagsRef tags, TFakeTable::const_iterator rowIt, TFakeTable::const_iterator rowEnd) + : ValueTags(tags.begin(), tags.end()) , RowIt(rowIt) , RowEnd(rowEnd) { - Cols.reserve(tags.size()); - ValueTypes.reserve(tags.size()); - ValueCells.reserve(tags.size()); - + Cols.reserve(tags.size()); + ValueTypes.reserve(tags.size()); + ValueCells.reserve(tags.size()); + for (auto tag : ValueTags) { - auto *column = scheme.GetColumnInfo(root, tag); - - Cols.push_back(column); - ValueTypes.push_back(column->PType); + auto *column = scheme.GetColumnInfo(root, tag); + + Cols.push_back(column); + ValueTypes.push_back(column->PType); } for (auto tag : scheme.GetTableInfo(root)->KeyColumns) { @@ -112,23 +112,23 @@ public: } EReady Next(ENext mode) override - { - /* Should position to the first row on first Next() to conform db - iterator API, but iterator is already positioned to first row - just after ctor invocation. - */ - - while (IsValid()) { - if (!std::exchange(First, false)) - ++RowIt; - + { + /* Should position to the first row on first Next() to conform db + iterator API, but iterator is already positioned to first row + just after ctor invocation. + */ + + while (IsValid()) { + if (!std::exchange(First, false)) + ++RowIt; + if (!(mode == ENext::Data && IsValid() && RowIt->second.IsDeleted)) - break; - } - + break; + } + FillCells(); - - return IsValid () ? EReady::Data : EReady::Gone; + + return IsValid () ? EReady::Data : EReady::Gone; } bool IsValid() override { @@ -171,11 +171,11 @@ private: if (!IsValid()) return; - for (const TFakeTableCell& kc : RowIt->first.Columns) - KeyCells.push_back(*kc); + for (const TFakeTableCell& kc : RowIt->first.Columns) + KeyCells.push_back(*kc); - for (auto *col: Cols) - ValueCells.emplace_back(RowIt->second.Read(RowIt->first.Columns, *col)); + for (auto *col: Cols) + ValueCells.emplace_back(RowIt->second.Read(RowIt->first.Columns, *col)); } }; @@ -195,19 +195,19 @@ public: TString FinishTransaction(bool commit) override { if (commit) { - TAutoPtr<TSchemeChanges> schemeDeltaRecs = SchemeChanges.Flush(); - TSchemeModifier(*Scheme).Apply(*schemeDeltaRecs); + TAutoPtr<TSchemeChanges> schemeDeltaRecs = SchemeChanges.Flush(); + TSchemeModifier(*Scheme).Apply(*schemeDeltaRecs); // Apply scheme operations that affect existing data for (ui32 i = 0; i < schemeDeltaRecs->DeltaSize(); ++i) { - const TAlterRecord& rec = schemeDeltaRecs->GetDelta(i); + const TAlterRecord& rec = schemeDeltaRecs->GetDelta(i); switch (rec.GetDeltaType()) { - case TAlterRecord::AddTable: + case TAlterRecord::AddTable: Tables[rec.GetTableId()] = TFakeTable(); break; - case TAlterRecord::DropTable: + case TAlterRecord::DropTable: Tables.erase(rec.GetTableId()); break; - case TAlterRecord::DropColumn: + case TAlterRecord::DropColumn: EraseColumnValues(rec.GetTableId(), rec.GetColumnId()); break; default: @@ -226,23 +226,23 @@ public: } } TxChanges.clear(); - SchemeChanges.Flush(); + SchemeChanges.Flush(); return TString(); } void Update(ui32 root, ERowOp rop, TRawVals key, TArrayRef<const TUpdateOp> ops) override - { + { if (rop == ERowOp::Upsert) { - UpdateRow(root, key, ops); + UpdateRow(root, key, ops); } else if (rop == ERowOp::Erase){ - EraseRow(root, key); - } - } - - void UpdateRow(ui32 root, TRawVals key, TArrayRef<const TUpdateOp> ops) - { + EraseRow(root, key); + } + } + + void UpdateRow(ui32 root, TRawVals key, TArrayRef<const TUpdateOp> ops) + { TFakeKey fk; - FillKey(root, fk, key, true); + FillKey(root, fk, key, true); // Copy previous value from the commited data if (!TxChanges[root].contains(fk) && Tables[root].contains(fk)) { @@ -252,24 +252,24 @@ public: // Apply changes TFakeVal& fv = TxChanges[root][fk]; fv.IsDeleted = false; - for (auto &one: ops) { + for (auto &one: ops) { if (one.Op == ECellOp::Null || !one.Value) - fv.Columns[one.Tag].Set({ }); + fv.Columns[one.Tag].Set({ }); else - fv.Columns[one.Tag].Set(one.Value); + fv.Columns[one.Tag].Set(one.Value); } } - void EraseRow(ui32 root, TRawVals key) { + void EraseRow(ui32 root, TRawVals key) { TFakeKey fk; - FillKey(root, fk, key, true); + FillKey(root, fk, key, true); TFakeVal fv; fv.IsDeleted = true; TxChanges[root][fk] = fv; } void Precharge(ui32 root, - TRawVals keyFrom, TRawVals keyTo, + TRawVals keyFrom, TRawVals keyTo, TTagsRef tags, ui32 flags) override { Y_UNUSED(root); Y_UNUSED(keyFrom); @@ -279,42 +279,42 @@ public: } ITestIterator* Iterate(ui32 root, TRawVals key, TTagsRef tags, ELookup mode) noexcept override { - if (!key) { - return new TFakeDbIterator(GetScheme(), root, tags, Tables[root].begin(), Tables[root].end()); + if (!key) { + return new TFakeDbIterator(GetScheme(), root, tags, Tables[root].begin(), Tables[root].end()); } TFakeKey fk; - FillKey(root, fk, key, false); - if (mode == ELookup::ExactMatch) { - auto begin = Tables[root].find(fk); - decltype(begin) end = begin; - - return new TFakeDbIterator(GetScheme(), root, tags, begin, end == Tables[root].end() ? end : ++end); + FillKey(root, fk, key, false); + if (mode == ELookup::ExactMatch) { + auto begin = Tables[root].find(fk); + decltype(begin) end = begin; + + return new TFakeDbIterator(GetScheme(), root, tags, begin, end == Tables[root].end() ? end : ++end); } else { - auto begin = Tables[root].lower_bound(fk); - - if (mode == ELookup::GreaterThan && begin != Tables[root].end()) { + auto begin = Tables[root].lower_bound(fk); + + if (mode == ELookup::GreaterThan && begin != Tables[root].end()) { TFakeKeyComparator keyLess; // proceed to the next row if keys are equal - if (!keyLess(fk, begin->first) && !keyLess(begin->first, fk)) - ++begin; + if (!keyLess(fk, begin->first) && !keyLess(begin->first, fk)) + ++begin; } - - return new TFakeDbIterator(GetScheme(), root, tags, begin, Tables[root].end()); + + return new TFakeDbIterator(GetScheme(), root, tags, begin, Tables[root].end()); } } - void Apply(const TSchemeChanges &delta) override - { - SchemeChanges.Merge(delta); - } - + void Apply(const TSchemeChanges &delta) override + { + SchemeChanges.Merge(delta); + } + private: - void FillKey(ui32, TFakeKey& fk, TRawVals key, bool) const - { - fk.Columns.resize(key.size()); - for (ui32 on = 0; on < fk.Columns.size(); on++) { - fk.Columns[on].Set(key[on]); + void FillKey(ui32, TFakeKey& fk, TRawVals key, bool) const + { + fk.Columns.resize(key.size()); + for (ui32 on = 0; on < fk.Columns.size(); on++) { + fk.Columns[on].Set(key[on]); } } @@ -327,7 +327,7 @@ private: private: THashMap<ui32, TFakeTable> Tables; THashMap<ui32, TFakeTable> TxChanges; - TAlter SchemeChanges; + TAlter SchemeChanges; }; @@ -335,5 +335,5 @@ TAutoPtr<ITestDb> CreateFakeDb() { return new TFakeDb(); } -} // namspace NTable +} // namspace NTable } // namespace NKikimr diff --git a/ydb/core/tablet_flat/ut/flat_test_db.h b/ydb/core/tablet_flat/ut/flat_test_db.h index ed0af81c68..26669d33f6 100644 --- a/ydb/core/tablet_flat/ut/flat_test_db.h +++ b/ydb/core/tablet_flat/ut/flat_test_db.h @@ -8,7 +8,7 @@ #include <library/cpp/testing/unittest/registar.h> namespace NKikimr { -namespace NTable { +namespace NTable { // Unified interface for iterator class ITestIterator { @@ -26,9 +26,9 @@ public: // Unified interface for real DB implementation and simple reference implementation class ITestDb { public: - using ECodec = NPage::ECodec; - using ECache = NPage::ECache; - + using ECodec = NPage::ECodec; + using ECache = NPage::ECache; + virtual ~ITestDb() {} virtual void Init(const TScheme& scheme) = 0; @@ -37,10 +37,10 @@ public: virtual void Update(ui32 root, ERowOp, TRawVals key, TArrayRef<const TUpdateOp> ops) = 0; virtual void Precharge(ui32 root, - TRawVals keyFrom, TRawVals keyTo, - TTagsRef tags, ui32 flags) = 0; - virtual ITestIterator* Iterate(ui32 root, TRawVals key, TTagsRef tags, ELookup) = 0; - virtual void Apply(const TSchemeChanges&) = 0; + TRawVals keyFrom, TRawVals keyTo, + TTagsRef tags, ui32 flags) = 0; + virtual ITestIterator* Iterate(ui32 root, TRawVals key, TTagsRef tags, ELookup) = 0; + virtual void Apply(const TSchemeChanges&) = 0; }; // Means that iterator needs pages to be loaded @@ -58,17 +58,17 @@ public: {} EReady Next(ENext mode) override - { + { const auto ready = Iter->Next(mode); - - if (ready == EReady::Page) + + if (ready == EReady::Page) throw TIteratorNotReady(); - - return ready; + + return ready; } bool IsValid() override { - return Iter->Last() == EReady::Data; + return Iter->Last() == EReady::Data; } bool IsRowDeleted() override { @@ -84,7 +84,7 @@ public: } TCell GetValue(ui32 idx) override { - return Iter->Row().Get(idx); + return Iter->Row().Get(idx); } }; @@ -112,7 +112,7 @@ public: } const TScheme& GetScheme() const override { - return Db->GetScheme(); + return Db->GetScheme(); } TString FinishTransaction(bool commit) override { @@ -122,28 +122,28 @@ public: } void Update(ui32 root, ERowOp rop, TRawVals key, TArrayRef<const TUpdateOp> ops) override - { - Db->Update(root, rop, key, ops); + { + Db->Update(root, rop, key, ops); } void Precharge(ui32 root, - TRawVals keyFrom, TRawVals keyTo, + TRawVals keyFrom, TRawVals keyTo, TTagsRef tags, ui32 flags) override { - bool res = Db->Precharge(root, keyFrom, keyTo, tags, flags, -1, -1); + bool res = Db->Precharge(root, keyFrom, keyTo, tags, flags, -1, -1); if (!res) throw TIteratorNotReady(); } ITestIterator* Iterate(ui32 root, TRawVals key, TTagsRef tags, ELookup mode) override { - if (auto res = Db->Iterate(root, key, tags, mode)) - return new TFlatDbIterator(res); - throw TIteratorNotReady(); + if (auto res = Db->Iterate(root, key, tags, mode)) + return new TFlatDbIterator(res); + throw TIteratorNotReady(); } - void Apply(const TSchemeChanges &delta) override - { - Db->Alter().Merge(delta); - } + void Apply(const TSchemeChanges &delta) override + { + Db->Alter().Merge(delta); + } }; @@ -163,11 +163,11 @@ public: {} EReady Next(ENext mode) override - { + { const auto one = It1->Next(mode); const auto two = It2->Next(mode); - UNIT_ASSERT(one == two); - return one; + UNIT_ASSERT(one == two); + return one; } bool IsValid() override { @@ -205,8 +205,8 @@ public: private: static void VerifyEqualTuples(const TDbTupleRef& a, const TDbTupleRef& b) { - TString aStr = PrintRow(a); - TString bStr = PrintRow(b); + TString aStr = PrintRow(a); + TString bStr = PrintRow(b); UNIT_ASSERT_NO_DIFF(aStr, bStr); } }; @@ -248,29 +248,29 @@ public: } void Update(ui32 root, ERowOp rop, TRawVals key, TArrayRef<const TUpdateOp> ops) override { - Db1->Update(root, rop, key, ops); - Db2->Update(root, rop, key, ops); + Db1->Update(root, rop, key, ops); + Db2->Update(root, rop, key, ops); } void Precharge(ui32 root, - TRawVals keyFrom, TRawVals keyTo, + TRawVals keyFrom, TRawVals keyTo, TTagsRef tags, ui32 flags) override { - Db1->Precharge(root, keyFrom, keyTo, tags, flags); - Db2->Precharge(root, keyFrom, keyTo, tags, flags); + Db1->Precharge(root, keyFrom, keyTo, tags, flags); + Db2->Precharge(root, keyFrom, keyTo, tags, flags); } ITestIterator* Iterate(ui32 root, TRawVals key, TTagsRef tags, ELookup mode) override { return new TIteratorPair( - Db1->Iterate(root, key, tags, mode), - Db2->Iterate(root, key, tags, mode)); - } - - void Apply(const TSchemeChanges &delta) override - { - Db1->Apply(delta); - Db2->Apply(delta); + Db1->Iterate(root, key, tags, mode), + Db2->Iterate(root, key, tags, mode)); } + void Apply(const TSchemeChanges &delta) override + { + Db1->Apply(delta); + Db2->Apply(delta); + } + bool CompareDBs() { bool res = true; for (auto& ti : Db1->GetScheme().Tables) { @@ -290,16 +290,16 @@ private: valTags.push_back(ci.first); } - TAutoPtr<ITestIterator> it1 = Db1->Iterate(root, {}, valTags, ELookup::GreaterOrEqualThan); - TAutoPtr<ITestIterator> it2 = Db2->Iterate(root, {}, valTags, ELookup::GreaterOrEqualThan); - - ui64 errors = 0; - int cmp = 0; - EReady rdy1 = EReady::Gone; - EReady rdy2 = EReady::Gone; + TAutoPtr<ITestIterator> it1 = Db1->Iterate(root, {}, valTags, ELookup::GreaterOrEqualThan); + TAutoPtr<ITestIterator> it2 = Db2->Iterate(root, {}, valTags, ELookup::GreaterOrEqualThan); + ui64 errors = 0; + int cmp = 0; + EReady rdy1 = EReady::Gone; + EReady rdy2 = EReady::Gone; + while (true) { - TDbTupleRef key1, key2, val1, val2; + TDbTupleRef key1, key2, val1, val2; if ((rdy1 = cmp <= 0 ? it1->Next(ENext::Data) : rdy1) == EReady::Data) { key1 = it1->GetKey(); @@ -311,46 +311,46 @@ private: val2 = it2->GetValues(); } - if (rdy1 == rdy2 && rdy2 == EReady::Gone) { - break; - } else if (rdy1 == EReady::Data && rdy2 != EReady::Data) { - cmp = -1; - } else if (rdy1 != EReady::Data && rdy2 == EReady::Data) { - cmp = 1; - } else { - cmp = CmpTupleRefs(key1, key2); - } - - errors += (cmp != 0) ? 1 : 0; - - if (cmp > 0) { - Cerr << "Missing row in DB #1:" << Endl - << PrintRow(key2) << " : "<< PrintRow(val2) << Endl << Endl; - } else if (cmp < 0) { - Cerr << "Missing row in DB #2:" << Endl - << PrintRow(key1) << " : "<< PrintRow(val1) << Endl << Endl; - } else if (CmpTupleRefs(val1, val2) != 0) { - errors++; - Cerr << "Different values for key " << PrintRow(key1) << Endl; - Cerr << PrintRow(val1) << Endl - << PrintRow(val2) << Endl << Endl; + if (rdy1 == rdy2 && rdy2 == EReady::Gone) { + break; + } else if (rdy1 == EReady::Data && rdy2 != EReady::Data) { + cmp = -1; + } else if (rdy1 != EReady::Data && rdy2 == EReady::Data) { + cmp = 1; + } else { + cmp = CmpTupleRefs(key1, key2); + } + + errors += (cmp != 0) ? 1 : 0; + + if (cmp > 0) { + Cerr << "Missing row in DB #1:" << Endl + << PrintRow(key2) << " : "<< PrintRow(val2) << Endl << Endl; + } else if (cmp < 0) { + Cerr << "Missing row in DB #2:" << Endl + << PrintRow(key1) << " : "<< PrintRow(val1) << Endl << Endl; + } else if (CmpTupleRefs(val1, val2) != 0) { + errors++; + Cerr << "Different values for key " << PrintRow(key1) << Endl; + Cerr << PrintRow(val1) << Endl + << PrintRow(val2) << Endl << Endl; } } - - return errors == 0; - } - - static int CmpTupleRefs(const TDbTupleRef &one, const TDbTupleRef &two) { - const auto num = one.ColumnCount; - - if (num != two.ColumnCount) { - Y_FAIL("Got different key columns count"); - } else if (!std::equal(one.Types, one.Types + num, two.Types)) { - Y_FAIL("TDbTupleRef rows types vec are not the same"); - } else { - return CompareTypedCellVectors(one.Columns, two.Columns, one.Types, num); - } - } + + return errors == 0; + } + + static int CmpTupleRefs(const TDbTupleRef &one, const TDbTupleRef &two) { + const auto num = one.ColumnCount; + + if (num != two.ColumnCount) { + Y_FAIL("Got different key columns count"); + } else if (!std::equal(one.Types, one.Types + num, two.Types)) { + Y_FAIL("TDbTupleRef rows types vec are not the same"); + } else { + return CompareTypedCellVectors(one.Columns, two.Columns, one.Types, num); + } + } }; } // namspace NTabletFlatExecutor diff --git a/ydb/core/tablet_flat/ut/flat_test_db_helpers.h b/ydb/core/tablet_flat/ut/flat_test_db_helpers.h index ffc9a36daa..c210807f7b 100644 --- a/ydb/core/tablet_flat/ut/flat_test_db_helpers.h +++ b/ydb/core/tablet_flat/ut/flat_test_db_helpers.h @@ -10,7 +10,7 @@ #include <library/cpp/testing/unittest/registar.h> namespace NKikimr { -namespace NTable { +namespace NTable { struct TFakeTableCell { private: @@ -43,11 +43,11 @@ public: Op = op; } - TCell operator*() const - { - return TCell((const char*)Val.Data(), Val.Size()); - } - + TCell operator*() const + { + return TCell((const char*)Val.Data(), Val.Size()); + } + const TRawTypeValue& Get() const { return Val; } @@ -82,10 +82,10 @@ inline TFakeTableCell MakeNull(ECellOp op) { return c; } -inline TFakeTableCell FromVal(NScheme::TTypeId, std::nullptr_t) { +inline TFakeTableCell FromVal(NScheme::TTypeId, std::nullptr_t) { return MakeNull(ECellOp::Set); -} - +} + inline TFakeTableCell FromVal(NScheme::TTypeId t, TString val) { TFakeTableCell c; c.Set(TRawTypeValue(val.data(), val.size(), t)); @@ -144,7 +144,7 @@ public: Y_VERIFY(tableInfo, "Unknown table id %u", GetRoot()); const ui32* tagId = tableInfo->ColumnNames.FindPtr(tagName); Y_VERIFY(tagId, "Unknown column \"%s\" in table %u", tagName.data(), GetRoot()); - const auto *colInfo = Scheme.GetColumnInfo(GetRoot(), *tagId); + const auto *colInfo = Scheme.GetColumnInfo(GetRoot(), *tagId); Y_VERIFY(colInfo, "Column info not found for table id %u, column id %u", GetRoot(), *tagId); NScheme::TTypeId type = colInfo->PType; TagOps[*tagId] = FromVal(type, val); @@ -156,7 +156,7 @@ public: Y_VERIFY(tableInfo, "Unknown table id %u", GetRoot()); const ui32* tagId = tableInfo->ColumnNames.FindPtr(tagName); Y_VERIFY(tagId, "Unknown column \"%s\" in table %u", tagName.data(), GetRoot()); - const auto * colInfo = Scheme.GetColumnInfo(GetRoot(), *tagId); + const auto * colInfo = Scheme.GetColumnInfo(GetRoot(), *tagId); Y_VERIFY(colInfo, "Column info not found for table id %u, column id %u", GetRoot(), *tagId); TagOps[*tagId] = MakeNull(ECellOp::Null); return *this; @@ -194,25 +194,25 @@ void AppendKeyColumn(ui32 root, const TScheme& scheme, TVector<TFakeTableCell>& // Helps to simplify test code that deals with ITestDb class TDbWrapper { ITestDb& Db; - TScheme Scheme; + TScheme Scheme; public: - using ECodec = NPage::ECodec; - using ECache = NPage::ECache; - + using ECodec = NPage::ECodec; + using ECache = NPage::ECache; + explicit TDbWrapper(ITestDb& db) : Db(db) - , Scheme(Db.GetScheme()) + , Scheme(Db.GetScheme()) {} - ITestDb* operator->() const { return &Db; } - + ITestDb* operator->() const { return &Db; } + TDbRowUpdate Update(ui32 root) { - return TDbRowUpdate(Scheme, root); + return TDbRowUpdate(Scheme, root); } TDbRowErase Erase(ui32 root) { - return TDbRowErase(Scheme, root); + return TDbRowErase(Scheme, root); } void Apply(const TDbRowUpdate& update) { @@ -222,9 +222,9 @@ public: key.push_back(col.Get()); } - TVector<TUpdateOp> ops; + TVector<TUpdateOp> ops; for (const auto& op : update.GetTagOps()) { - ops.push_back(TUpdateOp(op.first, op.second.GetOp(), op.second.Get())); + ops.push_back(TUpdateOp(op.first, op.second.GetOp(), op.second.Get())); } Db.Update(update.GetRoot(), ERowOp::Upsert, key, ops); @@ -240,15 +240,15 @@ public: Db.Update(erase.GetRoot(), ERowOp::Erase, key, { }); } - void Apply(const TSchemeChanges &delta) - { - Db.Apply(delta); - TSchemeModifier(Scheme).Apply(delta); - } - + void Apply(const TSchemeChanges &delta) + { + Db.Apply(delta); + TSchemeModifier(Scheme).Apply(delta); + } + void FinishTransaction(bool commit) { Db.FinishTransaction(commit); - Scheme = Db.GetScheme(); + Scheme = Db.GetScheme(); } }; diff --git a/ydb/core/tablet_flat/ut/ut_bloom.cpp b/ydb/core/tablet_flat/ut/ut_bloom.cpp index 0ba3f5b662..e8654453ed 100644 --- a/ydb/core/tablet_flat/ut/ut_bloom.cpp +++ b/ydb/core/tablet_flat/ut/ut_bloom.cpp @@ -4,307 +4,307 @@ #include <ydb/core/tablet_flat/test/libs/table/model/keys.h> #include <ydb/core/tablet_flat/test/libs/table/model/small.h> #include <ydb/core/tablet_flat/test/libs/table/test_dbase.h> - + #include <library/cpp/testing/unittest/registar.h> - -namespace NKikimr { -namespace NTable { - + +namespace NKikimr { +namespace NTable { + Y_UNIT_TEST_SUITE(Bloom) { - using namespace NTest; - - static const NTest::TMass Mass0(new NTest::TModelS3Hash, 24000, 42, 0.5); - - struct TCooker { + using namespace NTest; + + static const NTest::TMass Mass0(new NTest::TModelS3Hash, 24000, 42, 0.5); + + struct TCooker { static TIntrusiveConstPtr<NPage::TBloom> Make(const TMass &mass, float rate) - { - TCooker cooker(*mass.Model->Scheme, mass.Saved.Size(), rate); - - return cooker.Add(mass.Saved).Flush(); - } - - TCooker(const TRowScheme &scheme, ui64 rows, float rate) - : Tool(scheme) + { + TCooker cooker(*mass.Model->Scheme, mass.Saved.Size(), rate); + + return cooker.Add(mass.Saved).Flush(); + } + + TCooker(const TRowScheme &scheme, ui64 rows, float rate) + : Tool(scheme) , Writer(rows, rate) - { - - } - - TCooker& Add(const TRowsHeap &rows) - { - for (const auto &one : rows) Add(one); - - return *this; - } - - TCooker& Add(const NTest::TRow &row) - { - const auto key = Tool.KeyCells(row); - - return Writer.Add(key), *this; - } - + { + + } + + TCooker& Add(const TRowsHeap &rows) + { + for (const auto &one : rows) Add(one); + + return *this; + } + + TCooker& Add(const NTest::TRow &row) + { + const auto key = Tool.KeyCells(row); + + return Writer.Add(key), *this; + } + TIntrusiveConstPtr<NPage::TBloom> Flush() noexcept - { - return new NPage::TBloom(Writer.Make()); - } - - private: - const NTest::TRowTool Tool; - NBloom::TWriter Writer; - }; - - struct TRater { + { + return new NPage::TBloom(Writer.Make()); + } + + private: + const NTest::TRowTool Tool; + NBloom::TWriter Writer; + }; + + struct TRater { TRater(const TRowScheme &scheme, TIntrusiveConstPtr<NPage::TBloom> page) - : Tool(scheme) - , Page(std::move(page)) - { - - } - - double Do(const TMass &mass) const - { - UNIT_ASSERT_C(Filter(mass.Saved) == 0, "Saved rows weeded"); - - const auto size = mass.Holes.Size(); - - return size ? double(size - Filter(mass.Holes)) / size : 0.; - } - - ui64 Filter(const TRowsHeap &rows) const - { - ui64 filtered = 0; - - for (const auto &one: rows) { - const auto key = Tool.KeyCells(one); - const NBloom::TPrefix prefix(key); - + : Tool(scheme) + , Page(std::move(page)) + { + + } + + double Do(const TMass &mass) const + { + UNIT_ASSERT_C(Filter(mass.Saved) == 0, "Saved rows weeded"); + + const auto size = mass.Holes.Size(); + + return size ? double(size - Filter(mass.Holes)) / size : 0.; + } + + ui64 Filter(const TRowsHeap &rows) const + { + ui64 filtered = 0; + + for (const auto &one: rows) { + const auto key = Tool.KeyCells(one); + const NBloom::TPrefix prefix(key); + filtered += Page->MightHave(prefix.Get(key.size())) ? 0 : 1; - } - - return filtered; - } - - public: - const NTest::TRowTool Tool; + } + + return filtered; + } + + public: + const NTest::TRowTool Tool; const TIntrusiveConstPtr<NPage::TBloom> Page; - }; - - static TAlter MakeAlter(const ui32 table = 1) - { - TAlter alter; - - alter - .AddTable("me", table) + }; + + static TAlter MakeAlter(const ui32 table = 1) + { + TAlter alter; + + alter + .AddTable("me", table) .AddColumn(1, "name", 1, ETypes::String, false) .AddColumn(1, "salt", 2, ETypes::Uint64, false) - .AddColumnToKey(1, 1) - .AddColumnToKey(1, 2); - - return alter; - } - + .AddColumnToKey(1, 1) + .AddColumnToKey(1, 2); + + return alter; + } + Y_UNIT_TEST(Conf) - { + { NBloom::TEstimator estimator(0.001); - UNIT_ASSERT(estimator.Hashes() > 0); - UNIT_ASSERT(estimator.Bits(0) > 0); - } - + UNIT_ASSERT(estimator.Hashes() > 0); + UNIT_ASSERT(estimator.Bits(0) > 0); + } + Y_UNIT_TEST(Hashes) - { - const NTest::TRowTool tool(*Mass0.Model->Scheme); - - ui64 salt = 0; - - for (const auto &one: Mass0.Saved) { - const auto key = tool.KeyCells(one); - const NBloom::TPrefix raw(key); - + { + const NTest::TRowTool tool(*Mass0.Model->Scheme); + + ui64 salt = 0; + + for (const auto &one: Mass0.Saved) { + const auto key = tool.KeyCells(one); + const NBloom::TPrefix raw(key); + ui64 val = NBloom::THash(raw.Get(key.size())).Next(); - - salt = MurmurHash<ui64>((void*)&val, sizeof(val), salt); - } - - UNIT_ASSERT_C(0x3841f2f07c20fc07 == salt, "Hash is broken"); - } - + + salt = MurmurHash<ui64>((void*)&val, sizeof(val), salt); + } + + UNIT_ASSERT_C(0x3841f2f07c20fc07 == salt, "Hash is broken"); + } + Y_UNIT_TEST(Rater) - { - const auto filter = TCooker::Make(Mass0, 0.001); - - auto rate = TRater(*Mass0.Model->Scheme, filter).Do(Mass0); - - UNIT_ASSERT_C(rate < 0.001 * 1.3, "Bloom filter error " << rate); - } - + { + const auto filter = TCooker::Make(Mass0, 0.001); + + auto rate = TRater(*Mass0.Model->Scheme, filter).Do(Mass0); + + UNIT_ASSERT_C(rate < 0.001 * 1.3, "Bloom filter error " << rate); + } + Y_UNIT_TEST(Dipping) - { - double edge = 0.13, error = 0.1; - - for (auto num : xrange(4) ) { - const auto filter = TCooker::Make(Mass0, error); - - auto rate = TRater(*Mass0.Model->Scheme, filter).Do(Mass0); - - UNIT_ASSERT_C(rate < edge, "on " << num << " error " << rate); - - edge = rate * 0.13, error *= 0.1; - } - } - + { + double edge = 0.13, error = 0.1; + + for (auto num : xrange(4) ) { + const auto filter = TCooker::Make(Mass0, error); + + auto rate = TRater(*Mass0.Model->Scheme, filter).Do(Mass0); + + UNIT_ASSERT_C(rate < edge, "on " << num << " error " << rate); + + edge = rate * 0.13, error *= 0.1; + } + } + Y_UNIT_TEST(Basics) - { - TDbExec me; - - me.To(10).Begin().Apply(*MakeAlter()).Commit(); - - const auto ru1 = *me.Natural(1).Col("ba0_huxu", 01234_u64); - const auto rw1 = *me.Natural(1).Col("ba2_d7mj", 12340_u64); - const auto ru2 = *me.Natural(1).Col("ba4_tfcr", 23401_u64); - const auto rw2 = *me.Natural(1).Col("ba6_fdy4", 34012_u64); - const auto rw3 = *me.Natural(1).Col("ba8_digr", 40123_u64); - - /* These keys are fitted to be filtered in all parts with - ByKey Bloom filter enabled, thus in Pw and Pz parts. */ - - const auto no1 = *me.Natural(1).Col("ba1_p9lw", 53543_u64); - const auto no2 = *me.Natural(1).Col("ba3_g0ny", 53442_u64); - const auto no3 = *me.Natural(1).Col("ba5_3hpx", 50894_u64); - - /*_ 10: Filter shouldn't be used when it is not enabled, Pu */ - - me.To(11).Begin().Put(1, ru1, ru2).Commit().Snap(1).Compact(1); - me.To(12).Select(1).Has(ru1, ru2).NoKey(no1, no2, no3); - - { + { + TDbExec me; + + me.To(10).Begin().Apply(*MakeAlter()).Commit(); + + const auto ru1 = *me.Natural(1).Col("ba0_huxu", 01234_u64); + const auto rw1 = *me.Natural(1).Col("ba2_d7mj", 12340_u64); + const auto ru2 = *me.Natural(1).Col("ba4_tfcr", 23401_u64); + const auto rw2 = *me.Natural(1).Col("ba6_fdy4", 34012_u64); + const auto rw3 = *me.Natural(1).Col("ba8_digr", 40123_u64); + + /* These keys are fitted to be filtered in all parts with + ByKey Bloom filter enabled, thus in Pw and Pz parts. */ + + const auto no1 = *me.Natural(1).Col("ba1_p9lw", 53543_u64); + const auto no2 = *me.Natural(1).Col("ba3_g0ny", 53442_u64); + const auto no3 = *me.Natural(1).Col("ba5_3hpx", 50894_u64); + + /*_ 10: Filter shouldn't be used when it is not enabled, Pu */ + + me.To(11).Begin().Put(1, ru1, ru2).Commit().Snap(1).Compact(1); + me.To(12).Select(1).Has(ru1, ru2).NoKey(no1, no2, no3); + + { auto subset = me->Subset(1, TEpoch::Max(), { }, { }); - + UNIT_ASSERT(subset->Flatten.size() == 1 && !subset->Flatten[0]->ByKey); - - auto &stats = me.Relax().BackLog().Stats; - - UNIT_ASSERT_VALUES_EQUAL(stats.SelectWeeded, 0); + + auto &stats = me.Relax().BackLog().Stats; + + UNIT_ASSERT_VALUES_EQUAL(stats.SelectWeeded, 0); UNIT_ASSERT_VALUES_EQUAL(stats.SelectSieved, 4); /* ba? keys */ UNIT_ASSERT_VALUES_EQUAL(stats.SelectNoKey, 2); /* no? keys */ - } - - /*_ 20: Make next part Pw with enabled by key bloom filter */ - - me.To(20).Begin().Apply(*TAlter().SetByKeyFilter(1, true)); - me.To(21).Put(1, rw1, rw2, rw3).Commit().Snap(1).Compact(1, false); - me.To(22).Select(1).Has(ru1, ru2, rw1, rw2, rw3).NoKey(no1, no2, no3); - - { + } + + /*_ 20: Make next part Pw with enabled by key bloom filter */ + + me.To(20).Begin().Apply(*TAlter().SetByKeyFilter(1, true)); + me.To(21).Put(1, rw1, rw2, rw3).Commit().Snap(1).Compact(1, false); + me.To(22).Select(1).Has(ru1, ru2, rw1, rw2, rw3).NoKey(no1, no2, no3); + + { auto subset = me->Subset(1, TEpoch::Max(), { }, { }); - - UNIT_ASSERT( - subset->Flatten.at(0)->ByKey || subset->Flatten.at(1)->ByKey); - - auto &stats = me.Relax().BackLog().Stats; - + + UNIT_ASSERT( + subset->Flatten.at(0)->ByKey || subset->Flatten.at(1)->ByKey); + + auto &stats = me.Relax().BackLog().Stats; + /* { Weeded 3 } is { Pw : ru no } - { no3, no1 are out of range }, { Sieved 7 } is { Pu : ru rw no } + { Pw : rw } - ..., { NoKey 2 } is { no1, no2 } because no3 is out of range */ - + UNIT_ASSERT_VALUES_EQUAL(stats.SelectWeeded, 3); UNIT_ASSERT_VALUES_EQUAL(stats.SelectSieved, 7); UNIT_ASSERT_VALUES_EQUAL(stats.SelectNoKey, 2); - } - - /*_ 30: Recompact all parts to one Pz and repeat Select()'s */ - - me.To(30).Compact(1, true /* final compaction */); - me.To(31).Select(1).Has(ru1, ru2, rw1, rw2, rw3).NoKey(no1, no2, no3); - - { + } + + /*_ 30: Recompact all parts to one Pz and repeat Select()'s */ + + me.To(30).Compact(1, true /* final compaction */); + me.To(31).Select(1).Has(ru1, ru2, rw1, rw2, rw3).NoKey(no1, no2, no3); + + { const auto subset = me->Subset(1, TEpoch::Max(), { }, { }); - + UNIT_ASSERT(subset->Flatten.size() == 1 && subset->Flatten[0]->ByKey); - - auto &stats = me.Relax().BackLog().Stats; - - UNIT_ASSERT_VALUES_EQUAL(stats.SelectWeeded, 3); - UNIT_ASSERT_VALUES_EQUAL(stats.SelectSieved, 5); - UNIT_ASSERT_VALUES_EQUAL(stats.SelectNoKey, 0); - + + auto &stats = me.Relax().BackLog().Stats; + + UNIT_ASSERT_VALUES_EQUAL(stats.SelectWeeded, 3); + UNIT_ASSERT_VALUES_EQUAL(stats.SelectSieved, 5); + UNIT_ASSERT_VALUES_EQUAL(stats.SelectNoKey, 0); + DumpPart(static_cast<const TPartStore&>(*subset->Flatten[0]), 10); - } - - /*_ 40: Disable filter then check that is really gone */ - - me.To(40).Begin().Apply(*TAlter().SetByKeyFilter(1, false)); - me.To(41).Commit().Compact(1, true /* final compaction */); - - { + } + + /*_ 40: Disable filter then check that is really gone */ + + me.To(40).Begin().Apply(*TAlter().SetByKeyFilter(1, false)); + me.To(41).Commit().Compact(1, true /* final compaction */); + + { const auto subset = me->Subset(1, TEpoch::Max(), { }, { }); - + UNIT_ASSERT(subset->Flatten.size() == 1 && !subset->Flatten[0]->ByKey); - } - } - + } + } + Y_UNIT_TEST(Stairs) - { - const ui32 Height = 99; - - TDbExec me; - - me.To(10).Begin().Apply(*MakeAlter()).Commit(); - + { + const ui32 Height = 99; + + TDbExec me; + + me.To(10).Begin().Apply(*MakeAlter()).Commit(); + const TIntrusivePtr<TGrowHeap> heap = new TGrowHeap(128 * 1024); - - TDeque<NTest::TRow> ladder; - - /* 1xxx: Add rows and parts extending key by one col each time */ - - for (auto col : xrange(ui32(3), Height + 3)) { - TAlter alter; - - auto name = Sprintf("sub_%04u", col); + + TDeque<NTest::TRow> ladder; + + /* 1xxx: Add rows and parts extending key by one col each time */ + + for (auto col : xrange(ui32(3), Height + 3)) { + TAlter alter; + + auto name = Sprintf("sub_%04u", col); alter.AddColumn(1, name, col, ETypes::String, false); - alter.AddColumnToKey(1, col); - alter.SetByKeyFilter(1, col > 10); /* first 8 parts w/o filter */ - - me.To(col * 10 + 1001).Begin().Apply(*alter).Commit(); - - TRow &row = (ladder.emplace_back(heap), ladder.back()); - - row.Do(1, "foo").Do(2, 77_u64); - - for (auto sub: xrange(ui32(3), col + 1)) - row.Do(sub, Sprintf("%x_%x", col, sub)); - - me.To(col * 10 + 1002).Begin().Put(1, row).Commit().Snap(1); - me.To(col * 10 + 1003).Compact(1, false).Select(1).Has(row); - - const ui32 limit = 1 + (Min(ui32(10), col) - 2) + 5 /* error */; - - UNIT_ASSERT(me.Relax().BackLog().Stats.SelectSieved < limit); - } - - { + alter.AddColumnToKey(1, col); + alter.SetByKeyFilter(1, col > 10); /* first 8 parts w/o filter */ + + me.To(col * 10 + 1001).Begin().Apply(*alter).Commit(); + + TRow &row = (ladder.emplace_back(heap), ladder.back()); + + row.Do(1, "foo").Do(2, 77_u64); + + for (auto sub: xrange(ui32(3), col + 1)) + row.Do(sub, Sprintf("%x_%x", col, sub)); + + me.To(col * 10 + 1002).Begin().Put(1, row).Commit().Snap(1); + me.To(col * 10 + 1003).Compact(1, false).Select(1).Has(row); + + const ui32 limit = 1 + (Min(ui32(10), col) - 2) + 5 /* error */; + + UNIT_ASSERT(me.Relax().BackLog().Stats.SelectSieved < limit); + } + + { const auto subset = me->Subset(1, TEpoch::Max(), { }, { }); - + UNIT_ASSERT_VALUES_EQUAL(subset->Flatten.size(), Height); UNIT_ASSERT_VALUES_EQUAL(subset->Frozen.size(), 0); - } - - /* 8xxx: Extend incomplete keys with nulls and check it precense */ - - for (auto &row : ladder) { + } + + /* 8xxx: Extend incomplete keys with nulls and check it precense */ + + for (auto &row : ladder) { const ui32 serial = 8000 + (*row).size(); - + for (ui32 grow = (*row).size(); grow++ < Height + 2; ) - row.Do(grow, nullptr); - - me.To(serial).Begin().Select(1).Has(row); - - const ui32 limit = 1 + 8 /* w/o filter */ + 5 /* error */; - - UNIT_ASSERT(me.Commit().BackLog().Stats.SelectSieved < limit); - } - } -} - -} -} + row.Do(grow, nullptr); + + me.To(serial).Begin().Select(1).Has(row); + + const ui32 limit = 1 + 8 /* w/o filter */ + 5 /* error */; + + UNIT_ASSERT(me.Commit().BackLog().Stats.SelectSieved < limit); + } + } +} + +} +} diff --git a/ydb/core/tablet_flat/ut/ut_charge.cpp b/ydb/core/tablet_flat/ut/ut_charge.cpp index 17717c26f1..eece34e9f8 100644 --- a/ydb/core/tablet_flat/ut/ut_charge.cpp +++ b/ydb/core/tablet_flat/ut/ut_charge.cpp @@ -7,265 +7,265 @@ #include <ydb/core/tablet_flat/test/libs/table/test_envs.h> #include <ydb/core/tablet_flat/test/libs/table/wrap_part.h> #include <ydb/core/tablet_flat/test/libs/table/test_steps.h> - + #include <library/cpp/testing/unittest/registar.h> - -namespace NKikimr { -namespace NTable { - -namespace { - - const NTest::TMass Mass(new NTest::TModelStd(false), 4 * 9); - - struct TTouchEnv : public NTest::TTestEnv { - using TArr = std::initializer_list<ui16>; - - TTouchEnv(bool fail) : Fail(fail) { } - + +namespace NKikimr { +namespace NTable { + +namespace { + + const NTest::TMass Mass(new NTest::TModelStd(false), 4 * 9); + + struct TTouchEnv : public NTest::TTestEnv { + using TArr = std::initializer_list<ui16>; + + TTouchEnv(bool fail) : Fail(fail) { } + const TSharedData* TryGetPage(const TPart *part, TPageId id, TGroupId groupId) override - { + { Y_VERIFY(groupId.IsMain(), "TODO: support column groups"); - Touched.insert(id); - + Touched.insert(id); + return Fail ? nullptr : NTest::TTestEnv::TryGetPage(part, id, groupId); - } - - bool Is(const TArr &arr, ui32 flags) const noexcept - { - size_t hits = 0, miss = 0, seq = 0, has = arr.size(); - - for (auto page: arr) { - if (++seq && Touched.count(page)) { - hits++; - } else if ((flags & 0x01) && has > 1 && seq == 1) { - miss++; /* may have no the fist page */ - } else if ((flags & 0x02) && has > 1 && seq == has) { - miss++; /* may have no the last page */ - } - } - - return hits == Touched.size() && (hits + miss) == arr.size(); - } - - const bool Fail = false; - TSet<TPageId> Touched; - }; - - struct TCooker { - TCooker(const TRowScheme &scheme) - : Tool(scheme) + } + + bool Is(const TArr &arr, ui32 flags) const noexcept + { + size_t hits = 0, miss = 0, seq = 0, has = arr.size(); + + for (auto page: arr) { + if (++seq && Touched.count(page)) { + hits++; + } else if ((flags & 0x01) && has > 1 && seq == 1) { + miss++; /* may have no the fist page */ + } else if ((flags & 0x02) && has > 1 && seq == has) { + miss++; /* may have no the last page */ + } + } + + return hits == Touched.size() && (hits + miss) == arr.size(); + } + + const bool Fail = false; + TSet<TPageId> Touched; + }; + + struct TCooker { + TCooker(const TRowScheme &scheme) + : Tool(scheme) , Writer(new TPartScheme(scheme.Cols), { }, NPage::TGroupId(0)) - { - - } - - TCooker& Add(const NTest::TRow &row, ui64 offset, ui32 page) - { - const TCelled key(Tool.LookupKey(row), *Tool.Scheme.Keys, false); - - return Writer.Add(key, offset, page), *this; - } - + { + + } + + TCooker& Add(const NTest::TRow &row, ui64 offset, ui32 page) + { + const TCelled key(Tool.LookupKey(row), *Tool.Scheme.Keys, false); + + return Writer.Add(key, offset, page), *this; + } + TSharedData Flush() - { - return Writer.Flush(); - } - - private: - const NTest::TRowTool Tool; - NPage::TIndexWriter Writer; - }; - - struct TModel : public NTest::TSteps<TModel> { - using TArr = std::initializer_list<ui16>; - - TModel() - : Tool(*Mass.Model->Scheme) - { - auto pages = Eggs.At(0)->Index->End() - Eggs.At(0)->Index->Begin(); - - UNIT_ASSERT(pages == 9); - } - - static NTest::TPartEggs MakeEggs() noexcept - { - NPage::TConf conf{ true, 8192 }; - + { + return Writer.Flush(); + } + + private: + const NTest::TRowTool Tool; + NPage::TIndexWriter Writer; + }; + + struct TModel : public NTest::TSteps<TModel> { + using TArr = std::initializer_list<ui16>; + + TModel() + : Tool(*Mass.Model->Scheme) + { + auto pages = Eggs.At(0)->Index->End() - Eggs.At(0)->Index->Begin(); + + UNIT_ASSERT(pages == 9); + } + + static NTest::TPartEggs MakeEggs() noexcept + { + NPage::TConf conf{ true, 8192 }; + conf.Group(0).PageRows = 3; /* each page has 3 physical rows, but... */ - - NTest::TPartCook cook(Mass.Model->Scheme, conf); - - for (auto seq: xrange(Mass.Saved.Size())) { - /* ... but rows pack has 4 rows per each page, the first row in - each pack is ommited and used as spacer between pages. */ - - if (seq % 4 > 0) cook.Add(Mass.Saved[seq]); - } - - return cook.Finish(); - } - - void Check(ui32 lower, ui32 upper, ui64 items, TArr arr) const - { - Index(lower, upper, items, arr); - Iter(lower, upper, items ? items : Max<ui32>(), arr); - } - - void Index(ui32 lower, ui32 upper, ui64 items, TArr arr) const - { - Y_VERIFY(lower <= upper && upper < Mass.Saved.Size()); - - TTouchEnv env(true); - + + NTest::TPartCook cook(Mass.Model->Scheme, conf); + + for (auto seq: xrange(Mass.Saved.Size())) { + /* ... but rows pack has 4 rows per each page, the first row in + each pack is ommited and used as spacer between pages. */ + + if (seq % 4 > 0) cook.Add(Mass.Saved[seq]); + } + + return cook.Finish(); + } + + void Check(ui32 lower, ui32 upper, ui64 items, TArr arr) const + { + Index(lower, upper, items, arr); + Iter(lower, upper, items ? items : Max<ui32>(), arr); + } + + void Index(ui32 lower, ui32 upper, ui64 items, TArr arr) const + { + Y_VERIFY(lower <= upper && upper < Mass.Saved.Size()); + + TTouchEnv env(true); + const auto &nulls = *Tool.Scheme.Keys; - const auto from = Tool.KeyCells(Mass.Saved[lower]); - const auto to = Tool.KeyCells(Mass.Saved[upper]); - + const auto from = Tool.KeyCells(Mass.Saved[lower]); + const auto to = Tool.KeyCells(Mass.Saved[upper]); + TRun run(nulls); auto part = Eggs.Lone(); for (auto& slice : *part->Slices) { run.Insert(part, slice); } - + TCharge::Range(&env, from, to, run, nulls, TTagsRef{ }, items, Max<ui64>()); - if (!env.Is(arr, 0x00 /* require all pages */)) { - Log() - << "Charge over keys [" << lower << ", " << upper << "]" - << " lim " << (items ? items : 9999) << "r" - << ", touched " << NFmt::Arr(env.Touched) - << ", expected " << NFmt::Arr(arr) << Endl; - - UNIT_ASSERT(false); - } - } - - void Iter(ui32 lower, ui32 upper, ui64 items, TArr arr) const - { - Y_VERIFY(lower <= upper && upper < Mass.Saved.Size()); - - NTest::TCheckIt wrap(Eggs, { new TTouchEnv(false) }); - - wrap.To(CurrentStep()).Seek(Mass.Saved[lower], ESeek::Lower); - + if (!env.Is(arr, 0x00 /* require all pages */)) { + Log() + << "Charge over keys [" << lower << ", " << upper << "]" + << " lim " << (items ? items : 9999) << "r" + << ", touched " << NFmt::Arr(env.Touched) + << ", expected " << NFmt::Arr(arr) << Endl; + + UNIT_ASSERT(false); + } + } + + void Iter(ui32 lower, ui32 upper, ui64 items, TArr arr) const + { + Y_VERIFY(lower <= upper && upper < Mass.Saved.Size()); + + NTest::TCheckIt wrap(Eggs, { new TTouchEnv(false) }); + + wrap.To(CurrentStep()).Seek(Mass.Saved[lower], ESeek::Lower); + for (ui32 key = lower + 1; items-- > 1 && key <= upper; key++) { if (key % 4 == 0) { ++key; - } - + } + auto last = (key == Mass.Saved.Size() - 1); - + wrap.Next().Is(last ? EReady::Gone : EReady::Data); } - auto env = wrap.Displace<TTouchEnv>(nullptr); - - if (!env->Is(arr, 0x02 /* last page may be unused */)) { - Log() - << "Iter over keys [" << lower << ", " << upper << "]" - << " touched pages " << NFmt::Arr(env->Touched) - << ", expected " << NFmt::Arr(arr) << Endl; - - UNIT_ASSERT(false); - } - } - - const NTest::TRowTool Tool; - const NTest::TPartEggs Eggs = MakeEggs(); - }; - -} - + auto env = wrap.Displace<TTouchEnv>(nullptr); + + if (!env->Is(arr, 0x02 /* last page may be unused */)) { + Log() + << "Iter over keys [" << lower << ", " << upper << "]" + << " touched pages " << NFmt::Arr(env->Touched) + << ", expected " << NFmt::Arr(arr) << Endl; + + UNIT_ASSERT(false); + } + } + + const NTest::TRowTool Tool; + const NTest::TPartEggs Eggs = MakeEggs(); + }; + +} + Y_UNIT_TEST_SUITE(Charge) { - - using namespace NTest; - + + using namespace NTest; + Y_UNIT_TEST(Lookups) - { - TLayoutCook lay; - - lay - .Col(0, 0, NScheme::NTypeIds::Uint32) - .Col(0, 1, NScheme::NTypeIds::String) - .Key({0, 1}); - - const auto foo = *TNatural(*lay).Col(555_u32, "foo"); - const auto bar = *TNatural(*lay).Col(777_u32, "bar"); + { + TLayoutCook lay; + + lay + .Col(0, 0, NScheme::NTypeIds::Uint32) + .Col(0, 1, NScheme::NTypeIds::String) + .Key({0, 1}); + + const auto foo = *TNatural(*lay).Col(555_u32, "foo"); + const auto bar = *TNatural(*lay).Col(777_u32, "bar"); const auto baz = *TNatural(*lay).Col(999_u32, "baz"); - + NPage::TIndex me( TCooker(*lay) .Add(foo, 0, 1) .Add(bar, 10, 2) .Add(baz, 19, 2) .Flush()); - - /* TODO: Special row keys such as { } or incomplete keys with +inf - cells are not used in this UT set. It is ok since precharge - code do not read keys bypassing it directly to NPage::TIndex. - Thus, need to test TIndex::Lookup () for that cases only. */ - } - + + /* TODO: Special row keys such as { } or incomplete keys with +inf + cells are not used in this UT set. It is ok since precharge + code do not read keys bypassing it directly to NPage::TIndex. + Thus, need to test TIndex::Lookup () for that cases only. */ + } + Y_UNIT_TEST(Basics) - { - using TArr = TTouchEnv::TArr; - - TModel me; - - { /*_ 1xx: A set of some edge and basic cases */ - - me.To(100).Check(33, 34, 0, { 8 }); // keys on the last page - me.To(101).Check(0, 0, 0, { 0, 1 }); // keys before the part - me.To(102).Check(3, 4, 0, { 0, 1 }); - me.To(103).Check(3, 5, 0, { 0, 1, 2 }); - me.To(104).Check(4, 8, 0, { 0, 1, 2 }); - me.To(105).Check(4, 12, 0, { 0, 1, 2, 3 }); - me.To(106).Check(8, 12, 0, { 1, 2, 3 }); + { + using TArr = TTouchEnv::TArr; + + TModel me; + + { /*_ 1xx: A set of some edge and basic cases */ + + me.To(100).Check(33, 34, 0, { 8 }); // keys on the last page + me.To(101).Check(0, 0, 0, { 0, 1 }); // keys before the part + me.To(102).Check(3, 4, 0, { 0, 1 }); + me.To(103).Check(3, 5, 0, { 0, 1, 2 }); + me.To(104).Check(4, 8, 0, { 0, 1, 2 }); + me.To(105).Check(4, 12, 0, { 0, 1, 2, 3 }); + me.To(106).Check(8, 12, 0, { 1, 2, 3 }); me.To(107).Check(8, 13, 0, { 1, 2, 3, 4 }); me.To(108).Check(8, 14, 0, { 1, 2, 3, 4 }); - me.To(110).Check(0, 35, 0, { 0, 1, 2, 3, 4, 5, 6, 7, 8 }); - } - - /*_ 2xx: Simple loads rows within the same page */ - - for (const ui16 it: xrange(8)) { - const TArr span{ it, ui16(it + 1) }; - - const ui32 base = 200 + it * 10, lead = it * 4; - - me.To(base + 1).Check(lead + 1, lead + 1, 0, span); - me.To(base + 2).Check(lead + 1, lead + 2, 0, span); - me.To(base + 3).Check(lead + 1, lead + 3, 0, span); - me.To(base + 4).Check(lead + 2, lead + 3, 0, span); - me.To(base + 5).Check(lead + 3, lead + 3, 0, span); - } - - /*_ 3xx: Simple loads spans more than one page */ - - for (const ui16 it: xrange(5)) { - const TArr span{ it, ui16(it + 1), ui16(it + 2), ui16(it + 3) }; - - const ui32 base = 300 + it * 10, lead = it * 4; - - me.To(base + 1).Check(lead + 1, lead + 9, 0, span); - me.To(base + 2).Check(lead + 1, lead + 10, 0, span); - me.To(base + 3).Check(lead + 1, lead + 11, 0, span); - } - } - + me.To(110).Check(0, 35, 0, { 0, 1, 2, 3, 4, 5, 6, 7, 8 }); + } + + /*_ 2xx: Simple loads rows within the same page */ + + for (const ui16 it: xrange(8)) { + const TArr span{ it, ui16(it + 1) }; + + const ui32 base = 200 + it * 10, lead = it * 4; + + me.To(base + 1).Check(lead + 1, lead + 1, 0, span); + me.To(base + 2).Check(lead + 1, lead + 2, 0, span); + me.To(base + 3).Check(lead + 1, lead + 3, 0, span); + me.To(base + 4).Check(lead + 2, lead + 3, 0, span); + me.To(base + 5).Check(lead + 3, lead + 3, 0, span); + } + + /*_ 3xx: Simple loads spans more than one page */ + + for (const ui16 it: xrange(5)) { + const TArr span{ it, ui16(it + 1), ui16(it + 2), ui16(it + 3) }; + + const ui32 base = 300 + it * 10, lead = it * 4; + + me.To(base + 1).Check(lead + 1, lead + 9, 0, span); + me.To(base + 2).Check(lead + 1, lead + 10, 0, span); + me.To(base + 3).Check(lead + 1, lead + 11, 0, span); + } + } + Y_UNIT_TEST(Limits) - { + { /* XXX: Precharger is conservative about row limits, because it cannot know how many rows will really be consumed on the first page. Precharge will also add one extra row because datashard uses it to check for truncation, thus the limit of 8 (3 rows per page) rows really assumes 4 pages. - */ - - TModel me; - - /*_ 1xx: custom spanned loads scenarios */ - + */ + + TModel me; + + /*_ 1xx: custom spanned loads scenarios */ + me.To(101).Index(0, 35, 8 /* rows */, { 0, 1, 2, 3 }); me.To(102).Index(0, 35, 11 /* rows */, { 0, 1, 2, 3, 4 }); me.To(103).Index(0, 35, 14 /* rows */, { 0, 1, 2, 3, 4, 5 }); @@ -276,20 +276,20 @@ Y_UNIT_TEST_SUITE(Charge) { me.To(112).Index(9, 35, 11 /* rows */, { 2, 3, 4, 5, 6 }); me.To(113).Index(9, 35, 14 /* rows */, { 2, 3, 4, 5, 6, 7 }); me.To(120).Index(25, 35, 8 /* rows */, { 6, 7, 8 }); - - /*_ 2xx: one row charge limit on two page */ - - for (const ui16 page : xrange(4)) { - const TTouchEnv::TArr span{ page, ui16(page + 1) }; - - const ui32 base = 200 + page * 10, lead = page * 4; - - me.To(base + 1).Check(lead + 1, 35, 1, span); - me.To(base + 2).Check(lead + 2, 35, 1, span); - me.To(base + 3).Check(lead + 3, 35, 1, span); - } - } -} - -} -} + + /*_ 2xx: one row charge limit on two page */ + + for (const ui16 page : xrange(4)) { + const TTouchEnv::TArr span{ page, ui16(page + 1) }; + + const ui32 base = 200 + page * 10, lead = page * 4; + + me.To(base + 1).Check(lead + 1, 35, 1, span); + me.To(base + 2).Check(lead + 2, 35, 1, span); + me.To(base + 3).Check(lead + 3, 35, 1, span); + } + } +} + +} +} diff --git a/ydb/core/tablet_flat/ut/ut_compaction.cpp b/ydb/core/tablet_flat/ut/ut_compaction.cpp index ef0d9bbf15..676b0df291 100644 --- a/ydb/core/tablet_flat/ut/ut_compaction.cpp +++ b/ydb/core/tablet_flat/ut/ut_compaction.cpp @@ -6,168 +6,168 @@ #include <ydb/core/tablet_flat/test/libs/table/test_make.h> #include <ydb/core/tablet_flat/test/libs/table/test_envs.h> #include <ydb/core/tablet_flat/test/libs/table/test_wreck.h> - + #include <library/cpp/testing/unittest/registar.h> - -namespace NKikimr { -namespace NTable { - + +namespace NKikimr { +namespace NTable { + Y_UNIT_TEST_SUITE(TCompaction) { - + Y_UNIT_TEST(OneMemtable) - { - using namespace NTest; - - const TMass mass(new TModelStd(false), 16); - - auto eggs = TCompaction().Do(TMake(mass).Mem()); - - TCheckIt(eggs, { }).IsTheSame(mass.Saved); - } - + { + using namespace NTest; + + const TMass mass(new TModelStd(false), 16); + + auto eggs = TCompaction().Do(TMake(mass).Mem()); + + TCheckIt(eggs, { }).IsTheSame(mass.Saved); + } + Y_UNIT_TEST(ManyParts) - { - using namespace NTest; - - const TMass mass(new TModelStd(false), 32 * 1025); - - auto subset = TMake(mass).Mixed(0, 19, NTest::TMixerRnd(19)); - auto eggs = TCompaction().Do(*subset); - - TCheckIt(eggs, { }).IsTheSame(mass.Saved); - } - + { + using namespace NTest; + + const TMass mass(new TModelStd(false), 32 * 1025); + + auto subset = TMake(mass).Mixed(0, 19, NTest::TMixerRnd(19)); + auto eggs = TCompaction().Do(*subset); + + TCheckIt(eggs, { }).IsTheSame(mass.Saved); + } + Y_UNIT_TEST(BootAbort) - { - using namespace NTest; - - TMersenne<ui64> rnd; - - const TMass mass(new TModelStd(false), 32 * 1025); - auto subset = TMake(mass).Mixed(0, 19, NTest::TMixerRnd(19)); - - TAutoPtr<IPages> env = new TFailEnv<decltype(rnd)>(rnd, -1.); - - auto eggs = TCompaction(env, { }, 1 /* early abort */).Do(*subset); - - UNIT_ASSERT(!eggs.Parts && eggs.NoResult()); - } - + { + using namespace NTest; + + TMersenne<ui64> rnd; + + const TMass mass(new TModelStd(false), 32 * 1025); + auto subset = TMake(mass).Mixed(0, 19, NTest::TMixerRnd(19)); + + TAutoPtr<IPages> env = new TFailEnv<decltype(rnd)>(rnd, -1.); + + auto eggs = TCompaction(env, { }, 1 /* early abort */).Do(*subset); + + UNIT_ASSERT(!eggs.Parts && eggs.NoResult()); + } + Y_UNIT_TEST(Defaults) - { - using namespace NTest; - - TLayoutCook lay; - - lay - .Col(0, 0, NScheme::NTypeIds::Uint64) - .Col(0, 8, NScheme::NTypeIds::Uint32, Cimple<ui32>(7)) - .Key({ 0 }); - - auto one = *TNatural(*lay).Col<ui64,ui32>(1, 3); - - auto eggs = - TPartCook(lay, { false, 4096 }) - .Add(one) /* full row */ - .AddN(2_u64, nullptr) /* explciit null */ - .AddN(3_u64).Finish(); /* default value */ - - { /* Read without default values expansion */ - - auto born = TCompaction(nullptr, { true, 7 * 1024 }).Do(eggs); - - TCheckIt - (born, { nullptr, 0 }, nullptr , false) - .To(10).Seek({ }, ESeek::Lower).Is(one) - .To(11).Next().IsN(2_u64, nullptr) /* expllcit null */ - .To(12).Next().IsN(3_u64, nullptr) /* ommited value */ - .To(19).Next().Is(EReady::Gone); - } - - { /* Read with expansion ommited to defaults */ - - auto born = TCompaction(nullptr, { true, 7 * 1024 }).Do(eggs); - - TCheckIt - (born, { nullptr, 0 }, nullptr, true) - .To(20).Seek({ }, ESeek::Lower).Is(one) - .To(21).Next().IsN(2_u64, nullptr) - .To(22).Next().IsN(3_u64, 7_u32) - .To(29).Next().Is(EReady::Gone); - } - } - + { + using namespace NTest; + + TLayoutCook lay; + + lay + .Col(0, 0, NScheme::NTypeIds::Uint64) + .Col(0, 8, NScheme::NTypeIds::Uint32, Cimple<ui32>(7)) + .Key({ 0 }); + + auto one = *TNatural(*lay).Col<ui64,ui32>(1, 3); + + auto eggs = + TPartCook(lay, { false, 4096 }) + .Add(one) /* full row */ + .AddN(2_u64, nullptr) /* explciit null */ + .AddN(3_u64).Finish(); /* default value */ + + { /* Read without default values expansion */ + + auto born = TCompaction(nullptr, { true, 7 * 1024 }).Do(eggs); + + TCheckIt + (born, { nullptr, 0 }, nullptr , false) + .To(10).Seek({ }, ESeek::Lower).Is(one) + .To(11).Next().IsN(2_u64, nullptr) /* expllcit null */ + .To(12).Next().IsN(3_u64, nullptr) /* ommited value */ + .To(19).Next().Is(EReady::Gone); + } + + { /* Read with expansion ommited to defaults */ + + auto born = TCompaction(nullptr, { true, 7 * 1024 }).Do(eggs); + + TCheckIt + (born, { nullptr, 0 }, nullptr, true) + .To(20).Seek({ }, ESeek::Lower).Is(one) + .To(21).Next().IsN(2_u64, nullptr) + .To(22).Next().IsN(3_u64, 7_u32) + .To(29).Next().Is(EReady::Gone); + } + } + Y_UNIT_TEST(Merges) - { - using namespace NTest; - - TLayoutCook lay; - - lay - .Col(0, 0, NScheme::NTypeIds::Uint64) - .Col(0, 8, NScheme::NTypeIds::Uint32, Cimple<ui32>(5)) - .Col(0, 9, NScheme::NTypeIds::Uint32, Cimple<ui32>(7)) - .Key({ 0 }); - - auto lower = + { + using namespace NTest; + + TLayoutCook lay; + + lay + .Col(0, 0, NScheme::NTypeIds::Uint64) + .Col(0, 8, NScheme::NTypeIds::Uint32, Cimple<ui32>(5)) + .Col(0, 9, NScheme::NTypeIds::Uint32, Cimple<ui32>(7)) + .Key({ 0 }); + + auto lower = TPartCook(lay, { false, 4096 }, { }, TEpoch::FromIndex(1)) - .AddN(1_u64, 1_u32, 1_u32) - .AddN(2_u64, 2_u32, 3_u32) - .AddN(3_u64, 3_u32, 6_u32) - .AddN(4_u64, 4_u32, 8_u32) + .AddN(1_u64, 1_u32, 1_u32) + .AddN(2_u64, 2_u32, 3_u32) + .AddN(3_u64, 3_u32, 6_u32) + .AddN(4_u64, 4_u32, 8_u32) .Finish(); - - auto middle = + + auto middle = TPartCook(lay, { false, 4096 }, { }, TEpoch::FromIndex(2)) .AddOpN(ERowOp::Erase, 2_u64) .AddOpN(ERowOp::Erase, 3_u64) .AddOpN(ERowOp::Reset, 4_u64, 9_u32, nullptr) .Finish(); - - auto upper = + + auto upper = TPartCook(lay, { false, 4096 }, { }, TEpoch::FromIndex(3)) .AddOpN(ERowOp::Erase, 2_u64) .AddOpN(ERowOp::Upsert, 3_u64, ECellOp::Empty, nullptr) .AddOpN(ERowOp::Upsert, 4_u64, ECellOp::Empty, ECellOp::Reset) .Finish(); - - { /* full parts merge, check final results only */ - TCompaction make(nullptr, { true, 7 * 1024 }); - + + { /* full parts merge, check final results only */ + TCompaction make(nullptr, { true, 7 * 1024 }); + auto born = make.Do(lower.Scheme, { &lower, &middle, &upper }); - - TCheckIt - (born, { nullptr, 0 }, nullptr, true /* expand defaults */) - .To(20).Seek({ }, ESeek::Lower).Is(EReady::Data) + + TCheckIt + (born, { nullptr, 0 }, nullptr, true /* expand defaults */) + .To(20).Seek({ }, ESeek::Lower).Is(EReady::Data) .To(21).IsOpN(ERowOp::Upsert, 1_u64, 1_u32, 1_u32) - .Next() + .Next() .To(22).IsOpN(ERowOp::Reset, 3_u64, ECellOp::Empty, nullptr) .To(23).IsOpN(ERowOp::Reset, 3_u64, 5_u32, nullptr) - .Next() + .Next() .To(24).IsOpN(ERowOp::Reset, 4_u64, 9_u32, ECellOp::Empty) .To(25).IsOpN(ERowOp::Reset, 4_u64, 9_u32, 7_u32) - .To(29).Next().Is(EReady::Gone); - } - - { /* partial merge, check intermediate states */ - TCompaction make(nullptr, { false, 7 * 1024 }); - + .To(29).Next().Is(EReady::Gone); + } + + { /* partial merge, check intermediate states */ + TCompaction make(nullptr, { false, 7 * 1024 }); + auto born = make.Do(lower.Scheme, { &middle, &upper }); - - TCheckIt - (born, { nullptr, 0 }, nullptr, true /* expand defaults */) - .To(30).Seek({ }, ESeek::Lower).Is(EReady::Data) + + TCheckIt + (born, { nullptr, 0 }, nullptr, true /* expand defaults */) + .To(30).Seek({ }, ESeek::Lower).Is(EReady::Data) .To(31).IsOpN(ERowOp::Erase, 2_u64, ECellOp::Empty, ECellOp::Empty) - .Next() + .Next() .To(32).IsOpN(ERowOp::Reset, 3_u64, ECellOp::Empty, nullptr) .To(33).IsOpN(ERowOp::Reset, 3_u64, 5_u32, nullptr) - .Next() + .Next() .To(34).IsOpN(ERowOp::Reset, 4_u64, 9_u32, ECellOp::Reset) .To(35).IsOpN(ERowOp::Reset, 4_u64, 9_u32, 7_u32) - .To(39).Next().Is(EReady::Gone); - } - } -} - -} -} + .To(39).Next().Is(EReady::Gone); + } + } +} + +} +} diff --git a/ydb/core/tablet_flat/ut/ut_compaction_multi.cpp b/ydb/core/tablet_flat/ut/ut_compaction_multi.cpp index 6687e80e4a..0410986e49 100644 --- a/ydb/core/tablet_flat/ut/ut_compaction_multi.cpp +++ b/ydb/core/tablet_flat/ut/ut_compaction_multi.cpp @@ -25,10 +25,10 @@ Y_UNIT_TEST_SUITE(TCompactionMulti) { auto subset = TMake(mass).Mixed(0, 19, NTest::TMixerRnd(19)); auto eggs = TCompaction(nullptr, conf).Do(*subset); - UNIT_ASSERT_C(eggs.Parts.size() > 3, - "Compaction produced " << eggs.Parts.size() << " parts"); + UNIT_ASSERT_C(eggs.Parts.size() > 3, + "Compaction produced " << eggs.Parts.size() << " parts"); - TCheckIt(eggs, { }).IsTheSame(mass.Saved); + TCheckIt(eggs, { }).IsTheSame(mass.Saved); } void RunMainEdgeTest( @@ -42,10 +42,10 @@ Y_UNIT_TEST_SUITE(TCompactionMulti) { TPartCook(scheme, initialConf) .Add(rows.begin(), rows.end()) .Finish(); - UNIT_ASSERT_C(initial.Parts.size() == 1, - "Unexpected " << initial.Parts.size() << " results"); + UNIT_ASSERT_C(initial.Parts.size() == 1, + "Unexpected " << initial.Parts.size() << " results"); - auto* initialPart = initial.Parts.at(0).Get(); + auto* initialPart = initial.Parts.at(0).Get(); auto fullPageSize = initialPart->Store->GetPage(0, 0)->size(); auto fullPartSize = initialPart->Store->PageCollectionBytes(0); @@ -70,37 +70,37 @@ Y_UNIT_TEST_SUITE(TCompactionMulti) { // Verify we produce part with the exact same size { auto born = TCompaction(nullptr, conf).Do(initial); - UNIT_ASSERT_VALUES_EQUAL(born.Parts.size(), attempt ? 2u : 1u); + UNIT_ASSERT_VALUES_EQUAL(born.Parts.size(), attempt ? 2u : 1u); UNIT_ASSERT_VALUES_EQUAL(born.At(0)->Store->PageCollectionBytes(0), lastPartSize); - TCheckIt(born, { }).IsTheSame(rows).Is(EReady::Gone); + TCheckIt(born, { }).IsTheSame(rows).Is(EReady::Gone); } --conf.MainPageCollectionEdge; // Verify we produce part that is slightly smaller when not enough space { - const auto born = TCompaction(nullptr, conf).Do(initial); - UNIT_ASSERT_VALUES_EQUAL(born.Parts.size(), 2u); + const auto born = TCompaction(nullptr, conf).Do(initial); + UNIT_ASSERT_VALUES_EQUAL(born.Parts.size(), 2u); lastPartSize = born.At(0)->Store->PageCollectionBytes(0); UNIT_ASSERT_C(lastPartSize <= conf.MainPageCollectionEdge, "Produced part with size " << lastPartSize << " expected no more than " << conf.MainPageCollectionEdge); - TCheckIt(born, { }).IsTheSame(rows).Is(EReady::Gone); + TCheckIt(born, { }).IsTheSame(rows).Is(EReady::Gone); // The first part must gen one less row than the last time auto size = rows.end() - rows.begin(); auto split = size - attempt - 1; // The first part must get one less row than the last time - TPartEggs egg1{ nullptr, born.Scheme, { born.At(0) } }; - TPartEggs egg2{ nullptr, born.Scheme, { born.At(1) } }; - TCheckIt(egg1, { }) + TPartEggs egg1{ nullptr, born.Scheme, { born.At(0) } }; + TPartEggs egg2{ nullptr, born.Scheme, { born.At(1) } }; + TCheckIt(egg1, { }) .IsTheSame(rows.begin(), rows.begin() + split) .Is(EReady::Gone); - TCheckIt(egg2, { }) + TCheckIt(egg2, { }) .IsTheSame(rows.begin() + split, rows.end()) .Is(EReady::Gone); @@ -110,7 +110,7 @@ Y_UNIT_TEST_SUITE(TCompactionMulti) { for (auto it : xrange(size)) { const auto key = tool.KeyCells(rows[it]); const NBloom::TPrefix prefix(key); - auto* part = born.At(it >= split ? 1 : 0).Get(); + auto* part = born.At(it >= split ? 1 : 0).Get(); UNIT_ASSERT_C(part->ByKey, "Part is missing a bloom filter"); UNIT_ASSERT_C( part->MightHaveKey(prefix.Get(key.size())), @@ -149,8 +149,8 @@ Y_UNIT_TEST_SUITE(TCompactionMulti) { TPartCook(mass.Model->Scheme, initialConf) .Add(mass.Saved.begin(), mass.Saved.end()) .Finish(); - UNIT_ASSERT_C(initial.Parts.size() == 1, - "Unexpected " << initial.Parts.size() << " results"); + UNIT_ASSERT_C(initial.Parts.size() == 1, + "Unexpected " << initial.Parts.size() << " results"); auto fullPartSize = initial.Parts.at(0)->Store->PageCollectionBytes(0); @@ -158,17 +158,17 @@ Y_UNIT_TEST_SUITE(TCompactionMulti) { conf.MainPageCollectionEdge = fullPartSize / 4; auto born = TCompaction(nullptr, conf).Do(initial); - UNIT_ASSERT_C(born.Parts.size() >= 4, - "Unexpected " << born.Parts.size() << " results after compaction"); + UNIT_ASSERT_C(born.Parts.size() >= 4, + "Unexpected " << born.Parts.size() << " results after compaction"); - for (auto &part : born.Parts) { + for (auto &part : born.Parts) { auto partSize = part->Store->PageCollectionBytes(0); UNIT_ASSERT_C(partSize <= conf.MainPageCollectionEdge, "Unexpected main page collection with " << partSize << " bytes," << " maximum of " << conf.MainPageCollectionEdge << " allowed"); } - TCheckIt(born, { }).IsTheSame(mass.Saved).Is(EReady::Gone); + TCheckIt(born, { }).IsTheSame(mass.Saved).Is(EReady::Gone); } Y_UNIT_TEST(MainPageCollectionOverflow) @@ -188,7 +188,7 @@ Y_UNIT_TEST_SUITE(TCompactionMulti) { rows.Put(*TNatural(*lay).Col(ui64(i), ui64(i * 10))); } - auto initialConf = NPage::TConf{ false, 2044 }; + auto initialConf = NPage::TConf{ false, 2044 }; initialConf.ByKeyFilter = true; initialConf.MaxRows = rows.Size(); @@ -217,7 +217,7 @@ Y_UNIT_TEST_SUITE(TCompactionMulti) { } } - auto initialConf = NPage::TConf{ false, 2044 }; + auto initialConf = NPage::TConf{ false, 2044 }; initialConf.ByKeyFilter = true; initialConf.MaxRows = rows.Size(); initialConf.SmallEdge = 13; @@ -247,7 +247,7 @@ Y_UNIT_TEST_SUITE(TCompactionMulti) { } } - auto initialConf = NPage::TConf{ false, 2044 }; + auto initialConf = NPage::TConf{ false, 2044 }; initialConf.ByKeyFilter = true; initialConf.MaxRows = rows.Size(); initialConf.LargeEdge = 13; diff --git a/ydb/core/tablet_flat/ut/ut_db_iface.cpp b/ydb/core/tablet_flat/ut/ut_db_iface.cpp index 9843e5a603..d592497fab 100644 --- a/ydb/core/tablet_flat/ut/ut_db_iface.cpp +++ b/ydb/core/tablet_flat/ut/ut_db_iface.cpp @@ -1,276 +1,276 @@ #include <ydb/core/tablet_flat/flat_dbase_scheme.h> #include <ydb/core/tablet_flat/test/libs/table/test_dbase.h> #include <ydb/core/tablet_flat/test/libs/rows/cook.h> - + #include <library/cpp/testing/unittest/registar.h> -#include <util/stream/file.h> - -namespace NKikimr { -namespace NTable { - +#include <util/stream/file.h> + +namespace NKikimr { +namespace NTable { + Y_UNIT_TEST_SUITE(DBase) { - using namespace NTest; - - TAlter MakeAlter(const ui32 table = 1) - { - TAlter alter; - - alter - .AddTable(Sprintf("me_%02u", table), table) + using namespace NTest; + + TAlter MakeAlter(const ui32 table = 1) + { + TAlter alter; + + alter + .AddTable(Sprintf("me_%02u", table), table) .AddColumn(table, "key", 1, ETypes::String, false) .AddColumn(table, "arg1", 4, ETypes::Uint64, false, Cimple(77_u64)) .AddColumn(table, "arg2", 5, ETypes::String, false) - .AddColumnToKey(table, 1); - - return alter; - } - + .AddColumnToKey(table, 1); + + return alter; + } + Y_UNIT_TEST(Basics) - { - TDbExec me; - - me.To(10).Begin().Apply(*MakeAlter().Flush()).Commit(); - - const auto nil = *me.Natural(1).Col(nullptr); - const auto foo = *me.Natural(1).Col("foo", 33_u64); - const auto bar = *me.Natural(1).Col("bar", 11_u64); + { + TDbExec me; + + me.To(10).Begin().Apply(*MakeAlter().Flush()).Commit(); + + const auto nil = *me.Natural(1).Col(nullptr); + const auto foo = *me.Natural(1).Col("foo", 33_u64); + const auto bar = *me.Natural(1).Col("bar", 11_u64); const auto ba1 = *me.Natural(1).Col("bar", ECellOp::Empty, "yo"); const auto ba2 = *me.Natural(1).Col("bar", ECellOp::Reset, "me"); const auto ba3 = *me.Natural(1).Col("bar", 99_u64, ECellOp::Reset); const auto ba4 = *me.Natural(1).Col("bar", ECellOp::Null, "eh"); - - me.To(11).Iter(1).NoKey(foo).NoKey(bar); - - /*_ 10: Check rollback and next working tx */ - - me.To(12).Begin().Add(1, foo).Add(1, nil).Commit(); - me.To(13).Iter(1).Has(foo).HasN(nullptr, 77_u64).NoKey(bar); - me.To(14).Begin().Add(1, bar).Reject(); - me.To(15).Iter(1).Has(foo).NoKey(bar); - me.To(16).Begin().Add(1, bar).Commit(); - me.To(17).Iter(1).Has(foo).Has(bar); - me.To(18).Affects(0, { 1 }); - - /* The following update just puts flush event to redo log, content - of alter script have no any other sense in context of this test. - Flush event will be checked on changes rollup and in redo log - ABI tests which uses log from this test. - */ - - me.To(19).Begin().Apply(*TAlter().SetRoom(1, 0, 1, 2, 1)).Commit(); - - /*_ 20: Check that log is applied correctly */ - - me.To(20).Replay(EPlay::Boot).Iter(1).Has(foo).Has(bar); - me.To(22).Replay(EPlay::Redo).Iter(1).Has(foo).Has(bar); - - /*_ 30: Check erase of some row and update */ - + + me.To(11).Iter(1).NoKey(foo).NoKey(bar); + + /*_ 10: Check rollback and next working tx */ + + me.To(12).Begin().Add(1, foo).Add(1, nil).Commit(); + me.To(13).Iter(1).Has(foo).HasN(nullptr, 77_u64).NoKey(bar); + me.To(14).Begin().Add(1, bar).Reject(); + me.To(15).Iter(1).Has(foo).NoKey(bar); + me.To(16).Begin().Add(1, bar).Commit(); + me.To(17).Iter(1).Has(foo).Has(bar); + me.To(18).Affects(0, { 1 }); + + /* The following update just puts flush event to redo log, content + of alter script have no any other sense in context of this test. + Flush event will be checked on changes rollup and in redo log + ABI tests which uses log from this test. + */ + + me.To(19).Begin().Apply(*TAlter().SetRoom(1, 0, 1, 2, 1)).Commit(); + + /*_ 20: Check that log is applied correctly */ + + me.To(20).Replay(EPlay::Boot).Iter(1).Has(foo).Has(bar); + me.To(22).Replay(EPlay::Redo).Iter(1).Has(foo).Has(bar); + + /*_ 30: Check erase of some row and update */ + me.To(30).Begin().Add(1, ba1).Add(1, foo, ERowOp::Erase).Commit(); - me.To(31).Iter(1, false).NoKey(foo).NoVal(bar); - me.To(32).Iter(1, false).HasN("bar", 11_u64, "yo"); /* omited arg1 */ - me.To(33).Begin().Add(1, ba2).Commit(); - me.To(34).Iter(1, false).HasN("bar", 77_u64, "me"); /* default arg1 */ - me.To(35).Begin().Add(1, ba3).Commit(); - me.To(36).Iter(1, false).HasN("bar", 99_u64, nullptr); - me.To(37).Begin().Add(1, ba4).Commit(); - me.To(38).Iter(1, false).HasN("bar", nullptr, "eh").Has(ba4); - - /*_ 40: Finally reboot again and check result */ - - me.To(40).Replay(EPlay::Boot).Iter(1, false).Has(ba4).NoKey(foo); - me.To(41).Replay(EPlay::Redo).Iter(1, false).Has(ba4).NoKey(foo); - - /*_ 50: Erase and update the same row in tx */ - + me.To(31).Iter(1, false).NoKey(foo).NoVal(bar); + me.To(32).Iter(1, false).HasN("bar", 11_u64, "yo"); /* omited arg1 */ + me.To(33).Begin().Add(1, ba2).Commit(); + me.To(34).Iter(1, false).HasN("bar", 77_u64, "me"); /* default arg1 */ + me.To(35).Begin().Add(1, ba3).Commit(); + me.To(36).Iter(1, false).HasN("bar", 99_u64, nullptr); + me.To(37).Begin().Add(1, ba4).Commit(); + me.To(38).Iter(1, false).HasN("bar", nullptr, "eh").Has(ba4); + + /*_ 40: Finally reboot again and check result */ + + me.To(40).Replay(EPlay::Boot).Iter(1, false).Has(ba4).NoKey(foo); + me.To(41).Replay(EPlay::Redo).Iter(1, false).Has(ba4).NoKey(foo); + + /*_ 50: Erase and update the same row in tx */ + me.To(50).Begin().Add(1, bar, ERowOp::Erase).Add(1, bar).Commit(); - me.To(51).Iter(1, false).Has(bar).NoKey(foo); - - /*_ 60: Check rows counters after compaction */ - - me.To(60).Snap(1).Compact(1, false).Iter(1, false).Has(bar); - + me.To(51).Iter(1, false).Has(bar).NoKey(foo); + + /*_ 60: Check rows counters after compaction */ + + me.To(60).Snap(1).Compact(1, false).Iter(1, false).Has(bar); + UNIT_ASSERT(me->Counters().Parts.RowsTotal == 3); UNIT_ASSERT(me->Counters().Parts.RowsErase == 1); - UNIT_ASSERT(me.GetLog().size() == 10); - } - + UNIT_ASSERT(me.GetLog().size() == 10); + } + Y_UNIT_TEST(Select) - { - TDbExec me; - - me.To(10).Begin().Apply(*MakeAlter().Flush()).Commit(); - - const auto bar = *me.Natural(1).Col("bar", 11_u64); + { + TDbExec me; + + me.To(10).Begin().Apply(*MakeAlter().Flush()).Commit(); + + const auto bar = *me.Natural(1).Col("bar", 11_u64); const auto ba1 = *me.Natural(1).Col("bar", ECellOp::Empty, "yo"); const auto ba2 = *me.Natural(1).Col("bar", ECellOp::Reset, "me"); const auto ba3 = *me.Natural(1).Col("bar", 99_u64, ECellOp::Reset); const auto ba4 = *me.Natural(1).Col("bar", ECellOp::Null, "eh"); - - me.To(11).Begin().Add(1, bar).Commit().Select(1).Has(bar); - me.To(12).Snap(1).Compact(1, false).Select(1).Has(bar); - me.To(20).Begin().Add(1, ba1).Commit().Snap(1).Compact(1, false); - me.To(21).Select(1).HasN("bar", 11_u64, "yo"); - me.To(30).Begin().Add(1, ba2).Commit().Snap(1).Compact(1, false); - me.To(31).Select(1).HasN("bar", 77_u64, "me"); - me.To(40).Begin().Add(1, ba3).Commit().Snap(1); - me.To(41).Select(1).HasN("bar", 99_u64, nullptr); - me.To(50).Begin().Add(1, ba4).Commit().Snap(1); - me.To(51).Select(1).Has(ba4); + + me.To(11).Begin().Add(1, bar).Commit().Select(1).Has(bar); + me.To(12).Snap(1).Compact(1, false).Select(1).Has(bar); + me.To(20).Begin().Add(1, ba1).Commit().Snap(1).Compact(1, false); + me.To(21).Select(1).HasN("bar", 11_u64, "yo"); + me.To(30).Begin().Add(1, ba2).Commit().Snap(1).Compact(1, false); + me.To(31).Select(1).HasN("bar", 77_u64, "me"); + me.To(40).Begin().Add(1, ba3).Commit().Snap(1); + me.To(41).Select(1).HasN("bar", 99_u64, nullptr); + me.To(50).Begin().Add(1, ba4).Commit().Snap(1); + me.To(51).Select(1).Has(ba4); me.To(60).Begin().Add(1, ba3, ERowOp::Erase).Commit().Snap(1); - me.To(61).Select(1).NoKey(bar); + me.To(61).Select(1).NoKey(bar); me.To(62).Begin().Add(1, bar, ERowOp::Upsert).Commit(); - me.To(63).Select(1).Has(bar); - - /* Ensure that test was acomplished on non-trivial subset */ - + me.To(63).Select(1).Has(bar); + + /* Ensure that test was acomplished on non-trivial subset */ + const auto subset = me->Subset(1, TEpoch::Max(), { }, { }); - + UNIT_ASSERT(subset->Flatten.size() == 3 && subset->Frozen.size() == 3); - } - + } + Y_UNIT_TEST(Defaults) - { - TDbExec me; - - const TString large30("0123456789abcdef0123456789abcd"); - const TString large35("0123456789abcdef0123456789abcdef012"); - - me.To(10).Begin().Apply(*MakeAlter().Flush()); - - const auto nuke = *me.Natural(1).Col(nullptr, 11_u64); - - me.To(11).Add(1, nuke).Commit().Iter(1).Has(nuke); - - me.To(12).Begin().Apply( - *TAlter() + { + TDbExec me; + + const TString large30("0123456789abcdef0123456789abcd"); + const TString large35("0123456789abcdef0123456789abcdef012"); + + me.To(10).Begin().Apply(*MakeAlter().Flush()); + + const auto nuke = *me.Natural(1).Col(nullptr, 11_u64); + + me.To(11).Add(1, nuke).Commit().Iter(1).Has(nuke); + + me.To(12).Begin().Apply( + *TAlter() .AddColumn(1, "sub", 2, ETypes::Uint32, false, Cimple(77_u32)) .AddColumn(1, "en0", 6, ETypes::String, false, TCell("", 0)) .AddColumn(1, "en1", 7, ETypes::String, false, TCell(large30)) .AddColumn(1, "en2", 8, ETypes::String, false, TCell(large35)) - .DropColumn(1, 5) - .AddColumnToKey(1, 2)); - - const auto foo = *me.Natural(1).Col("foo", nullptr, 33_u64); - const auto cap = *me.Natural(1).Col("cap", TOmit{ }, 33_u64); - const auto bar = *me.Natural(1).Col("bar", 11_u32, 33_u64, "me", "you"); - const auto ba8 = *me.Natural(1).Col("bar", 11_u32, 33_u64, ""); - const auto ba9 = *me.Natural(1).Col("bar", 11_u32, 33_u64, nullptr); - - me.To(13).Put(1, foo, cap, bar).Commit(); - me.Iter(1) - .To(14).HasN(nullptr, 77_u32, 11_u64, "", large30, large35) - .To(15).HasN("foo", nullptr, 33_u64, "", large30, large35) - .To(15).HasN("cap", 77_u32, 33_u64, "", large30, large35) - .To(16).HasN("bar", 11_u32, 33_u64, "me", "you", large35) - .To(17).NoVal(ba8).NoVal(ba9); - - me.To(20).Replay(EPlay::Boot); /* check incomplete keys rollup */ - - me.Iter(1) - .To(21).HasN(nullptr, 77_u32, 11_u64, "", large30, large35) - .To(22).HasN("foo", nullptr, 33_u64, "", large30, large35) - .To(23).HasN("cap", 77_u32, 33_u64, "", large30, large35) - .To(24).HasN("bar", 11_u32, 33_u64, "me", "you", large35); - } - + .DropColumn(1, 5) + .AddColumnToKey(1, 2)); + + const auto foo = *me.Natural(1).Col("foo", nullptr, 33_u64); + const auto cap = *me.Natural(1).Col("cap", TOmit{ }, 33_u64); + const auto bar = *me.Natural(1).Col("bar", 11_u32, 33_u64, "me", "you"); + const auto ba8 = *me.Natural(1).Col("bar", 11_u32, 33_u64, ""); + const auto ba9 = *me.Natural(1).Col("bar", 11_u32, 33_u64, nullptr); + + me.To(13).Put(1, foo, cap, bar).Commit(); + me.Iter(1) + .To(14).HasN(nullptr, 77_u32, 11_u64, "", large30, large35) + .To(15).HasN("foo", nullptr, 33_u64, "", large30, large35) + .To(15).HasN("cap", 77_u32, 33_u64, "", large30, large35) + .To(16).HasN("bar", 11_u32, 33_u64, "me", "you", large35) + .To(17).NoVal(ba8).NoVal(ba9); + + me.To(20).Replay(EPlay::Boot); /* check incomplete keys rollup */ + + me.Iter(1) + .To(21).HasN(nullptr, 77_u32, 11_u64, "", large30, large35) + .To(22).HasN("foo", nullptr, 33_u64, "", large30, large35) + .To(23).HasN("cap", 77_u32, 33_u64, "", large30, large35) + .To(24).HasN("bar", 11_u32, 33_u64, "me", "you", large35); + } + Y_UNIT_TEST(Subsets) - { - TDbExec me; - - me.To(10).Begin().Apply(*MakeAlter().Flush()).Commit(); - - const auto ro1 = *me.Natural(1).Col("row1", 11_u64, "foo"); - const auto ro2 = *me.Natural(1).Col("row2", 22_u64, "bar"); - const auto ro3 = *me.Natural(1).Col("row3", 33_u64, "foo"); - const auto ro4 = *me.Natural(1).Col("row4", 44_u64, "bar"); - - me.Begin().Put(1, ro1, ro2).Commit().Snap(1).Compact(1, false); - me.Begin().Put(1, ro3, ro4).Commit().Snap(1).Compact(1, false); - - { /*_ Check memtable snapshots for compactions */ + { + TDbExec me; + + me.To(10).Begin().Apply(*MakeAlter().Flush()).Commit(); + + const auto ro1 = *me.Natural(1).Col("row1", 11_u64, "foo"); + const auto ro2 = *me.Natural(1).Col("row2", 22_u64, "bar"); + const auto ro3 = *me.Natural(1).Col("row3", 33_u64, "foo"); + const auto ro4 = *me.Natural(1).Col("row4", 44_u64, "bar"); + + me.Begin().Put(1, ro1, ro2).Commit().Snap(1).Compact(1, false); + me.Begin().Put(1, ro3, ro4).Commit().Snap(1).Compact(1, false); + + { /*_ Check memtable snapshots for compactions */ auto subset = me->Subset(1, TEpoch::Max(), { }, { }); - + UNIT_ASSERT(subset->Flatten.size() == 2 && subset->Frozen.size() == 0); - UNIT_ASSERT(subset->Flatten[0]->Stat.Rows == 2); - UNIT_ASSERT(subset->Flatten[1]->Stat.Rows == 2); - } - - me.To(12).Iter(1).Has(ro1).Has(ro2).Has(ro3).Has(ro4); - me.Compact(1, true); /* should collapse all parts to one */ - me.To(13).Iter(1).Has(ro1).Has(ro2).Has(ro3).Has(ro4); - - { /*_ Check Replace(...) with non-trivail subsets */ + UNIT_ASSERT(subset->Flatten[0]->Stat.Rows == 2); + UNIT_ASSERT(subset->Flatten[1]->Stat.Rows == 2); + } + + me.To(12).Iter(1).Has(ro1).Has(ro2).Has(ro3).Has(ro4); + me.Compact(1, true); /* should collapse all parts to one */ + me.To(13).Iter(1).Has(ro1).Has(ro2).Has(ro3).Has(ro4); + + { /*_ Check Replace(...) with non-trivail subsets */ auto subset = me->Subset(1, TEpoch::Max(), { }, { }); - + UNIT_ASSERT(subset->Flatten.size() == 1 && subset->Frozen.size() == 0); - UNIT_ASSERT(subset->Flatten[0]->Stat.Rows == 4); - UNIT_ASSERT(subset->Flatten[0]->Stat.Drops == 0); - } - - { /*_ Ensure that debug dumper doesn't crash */ - TStringStream dump; - - me.Begin()->DebugDump(dump, *DbgRegistry()); - + UNIT_ASSERT(subset->Flatten[0]->Stat.Rows == 4); + UNIT_ASSERT(subset->Flatten[0]->Stat.Drops == 0); + } + + { /*_ Ensure that debug dumper doesn't crash */ + TStringStream dump; + + me.Begin()->DebugDump(dump, *DbgRegistry()); + UNIT_ASSERT(dump.Str().size() > 20 && dump.Str().size() < 10000); - } - } - + } + } + Y_UNIT_TEST(Garbage) - { - TDbExec me; - - me.To(10).Begin().Apply(*MakeAlter().Flush()).Commit(); - - const auto ro1 = *me.Natural(1).Col("foo", 11_u64, "boo"); - const auto ro2 = *me.Natural(1).Col("foo", 22_u64); - const auto ro3 = *me.Natural(1).Col("foo"); - const auto ro4 = *me.Natural(1).Col("foo", 99_u64); - - /*_ 10: Cut columns from table updating reduced row each time */ - - me.Begin().Add(1, ro1).Commit().Snap(1); - - me.To(11).Compact(1, false).Iter(1).Has(ro1); - - me.Begin().Apply(*TAlter().DropColumn(1, 5)).Add(1, ro2).Commit(); - - me.To(12).Compact(1, false).Iter(1).Has(ro2); - - me.Begin().Apply(*TAlter().DropColumn(1, 4)).Add(1, ro3).Commit(); - - me.To(14).Compact(1, false).Iter(1).Has(ro3); - - { /*_ Ressurect column, ** hack allowed only in this UT ** */ + { + TDbExec me; + + me.To(10).Begin().Apply(*MakeAlter().Flush()).Commit(); + + const auto ro1 = *me.Natural(1).Col("foo", 11_u64, "boo"); + const auto ro2 = *me.Natural(1).Col("foo", 22_u64); + const auto ro3 = *me.Natural(1).Col("foo"); + const auto ro4 = *me.Natural(1).Col("foo", 99_u64); + + /*_ 10: Cut columns from table updating reduced row each time */ + + me.Begin().Add(1, ro1).Commit().Snap(1); + + me.To(11).Compact(1, false).Iter(1).Has(ro1); + + me.Begin().Apply(*TAlter().DropColumn(1, 5)).Add(1, ro2).Commit(); + + me.To(12).Compact(1, false).Iter(1).Has(ro2); + + me.Begin().Apply(*TAlter().DropColumn(1, 4)).Add(1, ro3).Commit(); + + me.To(14).Compact(1, false).Iter(1).Has(ro3); + + { /*_ Ressurect column, ** hack allowed only in this UT ** */ auto raw = TAlter().AddColumn(1, "new", 4, ETypes::Uint64, false).Flush(); - - me.Begin().Apply(*raw).Add(1, ro4).Commit(); - } - + + me.Begin().Apply(*raw).Add(1, ro4).Commit(); + } + UNIT_ASSERT(me->Counters().MemTableOps == 2); UNIT_ASSERT(me->Counters().MemTableBytes > 0); UNIT_ASSERT(me->Counters().Parts.PlainBytes > 0); UNIT_ASSERT(me->Counters().Parts.IndexBytes > 0); - - me.To(16).Compact(1, false).Iter(1).Has(ro4); /* NOOP compaction */ - - /*_ 20: Add one more table to be garbage in final blow */ - - me.To(20).Begin().Apply(*MakeAlter(2).Flush()).Commit(); - me.To(21).Begin().Put(2, ro1, ro2).Commit().Snap(2).Compact(2); - + + me.To(16).Compact(1, false).Iter(1).Has(ro4); /* NOOP compaction */ + + /*_ 20: Add one more table to be garbage in final blow */ + + me.To(20).Begin().Apply(*MakeAlter(2).Flush()).Commit(); + me.To(21).Begin().Put(2, ro1, ro2).Commit().Snap(2).Compact(2); + UNIT_ASSERT(me->Counters().Parts.PartsCount == 4); - - /*_ 40: Finally drop entire table and check presence of garbage */ - - me.Begin().Apply(*TAlter().DropTable(1).DropTable(2)).Commit(); - - UNIT_ASSERT(me.BackLog().Garbage.size() == 2); - UNIT_ASSERT(me.BackLog().Garbage[0]->Flatten.size() == 3); - UNIT_ASSERT(me.BackLog().Garbage[0]->Frozen.size() == 1); - UNIT_ASSERT(me.BackLog().Garbage[1]->Flatten.size() == 1); - UNIT_ASSERT(me.BackLog().Garbage[1]->Frozen.size() == 0); + + /*_ 40: Finally drop entire table and check presence of garbage */ + + me.Begin().Apply(*TAlter().DropTable(1).DropTable(2)).Commit(); + + UNIT_ASSERT(me.BackLog().Garbage.size() == 2); + UNIT_ASSERT(me.BackLog().Garbage[0]->Flatten.size() == 3); + UNIT_ASSERT(me.BackLog().Garbage[0]->Frozen.size() == 1); + UNIT_ASSERT(me.BackLog().Garbage[1]->Flatten.size() == 1); + UNIT_ASSERT(me.BackLog().Garbage[1]->Frozen.size() == 0); UNIT_ASSERT(me->Counters().MemTableOps == 0); UNIT_ASSERT(me->Counters().MemTableBytes == 0); UNIT_ASSERT(me->Counters().Parts.RowsTotal == 0); @@ -279,215 +279,215 @@ Y_UNIT_TEST_SUITE(DBase) { UNIT_ASSERT(me->Counters().Parts.PlainBytes == 0); UNIT_ASSERT(me->Counters().Parts.IndexBytes == 0); UNIT_ASSERT(me->Counters().Parts.OtherBytes == 0); - } - + } + Y_UNIT_TEST(Affects) - { - TDbExec me; - - me.To(10).Begin().Apply(*MakeAlter(2)).Commit(); - - const auto row = *me.Natural(2).Col("foo", 11_u64, "bar"); - - /*_ 10: Basic affects on one table modification */ - - me.To(12).Begin().Apply(*MakeAlter(1)).Add(1, row); - me.To(14).Commit().Affects(0, { 1 }).Select(1).Has(row); - - /*_ 20: Rerolling the same scheme has no effects */ - - me.To(20).Begin().Apply(*MakeAlter(1)).Apply(*MakeAlter(2)); - me.To(21).Commit().Affects(0, { }).Select(1).Has(row); - - UNIT_ASSERT(me.BackLog().Scheme == nullptr); - - /*_ 30: Affects from table drop and snapshots */ - - me.To(30).Begin().Apply(*TAlter().DropTable(1)); - me.To(31).Commit().Affects(0, { }); - me.To(32).Begin().Add(2, row).Commit().Affects(0, { 2 }); - me.To(33).Begin().Snapshot(2).Commit().Affects(0, { 2 }); - me.To(34).Compact(2); - + { + TDbExec me; + + me.To(10).Begin().Apply(*MakeAlter(2)).Commit(); + + const auto row = *me.Natural(2).Col("foo", 11_u64, "bar"); + + /*_ 10: Basic affects on one table modification */ + + me.To(12).Begin().Apply(*MakeAlter(1)).Add(1, row); + me.To(14).Commit().Affects(0, { 1 }).Select(1).Has(row); + + /*_ 20: Rerolling the same scheme has no effects */ + + me.To(20).Begin().Apply(*MakeAlter(1)).Apply(*MakeAlter(2)); + me.To(21).Commit().Affects(0, { }).Select(1).Has(row); + + UNIT_ASSERT(me.BackLog().Scheme == nullptr); + + /*_ 30: Affects from table drop and snapshots */ + + me.To(30).Begin().Apply(*TAlter().DropTable(1)); + me.To(31).Commit().Affects(0, { }); + me.To(32).Begin().Add(2, row).Commit().Affects(0, { 2 }); + me.To(33).Begin().Snapshot(2).Commit().Affects(0, { 2 }); + me.To(34).Compact(2); + UNIT_ASSERT(me->Counters().MemTableOps == 0); UNIT_ASSERT(me.BackLog().Snapshots.at(0).Epoch == TEpoch::FromIndex(2)); - - { + + { const auto subset = me->Subset(2, TEpoch::Max(), { }, { }); - + UNIT_ASSERT(subset->Flatten.size() == 1 && subset->Frozen.size() == 0); - } - - me.To(40).Replay(EPlay::Boot).Replay(EPlay::Redo); - } - + } + + me.To(40).Replay(EPlay::Boot).Replay(EPlay::Redo); + } + Y_UNIT_TEST(WideKey) - { + { const TIntrusivePtr<TGrowHeap> heap = new TGrowHeap(128 * 1024); - - for (auto keys: { 128, 512, 1024, 4096, 8192, 9999 }) { - auto alter = MakeAlter(); - - for (auto sub : xrange(keys)) { - auto name = Sprintf("sub_%04u", sub); + + for (auto keys: { 128, 512, 1024, 4096, 8192, 9999 }) { + auto alter = MakeAlter(); + + for (auto sub : xrange(keys)) { + auto name = Sprintf("sub_%04u", sub); alter.AddColumn(1, name, 6 + sub, ETypes::Uint32, false); - alter.AddColumnToKey(1, 6 + sub); - } - - TRow row(heap); - - row.Do(1, "foo").Do(4, 77_u64); - - for (auto sub : xrange(keys)) - row.Do(6 + sub, ui32(7 + sub)); - - TDbExec me; - - me.To(keys * 10 + 1).Begin().Apply(*alter).Add(1, row); - me.To(keys * 10 + 2).Commit().Iter(1).Has(row); - me.To(keys * 10 + 3).Compact(1, true).Iter(1).Has(row); - } - } - + alter.AddColumnToKey(1, 6 + sub); + } + + TRow row(heap); + + row.Do(1, "foo").Do(4, 77_u64); + + for (auto sub : xrange(keys)) + row.Do(6 + sub, ui32(7 + sub)); + + TDbExec me; + + me.To(keys * 10 + 1).Begin().Apply(*alter).Add(1, row); + me.To(keys * 10 + 2).Commit().Iter(1).Has(row); + me.To(keys * 10 + 3).Compact(1, true).Iter(1).Has(row); + } + } + Y_UNIT_TEST(Annex) - { - auto alter = MakeAlter(1); - + { + auto alter = MakeAlter(1); + alter.SetRedo(32).SetFamilyBlobs(1, 0, Max<ui32>(), 24); - - TDbExec me; - - me.To(10).Begin().Apply(*alter.Flush()).Commit(); - - const TString large30("0123456789abcdef0123456789abcd"); - const TString large35("0123456789abcdef0123456789abcdef012"); - const TString large42("0123456789abcdef0123456789abcdef0123456789"); - const TString large44("0123456789abcdef0123456789abcdef0123456789ab"); - - const auto foo = *me.Natural(1).Col("foo", 77_u64, "foo"); - const auto ro30 = *me.Natural(1).Col("l30", 30_u64, large30); - const auto ro35 = *me.Natural(1).Col("l35", 35_u64, large35); - const auto ro42 = *me.Natural(1).Col("l42", 42_u64, large42); - const auto ro44 = *me.Natural(1).Col("l44", 44_u64, large44); - const auto zap = *me.Natural(1).Col("zap", 55_u64, "zap"); - - /*_ 10: Regular write without producing annex to redo log */ - - me.To(12).Begin().Put(1, foo, ro30).Commit(); - me.To(13).Iter(1, false).Has(foo).Has(ro30); - - UNIT_ASSERT(me.BackLog().Annex.size() == 0); - - /*_ 20: Put oversized blobs that should be placed to annex */ - - me.To(20).Begin().Put(1, zap, ro35, ro42).Commit(); - me.To(21).Iter(1, false).Has(zap).Has(ro35).Has(ro42); - - UNIT_ASSERT(me.BackLog().Annex.size() == 2); - UNIT_ASSERT(me.BackLog().Annex[0].Data.size() == 8 + 35); - UNIT_ASSERT(me.BackLog().Annex[1].Data.size() == 8 + 42); - + + TDbExec me; + + me.To(10).Begin().Apply(*alter.Flush()).Commit(); + + const TString large30("0123456789abcdef0123456789abcd"); + const TString large35("0123456789abcdef0123456789abcdef012"); + const TString large42("0123456789abcdef0123456789abcdef0123456789"); + const TString large44("0123456789abcdef0123456789abcdef0123456789ab"); + + const auto foo = *me.Natural(1).Col("foo", 77_u64, "foo"); + const auto ro30 = *me.Natural(1).Col("l30", 30_u64, large30); + const auto ro35 = *me.Natural(1).Col("l35", 35_u64, large35); + const auto ro42 = *me.Natural(1).Col("l42", 42_u64, large42); + const auto ro44 = *me.Natural(1).Col("l44", 44_u64, large44); + const auto zap = *me.Natural(1).Col("zap", 55_u64, "zap"); + + /*_ 10: Regular write without producing annex to redo log */ + + me.To(12).Begin().Put(1, foo, ro30).Commit(); + me.To(13).Iter(1, false).Has(foo).Has(ro30); + + UNIT_ASSERT(me.BackLog().Annex.size() == 0); + + /*_ 20: Put oversized blobs that should be placed to annex */ + + me.To(20).Begin().Put(1, zap, ro35, ro42).Commit(); + me.To(21).Iter(1, false).Has(zap).Has(ro35).Has(ro42); + + UNIT_ASSERT(me.BackLog().Annex.size() == 2); + UNIT_ASSERT(me.BackLog().Annex[0].Data.size() == 8 + 35); + UNIT_ASSERT(me.BackLog().Annex[1].Data.size() == 8 + 42); + /*_ 26: Annex should be promoted to external blobs in TMemTable */ - + auto subset = me.To(26).Snap(1)->Subset(1, TEpoch::Max(), { }, { }); - - UNIT_ASSERT(subset->Frozen.size() == 1 && subset->Flatten.size() == 0); + + UNIT_ASSERT(subset->Frozen.size() == 1 && subset->Flatten.size() == 0); UNIT_ASSERT(subset->Frozen[0]->GetBlobs()->Tail() == 2); - - /* Extra 8 bytes in each annex or external blob is occupied by - NPage::TLabel prefix which prefixes many binary units in NTable - */ - + + /* Extra 8 bytes in each annex or external blob is occupied by + NPage::TLabel prefix which prefixes many binary units in NTable + */ + UNIT_ASSERT(subset->Frozen[0]->GetBlobs()->GetRaw(0).Data.size() == 8 + 35); UNIT_ASSERT(subset->Frozen[0]->GetBlobs()->GetRaw(1).Data.size() == 8 + 42); - + /*_ 28: Test blobs refereces generation after TMemTable snapshot */ - - me.To(28).Begin().Put(1, ro44).Commit().Iter(1, false).Has(ro44); - - UNIT_ASSERT(me.BackLog().Annex.size() == 1); - UNIT_ASSERT(me.BackLog().Annex[0].Data.size() == 8 + 44); - - /*_ 30: Check that redo log replaying handle annex correctly */ - - me.To(30).Replay(EPlay::Boot).Iter(1).Has(foo, ro30, ro35, ro42, ro44); - me.To(31).Replay(EPlay::Redo).Iter(1).Has(foo, ro30, ro35, ro42, ro44); - - /*_ 40: Compaction should turn all largeXX to external blobs */ - + + me.To(28).Begin().Put(1, ro44).Commit().Iter(1, false).Has(ro44); + + UNIT_ASSERT(me.BackLog().Annex.size() == 1); + UNIT_ASSERT(me.BackLog().Annex[0].Data.size() == 8 + 44); + + /*_ 30: Check that redo log replaying handle annex correctly */ + + me.To(30).Replay(EPlay::Boot).Iter(1).Has(foo, ro30, ro35, ro42, ro44); + me.To(31).Replay(EPlay::Redo).Iter(1).Has(foo, ro30, ro35, ro42, ro44); + + /*_ 40: Compaction should turn all largeXX to external blobs */ + auto last = me.To(40).Snap(1).Compact(1)->Subset(1, TEpoch::FromIndex(666), { }, { }); - - UNIT_ASSERT(last->Frozen.size() == 0 && last->Flatten.size() == 1); - - UNIT_ASSERT(last->Flatten[0]->Blobs->Total() == 4); - UNIT_ASSERT(last->Flatten[0]->Blobs->Glob(0).Bytes() == 8 + 30); - UNIT_ASSERT(last->Flatten[0]->Blobs->Glob(1).Bytes() == 8 + 35); - UNIT_ASSERT(last->Flatten[0]->Blobs->Glob(2).Bytes() == 8 + 42); - UNIT_ASSERT(last->Flatten[0]->Blobs->Glob(3).Bytes() == 8 + 44); - + + UNIT_ASSERT(last->Frozen.size() == 0 && last->Flatten.size() == 1); + + UNIT_ASSERT(last->Flatten[0]->Blobs->Total() == 4); + UNIT_ASSERT(last->Flatten[0]->Blobs->Glob(0).Bytes() == 8 + 30); + UNIT_ASSERT(last->Flatten[0]->Blobs->Glob(1).Bytes() == 8 + 35); + UNIT_ASSERT(last->Flatten[0]->Blobs->Glob(2).Bytes() == 8 + 42); + UNIT_ASSERT(last->Flatten[0]->Blobs->Glob(3).Bytes() == 8 + 44); + UNIT_ASSERT(me->Counters().Parts.LargeItems == 4); UNIT_ASSERT(me->Counters().Parts.LargeBytes == 4 * 8 + 30 + 35 + 42 + 44); - - me.To(41).Iter(1).Has(foo).Has(foo, ro30, ro35, ro42, ro44, zap); - - /*_ 50: Finally, check that annexed counter really grows */ - - me.To(50).Begin().Put(1, zap).Commit().Snap(1); - + + me.To(41).Iter(1).Has(foo).Has(foo, ro30, ro35, ro42, ro44, zap); + + /*_ 50: Finally, check that annexed counter really grows */ + + me.To(50).Begin().Put(1, zap).Commit().Snap(1); + auto closed = me->Subset(1, TEpoch::Max(), { }, { }); - + UNIT_ASSERT(closed->Frozen.at(0)->GetBlobs()->Head == 3); - } - + } + Y_UNIT_TEST(Outer) - { - auto alter = MakeAlter(1); - - TDbExec me; - + { + auto alter = MakeAlter(1); + + TDbExec me; + me.To(10).Begin().Apply(*alter.SetFamilyBlobs(1, 0, 17, 999)).Commit(); - - const TString small17("0123456789abcdef0"); - const TString small21("0123456789abcdef01234"); - - const auto foo = *me.Natural(1).Col("foo", 77_u64, "foo"); - const auto ro17 = *me.Natural(1).Col("s17", 17_u64, small17); - const auto ro21 = *me.Natural(1).Col("s21", 21_u64, small21); - - /*_ 10: Prepare two parts with attached outer blobs */ - - me.To(12).Begin().Put(1, foo, ro17).Commit().Snap(1).Compact(1, false); - me.To(14).Begin().Put(1, foo, ro21).Commit().Snap(1).Compact(1, false); - me.To(16).Iter(1, false).Has(foo, ro17, ro21); - + + const TString small17("0123456789abcdef0"); + const TString small21("0123456789abcdef01234"); + + const auto foo = *me.Natural(1).Col("foo", 77_u64, "foo"); + const auto ro17 = *me.Natural(1).Col("s17", 17_u64, small17); + const auto ro21 = *me.Natural(1).Col("s21", 21_u64, small21); + + /*_ 10: Prepare two parts with attached outer blobs */ + + me.To(12).Begin().Put(1, foo, ro17).Commit().Snap(1).Compact(1, false); + me.To(14).Begin().Put(1, foo, ro21).Commit().Snap(1).Compact(1, false); + me.To(16).Iter(1, false).Has(foo, ro17, ro21); + auto subset = me.To(18)->Subset(1, TEpoch::Max(), { }, { }); - + UNIT_ASSERT(subset->Flatten.size() == 2 && subset->Flatten[0]->Small); - UNIT_ASSERT(subset->Flatten[0]->Small->Stats().Items == 1); + UNIT_ASSERT(subset->Flatten[0]->Small->Stats().Items == 1); UNIT_ASSERT(me->Counters().Parts.SmallItems == 2); UNIT_ASSERT(me->Counters().Parts.SmallBytes == 2 * 8 + 17 + 21); UNIT_ASSERT(me->Counters().Parts.OtherBytes > 30); - - /*_ 20: Compact all data to the single final part */ - + + /*_ 20: Compact all data to the single final part */ + auto last = me.To(20).Compact(1, true)->Subset(1, TEpoch::FromIndex(666), { }, { }); - + UNIT_ASSERT(last->Flatten.size() == 1 && last->Flatten[0]->Small); - UNIT_ASSERT(last->Flatten[0]->Small->Stats().Items == 2); - UNIT_ASSERT(last->Flatten[0]->Small->Stats().Size == 54); + UNIT_ASSERT(last->Flatten[0]->Small->Stats().Items == 2); + UNIT_ASSERT(last->Flatten[0]->Small->Stats().Size == 54); UNIT_ASSERT(me->Counters().Parts.SmallItems == 2); UNIT_ASSERT(me->Counters().Parts.SmallBytes == 2 * 8 + 17 + 21); UNIT_ASSERT(me->Counters().Parts.OtherBytes > 30); - - /*_ 30: Clean database and check that all data gone */ - - me.To(30).Begin().Apply(*TAlter().DropTable(1)).Commit(); - + + /*_ 30: Clean database and check that all data gone */ + + me.To(30).Begin().Apply(*TAlter().DropTable(1)).Commit(); + UNIT_ASSERT(me->Counters().Parts.SmallItems == 0); UNIT_ASSERT(me->Counters().Parts.SmallBytes == 0); UNIT_ASSERT(me->Counters().Parts.OtherBytes == 0); - } - + } + Y_UNIT_TEST(VersionBasics) { TDbExec me; @@ -734,7 +734,7 @@ Y_UNIT_TEST_SUITE(DBase) { RunVersionChecks(true, true); } -} - -} -} +} + +} +} diff --git a/ydb/core/tablet_flat/ut/ut_db_scheme.cpp b/ydb/core/tablet_flat/ut/ut_db_scheme.cpp index ee12efa903..03fd104616 100644 --- a/ydb/core/tablet_flat/ut/ut_db_scheme.cpp +++ b/ydb/core/tablet_flat/ut/ut_db_scheme.cpp @@ -2,207 +2,207 @@ #include <ydb/core/scheme/scheme_types_defs.h> #include <ydb/core/tablet_flat/flat_dbase_apply.h> -namespace NKikimr { -namespace NTable { - -namespace { - - struct TModel { - using ECodec = NKikimr::NTable::NPage::ECodec; - using ECache = NKikimr::NTable::NPage::ECache; - - enum ETokens : ui32 { - TableId = 1, - - ColId1 = 1, - ColId2 = 2, - - GroupId1 = NKikimr::NTable::TColumn::LeaderFamily, - GroupId2 = GroupId1 + 3, - - StoreIdDef = TScheme::DefaultRoom, - StoreIdOut = StoreIdDef + 5, - - ChannelDef = TScheme::DefaultChannel, - ChannelOut = ChannelDef + 7, - ChannelBlobs = ChannelDef + 11, - }; - - TModel() { }; - - TAlter Build() const - { - TAlter bld; - - using namespace NKikimr; - - bld.AddTable("table1", TableId); - bld.SetRoom(TableId, StoreIdOut, ChannelOut, ChannelBlobs, ChannelOut); - bld.AddFamily(TableId, GroupId1, StoreIdDef); - bld.SetFamily(TableId, GroupId1, ECache::Ever, ECodec::LZ4); - bld.AddFamily(TableId, GroupId2, StoreIdOut); +namespace NKikimr { +namespace NTable { + +namespace { + + struct TModel { + using ECodec = NKikimr::NTable::NPage::ECodec; + using ECache = NKikimr::NTable::NPage::ECache; + + enum ETokens : ui32 { + TableId = 1, + + ColId1 = 1, + ColId2 = 2, + + GroupId1 = NKikimr::NTable::TColumn::LeaderFamily, + GroupId2 = GroupId1 + 3, + + StoreIdDef = TScheme::DefaultRoom, + StoreIdOut = StoreIdDef + 5, + + ChannelDef = TScheme::DefaultChannel, + ChannelOut = ChannelDef + 7, + ChannelBlobs = ChannelDef + 11, + }; + + TModel() { }; + + TAlter Build() const + { + TAlter bld; + + using namespace NKikimr; + + bld.AddTable("table1", TableId); + bld.SetRoom(TableId, StoreIdOut, ChannelOut, ChannelBlobs, ChannelOut); + bld.AddFamily(TableId, GroupId1, StoreIdDef); + bld.SetFamily(TableId, GroupId1, ECache::Ever, ECodec::LZ4); + bld.AddFamily(TableId, GroupId2, StoreIdOut); bld.AddColumn(TableId, "key", ColId1, NScheme::TSmallBoundedString::TypeId, { }); - bld.AddColumn(TableId, "value", ColId2, NScheme::TUint32::TypeId, { }); - bld.AddColumnToKey(TableId, ColId1); - bld.AddColumnToFamily(TableId, ColId1, GroupId1); - bld.AddColumnToFamily(TableId, ColId2, GroupId2); - - return bld; - } - - void Check(const TScheme &scheme) const - { - UNIT_ASSERT(scheme.Tables.size() == 1); - - auto it= scheme.Tables.find(TableId); - - UNIT_ASSERT(it != scheme.Tables.end()); - - const auto &table = it->second; - - UNIT_ASSERT(table.Columns.size() == 2); - UNIT_ASSERT(table.Families.size() == 2); - UNIT_ASSERT(table.Rooms.size() == 2); - - if (const auto *family = table.Families.FindPtr(GroupId1)) { - UNIT_ASSERT(family->Room == StoreIdDef); - UNIT_ASSERT(family->Cache == ECache::Ever); - UNIT_ASSERT(family->Codec == ECodec::LZ4); - UNIT_ASSERT(family->Large == Max<ui32>()); - } else { - UNIT_FAIL("Cannot find primary group in scheme"); - } - - UNIT_ASSERT(table.Families.find(GroupId2)->second.Room == StoreIdOut); - UNIT_ASSERT(table.Rooms.find(StoreIdDef)->second.Main == ChannelDef); - UNIT_ASSERT(table.Rooms.find(StoreIdDef)->second.Blobs == ChannelDef); - UNIT_ASSERT(table.Rooms.find(StoreIdOut)->second.Main == ChannelOut); - UNIT_ASSERT(table.Rooms.find(StoreIdOut)->second.Blobs == ChannelBlobs); - } - }; - - struct TCompare { - using TTableInfo = TScheme::TTableInfo; - - bool Do(ui32 table, const TScheme &left, const TScheme &right) const - { - auto le = left.Tables.find(table); - auto ri = right.Tables.find(table); - - return - le != left.Tables.end() - && ri != right.Tables.end() - && Do(le->second, ri->second); - } - - bool Do(const TTableInfo &base, const TTableInfo &with) const - { - return - base.Id == with.Id - && base.Name == with.Name - && ByValues(base.Columns, with.Columns) - && ByValues(base.Families, with.Families) - && ByValues(base.Rooms, with.Rooms); - } - - template<typename TValues> - static bool ByValues(const TValues &base, const TValues &with) - { - ui32 errors = (base.size() == with.size() ? 0 : 1); - - for (auto &it: base) { - const auto &on = with.find(it.first); - - if (on == with.end()) { - // Sometimes will be replaced with log line - } else if (!it.second.IsTheSame(on->second)) { - // Sometimes will be replaced with log line - } else - continue; - - errors++; - } - - return errors == 0; - } - }; -} - + bld.AddColumn(TableId, "value", ColId2, NScheme::TUint32::TypeId, { }); + bld.AddColumnToKey(TableId, ColId1); + bld.AddColumnToFamily(TableId, ColId1, GroupId1); + bld.AddColumnToFamily(TableId, ColId2, GroupId2); + + return bld; + } + + void Check(const TScheme &scheme) const + { + UNIT_ASSERT(scheme.Tables.size() == 1); + + auto it= scheme.Tables.find(TableId); + + UNIT_ASSERT(it != scheme.Tables.end()); + + const auto &table = it->second; + + UNIT_ASSERT(table.Columns.size() == 2); + UNIT_ASSERT(table.Families.size() == 2); + UNIT_ASSERT(table.Rooms.size() == 2); + + if (const auto *family = table.Families.FindPtr(GroupId1)) { + UNIT_ASSERT(family->Room == StoreIdDef); + UNIT_ASSERT(family->Cache == ECache::Ever); + UNIT_ASSERT(family->Codec == ECodec::LZ4); + UNIT_ASSERT(family->Large == Max<ui32>()); + } else { + UNIT_FAIL("Cannot find primary group in scheme"); + } + + UNIT_ASSERT(table.Families.find(GroupId2)->second.Room == StoreIdOut); + UNIT_ASSERT(table.Rooms.find(StoreIdDef)->second.Main == ChannelDef); + UNIT_ASSERT(table.Rooms.find(StoreIdDef)->second.Blobs == ChannelDef); + UNIT_ASSERT(table.Rooms.find(StoreIdOut)->second.Main == ChannelOut); + UNIT_ASSERT(table.Rooms.find(StoreIdOut)->second.Blobs == ChannelBlobs); + } + }; + + struct TCompare { + using TTableInfo = TScheme::TTableInfo; + + bool Do(ui32 table, const TScheme &left, const TScheme &right) const + { + auto le = left.Tables.find(table); + auto ri = right.Tables.find(table); + + return + le != left.Tables.end() + && ri != right.Tables.end() + && Do(le->second, ri->second); + } + + bool Do(const TTableInfo &base, const TTableInfo &with) const + { + return + base.Id == with.Id + && base.Name == with.Name + && ByValues(base.Columns, with.Columns) + && ByValues(base.Families, with.Families) + && ByValues(base.Rooms, with.Rooms); + } + + template<typename TValues> + static bool ByValues(const TValues &base, const TValues &with) + { + ui32 errors = (base.size() == with.size() ? 0 : 1); + + for (auto &it: base) { + const auto &on = with.find(it.first); + + if (on == with.end()) { + // Sometimes will be replaced with log line + } else if (!it.second.IsTheSame(on->second)) { + // Sometimes will be replaced with log line + } else + continue; + + errors++; + } + + return errors == 0; + } + }; +} + Y_UNIT_TEST_SUITE(TScheme) { Y_UNIT_TEST(Shapshot) - { - const TModel model; - - TScheme origin; + { + const TModel model; + + TScheme origin; - TSchemeModifier(origin).Apply(*model.Build().Flush()); + TSchemeModifier(origin).Apply(*model.Build().Flush()); - model.Check(origin); + model.Check(origin); - TScheme restored; + TScheme restored; - TSchemeModifier(restored).Apply(*origin.GetSnapshot()); + TSchemeModifier(restored).Apply(*origin.GetSnapshot()); - model.Check(restored); - - UNIT_ASSERT(!TCompare().Do(TModel::TableId, origin, {})); - UNIT_ASSERT(TCompare().Do(TModel::TableId, origin, origin)); - UNIT_ASSERT(TCompare().Do(TModel::TableId, origin, restored)); + model.Check(restored); + + UNIT_ASSERT(!TCompare().Do(TModel::TableId, origin, {})); + UNIT_ASSERT(TCompare().Do(TModel::TableId, origin, origin)); + UNIT_ASSERT(TCompare().Do(TModel::TableId, origin, restored)); } Y_UNIT_TEST(Delta) - { - const TModel model; + { + const TModel model; - TAlter delta = model.Build(); + TAlter delta = model.Build(); - TScheme restored; + TScheme restored; - TSchemeModifier(restored).Apply(*delta.Flush()); + TSchemeModifier(restored).Apply(*delta.Flush()); - model.Check(restored); + model.Check(restored); } Y_UNIT_TEST(Policy) - { - auto delta = TModel().Build(); - - TIntrusivePtr<TCompactionPolicy> policy = new TCompactionPolicy(); - policy->InMemSizeToSnapshot = 1234; - policy->InMemStepsToSnapshot = 100; - policy->InMemForceStepsToSnapshot = 200; - policy->InMemForceSizeToSnapshot = 5678; - policy->InMemResourceBrokerTask = NLocalDb::LegacyQueueIdToTaskName(0); - policy->ReadAheadHiThreshold = 100000; - policy->ReadAheadLoThreshold = 50000; - policy->Generations.push_back({150, 3, 4, 250, NLocalDb::LegacyQueueIdToTaskName(1), true}); - policy->Generations.push_back({550, 7, 8, 950, NLocalDb::LegacyQueueIdToTaskName(2), false}); - - delta.SetCompactionPolicy(TModel::TableId, *policy); - - TAutoPtr<TScheme> scheme = new TScheme(); - TSchemeModifier(*scheme).Apply(*delta.Flush()); + { + auto delta = TModel().Build(); + + TIntrusivePtr<TCompactionPolicy> policy = new TCompactionPolicy(); + policy->InMemSizeToSnapshot = 1234; + policy->InMemStepsToSnapshot = 100; + policy->InMemForceStepsToSnapshot = 200; + policy->InMemForceSizeToSnapshot = 5678; + policy->InMemResourceBrokerTask = NLocalDb::LegacyQueueIdToTaskName(0); + policy->ReadAheadHiThreshold = 100000; + policy->ReadAheadLoThreshold = 50000; + policy->Generations.push_back({150, 3, 4, 250, NLocalDb::LegacyQueueIdToTaskName(1), true}); + policy->Generations.push_back({550, 7, 8, 950, NLocalDb::LegacyQueueIdToTaskName(2), false}); + + delta.SetCompactionPolicy(TModel::TableId, *policy); + + TAutoPtr<TScheme> scheme = new TScheme(); + TSchemeModifier(*scheme).Apply(*delta.Flush()); auto snapshot = scheme->GetSnapshot(); TAutoPtr<TScheme> scheme2 = new TScheme(); - TSchemeModifier(*scheme2).Apply(*snapshot); - - if (auto &policy = scheme2->GetTableInfo(TModel::TableId)->CompactionPolicy) { - UNIT_ASSERT_VALUES_EQUAL(policy->InMemSizeToSnapshot, 1234); - UNIT_ASSERT_VALUES_EQUAL(policy->InMemStepsToSnapshot, 100); - UNIT_ASSERT_VALUES_EQUAL(policy->InMemForceStepsToSnapshot, 200); - UNIT_ASSERT_VALUES_EQUAL(policy->InMemForceSizeToSnapshot, 5678); - UNIT_ASSERT_VALUES_EQUAL(policy->ReadAheadHiThreshold, 100000); - UNIT_ASSERT_VALUES_EQUAL(policy->ReadAheadLoThreshold, 50000); - UNIT_ASSERT_VALUES_EQUAL(policy->Generations.size(), 2); - UNIT_ASSERT_VALUES_EQUAL(policy->Generations[0].SizeToCompact, 150); - UNIT_ASSERT_VALUES_EQUAL(policy->Generations[0].KeepInCache, true); - UNIT_ASSERT_VALUES_EQUAL(policy->Generations[1].ForceSizeToCompact, 950); - UNIT_ASSERT_VALUES_EQUAL(policy->Generations[1].KeepInCache, false); - } else { - UNIT_ASSERT(false); - } + TSchemeModifier(*scheme2).Apply(*snapshot); + + if (auto &policy = scheme2->GetTableInfo(TModel::TableId)->CompactionPolicy) { + UNIT_ASSERT_VALUES_EQUAL(policy->InMemSizeToSnapshot, 1234); + UNIT_ASSERT_VALUES_EQUAL(policy->InMemStepsToSnapshot, 100); + UNIT_ASSERT_VALUES_EQUAL(policy->InMemForceStepsToSnapshot, 200); + UNIT_ASSERT_VALUES_EQUAL(policy->InMemForceSizeToSnapshot, 5678); + UNIT_ASSERT_VALUES_EQUAL(policy->ReadAheadHiThreshold, 100000); + UNIT_ASSERT_VALUES_EQUAL(policy->ReadAheadLoThreshold, 50000); + UNIT_ASSERT_VALUES_EQUAL(policy->Generations.size(), 2); + UNIT_ASSERT_VALUES_EQUAL(policy->Generations[0].SizeToCompact, 150); + UNIT_ASSERT_VALUES_EQUAL(policy->Generations[0].KeepInCache, true); + UNIT_ASSERT_VALUES_EQUAL(policy->Generations[1].ForceSizeToCompact, 950); + UNIT_ASSERT_VALUES_EQUAL(policy->Generations[1].KeepInCache, false); + } else { + UNIT_ASSERT(false); + } } } diff --git a/ydb/core/tablet_flat/ut/ut_forward.cpp b/ydb/core/tablet_flat/ut/ut_forward.cpp index 246d3c70b3..d21d1b5f7c 100644 --- a/ydb/core/tablet_flat/ut/ut_forward.cpp +++ b/ydb/core/tablet_flat/ut/ut_forward.cpp @@ -6,226 +6,226 @@ #include <ydb/core/tablet_flat/flat_fwd_sieve.h> #include <ydb/core/tablet_flat/test/libs/table/test_steps.h> #include <library/cpp/testing/unittest/registar.h> -#include <util/random/shuffle.h> -#include <util/random/mersenne.h> - -namespace NKikimr { -namespace NTable { - -namespace { - +#include <util/random/shuffle.h> +#include <util/random/mersenne.h> + +namespace NKikimr { +namespace NTable { + +namespace { + struct TWrap : public NTest::TSteps<TWrap>, protected NFwd::IPageLoadingQueue { - using TFrames = NPage::TFrames; - + using TFrames = NPage::TFrames; + TWrap(TIntrusiveConstPtr<TFrames> frames, TIntrusiveConstPtr<TSlices> run, ui32 edge, ui64 aLo = 999, ui64 aHi = 999) - : Large(std::move(frames)) + : Large(std::move(frames)) , Run(std::move(run)) - , Edge(edge) - , AheadLo(aLo) - , AheadHi(aHi) - { - TVector<ui32> edges(Large->Stats().Tags.size(), edge); - + , Edge(edge) + , AheadLo(aLo) + , AheadHi(aHi) + { + TVector<ui32> edges(Large->Stats().Tags.size(), edge); + Cache = new NFwd::TBlobs(Large, Run, edges, true); - } - + } + TWrap(TIntrusiveConstPtr<TFrames> frames, ui32 edge, ui64 aLo = 999, ui64 aHi = 999) : TWrap(std::move(frames), TSlices::All(), edge, aLo, aHi) { } ui64 AddToQueue(ui32 page, ui16) noexcept override - { - Pages.push_back(page); - - return Large->Relation(page).Size; - } - - TDeque<TScreen::THole> Trace() noexcept - { - return dynamic_cast<NFwd::TBlobs&>(*Cache).Traced(); - } - - TWrap& Get(ui32 page, bool has, bool grow, bool need) - { - auto got = Cache->Handle(this, page, AheadLo); - - if (has != bool(got.Page) || grow != got.Grow || need != got.Need){ - Log() - << "Page " << page << " lookup got" - << " data=" << bool(got.Page) << "(" << has <<")" - << ", grow=" << got.Grow << "(" << grow << ")" - << ", need=" << got.Need << "(" << need << ")" - << Endl; - - UNIT_ASSERT(false); - } - - Grow = Grow || got.Grow; - - return *this; - } - - TWrap& Fill(ui32 least, ui32 most, std::initializer_list<ui16> tags) - { - if (std::exchange(Grow, false)) - Cache->Forward(this, AheadHi); - + { + Pages.push_back(page); + + return Large->Relation(page).Size; + } + + TDeque<TScreen::THole> Trace() noexcept + { + return dynamic_cast<NFwd::TBlobs&>(*Cache).Traced(); + } + + TWrap& Get(ui32 page, bool has, bool grow, bool need) + { + auto got = Cache->Handle(this, page, AheadLo); + + if (has != bool(got.Page) || grow != got.Grow || need != got.Need){ + Log() + << "Page " << page << " lookup got" + << " data=" << bool(got.Page) << "(" << has <<")" + << ", grow=" << got.Grow << "(" << grow << ")" + << ", need=" << got.Need << "(" << need << ")" + << Endl; + + UNIT_ASSERT(false); + } + + Grow = Grow || got.Grow; + + return *this; + } + + TWrap& Fill(ui32 least, ui32 most, std::initializer_list<ui16> tags) + { + if (std::exchange(Grow, false)) + Cache->Forward(this, AheadHi); + TVector<NPageCollection::TLoadedPage> load; - - for (auto page: std::exchange(Pages, TDeque<ui32>{ })) { - const auto &rel = Large->Relation(page); - - if (rel.Size >= Edge) { - Log() - << "Queued page " << page << ", " << rel.Size << "b" - << " above the edge " << Edge << "b" << Endl; - - UNIT_ASSERT(false); - } - - if (std::count(tags.begin(), tags.end(), rel.Tag) == 0) { - Log() - << "Page " << page << " has tag " << rel.Tag - << " out of allowed set" << Endl; - - UNIT_ASSERT(false); - } - + + for (auto page: std::exchange(Pages, TDeque<ui32>{ })) { + const auto &rel = Large->Relation(page); + + if (rel.Size >= Edge) { + Log() + << "Queued page " << page << ", " << rel.Size << "b" + << " above the edge " << Edge << "b" << Endl; + + UNIT_ASSERT(false); + } + + if (std::count(tags.begin(), tags.end(), rel.Tag) == 0) { + Log() + << "Page " << page << " has tag " << rel.Tag + << " out of allowed set" << Endl; + + UNIT_ASSERT(false); + } + load.emplace_back(page, TSharedData::Copy(TString(rel.Size, 'x'))); - } - - if (load.size() < least || load.size() >= most) { - Log() - << "Unexpected queued page count " << load.size() - << ", should be [" << least << ", " << most << ")" - << Endl; - - UNIT_ASSERT(false); - } - - Shuffle(load.begin(), load.end(), Rnd); - - Cache->Apply(load); - - UNIT_ASSERT(Cache->Stat.Saved == Cache->Stat.Fetch); - - return *this; - } - - public: + } + + if (load.size() < least || load.size() >= most) { + Log() + << "Unexpected queued page count " << load.size() + << ", should be [" << least << ", " << most << ")" + << Endl; + + UNIT_ASSERT(false); + } + + Shuffle(load.begin(), load.end(), Rnd); + + Cache->Apply(load); + + UNIT_ASSERT(Cache->Stat.Saved == Cache->Stat.Fetch); + + return *this; + } + + public: const TIntrusiveConstPtr<TFrames> Large; const TIntrusiveConstPtr<TSlices> Run; - const ui32 Edge = Max<ui32>(); - const ui64 AheadLo = 0; - const ui64 AheadHi = Max<ui64>(); - - private: - bool Grow = false; + const ui32 Edge = Max<ui32>(); + const ui64 AheadLo = 0; + const ui64 AheadHi = Max<ui64>(); + + private: + bool Grow = false; TAutoPtr<NFwd::IPageLoadingLogic> Cache; - TDeque<ui32> Pages; - TMersenne<ui64> Rnd; - }; -} - + TDeque<ui32> Pages; + TMersenne<ui64> Rnd; + }; +} + Y_UNIT_TEST_SUITE(NFwd) { - + static TIntrusiveConstPtr<NPage::TFrames> Cook() - { - NPage::TFrameWriter writer(3); - - writer.Put(10, 0, 10); /* 0: */ - writer.Put(10, 2, 20); - writer.Put(13, 1, 10); - writer.Put(15, 0, 50); - writer.Put(15, 1, 55); - writer.Put(15, 2, 61); /* 5: */ - writer.Put(17, 2, 13); - writer.Put(18, 2, 10); - writer.Put(19, 2, 17); - writer.Put(22, 2, 15); - - return new NPage::TFrames(writer.Make()); - } - + { + NPage::TFrameWriter writer(3); + + writer.Put(10, 0, 10); /* 0: */ + writer.Put(10, 2, 20); + writer.Put(13, 1, 10); + writer.Put(15, 0, 50); + writer.Put(15, 1, 55); + writer.Put(15, 2, 61); /* 5: */ + writer.Put(17, 2, 13); + writer.Put(18, 2, 10); + writer.Put(19, 2, 17); + writer.Put(22, 2, 15); + + return new NPage::TFrames(writer.Make()); + } + Y_UNIT_TEST(MemTableTest) - { - { /*_ Trivial test, should not produce empty frames */ - UNIT_ASSERT(!NPage::TFrameWriter().Make()); - } - - const auto frames = Cook(); - - { /*_ Basic tests on aggregate values */ - const auto stat = frames->Stats(); - - UNIT_ASSERT(stat.Items == 10); - UNIT_ASSERT(stat.Rows == 7); - UNIT_ASSERT(stat.Size == 261); - UNIT_ASSERT(stat.Tags.at(0) == 2); - UNIT_ASSERT(stat.Tags.at(1) == 2); - UNIT_ASSERT(stat.Tags.at(2) == 6); - } - - { /*_ Test on frame relation offsets */ - UNIT_ASSERT(frames->Relation(3).Refer == -3); - UNIT_ASSERT(frames->Relation(4).Refer == 1); - UNIT_ASSERT(frames->Relation(5).Refer == 2); - } - - { /*_ Test row assigment in entries */ - UNIT_ASSERT(frames->Relation(3).Row == 15); - UNIT_ASSERT(frames->Relation(4).Row == 15); - UNIT_ASSERT(frames->Relation(5).Row == 15); - } - } - + { + { /*_ Trivial test, should not produce empty frames */ + UNIT_ASSERT(!NPage::TFrameWriter().Make()); + } + + const auto frames = Cook(); + + { /*_ Basic tests on aggregate values */ + const auto stat = frames->Stats(); + + UNIT_ASSERT(stat.Items == 10); + UNIT_ASSERT(stat.Rows == 7); + UNIT_ASSERT(stat.Size == 261); + UNIT_ASSERT(stat.Tags.at(0) == 2); + UNIT_ASSERT(stat.Tags.at(1) == 2); + UNIT_ASSERT(stat.Tags.at(2) == 6); + } + + { /*_ Test on frame relation offsets */ + UNIT_ASSERT(frames->Relation(3).Refer == -3); + UNIT_ASSERT(frames->Relation(4).Refer == 1); + UNIT_ASSERT(frames->Relation(5).Refer == 2); + } + + { /*_ Test row assigment in entries */ + UNIT_ASSERT(frames->Relation(3).Row == 15); + UNIT_ASSERT(frames->Relation(4).Row == 15); + UNIT_ASSERT(frames->Relation(5).Row == 15); + } + } + Y_UNIT_TEST(Lower) - { - const auto frames = Cook(); - - UNIT_ASSERT(frames->Lower(8, 0, Max<ui32>()) == 0); - UNIT_ASSERT(frames->Lower(10, 0, Max<ui32>()) == 0); - UNIT_ASSERT(frames->Lower(13, 0, Max<ui32>()) == 2); - UNIT_ASSERT(frames->Lower(15, 0, Max<ui32>()) == 3); - UNIT_ASSERT(frames->Lower(17, 0, Max<ui32>()) == 6); - UNIT_ASSERT(frames->Lower(18, 0, Max<ui32>()) == 7); - UNIT_ASSERT(frames->Lower(19, 0, Max<ui32>()) == 8); - UNIT_ASSERT(frames->Lower(10, 1, Max<ui32>()) == 1); - UNIT_ASSERT(frames->Lower(15, 1, 2) == 2); - UNIT_ASSERT(frames->Lower(15, 0, 0) == 0); - UNIT_ASSERT(frames->Lower(15, Max<ui32>(), Max<ui32>()) == 10); - } - + { + const auto frames = Cook(); + + UNIT_ASSERT(frames->Lower(8, 0, Max<ui32>()) == 0); + UNIT_ASSERT(frames->Lower(10, 0, Max<ui32>()) == 0); + UNIT_ASSERT(frames->Lower(13, 0, Max<ui32>()) == 2); + UNIT_ASSERT(frames->Lower(15, 0, Max<ui32>()) == 3); + UNIT_ASSERT(frames->Lower(17, 0, Max<ui32>()) == 6); + UNIT_ASSERT(frames->Lower(18, 0, Max<ui32>()) == 7); + UNIT_ASSERT(frames->Lower(19, 0, Max<ui32>()) == 8); + UNIT_ASSERT(frames->Lower(10, 1, Max<ui32>()) == 1); + UNIT_ASSERT(frames->Lower(15, 1, 2) == 2); + UNIT_ASSERT(frames->Lower(15, 0, 0) == 0); + UNIT_ASSERT(frames->Lower(15, Max<ui32>(), Max<ui32>()) == 10); + } + Y_UNIT_TEST(Sieve) - { + { NPage::TExtBlobsWriter out; - + std::array<NPageCollection::TGlobId, 6> globs = {{ - { TLogoBlobID(1, 2, 3, 1, 10, 0), 7 }, - { TLogoBlobID(1, 2, 3, 7, 12, 1), 7 }, - { TLogoBlobID(1, 2, 3, 13, 14, 2), 7 }, - { TLogoBlobID(1, 2, 3, 33, 16, 3), 4 }, - { TLogoBlobID(1, 2, 3, 57, 18, 4), 7 }, - { TLogoBlobID(1, 2, 3, 99, 20, 5), 7 }, - }}; - - for (auto &one: globs) out.Put(one); - + { TLogoBlobID(1, 2, 3, 1, 10, 0), 7 }, + { TLogoBlobID(1, 2, 3, 7, 12, 1), 7 }, + { TLogoBlobID(1, 2, 3, 13, 14, 2), 7 }, + { TLogoBlobID(1, 2, 3, 33, 16, 3), 4 }, + { TLogoBlobID(1, 2, 3, 57, 18, 4), 7 }, + { TLogoBlobID(1, 2, 3, 99, 20, 5), 7 }, + }}; + + for (auto &one: globs) out.Put(one); + const auto blobs = new NPage::TExtBlobs(out.Make(), { }); - + NFwd::TSieve sieve{ blobs, nullptr, nullptr, {{ 1, 3}}}; - - TVector<TLogoBlobID> logo; - - sieve.MaterializeTo(logo); - - UNIT_ASSERT(logo.size() == 4); - UNIT_ASSERT(logo[0] == globs[0].Logo); - UNIT_ASSERT(logo[1] == globs[3].Logo); - UNIT_ASSERT(logo[3] == globs[5].Logo); - } - + + TVector<TLogoBlobID> logo; + + sieve.MaterializeTo(logo); + + UNIT_ASSERT(logo.size() == 4); + UNIT_ASSERT(logo[0] == globs[0].Logo); + UNIT_ASSERT(logo[1] == globs[3].Logo); + UNIT_ASSERT(logo[3] == globs[5].Logo); + } + Y_UNIT_TEST(SieveFiltered) { NPage::TExtBlobsWriter out; @@ -244,7 +244,7 @@ Y_UNIT_TEST_SUITE(NFwd) { const auto blobs = new NPage::TExtBlobs(out.Make(), { }); TIntrusiveConstPtr<NPage::TFrames> frames; - + { NPage::TFrameWriter writer(3); writer.Put(10, 1, 10); @@ -287,82 +287,82 @@ Y_UNIT_TEST_SUITE(NFwd) { } Y_UNIT_TEST(Basics) - { - /*_ Check unorderd access over the same frame */ - TWrap(Cook(), 61).Get(1, false, true, true).Get(0, false, true, true); - TWrap(Cook(), 61).Get(4, false, true, true).Get(3, false, true, true); - - /*_ Should not load page with size above the dge */ - TWrap(Cook(), 61).Get(5, false, true, false).Fill(4, 5, { 2 }); - - /*_ Jump between frames with full cache flush */ - TWrap(Cook(), 61, 1, 10) - .To(30).Get(1, false, true, true).Fill(1, 2, { 2 }) - .To(31).Get(6, false, true, true).Fill(1, 2, { 2 }); - - /*_ Long jump, from begin of incomplete frame */ - TWrap(Cook(), 61).Get(3, false, true, true).Get(7, false, true, true); - } - + { + /*_ Check unorderd access over the same frame */ + TWrap(Cook(), 61).Get(1, false, true, true).Get(0, false, true, true); + TWrap(Cook(), 61).Get(4, false, true, true).Get(3, false, true, true); + + /*_ Should not load page with size above the dge */ + TWrap(Cook(), 61).Get(5, false, true, false).Fill(4, 5, { 2 }); + + /*_ Jump between frames with full cache flush */ + TWrap(Cook(), 61, 1, 10) + .To(30).Get(1, false, true, true).Fill(1, 2, { 2 }) + .To(31).Get(6, false, true, true).Fill(1, 2, { 2 }); + + /*_ Long jump, from begin of incomplete frame */ + TWrap(Cook(), 61).Get(3, false, true, true).Get(7, false, true, true); + } + Y_UNIT_TEST(Simple) - { - TWrap(Cook(), 61, 999, 999) - /*_ Get, load and reread the same blob */ - .To(10).Get(1, false, true, true) - .To(11).Fill(5, 6, { 2 }) - .To(12).Get(1, true, false, true) - /*_ Try blob above the materialize edge */ - .To(13).Get(5, false, false, false) - /*_ Try next blob with the same tag */ - .To(14).Get(6, true, false, true); - } - + { + TWrap(Cook(), 61, 999, 999) + /*_ Get, load and reread the same blob */ + .To(10).Get(1, false, true, true) + .To(11).Fill(5, 6, { 2 }) + .To(12).Get(1, true, false, true) + /*_ Try blob above the materialize edge */ + .To(13).Get(5, false, false, false) + /*_ Try next blob with the same tag */ + .To(14).Get(6, true, false, true); + } + Y_UNIT_TEST(Shuffle) - { - TWrap(Cook(), 61, 999, 999) - /*_ Touch two columns on the same frame */ - .To(10).Get(1, false, true, true) - .To(11).Get(0, false, true, true) - .To(12).Fill(7, 8, { 0, 2 }) - .To(13).Get(1, true, false, true) - .To(14).Get(0, true, false, true) - .To(15).Fill(0, 1, { }) - /*_ Then touch another tag on next frame*/ - .To(20).Get(2, false, true, true) - .To(21).Fill(2, 3, { 1 }); - } - + { + TWrap(Cook(), 61, 999, 999) + /*_ Touch two columns on the same frame */ + .To(10).Get(1, false, true, true) + .To(11).Get(0, false, true, true) + .To(12).Fill(7, 8, { 0, 2 }) + .To(13).Get(1, true, false, true) + .To(14).Get(0, true, false, true) + .To(15).Fill(0, 1, { }) + /*_ Then touch another tag on next frame*/ + .To(20).Get(2, false, true, true) + .To(21).Fill(2, 3, { 1 }); + } + Y_UNIT_TEST(Grow) - { - TWrap(Cook(), 55, 15, 30) - .To(10).Get(1, false, true, true).Fill(2, 3, { 2 }) - .To(12).Get(6, true, true, true).Fill(2, 3, { 2 }) - .To(14).Get(8, true, false, true).Fill(0, 1, { 2 }) - .To(16).Get(9, false, true, true).Fill(1, 2, { 2 }) - .To(17).Get(9, true, false, true).Fill(0, 1, { 2 }); - } - + { + TWrap(Cook(), 55, 15, 30) + .To(10).Get(1, false, true, true).Fill(2, 3, { 2 }) + .To(12).Get(6, true, true, true).Fill(2, 3, { 2 }) + .To(14).Get(8, true, false, true).Fill(0, 1, { 2 }) + .To(16).Get(9, false, true, true).Fill(1, 2, { 2 }) + .To(17).Get(9, true, false, true).Fill(0, 1, { 2 }); + } + Y_UNIT_TEST(Trace) - { - TWrap wrap(Cook(), 15, 999, 999); - - wrap - .To(1).Get(1, false, true, false) - .To(2).Get(2, false, true, true) - .To(3).Get(4, false, true, false) - .To(4).Get(5, false, true, false) - .To(5).Get(7, false, true, true) - .To(6).Get(9, false, true, false) - .Fill(2, 3, { 1, 2 }); - - const auto trace = wrap.To(8).Trace(); - - UNIT_ASSERT(trace.size() == 3); - UNIT_ASSERT(trace[0] == TScreen::THole(1, 2)); - UNIT_ASSERT(trace[1] == TScreen::THole(4, 6)); - UNIT_ASSERT(trace[2] == TScreen::THole(9, 10)); - } - + { + TWrap wrap(Cook(), 15, 999, 999); + + wrap + .To(1).Get(1, false, true, false) + .To(2).Get(2, false, true, true) + .To(3).Get(4, false, true, false) + .To(4).Get(5, false, true, false) + .To(5).Get(7, false, true, true) + .To(6).Get(9, false, true, false) + .Fill(2, 3, { 1, 2 }); + + const auto trace = wrap.To(8).Trace(); + + UNIT_ASSERT(trace.size() == 3); + UNIT_ASSERT(trace[0] == TScreen::THole(1, 2)); + UNIT_ASSERT(trace[1] == TScreen::THole(4, 6)); + UNIT_ASSERT(trace[2] == TScreen::THole(9, 10)); + } + Y_UNIT_TEST(Filtered) { TIntrusivePtr<TSlices> run = new TSlices; @@ -380,7 +380,7 @@ Y_UNIT_TEST_SUITE(NFwd) { UNIT_ASSERT(trace.size() == 0); } -} - -} -} +} + +} +} diff --git a/ydb/core/tablet_flat/ut/ut_iterator.cpp b/ydb/core/tablet_flat/ut/ut_iterator.cpp index c14bad7cb4..d77d950871 100644 --- a/ydb/core/tablet_flat/ut/ut_iterator.cpp +++ b/ydb/core/tablet_flat/ut/ut_iterator.cpp @@ -11,24 +11,24 @@ #include <ydb/core/tablet_flat/test/libs/table/test_wreck.h> #include <ydb/core/tablet_flat/test/libs/table/test_mixer.h> #include <ydb/core/tablet_flat/test/libs/table/wrap_iter.h> - -#include <util/generic/xrange.h> - -namespace NKikimr { -namespace NTable { - -namespace { + +#include <util/generic/xrange.h> + +namespace NKikimr { +namespace NTable { + +namespace { static NPage::TConf Conf(ui32 page = NPage::TConf().Groups.at(0).PageSize) noexcept - { - NPage::TConf conf; - + { + NPage::TConf conf; + conf.Group(0).PageSize = page; - conf.LargeEdge = 29; /* neet to cover external blob usage */ - - return conf; - } - - const NTest::TMass Mass0(new NTest::TModelStd(false), 6666); + conf.LargeEdge = 29; /* neet to cover external blob usage */ + + return conf; + } + + const NTest::TMass Mass0(new NTest::TModelStd(false), 6666); static void VerifySingleLevelNonTrivial(const TAutoPtr<TSubset>& subset) { @@ -49,68 +49,68 @@ namespace { UNIT_ASSERT_C(levels.size() == 1, "Levels size " << levels.size()); } -} - -using TCheckIt = NTest::TChecker<NTest::TWrapIter, TSubset>; +} + +using TCheckIt = NTest::TChecker<NTest::TWrapIter, TSubset>; using TCheckReverseIt = NTest::TChecker<NTest::TWrapReverseIter, TSubset>; - + Y_UNIT_TEST_SUITE(TIterator) { - using namespace NTest; - + using namespace NTest; + Y_UNIT_TEST(Basics) - { - TCheckIt wrap(*TMake(Mass0).Mixed(0, 1, TMixerOne{ }), { }); - - { /*_ ESeek::Exact have to give at most one row */ - wrap.To(1).Seek(Mass0.Saved[7], ESeek::Exact).Is(Mass0.Saved[7]); - wrap.To(2).Next().Is(EReady::Gone); - } - - { /*_ Seek w/o pages have to yield EReady::Page forever */ + { + TCheckIt wrap(*TMake(Mass0).Mixed(0, 1, TMixerOne{ }), { }); + + { /*_ ESeek::Exact have to give at most one row */ + wrap.To(1).Seek(Mass0.Saved[7], ESeek::Exact).Is(Mass0.Saved[7]); + wrap.To(2).Next().Is(EReady::Gone); + } + + { /*_ Seek w/o pages have to yield EReady::Page forever */ auto *env = new TNoEnv{ false, ELargeObjNeed::Has }; - - wrap.Displace<IPages>(env); - - wrap.To(6).Seek(Mass0.Saved[7], ESeek::Lower).Is(EReady::Page); - env->Pages = true; /* load all pages to cache */ - wrap.To(7).Next().Is(EReady::Page).Next().Is(EReady::Page); - } - } - + + wrap.Displace<IPages>(env); + + wrap.To(6).Seek(Mass0.Saved[7], ESeek::Lower).Is(EReady::Page); + env->Pages = true; /* load all pages to cache */ + wrap.To(7).Next().Is(EReady::Page).Next().Is(EReady::Page); + } + } + Y_UNIT_TEST(External) - { - TCheckIt wrap(*TMake(Mass0, Conf()).Mixed(0, 1, TMixerOne{ }), { }); - - UNIT_ASSERT((*wrap).Flatten.size() == 1); - - auto *part = (*wrap).Flatten.at(0).Part.Get(); - - UNIT_ASSERT(part && part->Large && part->Blobs); - - /* Work on the second row with external blobs, should check how - iterator behaves on absense of blobs in cache on Next(). - */ - - const auto frame = ui32(0) - part->Large->Relation(0).Refer; - const auto on = part->Large->Relation(frame).Row; - + { + TCheckIt wrap(*TMake(Mass0, Conf()).Mixed(0, 1, TMixerOne{ }), { }); + + UNIT_ASSERT((*wrap).Flatten.size() == 1); + + auto *part = (*wrap).Flatten.at(0).Part.Get(); + + UNIT_ASSERT(part && part->Large && part->Blobs); + + /* Work on the second row with external blobs, should check how + iterator behaves on absense of blobs in cache on Next(). + */ + + const auto frame = ui32(0) - part->Large->Relation(0).Refer; + const auto on = part->Large->Relation(frame).Row; + auto *env = new TNoEnv{ true, ELargeObjNeed::Has }; - - wrap.Displace<IPages>(env); - wrap.To(1).Seek(Mass0.Saved[on-1], ESeek::Lower).Is(Mass0.Saved[on-1]); + + wrap.Displace<IPages>(env); + wrap.To(1).Seek(Mass0.Saved[on-1], ESeek::Lower).Is(Mass0.Saved[on-1]); env->Lobs = ELargeObjNeed::Yes; /* no any blobs in cache */ - wrap.To(2).Next().Is(EReady::Page).To(3).Next().Is(EReady::Page); + wrap.To(2).Next().Is(EReady::Page).To(3).Next().Is(EReady::Page); env->Lobs = ELargeObjNeed::Has; /* load all blobs to cache */ - wrap.To(8).Next().Is(Mass0.Saved[on]); - } - + wrap.To(8).Next().Is(Mass0.Saved[on]); + } + Y_UNIT_TEST(Single) - { - auto subset = TMake(Mass0, Conf()).Mixed(0, 1, TMixerOne{ }); - - TWreck<TCheckIt, TSubset>(Mass0, 666).Do(EWreck::Cached, *subset); - } - + { + auto subset = TMake(Mass0, Conf()).Mixed(0, 1, TMixerOne{ }); + + TWreck<TCheckIt, TSubset>(Mass0, 666).Do(EWreck::Cached, *subset); + } + Y_UNIT_TEST(SingleReverse) { auto subset = TMake(Mass0, Conf()).Mixed(0, 1, TMixerOne{ }); @@ -119,14 +119,14 @@ Y_UNIT_TEST_SUITE(TIterator) { } Y_UNIT_TEST(Mixed) - { - auto subset = TMake(Mass0, Conf(384)).Mixed(2, 2, TMixerRnd(4)); - - TWreck<TCheckIt, TSubset>(Mass0, 666).Do(EWreck::Cached, *subset); - TWreck<TCheckIt, TSubset>(Mass0, 666).Do(EWreck::Evicted, *subset); - TWreck<TCheckIt, TSubset>(Mass0, 666).Do(EWreck::Forward, *subset); - } - + { + auto subset = TMake(Mass0, Conf(384)).Mixed(2, 2, TMixerRnd(4)); + + TWreck<TCheckIt, TSubset>(Mass0, 666).Do(EWreck::Cached, *subset); + TWreck<TCheckIt, TSubset>(Mass0, 666).Do(EWreck::Evicted, *subset); + TWreck<TCheckIt, TSubset>(Mass0, 666).Do(EWreck::Forward, *subset); + } + Y_UNIT_TEST(MixedReverse) { auto subset = TMake(Mass0, Conf(384)).Mixed(2, 2, TMixerRnd(4)); @@ -135,32 +135,32 @@ Y_UNIT_TEST_SUITE(TIterator) { TWreck<TCheckReverseIt, TSubset, EDirection::Reverse>(Mass0, 666).Do(EWreck::Evicted, *subset); } - Y_UNIT_TEST(Serial) - { - TMixerSeq mixer(4, Mass0.Saved.Size()); - - auto subset = TMake(Mass0, Conf(384)).Mixed(2, 2, mixer); - + Y_UNIT_TEST(Serial) + { + TMixerSeq mixer(4, Mass0.Saved.Size()); + + auto subset = TMake(Mass0, Conf(384)).Mixed(2, 2, mixer); + VerifySingleLevelNonTrivial(subset); - + TWreck<TCheckIt, TSubset>(Mass0, 666).Do(EWreck::Cached, *subset); TWreck<TCheckIt, TSubset>(Mass0, 666).Do(EWreck::Evicted, *subset); TWreck<TCheckIt, TSubset>(Mass0, 666).Do(EWreck::Forward, *subset); } - + Y_UNIT_TEST(SerialReverse) { TMixerSeq mixer(4, Mass0.Saved.Size()); - + auto subset = TMake(Mass0, Conf(384)).Mixed(2, 2, mixer); - + VerifySingleLevelNonTrivial(subset); - + TWreck<TCheckReverseIt, TSubset, EDirection::Reverse>(Mass0, 666).Do(EWreck::Cached, *subset); TWreck<TCheckReverseIt, TSubset, EDirection::Reverse>(Mass0, 666).Do(EWreck::Evicted, *subset); - } - -} - -} -} + } + +} + +} +} diff --git a/ydb/core/tablet_flat/ut/ut_memtable.cpp b/ydb/core/tablet_flat/ut/ut_memtable.cpp index d5b6c32864..08baf7aeb9 100644 --- a/ydb/core/tablet_flat/ut/ut_memtable.cpp +++ b/ydb/core/tablet_flat/ut/ut_memtable.cpp @@ -5,74 +5,74 @@ #include <ydb/core/tablet_flat/test/libs/table/wrap_warm.h> #include <ydb/core/tablet_flat/test/libs/table/test_cooker.h> #include <ydb/core/tablet_flat/test/libs/table/test_wreck.h> - + #include <library/cpp/testing/unittest/registar.h> - -namespace NKikimr { -namespace NTable { - -namespace { - const NTest::TMass Mass(new NTest::TModelStd(false), 999); -} - + +namespace NKikimr { +namespace NTable { + +namespace { + const NTest::TMass Mass(new NTest::TModelStd(false), 999); +} + using TCheckIt = NTest::TChecker<NTest::TWrapMemtable, TIntrusiveConstPtr<TMemTable>>; using TCheckReverseIt = NTest::TChecker<NTest::TWrapReverseMemtable, TIntrusiveConstPtr<TMemTable>>; - + Y_UNIT_TEST_SUITE(Memtable) -{ - using namespace NTest; - +{ + using namespace NTest; + TIntrusiveConstPtr<TRowScheme> BasicRowLayout() noexcept - { - return - TLayoutCook() - .Col(0, 0, NScheme::NTypeIds::Uint32) - .Col(0, 1, NScheme::NTypeIds::String) - .Col(0, 2, NScheme::NTypeIds::Double, Cimple(3.14)) - .Col(0, 3, NScheme::NTypeIds::Bool) - .Key({0, 1}) - .RowScheme(); - } - + { + return + TLayoutCook() + .Col(0, 0, NScheme::NTypeIds::Uint32) + .Col(0, 1, NScheme::NTypeIds::String) + .Col(0, 2, NScheme::NTypeIds::Double, Cimple(3.14)) + .Col(0, 3, NScheme::NTypeIds::Bool) + .Key({0, 1}) + .RowScheme(); + } + Y_UNIT_TEST(Basics) - { - const auto lay = BasicRowLayout(); - - /* Test copied from TPart::Basics with except of iteration */ - - const auto foo = *TNatural(*lay).Col(555_u32, "foo", 3.14, nullptr); - const auto bar = *TNatural(*lay).Col(777_u32, "bar", 2.72, true); - - TCheckIt wrap(TCooker(lay).Add(foo).Add(bar).Unwrap(), { }); - - wrap.To(10).Has(foo).Has(bar); - wrap.To(11).NoVal(*TNatural(*lay).Col(555_u32, "foo", 10.)); - wrap.To(12).NoKey(*TNatural(*lay).Col(888_u32, "foo", 3.14)); - - /*_ Basic lower and upper bounds lookup semantic */ - - wrap.To(20).Seek(foo, ESeek::Lower).Is(foo); - wrap.To(21).Seek(foo, ESeek::Upper).Is(bar); - wrap.To(22).Seek(bar, ESeek::Upper).Is(EReady::Gone); - - /*_ The empty key is interpreted depending on ESeek mode... */ - - wrap.To(30).Seek({ }, ESeek::Lower).Is(foo); - wrap.To(31).Seek({ }, ESeek::Exact).Is(EReady::Gone); - wrap.To(32).Seek({ }, ESeek::Upper).Is(EReady::Gone); - - /* ... but incomplete keys are padded with +inf instead of nulls - on lookup. Check that it really happens for Seek()'s */ - - wrap.To(33).Seek(*TNatural(*lay).Col(555_u32), ESeek::Lower).Is(bar); - wrap.To(34).Seek(*TNatural(*lay).Col(555_u32), ESeek::Upper).Is(bar); - - /*_ Basic iteration over two rows in tables */ - - wrap.To(40).Seek({ }, ESeek::Lower); - wrap.To(41).Is(foo).Next().Is(bar).Next().Is(EReady::Gone); - } - + { + const auto lay = BasicRowLayout(); + + /* Test copied from TPart::Basics with except of iteration */ + + const auto foo = *TNatural(*lay).Col(555_u32, "foo", 3.14, nullptr); + const auto bar = *TNatural(*lay).Col(777_u32, "bar", 2.72, true); + + TCheckIt wrap(TCooker(lay).Add(foo).Add(bar).Unwrap(), { }); + + wrap.To(10).Has(foo).Has(bar); + wrap.To(11).NoVal(*TNatural(*lay).Col(555_u32, "foo", 10.)); + wrap.To(12).NoKey(*TNatural(*lay).Col(888_u32, "foo", 3.14)); + + /*_ Basic lower and upper bounds lookup semantic */ + + wrap.To(20).Seek(foo, ESeek::Lower).Is(foo); + wrap.To(21).Seek(foo, ESeek::Upper).Is(bar); + wrap.To(22).Seek(bar, ESeek::Upper).Is(EReady::Gone); + + /*_ The empty key is interpreted depending on ESeek mode... */ + + wrap.To(30).Seek({ }, ESeek::Lower).Is(foo); + wrap.To(31).Seek({ }, ESeek::Exact).Is(EReady::Gone); + wrap.To(32).Seek({ }, ESeek::Upper).Is(EReady::Gone); + + /* ... but incomplete keys are padded with +inf instead of nulls + on lookup. Check that it really happens for Seek()'s */ + + wrap.To(33).Seek(*TNatural(*lay).Col(555_u32), ESeek::Lower).Is(bar); + wrap.To(34).Seek(*TNatural(*lay).Col(555_u32), ESeek::Upper).Is(bar); + + /*_ Basic iteration over two rows in tables */ + + wrap.To(40).Seek({ }, ESeek::Lower); + wrap.To(41).Is(foo).Next().Is(bar).Next().Is(EReady::Gone); + } + Y_UNIT_TEST(BasicsReverse) { const auto lay = BasicRowLayout(); @@ -114,60 +114,60 @@ Y_UNIT_TEST_SUITE(Memtable) } Y_UNIT_TEST(Markers) - { - const auto lay = BasicRowLayout(); - + { + const auto lay = BasicRowLayout(); + auto reset = *TNatural(*lay).Col(555_u32, "foo", ECellOp::Reset); auto null = *TNatural(*lay).Col(556_u32, "foo", ECellOp::Null); - - TCooker cooker(lay); - + + TCooker cooker(lay); + TCheckIt(*cooker.Add(reset, ERowOp::Upsert), { }).To(10).Has(reset); TCheckIt(*cooker.Add(null, ERowOp::Upsert), { }).To(11).Has(null); - } - + } + Y_UNIT_TEST(Overlap) - { - const auto lay = BasicRowLayout(); - - auto r0W = *TNatural(*lay).Col(555_u32, "foo", 3.14, nullptr); - auto r1W = *TNatural(*lay).Col(555_u32, "foo", nullptr, false); - auto r2W = *TNatural(*lay).Col(555_u32, "foo", 2.72); - auto r2R = *TNatural(*lay).Col(555_u32, "foo", 2.72, false); - auto r3W = *TNatural(*lay).Col(555_u32, "foo", nullptr, true); + { + const auto lay = BasicRowLayout(); + + auto r0W = *TNatural(*lay).Col(555_u32, "foo", 3.14, nullptr); + auto r1W = *TNatural(*lay).Col(555_u32, "foo", nullptr, false); + auto r2W = *TNatural(*lay).Col(555_u32, "foo", 2.72); + auto r2R = *TNatural(*lay).Col(555_u32, "foo", 2.72, false); + auto r3W = *TNatural(*lay).Col(555_u32, "foo", nullptr, true); auto r4W = *TNatural(*lay).Col(555_u32, "foo", ECellOp::Reset); - auto r4R = *TNatural(*lay).Col(555_u32, "foo", 3.14, true); - - TCooker cooker(lay); - + auto r4R = *TNatural(*lay).Col(555_u32, "foo", 3.14, true); + + TCooker cooker(lay); + TCheckIt(*cooker.Add(r0W, ERowOp::Upsert), { }).To(10).Has(r0W); TCheckIt(*cooker.Add(r1W, ERowOp::Upsert), { }).To(11).Has(r1W); TCheckIt(*cooker.Add(r2W, ERowOp::Upsert), { }).To(12).Has(r2R); TCheckIt(*cooker.Add(r3W, ERowOp::Upsert), { }).To(13).Has(r3W); TCheckIt(*cooker.Add(r4W, ERowOp::Upsert), { }).To(14).Has(r4R); TCheckIt(*cooker.Add(r0W, ERowOp::Erase), { }).To(19).NoKey(r0W, false); - } - + } + Y_UNIT_TEST(Wreck) - { + { auto egg = *TCooker(Mass.Model->Scheme).Add(Mass.Saved, ERowOp::Upsert); - + TWreck<TCheckIt, TIntrusiveConstPtr<TMemTable>>(Mass, 666).Do(EWreck::Cached, egg); - } - + } + Y_UNIT_TEST(Erased) - { - auto egg = - *TCooker(Mass.Model->Scheme) + { + auto egg = + *TCooker(Mass.Model->Scheme) .Add(Mass.Saved, ERowOp::Upsert) .Add(Mass.Holes, ERowOp::Upsert) .Add(Mass.Holes, ERowOp::Erase); - + TWreck<TCheckIt, TIntrusiveConstPtr<TMemTable>>(Mass, 666).Do(EWreck::Cached, egg); - } - -} - - -} -} + } + +} + + +} +} diff --git a/ydb/core/tablet_flat/ut/ut_other.cpp b/ydb/core/tablet_flat/ut/ut_other.cpp index ea1c287283..bde99450d5 100644 --- a/ydb/core/tablet_flat/ut/ut_other.cpp +++ b/ydb/core/tablet_flat/ut/ut_other.cpp @@ -3,58 +3,58 @@ #include <ydb/core/tablet_flat/flat_writer_conf.h> #include <ydb/core/tablet_flat/flat_writer_bundle.h> #include <ydb/core/tablet_flat/flat_sausage_chop.h> - + #include <library/cpp/testing/unittest/registar.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { - + +namespace NKikimr { +namespace NTabletFlatExecutor { + Y_UNIT_TEST_SUITE(NOther) { Y_UNIT_TEST(Blocks) - { - NWriter::TConf conf; - + { + NWriter::TConf conf; + conf.Groups[0].Block = 128; /* Page collection blob size */ - conf.Slots = { { 1, 11 }, { 3, 13 }, { 5, 17 } }; + conf.Slots = { { 1, 11 }, { 3, 13 }, { 5, 17 } }; conf.Groups[0].Channel = 3; /* Put data to channel 3 grp 13 */ conf.BlobsChannel = 5; /* Put blobs to channel 5 grp 17 */ - - const TLogoBlobID mask(1, 3, 7, 0, 0, 0); - + + const TLogoBlobID mask(1, 3, 7, 0, 0, 0); + TAutoPtr<NWriter::TBundle> bundle = new NWriter::TBundle(mask, conf); - - if (auto *out = static_cast<NTable::IPageWriter*>(bundle.Get())) { - for (auto seq: xrange(7)) + + if (auto *out = static_cast<NTable::IPageWriter*>(bundle.Get())) { + for (auto seq: xrange(7)) out->Write(TSharedData::Copy(TString(196, 'a' + seq)), NTable::EPage::Undef, 0); - - for (auto seq: xrange(3)) + + for (auto seq: xrange(3)) out->WriteLarge(TString(200, 'b' + seq), seq); /* external blobs */ - + out->Finish({ }); - } - - auto globs = bundle->GetBlobsToSave(); - + } + + auto globs = bundle->GetBlobsToSave(); + auto results = bundle->Results(); UNIT_ASSERT(results); UNIT_ASSERT(results[0].PageCollections.at(0)->Total() == 7); UNIT_ASSERT(globs.size() == 18 /* 11 page collections + 4 meta + 3 external */); - - /*_ Ensure that writer places blobs to the correct channel and grp */ - - for (auto &one: globs) { + + /*_ Ensure that writer places blobs to the correct channel and grp */ + + for (auto &one: globs) { UNIT_ASSERT(NPageCollection::TGroupBlobsByCookie::IsInPlane(one.GId.Logo, mask)); - UNIT_ASSERT( - (one.GId.Group == 13 && one.GId.Logo.Channel() == 3) - ||(one.GId.Group == 17 && one.GId.Logo.Channel() == 5)); - } + UNIT_ASSERT( + (one.GId.Group == 13 && one.GId.Logo.Channel() == 3) + ||(one.GId.Group == 17 && one.GId.Logo.Channel() == 5)); + } /*_ Ensure external blob references are accounted correctly */ UNIT_ASSERT(results[0].Growth.size() == 1); UNIT_ASSERT(results[0].Growth[0] == NTable::TScreen::THole(0, 3)); - } -} - -} -} + } +} + +} +} diff --git a/ydb/core/tablet_flat/ut/ut_pages.cpp b/ydb/core/tablet_flat/ut/ut_pages.cpp index b9e417861a..f1971e64bd 100644 --- a/ydb/core/tablet_flat/ut/ut_pages.cpp +++ b/ydb/core/tablet_flat/ut/ut_pages.cpp @@ -4,82 +4,82 @@ #include <ydb/core/tablet_flat/test/libs/table/wrap_part.h> #include <ydb/core/tablet_flat/test/libs/table/test_writer.h> #include <ydb/core/tablet_flat/test/libs/table/test_wreck.h> - + #include <library/cpp/testing/unittest/registar.h> #include <library/cpp/resource/resource.h> -#include <util/generic/xrange.h> -#include <util/stream/file.h> -#include <util/stream/str.h> - -namespace NKikimr { -namespace NTable { - -namespace { - /* Sample rows set for old pages compatability tests, should be +#include <util/generic/xrange.h> +#include <util/stream/file.h> +#include <util/stream/str.h> + +namespace NKikimr { +namespace NTable { + +namespace { + /* Sample rows set for old pages compatability tests, should be updated with assosiated raw page collections (see data/ directory). - */ - - const NTest::TMass MassZ(new NTest::TModelStd(false), 128); -} - + */ + + const NTest::TMass MassZ(new NTest::TModelStd(false), 128); +} + Y_UNIT_TEST_SUITE(NPage) { - + Y_UNIT_TEST(Encoded) - { - using namespace NTable::NTest; - - TLayoutCook lay; - - lay - .Col(0, 0, NScheme::NTypeIds::Uint32) - .Col(0, 1, NScheme::NTypeIds::String) - .Key({ 0 }); - - const auto foo = *TNatural(*lay).Col(555_u32, "foo"); - const auto bar = *TNatural(*lay).Col(777_u32, "bar"); - - NPage::TConf conf{ true, 2 * 1024 }; - + { + using namespace NTable::NTest; + + TLayoutCook lay; + + lay + .Col(0, 0, NScheme::NTypeIds::Uint32) + .Col(0, 1, NScheme::NTypeIds::String) + .Key({ 0 }); + + const auto foo = *TNatural(*lay).Col(555_u32, "foo"); + const auto bar = *TNatural(*lay).Col(777_u32, "bar"); + + NPage::TConf conf{ true, 2 * 1024 }; + conf.Group(0).Codec = NPage::ECodec::LZ4; conf.Group(0).ForceCompression = true; /* required for this UT only */ - - TCheckIt wrap(TPartCook(lay, conf).Add(foo).Finish(), { }); - - wrap.To(1).Has(foo).To(2).NoKey(bar); - + + TCheckIt wrap(TPartCook(lay, conf).Add(foo).Finish(), { }); + + wrap.To(1).Has(foo).To(2).NoKey(bar); + auto &part = dynamic_cast<const NTest::TPartStore&>(*(*wrap).Eggs.Lone()); - + for (auto page: xrange(part.Store->PageCollectionPagesCount(0))) { auto *raw = part.Store->GetPage(0, page); - auto got = NPage::THello().Read(*raw, NPage::EPage::Undef); - + auto got = NPage::THello().Read(*raw, NPage::EPage::Undef); + if (got.Type != NPage::EPage::DataPage) { - /* Have to check for compression only rows page */ - } else if (got.Codec == NPage::ECodec::Plain) { - UNIT_FAIL("Test has failed to cook compressed pages"); - } - } - } - + /* Have to check for compression only rows page */ + } else if (got.Codec == NPage::ECodec::Plain) { + UNIT_FAIL("Test has failed to cook compressed pages"); + } + } + } + Y_UNIT_TEST(ABI_002) - { - const auto raw = NResource::Find("abi/002_full_part.pages"); - - TStringInput input(raw); - - { - using namespace NTest; - - const TLogoBlobID label(1,2,3); - - auto part = NTest::TLoader(TStore::Restore(input), { }).Load(label); - - TPartEggs eggs{ nullptr, MassZ.Model->Scheme, { std::move(part) } }; - - TWreck<TCheckIt, TPartEggs>(MassZ, 666).Do(EWreck::Cached, eggs); - } - } - + { + const auto raw = NResource::Find("abi/002_full_part.pages"); + + TStringInput input(raw); + + { + using namespace NTest; + + const TLogoBlobID label(1,2,3); + + auto part = NTest::TLoader(TStore::Restore(input), { }).Load(label); + + TPartEggs eggs{ nullptr, MassZ.Model->Scheme, { std::move(part) } }; + + TWreck<TCheckIt, TPartEggs>(MassZ, 666).Do(EWreck::Cached, eggs); + } + } + Y_UNIT_TEST(GroupIdEncoding) { NPage::TGroupId main; UNIT_ASSERT_VALUES_EQUAL(main.Raw(), 0u); @@ -97,7 +97,7 @@ Y_UNIT_TEST_SUITE(NPage) { UNIT_ASSERT(mainHist < altHist); } -} - -} -} +} + +} +} diff --git a/ydb/core/tablet_flat/ut/ut_part.cpp b/ydb/core/tablet_flat/ut/ut_part.cpp index 0c336e95ac..83603472a3 100644 --- a/ydb/core/tablet_flat/ut/ut_part.cpp +++ b/ydb/core/tablet_flat/ut/ut_part.cpp @@ -6,28 +6,28 @@ #include <ydb/core/tablet_flat/test/libs/table/test_writer.h> #include <ydb/core/tablet_flat/test/libs/table/test_wreck.h> #include <ydb/core/tablet_flat/test/libs/table/test_comp.h> - + #include <library/cpp/testing/unittest/registar.h> - -namespace NKikimr { -namespace NTable { - -namespace { + +namespace NKikimr { +namespace NTable { + +namespace { NPage::TConf PageConf(size_t groups = 1) noexcept - { - NPage::TConf conf{ true, 2 * 1024 }; - + { + NPage::TConf conf{ true, 2 * 1024 }; + conf.Groups.resize(groups); for (size_t group : xrange(groups)) { conf.Group(group).IndexMin = 1024; /* Should cover index buffer grow code */ } conf.SmallEdge = 19; /* Packed to page collection large cell values */ - conf.LargeEdge = 29; /* Large values placed to single blobs */ + conf.LargeEdge = 29; /* Large values placed to single blobs */ conf.SliceSize = conf.Group(0).PageSize * 4; - - return conf; - } - + + return conf; + } + const NTest::TMass& Mass0() { static const NTest::TMass mass0(new NTest::TModelStd(false), 24000); @@ -52,93 +52,93 @@ namespace { static const auto eggs1 = NTest::TPartCook::Make(mass1, PageConf(mass1.Model->Scheme->Families.size())); return eggs1; } -} - +} + Y_UNIT_TEST_SUITE(TPart) { - using namespace NTest; - + using namespace NTest; + Y_UNIT_TEST(State) - { - TRowState row(2); - + { + TRowState row(2); + const NPageCollection::TGlobId glob{ TLogoBlobID(10, 20, 30, 1, 0, 0), 7 }; - + row.Set(1, { ECellOp::Set, ELargeObj::GlobId }, TCell::Make(glob)); - UNIT_ASSERT(row.Need() == 0 && row.Left() == 1); + UNIT_ASSERT(row.Need() == 0 && row.Left() == 1); row.Set(0, { ECellOp::Null, ELargeObj::GlobId }, TCell::Make(glob)); - UNIT_ASSERT(row.Need() == 1 && row.Left() == 0); - } - + UNIT_ASSERT(row.Need() == 1 && row.Left() == 0); + } + Y_UNIT_TEST(Trivials) - { - TLayoutCook lay; - - lay + { + TLayoutCook lay; + + lay .Col(0, 0, NScheme::NTypeIds::String) - .Col(0, 1, NScheme::NTypeIds::Uint32) - .Col(0, 2, NScheme::NTypeIds::Uint64) - .Key({0, 1}); - - { /*_ Check that trivial part hasn't been produced by writer */ - auto eggs = TPartCook(lay, { true, 4096 }).Finish(); - - if (eggs.Written->Rows > 0) { - ythrow yexception() << "Unexpected trivial TWritten result"; - } else if (eggs.Parts) { + .Col(0, 1, NScheme::NTypeIds::Uint32) + .Col(0, 2, NScheme::NTypeIds::Uint64) + .Key({0, 1}); + + { /*_ Check that trivial part hasn't been produced by writer */ + auto eggs = TPartCook(lay, { true, 4096 }).Finish(); + + if (eggs.Written->Rows > 0) { + ythrow yexception() << "Unexpected trivial TWritten result"; + } else if (eggs.Parts) { ythrow yexception() << "Writer produced parts with trival data"; - } - } - } - + } + } + } + Y_UNIT_TEST(Basics) - { - TLayoutCook lay; - - lay - .Col(0, 0, NScheme::NTypeIds::Uint32) - .Col(0, 1, NScheme::NTypeIds::String) - .Col(0, 2, NScheme::NTypeIds::Double) - .Col(0, 3, NScheme::NTypeIds::Bool) - .Key({0, 1}); - - const auto foo = *TNatural(*lay).Col(555_u32, "foo", 3.14, nullptr); - const auto bar = *TNatural(*lay).Col(777_u32, "bar", 2.72, true); - - TCheckIt wrap(TPartCook(lay, { }).Add(foo).Add(bar).Finish(), { }); - - wrap.To(10).Has(foo).Has(bar); - wrap.To(11).NoVal(*TNatural(*lay).Col(555_u32, "foo", 10.)); - wrap.To(12).NoKey(*TNatural(*lay).Col(888_u32, "foo", 3.14)); - - /*_ Basic lower and upper bounds lookup semantic */ - - wrap.To(20).Seek(foo, ESeek::Lower).Is(foo); - wrap.To(21).Seek(foo, ESeek::Upper).Is(bar); - wrap.To(22).Seek(bar, ESeek::Upper).Is(EReady::Gone); - - /*_ The empty key is interpreted depending on ESeek mode... */ - - wrap.To(30).Seek({ }, ESeek::Lower).Is(foo); - wrap.To(31).Seek({ }, ESeek::Exact).Is(EReady::Gone); - wrap.To(32).Seek({ }, ESeek::Upper).Is(EReady::Gone); - - /* ... but incomplete keys are padded with +inf instead of nulls - on lookup. Check that it really happens for Seek()'s */ - - wrap.To(33).Seek(*TNatural(*lay).Col(555_u32), ESeek::Lower).Is(bar); - wrap.To(34).Seek(*TNatural(*lay).Col(555_u32), ESeek::Upper).Is(bar); + { + TLayoutCook lay; + + lay + .Col(0, 0, NScheme::NTypeIds::Uint32) + .Col(0, 1, NScheme::NTypeIds::String) + .Col(0, 2, NScheme::NTypeIds::Double) + .Col(0, 3, NScheme::NTypeIds::Bool) + .Key({0, 1}); + + const auto foo = *TNatural(*lay).Col(555_u32, "foo", 3.14, nullptr); + const auto bar = *TNatural(*lay).Col(777_u32, "bar", 2.72, true); + + TCheckIt wrap(TPartCook(lay, { }).Add(foo).Add(bar).Finish(), { }); + + wrap.To(10).Has(foo).Has(bar); + wrap.To(11).NoVal(*TNatural(*lay).Col(555_u32, "foo", 10.)); + wrap.To(12).NoKey(*TNatural(*lay).Col(888_u32, "foo", 3.14)); + + /*_ Basic lower and upper bounds lookup semantic */ + + wrap.To(20).Seek(foo, ESeek::Lower).Is(foo); + wrap.To(21).Seek(foo, ESeek::Upper).Is(bar); + wrap.To(22).Seek(bar, ESeek::Upper).Is(EReady::Gone); + + /*_ The empty key is interpreted depending on ESeek mode... */ + + wrap.To(30).Seek({ }, ESeek::Lower).Is(foo); + wrap.To(31).Seek({ }, ESeek::Exact).Is(EReady::Gone); + wrap.To(32).Seek({ }, ESeek::Upper).Is(EReady::Gone); + + /* ... but incomplete keys are padded with +inf instead of nulls + on lookup. Check that it really happens for Seek()'s */ + + wrap.To(33).Seek(*TNatural(*lay).Col(555_u32), ESeek::Lower).Is(bar); + wrap.To(34).Seek(*TNatural(*lay).Col(555_u32), ESeek::Upper).Is(bar); /* Verify part has correct first and last key in the index */ - const auto part = (*wrap).Eggs.Lone(); + const auto part = (*wrap).Eggs.Lone(); UNIT_ASSERT_VALUES_EQUAL(part->Index.Rows(), 2u); const NPage::TCompare<NPage::TIndex::TRecord> cmp(part->Scheme->Groups[0].ColsKeyIdx, *(*lay).Keys); UNIT_ASSERT_VALUES_EQUAL(cmp.Compare(*part->Index.GetFirstKeyRecord(), TRowTool(*lay).KeyCells(foo)), 0); UNIT_ASSERT_VALUES_EQUAL(cmp.Compare(*part->Index.GetLastKeyRecord(), TRowTool(*lay).KeyCells(bar)), 0); - - DumpPart(*(*wrap).Eggs.Lone(), 10); - } - + + DumpPart(*(*wrap).Eggs.Lone(), 10); + } + Y_UNIT_TEST(BasicColumnGroups) { using namespace NTable::NTest; @@ -166,244 +166,244 @@ Y_UNIT_TEST_SUITE(TPart) { } Y_UNIT_TEST(Nulls) - { - TLayoutCook lay, fake; - - lay - .Col(0, 0, NScheme::NTypeIds::Uint64) - .Col(0, 8, NScheme::NTypeIds::Uint32) - .Key({ 0 }); - - fake - .Col(0, 0, NScheme::NTypeIds::Uint64) - .Col(0, 1, NScheme::NTypeIds::Uint32, Cimple(3_u32)) - .Col(0, 2, NScheme::NTypeIds::Uint32, Cimple(7_u32)) - .Col(0, 8, NScheme::NTypeIds::Uint32, Cimple(99_u32)) - .Key({ 0, 1, 2 }); - - auto eggs = - TPartCook(lay, { true, 4096 }) - .AddN(10_u64, 77_u32) - .AddN(12_u64, 44_u32) - .AddN(17_u64, nullptr) /* explicit null */ - .AddN(19_u64) /* default value */ - .Finish(); - + { + TLayoutCook lay, fake; + + lay + .Col(0, 0, NScheme::NTypeIds::Uint64) + .Col(0, 8, NScheme::NTypeIds::Uint32) + .Key({ 0 }); + + fake + .Col(0, 0, NScheme::NTypeIds::Uint64) + .Col(0, 1, NScheme::NTypeIds::Uint32, Cimple(3_u32)) + .Col(0, 2, NScheme::NTypeIds::Uint32, Cimple(7_u32)) + .Col(0, 8, NScheme::NTypeIds::Uint32, Cimple(99_u32)) + .Key({ 0, 1, 2 }); + + auto eggs = + TPartCook(lay, { true, 4096 }) + .AddN(10_u64, 77_u32) + .AddN(12_u64, 44_u32) + .AddN(17_u64, nullptr) /* explicit null */ + .AddN(19_u64) /* default value */ + .Finish(); + eggs.Scheme = fake.RowScheme(); - + TCheckIt wrap(std::move(eggs), { }); - auto trA = *TNatural(*fake).Col(10_u64, 3_u32, 7_u32, 77_u32); - auto trB = *TNatural(*fake).Col(12_u64, 3_u32, 7_u32, 44_u32); - auto trC = *TNatural(*fake).Col(17_u64, 3_u32, 7_u32, nullptr); - auto trD = *TNatural(*fake).Col(19_u64, 3_u32, 7_u32, 99_u32); - - auto low = *TNatural(*fake).Col(10_u64, 2_u32, 2_u32); - auto mid = *TNatural(*fake).Col(10_u64, 3_u32, 5_u32); - auto upp = *TNatural(*fake).Col(10_u64, 3_u32, 8_u32); - - wrap.To(10).Has(trA); /* default values in key */ - wrap.To(11).Has(trB); /* default values in key */ - wrap.To(12).Has(trC); /* explicit null in values */ - wrap.To(13).Has(trD); /* default value in values */ - wrap.To(20).Seek(trA, ESeek::Lower).Is(trA); - wrap.To(21).Seek(trA, ESeek::Upper).Is(trB); - wrap.To(22).Seek(low, ESeek::Lower).Is(trA); - wrap.To(23).Seek(low, ESeek::Exact).Is(EReady::Gone); - wrap.To(24).Seek(mid, ESeek::Lower).Is(trA); - wrap.To(25).Seek(mid, ESeek::Upper).Is(trA); - wrap.To(26).Seek(mid, ESeek::Exact).Is(EReady::Gone); - wrap.To(27).Seek(upp, ESeek::Lower).Is(trB); - wrap.To(28).Seek(upp, ESeek::Upper).Is(trB); - wrap.To(29).Seek(upp, ESeek::Exact).Is(EReady::Gone); - } - + auto trA = *TNatural(*fake).Col(10_u64, 3_u32, 7_u32, 77_u32); + auto trB = *TNatural(*fake).Col(12_u64, 3_u32, 7_u32, 44_u32); + auto trC = *TNatural(*fake).Col(17_u64, 3_u32, 7_u32, nullptr); + auto trD = *TNatural(*fake).Col(19_u64, 3_u32, 7_u32, 99_u32); + + auto low = *TNatural(*fake).Col(10_u64, 2_u32, 2_u32); + auto mid = *TNatural(*fake).Col(10_u64, 3_u32, 5_u32); + auto upp = *TNatural(*fake).Col(10_u64, 3_u32, 8_u32); + + wrap.To(10).Has(trA); /* default values in key */ + wrap.To(11).Has(trB); /* default values in key */ + wrap.To(12).Has(trC); /* explicit null in values */ + wrap.To(13).Has(trD); /* default value in values */ + wrap.To(20).Seek(trA, ESeek::Lower).Is(trA); + wrap.To(21).Seek(trA, ESeek::Upper).Is(trB); + wrap.To(22).Seek(low, ESeek::Lower).Is(trA); + wrap.To(23).Seek(low, ESeek::Exact).Is(EReady::Gone); + wrap.To(24).Seek(mid, ESeek::Lower).Is(trA); + wrap.To(25).Seek(mid, ESeek::Upper).Is(trA); + wrap.To(26).Seek(mid, ESeek::Exact).Is(EReady::Gone); + wrap.To(27).Seek(upp, ESeek::Lower).Is(trB); + wrap.To(28).Seek(upp, ESeek::Upper).Is(trB); + wrap.To(29).Seek(upp, ESeek::Exact).Is(EReady::Gone); + } + Y_UNIT_TEST(Matter) - { - TLayoutCook lay; - - lay.Col(0, 0, ETypes::Uint32).Col(0, 1, ETypes::String).Key({ 0 }); - - const auto foo = *TNatural(*lay).Col(7_u32, TString(128, 'x')); - - TCheckIt wrap(TPartCook(lay, { true, 99, 32 }).Add(foo).Finish(), { }); - - wrap.To(10).Seek(foo, ESeek::Exact).To(11).Is(foo); - + { + TLayoutCook lay; + + lay.Col(0, 0, ETypes::Uint32).Col(0, 1, ETypes::String).Key({ 0 }); + + const auto foo = *TNatural(*lay).Col(7_u32, TString(128, 'x')); + + TCheckIt wrap(TPartCook(lay, { true, 99, 32 }).Add(foo).Finish(), { }); + + wrap.To(10).Seek(foo, ESeek::Exact).To(11).Is(foo); + auto &part = dynamic_cast<const NTest::TPartStore&>(*(*wrap).Eggs.Lone()); - + const auto glob = part.Store->GlobForBlob(0); - - { /*_ Check that part has exactly one external blob */ + + { /*_ Check that part has exactly one external blob */ UNIT_ASSERT(part.Store->PageCollectionPagesCount(part.Store->GetExternRoom()) == 1); - UNIT_ASSERT(part.Blobs->Total() == 1); - UNIT_ASSERT(part.Blobs->Glob(0) == glob); - UNIT_ASSERT(part.Large->Stats().Items == 1); - UNIT_ASSERT(part.Large->Relation(0).Row == 0); - UNIT_ASSERT(part.Large->Relation(0).Tag == 1); - } - - { /*_ Check access to external blob out of cache */ + UNIT_ASSERT(part.Blobs->Total() == 1); + UNIT_ASSERT(part.Blobs->Glob(0) == glob); + UNIT_ASSERT(part.Large->Stats().Items == 1); + UNIT_ASSERT(part.Large->Relation(0).Row == 0); + UNIT_ASSERT(part.Large->Relation(0).Tag == 1); + } + + { /*_ Check access to external blob out of cache */ wrap.Displace<IPages>(new TNoEnv{ true, ELargeObjNeed::Yes }); - - wrap.To(12).Seek(foo, ESeek::Exact).Is(EReady::Page); - } - - { /*_ Check correctness of reference to TGlobId array */ + + wrap.To(12).Seek(foo, ESeek::Exact).Is(EReady::Page); + } + + { /*_ Check correctness of reference to TGlobId array */ wrap.Displace<IPages>(new TNoEnv{ true, ELargeObjNeed::No }); - wrap.To(14).Seek(foo, ESeek::Exact); - - const auto cell = (*wrap).Apply().Get(1); - - UNIT_ASSERT(cell.Data() == (void*)&(**part.Blobs)[0]); + wrap.To(14).Seek(foo, ESeek::Exact); + + const auto cell = (*wrap).Apply().Get(1); + + UNIT_ASSERT(cell.Data() == (void*)&(**part.Blobs)[0]); UNIT_ASSERT(cell.Size() == sizeof(NPageCollection::TGlobId)); - } - - { /*_ Check marker of absent external blob in TCell */ + } + + { /*_ Check marker of absent external blob in TCell */ wrap.Displace<IPages>(new TNoEnv{ true, ELargeObjNeed::No }); - - auto marked = *TNatural(*lay).Col(7_u32, glob); - - wrap.To(16).Seek(foo, ESeek::Exact).Is(marked); - } - - DumpPart(*(*wrap).Eggs.Lone(), 10); - } - + + auto marked = *TNatural(*lay).Col(7_u32, glob); + + wrap.To(16).Seek(foo, ESeek::Exact).Is(marked); + } + + DumpPart(*(*wrap).Eggs.Lone(), 10); + } + Y_UNIT_TEST(External) - { - TLayoutCook lay; - - lay.Col(0, 0, ETypes::Uint32).Col(0, 1, ETypes::String).Key({ 0 }); - - TPartCook cook(lay, { }); - + { + TLayoutCook lay; + + lay.Col(0, 0, ETypes::Uint32).Col(0, 1, ETypes::String).Key({ 0 }); + + TPartCook cook(lay, { }); + const auto glob = cook.PutBlob(TString(128, 'x'), 0); - const auto foo = *TNatural(*lay).Col(7_u32, glob); - - TCheckIt wrap(cook.Add(foo).Finish(), { }); - + const auto foo = *TNatural(*lay).Col(7_u32, glob); + + TCheckIt wrap(cook.Add(foo).Finish(), { }); + wrap.Displace<IPages>(new TNoEnv{ true, ELargeObjNeed::No }); - wrap.To(10).Seek(foo, ESeek::Exact).To(11).Is(foo); - - { /*_ Check that part has correct glob in its catalog */ - auto &part = *(*wrap).Eggs.Lone(); - - UNIT_ASSERT(part.Blobs->Total() == 1); - UNIT_ASSERT(part.Large->Stats().Items == 1); - UNIT_ASSERT(part.Blobs->Glob(0) == glob); - } - - DumpPart(*(*wrap).Eggs.Lone(), 10); - } - + wrap.To(10).Seek(foo, ESeek::Exact).To(11).Is(foo); + + { /*_ Check that part has correct glob in its catalog */ + auto &part = *(*wrap).Eggs.Lone(); + + UNIT_ASSERT(part.Blobs->Total() == 1); + UNIT_ASSERT(part.Large->Stats().Items == 1); + UNIT_ASSERT(part.Blobs->Glob(0) == glob); + } + + DumpPart(*(*wrap).Eggs.Lone(), 10); + } + Y_UNIT_TEST(Outer) - { - using namespace NTable::NTest; - - TLayoutCook lay; - - lay.Col(0, 0, ETypes::Uint32).Col(0, 1, ETypes::String).Key({ 0 }); - - TPartCook cook(lay, PageConf()); - - const auto foo = *TNatural(*lay).Col(7_u32, TString(24, 'x')); - const auto bar = *TNatural(*lay).Col(8_u32, TString(10, 'x')); - - TCheckIt wrap(cook.Add(foo).Add(bar).Finish(), { }); - - wrap.To(10).Has(foo, bar); - - { /*_ Check that part has correct glob in its catalog */ - auto &part = *(*wrap).Eggs.Lone(); - - UNIT_ASSERT_C(part.Small, "Writer didn't produced small blobs"); - UNIT_ASSERT(part.Small->Stats().Items == 1); - } - - DumpPart(*(*wrap).Eggs.Lone(), 10); - } - + { + using namespace NTable::NTest; + + TLayoutCook lay; + + lay.Col(0, 0, ETypes::Uint32).Col(0, 1, ETypes::String).Key({ 0 }); + + TPartCook cook(lay, PageConf()); + + const auto foo = *TNatural(*lay).Col(7_u32, TString(24, 'x')); + const auto bar = *TNatural(*lay).Col(8_u32, TString(10, 'x')); + + TCheckIt wrap(cook.Add(foo).Add(bar).Finish(), { }); + + wrap.To(10).Has(foo, bar); + + { /*_ Check that part has correct glob in its catalog */ + auto &part = *(*wrap).Eggs.Lone(); + + UNIT_ASSERT_C(part.Small, "Writer didn't produced small blobs"); + UNIT_ASSERT(part.Small->Stats().Items == 1); + } + + DumpPart(*(*wrap).Eggs.Lone(), 10); + } + Y_UNIT_TEST(MassCheck) - { + { UNIT_ASSERT_C(Eggs0().Parts.size() == 1, "Eggs0 has " << Eggs0().Parts.size() << "p"); - - auto &part = *Eggs0().Lone(); - auto pages = part.Index->End() - part.Index->Begin(); + + auto &part = *Eggs0().Lone(); + auto pages = part.Index->End() - part.Index->Begin(); auto minIndex = PageConf().Groups.at(0).IndexMin * 8; - - auto cWidth = [](const NPage::TFrames *frames, ui32 span) -> ui32 { - if (nullptr == frames) return 0; - - ui32 page = 0, found = 0; - - while (auto rel = frames->Relation(page)) { - UNIT_ASSERT(rel.Refer <= 0); - - found += bool(ui32(-rel.Refer) >= span); - page = page - rel.Refer; - } - - return found; - }; - - /*_ Ensure that produced part has enough pages for code coverage and - index grow algorithm in data pages writer has been triggered. */ - + + auto cWidth = [](const NPage::TFrames *frames, ui32 span) -> ui32 { + if (nullptr == frames) return 0; + + ui32 page = 0, found = 0; + + while (auto rel = frames->Relation(page)) { + UNIT_ASSERT(rel.Refer <= 0); + + found += bool(ui32(-rel.Refer) >= span); + page = page - rel.Refer; + } + + return found; + }; + + /*_ Ensure that produced part has enough pages for code coverage and + index grow algorithm in data pages writer has been triggered. */ + UNIT_ASSERT(pages > 100 && part.Index.RawSize() >= minIndex); - - { /*_ Ensure that part has some external blobs written to room 1 */ - auto one = Eggs0().Lone()->Blobs->Total(); - auto two = Eggs0().Lone()->Large->Stats().Items; - + + { /*_ Ensure that part has some external blobs written to room 1 */ + auto one = Eggs0().Lone()->Blobs->Total(); + auto two = Eggs0().Lone()->Large->Stats().Items; + UNIT_ASSERT(one && one == two && one == part.Store->PageCollectionPagesCount(part.Store->GetExternRoom())); - } - - { /*_ Ensure that part has some outer packed blobs in room 2 */ - auto one = Eggs0().Lone()->Small->Stats().Items; - + } + + { /*_ Ensure that part has some outer packed blobs in room 2 */ + auto one = Eggs0().Lone()->Small->Stats().Items; + UNIT_ASSERT(one && one == part.Store->PageCollectionPagesCount(part.Store->GetOuterRoom())); - } - - { /*_ Enusre there is some rows with two cells with references */ - - ui32 large = cWidth(Eggs0().Lone()->Large.Get(), 2); - ui32 small = cWidth(Eggs0().Lone()->Small.Get(), 2); - - UNIT_ASSERT_C(small > 10, "Eggs0 has trivial outer packed set"); - UNIT_ASSERT_C(large > 10, "Eggs0 has trivial external blobs set"); - } - + } + + { /*_ Enusre there is some rows with two cells with references */ + + ui32 large = cWidth(Eggs0().Lone()->Large.Get(), 2); + ui32 small = cWidth(Eggs0().Lone()->Small.Get(), 2); + + UNIT_ASSERT_C(small > 10, "Eggs0 has trivial outer packed set"); + UNIT_ASSERT_C(large > 10, "Eggs0 has trivial external blobs set"); + } + { /*_ Check that the last key matches in the index */ - UNIT_ASSERT_VALUES_EQUAL(part.Index.Rows(), Mass0().Saved.Size()); + UNIT_ASSERT_VALUES_EQUAL(part.Index.Rows(), Mass0().Saved.Size()); const NPage::TCompare<NPage::TIndex::TRecord> cmp(part.Scheme->Groups[0].ColsKeyIdx, *Eggs0().Scheme->Keys); auto lastKey = TRowTool(*Eggs0().Scheme).KeyCells(Mass0().Saved[Mass0().Saved.Size()-1]); - UNIT_ASSERT_VALUES_EQUAL(cmp.Compare(*part.Index.GetLastKeyRecord(), lastKey), 0); + UNIT_ASSERT_VALUES_EQUAL(cmp.Compare(*part.Index.GetLastKeyRecord(), lastKey), 0); } { /*_ Check that part has correct number of slices */ UNIT_ASSERT_C(part.Slices, "Part was generated without slices"); UNIT_ASSERT_C(part.Slices->size() > 1, "Slice items " << +part.Slices->size()); } - - DumpPart(*Eggs0().Lone(), 1); - } - + + DumpPart(*Eggs0().Lone(), 1); + } + Y_UNIT_TEST(WreckPart) - { + { TWreck<TCheckIt, TPartEggs>(Mass0(), 666).Do(EWreck::Cached, Eggs0()); - } - + } + Y_UNIT_TEST(PageFailEnv) - { + { TWreck<TCheckIt, TPartEggs>(Mass0(), 666).Do(EWreck::Evicted, Eggs0()); - } - + } + Y_UNIT_TEST(ForwardEnv) - { + { TWreck<TCheckIt, TPartEggs>(Mass0(), 666).Do(EWreck::Forward, Eggs0()); - } - + } + Y_UNIT_TEST(WreckPartColumnGroups) { TWreck<TCheckIt, TPartEggs>(Mass1(), 666).Do(EWreck::Cached, Eggs1()); @@ -607,7 +607,7 @@ Y_UNIT_TEST_SUITE(TPart) { auto cooked2 = TCompaction(new TForwardEnv(512, 1024), conf).Do(subset); } -} - -} -} +} + +} +} diff --git a/ydb/core/tablet_flat/ut/ut_part_multi.cpp b/ydb/core/tablet_flat/ut/ut_part_multi.cpp index cdc6714a55..c5a37bec0b 100644 --- a/ydb/core/tablet_flat/ut/ut_part_multi.cpp +++ b/ydb/core/tablet_flat/ut/ut_part_multi.cpp @@ -31,16 +31,16 @@ Y_UNIT_TEST_SUITE(TPartMulti) { const auto baz = *TNatural(*lay).Col(888_u32, "baz", 5.42, false); const auto zzz = *TNatural(*lay).Col(999_u32, "zzz", 4.11, false); - NTest::TPartEggs eggs = { - nullptr, + NTest::TPartEggs eggs = { + nullptr, lay.RowScheme(), { - TPartCook(lay, { }).Add(foo).Add(bar).Finish().Lone(), - TPartCook(lay, { }).Add(baz).Finish().Lone(), - TPartCook(lay, { }).Add(zzz).Finish().Lone(), + TPartCook(lay, { }).Add(foo).Add(bar).Finish().Lone(), + TPartCook(lay, { }).Add(baz).Finish().Lone(), + TPartCook(lay, { }).Add(zzz).Finish().Lone(), }}; - TCheckIt wrap(eggs, { }); + TCheckIt wrap(eggs, { }); wrap.To(10).Has(foo).Has(bar); wrap.To(11).NoVal(*TNatural(*lay).Col(555_u32, "foo", 10.)); diff --git a/ydb/core/tablet_flat/ut/ut_proto.cpp b/ydb/core/tablet_flat/ut/ut_proto.cpp index aa1dac4328..1563e05a72 100644 --- a/ydb/core/tablet_flat/ut/ut_proto.cpp +++ b/ydb/core/tablet_flat/ut/ut_proto.cpp @@ -1,36 +1,36 @@ #include <ydb/core/tablet_flat/flat_sausage_solid.h> #include <ydb/core/tablet_flat/flat_store_solid.h> #include <library/cpp/testing/unittest/registar.h> - -namespace NKikimr { -namespace NTabletFlatExecutor { - + +namespace NKikimr { +namespace NTabletFlatExecutor { + Y_UNIT_TEST_SUITE(NProto /* executor binary units */) { Y_UNIT_TEST(LargeGlobId) - { + { NKikimrExecutorFlat::TPageCollection pageCollection; - + NPageCollection::TLargeGlobId largeGlobId(13, TLogoBlobID{ 1, 3, 7, 11, 10, 0 }, 77); - + UNIT_ASSERT_VALUES_EQUAL(largeGlobId.BlobCount(), 8u); - ui32 num = 0; + ui32 num = 0; for (auto logo : largeGlobId.Blobs()) { ++num; LogoBlobIDFromLogoBlobID(logo, pageCollection.AddMetaId()); - + UNIT_ASSERT_C(num <= 8 && logo.Cookie() + 1 == num, "num=" << num << " logo=" << logo); UNIT_ASSERT_C(logo.BlobSize() == (num == 8 ? 7 : 10), "num=" << num << " logo=" << logo); - } + } UNIT_ASSERT_VALUES_EQUAL(num, 8u); - - auto lookup = [](const TLogoBlobID&) { return 13; }; - + + auto lookup = [](const TLogoBlobID&) { return 13; }; + auto other = TLargeGlobIdProto::Get(pageCollection.GetMetaId(), lookup); - + UNIT_ASSERT(other == largeGlobId); - } -} - -} -} + } +} + +} +} diff --git a/ydb/core/tablet_flat/ut/ut_redo.cpp b/ydb/core/tablet_flat/ut/ut_redo.cpp index 73271b4403..91e002f7aa 100644 --- a/ydb/core/tablet_flat/ut/ut_redo.cpp +++ b/ydb/core/tablet_flat/ut/ut_redo.cpp @@ -1,80 +1,80 @@ #include <ydb/core/tablet_flat/test/libs/table/test_dbase.h> #include <ydb/core/tablet_flat/test/libs/rows/cook.h> - + #include <library/cpp/testing/unittest/registar.h> #include <library/cpp/resource/resource.h> -#include <util/stream/file.h> - -namespace NKikimr { -namespace NTable { - - +#include <util/stream/file.h> + +namespace NKikimr { +namespace NTable { + + Y_UNIT_TEST_SUITE(Redo) { - namespace ETypes = NScheme::NTypeIds; - - using namespace NTest; - + namespace ETypes = NScheme::NTypeIds; + + using namespace NTest; + Y_UNIT_TEST(ABI_008) - { - /* Redo log taken from DBase::Basics test that cover all events */ - - TLayoutCook lay; - - lay - .Col(0, 1, ETypes::String) - .Col(0, 4, ETypes::Uint64, Cimple(77_u64)) - .Col(0, 5, ETypes::String) - .Key({ 1 }); - - const auto foo = *TNatural(*lay).Col("foo", 33_u64); - const auto bar = *TNatural(*lay).Col("bar", 11_u64); - - const auto raw = NResource::Find("abi/008_basics_db.redo"); - - TStringInput input(raw); - - auto changes = TDbExec::RestoreChanges(input); - - UNIT_ASSERT_C(changes.size() == 9, "Unexpected changes in test data"); - - TDbExec me; - ui32 serial = 0; - - for (auto &one: changes) { - me.To(++serial)->RollUp(one->Stamp, one->Scheme, one->Redo, { }); - - if (1 == serial) { - /* Just applied initial alter script, nothing to check */ - + { + /* Redo log taken from DBase::Basics test that cover all events */ + + TLayoutCook lay; + + lay + .Col(0, 1, ETypes::String) + .Col(0, 4, ETypes::Uint64, Cimple(77_u64)) + .Col(0, 5, ETypes::String) + .Key({ 1 }); + + const auto foo = *TNatural(*lay).Col("foo", 33_u64); + const auto bar = *TNatural(*lay).Col("bar", 11_u64); + + const auto raw = NResource::Find("abi/008_basics_db.redo"); + + TStringInput input(raw); + + auto changes = TDbExec::RestoreChanges(input); + + UNIT_ASSERT_C(changes.size() == 9, "Unexpected changes in test data"); + + TDbExec me; + ui32 serial = 0; + + for (auto &one: changes) { + me.To(++serial)->RollUp(one->Stamp, one->Scheme, one->Redo, { }); + + if (1 == serial) { + /* Just applied initial alter script, nothing to check */ + UNIT_ASSERT(me->Subset(1, TEpoch::Max(), { }, { })->Head == TEpoch::FromIndex(1)); - - } else if (2 == serial) { - me.Iter(1).Has(foo).HasN(nullptr, 77_u64).NoKey(bar); - } else if (3 == serial) { - me.Iter(1).Has(foo).Has(bar); - } else if (4 == serial) { + + } else if (2 == serial) { + me.Iter(1).Has(foo).HasN(nullptr, 77_u64).NoKey(bar); + } else if (3 == serial) { + me.Iter(1).Has(foo).Has(bar); + } else if (4 == serial) { /* Table flush (snapshot) event received with scheme updates */ - + UNIT_ASSERT(me->Subset(1, TEpoch::Max(), { }, { })->Head == TEpoch::FromIndex(2)); - - } else if (5 == serial) { - me.Iter(1, false).NoKey(foo).NoVal(bar); - me.Iter(1, false).HasN("bar", 11_u64, "yo"); - } else if (6 == serial) { - me.Iter(1, false).HasN("bar", 77_u64, "me"); - } else if (7 == serial) { - me.Iter(1, false).HasN("bar", 99_u64, nullptr); - } else if (8 == serial) { - me.Iter(1, false).HasN("bar", nullptr, "eh"); - } else if (9 == serial) { - me.Iter(1, false).Has(bar).NoKey(foo); - } else { - UNIT_FAIL("Got to many change entries in redo samples"); - } - } - } -} - - -} -} + + } else if (5 == serial) { + me.Iter(1, false).NoKey(foo).NoVal(bar); + me.Iter(1, false).HasN("bar", 11_u64, "yo"); + } else if (6 == serial) { + me.Iter(1, false).HasN("bar", 77_u64, "me"); + } else if (7 == serial) { + me.Iter(1, false).HasN("bar", 99_u64, nullptr); + } else if (8 == serial) { + me.Iter(1, false).HasN("bar", nullptr, "eh"); + } else if (9 == serial) { + me.Iter(1, false).Has(bar).NoKey(foo); + } else { + UNIT_FAIL("Got to many change entries in redo samples"); + } + } + } +} + + +} +} diff --git a/ydb/core/tablet_flat/ut/ut_sausage.cpp b/ydb/core/tablet_flat/ut/ut_sausage.cpp index 9fed2caacc..eec01ee13c 100644 --- a/ydb/core/tablet_flat/ut/ut_sausage.cpp +++ b/ydb/core/tablet_flat/ut/ut_sausage.cpp @@ -6,411 +6,411 @@ #include <ydb/core/tablet_flat/flat_sausage_chop.h> #include <ydb/core/tablet_flat/flat_sausage_grind.h> #include <ydb/core/tablet_flat/util_fmt_desc.h> - + #include <library/cpp/testing/unittest/registar.h> -#include <util/generic/xrange.h> -#include <array> - -namespace NKikimr { +#include <util/generic/xrange.h> +#include <array> + +namespace NKikimr { namespace NPageCollection { - -namespace { + +namespace { struct TMyPageCollection { using TArrayRef = TArrayRef<const TGlobId>; - + TMyPageCollection(TArrayRef globs) : Globs(globs) { } - - inline TBorder Bounds(ui32 page) const noexcept - { - const auto size = Glob(page).Logo.BlobSize(); - - return { size, { page, 0 }, { page, size } }; - } - - inline TGlobId Glob(ui32 at) const noexcept - { - return at < Globs.size() ? Globs[at] : TGlobId{ }; - } - + + inline TBorder Bounds(ui32 page) const noexcept + { + const auto size = Glob(page).Logo.BlobSize(); + + return { size, { page, 0 }, { page, size } }; + } + + inline TGlobId Glob(ui32 at) const noexcept + { + return at < Globs.size() ? Globs[at] : TGlobId{ }; + } + const TArrayRef Globs; - }; -} - + }; +} + Y_UNIT_TEST_SUITE(NPageCollection) { using TGlow = TPagesToBlobsConverter<TMeta>; - - static const std::array<TLogoBlobID, 7> Blobs = {{ - TLogoBlobID(10, 20, 30, 1, 100, 0), - TLogoBlobID(10, 20, 30, 1, 120, 1), - TLogoBlobID(10, 20, 30, 1, 40, 2), - TLogoBlobID(10, 20, 30, 1, 60, 3), - TLogoBlobID(10, 20, 30, 1, 140, 4), - TLogoBlobID(10, 20, 30, 1, 170, 5), - TLogoBlobID(10, 20, 30, 1, 150, 6), - }}; - - const std::array<ui32, 9> Pages= {{ 50, 30, 80, 60, 40, 60, 70, 380, 10 }}; - + + static const std::array<TLogoBlobID, 7> Blobs = {{ + TLogoBlobID(10, 20, 30, 1, 100, 0), + TLogoBlobID(10, 20, 30, 1, 120, 1), + TLogoBlobID(10, 20, 30, 1, 40, 2), + TLogoBlobID(10, 20, 30, 1, 60, 3), + TLogoBlobID(10, 20, 30, 1, 140, 4), + TLogoBlobID(10, 20, 30, 1, 170, 5), + TLogoBlobID(10, 20, 30, 1, 150, 6), + }}; + + const std::array<ui32, 9> Pages= {{ 50, 30, 80, 60, 40, 60, 70, 380, 10 }}; + TSharedData MakeMeta() - { + { NPageCollection::TRecord meta(0); - - meta.Push(Blobs); - - for (auto size: Pages) { - TString lumber(size, '9'); + + meta.Push(Blobs); + + for (auto size: Pages) { + TString lumber(size, '9'); meta.Push(0, lumber); - } - + } + return meta.Finish(); - } - + } + Y_UNIT_TEST(Align) - { - const std::array<ui64, 3> steps = {{ 200, 500, 1000 }}; - - const TAlign align(steps); - - const auto lookup1 = align.Lookup(0, 1000); - const auto lookup2 = align.Lookup(100, 800); - const auto lookup3 = align.Lookup(300, 200); - const auto lookup4 = align.Lookup(300, 250); - const auto lookup5 = align.Lookup(200, 20); - - UNIT_ASSERT(lookup1.Lo.Blob == 0 && lookup1.Lo.Skip == 0 - && lookup1.Up.Blob == 2 && lookup1.Up.Skip == 500); - UNIT_ASSERT(lookup2.Lo.Blob == 0 && lookup2.Lo.Skip == 100 - && lookup2.Up.Blob == 2 && lookup2.Up.Skip == 400); - UNIT_ASSERT(lookup3.Lo.Blob == 1 && lookup3.Lo.Skip == 100 - && lookup3.Up.Blob == 1 && lookup3.Up.Skip == 300); - UNIT_ASSERT(lookup4.Lo.Blob == 1 && lookup4.Lo.Skip == 100 - && lookup4.Up.Blob == 2 && lookup4.Up.Skip == 50); - UNIT_ASSERT(lookup5.Lo.Blob == 1 && lookup5.Lo.Skip == 0 - && lookup5.Up.Blob == 1 && lookup5.Up.Skip == 20); - } - + { + const std::array<ui64, 3> steps = {{ 200, 500, 1000 }}; + + const TAlign align(steps); + + const auto lookup1 = align.Lookup(0, 1000); + const auto lookup2 = align.Lookup(100, 800); + const auto lookup3 = align.Lookup(300, 200); + const auto lookup4 = align.Lookup(300, 250); + const auto lookup5 = align.Lookup(200, 20); + + UNIT_ASSERT(lookup1.Lo.Blob == 0 && lookup1.Lo.Skip == 0 + && lookup1.Up.Blob == 2 && lookup1.Up.Skip == 500); + UNIT_ASSERT(lookup2.Lo.Blob == 0 && lookup2.Lo.Skip == 100 + && lookup2.Up.Blob == 2 && lookup2.Up.Skip == 400); + UNIT_ASSERT(lookup3.Lo.Blob == 1 && lookup3.Lo.Skip == 100 + && lookup3.Up.Blob == 1 && lookup3.Up.Skip == 300); + UNIT_ASSERT(lookup4.Lo.Blob == 1 && lookup4.Lo.Skip == 100 + && lookup4.Up.Blob == 2 && lookup4.Up.Skip == 50); + UNIT_ASSERT(lookup5.Lo.Blob == 1 && lookup5.Lo.Skip == 0 + && lookup5.Up.Blob == 1 && lookup5.Up.Skip == 20); + } + Y_UNIT_TEST(Meta) - { - TString chunk1(5000000, '1'); - TString chunk2(15000000, '2'); - TString chunk3(6000000, '3'); - - const TGlobId glob{ TLogoBlobID(10, 20, 30, 1, 0, 0), 777 }; - - auto checkGlobs = [&](TVector<TGlob> blobs) { - for (const auto &one: blobs) { + { + TString chunk1(5000000, '1'); + TString chunk2(15000000, '2'); + TString chunk3(6000000, '3'); + + const TGlobId glob{ TLogoBlobID(10, 20, 30, 1, 0, 0), 777 }; + + auto checkGlobs = [&](TVector<TGlob> blobs) { + for (const auto &one: blobs) { bool pln = TGroupBlobsByCookie::IsInPlane(one.GId.Logo, glob.Logo); - bool grp = (one.GId.Group == glob.Group); - bool cnl = (one.GId.Logo.Channel() == glob.Logo.Channel()); - - UNIT_ASSERT(pln && grp && cnl); - } - - return blobs.size(); - }; - + bool grp = (one.GId.Group == glob.Group); + bool cnl = (one.GId.Logo.Channel() == glob.Logo.Channel()); + + UNIT_ASSERT(pln && grp && cnl); + } + + return blobs.size(); + }; + TCookieAllocator cookieAllocator(10, (ui64(20) << 32) | 30, { 0, 999 }, {{ 1, 777 }}); - + TWriter writer(cookieAllocator, 1 /* channel */, 8192 * 1024); - + const auto r1 = writer.AddPage(chunk1, 1); writer.AddInplace(r1, TStringBuf("chunk 1")); - - UNIT_ASSERT(r1 == 0 && checkGlobs(writer.Grab()) == 0); - + + UNIT_ASSERT(r1 == 0 && checkGlobs(writer.Grab()) == 0); + const auto r2 = writer.AddPage(chunk2, 2); writer.AddInplace(r2, TStringBuf("chunk 2")); - - UNIT_ASSERT(r2 == 1 && checkGlobs(writer.Grab()) == 2); - + + UNIT_ASSERT(r2 == 1 && checkGlobs(writer.Grab()) == 2); + const auto r3 = writer.AddPage(chunk3, 3); writer.AddInplace(r3, TStringBuf("chunk 3")); - - UNIT_ASSERT(r3 == 2 && checkGlobs(writer.Grab()) == 1); - - const auto blob = writer.Finish(true); - - UNIT_ASSERT(checkGlobs(writer.Grab()) == 1); - - const TMeta meta(blob, 0 /* group, unused */); - - UNIT_ASSERT(meta.TotalPages() == 3); - UNIT_ASSERT(meta.GetPageType(0) == 1); - UNIT_ASSERT(meta.GetPageType(1) == 2); - UNIT_ASSERT(meta.GetPageType(2) == 3); - - UNIT_ASSERT(meta.GetPageInplaceData(0) == "chunk 1"); - UNIT_ASSERT(meta.GetPageInplaceData(1) == "chunk 2"); - UNIT_ASSERT(meta.GetPageInplaceData(2) == "chunk 3"); - - auto l1 = meta.Bounds(0); - auto l2 = meta.Bounds(1); - auto l3 = meta.Bounds(2); - - UNIT_ASSERT(l1.Lo.Blob == 0 && l1.Up.Blob == 0); - UNIT_ASSERT(l2.Lo.Blob == 0 && l2.Up.Blob == 2); - UNIT_ASSERT(l3.Lo.Blob == 2 && l3.Up.Blob == 3); - } - + + UNIT_ASSERT(r3 == 2 && checkGlobs(writer.Grab()) == 1); + + const auto blob = writer.Finish(true); + + UNIT_ASSERT(checkGlobs(writer.Grab()) == 1); + + const TMeta meta(blob, 0 /* group, unused */); + + UNIT_ASSERT(meta.TotalPages() == 3); + UNIT_ASSERT(meta.GetPageType(0) == 1); + UNIT_ASSERT(meta.GetPageType(1) == 2); + UNIT_ASSERT(meta.GetPageType(2) == 3); + + UNIT_ASSERT(meta.GetPageInplaceData(0) == "chunk 1"); + UNIT_ASSERT(meta.GetPageInplaceData(1) == "chunk 2"); + UNIT_ASSERT(meta.GetPageInplaceData(2) == "chunk 3"); + + auto l1 = meta.Bounds(0); + auto l2 = meta.Bounds(1); + auto l3 = meta.Bounds(2); + + UNIT_ASSERT(l1.Lo.Blob == 0 && l1.Up.Blob == 0); + UNIT_ASSERT(l2.Lo.Blob == 0 && l2.Up.Blob == 2); + UNIT_ASSERT(l3.Lo.Blob == 2 && l3.Up.Blob == 3); + } + Y_UNIT_TEST(PagesToBlobsConverter) - { - const TMeta meta(MakeMeta(), 0); - - auto grow = [&meta](const TVector<ui32> pages) { - TGlow flow(meta, pages); - flow.Grow(Max<ui64>()); + { + const TMeta meta(MakeMeta(), 0); + + auto grow = [&meta](const TVector<ui32> pages) { + TGlow flow(meta, pages); + flow.Grow(Max<ui64>()); return std::move(flow.Queue); - }; - - { /*_ { 1 } lies away of the bounds of one blob */ - const auto ln = grow({ 1 }); - - UNIT_ASSERT(ln.size() == 1); + }; + + { /*_ { 1 } lies away of the bounds of one blob */ + const auto ln = grow({ 1 }); + + UNIT_ASSERT(ln.size() == 1); UNIT_ASSERT((ln[0] == TGlow::TReadPortion{ 0, 30, 0, 50 })); - } - - { /*_ { 0, 6 } snaps to the start of the single blob */ - const auto ln = grow({ 0, 6 }); - - UNIT_ASSERT(ln.size() == 2); + } + + { /*_ { 0, 6 } snaps to the start of the single blob */ + const auto ln = grow({ 0, 6 }); + + UNIT_ASSERT(ln.size() == 2); UNIT_ASSERT((ln[0] == TGlow::TReadPortion{ 0, 50, 0, 0 })); UNIT_ASSERT((ln[1] == TGlow::TReadPortion{ 1, 70, 4, 0 })); - } - - { /*_ { 3, 8 } snaps to the end of the single blob */ - const auto ln = grow({ 3, 8 }); - - UNIT_ASSERT(ln.size() == 2); + } + + { /*_ { 3, 8 } snaps to the end of the single blob */ + const auto ln = grow({ 3, 8 }); + + UNIT_ASSERT(ln.size() == 2); UNIT_ASSERT((ln[0] == TGlow::TReadPortion{ 0, 60, 1, 60 })); UNIT_ASSERT((ln[1] == TGlow::TReadPortion{ 1, 10, 6, 140 })); - } - - { /*_ { 2 } spans over the bounds of the two blobs */ - const auto ln = grow({ 2 }); - - - UNIT_ASSERT(ln.size() == 2); + } + + { /*_ { 2 } spans over the bounds of the two blobs */ + const auto ln = grow({ 2 }); + + + UNIT_ASSERT(ln.size() == 2); UNIT_ASSERT((ln[0] == TGlow::TReadPortion{ 0, 20, 0, 80 })); UNIT_ASSERT((ln[1] == TGlow::TReadPortion{ 0, 60, 1, 0 })); - } - - { /*_ { 4, 5 } each occupies entire single blob */ - const auto ln = grow({ 4, 5 }); - - UNIT_ASSERT(ln.size() == 2); + } + + { /*_ { 4, 5 } each occupies entire single blob */ + const auto ln = grow({ 4, 5 }); + + UNIT_ASSERT(ln.size() == 2); UNIT_ASSERT((ln[0] == TGlow::TReadPortion{ 0, 40, 2, 0 })); UNIT_ASSERT((ln[1] == TGlow::TReadPortion{ 1, 60, 3, 0 })); - } - - { /*_ { 7 } spans over a serveral subsequent blobs */ - const auto ln = grow({ 7 }); - - UNIT_ASSERT(ln.size() == 3); + } + + { /*_ { 7 } spans over a serveral subsequent blobs */ + const auto ln = grow({ 7 }); + + UNIT_ASSERT(ln.size() == 3); UNIT_ASSERT((ln[0] == TGlow::TReadPortion{ 0, 70, 4, 70 })); UNIT_ASSERT((ln[1] == TGlow::TReadPortion{ 0, 170, 5, 0 })); UNIT_ASSERT((ln[2] == TGlow::TReadPortion{ 0, 140, 6, 0 })); - } - } - + } + } + Y_UNIT_TEST(Grow) - { - const TMeta meta(MakeMeta(), 0); - const std::array<ui32, 9> nums = {{ 0, 1, 2, 3, 4, 5, 6, 7, 8 }}; - - TGlow flow(meta, nums); - - auto grow = [&flow](ui64 bytes) { - ui64 used = 0; - - if (const auto more = flow.Grow(bytes)) - for (const auto on : xrange(+more)) + { + const TMeta meta(MakeMeta(), 0); + const std::array<ui32, 9> nums = {{ 0, 1, 2, 3, 4, 5, 6, 7, 8 }}; + + TGlow flow(meta, nums); + + auto grow = [&flow](ui64 bytes) { + ui64 used = 0; + + if (const auto more = flow.Grow(bytes)) + for (const auto on : xrange(+more)) used += flow.Queue[more.From + on].Size; - - return used; - }; - - UNIT_ASSERT((grow(200) == 160)); - UNIT_ASSERT((grow(200) == 160)); - UNIT_ASSERT((grow(200) == 70)); - UNIT_ASSERT((grow(200) == 380)); - UNIT_ASSERT((grow(200) == 10)); - } - + + return used; + }; + + UNIT_ASSERT((grow(200) == 160)); + UNIT_ASSERT((grow(200) == 160)); + UNIT_ASSERT((grow(200) == 70)); + UNIT_ASSERT((grow(200) == 380)); + UNIT_ASSERT((grow(200) == 10)); + } + Y_UNIT_TEST(Groups) - { - const std::array<TGlobId, 6> globs = {{ - { TLogoBlobID(1, 2, 3, 1, 10, 0), 7 }, - { TLogoBlobID(1, 2, 3, 1, 12, 1), 7 }, - { TLogoBlobID(1, 2, 3, 1, 14, 2), 7 }, - { TLogoBlobID(1, 2, 3, 1, 16, 3), 4 }, - { TLogoBlobID(1, 2, 3, 1, 18, 4), 7 }, - { TLogoBlobID(1, 2, 3, 1, 20, 5), 7 }, - }}; - + { + const std::array<TGlobId, 6> globs = {{ + { TLogoBlobID(1, 2, 3, 1, 10, 0), 7 }, + { TLogoBlobID(1, 2, 3, 1, 12, 1), 7 }, + { TLogoBlobID(1, 2, 3, 1, 14, 2), 7 }, + { TLogoBlobID(1, 2, 3, 1, 16, 3), 4 }, + { TLogoBlobID(1, 2, 3, 1, 18, 4), 7 }, + { TLogoBlobID(1, 2, 3, 1, 20, 5), 7 }, + }}; + const TMyPageCollection myPageCollection(globs); - + auto check = [&globs](const TPagesToBlobsConverter<TMyPageCollection> &flow) { for (auto num : xrange(flow.Queue.size())) { const auto &brick = flow.Queue.at(num); - - UNIT_ASSERT(brick.Slot == num && brick.Blob == num); - UNIT_ASSERT(brick.Size == globs[num].Logo.BlobSize()); - UNIT_ASSERT(brick.Skip == 0); - } - }; - - { /*_ Take the only blob page in middle */ + + UNIT_ASSERT(brick.Slot == num && brick.Blob == num); + UNIT_ASSERT(brick.Size == globs[num].Logo.BlobSize()); + UNIT_ASSERT(brick.Skip == 0); + } + }; + + { /*_ Take the only blob page in middle */ const ui32 slice1[] = { 3 }; const ui32 slice2[] = { 4 }; auto one = TPagesToBlobsConverter<TMyPageCollection>(myPageCollection, slice1).Grow(7500); auto two = TPagesToBlobsConverter<TMyPageCollection>(myPageCollection, slice2).Grow(7500); - - UNIT_ASSERT(one && one.From == 0 && one.To == 1); - UNIT_ASSERT(two && two.From == 0 && two.To == 1); - } - + + UNIT_ASSERT(one && one.From == 0 && one.To == 1); + UNIT_ASSERT(two && two.From == 0 && two.To == 1); + } + { /*_ Read all pages in blobs page collection */ const ui32 slice[] = { 0, 1, 2, 3, 4, 5 }; TPagesToBlobsConverter<TMyPageCollection> flow(myPageCollection, slice); - - auto one = flow.Grow(7500); - auto two = flow.Grow(7500); - auto thr = flow.Grow(7500); - + + auto one = flow.Grow(7500); + auto two = flow.Grow(7500); + auto thr = flow.Grow(7500); + UNIT_ASSERT(one); UNIT_ASSERT_VALUES_EQUAL(one.From, 0); UNIT_ASSERT_VALUES_EQUAL(one.To, 3); - UNIT_ASSERT(one && one.From == 0 && one.To == 3); - UNIT_ASSERT(two && two.From == 3 && two.To == 4); - UNIT_ASSERT(thr && thr.From == 4 && thr.To == 6); - - check(flow); - } - - { /*_ Read with limits on each package */ + UNIT_ASSERT(one && one.From == 0 && one.To == 3); + UNIT_ASSERT(two && two.From == 3 && two.To == 4); + UNIT_ASSERT(thr && thr.From == 4 && thr.To == 6); + + check(flow); + } + + { /*_ Read with limits on each package */ const ui32 slice[] = { 0, 1, 2, 3, 4, 5 }; TPagesToBlobsConverter<TMyPageCollection> flow(myPageCollection, slice); - - auto one = flow.Grow(40); - auto two = flow.Grow(40); - auto thr = flow.Grow(40); - - UNIT_ASSERT(one && one.From == 0 && one.To == 3); - UNIT_ASSERT(two && two.From == 3 && two.To == 4); - UNIT_ASSERT(thr && thr.From == 4 && thr.To == 6); - - check(flow); - } - } - + + auto one = flow.Grow(40); + auto two = flow.Grow(40); + auto thr = flow.Grow(40); + + UNIT_ASSERT(one && one.From == 0 && one.To == 3); + UNIT_ASSERT(two && two.From == 3 && two.To == 4); + UNIT_ASSERT(thr && thr.From == 4 && thr.To == 6); + + check(flow); + } + } + Y_UNIT_TEST(Chop) - { - static const std::array<TLogoBlobID, 6> dash = {{ - TLogoBlobID(10, 20, 30, 1, 25, 0), - TLogoBlobID(10, 20, 30, 1, 25, 1), - TLogoBlobID(10, 20, 30, 1, 10, 2), - TLogoBlobID(10, 20, 30, 1, 15, 5), - TLogoBlobID(10, 20, 30, 1, 15, 6), - TLogoBlobID(10, 20, 30, 1, 10, 9), - }}; - - { /* array of logos with full span */ + { + static const std::array<TLogoBlobID, 6> dash = {{ + TLogoBlobID(10, 20, 30, 1, 25, 0), + TLogoBlobID(10, 20, 30, 1, 25, 1), + TLogoBlobID(10, 20, 30, 1, 10, 2), + TLogoBlobID(10, 20, 30, 1, 15, 5), + TLogoBlobID(10, 20, 30, 1, 15, 6), + TLogoBlobID(10, 20, 30, 1, 10, 9), + }}; + + { /* array of logos with full span */ const auto span = TGroupBlobsByCookie(Blobs).Do(); - - UNIT_ASSERT(span.size() == 7 && span[0] == Blobs[0]); - } - - { /* tirvial array of zero lengh */ + + UNIT_ASSERT(span.size() == 7 && span[0] == Blobs[0]); + } + + { /* tirvial array of zero lengh */ const auto span = TGroupBlobsByCookie({ }).Do(); - - UNIT_ASSERT(span.size() == 0); - } - + + UNIT_ASSERT(span.size() == 0); + } + { /* dashed aray and largeGlobId parser */ TGroupBlobsByCookie chop(dash); - + TVector<TGroupBlobsByCookie::TArray> span; - - for (size_t it = 0; it < 4; it++) - span.emplace_back(chop.Do()); - - UNIT_ASSERT(span[0].size() == 3 && span[0][0] == dash[0]); - UNIT_ASSERT(span[1].size() == 2 && span[1][0] == dash[3]); - UNIT_ASSERT(span[2].size() == 1 && span[2][0] == dash[5]); - UNIT_ASSERT(span[3].size() == 0); - + + for (size_t it = 0; it < 4; it++) + span.emplace_back(chop.Do()); + + UNIT_ASSERT(span[0].size() == 3 && span[0][0] == dash[0]); + UNIT_ASSERT(span[1].size() == 2 && span[1][0] == dash[3]); + UNIT_ASSERT(span[2].size() == 1 && span[2][0] == dash[5]); + UNIT_ASSERT(span[3].size() == 0); + const auto largeGlobId = TGroupBlobsByCookie::ToLargeGlobId(span[0]); - + UNIT_ASSERT(largeGlobId.Bytes == 60 && largeGlobId.Lead == dash[0]); UNIT_ASSERT(TGroupBlobsByCookie::ToLargeGlobId(span[2]).Bytes == 10); UNIT_ASSERT(TGroupBlobsByCookie::ToLargeGlobId({ }).Bytes == 0); - } - } - + } + } + Y_UNIT_TEST(CookieAllocator) - { + { TSteppedCookieAllocator cookieAllocator(1, (ui64(2) << 32) | 1, { 10, 32 }, {{ 3, 999 }}); - + cookieAllocator.Switch(3, true /* require step switch */); - + { /*_ LargeGlobId spanned over several blobs */ auto largeGlobId = cookieAllocator.Do(3, 25, 10); auto itBlobs = largeGlobId.Blobs().begin(); - + UNIT_ASSERT(largeGlobId.Group == 999 && largeGlobId.BlobCount() == 3); UNIT_ASSERT(*itBlobs++ == TLogoBlobID(1, 2, 3, 3, 10, 10)); UNIT_ASSERT(*itBlobs++ == TLogoBlobID(1, 2, 3, 3, 10, 11)); UNIT_ASSERT(*itBlobs++ == TLogoBlobID(1, 2, 3, 3, 5, 12)); UNIT_ASSERT(itBlobs == largeGlobId.Blobs().end()); - } - + } + { /*_ Trivial largeGlobId occupying one blob */ auto largeGlobId = cookieAllocator.Do(3, 9, 10); auto itBlobs = largeGlobId.Blobs().begin(); - + UNIT_ASSERT(largeGlobId.Group == 999 && largeGlobId.BlobCount() == 1); UNIT_ASSERT(*itBlobs++ == TLogoBlobID(1, 2, 3, 3, 9, 14)); UNIT_ASSERT(itBlobs == largeGlobId.Blobs().end()); - } - + } + { /*_ Single blob just after placed largeGlobId */ auto glob = cookieAllocator.Do(3, 88); - - UNIT_ASSERT(glob == TGlobId(TLogoBlobID(1, 2, 3, 3, 88, 16), 999)); - } - - { /*_ Continue single blob series, no holes */ + + UNIT_ASSERT(glob == TGlobId(TLogoBlobID(1, 2, 3, 3, 88, 16), 999)); + } + + { /*_ Continue single blob series, no holes */ auto glob = cookieAllocator.Do(3, 26); - - UNIT_ASSERT(glob == TGlobId(TLogoBlobID(1, 2, 3, 3, 26, 17), 999)); - } - + + UNIT_ASSERT(glob == TGlobId(TLogoBlobID(1, 2, 3, 3, 26, 17), 999)); + } + { /*_ Trivial largeGlobId with exact blob size */ auto largeGlobId = cookieAllocator.Do(3, 10, 10); auto itBlobs = largeGlobId.Blobs().begin(); - + UNIT_ASSERT(largeGlobId.Group == 999 && largeGlobId.BlobCount() == 1); UNIT_ASSERT(*itBlobs++ == TLogoBlobID(1, 2, 3, 3, 10, 19)); UNIT_ASSERT(itBlobs == largeGlobId.Blobs().end()); - } - + } + cookieAllocator.Switch(6, true /* require step switch*/); - - { /*_ After step switch should reset state */ + + { /*_ After step switch should reset state */ auto glob = cookieAllocator.Do(3, 19); - - UNIT_ASSERT(glob == TGlobId(TLogoBlobID(1, 2, 6, 3, 19, 10), 999)); - } - + + UNIT_ASSERT(glob == TGlobId(TLogoBlobID(1, 2, 6, 3, 19, 10), 999)); + } + cookieAllocator.Switch(6, false /* should allow noop */); - + { /*_ On NOOP cookieRange state should not be altered */ auto glob = cookieAllocator.Do(3, 77); - - UNIT_ASSERT(glob == TGlobId(TLogoBlobID(1, 2, 6, 3, 77, 11), 999)); - } - } -} - -} -} + + UNIT_ASSERT(glob == TGlobId(TLogoBlobID(1, 2, 6, 3, 77, 11), 999)); + } + } +} + +} +} diff --git a/ydb/core/tablet_flat/ut/ut_screen.cpp b/ydb/core/tablet_flat/ut/ut_screen.cpp index b2d04bc6cf..9d76291273 100644 --- a/ydb/core/tablet_flat/ut/ut_screen.cpp +++ b/ydb/core/tablet_flat/ut/ut_screen.cpp @@ -6,13 +6,13 @@ #include <ydb/core/tablet_flat/test/libs/table/test_writer.h> #include <ydb/core/tablet_flat/test/libs/table/test_curtain.h> #include <ydb/core/tablet_flat/test/libs/table/test_envs.h> - + #include <library/cpp/testing/unittest/registar.h> - -namespace NKikimr { -namespace NTable { - -namespace { + +namespace NKikimr { +namespace NTable { + +namespace { const NTest::TMass& Mass0() { static const NTest::TMass mass0(new NTest::TModelStd(false), 24000); @@ -22,104 +22,104 @@ namespace { const NTest::TPartEggs& Eggs0() { static const NTest::TPartEggs eggs0 = NTest::TPartCook::Make(Mass0(), { }); - UNIT_ASSERT_C(eggs0.Parts.size() == 1, - "Unexpected " << eggs0.Parts.size() << " results"); + UNIT_ASSERT_C(eggs0.Parts.size() == 1, + "Unexpected " << eggs0.Parts.size() << " results"); return eggs0; } -} - +} + Y_UNIT_TEST_SUITE(TScreen) { - + Y_UNIT_TEST(Cuts) - { - using namespace NTable::NTest; - using THole = TScreen::THole; - + { + using namespace NTable::NTest; + using THole = TScreen::THole; + TIntrusiveConstPtr<TScreen> one(new TScreen({ { 3, 10 }, { 40, 70 }, { 80, 99 } })); - - auto cut = [=](THole hole) { return TScreen::Cut(one, hole); }; - - UNIT_ASSERT(cut({ 1, 3 })->Bounds() == THole(false)); - UNIT_ASSERT(cut(THole(false))->Bounds() == THole(false)); - UNIT_ASSERT(cut({ 0, 5 })->Cmp(TScreen({ THole(3, 5) }))); - UNIT_ASSERT(cut({ 7, 10 })->Cmp(TScreen({ THole(7, 10) }))); - UNIT_ASSERT(cut({ 7, 25 })->Cmp(TScreen({ THole(7, 10) }))); - UNIT_ASSERT(cut({ 7, 44 })->Cmp(TScreen({ {7, 10}, {40, 44} }))); - UNIT_ASSERT(cut({ 7, 91 })->Bounds() == THole({ 7, 91 })); - UNIT_ASSERT(cut({ 0, 101 })->Cmp(*one)); - UNIT_ASSERT(cut(THole(true))->Cmp(*one)); - UNIT_ASSERT(cut({ 7, 91 })->Cmp( - TScreen({ {7, 10 }, { 40, 70 }, { 80, 91 } }))); - } - + + auto cut = [=](THole hole) { return TScreen::Cut(one, hole); }; + + UNIT_ASSERT(cut({ 1, 3 })->Bounds() == THole(false)); + UNIT_ASSERT(cut(THole(false))->Bounds() == THole(false)); + UNIT_ASSERT(cut({ 0, 5 })->Cmp(TScreen({ THole(3, 5) }))); + UNIT_ASSERT(cut({ 7, 10 })->Cmp(TScreen({ THole(7, 10) }))); + UNIT_ASSERT(cut({ 7, 25 })->Cmp(TScreen({ THole(7, 10) }))); + UNIT_ASSERT(cut({ 7, 44 })->Cmp(TScreen({ {7, 10}, {40, 44} }))); + UNIT_ASSERT(cut({ 7, 91 })->Bounds() == THole({ 7, 91 })); + UNIT_ASSERT(cut({ 0, 101 })->Cmp(*one)); + UNIT_ASSERT(cut(THole(true))->Cmp(*one)); + UNIT_ASSERT(cut({ 7, 91 })->Cmp( + TScreen({ {7, 10 }, { 40, 70 }, { 80, 91 } }))); + } + Y_UNIT_TEST(Join) - { - using namespace NTable::NTest; - using THole = TScreen::THole; - + { + using namespace NTable::NTest; + using THole = TScreen::THole; + TIntrusiveConstPtr<TScreen> whole(new TScreen({{ 3, 10 }, { 40, 70 }, { 80, 99 }})); - - { /* Check simple split and merge w/o gliding edges */ - - auto left = TScreen::Cut(whole, { 0, 33 }); - auto right = TScreen::Cut(whole, { 33, 666 }); - auto join = TScreen::Join(left, right); - - UNIT_ASSERT(join && join->Cmp(*whole)); - } - - { /* Check simple split and join to the same screen */ - auto left = TScreen::Cut(whole, { 0, 55 }); - auto right = TScreen::Cut(whole, { 55, 666 }); - auto join = TScreen::Join(left, right); - - UNIT_ASSERT(join && join->Cmp(*whole)); - } - - { /* Check trivialiry of joining to the complete hole */ - - auto *left = new TScreen({ THole(0, 666) }); - auto *right = new TScreen({ THole(666, Max<TRowId>()) }); - - UNIT_ASSERT(TScreen::Join(left, right) == nullptr); - } - } - + + { /* Check simple split and merge w/o gliding edges */ + + auto left = TScreen::Cut(whole, { 0, 33 }); + auto right = TScreen::Cut(whole, { 33, 666 }); + auto join = TScreen::Join(left, right); + + UNIT_ASSERT(join && join->Cmp(*whole)); + } + + { /* Check simple split and join to the same screen */ + auto left = TScreen::Cut(whole, { 0, 55 }); + auto right = TScreen::Cut(whole, { 55, 666 }); + auto join = TScreen::Join(left, right); + + UNIT_ASSERT(join && join->Cmp(*whole)); + } + + { /* Check trivialiry of joining to the complete hole */ + + auto *left = new TScreen({ THole(0, 666) }); + auto *right = new TScreen({ THole(666, Max<TRowId>()) }); + + UNIT_ASSERT(TScreen::Join(left, right) == nullptr); + } + } + Y_UNIT_TEST(Sequential) - { - using namespace NTable::NTest; - + { + using namespace NTable::NTest; + NTest::TCurtain cook(Eggs0()); - - for (size_t off = 0; off < 16; off++) { - const size_t len = off << 8; - + + for (size_t off = 0; off < 16; off++) { + const size_t len = off << 8; + auto cu0 = cook.Make(Mass0().Saved, 3, (7 + (len >> 1) - 3) >> 1); auto cu = cook.Make(Mass0().Saved, 7 + (len >> 1), 13 + len); Y_VERIFY(cu0.End != cu.Begin); - + for (int joined = 0; joined < 2; ++joined) { auto screen = joined ? TScreen::Join(cu0.Screen, cu.Screen) : cu.Screen; - auto slice = TSlicer(*Eggs0().Scheme).Cut(*Eggs0().Lone(), *screen); - + auto slice = TSlicer(*Eggs0().Scheme).Cut(*Eggs0().Lone(), *screen); + { /*_ Check that simple screen is really working */ - TCheckIt iter(Eggs0(), { new TForwardEnv(1, 2), 3 }, slice); - + TCheckIt iter(Eggs0(), { new TForwardEnv(1, 2), 3 }, slice); + iter.To(4 + (off << 2) + (joined << 1)) .Seek({}, ESeek::Lower); - + if (joined) { iter.Is(cu0.Begin, cu0.End); } - + iter.Is(cu.Begin, cu.End); - + iter.Is(EReady::Gone); } - + { /* Check working partial screening on hole edge */ - TCheckIt iter(Eggs0(), { new TForwardEnv(1, 2), 3 }, slice); - + TCheckIt iter(Eggs0(), { new TForwardEnv(1, 2), 3 }, slice); + auto it = cu.Begin + (len >> 2); iter.To(5 + (off << 2) + (joined << 1)) @@ -129,100 +129,100 @@ Y_UNIT_TEST_SUITE(TScreen) { iter.Is(EReady::Gone); } - } - } - } - + } + } + } + Y_UNIT_TEST(Random) - { - using namespace NTable::NTest; - + { + using namespace NTable::NTest; + NTest::TCurtain cook(Eggs0()); - - TMersenne<ui64> rnd; - - for (size_t z = 0; z < 8192; z++) { + + TMersenne<ui64> rnd; + + for (size_t z = 0; z < 8192; z++) { auto cu = cook.Make(Mass0().Saved, rnd, 8192); - auto slice = TSlicer(*Eggs0().Scheme).Cut(*Eggs0().Lone(), *cu.Screen); - - TCheckIt iter(Eggs0(), { new TTestEnv, 0 }, slice); - - iter.To(4 + z); - - if (rnd.Uniform(0, 2) == 0) { + auto slice = TSlicer(*Eggs0().Scheme).Cut(*Eggs0().Lone(), *cu.Screen); + + TCheckIt iter(Eggs0(), { new TTestEnv, 0 }, slice); + + iter.To(4 + z); + + if (rnd.Uniform(0, 2) == 0) { auto it = Mass0().Saved.AnyIn(rnd, cu.Begin, cu.End); - - iter.Seek(*it, ESeek::Exact).Is(*it, true); - iter.Seek(*it, ESeek::Lower).Is(*it, true); - } else { + + iter.Seek(*it, ESeek::Exact).Is(*it, true); + iter.Seek(*it, ESeek::Lower).Is(*it, true); + } else { auto it = Mass0().Saved.AnyOff(rnd, cu.Begin, cu.End); - - iter.Seek(*it, ESeek::Exact).Is(EReady::Gone); - - if (it < cu.Begin) { - iter.Seek(*it, ESeek::Lower).Is(*cu.Begin); - iter.Seek(*it, ESeek::Upper).Is(*cu.Begin); - } else if (it >= cu.End) { - iter.Seek(*it, ESeek::Lower).Is(EReady::Gone); - iter.Seek(*it, ESeek::Upper).Is(EReady::Gone); - } else { - Y_FAIL("Got AnyOff row within the range"); - } - } - } - } - + + iter.Seek(*it, ESeek::Exact).Is(EReady::Gone); + + if (it < cu.Begin) { + iter.Seek(*it, ESeek::Lower).Is(*cu.Begin); + iter.Seek(*it, ESeek::Upper).Is(*cu.Begin); + } else if (it >= cu.End) { + iter.Seek(*it, ESeek::Lower).Is(EReady::Gone); + iter.Seek(*it, ESeek::Upper).Is(EReady::Gone); + } else { + Y_FAIL("Got AnyOff row within the range"); + } + } + } + } + Y_UNIT_TEST(Shrink) - { - using namespace NTable::NTest; - + { + using namespace NTable::NTest; + const TRowTool tool(*Eggs0().Scheme); - TAutoPtr<TTestEnv> env = new TTestEnv; + TAutoPtr<TTestEnv> env = new TTestEnv; TShrink shrink(env.Get(), Eggs0().Scheme->Keys); - - { /* shrink to empty set shoudn't produce any results */ + + { /* shrink to empty set shoudn't produce any results */ const auto key = tool.LookupKey(Mass0().Saved[0]); - + shrink.Put(Eggs0().ToPartView(), { }, key); - + UNIT_ASSERT(shrink.Skipped == 0 && shrink.PartView.size() == 0); - } - - { /* shrink to the entire set should leave part as is */ + } + + { /* shrink to the entire set should leave part as is */ const auto key = tool.LookupKey(Mass0().Saved[0]); - + shrink.Put(Eggs0().ToPartView(), key, { }); - + UNIT_ASSERT(shrink.Skipped == 0 && shrink.PartView.size() == 1); - + const auto partView = std::move(shrink.PartView[0]); - + UNIT_ASSERT(!partView.Screen && partView.Part.Get() == Eggs0().At(0).Get()); - } - - { /* basic regular shrink of some trivial subset */ - const auto hole = TScreen::THole(666, 891); - + } + + { /* basic regular shrink of some trivial subset */ + const auto hole = TScreen::THole(666, 891); + auto begin = tool.LookupKey(Mass0().Saved[hole.Begin]); auto end = tool.LookupKey(Mass0().Saved[hole.End]); - + shrink.Put(Eggs0().ToPartView(), begin, end); - + UNIT_ASSERT(shrink.Skipped == 0 && shrink.PartView.size() == 2); - + const auto scr = std::move(shrink.PartView[1].Screen); const auto run = std::move(shrink.PartView[1].Slices); - + UNIT_ASSERT(scr && shrink.PartView[1].Part.Get() == Eggs0().At(0).Get()); - UNIT_ASSERT(scr->Size() == 1 && scr->Hole(0) == hole); + UNIT_ASSERT(scr->Size() == 1 && scr->Hole(0) == hole); UNIT_ASSERT(run && run->size() == 1); UNIT_ASSERT(run->front().FirstRowId == hole.Begin); UNIT_ASSERT(run->front().FirstInclusive == true); UNIT_ASSERT(run->back().LastRowId == hole.End); UNIT_ASSERT(run->back().LastInclusive == false); - } - } - + } + } + Y_UNIT_TEST(Cook) { TScreen::TCook cook; @@ -255,7 +255,7 @@ Y_UNIT_TEST_SUITE(TScreen) { } } -} - -} -} +} + +} +} diff --git a/ydb/core/tablet_flat/ut/ut_self.cpp b/ydb/core/tablet_flat/ut/ut_self.cpp index 5cf8efb163..d63d5e727f 100644 --- a/ydb/core/tablet_flat/ut/ut_self.cpp +++ b/ydb/core/tablet_flat/ut/ut_self.cpp @@ -1,57 +1,57 @@ #include <ydb/core/tablet_flat/test/libs/rows/layout.h> #include <ydb/core/tablet_flat/test/libs/rows/cook.h> #include <ydb/core/tablet_flat/test/libs/rows/tool.h> - + #include <library/cpp/testing/unittest/registar.h> - -namespace NKikimr { -namespace NTable { - + +namespace NKikimr { +namespace NTable { + Y_UNIT_TEST_SUITE(Self) { - + Y_UNIT_TEST(Literals) - { - using namespace NTest; - using TPut = NTest::TCookRow; - - TLayoutCook lay; - - lay - .Col(0, 0, NScheme::NTypeIds::String) - .Col(0, 1, NScheme::NTypeIds::Uint32) - .Col(0, 2, NScheme::NTypeIds::Double) - .Col(0, 3, NScheme::NTypeIds::Bool) - .Key({0, 1}); - - auto put = *TPut().Do(0, "foo").Do<double>(2, 3.14).Do<ui32>(1, 42); - auto natTail = *TNatural(*lay).Col("foo", 42_u32, 3.14); - auto natNull = *TNatural(*lay).Col("foo", 42_u32, 3.14, nullptr); - - /*_ Different binary rows representations should have the same - textual output. Along with check that test rows wrappers - really cooks materialized rows with expected result. - */ - - auto *lit = "(String : foo, Uint32 : 42, Double : 3.14, Bool : NULL)"; - - const auto check = [=](const TString &sample) - { - if (sample != lit) { - Cerr - << "Row validation failed: " - << NUnitTest::ColoredDiff(lit, sample) - << Endl; - - UNIT_ASSERT(false); - } - }; - - check(TRowTool(*lay).Describe(put)); - check(TRowTool(*lay).Describe(natTail)); - check(TRowTool(*lay).Describe(natNull)); - } - -}; - -} -} + { + using namespace NTest; + using TPut = NTest::TCookRow; + + TLayoutCook lay; + + lay + .Col(0, 0, NScheme::NTypeIds::String) + .Col(0, 1, NScheme::NTypeIds::Uint32) + .Col(0, 2, NScheme::NTypeIds::Double) + .Col(0, 3, NScheme::NTypeIds::Bool) + .Key({0, 1}); + + auto put = *TPut().Do(0, "foo").Do<double>(2, 3.14).Do<ui32>(1, 42); + auto natTail = *TNatural(*lay).Col("foo", 42_u32, 3.14); + auto natNull = *TNatural(*lay).Col("foo", 42_u32, 3.14, nullptr); + + /*_ Different binary rows representations should have the same + textual output. Along with check that test rows wrappers + really cooks materialized rows with expected result. + */ + + auto *lit = "(String : foo, Uint32 : 42, Double : 3.14, Bool : NULL)"; + + const auto check = [=](const TString &sample) + { + if (sample != lit) { + Cerr + << "Row validation failed: " + << NUnitTest::ColoredDiff(lit, sample) + << Endl; + + UNIT_ASSERT(false); + } + }; + + check(TRowTool(*lay).Describe(put)); + check(TRowTool(*lay).Describe(natTail)); + check(TRowTool(*lay).Describe(natNull)); + } + +}; + +} +} diff --git a/ydb/core/tablet_flat/ut/ut_slice.cpp b/ydb/core/tablet_flat/ut/ut_slice.cpp index 5833066aad..a45254c425 100644 --- a/ydb/core/tablet_flat/ut/ut_slice.cpp +++ b/ydb/core/tablet_flat/ut/ut_slice.cpp @@ -1,7 +1,7 @@ #include <ydb/core/tablet_flat/flat_part_slice.h> #include <ydb/core/tablet_flat/flat_part_overlay.h> #include <ydb/core/tablet_flat/util_fmt_desc.h> - + #include <library/cpp/testing/unittest/registar.h> namespace NKikimr { diff --git a/ydb/core/tablet_flat/ut/ut_slice_loader.cpp b/ydb/core/tablet_flat/ut/ut_slice_loader.cpp index 822319b533..e408d01bf2 100644 --- a/ydb/core/tablet_flat/ut/ut_slice_loader.cpp +++ b/ydb/core/tablet_flat/ut/ut_slice_loader.cpp @@ -41,14 +41,14 @@ namespace { const NTest::TPartEggs& Eggs0() { static const NTest::TPartEggs eggs0 = NTest::TPartCook::Make(Mass0(), PageConf()); - UNIT_ASSERT_C(eggs0.Parts.size() == 1, - "Unexpected " << eggs0.Parts.size() << " results"); + UNIT_ASSERT_C(eggs0.Parts.size() == 1, + "Unexpected " << eggs0.Parts.size() << " results"); return eggs0; } const TIntrusiveConstPtr<NTest::TPartStore>& Part0() { - static const auto part = Eggs0().At(0); + static const auto part = Eggs0().At(0); return part; } @@ -73,8 +73,8 @@ namespace { NPageCollection::TInfo Page(ui32 page) const noexcept override { const auto array = Part->Store->PageCollectionArray(Room); - - return { ui32(array.at(page).size()), ui32(EPage::Undef) }; + + return { ui32(array.at(page).size()), ui32(EPage::Undef) }; } NPageCollection::TBorder Bounds(ui32) const noexcept override @@ -102,65 +102,65 @@ namespace { ui32 Room; }; - struct TCheckResult { - size_t Pages; + struct TCheckResult { + size_t Pages; TIntrusivePtr<TSlices> Run; }; void VerifyRunOrder(TIntrusiveConstPtr<TSlices> run, const TKeyNulls& keys) { const TSlice* prev = nullptr; - for (auto& slice : *run) { - if (prev) { + for (auto& slice : *run) { + if (prev) { UNIT_ASSERT_C(TSlice::LessByRowId(*prev, slice), - "Two slices intersect by row ids: " << - NFmt::Do(*prev) << " and " << NFmt::Do(slice)); + "Two slices intersect by row ids: " << + NFmt::Do(*prev) << " and " << NFmt::Do(slice)); UNIT_ASSERT_C(TSlice::LessByKey(*prev, slice, keys), - "Two slices intersect by keys: " << - NFmt::Do(*prev) << " and " << NFmt::Do(slice)); - } - prev = &slice; - } - } + "Two slices intersect by keys: " << + NFmt::Do(*prev) << " and " << NFmt::Do(slice)); + } + prev = &slice; + } + } TCheckResult RunLoaderTest(TIntrusiveConstPtr<NTest::TPartStore> part, TIntrusiveConstPtr<TScreen> screen) - { - TCheckResult result; - + { + TCheckResult result; + TIntrusiveConstPtr<NPageCollection::IPageCollection> pageCollection = new TTestPartPageCollection(part, 0); TKeysEnv env(part.Get(), new TCache(pageCollection)); - TKeysLoader loader(part.Get(), &env); + TKeysLoader loader(part.Get(), &env); - if (result.Run = loader.Do(screen)) { - env.Check(false); /* On success there shouldn't be left loads */ - result.Pages = 0; - } else if (auto fetch = env.GetFetches()) { + if (result.Run = loader.Do(screen)) { + env.Check(false); /* On success there shouldn't be left loads */ + result.Pages = 0; + } else if (auto fetch = env.GetFetches()) { UNIT_ASSERT_C(fetch->PageCollection.Get() == pageCollection.Get(), "TLoader wants to fetch from an unexpected pageCollection"); - UNIT_ASSERT_C(fetch->Pages, "TLoader wants a fetch, but there are no pages"); - result.Pages = fetch->Pages.size(); + UNIT_ASSERT_C(fetch->Pages, "TLoader wants a fetch, but there are no pages"); + result.Pages = fetch->Pages.size(); - for (auto pageId : fetch->Pages) { + for (auto pageId : fetch->Pages) { auto* page = part->Store->GetPage(0, pageId); UNIT_ASSERT_C(page, "TLoader wants a missing page " << pageId); - + env.Save(fetch->Cookie, { pageId, TSharedPageRef::MakePrivate(*page) }); } - result.Run = loader.Do(screen); - UNIT_ASSERT_C(result.Run, "TKeysLoader wants to do unexpected fetches"); - env.Check(false); /* On success there shouldn't be left loads */ + result.Run = loader.Do(screen); + UNIT_ASSERT_C(result.Run, "TKeysLoader wants to do unexpected fetches"); + env.Check(false); /* On success there shouldn't be left loads */ } else { - UNIT_ASSERT_C(false, "TKeysLoader was stalled"); + UNIT_ASSERT_C(false, "TKeysLoader was stalled"); } - const auto scrSize = screen ? screen->Size() : 1; - - UNIT_ASSERT_C(result.Run->size() == scrSize, - "Restored slice bounds have " << result.Run->size() << - " slices, expected to have " << scrSize); - VerifyRunOrder(result.Run, *Eggs0().Scheme->Keys); - + const auto scrSize = screen ? screen->Size() : 1; + + UNIT_ASSERT_C(result.Run->size() == scrSize, + "Restored slice bounds have " << result.Run->size() << + " slices, expected to have " << scrSize); + VerifyRunOrder(result.Run, *Eggs0().Scheme->Keys); + return result; } @@ -169,9 +169,9 @@ namespace { Y_UNIT_TEST_SUITE(TPartSliceLoader) { Y_UNIT_TEST(RestoreMissingSlice) { - auto result = RunLoaderTest(Part0(), nullptr); - UNIT_ASSERT_C(result.Pages == 0, - "Restoring slice bounds needed " << result.Pages << " extra pages"); + auto result = RunLoaderTest(Part0(), nullptr); + UNIT_ASSERT_C(result.Pages == 0, + "Restoring slice bounds needed " << result.Pages << " extra pages"); } Y_UNIT_TEST(RestoreMissingSliceFullScreen) { @@ -193,9 +193,9 @@ Y_UNIT_TEST_SUITE(TPartSliceLoader) { "Generated screen has " << holes.size() << " intervals"); screen = new TScreen(std::move(holes)); } - auto result = RunLoaderTest(Part0(), screen); - UNIT_ASSERT_C(result.Pages == 0, - "Restoring slice bounds needed " << result.Pages << " extra pages"); + auto result = RunLoaderTest(Part0(), screen); + UNIT_ASSERT_C(result.Pages == 0, + "Restoring slice bounds needed " << result.Pages << " extra pages"); } Y_UNIT_TEST(RestoreFromScreenIndexKeys) { @@ -218,9 +218,9 @@ Y_UNIT_TEST_SUITE(TPartSliceLoader) { holes.back().End = Max<TRowId>(); screen = new TScreen(std::move(holes)); } - auto result = RunLoaderTest(Part0(), screen); - UNIT_ASSERT_C(result.Pages == 0, - "Restoring slice bounds needed " << result.Pages << " extra pages"); + auto result = RunLoaderTest(Part0(), screen); + UNIT_ASSERT_C(result.Pages == 0, + "Restoring slice bounds needed " << result.Pages << " extra pages"); } Y_UNIT_TEST(RestoreFromScreenDataKeys) { @@ -246,9 +246,9 @@ Y_UNIT_TEST_SUITE(TPartSliceLoader) { UNIT_ASSERT_C(holes.size() > 2, "Generated screen has only " << holes.size() << " intervals"); screen = new TScreen(std::move(holes)); } - auto result = RunLoaderTest(Part0(), screen); - UNIT_ASSERT_C(result.Pages == screen->Size(), - "Restoring slice bounds needed " << result.Pages << + auto result = RunLoaderTest(Part0(), screen); + UNIT_ASSERT_C(result.Pages == screen->Size(), + "Restoring slice bounds needed " << result.Pages << " extra pages, expected " << screen->Size()); } } diff --git a/ydb/core/tablet_flat/ut/ya.make b/ydb/core/tablet_flat/ut/ya.make index fd66d04202..79b76b7df4 100644 --- a/ydb/core/tablet_flat/ut/ya.make +++ b/ydb/core/tablet_flat/ut/ya.make @@ -17,8 +17,8 @@ SRCS( datetime_ut.cpp decimal_ut.cpp flat_cxx_database_ut.cpp - ut_db_iface.cpp - ut_db_scheme.cpp + ut_db_iface.cpp + ut_db_scheme.cpp flat_executor_ut.cpp flat_executor_database_ut.cpp flat_executor_gclogic_ut.cpp @@ -30,35 +30,35 @@ SRCS( flat_test_db.cpp flat_test_db_helpers.h shared_handle_ut.cpp - ut_self.cpp - ut_iterator.cpp - ut_memtable.cpp - ut_sausage.cpp + ut_self.cpp + ut_iterator.cpp + ut_memtable.cpp + ut_sausage.cpp ut_comp_gen.cpp ut_comp_shard.cpp - ut_compaction.cpp + ut_compaction.cpp ut_compaction_multi.cpp - ut_charge.cpp - ut_part.cpp + ut_charge.cpp + ut_part.cpp ut_part_multi.cpp - ut_proto.cpp - ut_pages.cpp - ut_redo.cpp + ut_proto.cpp + ut_pages.cpp + ut_redo.cpp ut_rename_table_column.cpp - ut_other.cpp - ut_forward.cpp - ut_screen.cpp - ut_bloom.cpp + ut_other.cpp + ut_forward.cpp + ut_screen.cpp + ut_bloom.cpp ut_slice.cpp ut_slice_loader.cpp ut_versions.cpp ) -RESOURCE( +RESOURCE( ../test/data/002_full_part.pages abi/002_full_part.pages ../test/data/008_basics_db.redo abi/008_basics_db.redo -) - +) + PEERDIR( library/cpp/resource ydb/core/scheme diff --git a/ydb/core/tablet_flat/util_basics.h b/ydb/core/tablet_flat/util_basics.h index 3da3f7dfcc..cc2d728224 100644 --- a/ydb/core/tablet_flat/util_basics.h +++ b/ydb/core/tablet_flat/util_basics.h @@ -1,10 +1,10 @@ -#pragma once - -#include <util/generic/ptr.h> -#include <util/generic/array_ref.h> - -namespace NKikimr { +#pragma once + +#include <util/generic/ptr.h> +#include <util/generic/array_ref.h> + +namespace NKikimr { struct IDestructable { virtual ~IDestructable() = default; - }; -} + }; +} diff --git a/ydb/core/tablet_flat/util_deref.h b/ydb/core/tablet_flat/util_deref.h index 49d02d690a..9c2c72300c 100644 --- a/ydb/core/tablet_flat/util_deref.h +++ b/ydb/core/tablet_flat/util_deref.h @@ -1,42 +1,42 @@ -#pragma once - -#include <util/system/compiler.h> -#include <type_traits> - -namespace NKikimr { - - template<typename T> - using TStdLayout = std::enable_if_t<std::is_standard_layout<T>::value, T>; - +#pragma once + +#include <util/system/compiler.h> +#include <type_traits> + +namespace NKikimr { + + template<typename T> + using TStdLayout = std::enable_if_t<std::is_standard_layout<T>::value, T>; + template<typename T> using TStdLayoutOrVoid = std::enable_if_t<std::is_standard_layout<T>::value || std::is_void<T>::value, T>; - template<typename T, typename = TStdLayout<T>> - struct TDeref { + template<typename T, typename = TStdLayout<T>> + struct TDeref { static constexpr const T* At(const void *ptr, size_t off = 0) noexcept { - return + return reinterpret_cast<const T*>(static_cast<const char*>(ptr) + off); - } - + } + static constexpr T* At(void *ptr, size_t off = 0) noexcept { return reinterpret_cast<T*>(static_cast<char*>(ptr) + off); - } - + } + static inline T Copy(const void *ptr, size_t off = 0) noexcept - { - T object; + { + T object; memcpy(&object, static_cast<const char*>(ptr) + off, sizeof(T)); - return object; - } - }; - - template<typename T, typename = TStdLayout<T>> - struct TStdPad { - inline T operator*() const { - return TDeref<T>::Copy(&Pad, 0); - } - - const char Pad[sizeof(T)]; + return object; + } + }; + + template<typename T, typename = TStdLayout<T>> + struct TStdPad { + inline T operator*() const { + return TDeref<T>::Copy(&Pad, 0); + } + + const char Pad[sizeof(T)]; } Y_PACKED; - -} + +} diff --git a/ydb/core/tablet_flat/util_fmt_abort.h b/ydb/core/tablet_flat/util_fmt_abort.h index ffab6fde85..d23bbaeae7 100644 --- a/ydb/core/tablet_flat/util_fmt_abort.h +++ b/ydb/core/tablet_flat/util_fmt_abort.h @@ -1,41 +1,41 @@ -#pragma once - -#include <util/stream/str.h> -#include <util/system/yassert.h> -#include <util/system/src_root.h> - -namespace NKikimr { -namespace NUtil { - - class TFail : public TStringOutput { - public: - using TBuf = NPrivate::TStaticBuf; - - TFail(TBuf fname, ui32 line, const char *func) - : TStringOutput(Raw) - , File(fname) - , Func(func) - , Line(line) - { - Raw.reserve(192); - } - +#pragma once + +#include <util/stream/str.h> +#include <util/system/yassert.h> +#include <util/system/src_root.h> + +namespace NKikimr { +namespace NUtil { + + class TFail : public TStringOutput { + public: + using TBuf = NPrivate::TStaticBuf; + + TFail(TBuf fname, ui32 line, const char *func) + : TStringOutput(Raw) + , File(fname) + , Func(func) + , Line(line) + { + Raw.reserve(192); + } + [[noreturn]] ~TFail() - { - ::NPrivate::Panic(File, Line, Func, nullptr, "%s\n", Raw.data()); - } - - private: - const TBuf File; - const char *Func = nullptr; - const int Line = Max<int>(); - TString Raw; - }; - -} -} - -#define Y_Fail_Detailed()\ - NKikimr::NUtil::TFail logl(__SOURCE_FILE_IMPL__, __LINE__, __FUNCTION__) - -#define Y_Fail(stream) do{ Y_Fail_Detailed(); logl << stream; } while(false) + { + ::NPrivate::Panic(File, Line, Func, nullptr, "%s\n", Raw.data()); + } + + private: + const TBuf File; + const char *Func = nullptr; + const int Line = Max<int>(); + TString Raw; + }; + +} +} + +#define Y_Fail_Detailed()\ + NKikimr::NUtil::TFail logl(__SOURCE_FILE_IMPL__, __LINE__, __FUNCTION__) + +#define Y_Fail(stream) do{ Y_Fail_Detailed(); logl << stream; } while(false) diff --git a/ydb/core/tablet_flat/util_fmt_basic.h b/ydb/core/tablet_flat/util_fmt_basic.h index 1dad4a2a9a..4316d65ae7 100644 --- a/ydb/core/tablet_flat/util_fmt_basic.h +++ b/ydb/core/tablet_flat/util_fmt_basic.h @@ -1,67 +1,67 @@ -#pragma once - -#include "util_fmt_desc.h" - -namespace NKikimr { -namespace NFmt { - - struct TDelay { - TDelay(TDuration val): Val(val) { } - - TOut& Do(TOut &out) const noexcept - { - const ui64 grid[] = { - 60ull, /* minute */ - 3600ull, /* hour */ - 86400ull, /* day */ - 604800ull, /* week */ - 8553600ull, /* 99 days */ - 31557600ull, /* Julian 365.25 days year */ - 3155760000ull, /* Julian 100 years century */ - }; - - if (Val == TDuration::Max()) return out << "undef~"; - - const auto secs = Val.Seconds(); - - if (secs < grid[0]) return Small(out, secs); - if (secs < grid[1]) return Large(out, secs, 'm', grid[0]); - if (secs < grid[2]) return Large(out, secs, 'h', grid[1]); - if (secs < grid[4]) return Large(out, secs, 'd', grid[2]); - if (secs < grid[5]) return Large(out, secs, 'w', grid[3]); - if (secs < grid[6]) return Large(out, secs, 'y', grid[5]); - - return Large(out, secs, 'c', grid[6]); - } - - protected: - inline TOut& Small(TOut &out, ui64 secs) const noexcept - { - char ln_[8]; - - auto ms = Val.MilliSeconds() - secs * 1000; - - snprintf(ln_, sizeof(ln_), "%zu.%.03zu", secs, ms); - - return ln_[5] = 's', out.Write(ln_, 6), out; - } - - TOut& Large(TOut &out, double sec, char suff, ui64 base) const - { - char ln_[16]; - - snprintf(ln_, sizeof(ln_), "%.03f", sec / base); - - return ln_[5] = suff, out.Write(ln_, 6), out; - } - - TDuration Val; - }; - - inline TOut& operator<<(TOut &out, const NFmt::TDelay &print) - { - return print.Do(out); - } - -} -} +#pragma once + +#include "util_fmt_desc.h" + +namespace NKikimr { +namespace NFmt { + + struct TDelay { + TDelay(TDuration val): Val(val) { } + + TOut& Do(TOut &out) const noexcept + { + const ui64 grid[] = { + 60ull, /* minute */ + 3600ull, /* hour */ + 86400ull, /* day */ + 604800ull, /* week */ + 8553600ull, /* 99 days */ + 31557600ull, /* Julian 365.25 days year */ + 3155760000ull, /* Julian 100 years century */ + }; + + if (Val == TDuration::Max()) return out << "undef~"; + + const auto secs = Val.Seconds(); + + if (secs < grid[0]) return Small(out, secs); + if (secs < grid[1]) return Large(out, secs, 'm', grid[0]); + if (secs < grid[2]) return Large(out, secs, 'h', grid[1]); + if (secs < grid[4]) return Large(out, secs, 'd', grid[2]); + if (secs < grid[5]) return Large(out, secs, 'w', grid[3]); + if (secs < grid[6]) return Large(out, secs, 'y', grid[5]); + + return Large(out, secs, 'c', grid[6]); + } + + protected: + inline TOut& Small(TOut &out, ui64 secs) const noexcept + { + char ln_[8]; + + auto ms = Val.MilliSeconds() - secs * 1000; + + snprintf(ln_, sizeof(ln_), "%zu.%.03zu", secs, ms); + + return ln_[5] = 's', out.Write(ln_, 6), out; + } + + TOut& Large(TOut &out, double sec, char suff, ui64 base) const + { + char ln_[16]; + + snprintf(ln_, sizeof(ln_), "%.03f", sec / base); + + return ln_[5] = suff, out.Write(ln_, 6), out; + } + + TDuration Val; + }; + + inline TOut& operator<<(TOut &out, const NFmt::TDelay &print) + { + return print.Do(out); + } + +} +} diff --git a/ydb/core/tablet_flat/util_fmt_desc.h b/ydb/core/tablet_flat/util_fmt_desc.h index 00e76fd47a..15fc9f4602 100644 --- a/ydb/core/tablet_flat/util_fmt_desc.h +++ b/ydb/core/tablet_flat/util_fmt_desc.h @@ -1,131 +1,131 @@ -#pragma once - -#include <util/stream/str.h> - -#include <tuple> -#include <utility> - -namespace NKikimr { - - namespace NHelp { - - template<size_t ...> struct TIndexes { }; - +#pragma once + +#include <util/stream/str.h> + +#include <tuple> +#include <utility> + +namespace NKikimr { + + namespace NHelp { + + template<size_t ...> struct TIndexes { }; + template<size_t N, size_t ...Obtained> struct TGenIx : TGenIx<N - 1, N - 1, Obtained...> { }; - + template<size_t ...Obtained> struct TGenIx<0, Obtained...> - { + { using Type = TIndexes<Obtained...>; - }; - - template<typename TAr1, typename TAr2> - static inline void IsArrSized(const TAr1&, const TAr2&) - { - constexpr auto nums = std::tuple_size<TAr1>::value; - - static_assert(nums == std::tuple_size<TAr1>::value, ""); - } - } - - namespace NFmt { - using TOut = IOutputStream; - - template<typename Type> - struct TPut { - - template<typename ...TArg> - static void Do(TOut &out, const Type *ob, TArg&& ... args) - { - ob->Describe(out, std::forward<TArg>(args)...); - } - }; - - template<typename Type, typename ...TArg> - struct TDesc { - TDesc(const Type *ob, TArg&& ...args) - : Ob(ob), Args(std::forward<TArg>(args)...) { } - - inline TOut& Do(TOut &out) const noexcept - { - using Tups = std::tuple_size<std::tuple<TArg...>>; - - return Do(out, typename NHelp::TGenIx<Tups::value>::Type()); - } - - private: - template<size_t ... Index> - inline TOut& Do(TOut &out, NHelp::TIndexes<Index...>) const - { - if (Ob == nullptr) return out << "{nil}"; - - NFmt::TPut<Type>::Do(out, Ob, std::get<Index>(Args)...); - - return out; - } - - const Type *Ob = nullptr; - std::tuple<TArg...> Args; - }; - - template<typename TIter> - struct TArr { - TArr(TIter begin, TIter end) : Begin(begin), End(end) { } - - TOut& Do(TOut &out) const noexcept - { - out << "{ "; - - for (auto it = Begin; it != End; ++it) - out << (it == Begin ? "" : ", ") << *it; - - return out << (Begin == End ? "}" : " }"); - } - - private: - const TIter Begin, End; - }; - - template<typename Type, typename ...TArg> - inline TDesc<Type, TArg...> If(const Type *ob, TArg&& ...args) - { - return { ob, std::forward<TArg>(args)... }; - } - - template<typename Type, typename ...TArg> - inline TDesc<Type, TArg...> Do(const Type &ob, TArg&& ...args) - { - return { &ob, std::forward<TArg>(args)... }; - } - - template<typename Type, typename ...TArg> - inline TString Ln(const Type &ob, TArg&& ...args) noexcept - { - TStringStream ss; - - TDesc<Type, TArg...>(&ob, std::forward<TArg>(args)...).Do(ss); - - return ss.Str(); - } - - template<typename Type, - typename It = decltype(std::declval<const Type>().begin())> - inline TArr<It> Arr(const Type &arr) noexcept - { - return { arr.begin(), arr.end() }; - } - - template<typename Type, typename ...TArg> - inline TOut& operator<<(TOut &out, const TDesc<Type, TArg...> &wrap) - { - return wrap.Do(out); - } - - template<typename Type> - inline TOut& operator<<(TOut &out, const TArr<Type> &wrap) - { - return wrap.Do(out); - } - } -} + }; + + template<typename TAr1, typename TAr2> + static inline void IsArrSized(const TAr1&, const TAr2&) + { + constexpr auto nums = std::tuple_size<TAr1>::value; + + static_assert(nums == std::tuple_size<TAr1>::value, ""); + } + } + + namespace NFmt { + using TOut = IOutputStream; + + template<typename Type> + struct TPut { + + template<typename ...TArg> + static void Do(TOut &out, const Type *ob, TArg&& ... args) + { + ob->Describe(out, std::forward<TArg>(args)...); + } + }; + + template<typename Type, typename ...TArg> + struct TDesc { + TDesc(const Type *ob, TArg&& ...args) + : Ob(ob), Args(std::forward<TArg>(args)...) { } + + inline TOut& Do(TOut &out) const noexcept + { + using Tups = std::tuple_size<std::tuple<TArg...>>; + + return Do(out, typename NHelp::TGenIx<Tups::value>::Type()); + } + + private: + template<size_t ... Index> + inline TOut& Do(TOut &out, NHelp::TIndexes<Index...>) const + { + if (Ob == nullptr) return out << "{nil}"; + + NFmt::TPut<Type>::Do(out, Ob, std::get<Index>(Args)...); + + return out; + } + + const Type *Ob = nullptr; + std::tuple<TArg...> Args; + }; + + template<typename TIter> + struct TArr { + TArr(TIter begin, TIter end) : Begin(begin), End(end) { } + + TOut& Do(TOut &out) const noexcept + { + out << "{ "; + + for (auto it = Begin; it != End; ++it) + out << (it == Begin ? "" : ", ") << *it; + + return out << (Begin == End ? "}" : " }"); + } + + private: + const TIter Begin, End; + }; + + template<typename Type, typename ...TArg> + inline TDesc<Type, TArg...> If(const Type *ob, TArg&& ...args) + { + return { ob, std::forward<TArg>(args)... }; + } + + template<typename Type, typename ...TArg> + inline TDesc<Type, TArg...> Do(const Type &ob, TArg&& ...args) + { + return { &ob, std::forward<TArg>(args)... }; + } + + template<typename Type, typename ...TArg> + inline TString Ln(const Type &ob, TArg&& ...args) noexcept + { + TStringStream ss; + + TDesc<Type, TArg...>(&ob, std::forward<TArg>(args)...).Do(ss); + + return ss.Str(); + } + + template<typename Type, + typename It = decltype(std::declval<const Type>().begin())> + inline TArr<It> Arr(const Type &arr) noexcept + { + return { arr.begin(), arr.end() }; + } + + template<typename Type, typename ...TArg> + inline TOut& operator<<(TOut &out, const TDesc<Type, TArg...> &wrap) + { + return wrap.Do(out); + } + + template<typename Type> + inline TOut& operator<<(TOut &out, const TArr<Type> &wrap) + { + return wrap.Do(out); + } + } +} diff --git a/ydb/core/tablet_flat/util_fmt_flat.h b/ydb/core/tablet_flat/util_fmt_flat.h index 6712563b19..d6f0b69ac0 100644 --- a/ydb/core/tablet_flat/util_fmt_flat.h +++ b/ydb/core/tablet_flat/util_fmt_flat.h @@ -1,27 +1,27 @@ -#pragma once - -#include "defs.h" -#include "util_fmt_desc.h" - -namespace NKikimr { - - namespace NFmt { - - struct TStamp { - TStamp(ui64 stamp) : Stamp(stamp) { } - - TOut& Do(TOut &out) const noexcept - { - return out << Stamp.Gen() << ":" << Stamp.Step(); - } - - private: - const NTable::TTxStamp Stamp; - }; - - inline TOut& operator<<(TOut &out, const NFmt::TStamp &print) - { - return print.Do(out); - } - } -} +#pragma once + +#include "defs.h" +#include "util_fmt_desc.h" + +namespace NKikimr { + + namespace NFmt { + + struct TStamp { + TStamp(ui64 stamp) : Stamp(stamp) { } + + TOut& Do(TOut &out) const noexcept + { + return out << Stamp.Gen() << ":" << Stamp.Step(); + } + + private: + const NTable::TTxStamp Stamp; + }; + + inline TOut& operator<<(TOut &out, const NFmt::TStamp &print) + { + return print.Do(out); + } + } +} diff --git a/ydb/core/tablet_flat/util_fmt_line.h b/ydb/core/tablet_flat/util_fmt_line.h index 1b399ccec3..60dcf25431 100644 --- a/ydb/core/tablet_flat/util_fmt_line.h +++ b/ydb/core/tablet_flat/util_fmt_line.h @@ -1,80 +1,80 @@ -#pragma once - -#include <util/stream/str.h> -#include <util/string/printf.h> - -namespace NKikimr { -namespace NUtil { - - enum class ELnLev { /* named values for NActors::NLog::TLevel */ - - /* value = (((major = (1 + prio)) << 8) | minor */ - - Abort = ((0 + 0) << 8) | 0, /* Urgently abort execution */ - - Emerg = ((1 + 0) << 8) | 0, - - Crit = ((1 + 2) << 8) | 1, - Error = ((1 + 3) << 8) | 0, - Warn = ((1 + 4) << 8) | 0, - - Info = ((1 + 6) << 8) | 0, - Inf1 = ((1 + 6) << 8) | 1, - Inf2 = ((1 + 6) << 8) | 2, - Inf3 = ((1 + 6) << 8) | 3, - - Debug = ((1 + 7) << 8) | 0, - Dbg01 = ((1 + 7) << 8) | 1, - Dbg02 = ((1 + 7) << 8) | 2, - Dbg03 = ((1 + 7) << 8) | 3, - }; - - class ILogged { - public: - virtual void LogLn(ELnLev, const TString&) const noexcept = 0; - }; - - class TLogLn : public TStringOutput { - public: - TLogLn(TLogLn &&line) - : TStringOutput(line.Raw) - , Logged(line.Logged) - , Level(line.Level) - , Raw(std::move(line.Raw)) - { - if (Logged) Raw.reserve(256); - } - - TLogLn(const ILogged *logged, ELnLev level) - : TStringOutput(Raw) - , Logged(logged) - , Level(level) - { - - } - - ~TLogLn() - { - if (Logged && Raw) - Logged->LogLn(Level, Raw); - } - - explicit operator bool() const noexcept - { - return Logged != nullptr; - } - - private: - const ILogged * Logged = nullptr; - const ELnLev Level = ELnLev::Debug; - TString Raw; - }; - - class ILogger { - public: - virtual ~ILogger() = default; - virtual TLogLn Log(ELnLev) const noexcept = 0; - }; - -} -} +#pragma once + +#include <util/stream/str.h> +#include <util/string/printf.h> + +namespace NKikimr { +namespace NUtil { + + enum class ELnLev { /* named values for NActors::NLog::TLevel */ + + /* value = (((major = (1 + prio)) << 8) | minor */ + + Abort = ((0 + 0) << 8) | 0, /* Urgently abort execution */ + + Emerg = ((1 + 0) << 8) | 0, + + Crit = ((1 + 2) << 8) | 1, + Error = ((1 + 3) << 8) | 0, + Warn = ((1 + 4) << 8) | 0, + + Info = ((1 + 6) << 8) | 0, + Inf1 = ((1 + 6) << 8) | 1, + Inf2 = ((1 + 6) << 8) | 2, + Inf3 = ((1 + 6) << 8) | 3, + + Debug = ((1 + 7) << 8) | 0, + Dbg01 = ((1 + 7) << 8) | 1, + Dbg02 = ((1 + 7) << 8) | 2, + Dbg03 = ((1 + 7) << 8) | 3, + }; + + class ILogged { + public: + virtual void LogLn(ELnLev, const TString&) const noexcept = 0; + }; + + class TLogLn : public TStringOutput { + public: + TLogLn(TLogLn &&line) + : TStringOutput(line.Raw) + , Logged(line.Logged) + , Level(line.Level) + , Raw(std::move(line.Raw)) + { + if (Logged) Raw.reserve(256); + } + + TLogLn(const ILogged *logged, ELnLev level) + : TStringOutput(Raw) + , Logged(logged) + , Level(level) + { + + } + + ~TLogLn() + { + if (Logged && Raw) + Logged->LogLn(Level, Raw); + } + + explicit operator bool() const noexcept + { + return Logged != nullptr; + } + + private: + const ILogged * Logged = nullptr; + const ELnLev Level = ELnLev::Debug; + TString Raw; + }; + + class ILogger { + public: + virtual ~ILogger() = default; + virtual TLogLn Log(ELnLev) const noexcept = 0; + }; + +} +} diff --git a/ydb/core/tablet_flat/util_fmt_logger.h b/ydb/core/tablet_flat/util_fmt_logger.h index 784e1795fd..003f1efe0c 100644 --- a/ydb/core/tablet_flat/util_fmt_logger.h +++ b/ydb/core/tablet_flat/util_fmt_logger.h @@ -1,72 +1,72 @@ -#pragma once - -#include "util_fmt_line.h" - +#pragma once + +#include "util_fmt_line.h" + #include <ydb/core/base/appdata.h> #include <library/cpp/time_provider/time_provider.h> #include <library/cpp/actors/core/actorsystem.h> #include <library/cpp/actors/core/log_iface.h> - -namespace NKikimr { -namespace NUtil { - - class TLogger : private ILogged, public ILogger { - public: - using TSys = ::NActors::TActorSystem; - using EComp = ::NActors::NLog::EComponent; - using EPrio = ::NActors::NLog::EPrio; + +namespace NKikimr { +namespace NUtil { + + class TLogger : private ILogged, public ILogger { + public: + using TSys = ::NActors::TActorSystem; + using EComp = ::NActors::NLog::EComponent; + using EPrio = ::NActors::NLog::EPrio; using TPath = ::NActors::TActorId; - - TLogger(TSys *sys, EComp comp) - : Time(TAppData::TimeProvider.Get()) - , Sys(sys) - , Path(Sys->LoggerSettings()->LoggerActorId) - , Comp(comp) - { - - } - + + TLogger(TSys *sys, EComp comp) + : Time(TAppData::TimeProvider.Get()) + , Sys(sys) + , Path(Sys->LoggerSettings()->LoggerActorId) + , Comp(comp) + { + + } + TLogLn Log(ELnLev level_) const noexcept override - { - const NActors::NLog::TLevel level{ ui32(level_) }; - - const auto force = level.IsUrgentAbortion(); - const auto pass = ShouldLog(level.ToPrio(), level.Raw & 0xff); - - return { force || pass ? this : nullptr, level_ }; - } - - private: - bool ShouldLog(EPrio prio_, ui8 minor) const noexcept - { - /* Minor filtering isn't implemented in levle settings */ - - const auto raw = ui32(prio_) + (minor ? 1 : 0); - const auto prio = NActors::NLog::EPriority(raw); - const auto *conf = Sys ? Sys->LoggerSettings() : nullptr; - - return conf && conf->Satisfies(prio, Comp, 0ull); - } - + { + const NActors::NLog::TLevel level{ ui32(level_) }; + + const auto force = level.IsUrgentAbortion(); + const auto pass = ShouldLog(level.ToPrio(), level.Raw & 0xff); + + return { force || pass ? this : nullptr, level_ }; + } + + private: + bool ShouldLog(EPrio prio_, ui8 minor) const noexcept + { + /* Minor filtering isn't implemented in levle settings */ + + const auto raw = ui32(prio_) + (minor ? 1 : 0); + const auto prio = NActors::NLog::EPriority(raw); + const auto *conf = Sys ? Sys->LoggerSettings() : nullptr; + + return conf && conf->Satisfies(prio, Comp, 0ull); + } + void LogLn(ELnLev level, const TString &line) const noexcept override - { - /* Usage of time provider will be possible on complete migration - to this logger. Legacy macros based logging takes just Now(). - */ - - auto stamp = false ? Time->Now() : TInstant::Now(); - - auto *ev = new NLog::TEvLog(stamp, ui32(level), Comp, line); - - if (!Sys->Send(Path, ev)) - Y_FAIL("Cannot send NLog::TEvLog to logger actor"); - } - - private: - ITimeProvider * const Time = nullptr; - TSys * const Sys = nullptr; - const TPath Path; - const EComp Comp; - }; -} -} + { + /* Usage of time provider will be possible on complete migration + to this logger. Legacy macros based logging takes just Now(). + */ + + auto stamp = false ? Time->Now() : TInstant::Now(); + + auto *ev = new NLog::TEvLog(stamp, ui32(level), Comp, line); + + if (!Sys->Send(Path, ev)) + Y_FAIL("Cannot send NLog::TEvLog to logger actor"); + } + + private: + ITimeProvider * const Time = nullptr; + TSys * const Sys = nullptr; + const TPath Path; + const EComp Comp; + }; +} +} diff --git a/ydb/core/tablet_flat/ya.make b/ydb/core/tablet_flat/ya.make index 6b1226bf01..35e10811fc 100644 --- a/ydb/core/tablet_flat/ya.make +++ b/ydb/core/tablet_flat/ya.make @@ -7,7 +7,7 @@ OWNER( SRCS( defs.h - flat_boot_misc.cpp + flat_boot_misc.cpp flat_comp.cpp flat_comp_create.cpp flat_comp_gen.cpp @@ -15,8 +15,8 @@ SRCS( flat_cxx_database.h flat_database.cpp flat_database.h - flat_dbase_scheme.cpp - flat_dbase_apply.cpp + flat_dbase_scheme.cpp + flat_dbase_apply.cpp flat_exec_broker.cpp flat_exec_commit.cpp flat_exec_commit_mgr.cpp @@ -34,18 +34,18 @@ SRCS( flat_executor_db_mon.cpp flat_executor_gclogic.cpp flat_executor_gclogic.h - flat_bio_actor.cpp + flat_bio_actor.cpp flat_executor_snapshot.cpp flat_executor_txloglogic.cpp flat_executor_txloglogic.h flat_iterator.h flat_load_blob_queue.cpp - flat_mem_warm.cpp + flat_mem_warm.cpp flat_sausagecache.cpp flat_sausagecache.h - flat_sausage_meta.cpp - flat_page_label.cpp - flat_part_dump.cpp + flat_sausage_meta.cpp + flat_page_label.cpp + flat_part_dump.cpp flat_part_iter_multi.cpp flat_part_loader.cpp flat_part_overlay.cpp @@ -57,12 +57,12 @@ SRCS( flat_stat_part.h flat_stat_table.h flat_stat_table.cpp - flat_store_hotdog.cpp + flat_store_hotdog.cpp flat_table.cpp flat_table.h flat_table_part.cpp flat_table_part.h - flat_table_misc.cpp + flat_table_misc.cpp flat_update_op.h probes.cpp shared_handle.cpp diff --git a/ydb/core/testlib/actors/test_runtime_ut.cpp b/ydb/core/testlib/actors/test_runtime_ut.cpp index fce7f19293..84146ff100 100644 --- a/ydb/core/testlib/actors/test_runtime_ut.cpp +++ b/ydb/core/testlib/actors/test_runtime_ut.cpp @@ -9,12 +9,12 @@ namespace NKikimr { using namespace NActors; Y_UNIT_TEST_SUITE(TActorTest) { - TTestActorRuntime::TEgg MakeEgg() - { - return + TTestActorRuntime::TEgg MakeEgg() + { + return { new TAppData(0, 0, 0, 0, { }, nullptr, nullptr, nullptr, nullptr), nullptr, nullptr }; - } - + } + Y_UNIT_TEST(TestHandleEvent) { class TMyActor : public TActor<TMyActor> { public: @@ -36,7 +36,7 @@ Y_UNIT_TEST_SUITE(TActorTest) { }; TTestActorRuntime runtime; - runtime.Initialize(MakeEgg()); + runtime.Initialize(MakeEgg()); TActorId sender = runtime.AllocateEdgeActor(); TActorId actorId = runtime.Register(new TMyActor(sender)); runtime.Send(new IEventHandle(actorId, sender, new TEvents::TEvWakeup)); @@ -58,7 +58,7 @@ Y_UNIT_TEST_SUITE(TActorTest) { }; TTestActorRuntime runtime; - runtime.Initialize(MakeEgg()); + runtime.Initialize(MakeEgg()); TActorId sender = runtime.AllocateEdgeActor(); TActorId actorId = runtime.Register(new TMyActor); runtime.Send(new IEventHandle(actorId, sender, new TEvents::TEvPoisonPill)); @@ -96,7 +96,7 @@ Y_UNIT_TEST_SUITE(TActorTest) { }; TTestActorRuntime runtime; - runtime.Initialize(MakeEgg()); + runtime.Initialize(MakeEgg()); TActorId sender = runtime.AllocateEdgeActor(); auto actor = new TMyActor; TActorId actorId = runtime.Register(actor); @@ -121,7 +121,7 @@ Y_UNIT_TEST_SUITE(TActorTest) { }; TTestActorRuntime runtime; - runtime.Initialize(MakeEgg()); + runtime.Initialize(MakeEgg()); TActorId sender = runtime.AllocateEdgeActor(); TActorId actorId = runtime.Register(new TMyActor); runtime.Send(new IEventHandle(actorId, sender, new TEvents::TEvPing)); @@ -154,7 +154,7 @@ Y_UNIT_TEST_SUITE(TActorTest) { }; TTestActorRuntime runtime; - runtime.Initialize(MakeEgg()); + runtime.Initialize(MakeEgg()); runtime.SetScheduledEventFilter([](TTestActorRuntimeBase& runtime, TAutoPtr<IEventHandle>& event, TDuration delay, TInstant& deadline) { Y_UNUSED(event); deadline = runtime.GetCurrentTime() + delay; @@ -208,7 +208,7 @@ Y_UNIT_TEST_SUITE(TActorTest) { }; TTestActorRuntime runtime; - runtime.Initialize(MakeEgg()); + runtime.Initialize(MakeEgg()); TActorId sender = runtime.AllocateEdgeActor(); auto actor = new TMyActor; TActorId actorId = runtime.Register(actor); @@ -268,7 +268,7 @@ Y_UNIT_TEST_SUITE(TActorTest) { }; TTestActorRuntime runtime; - runtime.Initialize(MakeEgg()); + runtime.Initialize(MakeEgg()); try { TActorId sender = runtime.AllocateEdgeActor(); auto myActor = new TMyActor(&syncMutex); @@ -323,7 +323,7 @@ Y_UNIT_TEST_SUITE(TActorTest) { }; TTestActorRuntime runtime; - runtime.Initialize(MakeEgg()); + runtime.Initialize(MakeEgg()); runtime.SetScheduledEventFilter([](TTestActorRuntimeBase& runtime, TAutoPtr<IEventHandle>& event, TDuration delay, TInstant& deadline) { if (event->GetTypeRewrite() != TEvents::TSystem::Wakeup) return true; @@ -435,7 +435,7 @@ Y_UNIT_TEST_SUITE(TActorTest) { }; TTestActorRuntime runtime; - runtime.Initialize(MakeEgg()); + runtime.Initialize(MakeEgg()); try { TActorId sender = runtime.AllocateEdgeActor(); @@ -516,7 +516,7 @@ Y_UNIT_TEST_SUITE(TActorTest) { }; TTestActorRuntime runtime; - runtime.Initialize(MakeEgg()); + runtime.Initialize(MakeEgg()); TActorId sender = runtime.AllocateEdgeActor(); TMyActor* myActor = new TMyActor; TActorId actorId = runtime.Register(myActor); @@ -577,7 +577,7 @@ Y_UNIT_TEST_SUITE(TActorTest) { }; TTestActorRuntime runtime; - runtime.Initialize(MakeEgg()); + runtime.Initialize(MakeEgg()); TActorId edge1 = runtime.AllocateEdgeActor(); TActorId edge2 = runtime.AllocateEdgeActor(); TActorId edge3 = runtime.AllocateEdgeActor(); diff --git a/ydb/core/testlib/actors/ut/ya.make b/ydb/core/testlib/actors/ut/ya.make index 85a31fe740..ea0a6c39e9 100644 --- a/ydb/core/testlib/actors/ut/ya.make +++ b/ydb/core/testlib/actors/ut/ya.make @@ -17,7 +17,7 @@ PEERDIR( ) SRCS( - test_runtime_ut.cpp + test_runtime_ut.cpp ) END() diff --git a/ydb/core/testlib/basics/appdata.h b/ydb/core/testlib/basics/appdata.h index 409869161f..7f69680696 100644 --- a/ydb/core/testlib/basics/appdata.h +++ b/ydb/core/testlib/basics/appdata.h @@ -1,5 +1,5 @@ -#pragma once - +#pragma once + #include "feature_flags.h" #include <ydb/core/base/appdata.h> @@ -10,9 +10,9 @@ #include <ydb/core/testlib/actors/test_runtime.h> #include <ydb/core/tx/datashard/export_iface.h> #include <ydb/core/tx/datashard/export_s3.h> - -namespace NKikimr { - + +namespace NKikimr { + // FIXME // Split this factory class TDataShardExportFactory : public NKikimr::NDataShard::IExportFactory { @@ -36,21 +36,21 @@ namespace NKikimr { struct TAppPrepare : public TTestFeatureFlagsHolder<TAppPrepare> { struct TMine : public NActors::IDestructable { - TIntrusivePtr<NScheme::TTypeRegistry> Types; - TIntrusivePtr<NMiniKQL::IFunctionRegistry> Funcs; + TIntrusivePtr<NScheme::TTypeRegistry> Types; + TIntrusivePtr<NMiniKQL::IFunctionRegistry> Funcs; TIntrusivePtr<TFormatFactory> Formats; std::shared_ptr<NDataShard::IExportFactory> DataShardExportFactory; std::shared_ptr<NPDisk::IIoContextFactory> IoContext; ~TMine(); - }; - - using TFnReg = std::function<NMiniKQL::IFunctionRegistry*(const NScheme::TTypeRegistry&)>; - + }; + + using TFnReg = std::function<NMiniKQL::IFunctionRegistry*(const NScheme::TTypeRegistry&)>; + TAppPrepare(std::shared_ptr<NKikimr::NDataShard::IExportFactory> ef = {}); - + NActors::TTestActorRuntime::TEgg Unwrap() noexcept; - + void AddDomain(TDomainsInfo::TDomain* domain); void AddHive(ui32 hiveUid, ui64 hive); void ClearDomainsAndHive(); @@ -68,10 +68,10 @@ namespace NKikimr { void SetRequestSequenceSize(ui64 value); void AddSystemBackupSID(const TString& sid); void SetEnableProtoSourceIdInfo(std::optional<bool> value); - - TIntrusivePtr<TChannelProfiles> Channels; - NKikimrBlobStorage::TNodeWardenServiceSet BSConf; - TIntrusivePtr<TDomainsInfo> Domains; + + TIntrusivePtr<TChannelProfiles> Channels; + NKikimrBlobStorage::TNodeWardenServiceSet BSConf; + TIntrusivePtr<TDomainsInfo> Domains; TMap<ui32, NKikimrProto::TKeyConfig> Keys; bool EnableKqpSpilling = false; NKikimrConfig::TCompactionConfig CompactionConfig; @@ -80,9 +80,9 @@ namespace NKikimr { NKikimrConfig::TDataShardConfig DataShardConfig; NKikimrConfig::TMeteringConfig MeteringConfig; NKikimrPQ::TPQConfig PQConfig; - - private: - TAutoPtr<TMine> Mine; - }; - -} + + private: + TAutoPtr<TMine> Mine; + }; + +} diff --git a/ydb/core/testlib/basics/helpers.cpp b/ydb/core/testlib/basics/helpers.cpp index 259e4f9da9..e062539c96 100644 --- a/ydb/core/testlib/basics/helpers.cpp +++ b/ydb/core/testlib/basics/helpers.cpp @@ -1,43 +1,43 @@ -#include "helpers.h" +#include "helpers.h" #include <ydb/core/base/appdata.h> #include <ydb/core/tablet/bootstrapper.h> - -namespace NKikimr { - + +namespace NKikimr { + TTabletStorageInfo* CreateTestTabletInfo(ui64 tabletId, TTabletTypes::EType tabletType, - TBlobStorageGroupType::EErasureSpecies erasure, ui32 groupId) - { - THolder<TTabletStorageInfo> x(new TTabletStorageInfo()); - - x->TabletID = tabletId; - x->TabletType = tabletType; + TBlobStorageGroupType::EErasureSpecies erasure, ui32 groupId) + { + THolder<TTabletStorageInfo> x(new TTabletStorageInfo()); + + x->TabletID = tabletId; + x->TabletType = tabletType; x->Channels.resize(5); - - for (ui64 channel = 0; channel < x->Channels.size(); ++channel) { - x->Channels[channel].Channel = channel; - x->Channels[channel].Type = TBlobStorageGroupType(erasure); - x->Channels[channel].History.resize(1); - x->Channels[channel].History[0].FromGeneration = 0; - x->Channels[channel].History[0].GroupID = groupId; - } - - return x.Release(); - } - + + for (ui64 channel = 0; channel < x->Channels.size(); ++channel) { + x->Channels[channel].Channel = channel; + x->Channels[channel].Type = TBlobStorageGroupType(erasure); + x->Channels[channel].History.resize(1); + x->Channels[channel].History[0].FromGeneration = 0; + x->Channels[channel].History[0].GroupID = groupId; + } + + return x.Release(); + } + TActorId CreateTestBootstrapper(TTestActorRuntime &runtime, TTabletStorageInfo *info, std::function<IActor* (const TActorId &, TTabletStorageInfo*)> op, ui32 nodeIndex) - { - TIntrusivePtr<TBootstrapperInfo> bi(new TBootstrapperInfo(new TTabletSetupInfo(op, TMailboxType::Simple, 0, TMailboxType::Simple, 0))); - return runtime.Register(CreateBootstrapper(info, bi.Get()), nodeIndex); - } - - NTabletPipe::TClientConfig GetPipeConfigWithRetries() - { - NTabletPipe::TClientConfig pipeConfig; + { + TIntrusivePtr<TBootstrapperInfo> bi(new TBootstrapperInfo(new TTabletSetupInfo(op, TMailboxType::Simple, 0, TMailboxType::Simple, 0))); + return runtime.Register(CreateBootstrapper(info, bi.Get()), nodeIndex); + } + + NTabletPipe::TClientConfig GetPipeConfigWithRetries() + { + NTabletPipe::TClientConfig pipeConfig; pipeConfig.RetryPolicy = NTabletPipe::TClientRetryPolicy::WithRetries(); - return pipeConfig; - } - + return pipeConfig; + } + struct TPDiskReplyChecker : IReplyChecker { ~TPDiskReplyChecker() { @@ -68,21 +68,21 @@ namespace NKikimr { void TStrandedPDiskServiceFactory::Create(const TActorContext &ctx, ui32 pDiskID, const TIntrusivePtr<TPDiskConfig> &cfg, const NPDisk::TKey &mainKey, ui32 poolId, ui32 nodeId) - { - Y_UNUSED(ctx); - Y_VERIFY(!Runtime.IsRealThreads()); - Y_VERIFY(nodeId >= Runtime.GetNodeId(0) && nodeId < Runtime.GetNodeId(0) + Runtime.GetNodeCount()); - ui32 nodeIndex = nodeId - Runtime.GetNodeId(0); + { + Y_UNUSED(ctx); + Y_VERIFY(!Runtime.IsRealThreads()); + Y_VERIFY(nodeId >= Runtime.GetNodeId(0) && nodeId < Runtime.GetNodeId(0) + Runtime.GetNodeCount()); + ui32 nodeIndex = nodeId - Runtime.GetNodeId(0); Runtime.BlockOutputForActor(TActorId(nodeId, "actorsystem")); - + TActorId actorId = Runtime.Register(CreatePDisk(cfg, mainKey, Runtime.GetAppData(0).Counters), nodeIndex, poolId, TMailboxType::Revolving); TActorId pDiskServiceId = MakeBlobStoragePDiskID(nodeId, pDiskID); - - Runtime.BlockOutputForActor(pDiskServiceId); - Runtime.BlockOutputForActor(actorId); + + Runtime.BlockOutputForActor(pDiskServiceId); + Runtime.BlockOutputForActor(actorId); auto factory = CreateStrandingDecoratorFactory(&Runtime, []{ return MakeHolder<TPDiskReplyChecker>(); }); IActor* wrappedActor = factory->Wrap(actorId, true, TVector<TActorId>()); TActorId wrappedActorId = Runtime.Register(wrappedActor, nodeIndex, poolId, TMailboxType::Revolving); - Runtime.RegisterService(pDiskServiceId, wrappedActorId, nodeIndex); - } -} + Runtime.RegisterService(pDiskServiceId, wrappedActorId, nodeIndex); + } +} diff --git a/ydb/core/testlib/basics/helpers.h b/ydb/core/testlib/basics/helpers.h index 7a70063f7a..cf8d527709 100644 --- a/ydb/core/testlib/basics/helpers.h +++ b/ydb/core/testlib/basics/helpers.h @@ -1,39 +1,39 @@ -#pragma once - -#include "appdata.h" -#include "runtime.h" +#pragma once + +#include "appdata.h" +#include "runtime.h" #include <ydb/core/util/defs.h> #include <ydb/core/base/blobstorage.h> #include <ydb/core/blobstorage/nodewarden/node_warden.h> #include <ydb/core/blobstorage/pdisk/blobstorage_pdisk.h> #include <ydb/core/blobstorage/pdisk/blobstorage_pdisk_factory.h> - -#include <functional> - -namespace NKikimr { -namespace NFake { - struct TStorage { - bool UseDisk = false; - ui64 SectorSize = 0; - ui64 ChunkSize = 0; - ui64 DiskSize = 0; - }; - - struct TCaches { - ui64 Shared = 32 * (ui64(1) << 20); // Shared cache limit, bytes - ui64 ScanQueue = 512 * (ui64(1) << 20); // Scan queue in flight limit, bytes - ui64 AsyncQueue = 512 * (ui64(1) << 20); // Async queue in flight limit, bytes - }; - - struct INode { - virtual void Birth(ui32 node) noexcept = 0; - }; -} - - const TBlobStorageGroupType::EErasureSpecies BootGroupErasure = TBlobStorageGroupType::ErasureNone; - + +#include <functional> + +namespace NKikimr { +namespace NFake { + struct TStorage { + bool UseDisk = false; + ui64 SectorSize = 0; + ui64 ChunkSize = 0; + ui64 DiskSize = 0; + }; + + struct TCaches { + ui64 Shared = 32 * (ui64(1) << 20); // Shared cache limit, bytes + ui64 ScanQueue = 512 * (ui64(1) << 20); // Scan queue in flight limit, bytes + ui64 AsyncQueue = 512 * (ui64(1) << 20); // Async queue in flight limit, bytes + }; + + struct INode { + virtual void Birth(ui32 node) noexcept = 0; + }; +} + + const TBlobStorageGroupType::EErasureSpecies BootGroupErasure = TBlobStorageGroupType::ErasureNone; + TTabletStorageInfo* CreateTestTabletInfo(ui64 tabletId, TTabletTypes::EType tabletType, - TBlobStorageGroupType::EErasureSpecies erasure = BootGroupErasure, ui32 groupId = 0); + TBlobStorageGroupType::EErasureSpecies erasure = BootGroupErasure, ui32 groupId = 0); TActorId CreateTestBootstrapper(TTestActorRuntime &runtime, TTabletStorageInfo *info, std::function<IActor* (const TActorId &, TTabletStorageInfo*)> op, ui32 nodeIndex = 0); NTabletPipe::TClientConfig GetPipeConfigWithRetries(); @@ -56,20 +56,20 @@ namespace NFake { // StateStorage, NodeWarden, TabletResolver, ResourceBroker, SharedPageCache void SetupBasicServices(TTestActorRuntime &runtime, TAppPrepare &app, bool mockDisk = false, NFake::INode *factory = nullptr, NFake::TStorage storage = {}, NFake::TCaches caches = {}); - + /// - class TStrandedPDiskServiceFactory : public IPDiskServiceFactory { - TTestActorRuntime &Runtime; - public: - TStrandedPDiskServiceFactory(TTestActorRuntime &runtime) - : Runtime(runtime) - {} - + class TStrandedPDiskServiceFactory : public IPDiskServiceFactory { + TTestActorRuntime &Runtime; + public: + TStrandedPDiskServiceFactory(TTestActorRuntime &runtime) + : Runtime(runtime) + {} + void Create(const TActorContext &ctx, ui32 pDiskID, const TIntrusivePtr<TPDiskConfig> &cfg, const NPDisk::TKey &mainKey, ui32 poolId, ui32 nodeId) override; - - virtual ~TStrandedPDiskServiceFactory() - {} - }; - -} + + virtual ~TStrandedPDiskServiceFactory() + {} + }; + +} diff --git a/ydb/core/testlib/basics/runtime.cpp b/ydb/core/testlib/basics/runtime.cpp index cd62ce82bf..96ddec9167 100644 --- a/ydb/core/testlib/basics/runtime.cpp +++ b/ydb/core/testlib/basics/runtime.cpp @@ -1,33 +1,33 @@ -#include "runtime.h" - +#include "runtime.h" + #include <ydb/core/base/appdata.h> #include <ydb/core/mind/dynamic_nameserver.h> #include <library/cpp/actors/dnsresolver/dnsresolver.h> #include <library/cpp/actors/interconnect/interconnect.h> #include <library/cpp/actors/interconnect/interconnect_tcp_server.h> -#include <util/generic/xrange.h> - -namespace NActors { - - TTestBasicRuntime::~TTestBasicRuntime() - { - - } - - void TTestBasicRuntime::Initialize(TEgg egg) - { - AddICStuff(); - - TTestActorRuntime::Initialize(std::move(egg)); - } - - void TTestBasicRuntime::AddICStuff() - { - TIntrusivePtr<TTableNameserverSetup> table = new TTableNameserverSetup; - - for (ui32 nodeIndex = 0; nodeIndex < GetNodeCount(); ++nodeIndex) { +#include <util/generic/xrange.h> + +namespace NActors { + + TTestBasicRuntime::~TTestBasicRuntime() + { + + } + + void TTestBasicRuntime::Initialize(TEgg egg) + { + AddICStuff(); + + TTestActorRuntime::Initialize(std::move(egg)); + } + + void TTestBasicRuntime::AddICStuff() + { + TIntrusivePtr<TTableNameserverSetup> table = new TTableNameserverSetup; + + for (ui32 nodeIndex = 0; nodeIndex < GetNodeCount(); ++nodeIndex) { const ui16 port = 12001 + nodeIndex; - table->StaticNodeTable[FirstNodeId + nodeIndex] = + table->StaticNodeTable[FirstNodeId + nodeIndex] = std::pair<TString, ui32>("::1", UseRealInterconnect ? GetPortManager().GetPort(port) : port); NActorsInterconnect::TNodeLocation proto; @@ -38,38 +38,38 @@ namespace NActors { table->StaticNodeTable[FirstNodeId + nodeIndex].Location = LocationCallback ? LocationCallback(nodeIndex) : TNodeLocation(proto); - } - + } + const TActorId dnsId = NDnsResolver::MakeDnsResolverActorId(); const TActorId namesId = GetNameserviceActorId(); - for (auto num : xrange(GetNodeCount())) { - auto* node = GetRawNode(num); - - node->Poller.Reset(new NInterconnect::TPollerThreads); - node->Poller->Start(); - + for (auto num : xrange(GetNodeCount())) { + auto* node = GetRawNode(num); + + node->Poller.Reset(new NInterconnect::TPollerThreads); + node->Poller->Start(); + AddLocalService(dnsId, TActorSetupCmd(NDnsResolver::CreateOnDemandDnsResolver(), TMailboxType::Simple, 0), num); - AddLocalService(namesId, - TActorSetupCmd(NKikimr::NNodeBroker::CreateDynamicNameserver(table), - TMailboxType::Simple, 0), num); - - const auto& nameNode = table->StaticNodeTable[FirstNodeId + num]; - - TIntrusivePtr<TInterconnectProxyCommon> common; - common.Reset(new TInterconnectProxyCommon); - common->NameserviceId = namesId; - common->TechnicalSelfHostName = "::1"; - common->ClusterUUID = ClusterUUID; - common->AcceptUUID = {ClusterUUID}; - + AddLocalService(namesId, + TActorSetupCmd(NKikimr::NNodeBroker::CreateDynamicNameserver(table), + TMailboxType::Simple, 0), num); + + const auto& nameNode = table->StaticNodeTable[FirstNodeId + num]; + + TIntrusivePtr<TInterconnectProxyCommon> common; + common.Reset(new TInterconnectProxyCommon); + common->NameserviceId = namesId; + common->TechnicalSelfHostName = "::1"; + common->ClusterUUID = ClusterUUID; + common->AcceptUUID = {ClusterUUID}; + if (UseRealInterconnect) { auto listener = new TInterconnectListenerTCP(nameNode.first, nameNode.second, common); AddLocalService({}, TActorSetupCmd(listener, TMailboxType::Simple, InterconnectPoolId()), num); AddLocalService(MakePollerActorId(), TActorSetupCmd(CreatePollerActor(), TMailboxType::Simple, 0), num); } - } - } -} + } + } +} diff --git a/ydb/core/testlib/basics/runtime.h b/ydb/core/testlib/basics/runtime.h index 982dd7500b..00741fe9c4 100644 --- a/ydb/core/testlib/basics/runtime.h +++ b/ydb/core/testlib/basics/runtime.h @@ -1,20 +1,20 @@ -#pragma once - +#pragma once + #include <ydb/core/testlib/actors/test_runtime.h> #include <library/cpp/actors/interconnect/interconnect.h> - -namespace NActors { - - class TTestBasicRuntime : public TTestActorRuntime { - public: - using TTestActorRuntime::TTestActorRuntime; - + +namespace NActors { + + class TTestBasicRuntime : public TTestActorRuntime { + public: + using TTestActorRuntime::TTestActorRuntime; + using TNodeLocationCallback = std::function<TNodeLocation(ui32)>; TNodeLocationCallback LocationCallback; - ~TTestBasicRuntime(); - - void Initialize(TEgg) override; - void AddICStuff(); - }; -} + ~TTestBasicRuntime(); + + void Initialize(TEgg) override; + void AddICStuff(); + }; +} diff --git a/ydb/core/testlib/basics/services.cpp b/ydb/core/testlib/basics/services.cpp index b4585ad96c..3f3ed37178 100644 --- a/ydb/core/testlib/basics/services.cpp +++ b/ydb/core/testlib/basics/services.cpp @@ -1,7 +1,7 @@ -#include "helpers.h" -#include "storage.h" -#include "appdata.h" -#include "runtime.h" +#include "helpers.h" +#include "storage.h" +#include "appdata.h" +#include "runtime.h" #include <ydb/core/base/appdata.h> #include <ydb/core/base/hive.h> #include <ydb/core/base/quoter.h> @@ -27,19 +27,19 @@ #include <ydb/core/tx/schemeshard/schemeshard.h> #include <ydb/core/tx/scheme_board/cache.h> #include <ydb/core/tx/columnshard/blob_cache.h> - -#include <util/system/env.h> - -static constexpr TDuration DISK_DISPATCH_TIMEOUT = NSan::PlainOrUnderSanitizer(TDuration::Seconds(10), TDuration::Seconds(20)); - -namespace NKikimr { + +#include <util/system/env.h> + +static constexpr TDuration DISK_DISPATCH_TIMEOUT = NSan::PlainOrUnderSanitizer(TDuration::Seconds(10), TDuration::Seconds(20)); + +namespace NKikimr { namespace NPDisk { extern const ui64 YdbDefaultPDiskSequence = 0x7e5700007e570000; } void SetupBSNodeWarden(TTestActorRuntime& runtime, ui32 nodeIndex, TIntrusivePtr<TNodeWardenConfig> nodeWardenConfig) - { + { runtime.AddLocalService(MakeBlobStorageNodeWardenID(runtime.GetNodeId(nodeIndex)), TActorSetupCmd(CreateBSNodeWarden(nodeWardenConfig), TMailboxType::Revolving, 0), nodeIndex); @@ -239,22 +239,22 @@ namespace NPDisk { void SetupBasicServices(TTestActorRuntime& runtime, TAppPrepare& app, bool mock, NFake::INode* factory, NFake::TStorage storage, NFake::TCaches caches) { - runtime.SetDispatchTimeout(storage.UseDisk ? DISK_DISPATCH_TIMEOUT : DEFAULT_DISPATCH_TIMEOUT); - + runtime.SetDispatchTimeout(storage.UseDisk ? DISK_DISPATCH_TIMEOUT : DEFAULT_DISPATCH_TIMEOUT); + TTestStorageFactory disk(runtime, storage, mock); - + { NKikimrBlobStorage::TNodeWardenServiceSet bsConfig; - Y_VERIFY(google::protobuf::TextFormat::ParseFromString(disk.MakeTextConf(*app.Domains), &bsConfig)); - app.SetBSConf(std::move(bsConfig)); - } - - if (app.Domains->Domains.empty()) { - app.AddDomain(TDomainsInfo::TDomain::ConstructEmptyDomain("dc-1").Release()); - app.AddHive(0, 0); + Y_VERIFY(google::protobuf::TextFormat::ParseFromString(disk.MakeTextConf(*app.Domains), &bsConfig)); + app.SetBSConf(std::move(bsConfig)); } - - for (ui32 nodeIndex = 0; nodeIndex < runtime.GetNodeCount(); ++nodeIndex) { + + if (app.Domains->Domains.empty()) { + app.AddDomain(TDomainsInfo::TDomain::ConstructEmptyDomain("dc-1").Release()); + app.AddHive(0, 0); + } + + for (ui32 nodeIndex = 0; nodeIndex < runtime.GetNodeCount(); ++nodeIndex) { SetupStateStorageGroups(runtime, nodeIndex, app); NKikimrProto::TKeyConfig keyConfig; if (const auto it = app.Keys.find(nodeIndex); it != app.Keys.end()) { @@ -269,12 +269,12 @@ namespace NPDisk { SetupBlobCache(runtime, nodeIndex); SetupQuoterService(runtime, nodeIndex); - if (factory) - factory->Birth(nodeIndex); - } - - runtime.Initialize(app.Unwrap()); - + if (factory) + factory->Birth(nodeIndex); + } + + runtime.Initialize(app.Unwrap()); + for (ui32 nodeIndex = 0; nodeIndex < runtime.GetNodeCount(); ++nodeIndex) { // NodeWarden (and its actors) relies on timers to work correctly auto actorId = runtime.GetLocalServiceId( @@ -284,12 +284,12 @@ namespace NPDisk { runtime.EnableScheduleForActor(actorId); } - if (!mock && !runtime.IsRealThreads()) { + if (!mock && !runtime.IsRealThreads()) { ui32 evNum = disk.DomainsNum * disk.DisksInDomain; - TDispatchOptions options; + TDispatchOptions options; options.FinalEvents.push_back( TDispatchOptions::TFinalEventCondition(TEvBlobStorage::EvLocalRecoveryDone, evNum)); - runtime.DispatchEvents(options); - } - } -} + runtime.DispatchEvents(options); + } + } +} diff --git a/ydb/core/testlib/basics/storage.h b/ydb/core/testlib/basics/storage.h index 36cee17818..8f346114bd 100644 --- a/ydb/core/testlib/basics/storage.h +++ b/ydb/core/testlib/basics/storage.h @@ -1,39 +1,39 @@ -#pragma once - -#include "helpers.h" +#pragma once + +#include "helpers.h" #include <ydb/core/blobstorage/crypto/default.h> #include <ydb/core/blobstorage/nodewarden/node_warden.h> #include <ydb/core/blobstorage/pdisk/blobstorage_pdisk_tools.h> #include <ydb/core/testlib/actors/test_runtime.h> #include <google/protobuf/text_format.h> - -#include <util/folder/dirut.h> -#include <util/string/printf.h> -#include <util/string/subst.h> - -namespace NKikimr { - + +#include <util/folder/dirut.h> +#include <util/string/printf.h> +#include <util/string/subst.h> + +namespace NKikimr { + struct TTestStorageFactory { - using TRuntime = TTestActorRuntime; - + using TRuntime = TTestActorRuntime; + static constexpr ui64 MEM_DISK_SIZE = ui64(32) << 30; - static constexpr ui64 DISK_SIZE = ui64(16000) << 20; + static constexpr ui64 DISK_SIZE = ui64(16000) << 20; static constexpr ui64 SECTOR_SIZE = ui64(4) << 10; - static constexpr ui64 MEM_CHUNK_SIZE = 32000000; - static constexpr ui64 CHUNK_SIZE = 80000000; - static constexpr bool STRAND_PDISK = true; - static constexpr bool USE_SYNC_PDISK = false; - static constexpr bool USE_MEM_SYNC_PDISK = true; - + static constexpr ui64 MEM_CHUNK_SIZE = 32000000; + static constexpr ui64 CHUNK_SIZE = 80000000; + static constexpr bool STRAND_PDISK = true; + static constexpr bool USE_SYNC_PDISK = false; + static constexpr bool USE_MEM_SYNC_PDISK = true; + TTestStorageFactory(TRuntime &runtime, NFake::TStorage conf, bool mock) - : DomainsNum(TBlobStorageGroupType(BootGroupErasure).BlobSubgroupSize()) - , Mock(mock) + : DomainsNum(TBlobStorageGroupType(BootGroupErasure).BlobSubgroupSize()) + , Mock(mock) , Conf(FixConf(conf)) - , Runtime(runtime) - { - /* Do not use real backend for storage mock, it is useless */ - - if (!Conf.UseDisk && !Mock) { + , Runtime(runtime) + { + /* Do not use real backend for storage mock, it is useless */ + + if (!Conf.UseDisk && !Mock) { static TIntrusivePtr<NPDisk::TSectorMap> unsafeSectorMap; static TMutex unsafeBufferLock; with_lock (unsafeBufferLock) { @@ -41,142 +41,142 @@ namespace NKikimr { unsafeSectorMap->ForceSize(Conf.DiskSize); SectorMap = unsafeSectorMap; } - } - - const bool strandedPDisk = STRAND_PDISK && !Runtime.IsRealThreads(); - if (strandedPDisk) { - Factory = new TStrandedPDiskServiceFactory(Runtime); - } else { - Factory = new TRealPDiskServiceFactory(); - } - + } + + const bool strandedPDisk = STRAND_PDISK && !Runtime.IsRealThreads(); + if (strandedPDisk) { + Factory = new TStrandedPDiskServiceFactory(Runtime); + } else { + Factory = new TRealPDiskServiceFactory(); + } + NPDisk::TKey mainKey = NPDisk::YdbDefaultPDiskSequence; - - static ui64 keySalt = 0; - ui64 salt = ++keySalt; + + static ui64 keySalt = 0; + ui64 salt = ++keySalt; TString baseDir = Runtime.GetTempDir(); - + if (Conf.UseDisk) { MakeDirIfNotExist(baseDir.c_str()); } - + PDiskPath = TStringBuilder() << baseDir << "pdisk_1.dat"; - - if (!Mock) { - FormatPDisk(PDiskPath, - Conf.DiskSize, Conf.SectorSize, Conf.ChunkSize, PDiskGuid, + + if (!Mock) { + FormatPDisk(PDiskPath, + Conf.DiskSize, Conf.SectorSize, Conf.ChunkSize, PDiskGuid, 0x123 + salt, 0x456 + salt, 0x789 + salt, mainKey, "", false, false, SectorMap); - } - } - + } + } + static NFake::TStorage FixConf(NFake::TStorage conf) noexcept - { - if (conf.DiskSize == 0) { - conf.DiskSize = conf.UseDisk ? DISK_SIZE : MEM_DISK_SIZE; + { + if (conf.DiskSize == 0) { + conf.DiskSize = conf.UseDisk ? DISK_SIZE : MEM_DISK_SIZE; conf.SectorSize = SECTOR_SIZE; - conf.ChunkSize = conf.UseDisk ? CHUNK_SIZE : MEM_CHUNK_SIZE; - } - - return conf; - } - + conf.ChunkSize = conf.UseDisk ? CHUNK_SIZE : MEM_CHUNK_SIZE; + } + + return conf; + } + TIntrusivePtr<TNodeWardenConfig> MakeWardenConf(const TDomainsInfo &domains, const NKikimrProto::TKeyConfig& keyConfig) const - { - TIntrusivePtr<TNodeWardenConfig> conf(new TNodeWardenConfig(Factory)); - - { - auto text = MakeTextConf(domains); - - google::protobuf::TextFormat::ParseFromString(text, &conf->ServiceSet); - } - - conf->ServiceSet.SetEnableProxyMock(Mock); - conf->PDiskConfigOverlay.SetGetDriveDataSwitch(NKikimrBlobStorage::TPDiskConfig::DoNotTouch); - conf->PDiskConfigOverlay.SetWriteCacheSwitch(NKikimrBlobStorage::TPDiskConfig::DoNotTouch); - + { + TIntrusivePtr<TNodeWardenConfig> conf(new TNodeWardenConfig(Factory)); + + { + auto text = MakeTextConf(domains); + + google::protobuf::TextFormat::ParseFromString(text, &conf->ServiceSet); + } + + conf->ServiceSet.SetEnableProxyMock(Mock); + conf->PDiskConfigOverlay.SetGetDriveDataSwitch(NKikimrBlobStorage::TPDiskConfig::DoNotTouch); + conf->PDiskConfigOverlay.SetWriteCacheSwitch(NKikimrBlobStorage::TPDiskConfig::DoNotTouch); + if (SectorMap) { conf->SectorMaps[PDiskPath] = SectorMap; } auto baseInfo = TVDiskConfig::TBaseInfo::SampleForTests(); TIntrusivePtr<TVDiskConfig> vDisk = conf->AllVDiskKinds->MakeVDiskConfig(baseInfo); - vDisk->AdvanceEntryPointTimeout = TDuration::Seconds(5); - vDisk->RecoveryLogCutterFirstDuration = TDuration::Seconds(3); - vDisk->RecoveryLogCutterRegularDuration = TDuration::Seconds(5); - vDisk->FreshCompaction = false; - vDisk->LevelCompaction = true; - vDisk->MaxLogoBlobDataSize = Conf.UseDisk ? CHUNK_SIZE / 3 : MEM_CHUNK_SIZE / 3; - + vDisk->AdvanceEntryPointTimeout = TDuration::Seconds(5); + vDisk->RecoveryLogCutterFirstDuration = TDuration::Seconds(3); + vDisk->RecoveryLogCutterRegularDuration = TDuration::Seconds(5); + vDisk->FreshCompaction = false; + vDisk->LevelCompaction = true; + vDisk->MaxLogoBlobDataSize = Conf.UseDisk ? CHUNK_SIZE / 3 : MEM_CHUNK_SIZE / 3; + ObtainTenantKey(&conf->TenantKey, keyConfig); ObtainStaticKey(&conf->StaticKey); - return conf; - } - - TString MakeTextConf(const TDomainsInfo &domains) const - { - TString escapedPdiskPath = PDiskPath; - SubstGlobal(escapedPdiskPath, "\\", "\\\\"); - TStringStream str; - - for (const auto &it: domains.Domains) { - str << "AvailabilityDomains: " << it.second->DomainUid << Endl; - } + return conf; + } + + TString MakeTextConf(const TDomainsInfo &domains) const + { + TString escapedPdiskPath = PDiskPath; + SubstGlobal(escapedPdiskPath, "\\", "\\\\"); + TStringStream str; + + for (const auto &it: domains.Domains) { + str << "AvailabilityDomains: " << it.second->DomainUid << Endl; + } str << "PDisks { NodeID: " << Runtime.GetNodeId(0) << " PDiskID: 1 PDiskGuid: " << PDiskGuid - << " Path: \"" << escapedPdiskPath << "\"}" << Endl; - str << "" << Endl; - - for (const ui32 ringIdx : xrange(1)) { - for (const ui32 domainIdx : xrange(DomainsNum)) { - for (const ui32 vDiskIdx : xrange(DisksInDomain)) { - ui32 slotId = vDiskIdx + domainIdx * DisksInDomain + ringIdx * DomainsNum * DisksInDomain; - - str << "VDisks {" << Endl; - str << " VDiskID { GroupID: 0 GroupGeneration: 1 Ring: " << ringIdx - << " Domain: " << domainIdx << " VDisk: " << vDiskIdx << " }" << Endl; + << " Path: \"" << escapedPdiskPath << "\"}" << Endl; + str << "" << Endl; + + for (const ui32 ringIdx : xrange(1)) { + for (const ui32 domainIdx : xrange(DomainsNum)) { + for (const ui32 vDiskIdx : xrange(DisksInDomain)) { + ui32 slotId = vDiskIdx + domainIdx * DisksInDomain + ringIdx * DomainsNum * DisksInDomain; + + str << "VDisks {" << Endl; + str << " VDiskID { GroupID: 0 GroupGeneration: 1 Ring: " << ringIdx + << " Domain: " << domainIdx << " VDisk: " << vDiskIdx << " }" << Endl; str << " VDiskLocation { NodeID: " << Runtime.GetNodeId(0) << " PDiskID: 1 PDiskGuid: " << PDiskGuid - << " VDiskSlotID: " << slotId << " }" << Endl; - str << "}" << Endl; - } - } - } - - str << "" << Endl; - str << "Groups {" << Endl; - str << " GroupID: 0" << Endl; - str << " GroupGeneration: 1 " << Endl; - str << " ErasureSpecies: " << (ui32)BootGroupErasure << Endl; - - for (const ui32 ringIdx : xrange(1)) { - str << " Rings {" << Endl; - for (const ui32 domainIdx : xrange(DomainsNum)) { - str << " FailDomains {" << Endl; - for (const ui32 vDiskIdx : xrange(DisksInDomain)) { - ui32 slotId = vDiskIdx + domainIdx * DisksInDomain + ringIdx * DomainsNum * DisksInDomain; + << " VDiskSlotID: " << slotId << " }" << Endl; + str << "}" << Endl; + } + } + } + + str << "" << Endl; + str << "Groups {" << Endl; + str << " GroupID: 0" << Endl; + str << " GroupGeneration: 1 " << Endl; + str << " ErasureSpecies: " << (ui32)BootGroupErasure << Endl; + + for (const ui32 ringIdx : xrange(1)) { + str << " Rings {" << Endl; + for (const ui32 domainIdx : xrange(DomainsNum)) { + str << " FailDomains {" << Endl; + for (const ui32 vDiskIdx : xrange(DisksInDomain)) { + ui32 slotId = vDiskIdx + domainIdx * DisksInDomain + ringIdx * DomainsNum * DisksInDomain; str << " VDiskLocations { NodeID: " << Runtime.GetNodeId(0) << " PDiskID: 1 VDiskSlotID: " << slotId - << " PDiskGuid: " << PDiskGuid << " }" << Endl; - } - str << " }" << Endl; - } - str << " }" << Endl; - } - str << "}"; - - return str.Str(); - } - - const ui32 DisksInDomain = 1; - const ui32 DomainsNum = 0; - const ui64 PDiskGuid = 123; - const bool Mock = false; - const NFake::TStorage Conf; - - private: - TTestActorRuntime &Runtime; - TIntrusivePtr<IPDiskServiceFactory> Factory; - TString PDiskPath; + << " PDiskGuid: " << PDiskGuid << " }" << Endl; + } + str << " }" << Endl; + } + str << " }" << Endl; + } + str << "}"; + + return str.Str(); + } + + const ui32 DisksInDomain = 1; + const ui32 DomainsNum = 0; + const ui64 PDiskGuid = 123; + const bool Mock = false; + const NFake::TStorage Conf; + + private: + TTestActorRuntime &Runtime; + TIntrusivePtr<IPDiskServiceFactory> Factory; + TString PDiskPath; TIntrusivePtr<NPDisk::TSectorMap> SectorMap; - }; - -} + }; + +} diff --git a/ydb/core/testlib/basics/ya.make b/ydb/core/testlib/basics/ya.make index 61f74922f4..771942276d 100644 --- a/ydb/core/testlib/basics/ya.make +++ b/ydb/core/testlib/basics/ya.make @@ -1,15 +1,15 @@ -LIBRARY() - +LIBRARY() + OWNER(g:kikimr) - -SRCS( + +SRCS( appdata.cpp - helpers.cpp - runtime.cpp + helpers.cpp + runtime.cpp services.cpp -) - -PEERDIR( +) + +PEERDIR( library/cpp/actors/dnsresolver library/cpp/regex/pcre library/cpp/testing/unittest @@ -30,14 +30,14 @@ PEERDIR( ydb/core/util ydb/library/yql/minikql/invoke_builtins ydb/library/yql/public/udf/service/exception_policy -) - +) + YQL_LAST_ABI_VERSION() -IF (GCC) +IF (GCC) CFLAGS( -fno-devirtualize-speculatively ) -ENDIF() - -END() +ENDIF() + +END() diff --git a/ydb/core/testlib/fake_coordinator.h b/ydb/core/testlib/fake_coordinator.h index b3098d60a5..c4c67d4550 100644 --- a/ydb/core/testlib/fake_coordinator.h +++ b/ydb/core/testlib/fake_coordinator.h @@ -26,7 +26,7 @@ namespace NKikimr { TFakeCoordinator(const TActorId &tablet, TTabletStorageInfo *info, TState::TPtr state) : TActor<TFakeCoordinator>(&TFakeCoordinator::StateInit) - , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) + , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) , State(state) , Pipes(NTabletPipe::CreateUnboundedClientCache(GetPipeClientConfig())) { diff --git a/ydb/core/testlib/tablet_flat_dummy.cpp b/ydb/core/testlib/tablet_flat_dummy.cpp index 1a9dca04a5..430e3cb094 100644 --- a/ydb/core/testlib/tablet_flat_dummy.cpp +++ b/ydb/core/testlib/tablet_flat_dummy.cpp @@ -1,4 +1,4 @@ -#include "tablet_helpers.h" +#include "tablet_helpers.h" #include <ydb/core/tablet_flat/tablet_flat_executed.h> #include <ydb/core/tablet_flat/flat_dbase_scheme.h> #include <ydb/core/tablet_flat/flat_cxx_database.h> @@ -10,7 +10,7 @@ namespace NKikimr { namespace { -class TDummyFlatTablet : public TActor<TDummyFlatTablet>, public NTabletFlatExecutor::TTabletExecutedFlat { +class TDummyFlatTablet : public TActor<TDummyFlatTablet>, public NTabletFlatExecutor::TTabletExecutedFlat { struct Schema : NIceDb::Schema { struct Snaps : Table<1> { @@ -116,7 +116,7 @@ public: TDummyFlatTablet(const TActorId &tablet, TTabletStorageInfo *info) : TActor(&TThis::StateInit) - , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) + , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) {} STFUNC(StateInit) { diff --git a/ydb/core/testlib/tablet_helpers.cpp b/ydb/core/testlib/tablet_helpers.cpp index a853040b93..64ad3cf243 100644 --- a/ydb/core/testlib/tablet_helpers.cpp +++ b/ydb/core/testlib/tablet_helpers.cpp @@ -121,11 +121,11 @@ namespace NKikimr { nodeIndex); } - struct TUltimateNodes : public NFake::INode { + struct TUltimateNodes : public NFake::INode { TUltimateNodes(TTestActorRuntime &runtime, const TAppPrepare *app) - : Runtime(runtime) - { - + : Runtime(runtime) + { + if (runtime.IsRealThreads()) { return; } @@ -140,10 +140,10 @@ namespace NKikimr { const TDomainsInfo::TDomain *domain = xpair.second.Get(); UseFakeTimeCast |= domain->Mediators.size() == 0; } - } - - void Birth(ui32 node) noexcept override - { + } + + void Birth(ui32 node) noexcept override + { SetupMediatorTimecastProxy(Runtime, node, UseFakeTimeCast); SetupMonitoringProxy(Runtime, node); SetupTabletCountersAggregator(Runtime, node); @@ -151,12 +151,12 @@ namespace NKikimr { SetupNodeWhiteboard(Runtime, node); SetupNodeTabletMonitor(Runtime, node); SetupPQNodeCache(Runtime, node); - } - - TTestActorRuntime &Runtime; + } + + TTestActorRuntime &Runtime; bool UseFakeTimeCast = false; - }; - + }; + class TTabletTracer : TNonCopyable { public: TTabletTracer(bool& tracingActive, const TVector<ui64>& tabletIds) @@ -617,8 +617,8 @@ namespace NKikimr { } void SetupTabletServices(TTestActorRuntime &runtime, TAppPrepare *app, bool mockDisk, NFake::TStorage storage, - NFake::TCaches caches) { - TAutoPtr<TAppPrepare> dummy; + NFake::TCaches caches) { + TAutoPtr<TAppPrepare> dummy; if (app == nullptr) { dummy = app = new TAppPrepare; } @@ -658,7 +658,7 @@ namespace NKikimr { void SetupChannelProfiles(TAppPrepare &app, ui32 domainId, ui32 nchannels) { Y_VERIFY(app.Domains && app.Domains->Domains.contains(domainId)); - auto& poolKinds = app.Domains->GetDomain(domainId).StoragePoolTypes; + auto& poolKinds = app.Domains->GetDomain(domainId).StoragePoolTypes; Y_VERIFY(!poolKinds.empty()); TIntrusivePtr<TChannelProfiles> channelProfiles = new TChannelProfiles; @@ -700,7 +700,7 @@ namespace NKikimr { } } - app.SetChannels(std::move(channelProfiles)); + app.SetChannels(std::move(channelProfiles)); } void SetupBoxAndStoragePool(TTestActorRuntime &runtime, const TActorId& sender, ui32 domainId, ui32 nGroups) { @@ -1092,7 +1092,7 @@ namespace NKikimr { TFakeHive(const TActorId &tablet, TTabletStorageInfo *info, TState::TPtr state, TGetTabletCreationFunc getTabletCreationFunc) : TActor<TFakeHive>(&TFakeHive::StateInit) - , NTabletFlatExecutor::TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) + , NTabletFlatExecutor::TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) , State(state) , GetTabletCreationFunc(getTabletCreationFunc) { diff --git a/ydb/core/testlib/tablet_helpers.h b/ydb/core/testlib/tablet_helpers.h index 81a7c614aa..059edde44c 100644 --- a/ydb/core/testlib/tablet_helpers.h +++ b/ydb/core/testlib/tablet_helpers.h @@ -14,10 +14,10 @@ #include <functional> namespace NKikimr { - struct TAppPrepare; - - const TBlobStorageGroupType::EErasureSpecies DataGroupErasure = TBlobStorageGroupType::ErasureNone; + struct TAppPrepare; + const TBlobStorageGroupType::EErasureSpecies DataGroupErasure = TBlobStorageGroupType::ErasureNone; + TActorId FollowerTablet(TTestActorRuntime &runtime, const TActorId &launcher, TTabletStorageInfo *info, std::function<IActor* (const TActorId &, TTabletStorageInfo*)> op); TActorId ResolveTablet(TTestActorRuntime& runtime, ui64 tabletId, ui32 nodeIndex = 0, bool sysTablet = false); diff --git a/ydb/core/testlib/tenant_runtime.cpp b/ydb/core/testlib/tenant_runtime.cpp index 974cc166d0..3847082afc 100644 --- a/ydb/core/testlib/tenant_runtime.cpp +++ b/ydb/core/testlib/tenant_runtime.cpp @@ -802,10 +802,10 @@ void TTenantTestRuntime::Setup(bool createTenantPools) SetupMonitoring(); } - TAppPrepare app; - + TAppPrepare app; + app.FeatureFlags = Extension.GetFeatureFlags(); - app.ClearDomainsAndHive(); + app.ClearDomainsAndHive(); ui32 planResolution = 500; // Add domains info. @@ -834,8 +834,8 @@ void TTenantTestRuntime::Setup(bool createTenantPools) ids.insert(ids.end(), domainPtr->TxAllocators.begin(), domainPtr->TxAllocators.end()); SetTxAllocatorTabletIds(ids); - app.AddDomain(domainPtr.Release()); - app.AddHive(i, Config.HiveId); + app.AddDomain(domainPtr.Release()); + app.AddHive(i, Config.HiveId); } for (size_t i = 0; i< Config.Nodes.size(); ++i) { @@ -1120,7 +1120,7 @@ void TTenantTestRuntime::Setup(bool createTenantPools) TTenantTestRuntime::TTenantTestRuntime(const TTenantTestConfig &config, const NKikimrConfig::TAppConfig &extension, bool createTenantPools) - : TTestBasicRuntime(config.Nodes.size(), config.DataCenterCount, false) + : TTestBasicRuntime(config.Nodes.size(), config.DataCenterCount, false) , Config(config) , Extension(extension) { diff --git a/ydb/core/testlib/tenant_runtime.h b/ydb/core/testlib/tenant_runtime.h index f98c1441af..6ca9e09e29 100644 --- a/ydb/core/testlib/tenant_runtime.h +++ b/ydb/core/testlib/tenant_runtime.h @@ -190,7 +190,7 @@ extern const TTenantTestConfig DefaultTenantTestConfig; bool IsTabletActiveEvent(IEventHandle& ev); -class TTenantTestRuntime : public TTestBasicRuntime { +class TTenantTestRuntime : public TTestBasicRuntime { private: void Setup(bool createTenantPools = true); diff --git a/ydb/core/testlib/test_client.cpp b/ydb/core/testlib/test_client.cpp index d4907c26f1..c6d05f3a63 100644 --- a/ydb/core/testlib/test_client.cpp +++ b/ydb/core/testlib/test_client.cpp @@ -157,7 +157,7 @@ namespace Tests { if (Settings->SupportsRedirect && IsServerRedirected()) return; - TAppPrepare app; /* will cook TAppData */ + TAppPrepare app; /* will cook TAppData */ app.SetNetDataSourceUrl(Settings->NetClassifierConfig.GetUpdaterConfig().GetNetDataSourceUrl()); app.SetEnableKqpSpilling(Settings->EnableKqpSpilling); app.SetKeepSnapshotTimeout(Settings->KeepSnapshotTimeout); @@ -165,14 +165,14 @@ namespace Tests { app.SetChangesQueueBytesLimit(Settings->ChangesQueueBytesLimit); app.CompactionConfig = Settings->CompactionConfig; app.FeatureFlags = Settings->FeatureFlags; - + Runtime = MakeHolder<TTestBasicRuntime>(StaticNodes() + DynamicNodes(), Settings->UseRealThreads); if (!Settings->UseRealThreads) Runtime->SetRegistrationObserverFunc([](TTestActorRuntimeBase& runtime, const TActorId&, const TActorId& actorId) { runtime.EnableScheduleForActor(actorId); }); - + for (auto& it: Settings->NodeKeys) { ui32 nodeId = it.first; const TString& keyValue = it.second; @@ -189,23 +189,23 @@ namespace Tests { SetupLogging(); SetupMessageBus(Settings->Port, Settings->TracePath); - SetupDomains(app); - + SetupDomains(app); + app.AddHive(Settings->Domain, ChangeStateStorage(Hive, Settings->Domain)); - app.SetFnRegistry(Settings->FrFactory); + app.SetFnRegistry(Settings->FrFactory); app.SetFormatsFactory(Settings->Formats); - + if (Settings->Formats) { NKikHouse::RegisterFormat(*Settings->Formats); } NKikimr::SetupChannelProfiles(app, Settings->Domain); - + Runtime->SetupMonitoring(); - Runtime->SetLogBackend(Settings->LogBackend); - + Runtime->SetLogBackend(Settings->LogBackend); + SetupTabletServices(*Runtime, &app, (StaticNodes() + DynamicNodes()) == 1 && Settings->EnableMockOnSingleNode, Settings->CustomDiskParams); - + CreateBootstrapTablets(); SetupStorage(); @@ -341,7 +341,7 @@ namespace Tests { ); } - void TServer::SetupDomains(TAppPrepare &app) { + void TServer::SetupDomains(TAppPrepare &app) { const ui32 domainId = Settings->Domain; ui64 planResolution = Settings->DomainPlanResolution; if (!planResolution) { @@ -355,7 +355,7 @@ namespace Tests { TVector<ui64>{TDomainsInfo::MakeTxMediatorIDFixed(domainId, 1)}, TVector<ui64>{TDomainsInfo::MakeTxAllocatorIDFixed(domainId, 1)}, Settings->StoragePoolTypes); - app.AddDomain(domain.Release()); + app.AddDomain(domain.Release()); } void TServer::CreateBootstrapTablets() { @@ -867,11 +867,11 @@ namespace Tests { } const NScheme::TTypeRegistry* TServer::GetTypeRegistry() { - return Runtime->GetAppData().TypeRegistry; + return Runtime->GetAppData().TypeRegistry; } const NMiniKQL::IFunctionRegistry* TServer::GetFunctionRegistry() { - return Runtime->GetAppData().FunctionRegistry; + return Runtime->GetAppData().FunctionRegistry; } TServer::~TServer() { @@ -1407,8 +1407,8 @@ namespace Tests { NMsgBusProxy::EResponseStatus TClient::CreateTable(const TString& parent, const TString& scheme, TDuration timeout) { NKikimrSchemeOp::TTableDescription table; - bool parseOk = ::google::protobuf::TextFormat::ParseFromString(scheme, &table); - UNIT_ASSERT(parseOk); + bool parseOk = ::google::protobuf::TextFormat::ParseFromString(scheme, &table); + UNIT_ASSERT(parseOk); return CreateTable(parent, table, timeout); } @@ -1525,8 +1525,8 @@ namespace Tests { NMsgBusProxy::EResponseStatus TClient::AlterTable(const TString& parent, const TString& alter) { NKikimrSchemeOp::TTableDescription table; - bool parseOk = ::google::protobuf::TextFormat::ParseFromString(alter, &table); - UNIT_ASSERT(parseOk); + bool parseOk = ::google::protobuf::TextFormat::ParseFromString(alter, &table); + UNIT_ASSERT(parseOk); return AlterTable(parent, table); } diff --git a/ydb/core/testlib/test_client.h b/ydb/core/testlib/test_client.h index 2064752ab4..953eeb70c7 100644 --- a/ydb/core/testlib/test_client.h +++ b/ydb/core/testlib/test_client.h @@ -99,9 +99,9 @@ namespace Tests { TString DomainName = TestDomainName; ui32 NodeCount = 1; ui32 DynamicNodeCount = 0; - NFake::TStorage CustomDiskParams; + NFake::TStorage CustomDiskParams; TControls Controls; - TAppPrepare::TFnReg FrFactory = &DefaultFrFactory; + TAppPrepare::TFnReg FrFactory = &DefaultFrFactory; TIntrusivePtr<TFormatFactory> Formats; bool EnableMockOnSingleNode = true; TAutoPtr<TLogBackend> LogBackend; @@ -135,9 +135,9 @@ namespace Tests { TServerSettings& SetDomainName(const TString& value); TServerSettings& SetNodeCount(ui32 value) { NodeCount = value; return *this; } TServerSettings& SetDynamicNodeCount(ui32 value) { DynamicNodeCount = value; return *this; } - TServerSettings& SetCustomDiskParams(const NFake::TStorage& value) { CustomDiskParams = value; return *this; } + TServerSettings& SetCustomDiskParams(const NFake::TStorage& value) { CustomDiskParams = value; return *this; } TServerSettings& SetControls(const TControls& value) { Controls = value; return *this; } - TServerSettings& SetFrFactory(const TAppPrepare::TFnReg& value) { FrFactory = value; return *this; } + TServerSettings& SetFrFactory(const TAppPrepare::TFnReg& value) { FrFactory = value; return *this; } TServerSettings& SetEnableMockOnSingleNode(bool value) { EnableMockOnSingleNode = value; return *this; } TServerSettings& SetLogBackend(TAutoPtr<TLogBackend> value) { LogBackend = value; return *this; } TServerSettings& SetLoggerInitializer(TLoggerInitializer value) { LoggerInitializer = std::move(value); return *this; } @@ -195,7 +195,7 @@ namespace Tests { void SetupStorage(); void SetupMessageBus(ui16 port, const TString &tracePath); - void SetupDomains(TAppPrepare&); + void SetupDomains(TAppPrepare&); void CreateBootstrapTablets(); void SetupLocalConfig(TLocalConfig &localConfig, const NKikimr::TAppData &appData); void SetupDomainLocalService(ui32 nodeIdx); diff --git a/ydb/core/tx/coordinator/coordinator__mediators_confirmations.cpp b/ydb/core/tx/coordinator/coordinator__mediators_confirmations.cpp index 28a644503d..fce5cfd2c7 100644 --- a/ydb/core/tx/coordinator/coordinator__mediators_confirmations.cpp +++ b/ydb/core/tx/coordinator/coordinator__mediators_confirmations.cpp @@ -34,7 +34,7 @@ struct TTxCoordinator::TTxMediatorConfirmations : public TTransactionBase<TTxCoo if (txit == Self->Transactions.end()) { FLOG_DEBUG_S(ctx, NKikimrServices::TX_COORDINATOR, "at tablet# " << Self->TabletID() - << " gen:step " << internalTxGen << ":" << internalTxStep + << " gen:step " << internalTxGen << ":" << internalTxStep << " Mediator " << mediatorId << " confirmed finish of transaction " << txid << " but transaction wasn't found"); for (const TTabletId affected : txidsx.second) { db.Table<Schema::AffectedSet>().Key(mediatorId, txid, affected).Delete(); @@ -48,14 +48,14 @@ struct TTxCoordinator::TTxMediatorConfirmations : public TTransactionBase<TTxCoo db.Table<Schema::AffectedSet>().Key(mediatorId, txid, affected).Delete(); FLOG_DEBUG_S(ctx, NKikimrServices::TX_COORDINATOR, "at tablet# " << Self->TabletID() - << " gen:step " << internalTxGen << ":" << internalTxStep + << " gen:step " << internalTxGen << ":" << internalTxStep << " Confirmed transaction " << txid << " for mediator " << mediatorId << " tablet " << affected << " result=" << result); } if (mediatorAffectedSet.empty()) { FLOG_DEBUG_S(ctx, NKikimrServices::TX_COORDINATOR, "at tablet# " << Self->TabletID() - << " gen:step " << internalTxGen << ":" << internalTxStep + << " gen:step " << internalTxGen << ":" << internalTxStep << " Mediator " << mediatorId << " confirmed finish of transaction " << txid); txit->second.UnconfirmedAffectedSet.erase(mediatorId); } @@ -63,7 +63,7 @@ struct TTxCoordinator::TTxMediatorConfirmations : public TTransactionBase<TTxCoo if (txit->second.UnconfirmedAffectedSet.empty()) { // transaction finished FLOG_DEBUG_S(ctx, NKikimrServices::TX_COORDINATOR, "at tablet# " << Self->TabletID() - << " gen:step " << internalTxGen << ":" << internalTxStep + << " gen:step " << internalTxGen << ":" << internalTxStep << " Transaction " << txid << " has been completed"); db.Table<Schema::Transaction>().Key(txid).Delete(); Self->Transactions.erase(txit); diff --git a/ydb/core/tx/coordinator/coordinator_impl.cpp b/ydb/core/tx/coordinator/coordinator_impl.cpp index b4eeb184e2..9e61d50dd2 100644 --- a/ydb/core/tx/coordinator/coordinator_impl.cpp +++ b/ydb/core/tx/coordinator/coordinator_impl.cpp @@ -49,7 +49,7 @@ const ui32 TTxCoordinator::Schema::CurrentVersion = 1; TTxCoordinator::TTxCoordinator(TTabletStorageInfo *info, const TActorId &tablet) : TActor(&TThis::StateInit) - , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) + , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) #ifdef COORDINATOR_LOG_TO_FILE , DebugName(Sprintf("/tmp/coordinator_db_log_%" PRIu64 ".%" PRIi32 ".%" PRIu64 ".gz", TabletID(), getpid(), tablet.LocalId())) , DebugLogFile(DebugName) diff --git a/ydb/core/tx/datashard/datashard__init.cpp b/ydb/core/tx/datashard/datashard__init.cpp index dc12c49959..722ffdf1a9 100644 --- a/ydb/core/tx/datashard/datashard__init.cpp +++ b/ydb/core/tx/datashard/datashard__init.cpp @@ -368,7 +368,7 @@ bool TDataShard::TTxInit::ReadEverything(TTransactionContext &txc) { return false; // TODO: properly check shard state - if (Self->State != TShardState::Offline && txc.DB.GetScheme().GetTableInfo(Schema::TxMain::TableId)) { + if (Self->State != TShardState::Offline && txc.DB.GetScheme().GetTableInfo(Schema::TxMain::TableId)) { if (!Self->TransQueue.Load(db)) return false; @@ -497,7 +497,7 @@ public: NIceDb::TNiceDb db(txc.DB); - bool isCreate = txc.DB.GetScheme().IsEmpty(); + bool isCreate = txc.DB.GetScheme().IsEmpty(); if (isCreate) { Self->State = TShardState::WaitScheme; @@ -516,8 +516,8 @@ public: } if (isCreate) { - txc.DB.Alter().SetExecutorAllowLogBatching(gAllowLogBatchingDefaultValue); - txc.DB.Alter().SetExecutorLogFlushPeriod(TDuration::MicroSeconds(500)); + txc.DB.Alter().SetExecutorAllowLogBatching(gAllowLogBatchingDefaultValue); + txc.DB.Alter().SetExecutorLogFlushPeriod(TDuration::MicroSeconds(500)); Self->PersistSys(db, Schema::Sys_State, Self->State); diff --git a/ydb/core/tx/datashard/datashard__s3.cpp b/ydb/core/tx/datashard/datashard__s3.cpp index 2f7a74bbab..6c94440d00 100644 --- a/ydb/core/tx/datashard/datashard__s3.cpp +++ b/ydb/core/tx/datashard/datashard__s3.cpp @@ -1,5 +1,5 @@ #include "datashard_impl.h" -#include <util/string/vector.h> +#include <util/string/vector.h> namespace NKikimr { namespace NDataShard { @@ -79,7 +79,7 @@ public: TString startAfterPath; if (Ev->Get()->Record.GetSerializedStartAfterKeySuffix().empty()) { key.emplace_back(pathPrefix.data(), pathPrefix.size(), NScheme::NTypeIds::Utf8); - key.resize(txc.DB.GetScheme().GetTableInfo(localTableId)->KeyColumns.size()); + key.resize(txc.DB.GetScheme().GetTableInfo(localTableId)->KeyColumns.size()); } else { suffixColumns.Parse(Ev->Get()->Record.GetSerializedStartAfterKeySuffix()); size_t prefixSize = prefixColumns.GetCells().size(); @@ -229,7 +229,7 @@ public: } } - return iter->Last() != NTable::EReady::Page; + return iter->Last() != NTable::EReady::Page; } void Complete(const TActorContext& ctx) override { diff --git a/ydb/core/tx/datashard/datashard__stats.cpp b/ydb/core/tx/datashard/datashard__stats.cpp index 129a14dca5..8126becb39 100644 --- a/ydb/core/tx/datashard/datashard__stats.cpp +++ b/ydb/core/tx/datashard/datashard__stats.cpp @@ -331,7 +331,7 @@ public: for (ui32 sysTableId : Self->SysTablesToTransferAtSplit) { THashSet<ui64> sysPartOwners; auto subset = txc.DB.Subset(sysTableId, NTable::TEpoch::Max(), { }, { }); - NTable::GetPartOwners(*subset, sysPartOwners); + NTable::GetPartOwners(*subset, sysPartOwners); Self->SysTablesPartOnwers.insert(sysPartOwners.begin(), sysPartOwners.end()); } return true; diff --git a/ydb/core/tx/datashard/datashard_impl.h b/ydb/core/tx/datashard/datashard_impl.h index 11313474f8..c45192a344 100644 --- a/ydb/core/tx/datashard/datashard_impl.h +++ b/ydb/core/tx/datashard/datashard_impl.h @@ -2340,7 +2340,7 @@ protected: if (LastDbStatsReportTime + gDbStatsReportInterval > now) return; - auto* resourceMetrics = Executor()->GetResourceMetrics(); + auto* resourceMetrics = Executor()->GetResourceMetrics(); for (const auto& t : TableInfos) { ui64 tableId = t.first; diff --git a/ydb/core/tx/datashard/datashard_loans.cpp b/ydb/core/tx/datashard/datashard_loans.cpp index adbfc4769d..568fab5d1c 100644 --- a/ydb/core/tx/datashard/datashard_loans.cpp +++ b/ydb/core/tx/datashard/datashard_loans.cpp @@ -78,7 +78,7 @@ public: PartMetaVec.push_back(partMeta); LOG_DEBUG_S(ctx, NKikimrServices::TX_DATASHARD, Self->TabletID() << " got returned parts " << PartMetaVec << " from " << FromTabletId); - txc.Env.CleanupLoan(partMeta, FromTabletId); + txc.Env.CleanupLoan(partMeta, FromTabletId); } return true; @@ -117,7 +117,7 @@ public: PartMetaVec.push_back(partMeta); TLogoBlobID borrowId; - txc.Env.ConfirmLoan(partMeta, borrowId); + txc.Env.ConfirmLoan(partMeta, borrowId); } return true; diff --git a/ydb/core/tx/datashard/datashard_split_dst.cpp b/ydb/core/tx/datashard/datashard_split_dst.cpp index 6575081001..6dbe098fb3 100644 --- a/ydb/core/tx/datashard/datashard_split_dst.cpp +++ b/ydb/core/tx/datashard/datashard_split_dst.cpp @@ -174,7 +174,7 @@ public: ui32 localTableId = Ev->Get()->Record.GetTableSnapshot(i).GetTableId(); TString compressedBody = Ev->Get()->Record.GetTableSnapshot(i).GetSnapshotData(); TString snapBody = NBlockCodecs::Codec("lz4fast")->Decode(compressedBody); - txc.Env.LoanTable(localTableId, snapBody); + txc.Env.LoanTable(localTableId, snapBody); } NIceDb::TNiceDb db(txc.DB); diff --git a/ydb/core/tx/datashard/datashard_split_src.cpp b/ydb/core/tx/datashard/datashard_split_src.cpp index a7349fc9cf..5abf1ad80a 100644 --- a/ydb/core/tx/datashard/datashard_split_src.cpp +++ b/ydb/core/tx/datashard/datashard_split_src.cpp @@ -183,7 +183,7 @@ public: snapContext = new TSplitSnapshotContext(opId, std::move(tablesToSnapshot)); } - txc.Env.MakeSnapshot(snapContext); + txc.Env.MakeSnapshot(snapContext); Self->SplitSnapshotStarted = true; Self->State = TShardState::SplitSrcMakeSnapshot; @@ -226,8 +226,8 @@ public: Y_VERIFY(Self->State == TShardState::SplitSrcMakeSnapshot, "Datashard in unexpected state %s", DatashardStateName(Self->State).data()); - txc.Env.ClearSnapshot(*SnapContext); - + txc.Env.ClearSnapshot(*SnapContext); + NIceDb::TNiceDb db(txc.DB); ui64 sourceOffsetsBytes = 0; @@ -259,7 +259,7 @@ public: // Extract dst range from split/merge description to pass it to BorrowSnapshot TSerializedCellVec fromCells(dstRangeDescr.GetKeyRangeBegin()); TSerializedCellVec toCells(dstRangeDescr.GetKeyRangeEnd()); - + auto cellsToRawValues = [&tableInfo] (const TSerializedCellVec& cells) { TVector<TRawTypeValue> rawVals; ui32 ki = 0; @@ -372,7 +372,7 @@ public: LOG_DEBUG_S(ctx, NKikimrServices::TX_DATASHARD, Self->TabletID() << " BorrowSnapshot is restarting for split OpId " << opId); return false; } else { - txc.Env.DropSnapshot(SnapContext); + txc.Env.DropSnapshot(SnapContext); Self->State = TShardState::SplitSrcSendingSnapshot; Self->PersistSys(db, Schema::Sys_State, Self->State); diff --git a/ydb/core/tx/datashard/datashard_user_table.cpp b/ydb/core/tx/datashard/datashard_user_table.cpp index 70bc940073..d3a05f1734 100644 --- a/ydb/core/tx/datashard/datashard_user_table.cpp +++ b/ydb/core/tx/datashard/datashard_user_table.cpp @@ -367,7 +367,7 @@ void TUserTable::DoApplyCreate( Y_VERIFY(tid != 0 && tid != Max<ui32>(), "Creating table %s with bad id %" PRIu32, tableName.c_str(), tid); - auto &alter = txc.DB.Alter(); + auto &alter = txc.DB.Alter(); alter.AddTable(tableName, tid); THashSet<ui32> appliedRooms; @@ -403,10 +403,10 @@ void TUserTable::DoApplyCreate( alter.SetCompactionPolicy(tid, *NLocalDb::CreateDefaultUserTablePolicy()); } - if (partConfig.HasEnableFilterByKey()) { + if (partConfig.HasEnableFilterByKey()) { alter.SetByKeyFilter(tid, partConfig.GetEnableFilterByKey()); - } - + } + // N.B. some settings only apply to the main table if (!shadow) { @@ -434,13 +434,13 @@ void TUserTable::ApplyAlter( TTransactionContext& txc, const TUserTable& oldTable, const NKikimrSchemeOp::TTableDescription& delta, TString& strError) { - const auto& configDelta = delta.GetPartitionConfig(); + const auto& configDelta = delta.GetPartitionConfig(); NKikimrSchemeOp::TTableDescription schema; GetSchema(schema); auto& config = *schema.MutablePartitionConfig(); - auto &alter = txc.DB.Alter(); - + auto &alter = txc.DB.Alter(); + // Check if we need to drop shadow table first if (configDelta.HasShadowData()) { if (configDelta.GetShadowData()) { @@ -499,7 +499,7 @@ void TUserTable::ApplyAlter( } } - for (const auto& col : delta.GetDropColumns()) { + for (const auto& col : delta.GetDropColumns()) { ui32 colId = col.GetId(); const TUserTable::TUserColumn * oldCol = oldTable.Columns.FindPtr(colId); Y_VERIFY(oldCol); @@ -544,12 +544,12 @@ void TUserTable::ApplyAlter( if (configDelta.HasExecutorCacheSize()) { config.SetExecutorCacheSize(configDelta.GetExecutorCacheSize()); - alter.SetExecutorCacheSize(configDelta.GetExecutorCacheSize()); + alter.SetExecutorCacheSize(configDelta.GetExecutorCacheSize()); } if (configDelta.HasResourceProfile() && configDelta.GetResourceProfile()) { config.SetResourceProfile(configDelta.GetResourceProfile()); - alter.SetExecutorResourceProfile(configDelta.GetResourceProfile()); + alter.SetExecutorResourceProfile(configDelta.GetResourceProfile()); } if (configDelta.HasExecutorFastLogPolicy()) { diff --git a/ydb/core/tx/datashard/datashard_user_table.h b/ydb/core/tx/datashard/datashard_user_table.h index 0dab30cb84..e20b81cd06 100644 --- a/ydb/core/tx/datashard/datashard_user_table.h +++ b/ydb/core/tx/datashard/datashard_user_table.h @@ -22,10 +22,10 @@ struct TUserTable : public TThrRefBase { using TPtr = TIntrusivePtr<TUserTable>; using TCPtr = TIntrusiveConstPtr<TUserTable>; - struct TUserFamily { - using ECodec = NTable::NPage::ECodec; - using ECache = NTable::NPage::ECache; - + struct TUserFamily { + using ECodec = NTable::NPage::ECodec; + using ECache = NTable::NPage::ECache; + TUserFamily(const NKikimrSchemeOp::TFamilyDescription& family) : ColumnCodec(family.GetColumnCodec()) , ColumnCache(family.GetColumnCache()) @@ -38,7 +38,7 @@ struct TUserTable : public TThrRefBase { , Name(family.GetName()) { } - + void Update(const NKikimrSchemeOp::TFamilyDescription& family) { if (family.HasColumnCodec()) { ColumnCodec = family.GetColumnCodec(); @@ -59,7 +59,7 @@ struct TUserTable : public TThrRefBase { } Room.Reset(new TStorageRoom(family.GetRoom())); } - + static ui32 SaveGetThreshold(ui32 value) { return 0 == value ? Max<ui32>() : value; } @@ -181,8 +181,8 @@ struct TUserTable : public TThrRefBase { if (Name) return Name; return "default"; - } - + } + ui32 GetRoomId() const { return Room->GetId(); } @@ -194,7 +194,7 @@ struct TUserTable : public TThrRefBase { if (family.HasColumnCodec()) return ToDbCodec(family.GetColumnCodec()); if (family.GetCodec() == 1) // legacy - return ECodec::LZ4; + return ECodec::LZ4; return ECodec::Plain; } @@ -204,7 +204,7 @@ struct TUserTable : public TThrRefBase { return ECodec::Plain; case NKikimrSchemeOp::EColumnCodec::ColumnCodecLZ4: case NKikimrSchemeOp::EColumnCodec::ColumnCodecZSTD: // FIXME: not supported - return ECodec::LZ4; + return ECodec::LZ4; // keep no default } Y_FAIL("unexpected"); @@ -228,13 +228,13 @@ struct TUserTable : public TThrRefBase { } Y_FAIL("unexpected"); } - }; - + }; + struct TUserColumn { NScheme::TTypeId Type; TString Name; bool IsKey; - ui32 Family = 0; + ui32 Family = 0; bool NotNull = false; TUserColumn(NScheme::TTypeId type, TString name, bool isKey = false) diff --git a/ydb/core/tx/datashard/datashard_ut_common.cpp b/ydb/core/tx/datashard/datashard_ut_common.cpp index d754f7ad0e..7cb47f5a15 100644 --- a/ydb/core/tx/datashard/datashard_ut_common.cpp +++ b/ydb/core/tx/datashard/datashard_ut_common.cpp @@ -36,9 +36,9 @@ void TTester::Setup(TTestActorRuntime& runtime, const TOptions& opts) { ui32 domainId = 0; ui32 planResolution = 500; - - TAppPrepare app; - + + TAppPrepare app; + app.SetEnableMvcc(opts.Mvcc); auto domain = TDomainsInfo::TDomain::ConstructDomainWithExplicitTabletIds( @@ -279,7 +279,7 @@ TRuntimeNode TEngineHolder::ProgramText2Bin(TTester& tester, const TString& prog auto expr = NYql::ParseText(programText); auto resFuture = NYql::ConvertToMiniKQL( - expr, tester.Runtime.GetAppData().FunctionRegistry, + expr, tester.Runtime.GetAppData().FunctionRegistry, &Env, &tester.DbSchemeResolver ); @@ -307,7 +307,7 @@ ui32 TFakeProxyTx::SetProgram(TTester& tester) { ui32 TFakeProxyTx::SetProgram(TTester& tester, const TString& programText) { TEngineFlatSettings settings(IEngineFlat::EProtocol::V1, - tester.Runtime.GetAppData().FunctionRegistry, + tester.Runtime.GetAppData().FunctionRegistry, *TAppData::RandomProvider, *TAppData::TimeProvider); NMiniKQL::TRuntimeNode pgm = ProgramText2Bin(tester, programText); @@ -988,7 +988,7 @@ ui64 TFakeMiniKQLProxy::Plan(ui64 stepId, const TMap<ui64, TFakeProxyTx::TPtr>& // TKeyExtractor::TKeyExtractor(TTester& tester, TString programText) { - Engine = CreateEngineFlat(TEngineFlatSettings(IEngineFlat::EProtocol::V1, tester.Runtime.GetAppData().FunctionRegistry, + Engine = CreateEngineFlat(TEngineFlatSettings(IEngineFlat::EProtocol::V1, tester.Runtime.GetAppData().FunctionRegistry, *TAppData::RandomProvider, *TAppData::TimeProvider)); NMiniKQL::TRuntimeNode pgm = ProgramText2Bin(tester, programText); diff --git a/ydb/core/tx/datashard/datashard_ut_common.h b/ydb/core/tx/datashard/datashard_ut_common.h index 4b5d7fe4ea..7a3e27f39c 100644 --- a/ydb/core/tx/datashard/datashard_ut_common.h +++ b/ydb/core/tx/datashard/datashard_ut_common.h @@ -92,7 +92,7 @@ public: ~TActiveZone() { if (Tester.ActiveZone) *Tester.ActiveZone = false; } }; - TTestBasicRuntime Runtime; + TTestBasicRuntime Runtime; TTester(ESchema schema, const TOptions& opts = TOptions()); TTester(ESchema schema, const TString& dispatchName, std::function<void (TTestActorRuntime&)> setup, diff --git a/ydb/core/tx/datashard/datashard_ut_init.cpp b/ydb/core/tx/datashard/datashard_ut_init.cpp index 818e30ab0c..8f514f6fc7 100644 --- a/ydb/core/tx/datashard/datashard_ut_init.cpp +++ b/ydb/core/tx/datashard/datashard_ut_init.cpp @@ -95,7 +95,7 @@ Y_UNIT_TEST_SUITE(TTxDataShardTestInit) { } Y_UNIT_TEST(TestGetShardStateAfterInitialization) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTester::Setup(runtime); TActorId sender = runtime.AllocateEdgeActor(); diff --git a/ydb/core/tx/datashard/datashard_ut_locks.cpp b/ydb/core/tx/datashard/datashard_ut_locks.cpp index 1d25c39f99..5cb98cab7f 100644 --- a/ydb/core/tx/datashard/datashard_ut_locks.cpp +++ b/ydb/core/tx/datashard/datashard_ut_locks.cpp @@ -48,7 +48,7 @@ namespace NTest { template <typename T> void IncCounter(T, const TDuration&) const {} private: - NTable::TScheme Schema; + NTable::TScheme Schema; static ui32 NumSysTables() { return 10; } @@ -57,20 +57,20 @@ namespace NTest { TableInfos[EUserTableId].Name = "user____Table"; TableInfos[EUserTableId].KeyColumnTypes.push_back(NScheme::NTypeIds::Uint32); - NTable::TAlter delta; + NTable::TAlter delta; for (ui32 tableId = 0; tableId < NumSysTables(); ++tableId) { - delta.AddTable(TString("Table") + ('A'+tableId), tableId); + delta.AddTable(TString("Table") + ('A'+tableId), tableId); delta.AddColumn(tableId, "key", 0, NScheme::NTypeIds::Uint32, false); - delta.AddColumnToKey(tableId, 0); + delta.AddColumnToKey(tableId, 0); } - delta.AddTable("user____Table", EUserTableId); + delta.AddTable("user____Table", EUserTableId); delta.AddColumn(EUserTableId, "key", 0, NScheme::NTypeIds::Uint32, false); - delta.AddColumnToKey(EUserTableId, 0); - - - NTable::TSchemeModifier(Schema).Apply(*delta.Flush()); + delta.AddColumnToKey(EUserTableId, 0); + + + NTable::TSchemeModifier(Schema).Apply(*delta.Flush()); } public: diff --git a/ydb/core/tx/datashard/datashard_ut_order.cpp b/ydb/core/tx/datashard/datashard_ut_order.cpp index 32472dce59..2ddf2e663d 100644 --- a/ydb/core/tx/datashard/datashard_ut_order.cpp +++ b/ydb/core/tx/datashard/datashard_ut_order.cpp @@ -72,7 +72,7 @@ private: TIntrusivePtr<NKikimr::NMiniKQL::IFunctionRegistry> FunctionRegistry; TIntrusivePtr<IRandomProvider> RandomProvider; TIntrusivePtr<ITimeProvider> TimeProvider; - NTable::TDatabase DB; + NTable::TDatabase DB; }; diff --git a/ydb/core/tx/mediator/mediator_impl.cpp b/ydb/core/tx/mediator/mediator_impl.cpp index c4b202b822..c5373aa05a 100644 --- a/ydb/core/tx/mediator/mediator_impl.cpp +++ b/ydb/core/tx/mediator/mediator_impl.cpp @@ -1,7 +1,7 @@ #include "mediator_impl.h" #include <ydb/core/engine/minikql/flat_local_tx_factory.h> - + namespace NKikimr { namespace NTxMediator { @@ -314,7 +314,7 @@ void TTxMediator::Handle(TEvents::TEvPoisonPill::TPtr &ev, const TActorContext & TTxMediator::TTxMediator(TTabletStorageInfo *info, const TActorId &tablet) : TActor(&TThis::StateInit) - , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) + , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) {} } diff --git a/ydb/core/tx/schemeshard/schemeshard__init.cpp b/ydb/core/tx/schemeshard/schemeshard__init.cpp index 650506549e..932aef2b7a 100644 --- a/ydb/core/tx/schemeshard/schemeshard__init.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__init.cpp @@ -24,10 +24,10 @@ struct TSchemeShard::TTxInit : public TTransactionBase<TSchemeShard> { {} bool CreateScheme(TTransactionContext &txc) { - if (!txc.DB.GetScheme().IsEmpty()) + if (!txc.DB.GetScheme().IsEmpty()) return false; - NIceDb::TNiceDb(txc.DB).Materialize<Schema>(); + NIceDb::TNiceDb(txc.DB).Materialize<Schema>(); return true; } diff --git a/ydb/core/tx/schemeshard/schemeshard_impl.cpp b/ydb/core/tx/schemeshard/schemeshard_impl.cpp index 0715543a22..d8ac84b3c0 100644 --- a/ydb/core/tx/schemeshard/schemeshard_impl.cpp +++ b/ydb/core/tx/schemeshard/schemeshard_impl.cpp @@ -3626,7 +3626,7 @@ TActorId TSchemeShard::TPipeClientFactory::CreateClient(const TActorContext& ctx TSchemeShard::TSchemeShard(const TActorId &tablet, TTabletStorageInfo *info) : TActor(&TThis::StateInit) - , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) + , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) , AllowConditionalEraseOperations(1, 0, 1) , AllowServerlessStorageBilling(0, 0, 1) , SplitSettings() diff --git a/ydb/core/tx/schemeshard/ut_base.cpp b/ydb/core/tx/schemeshard/ut_base.cpp index a76dcf9d5b..961848a4e3 100644 --- a/ydb/core/tx/schemeshard/ut_base.cpp +++ b/ydb/core/tx/schemeshard/ut_base.cpp @@ -12,7 +12,7 @@ using namespace NSchemeShardUT_Private; Y_UNIT_TEST_SUITE(TSchemeShardTest) { Y_UNIT_TEST(Boot) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); } @@ -44,7 +44,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(MkRmDir) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -663,7 +663,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(CreateTable) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -2395,7 +2395,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(IgnoreUserColumnIds) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -2427,7 +2427,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { #if 0 // KIKIMR-1452 Y_UNIT_TEST(CreateSameTable) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -2482,7 +2482,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { #endif Y_UNIT_TEST(CreateTableWithUniformPartitioning) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 123; @@ -2518,7 +2518,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(CreateTableWithSplitBounadaries) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 123; ++txId; @@ -2553,7 +2553,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(CreateTableWithConfig) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 123; @@ -2592,7 +2592,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(CreateTableWithNamedConfig) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 123; @@ -2618,7 +2618,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(CreateTableWithUnknownNamedConfig) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 123; @@ -2712,7 +2712,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(DependentOps) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 123; @@ -2755,7 +2755,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(ParallelCreateTable) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 123; @@ -2794,7 +2794,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { Y_UNIT_TEST(ParallelCreateSameTable) { //+ using ESts = NKikimrScheme::EStatus; - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 123; @@ -2838,7 +2838,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(CopyTable) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 123; @@ -2879,7 +2879,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(CopyTableTwiceSimultaneously) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 123; @@ -2930,7 +2930,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(CopyTableAndConcurrentChanges) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 123; @@ -3020,7 +3020,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(CopyTableAndConcurrentSplit) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -3071,7 +3071,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(CopyTableAndConcurrentMerge) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -3121,7 +3121,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(CopyTableAndConcurrentSplitMerge) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -3559,7 +3559,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(AlterTableAndConcurrentSplit) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -3724,7 +3724,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(DropTableAndConcurrentSplit) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -3761,7 +3761,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(AlterTable) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -3970,7 +3970,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(AlterTableKeyColumns) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -4059,7 +4059,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(AlterTableById) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -4094,7 +4094,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(AlterTableConfig) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -4221,7 +4221,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { using NKikimrSchemeOp::EColumnCache; using NKikimrSchemeOp::EColumnStorage; - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; TVector<ui64> tabletIds = {TTestTxConfig::FakeHiveTablets, TTestTxConfig::FakeHiveTablets+1}; @@ -4321,7 +4321,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(MultipleColumnFamilies) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -5134,7 +5134,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(AlterTableComapctionPolicy) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -5206,7 +5206,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(AlterTableFollowers) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -5719,7 +5719,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { Y_UNIT_TEST(AlterTableSizeToSplit) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -5812,7 +5812,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(AlterTableSettings) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -5922,7 +5922,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(CreatePersQueueGroup) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 1000; @@ -5980,7 +5980,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(AlterPersQueueGroup) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 1000; @@ -6237,7 +6237,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(DropTable) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 1000; @@ -6299,7 +6299,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(DropTableById) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 1000; @@ -6329,7 +6329,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(DropPQ) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 1000; @@ -6451,7 +6451,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(ParallelModifying) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 1000; @@ -6555,7 +6555,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(DropPQFail) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -6599,7 +6599,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(DropPQAbort) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -6809,7 +6809,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(Restart) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 123; @@ -6850,7 +6850,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(ReadOnlyMode) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 123; @@ -6894,7 +6894,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(PathErrors) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 123; @@ -6936,7 +6936,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(SchemeErrors) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 123; @@ -6965,7 +6965,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(ManyDirs) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 num = 500; @@ -6995,7 +6995,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(NestedDirs) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 123; @@ -7064,7 +7064,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(CreateFinishedInDescription) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -7147,7 +7147,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { }; Y_UNIT_TEST(CreateBlockStoreVolume) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -7253,7 +7253,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(AlterBlockStoreVolume) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime, /* nchannels */ 6); ui64 txId = 100; @@ -7677,7 +7677,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(DropBlockStoreVolume) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -7788,7 +7788,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(AssignBlockStoreVolume) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -7847,7 +7847,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(AssignBlockStoreVolumeDuringAlter) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -8464,7 +8464,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } Y_UNIT_TEST(CreateDropKesus) { //+ - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; diff --git a/ydb/core/tx/schemeshard/ut_subdomain.cpp b/ydb/core/tx/schemeshard/ut_subdomain.cpp index d0d30bf7da..d5c4cdba73 100644 --- a/ydb/core/tx/schemeshard/ut_subdomain.cpp +++ b/ydb/core/tx/schemeshard/ut_subdomain.cpp @@ -79,7 +79,7 @@ NLs::TCheckFunc LsCheckDiskQuotaExceeded(bool value = true) { Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { Y_UNIT_TEST(Create) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -145,7 +145,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { } Y_UNIT_TEST(LS) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -170,7 +170,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { } Y_UNIT_TEST(ConcurrentCreateSubDomainAndDescribe) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -199,7 +199,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { Y_UNIT_TEST(CreataWithoutPlanResolution) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -217,7 +217,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { } Y_UNIT_TEST(CreataWithoutTimeCastBuckets) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -235,7 +235,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { } Y_UNIT_TEST(CreateWithNoEqualName) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -313,7 +313,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { } Y_UNIT_TEST(CreateItemsInsideSubdomain) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -359,7 +359,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { } Y_UNIT_TEST(CreateItemsInsideSubdomainWithStoragePools) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -410,7 +410,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { } Y_UNIT_TEST(CreateSubDomainWithoutTablets) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -428,7 +428,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { } Y_UNIT_TEST(CreateSubDomainWithoutSomeTablets) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -455,7 +455,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { } Y_UNIT_TEST(CreateSubDomainWithoutTabletsThenMkDir) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -479,7 +479,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { } Y_UNIT_TEST(CreateSubDomainWithoutTabletsThenDrop) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -529,7 +529,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { } Y_UNIT_TEST(CreateSubDomainsInSeparateDir) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -568,7 +568,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { } Y_UNIT_TEST(SimultaneousCreateDelete) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -936,7 +936,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { } Y_UNIT_TEST(SimultaneousCreateTenantTable) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -1030,7 +1030,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { } Y_UNIT_TEST(SimultaneousCreateTenantDirTable) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -1329,7 +1329,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { } Y_UNIT_TEST(Restart) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -1367,7 +1367,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { } Y_UNIT_TEST(RestartAtInFly) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -1395,7 +1395,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { } Y_UNIT_TEST(Delete) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -1430,7 +1430,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { } Y_UNIT_TEST(DeleteAdd) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; @@ -1468,7 +1468,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) { } Y_UNIT_TEST(DeleteAndRestart) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); ui64 txId = 100; diff --git a/ydb/core/tx/tx_allocator/txallocator_impl.cpp b/ydb/core/tx/tx_allocator/txallocator_impl.cpp index a4940b8f35..9ff1dcbade 100644 --- a/ydb/core/tx/tx_allocator/txallocator_impl.cpp +++ b/ydb/core/tx/tx_allocator/txallocator_impl.cpp @@ -8,7 +8,7 @@ namespace NTxAllocator { TTxAllocator::TTxAllocator(const TActorId &tablet, TTabletStorageInfo *info) : TActor(&TThis::StateInit) - , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) + , TTabletExecutedFlat(info, tablet, new NMiniKQL::TMiniKQLFactory) , PrivateMarker((TabletID() & 0xFFFF) << (64 - 16)) { } diff --git a/ydb/core/tx/tx_allocator/txallocator_ut.cpp b/ydb/core/tx/tx_allocator/txallocator_ut.cpp index 11efd70cbc..d3ccf3cdd5 100644 --- a/ydb/core/tx/tx_allocator/txallocator_ut.cpp +++ b/ydb/core/tx/tx_allocator/txallocator_ut.cpp @@ -9,18 +9,18 @@ using namespace NTxAllocatorUT_Private; Y_UNIT_TEST_SUITE(TTxLocatorTest) { Y_UNIT_TEST(Boot) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); } Y_UNIT_TEST(TestZeroRange) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); AllocateAndCheck(runtime, 0, NKikimrTx::TEvTxAllocateResult::SUCCESS); } Y_UNIT_TEST(TestImposibleSize) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); const ui64 capacity = NTxAllocator::TTxAllocator::MaxCapacity; const ui64 requestSize = 123456; @@ -33,7 +33,7 @@ Y_UNIT_TEST_SUITE(TTxLocatorTest) { } Y_UNIT_TEST(TestAllocateAll) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); const ui64 capacity = NTxAllocator::TTxAllocator::MaxCapacity; AllocateAndCheck(runtime, capacity, NKikimrTx::TEvTxAllocateResult::SUCCESS); @@ -41,7 +41,7 @@ Y_UNIT_TEST_SUITE(TTxLocatorTest) { } Y_UNIT_TEST(TestAllocateAllByPieces) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); const ui64 capacity = NTxAllocator::TTxAllocator::MaxCapacity; const ui64 pieces = 1u << 5; @@ -56,7 +56,7 @@ Y_UNIT_TEST_SUITE(TTxLocatorTest) { } void DoSignificantRequests(const bool restartsEnable) { - TTestBasicRuntime runtime; + TTestBasicRuntime runtime; TTestEnv env(runtime); const ui64 rounds = 10; diff --git a/ydb/core/tx/tx_allocator/txallocator_ut_helpers.cpp b/ydb/core/tx/tx_allocator/txallocator_ut_helpers.cpp index 95566493b6..5d9543435b 100644 --- a/ydb/core/tx/tx_allocator/txallocator_ut_helpers.cpp +++ b/ydb/core/tx/tx_allocator/txallocator_ut_helpers.cpp @@ -74,7 +74,7 @@ void TTestEnv::SetupLogging(TTestActorRuntime &runtime) { void TTestEnv::Setup(TTestActorRuntime &runtime) { static constexpr ui32 domainId = 0; SetupLogging(runtime); - TAppPrepare app; + TAppPrepare app; auto domain = TDomainsInfo::TDomain::ConstructDomainWithExplicitTabletIds("dc-1", domainId, 0, domainId, domainId, TVector<ui32>{domainId}, domainId, TVector<ui32>{domainId}, @@ -85,7 +85,7 @@ void TTestEnv::Setup(TTestActorRuntime &runtime) { DefaultPoolKinds(2)); app.AddDomain(domain.Release()); //app.AddHive(0, 0); - SetupChannelProfiles(app); + SetupChannelProfiles(app); SetupTabletServices(runtime, &app, true); } diff --git a/ydb/core/util/pb.h b/ydb/core/util/pb.h index 81bf964f21..ccc2841ff6 100644 --- a/ydb/core/util/pb.h +++ b/ydb/core/util/pb.h @@ -3,7 +3,7 @@ #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/text_format.h> #include <util/stream/file.h> -#include <util/generic/array_ref.h> +#include <util/generic/array_ref.h> #include <util/system/type_name.h> namespace NKikimr { @@ -30,20 +30,20 @@ bool ParseBinPBFromFile(const TString &path, T *pb) { // Deserialize persisted protobuf without checking size limit (size should have checked before saving) template <class TProto> -bool ParseFromStringNoSizeLimit(TProto& proto, TArrayRef<const char> str) { +bool ParseFromStringNoSizeLimit(TProto& proto, TArrayRef<const char> str) { google::protobuf::io::CodedInputStream input(reinterpret_cast<const ui8*>(str.data()), str.size()); input.SetTotalBytesLimit(str.size()); return proto.ParseFromCodedStream(&input) && input.ConsumedEntireMessage(); } -template<typename TProto> -struct TProtoBox : public TProto { - TProtoBox(TArrayRef<const char> plain) { - bool ok = ParseFromStringNoSizeLimit(*this, plain); - Y_VERIFY(ok, "Cannot parse proto %s", TypeName<TProto>().c_str()); - } -}; - +template<typename TProto> +struct TProtoBox : public TProto { + TProtoBox(TArrayRef<const char> plain) { + bool ok = ParseFromStringNoSizeLimit(*this, plain); + Y_VERIFY(ok, "Cannot parse proto %s", TypeName<TProto>().c_str()); + } +}; + // Deserialized and merge persisted protobuf without checking size limit template <class TProto> bool MergeFromStringNoSizeLimit(TProto& proto, TArrayRef<const char> str) { diff --git a/ydb/core/viewer/browse.h b/ydb/core/viewer/browse.h index c5716f46a7..f9c1d6bd3a 100644 --- a/ydb/core/viewer/browse.h +++ b/ydb/core/viewer/browse.h @@ -596,15 +596,15 @@ public: THolder<TEvTablet::TEvGetCountersResponse> response = AggregateWhiteboardResponses(TabletCountersResults); ui64 dataSize = 0; - dataSize += GetCounterValue(response->Record.GetTabletCounters().GetExecutorCounters().GetSimpleCounters(), "LogRedoMemory"); - dataSize += GetCounterValue(response->Record.GetTabletCounters().GetExecutorCounters().GetSimpleCounters(), "DbIndexBytes"); - dataSize += GetCounterValue(response->Record.GetTabletCounters().GetExecutorCounters().GetSimpleCounters(), "DbDataBytes"); + dataSize += GetCounterValue(response->Record.GetTabletCounters().GetExecutorCounters().GetSimpleCounters(), "LogRedoMemory"); + dataSize += GetCounterValue(response->Record.GetTabletCounters().GetExecutorCounters().GetSimpleCounters(), "DbIndexBytes"); + dataSize += GetCounterValue(response->Record.GetTabletCounters().GetExecutorCounters().GetSimpleCounters(), "DbDataBytes"); dataSize += GetCounterValue(response->Record.GetTabletCounters().GetAppCounters().GetSimpleCounters(), "KV/RecordBytes"); dataSize += GetCounterValue(response->Record.GetTabletCounters().GetAppCounters().GetSimpleCounters(), "KV/TrashBytes"); pbCommon.SetDataSize(dataSize); ui64 memSize = 0; - memSize += GetCounterValue(response->Record.GetTabletCounters().GetExecutorCounters().GetSimpleCounters(), "DbWarmBytes"); // not cache + memSize += GetCounterValue(response->Record.GetTabletCounters().GetExecutorCounters().GetSimpleCounters(), "DbWarmBytes"); // not cache memSize += GetCounterValue(response->Record.GetTabletCounters().GetExecutorCounters().GetSimpleCounters(), "CacheFreshSize"); // cache memSize += GetCounterValue(response->Record.GetTabletCounters().GetExecutorCounters().GetSimpleCounters(), "CacheStagingSize"); // cache memSize += GetCounterValue(response->Record.GetTabletCounters().GetExecutorCounters().GetSimpleCounters(), "CacheWarmSize"); // cache diff --git a/ydb/core/viewer/content/viewer.js b/ydb/core/viewer/content/viewer.js index 1108f42278..df7f1e80a0 100644 --- a/ydb/core/viewer/content/viewer.js +++ b/ydb/core/viewer/content/viewer.js @@ -2614,9 +2614,9 @@ function onTreeNodeChildrenDataSizeComplete(dataSizeCell, result) { return; } var dataSize = 0; - dataSize += getCounter(result.TabletCounters.ExecutorCounters.SimpleCounters, "LogRedoMemory"); - dataSize += getCounter(result.TabletCounters.ExecutorCounters.SimpleCounters, "DbIndexBytes"); - dataSize += getCounter(result.TabletCounters.ExecutorCounters.SimpleCounters, "DbDataBytes"); + dataSize += getCounter(result.TabletCounters.ExecutorCounters.SimpleCounters, "LogRedoMemory"); + dataSize += getCounter(result.TabletCounters.ExecutorCounters.SimpleCounters, "DbIndexBytes"); + dataSize += getCounter(result.TabletCounters.ExecutorCounters.SimpleCounters, "DbDataBytes"); dataSize += getCounter(result.TabletCounters.AppCounters.SimpleCounters, "KV/RecordBytes"); dataSize += getCounter(result.TabletCounters.AppCounters.SimpleCounters, "KV/TrashBytes"); dataSizeCell.innerHTML = bytesToSize(dataSize); diff --git a/ydb/core/viewer/json_content.h b/ydb/core/viewer/json_content.h index 79b230f128..93cf3b7d1e 100644 --- a/ydb/core/viewer/json_content.h +++ b/ydb/core/viewer/json_content.h @@ -36,12 +36,12 @@ public: {} STFUNC(StateWaitingBrowse) { - switch (ev->GetTypeRewrite()) { + switch (ev->GetTypeRewrite()) { HFunc(NViewerEvents::TEvBrowseResponse, HandleBrowseResponse); CFunc(TEvents::TSystem::Wakeup, HandleBrowseTimeout); - } - } - + } + } + public: void Bootstrap(const TActorContext& ctx) { BuildRequestContext(&Event->Get()->Request, ContentRequestContext); @@ -58,7 +58,7 @@ public: new TEvents::TEvWakeup()); } -private: +private: static void BuildRequestContext( const NMonitoring::IMonHttpRequest* httpRequest, IViewer::TContentRequestContext& reqCtx) { @@ -94,11 +94,11 @@ private: void HandleBrowseResponse(NViewerEvents::TEvBrowseResponse::TPtr &ev, const TActorContext &ctx) { NViewerEvents::TEvBrowseResponse& event = *ev->Get(); - + if (!event.Error.empty()) { return SendErrorReplyAndDie(event.Error, ctx); } - + auto type = event.BrowseInfo.GetType(); auto contentHandler = Viewer->GetContentHandler(type); if (!contentHandler) { diff --git a/ydb/core/yql_testlib/yql_testlib.cpp b/ydb/core/yql_testlib/yql_testlib.cpp index 35838c40f6..7ffdad4723 100644 --- a/ydb/core/yql_testlib/yql_testlib.cpp +++ b/ydb/core/yql_testlib/yql_testlib.cpp @@ -155,17 +155,17 @@ void TYqlServer::Initialize() { ResumeYqlExecutionPromise = NThreading::NewPromise<void>(); Runtime.Reset(new TTestActorRuntime(StaticNodes() + DynamicNodes(), true)); - + Runtime->SetupMonitoring(); - Runtime->SetLogBackend(GetSettings().LogBackend); - - TAppPrepare app; - - SetupDomains(app); - SetupChannelProfiles(app); - + Runtime->SetLogBackend(GetSettings().LogBackend); + + TAppPrepare app; + + SetupDomains(app); + SetupChannelProfiles(app); + app.AddHive(Settings->Domain, ChangeStateStorage(Hive, Settings->Domain)); - app.SetFnRegistry([this](const NKikimr::NScheme::TTypeRegistry& typeRegistry) -> NKikimr::NMiniKQL::IFunctionRegistry* { + app.SetFnRegistry([this](const NKikimr::NScheme::TTypeRegistry& typeRegistry) -> NKikimr::NMiniKQL::IFunctionRegistry* { Y_UNUSED(typeRegistry); // register test UDFs auto freg = NKikimr::NMiniKQL::CreateFunctionRegistry(NKikimr::NMiniKQL::CreateBuiltinRegistry())->Clone(); @@ -173,11 +173,11 @@ void TYqlServer::Initialize() { return freg.Release(); } ); - - SetupMessageBus(GetSettings().Port, GetSettings().TracePath); - + + SetupMessageBus(GetSettings().Port, GetSettings().TracePath); + SetupTabletServices(*Runtime, &app, StaticNodes() == 1 && Settings->EnableMockOnSingleNode, Settings->CustomDiskParams); - + CreateBootstrapTablets(); SetupStorage(); diff --git a/ydb/tests/library/common/types.py b/ydb/tests/library/common/types.py index 5ec564d65f..284deb662a 100644 --- a/ydb/tests/library/common/types.py +++ b/ydb/tests/library/common/types.py @@ -15,10 +15,10 @@ class DeltaTypes(IntEnum): DropColumn = 4, AddColumnToKey = 5, AddColumnToFamily = 6, - AddFamily = 7, + AddFamily = 7, UpdateExecutorInfo = 8, SetCompactionPolicy = 9, - SetRoom = 10, + SetRoom = 10, SetFamily = 11, SetRedo = 12, SetTable = 13 |