diff options
author | gvvinblade <gvvinblade@yandex-team.ru> | 2022-02-10 16:52:27 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:52:27 +0300 |
commit | 75bb4f570f7414195473e1290048787dddf72c4b (patch) | |
tree | ab7fbbf3253d4c0e2793218f09378908beb025fb | |
parent | bf6efae899490f740bacb87d68c25d06c8971f07 (diff) | |
download | ydb-75bb4f570f7414195473e1290048787dddf72c4b.tar.gz |
Restoring authorship annotation for <gvvinblade@yandex-team.ru>. Commit 2 of 2.
136 files changed, 5429 insertions, 5429 deletions
diff --git a/ydb/core/cms/console/config_index.cpp b/ydb/core/cms/console/config_index.cpp index 84ede08766..98ede70c6f 100644 --- a/ydb/core/cms/console/config_index.cpp +++ b/ydb/core/cms/console/config_index.cpp @@ -221,35 +221,35 @@ void MergeMessageOverwriteRepeated(::google::protobuf::Message &to, to.MergeFrom(from); } -void TScopedConfig::ComputeConfig(NKikimrConfig::TAppConfig &config, bool addVersion) const +void TScopedConfig::ComputeConfig(NKikimrConfig::TAppConfig &config, bool addVersion) const { for (auto &pr : ConfigItems) { NKikimrConfig::TAppConfig mergeResult; - MergeItems(pr.second, mergeResult, addVersion); + MergeItems(pr.second, mergeResult, addVersion); config.MergeFrom(mergeResult); } } -void TScopedConfig::ComputeConfig(const THashSet<ui32> &kinds, NKikimrConfig::TAppConfig &config, bool addVersion) const -{ - for (auto &pr : ConfigItems) { - if (kinds.contains(pr.first)) { - NKikimrConfig::TAppConfig mergeResult; - MergeItems(pr.second, mergeResult, addVersion); - config.MergeFrom(mergeResult); - } - } -} - +void TScopedConfig::ComputeConfig(const THashSet<ui32> &kinds, NKikimrConfig::TAppConfig &config, bool addVersion) const +{ + for (auto &pr : ConfigItems) { + if (kinds.contains(pr.first)) { + NKikimrConfig::TAppConfig mergeResult; + MergeItems(pr.second, mergeResult, addVersion); + config.MergeFrom(mergeResult); + } + } +} + void TScopedConfig::MergeItems(const TOrderedConfigItems &items, - NKikimrConfig::TAppConfig &config, bool addVersion) const + NKikimrConfig::TAppConfig &config, bool addVersion) const { for (auto &item : items) - MergeItem(item, config, addVersion); + MergeItem(item, config, addVersion); } void TScopedConfig::MergeItem(TConfigItem::TPtr item, - NKikimrConfig::TAppConfig &config, bool addVersion) const + NKikimrConfig::TAppConfig &config, bool addVersion) const { if (item->MergeStrategy == NKikimrConsole::TConfigItem::OVERWRITE) config.CopyFrom(item->Config); @@ -259,13 +259,13 @@ void TScopedConfig::MergeItem(TConfigItem::TPtr item, MergeMessageOverwriteRepeated(config, item->Config); else Y_FAIL("unexpected merge strategy %d", static_cast<int>(item->MergeStrategy)); - - if (addVersion) { - auto vItem = config.MutableVersion()->AddItems(); - vItem->SetKind(item->Kind); - vItem->SetId(item->Id); - vItem->SetGeneration(item->Generation); - } + + if (addVersion) { + auto vItem = config.MutableVersion()->AddItems(); + vItem->SetKind(item->Kind); + vItem->SetId(item->Id); + vItem->SetGeneration(item->Generation); + } } TConfigItem::TPtr TConfigIndex::GetItem(ui64 id) const @@ -689,98 +689,98 @@ void TSubscriptionIndex::RemoveSubscription(ui64 id) Subscriptions.erase(id); } -TInMemorySubscription::TPtr TInMemorySubscriptionIndex::GetSubscription(const TActorId &subscriber) -{ - auto it = Subscriptions.find(subscriber); - if (it == Subscriptions.end()) - return nullptr; - return it->second; -} - -const THashMap<TActorId, TInMemorySubscription::TPtr> &TInMemorySubscriptionIndex::GetSubscriptions() const -{ - return Subscriptions; -} - -void TInMemorySubscriptionIndex::AddSubscription(TInMemorySubscription::TPtr subscription) -{ - Y_VERIFY(!Subscriptions.contains(subscription->Subscriber)); - - Subscriptions.emplace(subscription->Subscriber, subscription); - - SubscriptionsByNodeId[subscription->NodeId].insert(subscription); - SubscriptionsByHost[subscription->Host].insert(subscription); - SubscriptionsByTenant[subscription->Tenant].insert(subscription); - SubscriptionsByNodeType[subscription->NodeType].insert(subscription); -} - -void TInMemorySubscriptionIndex::RemoveSubscription(const TActorId &subscriber) -{ - auto it = Subscriptions.find(subscriber); - Y_VERIFY(it != Subscriptions.end()); - auto subscription = it->second; - - RemoveFromIndex(subscription, subscription->NodeId, SubscriptionsByNodeId); - RemoveFromIndex(subscription, subscription->Host, SubscriptionsByHost); - RemoveFromIndex(subscription, subscription->Tenant, SubscriptionsByTenant); - RemoveFromIndex(subscription, subscription->NodeType, SubscriptionsByNodeType); - - Subscriptions.erase(it); -} - -void TInMemorySubscriptionIndex::CollectAffectedSubscriptions(const TUsageScope &scope, - ui32 kind, - TInMemorySubscriptionSet &subscriptions) const -{ - if (subscriptions.size() == Subscriptions.size()) - return; - - if (scope.NodeIds.empty() && scope.Hosts.empty() && !scope.Tenant && !scope.NodeType) { - for (auto &it : Subscriptions) { - if (it.second->ItemKinds.contains(kind)) - subscriptions.insert(it.second); - } - - return; - } - - for (ui32 nodeId : scope.NodeIds) { - auto it = SubscriptionsByNodeId.find(nodeId); - if (it != SubscriptionsByNodeId.end()) { - for (auto & subscription : it->second) - if (subscription->ItemKinds.contains(kind)) - subscriptions.insert(subscription); - } - } - - for (auto &host : scope.Hosts) { - auto it = SubscriptionsByHost.find(host); - if (it != SubscriptionsByHost.end()) { - for (auto & subscription : it->second) - if (subscription->ItemKinds.contains(kind)) - subscriptions.insert(subscription); - } - } - - if (scope.Tenant) { - auto it = SubscriptionsByTenant.find(scope.Tenant); - if (it != SubscriptionsByTenant.end()) { - for (auto & subscription : it->second) - if (subscription->ItemKinds.contains(kind)) - subscriptions.insert(subscription); - } - } - - if (scope.NodeType) { - auto it = SubscriptionsByNodeType.find(scope.NodeType); - if (it != SubscriptionsByNodeType.end()) { - for (auto & subscription : it->second) - if (subscription->ItemKinds.contains(kind)) - subscriptions.insert(subscription); - } - } -} - +TInMemorySubscription::TPtr TInMemorySubscriptionIndex::GetSubscription(const TActorId &subscriber) +{ + auto it = Subscriptions.find(subscriber); + if (it == Subscriptions.end()) + return nullptr; + return it->second; +} + +const THashMap<TActorId, TInMemorySubscription::TPtr> &TInMemorySubscriptionIndex::GetSubscriptions() const +{ + return Subscriptions; +} + +void TInMemorySubscriptionIndex::AddSubscription(TInMemorySubscription::TPtr subscription) +{ + Y_VERIFY(!Subscriptions.contains(subscription->Subscriber)); + + Subscriptions.emplace(subscription->Subscriber, subscription); + + SubscriptionsByNodeId[subscription->NodeId].insert(subscription); + SubscriptionsByHost[subscription->Host].insert(subscription); + SubscriptionsByTenant[subscription->Tenant].insert(subscription); + SubscriptionsByNodeType[subscription->NodeType].insert(subscription); +} + +void TInMemorySubscriptionIndex::RemoveSubscription(const TActorId &subscriber) +{ + auto it = Subscriptions.find(subscriber); + Y_VERIFY(it != Subscriptions.end()); + auto subscription = it->second; + + RemoveFromIndex(subscription, subscription->NodeId, SubscriptionsByNodeId); + RemoveFromIndex(subscription, subscription->Host, SubscriptionsByHost); + RemoveFromIndex(subscription, subscription->Tenant, SubscriptionsByTenant); + RemoveFromIndex(subscription, subscription->NodeType, SubscriptionsByNodeType); + + Subscriptions.erase(it); +} + +void TInMemorySubscriptionIndex::CollectAffectedSubscriptions(const TUsageScope &scope, + ui32 kind, + TInMemorySubscriptionSet &subscriptions) const +{ + if (subscriptions.size() == Subscriptions.size()) + return; + + if (scope.NodeIds.empty() && scope.Hosts.empty() && !scope.Tenant && !scope.NodeType) { + for (auto &it : Subscriptions) { + if (it.second->ItemKinds.contains(kind)) + subscriptions.insert(it.second); + } + + return; + } + + for (ui32 nodeId : scope.NodeIds) { + auto it = SubscriptionsByNodeId.find(nodeId); + if (it != SubscriptionsByNodeId.end()) { + for (auto & subscription : it->second) + if (subscription->ItemKinds.contains(kind)) + subscriptions.insert(subscription); + } + } + + for (auto &host : scope.Hosts) { + auto it = SubscriptionsByHost.find(host); + if (it != SubscriptionsByHost.end()) { + for (auto & subscription : it->second) + if (subscription->ItemKinds.contains(kind)) + subscriptions.insert(subscription); + } + } + + if (scope.Tenant) { + auto it = SubscriptionsByTenant.find(scope.Tenant); + if (it != SubscriptionsByTenant.end()) { + for (auto & subscription : it->second) + if (subscription->ItemKinds.contains(kind)) + subscriptions.insert(subscription); + } + } + + if (scope.NodeType) { + auto it = SubscriptionsByNodeType.find(scope.NodeType); + if (it != SubscriptionsByNodeType.end()) { + for (auto & subscription : it->second) + if (subscription->ItemKinds.contains(kind)) + subscriptions.insert(subscription); + } + } +} + void TSubscriptionIndex::CollectAffectedSubscriptions(const TUsageScope &scope, ui32 kind, TSubscriptionSet &subscriptions) const diff --git a/ydb/core/cms/console/config_index.h b/ydb/core/cms/console/config_index.h index d844756377..b332b90b8f 100644 --- a/ydb/core/cms/console/config_index.h +++ b/ydb/core/cms/console/config_index.h @@ -284,16 +284,16 @@ public: using TPtr = TIntrusivePtr<TScopedConfig>; // Merge all config items into resulting config. - void ComputeConfig(NKikimrConfig::TAppConfig &config, bool addVersion = false) const; + void ComputeConfig(NKikimrConfig::TAppConfig &config, bool addVersion = false) const; + + // Merge config items with given kinds into resulting config. + void ComputeConfig(const THashSet<ui32> &kinds, NKikimrConfig::TAppConfig &config, bool addVersion = false) const; - // Merge config items with given kinds into resulting config. - void ComputeConfig(const THashSet<ui32> &kinds, NKikimrConfig::TAppConfig &config, bool addVersion = false) const; - private: void MergeItems(const TOrderedConfigItems &items, - NKikimrConfig::TAppConfig &config, bool addVersion) const; + NKikimrConfig::TAppConfig &config, bool addVersion) const; void MergeItem(TConfigItem::TPtr item, - NKikimrConfig::TAppConfig &config, bool addVersion) const; + NKikimrConfig::TAppConfig &config, bool addVersion) const; public: // Here all config items included into the scope are listed. @@ -647,59 +647,59 @@ private: TSubscriptionSet EmptySubscriptionsSet; }; -struct TInMemorySubscription : public TThrRefBase { - using TPtr = TIntrusivePtr<TInMemorySubscription>; - - TActorId Subscriber; - ui64 Generation; - - ui32 NodeId; - TString Host; - TString Tenant; - TString NodeType; - THashSet<ui32> ItemKinds; - - NKikimrConfig::TConfigVersion LastProvided; - - TActorId Worker; -}; - -using TInMemorySubscriptionSet = THashSet<TInMemorySubscription::TPtr, TPtrHash>; - -class TInMemorySubscriptionIndex { -public: - void CollectAffectedSubscriptions(const TUsageScope &scope, ui32 kind, TInMemorySubscriptionSet &out) const; - - TInMemorySubscription::TPtr GetSubscription(const TActorId &subscriber); - - const THashMap<TActorId, TInMemorySubscription::TPtr> &GetSubscriptions() const; - - void AddSubscription(TInMemorySubscription::TPtr subscription); - - void RemoveSubscription(const TActorId &subscriber); - -private: - template <typename TKey> - void RemoveFromIndex(TInMemorySubscription::TPtr subscription, - const TKey &key, - THashMap<TKey, TInMemorySubscriptionSet> &index) - { - auto it = index.find(key); - Y_VERIFY(it != index.end()); - Y_VERIFY(it->second.contains(subscription)); - it->second.erase(subscription); - if (it->second.empty()) - index.erase(it); - } - - THashMap<TActorId, TInMemorySubscription::TPtr> Subscriptions; - - THashMap<ui32, TInMemorySubscriptionSet> SubscriptionsByNodeId; - THashMap<TString, TInMemorySubscriptionSet> SubscriptionsByHost; - THashMap<TString, TInMemorySubscriptionSet> SubscriptionsByTenant; - THashMap<TString, TInMemorySubscriptionSet> SubscriptionsByNodeType; -}; - +struct TInMemorySubscription : public TThrRefBase { + using TPtr = TIntrusivePtr<TInMemorySubscription>; + + TActorId Subscriber; + ui64 Generation; + + ui32 NodeId; + TString Host; + TString Tenant; + TString NodeType; + THashSet<ui32> ItemKinds; + + NKikimrConfig::TConfigVersion LastProvided; + + TActorId Worker; +}; + +using TInMemorySubscriptionSet = THashSet<TInMemorySubscription::TPtr, TPtrHash>; + +class TInMemorySubscriptionIndex { +public: + void CollectAffectedSubscriptions(const TUsageScope &scope, ui32 kind, TInMemorySubscriptionSet &out) const; + + TInMemorySubscription::TPtr GetSubscription(const TActorId &subscriber); + + const THashMap<TActorId, TInMemorySubscription::TPtr> &GetSubscriptions() const; + + void AddSubscription(TInMemorySubscription::TPtr subscription); + + void RemoveSubscription(const TActorId &subscriber); + +private: + template <typename TKey> + void RemoveFromIndex(TInMemorySubscription::TPtr subscription, + const TKey &key, + THashMap<TKey, TInMemorySubscriptionSet> &index) + { + auto it = index.find(key); + Y_VERIFY(it != index.end()); + Y_VERIFY(it->second.contains(subscription)); + it->second.erase(subscription); + if (it->second.empty()) + index.erase(it); + } + + THashMap<TActorId, TInMemorySubscription::TPtr> Subscriptions; + + THashMap<ui32, TInMemorySubscriptionSet> SubscriptionsByNodeId; + THashMap<TString, TInMemorySubscriptionSet> SubscriptionsByHost; + THashMap<TString, TInMemorySubscriptionSet> SubscriptionsByTenant; + THashMap<TString, TInMemorySubscriptionSet> SubscriptionsByNodeType; +}; + struct TSubscriptionModifications { TSubscriptionModifications() = default; TSubscriptionModifications(const TSubscriptionModifications &other) = default; diff --git a/ydb/core/cms/console/configs_cache.cpp b/ydb/core/cms/console/configs_cache.cpp index 3891de7f4e..9f69ceacb1 100644 --- a/ydb/core/cms/console/configs_cache.cpp +++ b/ydb/core/cms/console/configs_cache.cpp @@ -1,150 +1,150 @@ -#include "configs_cache.h" -#include "console_configs_subscriber.h" -#include "console.h" - +#include "configs_cache.h" +#include "console_configs_subscriber.h" +#include "console.h" + #include <ydb/core/base/appdata.h> #include <ydb/core/node_whiteboard/node_whiteboard.h> - -#include <util/stream/file.h> -#include <util/system/fs.h> - -#include <library/cpp/actors/core/actor_bootstrapped.h> -#include <google/protobuf/text_format.h> - -#if defined BLOG_DEBUG || defined BLOG_ERROR || defined BLOG_WARN -#error log macro definition clash -#endif - -#define BLOG_DEBUG(stream) LOG_DEBUG_S(*TlsActivationContext, NKikimrServices::CONFIGS_CACHE, stream) -#define BLOG_ERROR(stream) LOG_ERROR_S(*TlsActivationContext, NKikimrServices::CONFIGS_CACHE, stream) -#define BLOG_WARN(stream) LOG_WARN_S(*TlsActivationContext, NKikimrServices::CONFIGS_CACHE, stream) - -namespace NKikimr::NConsole { - -namespace { - constexpr auto TMP_FILE_SUFFIX = ".tmp"; - - const THashSet<ui32> DYNAMIC_KINDS({ - (ui32)NKikimrConsole::TConfigItem::LogConfigItem, - (ui32)NKikimrConsole::TConfigItem::TableProfilesConfigItem - }); - - struct TSave { - TString PathToConfigCacheFile; - - explicit TSave(TString pathToConfigCacheFile) - : PathToConfigCacheFile(std::move(pathToConfigCacheFile)) {} - - void operator()(const NKikimrConfig::TAppConfig &config) { - if (!PathToConfigCacheFile) - return; - - try { - TString configString; - if (!google::protobuf::TextFormat::PrintToString(config, &configString)) - ythrow yexception() << "Failed to serialize config protobuf to string"; - - auto cfgFilePath = PathToConfigCacheFile + TMP_FILE_SUFFIX; - TFileOutput cfgFile(cfgFilePath); - cfgFile << configString; - - if (!NFs::Rename(cfgFilePath, PathToConfigCacheFile)) - ythrow yexception() << "Failed to rename temporary file " << LastSystemError() << " " << LastSystemErrorText(); - } catch (const yexception &ex) { - BLOG_WARN("An exception occurred while saving config: " << ex.what()); - } - } - }; - - struct TLoad { - TString PathToConfigCacheFile; - - explicit TLoad(TString pathToConfigCacheFile) - : PathToConfigCacheFile(std::move(pathToConfigCacheFile)) {} - - void operator()(NKikimrConfig::TAppConfig &config) { - if (!PathToConfigCacheFile) - return; - - try { - auto configFile = TFileInput(PathToConfigCacheFile); - auto configString = configFile.ReadAll(); - if (!google::protobuf::TextFormat::ParseFromString(configFile.ReadAll(), &config)) - ythrow yexception() << "Failed to parse config protobuf from string"; - } catch (const yexception &ex) { - BLOG_WARN("An exception occurred while getting config from cache file: " << ex.what()); - } - }; - }; -} - -void TConfigsCache::Bootstrap(const TActorContext &ctx) { - auto group = GetServiceCounters(AppData(ctx)->Counters, "utils")->GetSubgroup("component", "configs_cache"); - OutdatedConfiguration = group->GetCounter("OutdatedConfiguration"); - - Load(CurrentConfig); - - BLOG_DEBUG("Restored configuration: " << CurrentConfig.ShortDebugString()); - - const auto minKind = NKikimrConsole::TConfigItem::EKind_MIN; - const auto maxKind = NKikimrConsole::TConfigItem::EKind_MAX; - - TVector<ui32> kinds; - for (ui32 kind = minKind; kind <= maxKind; kind++) { - if (kind == NKikimrConsole::TConfigItem::Auto || !NKikimrConsole::TConfigItem::EKind_IsValid(kind)) - continue; - kinds.push_back(kind); - } - - auto client = CreateConfigsSubscriber(SelfId(), kinds, CurrentConfig); + +#include <util/stream/file.h> +#include <util/system/fs.h> + +#include <library/cpp/actors/core/actor_bootstrapped.h> +#include <google/protobuf/text_format.h> + +#if defined BLOG_DEBUG || defined BLOG_ERROR || defined BLOG_WARN +#error log macro definition clash +#endif + +#define BLOG_DEBUG(stream) LOG_DEBUG_S(*TlsActivationContext, NKikimrServices::CONFIGS_CACHE, stream) +#define BLOG_ERROR(stream) LOG_ERROR_S(*TlsActivationContext, NKikimrServices::CONFIGS_CACHE, stream) +#define BLOG_WARN(stream) LOG_WARN_S(*TlsActivationContext, NKikimrServices::CONFIGS_CACHE, stream) + +namespace NKikimr::NConsole { + +namespace { + constexpr auto TMP_FILE_SUFFIX = ".tmp"; + + const THashSet<ui32> DYNAMIC_KINDS({ + (ui32)NKikimrConsole::TConfigItem::LogConfigItem, + (ui32)NKikimrConsole::TConfigItem::TableProfilesConfigItem + }); + + struct TSave { + TString PathToConfigCacheFile; + + explicit TSave(TString pathToConfigCacheFile) + : PathToConfigCacheFile(std::move(pathToConfigCacheFile)) {} + + void operator()(const NKikimrConfig::TAppConfig &config) { + if (!PathToConfigCacheFile) + return; + + try { + TString configString; + if (!google::protobuf::TextFormat::PrintToString(config, &configString)) + ythrow yexception() << "Failed to serialize config protobuf to string"; + + auto cfgFilePath = PathToConfigCacheFile + TMP_FILE_SUFFIX; + TFileOutput cfgFile(cfgFilePath); + cfgFile << configString; + + if (!NFs::Rename(cfgFilePath, PathToConfigCacheFile)) + ythrow yexception() << "Failed to rename temporary file " << LastSystemError() << " " << LastSystemErrorText(); + } catch (const yexception &ex) { + BLOG_WARN("An exception occurred while saving config: " << ex.what()); + } + } + }; + + struct TLoad { + TString PathToConfigCacheFile; + + explicit TLoad(TString pathToConfigCacheFile) + : PathToConfigCacheFile(std::move(pathToConfigCacheFile)) {} + + void operator()(NKikimrConfig::TAppConfig &config) { + if (!PathToConfigCacheFile) + return; + + try { + auto configFile = TFileInput(PathToConfigCacheFile); + auto configString = configFile.ReadAll(); + if (!google::protobuf::TextFormat::ParseFromString(configFile.ReadAll(), &config)) + ythrow yexception() << "Failed to parse config protobuf from string"; + } catch (const yexception &ex) { + BLOG_WARN("An exception occurred while getting config from cache file: " << ex.what()); + } + }; + }; +} + +void TConfigsCache::Bootstrap(const TActorContext &ctx) { + auto group = GetServiceCounters(AppData(ctx)->Counters, "utils")->GetSubgroup("component", "configs_cache"); + OutdatedConfiguration = group->GetCounter("OutdatedConfiguration"); + + Load(CurrentConfig); + + BLOG_DEBUG("Restored configuration: " << CurrentConfig.ShortDebugString()); + + const auto minKind = NKikimrConsole::TConfigItem::EKind_MIN; + const auto maxKind = NKikimrConsole::TConfigItem::EKind_MAX; + + TVector<ui32> kinds; + for (ui32 kind = minKind; kind <= maxKind; kind++) { + if (kind == NKikimrConsole::TConfigItem::Auto || !NKikimrConsole::TConfigItem::EKind_IsValid(kind)) + continue; + kinds.push_back(kind); + } + + auto client = CreateConfigsSubscriber(SelfId(), kinds, CurrentConfig); SubscriptionClient = ctx.RegisterWithSameMailbox(client); - - Become(&TThis::StateWork); -} - -void TConfigsCache::Handle(TEvConsole::TEvConfigSubscriptionNotification::TPtr &ev) { - auto &rec = ev->Get()->Record; - - CurrentConfig.Swap(rec.MutableConfig()); - - BLOG_DEBUG("Saving configuration: " << CurrentConfig.ShortDebugString()); - - Save(CurrentConfig); - - for (auto kind : rec.GetAffectedKinds()) { - if (!DYNAMIC_KINDS.contains(kind)) { - const TActorId wb = NNodeWhiteboard::MakeNodeWhiteboardServiceId(SelfId().NodeId()); - NKikimrWhiteboard::TSystemStateInfo info; - info.SetConfigState(NKikimrWhiteboard::Outdated); - Send(wb, new NNodeWhiteboard::TEvWhiteboard::TEvSystemStateUpdate(info)); - - *OutdatedConfiguration = 1; - } - } -} - -void TConfigsCache::Handle(TEvConsole::TEvConfigSubscriptionError::TPtr &ev, const TActorContext &ctx) { - auto &rec = ev->Get()->Record; - - BLOG_ERROR("Failed to create subscription " << rec.GetCode() << " " << rec.GetReason() << " will die"); - - Die(ctx); -} - -void TConfigsCache::Handle(TEvents::TEvPoisonPill::TPtr &/*ev*/, const TActorContext &ctx) { - BLOG_DEBUG("Received poison pill, will die"); - - Die(ctx); -} - -void TConfigsCache::Die(const TActorContext &ctx) { - if (SubscriptionClient) - Send(SubscriptionClient, new TEvents::TEvPoisonPill()); - - TBase::Die(ctx); -} - -IActor *CreateConfigsCacheActor(const TString &pathToConfigCacheFile) { - return new TConfigsCache(TSave(pathToConfigCacheFile), TLoad(pathToConfigCacheFile)); -} -} + + Become(&TThis::StateWork); +} + +void TConfigsCache::Handle(TEvConsole::TEvConfigSubscriptionNotification::TPtr &ev) { + auto &rec = ev->Get()->Record; + + CurrentConfig.Swap(rec.MutableConfig()); + + BLOG_DEBUG("Saving configuration: " << CurrentConfig.ShortDebugString()); + + Save(CurrentConfig); + + for (auto kind : rec.GetAffectedKinds()) { + if (!DYNAMIC_KINDS.contains(kind)) { + const TActorId wb = NNodeWhiteboard::MakeNodeWhiteboardServiceId(SelfId().NodeId()); + NKikimrWhiteboard::TSystemStateInfo info; + info.SetConfigState(NKikimrWhiteboard::Outdated); + Send(wb, new NNodeWhiteboard::TEvWhiteboard::TEvSystemStateUpdate(info)); + + *OutdatedConfiguration = 1; + } + } +} + +void TConfigsCache::Handle(TEvConsole::TEvConfigSubscriptionError::TPtr &ev, const TActorContext &ctx) { + auto &rec = ev->Get()->Record; + + BLOG_ERROR("Failed to create subscription " << rec.GetCode() << " " << rec.GetReason() << " will die"); + + Die(ctx); +} + +void TConfigsCache::Handle(TEvents::TEvPoisonPill::TPtr &/*ev*/, const TActorContext &ctx) { + BLOG_DEBUG("Received poison pill, will die"); + + Die(ctx); +} + +void TConfigsCache::Die(const TActorContext &ctx) { + if (SubscriptionClient) + Send(SubscriptionClient, new TEvents::TEvPoisonPill()); + + TBase::Die(ctx); +} + +IActor *CreateConfigsCacheActor(const TString &pathToConfigCacheFile) { + return new TConfigsCache(TSave(pathToConfigCacheFile), TLoad(pathToConfigCacheFile)); +} +} diff --git a/ydb/core/cms/console/configs_cache.h b/ydb/core/cms/console/configs_cache.h index 99a3fc8f02..08ba529799 100644 --- a/ydb/core/cms/console/configs_cache.h +++ b/ydb/core/cms/console/configs_cache.h @@ -1,63 +1,63 @@ -#pragma once - -#include "defs.h" -#include "console.h" - +#pragma once + +#include "defs.h" +#include "console.h" + #include <ydb/core/base/counters.h> #include <ydb/core/protos/config.pb.h> -#include <library/cpp/actors/core/actor.h> - -namespace NKikimr::NConsole { - -using TSaveCallback = std::function<void(const NKikimrConfig::TAppConfig&)>; -using TLoadCallback = std::function<void(NKikimrConfig::TAppConfig&)>; - -class TConfigsCache : public TActorBootstrapped<TConfigsCache> { - -using TBase = TActorBootstrapped<TConfigsCache>; - -public: - TConfigsCache(TSaveCallback save, TLoadCallback load) - : Save(std::move(save)) - , Load(std::move(load)) {} - - void Bootstrap(const TActorContext &ctx); - - STFUNC(StateWork) { - TRACE_EVENT(NKikimrServices::CONFIGS_CACHE); - switch (ev->GetTypeRewrite()) { - hFuncTraced(TEvConsole::TEvConfigSubscriptionNotification, Handle); - HFuncTraced(TEvConsole::TEvConfigSubscriptionError, Handle); - HFuncTraced(TEvents::TEvPoisonPill, Handle); - default: - Y_FAIL("unexpected event type: %" PRIx32 " event: %s", - ev->GetTypeRewrite(), ev->HasEvent() ? ev->GetBase()->ToString().data() : "serialized?"); - } - } - - void Handle(TEvConsole::TEvConfigSubscriptionNotification::TPtr &ev); - - void Handle(TEvConsole::TEvConfigSubscriptionError::TPtr &ev, const TActorContext &ctx); - - void Handle(TEvents::TEvPoisonPill::TPtr &ev, const TActorContext &ctx); - -protected: - void Die(const TActorContext &ctx) override; - -private: - const TSaveCallback Save; - const TLoadCallback Load; - - TActorId SubscriptionClient; - - NKikimrConfig::TAppConfig CurrentConfig; - - NMonitoring::TDynamicCounters::TCounterPtr OutdatedConfiguration; -}; - -IActor *CreateConfigsCacheActor(const TString &pathToConfigCacheFile); - -inline TActorId MakeConfigsCacheActorID(ui32 node = 0) { - return TActorId(node, "configscache"); -} -} +#include <library/cpp/actors/core/actor.h> + +namespace NKikimr::NConsole { + +using TSaveCallback = std::function<void(const NKikimrConfig::TAppConfig&)>; +using TLoadCallback = std::function<void(NKikimrConfig::TAppConfig&)>; + +class TConfigsCache : public TActorBootstrapped<TConfigsCache> { + +using TBase = TActorBootstrapped<TConfigsCache>; + +public: + TConfigsCache(TSaveCallback save, TLoadCallback load) + : Save(std::move(save)) + , Load(std::move(load)) {} + + void Bootstrap(const TActorContext &ctx); + + STFUNC(StateWork) { + TRACE_EVENT(NKikimrServices::CONFIGS_CACHE); + switch (ev->GetTypeRewrite()) { + hFuncTraced(TEvConsole::TEvConfigSubscriptionNotification, Handle); + HFuncTraced(TEvConsole::TEvConfigSubscriptionError, Handle); + HFuncTraced(TEvents::TEvPoisonPill, Handle); + default: + Y_FAIL("unexpected event type: %" PRIx32 " event: %s", + ev->GetTypeRewrite(), ev->HasEvent() ? ev->GetBase()->ToString().data() : "serialized?"); + } + } + + void Handle(TEvConsole::TEvConfigSubscriptionNotification::TPtr &ev); + + void Handle(TEvConsole::TEvConfigSubscriptionError::TPtr &ev, const TActorContext &ctx); + + void Handle(TEvents::TEvPoisonPill::TPtr &ev, const TActorContext &ctx); + +protected: + void Die(const TActorContext &ctx) override; + +private: + const TSaveCallback Save; + const TLoadCallback Load; + + TActorId SubscriptionClient; + + NKikimrConfig::TAppConfig CurrentConfig; + + NMonitoring::TDynamicCounters::TCounterPtr OutdatedConfiguration; +}; + +IActor *CreateConfigsCacheActor(const TString &pathToConfigCacheFile); + +inline TActorId MakeConfigsCacheActorID(ui32 node = 0) { + return TActorId(node, "configscache"); +} +} diff --git a/ydb/core/cms/console/configs_cache_ut.cpp b/ydb/core/cms/console/configs_cache_ut.cpp index 6b08707267..501fd98e90 100644 --- a/ydb/core/cms/console/configs_cache_ut.cpp +++ b/ydb/core/cms/console/configs_cache_ut.cpp @@ -1,7 +1,7 @@ -#include "ut_helpers.h" -#include "console_configs_manager.h" -#include "configs_cache.h" - +#include "ut_helpers.h" +#include "console_configs_manager.h" +#include "configs_cache.h" + #include <ydb/core/base/counters.h> #include <ydb/core/node_whiteboard/node_whiteboard.h> #include <ydb/core/base/path.h> @@ -9,324 +9,324 @@ #include <ydb/core/tablet/bootstrapper.h> #include <ydb/core/tablet_flat/tablet_flat_executed.h> #include <ydb/core/testlib/tablet_helpers.h> - -#include <library/cpp/actors/interconnect/interconnect_impl.h> - + +#include <library/cpp/actors/interconnect/interconnect_impl.h> + #include <ydb/core/testlib/tenant_runtime.h> -#include <library/cpp/testing/unittest/registar.h> - -#include <util/system/hostname.h> - -namespace NKikimr { - -using namespace NConsole; -using namespace NConsole::NUT; - -namespace { - -void Canonize(NKikimrConfig::TConfigVersion *version) { - auto items = version->MutableItems(); - std::sort(items->begin(), items->end(), [](auto i1, auto i2) { - if (i1.GetKind() != i2.GetKind()) - return i1.GetKind() < i2.GetKind(); - else if (i1.GetId() != i2.GetId()) - return i1.GetId() < i2.GetId(); - else - return i1.GetGeneration() < i2.GetGeneration(); - }); -} - -TTenantTestConfig::TTenantPoolConfig DefaultTenantPoolConfig() -{ - TTenantTestConfig::TTenantPoolConfig res = { - // Static slots {tenant, {cpu, memory, network}} - {{ {DOMAIN1_NAME, {1, 1, 1}} }}, - // Dynamic slots {id, type, domain, tenant, {cpu, memory, network}} - {}, - // NodeType - "type1" - }; - return res; -} - -TTenantTestConfig DefaultTestConfig() -{ - TTenantTestConfig res = { - // Domains {name, schemeshard {{ subdomain_names }}} - {{ {DOMAIN1_NAME, SCHEME_SHARD1_ID, TVector<TString>()} }}, - // HiveId - HIVE_ID, - // FakeTenantSlotBroker - true, - // FakeSchemeShard - false, - // CreateConsole - true, - // Nodes {tenant_pool_config, data_center} - {{ - {DefaultTenantPoolConfig()}, - }}, - // DataCenterCount - 1, - // CreateConfigsDispatcher - true - }; - return res; -} - -NKikimrConsole::TConfigItem ITEM_DOMAIN_LOG_1; -NKikimrConsole::TConfigItem ITEM_DOMAIN_LOG_2; -NKikimrConsole::TConfigItem ITEM_DOMAIN_TENANT_POOL_1; - -void InitializeTestConfigItems() -{ - ITEM_DOMAIN_LOG_1 = - MakeConfigItem(NKikimrConsole::TConfigItem::LogConfigItem, - NKikimrConfig::TAppConfig(), {}, {}, "", "", 1, - NKikimrConsole::TConfigItem::MERGE, ""); - - ITEM_DOMAIN_LOG_2 = - MakeConfigItem(NKikimrConsole::TConfigItem::LogConfigItem, - NKikimrConfig::TAppConfig(), {}, {}, "", "", 2, - NKikimrConsole::TConfigItem::OVERWRITE, ""); - - ITEM_DOMAIN_TENANT_POOL_1 - = MakeConfigItem(NKikimrConsole::TConfigItem::TenantPoolConfigItem, - NKikimrConfig::TAppConfig(), {}, {}, "", "", 1, - NKikimrConsole::TConfigItem::MERGE, ""); -} - -void AwaitForCondition(const TTenantTestRuntime &runtime, const std::function<bool()> &cond, TDuration simTimeout = TDuration::Max()) { - TInstant deadline = runtime.GetCurrentTime() + simTimeout; - while (!cond() && runtime.GetCurrentTime() < deadline) { - Sleep(TDuration::MilliSeconds(100)); - } - - UNIT_ASSERT(cond()); -} - -struct TEvPrivate { - enum EEv { - EvSaveConfig = EventSpaceBegin(NKikimr::TKikimrEvents::ES_PRIVATE), - EvEnd - }; - - struct TEvSaveConfig : public TEventLocal<TEvSaveConfig, EvSaveConfig> { - TEvSaveConfig(NKikimrConfig::TAppConfig config) - : Config(config) {} - - NKikimrConfig::TAppConfig Config; - }; -}; - -} - -Y_UNIT_TEST_SUITE(TConfigsCacheTests) { - Y_UNIT_TEST(TestNoNotificationIfConfigIsCached) { - TTenantTestRuntime runtime(DefaultTestConfig()); - InitializeTestConfigItems(); - - ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-1"); - CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeAddAction(ITEM_DOMAIN_LOG_1)); - - TSaveCallback save = [](auto&) { - Y_ASSERT(false); - }; - - TLoadCallback load = [](auto &config) { - config.MutableLogConfig()->SetClusterName("cluster-1"); - auto item = config.MutableVersion()->AddItems(); - item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); - item->SetId(1); - item->SetGeneration(1); - }; - - auto actor = new TConfigsCache(save, load); - runtime.Register(actor); - - TDispatchOptions options; - options.FinalEvents.emplace_back(TEvConsole::EvConfigSubscriptionResponse, 1); - runtime.DispatchEvents(options); - } - - Y_UNIT_TEST(TestFullConfigurationRestore) { - TTenantTestRuntime runtime(DefaultTestConfig()); - InitializeTestConfigItems(); - - ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-1"); - CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeAddAction(ITEM_DOMAIN_LOG_1)); - - auto edge = runtime.AllocateEdgeActor(); - - TSaveCallback save = [&runtime, &edge](auto &config) { - runtime.Send(new IEventHandle(runtime.Sender, edge, new TEvPrivate::TEvSaveConfig(config))); - }; - - TLoadCallback load = [](auto&) {}; - - auto actor = new TConfigsCache(save, load); - runtime.Register(actor); - - NKikimrConfig::TAppConfig expected; - expected.MutableLogConfig()->SetClusterName("cluster-1"); - - auto item = expected.MutableVersion()->AddItems(); - item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); - item->SetId(1); - item->SetGeneration(1); - - TAutoPtr<IEventHandle> handle; - auto saved = runtime.GrabEdgeEventRethrow<TEvPrivate::TEvSaveConfig>(handle)->Config; - - UNIT_ASSERT_VALUES_EQUAL(expected.ShortDebugString(), saved.ShortDebugString()); - } - - Y_UNIT_TEST(TestConfigurationSaveOnNotification) { - TTenantTestRuntime runtime(DefaultTestConfig()); - InitializeTestConfigItems(); - - auto edge = runtime.AllocateEdgeActor(); - - TSaveCallback save = [&runtime, &edge](auto &config) { - runtime.Send(new IEventHandle(runtime.Sender, edge, new TEvPrivate::TEvSaveConfig(config))); - }; - - TLoadCallback load = [](auto&) {}; - - auto actor = new TConfigsCache(save, load); - runtime.Register(actor); - - TDispatchOptions options; - options.FinalEvents.emplace_back(TEvConsole::EvConfigSubscriptionResponse, 1); - runtime.DispatchEvents(options); - - ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-1"); - CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeAddAction(ITEM_DOMAIN_LOG_1)); - - NKikimrConfig::TAppConfig expected; - expected.MutableLogConfig()->SetClusterName("cluster-1"); - - auto item = expected.MutableVersion()->AddItems(); - item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); - item->SetId(1); - item->SetGeneration(1); - - TAutoPtr<IEventHandle> handle; - auto saved = runtime.GrabEdgeEventRethrow<TEvPrivate::TEvSaveConfig>(handle)->Config; - - UNIT_ASSERT_VALUES_EQUAL(expected.ShortDebugString(), saved.ShortDebugString()); - } - - Y_UNIT_TEST(TestOverwrittenConfigurationDoesntCauseNotification) { - TTenantTestRuntime runtime(DefaultTestConfig()); - InitializeTestConfigItems(); - - auto group = GetServiceCounters(runtime.GetDynamicCounters(0), "utils")->GetSubgroup("component", "configs_cache"); - auto inconsistent = group->GetCounter("InconsistentConfiguration"); - - UNIT_ASSERT(*inconsistent == 0); - - ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-1"); - ITEM_DOMAIN_LOG_2.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-2"); - - auto ids = CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, - MakeAddAction(ITEM_DOMAIN_LOG_1), - MakeAddAction(ITEM_DOMAIN_LOG_2)); - - AssignIds(ids, ITEM_DOMAIN_LOG_1, ITEM_DOMAIN_LOG_2); - - ui32 saves = 0; - TSaveCallback save = [&saves](auto&) { - saves++; - }; - - TLoadCallback load = [](auto&) {}; - - auto actor = new TConfigsCache(save, load); - runtime.Register(actor); - - TDispatchOptions options; - options.FinalEvents.emplace_back(TEvConsole::EvConfigSubscriptionResponse, 1); - runtime.DispatchEvents(options); - - AwaitForCondition(runtime, [&saves]() { return saves > 0; }, TDuration::MilliSeconds(5000)); - - UNIT_ASSERT_EQUAL(saves, 1); - - ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-3"); - - CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeModifyAction(ITEM_DOMAIN_LOG_1)); - - Sleep(TDuration::MilliSeconds(300)); - - UNIT_ASSERT_EQUAL(saves, 1); - } - - Y_UNIT_TEST(TestConfigurationChangeSensor) { - TTenantTestRuntime runtime(DefaultTestConfig()); - InitializeTestConfigItems(); - - auto edge = runtime.AllocateEdgeActor(); - - TSaveCallback save = [&runtime, &edge](auto &config) { - runtime.Send(new IEventHandle(runtime.Sender, edge, new TEvPrivate::TEvSaveConfig(config))); - }; - - TLoadCallback load = [](auto&) {}; - - auto actor = new TConfigsCache(save, load); - runtime.Register(actor); - - TDispatchOptions options; - options.FinalEvents.emplace_back(TEvConsole::EvConfigSubscriptionResponse, 1); - runtime.DispatchEvents(options); - - auto group = GetServiceCounters(runtime.GetDynamicCounters(0), "utils")->GetSubgroup("component", "configs_cache"); - auto outdated = group->GetCounter("OutdatedConfiguration"); - - UNIT_ASSERT(*outdated == 0); - - ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-1"); - CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeAddAction(ITEM_DOMAIN_LOG_1)); - - NKikimrConfig::TAppConfig expected; - expected.MutableLogConfig()->SetClusterName("cluster-1"); - { - auto item = expected.MutableVersion()->AddItems(); - item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); - item->SetId(1); - item->SetGeneration(1); - } - - TAutoPtr<IEventHandle> handle1; - auto saved1 = runtime.GrabEdgeEventRethrow<TEvPrivate::TEvSaveConfig>(handle1)->Config; - - Canonize(expected.MutableVersion()); - Canonize(saved1.MutableVersion()); - - UNIT_ASSERT_VALUES_EQUAL(expected.ShortDebugString(), saved1.ShortDebugString()); - UNIT_ASSERT(*outdated == 0); // log config change doesn't require node restart - - ITEM_DOMAIN_TENANT_POOL_1.MutableConfig()->MutableTenantPoolConfig()->SetNodeType("nodeType"); - CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeAddAction(ITEM_DOMAIN_TENANT_POOL_1)); - - auto tenantPool = expected.MutableTenantPoolConfig(); - tenantPool->SetNodeType("nodeType"); - { - auto item = expected.MutableVersion()->AddItems(); - item->SetKind(NKikimrConsole::TConfigItem::TenantPoolConfigItem); - item->SetId(2); - item->SetGeneration(1); - } - - TAutoPtr<IEventHandle> handle2; - auto saved2 = runtime.GrabEdgeEventRethrow<TEvPrivate::TEvSaveConfig>(handle2)->Config; - - Canonize(expected.MutableVersion()); - Canonize(saved2.MutableVersion()); - - UNIT_ASSERT_VALUES_EQUAL(expected.ShortDebugString(), saved2.ShortDebugString()); - UNIT_ASSERT(*outdated == 1); - } -} -} +#include <library/cpp/testing/unittest/registar.h> + +#include <util/system/hostname.h> + +namespace NKikimr { + +using namespace NConsole; +using namespace NConsole::NUT; + +namespace { + +void Canonize(NKikimrConfig::TConfigVersion *version) { + auto items = version->MutableItems(); + std::sort(items->begin(), items->end(), [](auto i1, auto i2) { + if (i1.GetKind() != i2.GetKind()) + return i1.GetKind() < i2.GetKind(); + else if (i1.GetId() != i2.GetId()) + return i1.GetId() < i2.GetId(); + else + return i1.GetGeneration() < i2.GetGeneration(); + }); +} + +TTenantTestConfig::TTenantPoolConfig DefaultTenantPoolConfig() +{ + TTenantTestConfig::TTenantPoolConfig res = { + // Static slots {tenant, {cpu, memory, network}} + {{ {DOMAIN1_NAME, {1, 1, 1}} }}, + // Dynamic slots {id, type, domain, tenant, {cpu, memory, network}} + {}, + // NodeType + "type1" + }; + return res; +} + +TTenantTestConfig DefaultTestConfig() +{ + TTenantTestConfig res = { + // Domains {name, schemeshard {{ subdomain_names }}} + {{ {DOMAIN1_NAME, SCHEME_SHARD1_ID, TVector<TString>()} }}, + // HiveId + HIVE_ID, + // FakeTenantSlotBroker + true, + // FakeSchemeShard + false, + // CreateConsole + true, + // Nodes {tenant_pool_config, data_center} + {{ + {DefaultTenantPoolConfig()}, + }}, + // DataCenterCount + 1, + // CreateConfigsDispatcher + true + }; + return res; +} + +NKikimrConsole::TConfigItem ITEM_DOMAIN_LOG_1; +NKikimrConsole::TConfigItem ITEM_DOMAIN_LOG_2; +NKikimrConsole::TConfigItem ITEM_DOMAIN_TENANT_POOL_1; + +void InitializeTestConfigItems() +{ + ITEM_DOMAIN_LOG_1 = + MakeConfigItem(NKikimrConsole::TConfigItem::LogConfigItem, + NKikimrConfig::TAppConfig(), {}, {}, "", "", 1, + NKikimrConsole::TConfigItem::MERGE, ""); + + ITEM_DOMAIN_LOG_2 = + MakeConfigItem(NKikimrConsole::TConfigItem::LogConfigItem, + NKikimrConfig::TAppConfig(), {}, {}, "", "", 2, + NKikimrConsole::TConfigItem::OVERWRITE, ""); + + ITEM_DOMAIN_TENANT_POOL_1 + = MakeConfigItem(NKikimrConsole::TConfigItem::TenantPoolConfigItem, + NKikimrConfig::TAppConfig(), {}, {}, "", "", 1, + NKikimrConsole::TConfigItem::MERGE, ""); +} + +void AwaitForCondition(const TTenantTestRuntime &runtime, const std::function<bool()> &cond, TDuration simTimeout = TDuration::Max()) { + TInstant deadline = runtime.GetCurrentTime() + simTimeout; + while (!cond() && runtime.GetCurrentTime() < deadline) { + Sleep(TDuration::MilliSeconds(100)); + } + + UNIT_ASSERT(cond()); +} + +struct TEvPrivate { + enum EEv { + EvSaveConfig = EventSpaceBegin(NKikimr::TKikimrEvents::ES_PRIVATE), + EvEnd + }; + + struct TEvSaveConfig : public TEventLocal<TEvSaveConfig, EvSaveConfig> { + TEvSaveConfig(NKikimrConfig::TAppConfig config) + : Config(config) {} + + NKikimrConfig::TAppConfig Config; + }; +}; + +} + +Y_UNIT_TEST_SUITE(TConfigsCacheTests) { + Y_UNIT_TEST(TestNoNotificationIfConfigIsCached) { + TTenantTestRuntime runtime(DefaultTestConfig()); + InitializeTestConfigItems(); + + ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-1"); + CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeAddAction(ITEM_DOMAIN_LOG_1)); + + TSaveCallback save = [](auto&) { + Y_ASSERT(false); + }; + + TLoadCallback load = [](auto &config) { + config.MutableLogConfig()->SetClusterName("cluster-1"); + auto item = config.MutableVersion()->AddItems(); + item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); + item->SetId(1); + item->SetGeneration(1); + }; + + auto actor = new TConfigsCache(save, load); + runtime.Register(actor); + + TDispatchOptions options; + options.FinalEvents.emplace_back(TEvConsole::EvConfigSubscriptionResponse, 1); + runtime.DispatchEvents(options); + } + + Y_UNIT_TEST(TestFullConfigurationRestore) { + TTenantTestRuntime runtime(DefaultTestConfig()); + InitializeTestConfigItems(); + + ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-1"); + CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeAddAction(ITEM_DOMAIN_LOG_1)); + + auto edge = runtime.AllocateEdgeActor(); + + TSaveCallback save = [&runtime, &edge](auto &config) { + runtime.Send(new IEventHandle(runtime.Sender, edge, new TEvPrivate::TEvSaveConfig(config))); + }; + + TLoadCallback load = [](auto&) {}; + + auto actor = new TConfigsCache(save, load); + runtime.Register(actor); + + NKikimrConfig::TAppConfig expected; + expected.MutableLogConfig()->SetClusterName("cluster-1"); + + auto item = expected.MutableVersion()->AddItems(); + item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); + item->SetId(1); + item->SetGeneration(1); + + TAutoPtr<IEventHandle> handle; + auto saved = runtime.GrabEdgeEventRethrow<TEvPrivate::TEvSaveConfig>(handle)->Config; + + UNIT_ASSERT_VALUES_EQUAL(expected.ShortDebugString(), saved.ShortDebugString()); + } + + Y_UNIT_TEST(TestConfigurationSaveOnNotification) { + TTenantTestRuntime runtime(DefaultTestConfig()); + InitializeTestConfigItems(); + + auto edge = runtime.AllocateEdgeActor(); + + TSaveCallback save = [&runtime, &edge](auto &config) { + runtime.Send(new IEventHandle(runtime.Sender, edge, new TEvPrivate::TEvSaveConfig(config))); + }; + + TLoadCallback load = [](auto&) {}; + + auto actor = new TConfigsCache(save, load); + runtime.Register(actor); + + TDispatchOptions options; + options.FinalEvents.emplace_back(TEvConsole::EvConfigSubscriptionResponse, 1); + runtime.DispatchEvents(options); + + ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-1"); + CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeAddAction(ITEM_DOMAIN_LOG_1)); + + NKikimrConfig::TAppConfig expected; + expected.MutableLogConfig()->SetClusterName("cluster-1"); + + auto item = expected.MutableVersion()->AddItems(); + item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); + item->SetId(1); + item->SetGeneration(1); + + TAutoPtr<IEventHandle> handle; + auto saved = runtime.GrabEdgeEventRethrow<TEvPrivate::TEvSaveConfig>(handle)->Config; + + UNIT_ASSERT_VALUES_EQUAL(expected.ShortDebugString(), saved.ShortDebugString()); + } + + Y_UNIT_TEST(TestOverwrittenConfigurationDoesntCauseNotification) { + TTenantTestRuntime runtime(DefaultTestConfig()); + InitializeTestConfigItems(); + + auto group = GetServiceCounters(runtime.GetDynamicCounters(0), "utils")->GetSubgroup("component", "configs_cache"); + auto inconsistent = group->GetCounter("InconsistentConfiguration"); + + UNIT_ASSERT(*inconsistent == 0); + + ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-1"); + ITEM_DOMAIN_LOG_2.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-2"); + + auto ids = CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, + MakeAddAction(ITEM_DOMAIN_LOG_1), + MakeAddAction(ITEM_DOMAIN_LOG_2)); + + AssignIds(ids, ITEM_DOMAIN_LOG_1, ITEM_DOMAIN_LOG_2); + + ui32 saves = 0; + TSaveCallback save = [&saves](auto&) { + saves++; + }; + + TLoadCallback load = [](auto&) {}; + + auto actor = new TConfigsCache(save, load); + runtime.Register(actor); + + TDispatchOptions options; + options.FinalEvents.emplace_back(TEvConsole::EvConfigSubscriptionResponse, 1); + runtime.DispatchEvents(options); + + AwaitForCondition(runtime, [&saves]() { return saves > 0; }, TDuration::MilliSeconds(5000)); + + UNIT_ASSERT_EQUAL(saves, 1); + + ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-3"); + + CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeModifyAction(ITEM_DOMAIN_LOG_1)); + + Sleep(TDuration::MilliSeconds(300)); + + UNIT_ASSERT_EQUAL(saves, 1); + } + + Y_UNIT_TEST(TestConfigurationChangeSensor) { + TTenantTestRuntime runtime(DefaultTestConfig()); + InitializeTestConfigItems(); + + auto edge = runtime.AllocateEdgeActor(); + + TSaveCallback save = [&runtime, &edge](auto &config) { + runtime.Send(new IEventHandle(runtime.Sender, edge, new TEvPrivate::TEvSaveConfig(config))); + }; + + TLoadCallback load = [](auto&) {}; + + auto actor = new TConfigsCache(save, load); + runtime.Register(actor); + + TDispatchOptions options; + options.FinalEvents.emplace_back(TEvConsole::EvConfigSubscriptionResponse, 1); + runtime.DispatchEvents(options); + + auto group = GetServiceCounters(runtime.GetDynamicCounters(0), "utils")->GetSubgroup("component", "configs_cache"); + auto outdated = group->GetCounter("OutdatedConfiguration"); + + UNIT_ASSERT(*outdated == 0); + + ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-1"); + CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeAddAction(ITEM_DOMAIN_LOG_1)); + + NKikimrConfig::TAppConfig expected; + expected.MutableLogConfig()->SetClusterName("cluster-1"); + { + auto item = expected.MutableVersion()->AddItems(); + item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); + item->SetId(1); + item->SetGeneration(1); + } + + TAutoPtr<IEventHandle> handle1; + auto saved1 = runtime.GrabEdgeEventRethrow<TEvPrivate::TEvSaveConfig>(handle1)->Config; + + Canonize(expected.MutableVersion()); + Canonize(saved1.MutableVersion()); + + UNIT_ASSERT_VALUES_EQUAL(expected.ShortDebugString(), saved1.ShortDebugString()); + UNIT_ASSERT(*outdated == 0); // log config change doesn't require node restart + + ITEM_DOMAIN_TENANT_POOL_1.MutableConfig()->MutableTenantPoolConfig()->SetNodeType("nodeType"); + CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeAddAction(ITEM_DOMAIN_TENANT_POOL_1)); + + auto tenantPool = expected.MutableTenantPoolConfig(); + tenantPool->SetNodeType("nodeType"); + { + auto item = expected.MutableVersion()->AddItems(); + item->SetKind(NKikimrConsole::TConfigItem::TenantPoolConfigItem); + item->SetId(2); + item->SetGeneration(1); + } + + TAutoPtr<IEventHandle> handle2; + auto saved2 = runtime.GrabEdgeEventRethrow<TEvPrivate::TEvSaveConfig>(handle2)->Config; + + Canonize(expected.MutableVersion()); + Canonize(saved2.MutableVersion()); + + UNIT_ASSERT_VALUES_EQUAL(expected.ShortDebugString(), saved2.ShortDebugString()); + UNIT_ASSERT(*outdated == 1); + } +} +} diff --git a/ydb/core/cms/console/configs_dispatcher_ut.cpp b/ydb/core/cms/console/configs_dispatcher_ut.cpp index 0f6d06ebab..997d1ba451 100644 --- a/ydb/core/cms/console/configs_dispatcher_ut.cpp +++ b/ydb/core/cms/console/configs_dispatcher_ut.cpp @@ -480,14 +480,14 @@ Y_UNIT_TEST_SUITE(TConfigsDispatcherTests) { // Config should be requested from CMS. auto config1 = GetConfig(runtime, {(ui32)NKikimrConsole::TConfigItem::LogConfigItem}, false); - CheckEqualsIgnoringVersion(config, config1); + CheckEqualsIgnoringVersion(config, config1); UNIT_ASSERT(nodeConfigRequests > 0); // We didn't ask to cache, so config should still be requested from CMS. // This time ask to cache config. nodeConfigRequests = 0; auto config2 = GetConfig(runtime, {(ui32)NKikimrConsole::TConfigItem::LogConfigItem}, true); - CheckEqualsIgnoringVersion(config, config2); + CheckEqualsIgnoringVersion(config, config2); UNIT_ASSERT(nodeConfigRequests > 0); // Make sure subscription is online by using it with another subscriber. @@ -497,7 +497,7 @@ Y_UNIT_TEST_SUITE(TConfigsDispatcherTests) { // This time we should get config with no requests to CMS. nodeConfigRequests = 0; auto config3 = GetConfig(runtime, {(ui32)NKikimrConsole::TConfigItem::LogConfigItem}, true); - CheckEqualsIgnoringVersion(config, config3); + CheckEqualsIgnoringVersion(config, config3); UNIT_ASSERT_VALUES_EQUAL(nodeConfigRequests, 0); // Change config and expect dispatcher to process notification. @@ -507,7 +507,7 @@ Y_UNIT_TEST_SUITE(TConfigsDispatcherTests) { // Now we should get new config with no requests to CMS. config.MutableLogConfig()->SetClusterName("cluster2"); auto config4 = GetConfig(runtime, {(ui32)NKikimrConsole::TConfigItem::LogConfigItem}, true); - CheckEqualsIgnoringVersion(config, config4); + CheckEqualsIgnoringVersion(config, config4); UNIT_ASSERT_VALUES_EQUAL(nodeConfigRequests, 0); } diff --git a/ydb/core/cms/console/console.h b/ydb/core/cms/console/console.h index aa196b0997..934d4e97e4 100644 --- a/ydb/core/cms/console/console.h +++ b/ydb/core/cms/console/console.h @@ -37,9 +37,9 @@ struct TEvConsole { EvCheckConfigUpdatesRequest, EvListConfigValidatorsRequest, EvToggleConfigValidatorRequest, - EvConfigSubscriptionRequest, - EvConfigSubscriptionCanceled, - EvConfigSubscriptionNotification, + EvConfigSubscriptionRequest, + EvConfigSubscriptionCanceled, + EvConfigSubscriptionNotification, // responses EvCreateTenantResponse = EvCreateTenantRequest + 1024, @@ -67,8 +67,8 @@ struct TEvConsole { EvCheckConfigUpdatesResponse, EvListConfigValidatorsResponse, EvToggleConfigValidatorResponse, - EvConfigSubscriptionResponse, - EvConfigSubscriptionError, + EvConfigSubscriptionResponse, + EvConfigSubscriptionError, EvEnd }; @@ -188,58 +188,58 @@ struct TEvConsole { } }; - struct TEvConfigSubscriptionRequest : public TEventShortDebugPB<TEvConfigSubscriptionRequest, NKikimrConsole::TConfigSubscriptionRequest, EvConfigSubscriptionRequest> {}; - - struct TEvConfigSubscriptionResponse : public TEventShortDebugPB<TEvConfigSubscriptionResponse, NKikimrConsole::TConfigSubscriptionResponse, EvConfigSubscriptionResponse> { - TEvConfigSubscriptionResponse() = default; - - TEvConfigSubscriptionResponse(ui64 generation, Ydb::StatusIds::StatusCode code, TString reason = TString()) { - Record.SetGeneration(generation); - Record.MutableStatus()->SetCode(code); - if (reason) - Record.MutableStatus()->SetReason(std::move(reason)); - } - }; - - struct TEvConfigSubscriptionError : public TEventShortDebugPB<TEvConfigSubscriptionError, NKikimrConsole::TConfigSubscriptionError, EvConfigSubscriptionError> { - TEvConfigSubscriptionError() = default; - - TEvConfigSubscriptionError(Ydb::StatusIds::StatusCode code, TString reason) - { - Record.SetCode(code); - Record.SetReason(std::move(reason)); - } - }; - - struct TEvConfigSubscriptionCanceled : public TEventShortDebugPB<TEvConfigSubscriptionCanceled, NKikimrConsole::TConfigSubscriptionCanceled, EvConfigSubscriptionCanceled> { - TEvConfigSubscriptionCanceled() = default; - - explicit TEvConfigSubscriptionCanceled(ui64 generation) - { - Record.SetGeneration(generation); - } - }; - - struct TEvConfigSubscriptionNotification : public TEventShortDebugPB<TEvConfigSubscriptionNotification, NKikimrConsole::TConfigSubscriptionNotification, EvConfigSubscriptionNotification> { - TEvConfigSubscriptionNotification() = default; - - TEvConfigSubscriptionNotification(ui64 generation, NKikimrConfig::TAppConfig &&config, const THashSet<ui32> &affectedKinds) - { - Record.SetGeneration(generation); - Record.MutableConfig()->Swap(&config); - for (ui32 kind : affectedKinds) - Record.AddAffectedKinds(kind); - } - - TEvConfigSubscriptionNotification(ui64 generation, const NKikimrConfig::TAppConfig &config, const THashSet<ui32> &affectedKinds) - { - Record.SetGeneration(generation); - Record.MutableConfig()->CopyFrom(config); - for (ui32 kind : affectedKinds) - Record.AddAffectedKinds(kind); - } - }; - + struct TEvConfigSubscriptionRequest : public TEventShortDebugPB<TEvConfigSubscriptionRequest, NKikimrConsole::TConfigSubscriptionRequest, EvConfigSubscriptionRequest> {}; + + struct TEvConfigSubscriptionResponse : public TEventShortDebugPB<TEvConfigSubscriptionResponse, NKikimrConsole::TConfigSubscriptionResponse, EvConfigSubscriptionResponse> { + TEvConfigSubscriptionResponse() = default; + + TEvConfigSubscriptionResponse(ui64 generation, Ydb::StatusIds::StatusCode code, TString reason = TString()) { + Record.SetGeneration(generation); + Record.MutableStatus()->SetCode(code); + if (reason) + Record.MutableStatus()->SetReason(std::move(reason)); + } + }; + + struct TEvConfigSubscriptionError : public TEventShortDebugPB<TEvConfigSubscriptionError, NKikimrConsole::TConfigSubscriptionError, EvConfigSubscriptionError> { + TEvConfigSubscriptionError() = default; + + TEvConfigSubscriptionError(Ydb::StatusIds::StatusCode code, TString reason) + { + Record.SetCode(code); + Record.SetReason(std::move(reason)); + } + }; + + struct TEvConfigSubscriptionCanceled : public TEventShortDebugPB<TEvConfigSubscriptionCanceled, NKikimrConsole::TConfigSubscriptionCanceled, EvConfigSubscriptionCanceled> { + TEvConfigSubscriptionCanceled() = default; + + explicit TEvConfigSubscriptionCanceled(ui64 generation) + { + Record.SetGeneration(generation); + } + }; + + struct TEvConfigSubscriptionNotification : public TEventShortDebugPB<TEvConfigSubscriptionNotification, NKikimrConsole::TConfigSubscriptionNotification, EvConfigSubscriptionNotification> { + TEvConfigSubscriptionNotification() = default; + + TEvConfigSubscriptionNotification(ui64 generation, NKikimrConfig::TAppConfig &&config, const THashSet<ui32> &affectedKinds) + { + Record.SetGeneration(generation); + Record.MutableConfig()->Swap(&config); + for (ui32 kind : affectedKinds) + Record.AddAffectedKinds(kind); + } + + TEvConfigSubscriptionNotification(ui64 generation, const NKikimrConfig::TAppConfig &config, const THashSet<ui32> &affectedKinds) + { + Record.SetGeneration(generation); + Record.MutableConfig()->CopyFrom(config); + for (ui32 kind : affectedKinds) + Record.AddAffectedKinds(kind); + } + }; + /** * If operation is unknown then TEvNotifyOperationCompletionResponse * is sent with NOT_FOUND status error. diff --git a/ydb/core/cms/console/console_configs_manager.h b/ydb/core/cms/console/console_configs_manager.h index a5dfab1dd3..2dca13be26 100644 --- a/ydb/core/cms/console/console_configs_manager.h +++ b/ydb/core/cms/console/console_configs_manager.h @@ -150,8 +150,8 @@ private: HFuncTraced(TEvInterconnect::TEvNodesInfo, Handle); HFuncTraced(TEvPrivate::TEvCleanupSubscriptions, Handle); HFuncTraced(TEvPrivate::TEvStateLoaded, Handle); - FFunc(TEvConsole::EvConfigSubscriptionRequest, ForwardToConfigsProvider); - FFunc(TEvConsole::EvConfigSubscriptionCanceled, ForwardToConfigsProvider); + FFunc(TEvConsole::EvConfigSubscriptionRequest, ForwardToConfigsProvider); + FFunc(TEvConsole::EvConfigSubscriptionCanceled, ForwardToConfigsProvider); default: Y_FAIL("TConfigsManager::StateWork unexpected event type: %" PRIx32 " event: %s", diff --git a/ydb/core/cms/console/console_configs_provider.cpp b/ydb/core/cms/console/console_configs_provider.cpp index a44f819a46..4ba6f46033 100644 --- a/ydb/core/cms/console/console_configs_provider.cpp +++ b/ydb/core/cms/console/console_configs_provider.cpp @@ -288,96 +288,96 @@ public: } }; -class TSubscriptionClientSender : public TActorBootstrapped<TSubscriptionClientSender> { - using TBase = TActorBootstrapped<TSubscriptionClientSender>; - -private: - TInMemorySubscription::TPtr Subscription; - TActorId OwnerId; - - ui64 NextOrder; - -public: - TSubscriptionClientSender(TInMemorySubscription::TPtr subscription, const TActorId &ownerId) - : Subscription(subscription) - , OwnerId(ownerId) - , NextOrder(1) - { - } - - void Bootstrap(const TActorContext &ctx) { - LOG_TRACE_S(ctx, NKikimrServices::CMS_CONFIGS, - "TSubscriptionClientSender(" << Subscription->Subscriber.ToString() << ") send TEvConfigSubscriptionResponse"); - - Send(Subscription->Subscriber, new TEvConsole::TEvConfigSubscriptionResponse(Subscription->Generation, Ydb::StatusIds::SUCCESS), - IEventHandle::FlagTrackDelivery | IEventHandle::FlagSubscribeOnSession); - Become(&TThis::StateWork); - } - - STFUNC(StateWork) { - TRACE_EVENT(NKikimrServices::CMS_CONFIGS); - - switch (ev->GetTypeRewrite()) { - HFuncTraced(TEvConsole::TEvConfigSubscriptionNotification, Handle); - HFuncTraced(TEvents::TEvPoisonPill, Handle); - HFuncTraced(TEvents::TEvUndelivered, Handle); - HFuncTraced(TEvInterconnect::TEvNodeDisconnected, Handle); - IgnoreFunc(TEvInterconnect::TEvNodeConnected); - - default: - Y_FAIL("unexpected event type: %" PRIx32 " event: %s", - ev->GetTypeRewrite(), ev->HasEvent() ? ev->GetBase()->ToString().data() : "serialized?"); - break; - } - } - - void Handle(TEvents::TEvPoisonPill::TPtr &/*ev*/, const TActorContext &ctx) - { - LOG_DEBUG_S(ctx, NKikimrServices::CMS_CONFIGS, - "TSubscriptionClientSender(" << Subscription->Subscriber.ToString() << ") received poison pill, " - << "will die."); - Die(ctx); - } - - void Handle(TEvents::TEvUndelivered::TPtr &/*ev*/, const TActorContext &ctx) - { - LOG_DEBUG_S(ctx, NKikimrServices::CMS_CONFIGS, - "TSubscriptionClientSender(" << Subscription->Subscriber.ToString() << ") received undelivered notification, " - << "will disconnect."); - - Send(OwnerId, new TConfigsProvider::TEvPrivate::TEvWorkerDisconnected(Subscription)); - Die(ctx); - } - - void Handle(TEvInterconnect::TEvNodeDisconnected::TPtr &/*ev*/, const TActorContext &ctx) - { - LOG_DEBUG_S(ctx, NKikimrServices::CMS_CONFIGS, - "TSubscriptionClientSender(" << Subscription->Subscriber.ToString() << ") received node disconnected notification, " - << "will disconnect."); - - Send(OwnerId, new TConfigsProvider::TEvPrivate::TEvWorkerDisconnected(Subscription)); - Die(ctx); - } - - void Handle(NConsole::TEvConsole::TEvConfigSubscriptionNotification::TPtr &ev, const TActorContext& ctx) - { - TAutoPtr<NConsole::TEvConsole::TEvConfigSubscriptionNotification> notification = ev->Release(); - notification.Get()->Record.SetOrder(NextOrder++); - - LOG_TRACE_S(ctx, NKikimrServices::CMS_CONFIGS, - "TSubscriptionClientSender(" << Subscription->Subscriber.ToString() << ") send TEvConfigSubscriptionNotificationRequest: " - << notification.Get()->Record.ShortDebugString()); - - Send(Subscription->Subscriber, notification.Release(), IEventHandle::FlagTrackDelivery | IEventHandle::FlagSubscribeOnSession); - } - -protected: - void Die(const TActorContext &ctx) override { - Send(TActivationContext::InterconnectProxy(Subscription->Subscriber.NodeId()), new TEvents::TEvUnsubscribe); - - TBase::Die(ctx); - } -}; +class TSubscriptionClientSender : public TActorBootstrapped<TSubscriptionClientSender> { + using TBase = TActorBootstrapped<TSubscriptionClientSender>; + +private: + TInMemorySubscription::TPtr Subscription; + TActorId OwnerId; + + ui64 NextOrder; + +public: + TSubscriptionClientSender(TInMemorySubscription::TPtr subscription, const TActorId &ownerId) + : Subscription(subscription) + , OwnerId(ownerId) + , NextOrder(1) + { + } + + void Bootstrap(const TActorContext &ctx) { + LOG_TRACE_S(ctx, NKikimrServices::CMS_CONFIGS, + "TSubscriptionClientSender(" << Subscription->Subscriber.ToString() << ") send TEvConfigSubscriptionResponse"); + + Send(Subscription->Subscriber, new TEvConsole::TEvConfigSubscriptionResponse(Subscription->Generation, Ydb::StatusIds::SUCCESS), + IEventHandle::FlagTrackDelivery | IEventHandle::FlagSubscribeOnSession); + Become(&TThis::StateWork); + } + + STFUNC(StateWork) { + TRACE_EVENT(NKikimrServices::CMS_CONFIGS); + + switch (ev->GetTypeRewrite()) { + HFuncTraced(TEvConsole::TEvConfigSubscriptionNotification, Handle); + HFuncTraced(TEvents::TEvPoisonPill, Handle); + HFuncTraced(TEvents::TEvUndelivered, Handle); + HFuncTraced(TEvInterconnect::TEvNodeDisconnected, Handle); + IgnoreFunc(TEvInterconnect::TEvNodeConnected); + + default: + Y_FAIL("unexpected event type: %" PRIx32 " event: %s", + ev->GetTypeRewrite(), ev->HasEvent() ? ev->GetBase()->ToString().data() : "serialized?"); + break; + } + } + + void Handle(TEvents::TEvPoisonPill::TPtr &/*ev*/, const TActorContext &ctx) + { + LOG_DEBUG_S(ctx, NKikimrServices::CMS_CONFIGS, + "TSubscriptionClientSender(" << Subscription->Subscriber.ToString() << ") received poison pill, " + << "will die."); + Die(ctx); + } + + void Handle(TEvents::TEvUndelivered::TPtr &/*ev*/, const TActorContext &ctx) + { + LOG_DEBUG_S(ctx, NKikimrServices::CMS_CONFIGS, + "TSubscriptionClientSender(" << Subscription->Subscriber.ToString() << ") received undelivered notification, " + << "will disconnect."); + + Send(OwnerId, new TConfigsProvider::TEvPrivate::TEvWorkerDisconnected(Subscription)); + Die(ctx); + } + + void Handle(TEvInterconnect::TEvNodeDisconnected::TPtr &/*ev*/, const TActorContext &ctx) + { + LOG_DEBUG_S(ctx, NKikimrServices::CMS_CONFIGS, + "TSubscriptionClientSender(" << Subscription->Subscriber.ToString() << ") received node disconnected notification, " + << "will disconnect."); + + Send(OwnerId, new TConfigsProvider::TEvPrivate::TEvWorkerDisconnected(Subscription)); + Die(ctx); + } + + void Handle(NConsole::TEvConsole::TEvConfigSubscriptionNotification::TPtr &ev, const TActorContext& ctx) + { + TAutoPtr<NConsole::TEvConsole::TEvConfigSubscriptionNotification> notification = ev->Release(); + notification.Get()->Record.SetOrder(NextOrder++); + + LOG_TRACE_S(ctx, NKikimrServices::CMS_CONFIGS, + "TSubscriptionClientSender(" << Subscription->Subscriber.ToString() << ") send TEvConfigSubscriptionNotificationRequest: " + << notification.Get()->Record.ShortDebugString()); + + Send(Subscription->Subscriber, notification.Release(), IEventHandle::FlagTrackDelivery | IEventHandle::FlagSubscribeOnSession); + } + +protected: + void Die(const TActorContext &ctx) override { + Send(TActivationContext::InterconnectProxy(Subscription->Subscriber.NodeId()), new TEvents::TEvUnsubscribe); + + TBase::Die(ctx); + } +}; } // anonymous namespace void TConfigsProvider::Bootstrap(const TActorContext &ctx) @@ -388,11 +388,11 @@ void TConfigsProvider::Bootstrap(const TActorContext &ctx) void TConfigsProvider::Die(const TActorContext &ctx) { - for (auto &it : InMemoryIndex.GetSubscriptions()) { - Send(it.second->Subscriber, new TEvConsole::TEvConfigSubscriptionCanceled(it.second->Generation)); - Send(it.second->Worker, new TEvents::TEvPoisonPill()); - } - + for (auto &it : InMemoryIndex.GetSubscriptions()) { + Send(it.second->Subscriber, new TEvConsole::TEvConfigSubscriptionCanceled(it.second->Generation)); + Send(it.second->Worker, new TEvents::TEvPoisonPill()); + } + TBase::Die(ctx); } @@ -408,14 +408,14 @@ void TConfigsProvider::ApplyConfigModifications(const TConfigModifications &modi LOG_TRACE(ctx, NKikimrServices::CMS_CONFIGS, "TConfigsProvider: applying config midifications"); TSubscriptionSet subscriptions; - TInMemorySubscriptionSet inMemorySubscriptions; + TInMemorySubscriptionSet inMemorySubscriptions; for (auto id : modifications.RemovedItems) { auto item = ConfigIndex.GetItem(id); LOG_TRACE_S(ctx, NKikimrServices::CMS_CONFIGS, "TConfigsProvider: remove " << item->ToString()); ConfigIndex.RemoveItem(id); SubscriptionIndex.CollectAffectedSubscriptions(item->UsageScope, item->Kind, subscriptions); - InMemoryIndex.CollectAffectedSubscriptions(item->UsageScope, item->Kind, inMemorySubscriptions); + InMemoryIndex.CollectAffectedSubscriptions(item->UsageScope, item->Kind, inMemorySubscriptions); } for (auto &pr : modifications.ModifiedItems) { auto item = ConfigIndex.GetItem(pr.first); @@ -427,21 +427,21 @@ void TConfigsProvider::ApplyConfigModifications(const TConfigModifications &modi ConfigIndex.AddItem(pr.second); SubscriptionIndex.CollectAffectedSubscriptions(item->UsageScope, item->Kind, subscriptions); - InMemoryIndex.CollectAffectedSubscriptions(item->UsageScope, item->Kind, inMemorySubscriptions); - if (item->UsageScope != pr.second->UsageScope) { + InMemoryIndex.CollectAffectedSubscriptions(item->UsageScope, item->Kind, inMemorySubscriptions); + if (item->UsageScope != pr.second->UsageScope) { SubscriptionIndex.CollectAffectedSubscriptions(pr.second->UsageScope, item->Kind, subscriptions); - InMemoryIndex.CollectAffectedSubscriptions(pr.second->UsageScope, item->Kind, inMemorySubscriptions); - } + InMemoryIndex.CollectAffectedSubscriptions(pr.second->UsageScope, item->Kind, inMemorySubscriptions); + } } for (auto item : modifications.AddedItems) { LOG_TRACE_S(ctx, NKikimrServices::CMS_CONFIGS, "TConfigsProvider: add new " << item->ToString()); ConfigIndex.AddItem(item); SubscriptionIndex.CollectAffectedSubscriptions(item->UsageScope, item->Kind, subscriptions); - InMemoryIndex.CollectAffectedSubscriptions(item->UsageScope, item->Kind, inMemorySubscriptions); + InMemoryIndex.CollectAffectedSubscriptions(item->UsageScope, item->Kind, inMemorySubscriptions); } CheckSubscriptions(subscriptions, ctx); - CheckSubscriptions(inMemorySubscriptions, ctx); + CheckSubscriptions(inMemorySubscriptions, ctx); } void TConfigsProvider::ApplySubscriptionModifications(const TSubscriptionModifications &modifications, @@ -508,13 +508,13 @@ void TConfigsProvider::CheckSubscriptions(const TSubscriptionSet &subscriptions, CheckSubscription(subscription, ctx); } -void TConfigsProvider::CheckSubscriptions(const TInMemorySubscriptionSet &subscriptions, - const TActorContext &ctx) -{ - for (auto &subscription : subscriptions) - CheckSubscription(subscription, ctx); -} - +void TConfigsProvider::CheckSubscriptions(const TInMemorySubscriptionSet &subscriptions, + const TActorContext &ctx) +{ + for (auto &subscription : subscriptions) + CheckSubscription(subscription, ctx); +} + void TConfigsProvider::CheckSubscription(TSubscription::TPtr subscription, const TActorContext &ctx) { @@ -573,164 +573,164 @@ void TConfigsProvider::CheckSubscription(TSubscription::TPtr subscription, subscription->Worker = ctx.RegisterWithSameMailbox(worker); } -void TConfigsProvider::CheckSubscription(TInMemorySubscription::TPtr subscription, - const TActorContext &ctx) -{ - LOG_TRACE_S(ctx, NKikimrServices::CMS_CONFIGS, - "TConfigsProvider: check if update is required for volatile subscription" - << " " << subscription->Subscriber.ToString() << ":" << subscription->Generation); - - auto config = ConfigIndex.BuildConfig(subscription->NodeId, subscription->Host, - subscription->Tenant, subscription->NodeType, - subscription->ItemKinds); - - THashMap<ui32, TConfigId> currKindIdMap; - THashMap<ui32, TConfigId> prevKindIdMap; - - for (auto kind : subscription->ItemKinds) { - auto it = config->ConfigItems.find(kind); - if (it != config->ConfigItems.end()) { - auto &id = currKindIdMap[kind]; - for (auto &item : it->second) { - if (item->MergeStrategy == NKikimrConsole::TConfigItem::OVERWRITE) - id.ItemIds.clear(); - id.ItemIds.push_back(std::make_pair(item->Id, item->Generation)); - } - } - } - for (auto &item : subscription->LastProvided.GetItems()) { - auto &id = prevKindIdMap[item.kind()]; - id.ItemIds.push_back(std::make_pair(item.GetId(), item.GetGeneration())); - } - - THashSet<ui32> affectedKinds; - NKikimrConfig::TConfigVersion version; - - for (auto &curr : currKindIdMap) { - auto prev = prevKindIdMap.find(curr.first); - - if (prev == prevKindIdMap.end() || curr.second != prev->second) { - // There are changes for the kind - affectedKinds.insert(curr.first); - for (auto &pr : curr.second.ItemIds) { - auto itemId = version.AddItems(); - itemId->SetKind(curr.first); - itemId->SetId(pr.first); - itemId->SetGeneration(pr.second); - } - } else if (prev != prevKindIdMap.end()) { - // There are no changes for the kind, lets just fill in current config ids - for (auto &pr : curr.second.ItemIds) { - auto itemId = version.AddItems(); - itemId->SetKind(curr.first); - itemId->SetId(pr.first); - itemId->SetGeneration(pr.second); - } - } - - if (prev != prevKindIdMap.end()) - prevKindIdMap.erase(prev); - } - - for (auto &prev : prevKindIdMap) { - // We already deleted all currently presented config kinds, so this one is definitely deleted - affectedKinds.insert(prev.first); - } - - if (affectedKinds.empty()) { - LOG_TRACE_S(ctx, NKikimrServices::CMS_CONFIGS, - "TConfigsProvider: no changes found for subscription" - << " " << subscription->Subscriber.ToString() << ":" << subscription->Generation); - return; - } - - LOG_TRACE_S(ctx, NKikimrServices::CMS_CONFIGS, - "TConfigsProvider: new config found for subscription" - << " " << subscription->Subscriber.ToString() << ":" << subscription->Generation - << " version=" << version.ShortDebugString()); - - subscription->LastProvided.Swap(&version); - - NKikimrConfig::TAppConfig appConfig; - config->ComputeConfig(affectedKinds, appConfig, true); - - Send(subscription->Worker, new TEvConsole::TEvConfigSubscriptionNotification(subscription->Generation, std::move(appConfig), affectedKinds)); -} - -void TConfigsProvider::Handle(TEvConsole::TEvConfigSubscriptionRequest::TPtr &ev, const TActorContext &ctx) -{ - auto subscriber = ev->Sender; - auto &rec = ev->Get()->Record; - - auto existing = InMemoryIndex.GetSubscription(subscriber); - if (existing) { - if (existing->Generation >= rec.GetGeneration()) { - LOG_DEBUG_S(ctx, NKikimrServices::CMS_CONFIGS, - "TConfigsProvider received stale subscription request " - << subscriber.ToString() << ":" << rec.GetGeneration()); - return; - } - - InMemoryIndex.RemoveSubscription(subscriber); - Send(existing->Worker, new TEvents::TEvPoisonPill()); - } - - TInMemorySubscription::TPtr subscription = new TInMemorySubscription(); - - subscription->Subscriber = subscriber; - subscription->Generation = rec.GetGeneration(); - - subscription->NodeId = rec.GetOptions().GetNodeId(); - subscription->Host = rec.GetOptions().GetHost(); - subscription->Tenant = rec.GetOptions().GetTenant(); - subscription->NodeType = rec.GetOptions().GetNodeType(); - - subscription->ItemKinds.insert(rec.GetConfigItemKinds().begin(), rec.GetConfigItemKinds().end()); - subscription->LastProvided.CopyFrom(rec.GetKnownVersion()); - - InMemoryIndex.AddSubscription(subscription); - - LOG_DEBUG_S(ctx, NKikimrServices::CMS_CONFIGS, - "TConfigsProvider registered new subscription " - << subscriber.ToString() << ":" << rec.GetGeneration()); - +void TConfigsProvider::CheckSubscription(TInMemorySubscription::TPtr subscription, + const TActorContext &ctx) +{ + LOG_TRACE_S(ctx, NKikimrServices::CMS_CONFIGS, + "TConfigsProvider: check if update is required for volatile subscription" + << " " << subscription->Subscriber.ToString() << ":" << subscription->Generation); + + auto config = ConfigIndex.BuildConfig(subscription->NodeId, subscription->Host, + subscription->Tenant, subscription->NodeType, + subscription->ItemKinds); + + THashMap<ui32, TConfigId> currKindIdMap; + THashMap<ui32, TConfigId> prevKindIdMap; + + for (auto kind : subscription->ItemKinds) { + auto it = config->ConfigItems.find(kind); + if (it != config->ConfigItems.end()) { + auto &id = currKindIdMap[kind]; + for (auto &item : it->second) { + if (item->MergeStrategy == NKikimrConsole::TConfigItem::OVERWRITE) + id.ItemIds.clear(); + id.ItemIds.push_back(std::make_pair(item->Id, item->Generation)); + } + } + } + for (auto &item : subscription->LastProvided.GetItems()) { + auto &id = prevKindIdMap[item.kind()]; + id.ItemIds.push_back(std::make_pair(item.GetId(), item.GetGeneration())); + } + + THashSet<ui32> affectedKinds; + NKikimrConfig::TConfigVersion version; + + for (auto &curr : currKindIdMap) { + auto prev = prevKindIdMap.find(curr.first); + + if (prev == prevKindIdMap.end() || curr.second != prev->second) { + // There are changes for the kind + affectedKinds.insert(curr.first); + for (auto &pr : curr.second.ItemIds) { + auto itemId = version.AddItems(); + itemId->SetKind(curr.first); + itemId->SetId(pr.first); + itemId->SetGeneration(pr.second); + } + } else if (prev != prevKindIdMap.end()) { + // There are no changes for the kind, lets just fill in current config ids + for (auto &pr : curr.second.ItemIds) { + auto itemId = version.AddItems(); + itemId->SetKind(curr.first); + itemId->SetId(pr.first); + itemId->SetGeneration(pr.second); + } + } + + if (prev != prevKindIdMap.end()) + prevKindIdMap.erase(prev); + } + + for (auto &prev : prevKindIdMap) { + // We already deleted all currently presented config kinds, so this one is definitely deleted + affectedKinds.insert(prev.first); + } + + if (affectedKinds.empty()) { + LOG_TRACE_S(ctx, NKikimrServices::CMS_CONFIGS, + "TConfigsProvider: no changes found for subscription" + << " " << subscription->Subscriber.ToString() << ":" << subscription->Generation); + return; + } + + LOG_TRACE_S(ctx, NKikimrServices::CMS_CONFIGS, + "TConfigsProvider: new config found for subscription" + << " " << subscription->Subscriber.ToString() << ":" << subscription->Generation + << " version=" << version.ShortDebugString()); + + subscription->LastProvided.Swap(&version); + + NKikimrConfig::TAppConfig appConfig; + config->ComputeConfig(affectedKinds, appConfig, true); + + Send(subscription->Worker, new TEvConsole::TEvConfigSubscriptionNotification(subscription->Generation, std::move(appConfig), affectedKinds)); +} + +void TConfigsProvider::Handle(TEvConsole::TEvConfigSubscriptionRequest::TPtr &ev, const TActorContext &ctx) +{ + auto subscriber = ev->Sender; + auto &rec = ev->Get()->Record; + + auto existing = InMemoryIndex.GetSubscription(subscriber); + if (existing) { + if (existing->Generation >= rec.GetGeneration()) { + LOG_DEBUG_S(ctx, NKikimrServices::CMS_CONFIGS, + "TConfigsProvider received stale subscription request " + << subscriber.ToString() << ":" << rec.GetGeneration()); + return; + } + + InMemoryIndex.RemoveSubscription(subscriber); + Send(existing->Worker, new TEvents::TEvPoisonPill()); + } + + TInMemorySubscription::TPtr subscription = new TInMemorySubscription(); + + subscription->Subscriber = subscriber; + subscription->Generation = rec.GetGeneration(); + + subscription->NodeId = rec.GetOptions().GetNodeId(); + subscription->Host = rec.GetOptions().GetHost(); + subscription->Tenant = rec.GetOptions().GetTenant(); + subscription->NodeType = rec.GetOptions().GetNodeType(); + + subscription->ItemKinds.insert(rec.GetConfigItemKinds().begin(), rec.GetConfigItemKinds().end()); + subscription->LastProvided.CopyFrom(rec.GetKnownVersion()); + + InMemoryIndex.AddSubscription(subscription); + + LOG_DEBUG_S(ctx, NKikimrServices::CMS_CONFIGS, + "TConfigsProvider registered new subscription " + << subscriber.ToString() << ":" << rec.GetGeneration()); + subscription->Worker = RegisterWithSameMailbox(new TSubscriptionClientSender(subscription, SelfId())); - - CheckSubscription(subscription, ctx); - } - -void TConfigsProvider::Handle(TEvConsole::TEvConfigSubscriptionCanceled::TPtr &ev, const TActorContext &ctx) -{ - auto subscriber = ev->Sender; - auto &rec = ev->Get()->Record; - - auto subscription = InMemoryIndex.GetSubscription(subscriber); - if (!subscription || subscription->Generation > rec.GetGeneration()) { - LOG_DEBUG_S(ctx, NKikimrServices::CMS_CONFIGS, - "TConfigsProvider received stale subscription canceled request " - << subscriber.ToString() << ":" << rec.GetGeneration()); - return; - } - - Y_VERIFY(subscription->Worker); - - InMemoryIndex.RemoveSubscription(subscriber); - Send(subscription->Worker, new TEvents::TEvPoisonPill()); -} - -void TConfigsProvider::Handle(TEvPrivate::TEvWorkerDisconnected::TPtr &ev, const TActorContext &ctx) -{ - auto subscription = ev->Get()->Subscription; - auto existing = InMemoryIndex.GetSubscription(subscription->Subscriber); - if (existing == subscription) { - InMemoryIndex.RemoveSubscription(subscription->Subscriber); - Send(subscription->Subscriber, new TEvConsole::TEvConfigSubscriptionCanceled(subscription->Generation)); - - LOG_DEBUG_S(ctx, NKikimrServices::CMS_CONFIGS, "TConfigsProvider removed subscription " - << subscription->Subscriber<< ":" << subscription->Generation << " (subscription worker died)"); - } -} - + + CheckSubscription(subscription, ctx); + } + +void TConfigsProvider::Handle(TEvConsole::TEvConfigSubscriptionCanceled::TPtr &ev, const TActorContext &ctx) +{ + auto subscriber = ev->Sender; + auto &rec = ev->Get()->Record; + + auto subscription = InMemoryIndex.GetSubscription(subscriber); + if (!subscription || subscription->Generation > rec.GetGeneration()) { + LOG_DEBUG_S(ctx, NKikimrServices::CMS_CONFIGS, + "TConfigsProvider received stale subscription canceled request " + << subscriber.ToString() << ":" << rec.GetGeneration()); + return; + } + + Y_VERIFY(subscription->Worker); + + InMemoryIndex.RemoveSubscription(subscriber); + Send(subscription->Worker, new TEvents::TEvPoisonPill()); +} + +void TConfigsProvider::Handle(TEvPrivate::TEvWorkerDisconnected::TPtr &ev, const TActorContext &ctx) +{ + auto subscription = ev->Get()->Subscription; + auto existing = InMemoryIndex.GetSubscription(subscription->Subscriber); + if (existing == subscription) { + InMemoryIndex.RemoveSubscription(subscription->Subscriber); + Send(subscription->Subscriber, new TEvConsole::TEvConfigSubscriptionCanceled(subscription->Generation)); + + LOG_DEBUG_S(ctx, NKikimrServices::CMS_CONFIGS, "TConfigsProvider removed subscription " + << subscription->Subscriber<< ":" << subscription->Generation << " (subscription worker died)"); + } +} + void TConfigsProvider::Handle(TEvConsole::TEvCheckConfigUpdatesRequest::TPtr &ev, const TActorContext &ctx) { auto &rec = ev->Get()->Record; @@ -942,7 +942,7 @@ void TConfigsProvider::Handle(TEvConsole::TEvGetNodeConfigRequest::TPtr &ev, con kinds.insert(kind); auto config = ConfigIndex.GetNodeConfig(rec.GetNode(), kinds); - config->ComputeConfig(*response->Record.MutableConfig(), true); + config->ComputeConfig(*response->Record.MutableConfig(), true); if (Config.EnableValidationOnNodeConfigRequest) { auto registry = TValidatorsRegistry::Instance(); diff --git a/ydb/core/cms/console/console_configs_provider.h b/ydb/core/cms/console/console_configs_provider.h index 7646491f7b..ddb74d52d4 100644 --- a/ydb/core/cms/console/console_configs_provider.h +++ b/ydb/core/cms/console/console_configs_provider.h @@ -25,7 +25,7 @@ public: EvSetSubscriptions, EvUpdateConfigs, EvUpdateSubscriptions, - EvWorkerDisconnected, + EvWorkerDisconnected, EvEnd }; @@ -50,15 +50,15 @@ public: TSubscription::TPtr Subscription; }; - struct TEvWorkerDisconnected : public TEventLocal<TEvWorkerDisconnected, EvWorkerDisconnected> { - explicit TEvWorkerDisconnected(TInMemorySubscription::TPtr subscription) - : Subscription(subscription) - { - } - - TInMemorySubscription::TPtr Subscription; - }; - + struct TEvWorkerDisconnected : public TEventLocal<TEvWorkerDisconnected, EvWorkerDisconnected> { + explicit TEvWorkerDisconnected(TInMemorySubscription::TPtr subscription) + : Subscription(subscription) + { + } + + TInMemorySubscription::TPtr Subscription; + }; + struct TEvSetConfig : public TEventLocal<TEvSetConfig, EvSetConfig> { TEvSetConfig(const TConfigsConfig &config) : Config(config) @@ -124,15 +124,15 @@ private: void CheckAllSubscriptions(const TActorContext &ctx); void CheckSubscriptions(const TSubscriptionSet &subscriptions, const TActorContext &ctx); - void CheckSubscriptions(const TInMemorySubscriptionSet &subscriptions, - const TActorContext &ctx); + void CheckSubscriptions(const TInMemorySubscriptionSet &subscriptions, + const TActorContext &ctx); void CheckSubscription(TSubscription::TPtr subscriptions, const TActorContext &ctx); - void CheckSubscription(TInMemorySubscription::TPtr subscriptions, - const TActorContext &ctx); + void CheckSubscription(TInMemorySubscription::TPtr subscriptions, + const TActorContext &ctx); - void Handle(TEvConsole::TEvConfigSubscriptionRequest::TPtr &ev, const TActorContext &ctx); - void Handle(TEvConsole::TEvConfigSubscriptionCanceled::TPtr &ev, const TActorContext &ctx); + void Handle(TEvConsole::TEvConfigSubscriptionRequest::TPtr &ev, const TActorContext &ctx); + void Handle(TEvConsole::TEvConfigSubscriptionCanceled::TPtr &ev, const TActorContext &ctx); void Handle(TEvConsole::TEvCheckConfigUpdatesRequest::TPtr &ev, const TActorContext &ctx); void Handle(TEvConsole::TEvConfigNotificationResponse::TPtr &ev, const TActorContext &ctx); void Handle(TEvConsole::TEvGetConfigItemsRequest::TPtr &ev, const TActorContext &ctx); @@ -140,7 +140,7 @@ private: void Handle(TEvConsole::TEvGetNodeConfigItemsRequest::TPtr &ev, const TActorContext &ctx); void Handle(TEvConsole::TEvGetNodeConfigRequest::TPtr &ev, const TActorContext &ctx); void Handle(TEvConsole::TEvListConfigSubscriptionsRequest::TPtr &ev, const TActorContext &ctx); - void Handle(TEvPrivate::TEvWorkerDisconnected::TPtr &ev, const TActorContext &ctx); + void Handle(TEvPrivate::TEvWorkerDisconnected::TPtr &ev, const TActorContext &ctx); void Handle(TEvPrivate::TEvNotificationTimeout::TPtr &ev, const TActorContext &ctx); void Handle(TEvPrivate::TEvSenderDied::TPtr &ev, const TActorContext &ctx); void Handle(TEvPrivate::TEvSetConfig::TPtr &ev, const TActorContext &ctx); @@ -152,15 +152,15 @@ private: void HandlePoison(const TActorContext &ctx) { LOG_DEBUG(ctx, NKikimrServices::CMS_CONFIGS, "TConfigsProvider::HandlePoison"); - + Die(ctx); } STFUNC(StateWork) { TRACE_EVENT(NKikimrServices::CMS_CONFIGS); switch (ev->GetTypeRewrite()) { - HFuncTraced(TEvConsole::TEvConfigSubscriptionRequest, Handle); - HFuncTraced(TEvConsole::TEvConfigSubscriptionCanceled, Handle); + HFuncTraced(TEvConsole::TEvConfigSubscriptionRequest, Handle); + HFuncTraced(TEvConsole::TEvConfigSubscriptionCanceled, Handle); HFuncTraced(TEvConsole::TEvCheckConfigUpdatesRequest, Handle); HFuncTraced(TEvConsole::TEvConfigNotificationResponse, Handle); HFuncTraced(TEvConsole::TEvGetConfigItemsRequest, Handle); @@ -168,7 +168,7 @@ private: HFuncTraced(TEvConsole::TEvGetNodeConfigItemsRequest, Handle); HFuncTraced(TEvConsole::TEvGetNodeConfigRequest, Handle); HFuncTraced(TEvConsole::TEvListConfigSubscriptionsRequest, Handle); - HFuncTraced(TEvPrivate::TEvWorkerDisconnected, Handle); + HFuncTraced(TEvPrivate::TEvWorkerDisconnected, Handle); HFuncTraced(TEvPrivate::TEvNotificationTimeout, Handle); HFuncTraced(TEvPrivate::TEvSenderDied, Handle); HFuncTraced(TEvPrivate::TEvSetConfig, Handle); @@ -209,7 +209,7 @@ private: TConfigsConfig Config; TConfigIndex ConfigIndex; TSubscriptionIndex SubscriptionIndex; - TInMemorySubscriptionIndex InMemoryIndex; + TInMemorySubscriptionIndex InMemoryIndex; }; } // namespace NConsole diff --git a/ydb/core/cms/console/console_configs_subscriber.cpp b/ydb/core/cms/console/console_configs_subscriber.cpp index 9bb28f4d63..20f3969f86 100644 --- a/ydb/core/cms/console/console_configs_subscriber.cpp +++ b/ydb/core/cms/console/console_configs_subscriber.cpp @@ -1,33 +1,33 @@ -#include "console_configs_subscriber.h" -#include "console.h" -#include "config_index.h" +#include "console_configs_subscriber.h" +#include "console.h" +#include "config_index.h" #include "util.h" - + #include <ydb/core/base/appdata.h> #include <ydb/core/base/tablet_pipe.h> #include <ydb/core/mind/tenant_pool.h> - -#include <library/cpp/actors/core/actor_bootstrapped.h> -#include <util/system/hostname.h> -#include <util/generic/ptr.h> - -#include <utility> - -#if defined BLOG_D || defined BLOG_I || defined BLOG_ERROR || defined BLOG_TRACE -#error log macro definition clash -#endif - -#define BLOG_D(stream) LOG_DEBUG_S(*TlsActivationContext, NKikimrServices::CMS_CONFIGS, stream) -#define BLOG_I(stream) LOG_INFO_S(*TlsActivationContext, NKikimrServices::CMS_CONFIGS, stream) -#define BLOG_ERROR(stream) LOG_ERROR_S(*TlsActivationContext, NKikimrServices::CMS_CONFIGS, stream) -#define BLOG_TRACE(stream) LOG_TRACE_S(*TlsActivationContext, NKikimrServices::CMS_CONFIGS, stream) - -namespace NKikimr::NConsole { - -class TConfigsSubscriber : public TActorBootstrapped<TConfigsSubscriber> { + +#include <library/cpp/actors/core/actor_bootstrapped.h> +#include <util/system/hostname.h> +#include <util/generic/ptr.h> + +#include <utility> + +#if defined BLOG_D || defined BLOG_I || defined BLOG_ERROR || defined BLOG_TRACE +#error log macro definition clash +#endif + +#define BLOG_D(stream) LOG_DEBUG_S(*TlsActivationContext, NKikimrServices::CMS_CONFIGS, stream) +#define BLOG_I(stream) LOG_INFO_S(*TlsActivationContext, NKikimrServices::CMS_CONFIGS, stream) +#define BLOG_ERROR(stream) LOG_ERROR_S(*TlsActivationContext, NKikimrServices::CMS_CONFIGS, stream) +#define BLOG_TRACE(stream) LOG_TRACE_S(*TlsActivationContext, NKikimrServices::CMS_CONFIGS, stream) + +namespace NKikimr::NConsole { + +class TConfigsSubscriber : public TActorBootstrapped<TConfigsSubscriber> { private: using TBase = TActorBootstrapped<TConfigsSubscriber>; - + struct TEvPrivate { enum EEv { EvRetryPoolStatus = EventSpaceBegin(TKikimrEvents::ES_PRIVATE), @@ -38,57 +38,57 @@ private: }; }; -public: - TConfigsSubscriber(const TActorId &ownerId, const TVector<ui32> &kinds, const NKikimrConfig::TAppConfig ¤tConfig) - : OwnerId(ownerId) - , Kinds(kinds) - , Generation(0) - , NextGeneration(1) - , LastOrder(0) - , CurrentConfig(currentConfig) {} - +public: + TConfigsSubscriber(const TActorId &ownerId, const TVector<ui32> &kinds, const NKikimrConfig::TAppConfig ¤tConfig) + : OwnerId(ownerId) + , Kinds(kinds) + , Generation(0) + , NextGeneration(1) + , LastOrder(0) + , CurrentConfig(currentConfig) {} + static constexpr NKikimrServices::TActivity::EType ActorActivityType() { return NKikimrServices::TActivity::CMS_CONFIGS_SUBSCRIBER; } - void Bootstrap(const TActorContext &ctx) { - auto dinfo = AppData(ctx)->DomainsInfo; - if (dinfo->Domains.size() != 1) { - Send(OwnerId, new NConsole::TEvConsole::TEvConfigSubscriptionError(Ydb::StatusIds::GENERIC_ERROR, "Ambiguous domain (use --domain option)")); - - Die(ctx); - - return; - } - - DomainUid = dinfo->Domains.begin()->second->DomainUid; - StateStorageGroup = dinfo->GetDefaultStateStorageGroup(DomainUid); - + void Bootstrap(const TActorContext &ctx) { + auto dinfo = AppData(ctx)->DomainsInfo; + if (dinfo->Domains.size() != 1) { + Send(OwnerId, new NConsole::TEvConsole::TEvConfigSubscriptionError(Ydb::StatusIds::GENERIC_ERROR, "Ambiguous domain (use --domain option)")); + + Die(ctx); + + return; + } + + DomainUid = dinfo->Domains.begin()->second->DomainUid; + StateStorageGroup = dinfo->GetDefaultStateStorageGroup(DomainUid); + SendPoolStatusRequest(ctx); - Become(&TThis::StateWork); - } - - STFUNC(StateWork) { - TRACE_EVENT(NKikimrServices::CMS_CONFIGS); - - switch (ev->GetTypeRewrite()) { + Become(&TThis::StateWork); + } + + STFUNC(StateWork) { + TRACE_EVENT(NKikimrServices::CMS_CONFIGS); + + switch (ev->GetTypeRewrite()) { HFuncTraced(TEvPrivate::TEvRetryPoolStatus, Handle); - HFuncTraced(TEvTenantPool::TEvTenantPoolStatus, Handle); - HFuncTraced(TEvConsole::TEvConfigSubscriptionResponse, Handle); - HFuncTraced(TEvConsole::TEvConfigSubscriptionError, Handle); - HFuncTraced(TEvConsole::TEvConfigSubscriptionNotification, Handle); - HFuncTraced(TEvConsole::TEvConfigSubscriptionCanceled, Handle); - HFuncTraced(TEvTabletPipe::TEvClientConnected, Handle); - HFuncTraced(TEvTabletPipe::TEvClientDestroyed, Handle); - HFuncTraced(TEvents::TEvUndelivered, Handle); - HFuncTraced(TEvents::TEvPoisonPill, Handle); - - default: - Y_FAIL("unexpected event type: %" PRIx32 " event: %s", - ev->GetTypeRewrite(), ev->HasEvent() ? ev->GetBase()->ToString().data() : "serialized?"); - } - } - + HFuncTraced(TEvTenantPool::TEvTenantPoolStatus, Handle); + HFuncTraced(TEvConsole::TEvConfigSubscriptionResponse, Handle); + HFuncTraced(TEvConsole::TEvConfigSubscriptionError, Handle); + HFuncTraced(TEvConsole::TEvConfigSubscriptionNotification, Handle); + HFuncTraced(TEvConsole::TEvConfigSubscriptionCanceled, Handle); + HFuncTraced(TEvTabletPipe::TEvClientConnected, Handle); + HFuncTraced(TEvTabletPipe::TEvClientDestroyed, Handle); + HFuncTraced(TEvents::TEvUndelivered, Handle); + HFuncTraced(TEvents::TEvPoisonPill, Handle); + + default: + Y_FAIL("unexpected event type: %" PRIx32 " event: %s", + ev->GetTypeRewrite(), ev->HasEvent() ? ev->GetBase()->ToString().data() : "serialized?"); + } + } + void SendPoolStatusRequest(const TActorContext &ctx) { ctx.Send(MakeTenantPoolID(ctx.SelfID.NodeId(), DomainUid), new TEvTenantPool::TEvGetStatus(true), IEventHandle::FlagTrackDelivery); @@ -98,116 +98,116 @@ public: SendPoolStatusRequest(ctx); } - void Handle(TEvTenantPool::TEvTenantPoolStatus::TPtr &ev, const TActorContext &ctx) { - auto &rec = ev->Get()->Record; - - NodeType = rec.GetNodeType(); - - THashSet<TString> tenants; - for (auto &slot : rec.GetSlots()) - tenants.insert(slot.GetAssignedTenant()); - - if (tenants.size() == 1) - Tenant = CanonizePath(*tenants.begin()); - else - Tenant = tenants.empty() ? "<none>" : "<multiple>"; - - Subscribe(ctx); - } - - void Handle(TEvConsole::TEvConfigSubscriptionResponse::TPtr &ev, const TActorContext &ctx) { - auto &rec = ev->Get()->Record; - - if (rec.GetGeneration() != Generation) { - BLOG_I("Generation mismatch for TEvConfigSubscriptionResponse"); - - return; - } - - if (rec.GetStatus().GetCode() != Ydb::StatusIds::SUCCESS) { - Send(OwnerId, new TEvConsole::TEvConfigSubscriptionError(rec.GetStatus().GetCode(), rec.GetStatus().GetReason())); - - Generation = 0; - Die(ctx); - } - } - - void Handle(TEvConsole::TEvConfigSubscriptionError::TPtr &ev, const TActorContext &ctx) { + void Handle(TEvTenantPool::TEvTenantPoolStatus::TPtr &ev, const TActorContext &ctx) { + auto &rec = ev->Get()->Record; + + NodeType = rec.GetNodeType(); + + THashSet<TString> tenants; + for (auto &slot : rec.GetSlots()) + tenants.insert(slot.GetAssignedTenant()); + + if (tenants.size() == 1) + Tenant = CanonizePath(*tenants.begin()); + else + Tenant = tenants.empty() ? "<none>" : "<multiple>"; + + Subscribe(ctx); + } + + void Handle(TEvConsole::TEvConfigSubscriptionResponse::TPtr &ev, const TActorContext &ctx) { + auto &rec = ev->Get()->Record; + + if (rec.GetGeneration() != Generation) { + BLOG_I("Generation mismatch for TEvConfigSubscriptionResponse"); + + return; + } + + if (rec.GetStatus().GetCode() != Ydb::StatusIds::SUCCESS) { + Send(OwnerId, new TEvConsole::TEvConfigSubscriptionError(rec.GetStatus().GetCode(), rec.GetStatus().GetReason())); + + Generation = 0; + Die(ctx); + } + } + + void Handle(TEvConsole::TEvConfigSubscriptionError::TPtr &ev, const TActorContext &ctx) { NActors::TActivationContext::Send(ev->Forward(OwnerId)); - - Generation = 0; - Die(ctx); - } - - void Handle(NConsole::TEvConsole::TEvConfigSubscriptionNotification::TPtr &ev, const TActorContext &ctx) { - auto &rec = ev->Get()->Record; - - if (rec.GetGeneration() != Generation) { - BLOG_I("Generation mismatch for TEvConfigSubscriptionNotification"); - - return; - } - - Y_VERIFY(Pipe); - - if (rec.GetOrder() != (LastOrder + 1)) { - BLOG_I("Order mismatch, will resubscribe"); - - Subscribe(ctx); - - return; - } - - NKikimrConfig::TConfigVersion newVersion(rec.GetConfig().GetVersion()); - THashSet<ui32> changes(rec.GetAffectedKinds().begin(), rec.GetAffectedKinds().end()); - for (auto &item : CurrentConfig.GetVersion().GetItems()) { - if (!changes.contains(item.GetKind())) - newVersion.AddItems()->CopyFrom(item); - } - - auto *desc1 = CurrentConfig.GetDescriptor(); - auto *reflection = CurrentConfig.GetReflection(); - for (auto kind : rec.GetAffectedKinds()) { - auto *field = desc1->FindFieldByNumber(kind); - if (field && reflection->HasField(CurrentConfig, field)) - reflection->ClearField(&CurrentConfig, field); - } - - CurrentConfig.MergeFrom(rec.GetConfig()); - if (newVersion.GetItems().empty()) - CurrentConfig.ClearVersion(); - else - CurrentConfig.MutableVersion()->Swap(&newVersion); - - Send(OwnerId, new TEvConsole::TEvConfigSubscriptionNotification(Generation, CurrentConfig, changes), - IEventHandle::FlagTrackDelivery); - - LastOrder++; - } - - void Handle(NConsole::TEvConsole::TEvConfigSubscriptionCanceled::TPtr &ev, const TActorContext &ctx) { - auto &rec = ev->Get()->Record; - - if (rec.GetGeneration() != Generation) { - BLOG_I("Generation mismatch for TEvConfigSubscriptionCanceled"); - - return; - } - - Y_VERIFY(Pipe); - - Subscribe(ctx); - } - - void Handle(TEvTabletPipe::TEvClientConnected::TPtr &ev, const TActorContext &ctx) { - if (ev->Get()->Status != NKikimrProto::OK) - OnPipeDestroyed(ctx); - } - - void Handle(TEvTabletPipe::TEvClientDestroyed::TPtr &/*ev*/, const TActorContext &ctx) { - OnPipeDestroyed(ctx); - } - + + Generation = 0; + Die(ctx); + } + + void Handle(NConsole::TEvConsole::TEvConfigSubscriptionNotification::TPtr &ev, const TActorContext &ctx) { + auto &rec = ev->Get()->Record; + + if (rec.GetGeneration() != Generation) { + BLOG_I("Generation mismatch for TEvConfigSubscriptionNotification"); + + return; + } + + Y_VERIFY(Pipe); + + if (rec.GetOrder() != (LastOrder + 1)) { + BLOG_I("Order mismatch, will resubscribe"); + + Subscribe(ctx); + + return; + } + + NKikimrConfig::TConfigVersion newVersion(rec.GetConfig().GetVersion()); + THashSet<ui32> changes(rec.GetAffectedKinds().begin(), rec.GetAffectedKinds().end()); + for (auto &item : CurrentConfig.GetVersion().GetItems()) { + if (!changes.contains(item.GetKind())) + newVersion.AddItems()->CopyFrom(item); + } + + auto *desc1 = CurrentConfig.GetDescriptor(); + auto *reflection = CurrentConfig.GetReflection(); + for (auto kind : rec.GetAffectedKinds()) { + auto *field = desc1->FindFieldByNumber(kind); + if (field && reflection->HasField(CurrentConfig, field)) + reflection->ClearField(&CurrentConfig, field); + } + + CurrentConfig.MergeFrom(rec.GetConfig()); + if (newVersion.GetItems().empty()) + CurrentConfig.ClearVersion(); + else + CurrentConfig.MutableVersion()->Swap(&newVersion); + + Send(OwnerId, new TEvConsole::TEvConfigSubscriptionNotification(Generation, CurrentConfig, changes), + IEventHandle::FlagTrackDelivery); + + LastOrder++; + } + + void Handle(NConsole::TEvConsole::TEvConfigSubscriptionCanceled::TPtr &ev, const TActorContext &ctx) { + auto &rec = ev->Get()->Record; + + if (rec.GetGeneration() != Generation) { + BLOG_I("Generation mismatch for TEvConfigSubscriptionCanceled"); + + return; + } + + Y_VERIFY(Pipe); + + Subscribe(ctx); + } + + void Handle(TEvTabletPipe::TEvClientConnected::TPtr &ev, const TActorContext &ctx) { + if (ev->Get()->Status != NKikimrProto::OK) + OnPipeDestroyed(ctx); + } + + void Handle(TEvTabletPipe::TEvClientDestroyed::TPtr &/*ev*/, const TActorContext &ctx) { + OnPipeDestroyed(ctx); + } + void Handle(TEvents::TEvUndelivered::TPtr &ev, const TActorContext &ctx) { switch (ev->Get()->SourceType) { case TEvTenantPool::TEvGetStatus::EventType: { @@ -218,84 +218,84 @@ public: default: Die(ctx); } - } - - void Handle(TEvents::TEvPoisonPill::TPtr &/*ev*/, const TActorContext &ctx) { - Die(ctx); - } - -protected: - void Die(const TActorContext &ctx) override { - if (Pipe) { - if (Generation != 0) - NTabletPipe::SendData(ctx, Pipe, new NConsole::TEvConsole::TEvConfigSubscriptionCanceled(Generation)); - - NTabletPipe::CloseClient(ctx, Pipe); - } - - TBase::Die(ctx); - } - -private: - void Subscribe(const TActorContext &ctx) { - Generation = 0; - LastOrder = 0; - - if (!Pipe) - OpenPipe(ctx); - - auto request = MakeHolder<TEvConsole::TEvConfigSubscriptionRequest>(); - - request->Record.SetGeneration(Generation = NextGeneration++); - request->Record.MutableOptions()->SetNodeId(SelfId().NodeId()); - request->Record.MutableOptions()->SetTenant(Tenant); - request->Record.MutableOptions()->SetNodeType(NodeType); - request->Record.MutableOptions()->SetHost(FQDNHostName()); - - for (auto &kind : Kinds) - request->Record.AddConfigItemKinds(kind); - - if (CurrentConfig.HasVersion()) - request->Record.MutableKnownVersion()->CopyFrom(CurrentConfig.GetVersion()); - - NTabletPipe::SendData(ctx, Pipe, request.Release()); - } - - void OnPipeDestroyed(const TActorContext &ctx) { - Pipe = TActorId(); - - Subscribe(ctx); - } - - void OpenPipe(const TActorContext &ctx) { - auto console = MakeConsoleID(StateStorageGroup); - - NTabletPipe::TClientConfig pipeConfig; + } + + void Handle(TEvents::TEvPoisonPill::TPtr &/*ev*/, const TActorContext &ctx) { + Die(ctx); + } + +protected: + void Die(const TActorContext &ctx) override { + if (Pipe) { + if (Generation != 0) + NTabletPipe::SendData(ctx, Pipe, new NConsole::TEvConsole::TEvConfigSubscriptionCanceled(Generation)); + + NTabletPipe::CloseClient(ctx, Pipe); + } + + TBase::Die(ctx); + } + +private: + void Subscribe(const TActorContext &ctx) { + Generation = 0; + LastOrder = 0; + + if (!Pipe) + OpenPipe(ctx); + + auto request = MakeHolder<TEvConsole::TEvConfigSubscriptionRequest>(); + + request->Record.SetGeneration(Generation = NextGeneration++); + request->Record.MutableOptions()->SetNodeId(SelfId().NodeId()); + request->Record.MutableOptions()->SetTenant(Tenant); + request->Record.MutableOptions()->SetNodeType(NodeType); + request->Record.MutableOptions()->SetHost(FQDNHostName()); + + for (auto &kind : Kinds) + request->Record.AddConfigItemKinds(kind); + + if (CurrentConfig.HasVersion()) + request->Record.MutableKnownVersion()->CopyFrom(CurrentConfig.GetVersion()); + + NTabletPipe::SendData(ctx, Pipe, request.Release()); + } + + void OnPipeDestroyed(const TActorContext &ctx) { + Pipe = TActorId(); + + Subscribe(ctx); + } + + void OpenPipe(const TActorContext &ctx) { + auto console = MakeConsoleID(StateStorageGroup); + + NTabletPipe::TClientConfig pipeConfig; pipeConfig.RetryPolicy = FastConnectRetryPolicy(); - auto pipe = NTabletPipe::CreateClient(ctx.SelfID, console, pipeConfig); - Pipe = ctx.ExecutorThread.RegisterActor(pipe); - } - -private: - const TActorId OwnerId; - const TVector<ui32> Kinds; - - ui64 Generation; - ui64 NextGeneration; - ui64 LastOrder; - - NKikimrConfig::TAppConfig CurrentConfig; - - TString Tenant; - TString NodeType; - - ui32 DomainUid; - ui32 StateStorageGroup; - - TActorId Pipe; -}; - -IActor *CreateConfigsSubscriber(const TActorId &ownerId, const TVector<ui32> &kinds, const NKikimrConfig::TAppConfig ¤tConfig) { - return new TConfigsSubscriber(ownerId, kinds, currentConfig); -} -} + auto pipe = NTabletPipe::CreateClient(ctx.SelfID, console, pipeConfig); + Pipe = ctx.ExecutorThread.RegisterActor(pipe); + } + +private: + const TActorId OwnerId; + const TVector<ui32> Kinds; + + ui64 Generation; + ui64 NextGeneration; + ui64 LastOrder; + + NKikimrConfig::TAppConfig CurrentConfig; + + TString Tenant; + TString NodeType; + + ui32 DomainUid; + ui32 StateStorageGroup; + + TActorId Pipe; +}; + +IActor *CreateConfigsSubscriber(const TActorId &ownerId, const TVector<ui32> &kinds, const NKikimrConfig::TAppConfig ¤tConfig) { + return new TConfigsSubscriber(ownerId, kinds, currentConfig); +} +} diff --git a/ydb/core/cms/console/console_configs_subscriber.h b/ydb/core/cms/console/console_configs_subscriber.h index 49d42e0bca..2542b1ec1f 100644 --- a/ydb/core/cms/console/console_configs_subscriber.h +++ b/ydb/core/cms/console/console_configs_subscriber.h @@ -1,11 +1,11 @@ -#pragma once - -#include "defs.h" -#include "configs_config.h" -#include "console.h" - -#include <library/cpp/actors/core/actor.h> - -namespace NKikimr::NConsole { -IActor * CreateConfigsSubscriber(const TActorId &ownerId, const TVector<ui32> &kinds, const NKikimrConfig::TAppConfig ¤tConfig); -} +#pragma once + +#include "defs.h" +#include "configs_config.h" +#include "console.h" + +#include <library/cpp/actors/core/actor.h> + +namespace NKikimr::NConsole { +IActor * CreateConfigsSubscriber(const TActorId &ownerId, const TVector<ui32> &kinds, const NKikimrConfig::TAppConfig ¤tConfig); +} diff --git a/ydb/core/cms/console/console_impl.h b/ydb/core/cms/console/console_impl.h index a4ae576487..0894337c3e 100644 --- a/ydb/core/cms/console/console_impl.h +++ b/ydb/core/cms/console/console_impl.h @@ -83,8 +83,8 @@ private: { TRACE_EVENT(NKikimrServices::CMS); switch (ev->GetTypeRewrite()) { - FFunc(TEvConsole::EvConfigSubscriptionRequest, ForwardToConfigsManager); - FFunc(TEvConsole::EvConfigSubscriptionCanceled, ForwardToConfigsManager); + FFunc(TEvConsole::EvConfigSubscriptionRequest, ForwardToConfigsManager); + FFunc(TEvConsole::EvConfigSubscriptionCanceled, ForwardToConfigsManager); FFunc(TEvConsole::EvAddConfigSubscriptionRequest, ForwardToConfigsManager); FFunc(TEvConsole::EvAlterTenantRequest, ForwardToTenantsManager); FFunc(TEvConsole::EvCheckConfigUpdatesRequest, ForwardToConfigsManager); diff --git a/ydb/core/cms/console/console_ut_configs.cpp b/ydb/core/cms/console/console_ut_configs.cpp index 58d86fa2a6..0cb1655281 100644 --- a/ydb/core/cms/console/console_ut_configs.cpp +++ b/ydb/core/cms/console/console_ut_configs.cpp @@ -1,6 +1,6 @@ #include "ut_helpers.h" #include "console_configs_manager.h" -#include "console_configs_subscriber.h" +#include "console_configs_subscriber.h" #include <ydb/core/base/counters.h> #include <ydb/core/node_whiteboard/node_whiteboard.h> @@ -9,9 +9,9 @@ #include <ydb/core/tablet/bootstrapper.h> #include <ydb/core/tablet_flat/tablet_flat_executed.h> #include <ydb/core/testlib/tablet_helpers.h> - -#include <library/cpp/actors/interconnect/interconnect_impl.h> - + +#include <library/cpp/actors/interconnect/interconnect_impl.h> + #include <ydb/core/testlib/tenant_runtime.h> #include <library/cpp/testing/unittest/registar.h> @@ -87,31 +87,31 @@ TTenantTestConfig DefaultConsoleTestConfig() return res; } -TTenantTestConfig MultipleNodesConsoleTestConfig() -{ - TTenantTestConfig res = { - // Domains {name, schemeshard {{ subdomain_names }}} - {{ {DOMAIN1_NAME, SCHEME_SHARD1_ID, TVector<TString>()} }}, - // HiveId - HIVE_ID, - // FakeTenantSlotBroker - true, - // FakeSchemeShard - false, - // CreateConsole - true, - // Nodes {tenant_pool_config, data_center} - {{ - {DefaultTenantPoolConfig()}, - },{ - {DefaultTenantPoolConfig()}, - }}, - // DataCenterCount - 1 - }; - return res; -} - +TTenantTestConfig MultipleNodesConsoleTestConfig() +{ + TTenantTestConfig res = { + // Domains {name, schemeshard {{ subdomain_names }}} + {{ {DOMAIN1_NAME, SCHEME_SHARD1_ID, TVector<TString>()} }}, + // HiveId + HIVE_ID, + // FakeTenantSlotBroker + true, + // FakeSchemeShard + false, + // CreateConsole + true, + // Nodes {tenant_pool_config, data_center} + {{ + {DefaultTenantPoolConfig()}, + },{ + {DefaultTenantPoolConfig()}, + }}, + // DataCenterCount + 1 + }; + return res; +} + TTenantTestConfig TenantConsoleTestConfig() { TTenantTestConfig res = { @@ -394,7 +394,7 @@ void CheckGetNodeConfig(TTenantTestRuntime &runtime, ui32 nodeId, const TString runtime.SendToConsole(event); auto reply = runtime.GrabEdgeEventRethrow<TEvConsole::TEvGetNodeConfigResponse>(handle); UNIT_ASSERT_VALUES_EQUAL(reply->Record.GetStatus().GetCode(), Ydb::StatusIds::SUCCESS); - CheckEqualsIgnoringVersion(reply->Record.GetConfig(), config); + CheckEqualsIgnoringVersion(reply->Record.GetConfig(), config); } void CheckGetNodeConfig(TTenantTestRuntime &runtime, @@ -3525,243 +3525,243 @@ Y_UNIT_TEST_SUITE(TConsoleConfigSubscriptionTests) { } } -Y_UNIT_TEST_SUITE(TConsoleInMemoryConfigSubscriptionTests) { - Y_UNIT_TEST(TestSubscriptionCreate) { - TTenantTestRuntime runtime(DefaultConsoleTestConfig()); - InitializeTestConfigItems(); - - ui32 nodeId = runtime.GetNodeId(0); - ui32 generation = 1; - TActorId edgeId = runtime.Sender; - - auto *event = new TEvConsole::TEvConfigSubscriptionRequest; - event->Record.SetGeneration(generation); - event->Record.MutableOptions()->SetNodeId(nodeId); - event->Record.MutableOptions()->SetHost("host1"); - event->Record.MutableOptions()->SetTenant("tenant-1"); - event->Record.MutableOptions()->SetNodeType("type1"); - event->Record.AddConfigItemKinds(NKikimrConsole::TConfigItem::LogConfigItem); - runtime.SendToPipe(MakeConsoleID(0), edgeId, event, 0, GetPipeConfigWithRetries()); - - ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-1"); - - CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, - MakeAddAction(ITEM_DOMAIN_LOG_1)); - - NKikimrConfig::TAppConfig config1; - config1.MutableLogConfig()->SetClusterName("cluster-1"); - - auto item = config1.MutableVersion()->AddItems(); - item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); - item->SetId(1); - item->SetGeneration(1); - - auto notification = runtime.GrabEdgeEventRethrow<TEvConsole::TEvConfigSubscriptionNotification>(edgeId); - - UNIT_ASSERT_VALUES_EQUAL(notification->Get()->Record.GetGeneration(), generation); - UNIT_ASSERT_VALUES_EQUAL(notification->Get()->Record.GetConfig().ShortDebugString(), config1.ShortDebugString()); - } - - Y_UNIT_TEST(TestSubscriptionClient) { - TTenantTestRuntime runtime(DefaultConsoleTestConfig()); - InitializeTestConfigItems(); - - TActorId edgeId = runtime.Sender; - - auto subscriber = NConsole::CreateConfigsSubscriber(edgeId, TVector<ui32>({(ui32)NKikimrConsole::TConfigItem::LogConfigItem}), NKikimrConfig::TAppConfig()); - - runtime.Register(subscriber); - - ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-1"); - - CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, - MakeAddAction(ITEM_DOMAIN_LOG_1)); - - NKikimrConfig::TAppConfig config; - config.MutableLogConfig()->SetClusterName("cluster-1"); - - auto item = config.MutableVersion()->AddItems(); - item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); - item->SetId(1); - item->SetGeneration(1); - - auto notification = runtime.GrabEdgeEventRethrow<TEvConsole::TEvConfigSubscriptionNotification>(edgeId); - - UNIT_ASSERT_VALUES_EQUAL(notification->Get()->Record.GetGeneration(), 1); - UNIT_ASSERT_VALUES_EQUAL(notification->Get()->Record.GetConfig().ShortDebugString(), config.ShortDebugString()); - } - - Y_UNIT_TEST(TestSubscriptionClientManyUpdates) { - TTenantTestRuntime runtime(DefaultConsoleTestConfig()); - InitializeTestConfigItems(); - - TActorId edgeId = runtime.Sender; - - auto subscriber = NConsole::CreateConfigsSubscriber(edgeId, TVector<ui32>({(ui32)NKikimrConsole::TConfigItem::LogConfigItem}), NKikimrConfig::TAppConfig()); - - runtime.Register(subscriber); - - for (int i = 0; i < 100; i++) { - ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName(TStringBuilder() << "cluster-" << i); - - if (i == 0) { - CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeAddAction(ITEM_DOMAIN_LOG_1)); - ITEM_DOMAIN_LOG_1.MutableId()->SetId(1); - } else { - CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeModifyAction(ITEM_DOMAIN_LOG_1)); - } - - ITEM_DOMAIN_LOG_1.MutableId()->SetGeneration(i + 1); - } - - for (int i = 0; i < 100; i++) { - NKikimrConfig::TAppConfig config; - config.MutableLogConfig()->SetClusterName(TStringBuilder() << "cluster-" << i); - - auto item = config.MutableVersion()->AddItems(); - item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); - item->SetId(1); - item->SetGeneration(i + 1); - - auto notification = runtime.GrabEdgeEventRethrow<TEvConsole::TEvConfigSubscriptionNotification>(edgeId); - - UNIT_ASSERT_VALUES_EQUAL(notification->Get()->Record.GetGeneration(), 1); - UNIT_ASSERT_VALUES_EQUAL(notification->Get()->Record.GetConfig().ShortDebugString(), config.ShortDebugString()); - } - } - - Y_UNIT_TEST(TestSubscriptionClientManyUpdatesAddRemove) { - TTenantTestRuntime runtime(DefaultConsoleTestConfig()); - TActorId edgeId = runtime.Sender; - - auto subscriber = NConsole::CreateConfigsSubscriber(edgeId, TVector<ui32>({(ui32)NKikimrConsole::TConfigItem::LogConfigItem}), NKikimrConfig::TAppConfig()); - - runtime.Register(subscriber); - - ui64 id = 0; - for (int i = 0; i < 100; i++) { - if (i % 2 == 0) { - auto logConfigItem = MakeConfigItem(NKikimrConsole::TConfigItem::LogConfigItem, - NKikimrConfig::TAppConfig(), {}, {}, "", "", 1, - NKikimrConsole::TConfigItem::MERGE, ""); - - logConfigItem.MutableConfig()->MutableLogConfig()->SetClusterName(TStringBuilder() << "cluster-" << i); - - auto ids = CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeAddAction(logConfigItem)); - - UNIT_ASSERT_VALUES_EQUAL(ids.size(), 1); - - id = ids[0]; - } else { - CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeRemoveAction(id, 1)); - } - } - - for (int i = 0; i < 100; i++) { - NKikimrConfig::TAppConfig config; - - if (i % 2 == 0) { - config.MutableLogConfig()->SetClusterName(TStringBuilder() << "cluster-" << i); - - auto item = config.MutableVersion()->AddItems(); - item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); - item->SetId(i / 2 + 1); - item->SetGeneration(1); - } - - auto notification = runtime.GrabEdgeEventRethrow<TEvConsole::TEvConfigSubscriptionNotification>(edgeId); - - UNIT_ASSERT_VALUES_EQUAL(notification->Get()->Record.GetGeneration(), 1); - UNIT_ASSERT_VALUES_EQUAL(notification->Get()->Record.GetConfig().ShortDebugString(), config.ShortDebugString()); - } - } - - Y_UNIT_TEST(TestSubscriptionClientDeadCausesSupscriptionDeregistration) { - TTenantTestRuntime runtime(DefaultConsoleTestConfig()); - InitializeTestConfigItems(); - - TActorId edgeId = runtime.Sender; - - auto subscriber = NConsole::CreateConfigsSubscriber(edgeId, TVector<ui32>({(ui32)NKikimrConsole::TConfigItem::LogConfigItem}), NKikimrConfig::TAppConfig()); - const auto &clientId = runtime.Register(subscriber); - - TDispatchOptions options1; - options1.FinalEvents.emplace_back(TEvConsole::EvConfigSubscriptionResponse, 1); - runtime.DispatchEvents(options1); - - runtime.Send(new IEventHandle(clientId, edgeId, new TEvents::TEvPoisonPill()), 0, true); - - TDispatchOptions options2; - options2.FinalEvents.emplace_back(TEvConsole::EvConfigSubscriptionCanceled, 3); - runtime.DispatchEvents(options2); - } - - Y_UNIT_TEST(TestSubscriptionClientReconnectsOnConnectionLoose) { - TTenantTestRuntime runtime(MultipleNodesConsoleTestConfig()); - InitializeTestConfigItems(); - - TActorId edgeId = runtime.AllocateEdgeActor(1); - - auto subscriber = NConsole::CreateConfigsSubscriber(edgeId, TVector<ui32>({(ui32)NKikimrConsole::TConfigItem::LogConfigItem}), NKikimrConfig::TAppConfig()); - runtime.Register(subscriber, 1); - - TDispatchOptions options1; - options1.FinalEvents.emplace_back(TEvConsole::EvConfigSubscriptionResponse, 1); - runtime.DispatchEvents(options1); - - ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-1"); - - auto ids = CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, - MakeAddAction(ITEM_DOMAIN_LOG_1)); - - AssignIds(ids, ITEM_DOMAIN_LOG_1); - - NKikimrConfig::TAppConfig config1; - config1.MutableLogConfig()->SetClusterName("cluster-1"); - { - auto item = config1.MutableVersion()->AddItems(); - item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); - item->SetId(1); - item->SetGeneration(1); - } - - auto notification1 = runtime.GrabEdgeEventRethrow<TEvConsole::TEvConfigSubscriptionNotification>(edgeId); - - UNIT_ASSERT_VALUES_EQUAL(notification1->Get()->Record.GetGeneration(), 1); - UNIT_ASSERT_VALUES_EQUAL(notification1->Get()->Record.GetConfig().ShortDebugString(), config1.ShortDebugString()); - - TAutoPtr<IEventHandle> handle = new IEventHandle( - runtime.GetInterconnectProxy(0, 1), - runtime.Sender, - new TEvInterconnect::TEvDisconnect()); - - runtime.Send(handle.Release(), 0, true); - - TDispatchOptions options2; - options2.FinalEvents.emplace_back(TEvConsole::EvConfigSubscriptionResponse, 1); - runtime.DispatchEvents(options2); - - ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-2"); - - CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, - MakeModifyAction(ITEM_DOMAIN_LOG_1)); - - NKikimrConfig::TAppConfig config2; - config2.MutableLogConfig()->SetClusterName("cluster-2"); - { - auto item = config2.MutableVersion()->AddItems(); - item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); - item->SetId(1); - item->SetGeneration(2); - } - - auto notification2 = runtime.GrabEdgeEventRethrow<TEvConsole::TEvConfigSubscriptionNotification>(edgeId); - - UNIT_ASSERT_VALUES_EQUAL(notification2->Get()->Record.GetGeneration(), 2); - UNIT_ASSERT_VALUES_EQUAL(notification2->Get()->Record.GetConfig().ShortDebugString(), config2.ShortDebugString()); - } -} - +Y_UNIT_TEST_SUITE(TConsoleInMemoryConfigSubscriptionTests) { + Y_UNIT_TEST(TestSubscriptionCreate) { + TTenantTestRuntime runtime(DefaultConsoleTestConfig()); + InitializeTestConfigItems(); + + ui32 nodeId = runtime.GetNodeId(0); + ui32 generation = 1; + TActorId edgeId = runtime.Sender; + + auto *event = new TEvConsole::TEvConfigSubscriptionRequest; + event->Record.SetGeneration(generation); + event->Record.MutableOptions()->SetNodeId(nodeId); + event->Record.MutableOptions()->SetHost("host1"); + event->Record.MutableOptions()->SetTenant("tenant-1"); + event->Record.MutableOptions()->SetNodeType("type1"); + event->Record.AddConfigItemKinds(NKikimrConsole::TConfigItem::LogConfigItem); + runtime.SendToPipe(MakeConsoleID(0), edgeId, event, 0, GetPipeConfigWithRetries()); + + ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-1"); + + CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, + MakeAddAction(ITEM_DOMAIN_LOG_1)); + + NKikimrConfig::TAppConfig config1; + config1.MutableLogConfig()->SetClusterName("cluster-1"); + + auto item = config1.MutableVersion()->AddItems(); + item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); + item->SetId(1); + item->SetGeneration(1); + + auto notification = runtime.GrabEdgeEventRethrow<TEvConsole::TEvConfigSubscriptionNotification>(edgeId); + + UNIT_ASSERT_VALUES_EQUAL(notification->Get()->Record.GetGeneration(), generation); + UNIT_ASSERT_VALUES_EQUAL(notification->Get()->Record.GetConfig().ShortDebugString(), config1.ShortDebugString()); + } + + Y_UNIT_TEST(TestSubscriptionClient) { + TTenantTestRuntime runtime(DefaultConsoleTestConfig()); + InitializeTestConfigItems(); + + TActorId edgeId = runtime.Sender; + + auto subscriber = NConsole::CreateConfigsSubscriber(edgeId, TVector<ui32>({(ui32)NKikimrConsole::TConfigItem::LogConfigItem}), NKikimrConfig::TAppConfig()); + + runtime.Register(subscriber); + + ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-1"); + + CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, + MakeAddAction(ITEM_DOMAIN_LOG_1)); + + NKikimrConfig::TAppConfig config; + config.MutableLogConfig()->SetClusterName("cluster-1"); + + auto item = config.MutableVersion()->AddItems(); + item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); + item->SetId(1); + item->SetGeneration(1); + + auto notification = runtime.GrabEdgeEventRethrow<TEvConsole::TEvConfigSubscriptionNotification>(edgeId); + + UNIT_ASSERT_VALUES_EQUAL(notification->Get()->Record.GetGeneration(), 1); + UNIT_ASSERT_VALUES_EQUAL(notification->Get()->Record.GetConfig().ShortDebugString(), config.ShortDebugString()); + } + + Y_UNIT_TEST(TestSubscriptionClientManyUpdates) { + TTenantTestRuntime runtime(DefaultConsoleTestConfig()); + InitializeTestConfigItems(); + + TActorId edgeId = runtime.Sender; + + auto subscriber = NConsole::CreateConfigsSubscriber(edgeId, TVector<ui32>({(ui32)NKikimrConsole::TConfigItem::LogConfigItem}), NKikimrConfig::TAppConfig()); + + runtime.Register(subscriber); + + for (int i = 0; i < 100; i++) { + ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName(TStringBuilder() << "cluster-" << i); + + if (i == 0) { + CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeAddAction(ITEM_DOMAIN_LOG_1)); + ITEM_DOMAIN_LOG_1.MutableId()->SetId(1); + } else { + CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeModifyAction(ITEM_DOMAIN_LOG_1)); + } + + ITEM_DOMAIN_LOG_1.MutableId()->SetGeneration(i + 1); + } + + for (int i = 0; i < 100; i++) { + NKikimrConfig::TAppConfig config; + config.MutableLogConfig()->SetClusterName(TStringBuilder() << "cluster-" << i); + + auto item = config.MutableVersion()->AddItems(); + item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); + item->SetId(1); + item->SetGeneration(i + 1); + + auto notification = runtime.GrabEdgeEventRethrow<TEvConsole::TEvConfigSubscriptionNotification>(edgeId); + + UNIT_ASSERT_VALUES_EQUAL(notification->Get()->Record.GetGeneration(), 1); + UNIT_ASSERT_VALUES_EQUAL(notification->Get()->Record.GetConfig().ShortDebugString(), config.ShortDebugString()); + } + } + + Y_UNIT_TEST(TestSubscriptionClientManyUpdatesAddRemove) { + TTenantTestRuntime runtime(DefaultConsoleTestConfig()); + TActorId edgeId = runtime.Sender; + + auto subscriber = NConsole::CreateConfigsSubscriber(edgeId, TVector<ui32>({(ui32)NKikimrConsole::TConfigItem::LogConfigItem}), NKikimrConfig::TAppConfig()); + + runtime.Register(subscriber); + + ui64 id = 0; + for (int i = 0; i < 100; i++) { + if (i % 2 == 0) { + auto logConfigItem = MakeConfigItem(NKikimrConsole::TConfigItem::LogConfigItem, + NKikimrConfig::TAppConfig(), {}, {}, "", "", 1, + NKikimrConsole::TConfigItem::MERGE, ""); + + logConfigItem.MutableConfig()->MutableLogConfig()->SetClusterName(TStringBuilder() << "cluster-" << i); + + auto ids = CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeAddAction(logConfigItem)); + + UNIT_ASSERT_VALUES_EQUAL(ids.size(), 1); + + id = ids[0]; + } else { + CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, MakeRemoveAction(id, 1)); + } + } + + for (int i = 0; i < 100; i++) { + NKikimrConfig::TAppConfig config; + + if (i % 2 == 0) { + config.MutableLogConfig()->SetClusterName(TStringBuilder() << "cluster-" << i); + + auto item = config.MutableVersion()->AddItems(); + item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); + item->SetId(i / 2 + 1); + item->SetGeneration(1); + } + + auto notification = runtime.GrabEdgeEventRethrow<TEvConsole::TEvConfigSubscriptionNotification>(edgeId); + + UNIT_ASSERT_VALUES_EQUAL(notification->Get()->Record.GetGeneration(), 1); + UNIT_ASSERT_VALUES_EQUAL(notification->Get()->Record.GetConfig().ShortDebugString(), config.ShortDebugString()); + } + } + + Y_UNIT_TEST(TestSubscriptionClientDeadCausesSupscriptionDeregistration) { + TTenantTestRuntime runtime(DefaultConsoleTestConfig()); + InitializeTestConfigItems(); + + TActorId edgeId = runtime.Sender; + + auto subscriber = NConsole::CreateConfigsSubscriber(edgeId, TVector<ui32>({(ui32)NKikimrConsole::TConfigItem::LogConfigItem}), NKikimrConfig::TAppConfig()); + const auto &clientId = runtime.Register(subscriber); + + TDispatchOptions options1; + options1.FinalEvents.emplace_back(TEvConsole::EvConfigSubscriptionResponse, 1); + runtime.DispatchEvents(options1); + + runtime.Send(new IEventHandle(clientId, edgeId, new TEvents::TEvPoisonPill()), 0, true); + + TDispatchOptions options2; + options2.FinalEvents.emplace_back(TEvConsole::EvConfigSubscriptionCanceled, 3); + runtime.DispatchEvents(options2); + } + + Y_UNIT_TEST(TestSubscriptionClientReconnectsOnConnectionLoose) { + TTenantTestRuntime runtime(MultipleNodesConsoleTestConfig()); + InitializeTestConfigItems(); + + TActorId edgeId = runtime.AllocateEdgeActor(1); + + auto subscriber = NConsole::CreateConfigsSubscriber(edgeId, TVector<ui32>({(ui32)NKikimrConsole::TConfigItem::LogConfigItem}), NKikimrConfig::TAppConfig()); + runtime.Register(subscriber, 1); + + TDispatchOptions options1; + options1.FinalEvents.emplace_back(TEvConsole::EvConfigSubscriptionResponse, 1); + runtime.DispatchEvents(options1); + + ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-1"); + + auto ids = CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, + MakeAddAction(ITEM_DOMAIN_LOG_1)); + + AssignIds(ids, ITEM_DOMAIN_LOG_1); + + NKikimrConfig::TAppConfig config1; + config1.MutableLogConfig()->SetClusterName("cluster-1"); + { + auto item = config1.MutableVersion()->AddItems(); + item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); + item->SetId(1); + item->SetGeneration(1); + } + + auto notification1 = runtime.GrabEdgeEventRethrow<TEvConsole::TEvConfigSubscriptionNotification>(edgeId); + + UNIT_ASSERT_VALUES_EQUAL(notification1->Get()->Record.GetGeneration(), 1); + UNIT_ASSERT_VALUES_EQUAL(notification1->Get()->Record.GetConfig().ShortDebugString(), config1.ShortDebugString()); + + TAutoPtr<IEventHandle> handle = new IEventHandle( + runtime.GetInterconnectProxy(0, 1), + runtime.Sender, + new TEvInterconnect::TEvDisconnect()); + + runtime.Send(handle.Release(), 0, true); + + TDispatchOptions options2; + options2.FinalEvents.emplace_back(TEvConsole::EvConfigSubscriptionResponse, 1); + runtime.DispatchEvents(options2); + + ITEM_DOMAIN_LOG_1.MutableConfig()->MutableLogConfig()->SetClusterName("cluster-2"); + + CheckConfigure(runtime, Ydb::StatusIds::SUCCESS, + MakeModifyAction(ITEM_DOMAIN_LOG_1)); + + NKikimrConfig::TAppConfig config2; + config2.MutableLogConfig()->SetClusterName("cluster-2"); + { + auto item = config2.MutableVersion()->AddItems(); + item->SetKind(NKikimrConsole::TConfigItem::LogConfigItem); + item->SetId(1); + item->SetGeneration(2); + } + + auto notification2 = runtime.GrabEdgeEventRethrow<TEvConsole::TEvConfigSubscriptionNotification>(edgeId); + + UNIT_ASSERT_VALUES_EQUAL(notification2->Get()->Record.GetGeneration(), 2); + UNIT_ASSERT_VALUES_EQUAL(notification2->Get()->Record.GetConfig().ShortDebugString(), config2.ShortDebugString()); + } +} + Y_UNIT_TEST_SUITE(TConsoleConfigHelpersTests) { Y_UNIT_TEST(TestConfigCourier) { TTenantTestRuntime runtime(TenantConsoleTestConfig()); @@ -3787,7 +3787,7 @@ Y_UNIT_TEST_SUITE(TConsoleConfigHelpersTests) { runtime.Register(courier1, 0); auto reply1 = runtime.GrabEdgeEventRethrow<TEvConsole::TEvGetNodeConfigResponse>(handle); UNIT_ASSERT_VALUES_EQUAL(handle->Cookie, 123); - CheckEqualsIgnoringVersion(reply1->Record.GetConfig(), config1); + CheckEqualsIgnoringVersion(reply1->Record.GetConfig(), config1); NKikimrConfig::TAppConfig config2; config2.MutableLogConfig()->SetClusterName("cluster2"); @@ -3796,7 +3796,7 @@ Y_UNIT_TEST_SUITE(TConsoleConfigHelpersTests) { runtime.Register(courier2, 0); auto reply2 = runtime.GrabEdgeEventRethrow<TEvConsole::TEvGetNodeConfigResponse>(handle); UNIT_ASSERT_VALUES_EQUAL(handle->Cookie, 321); - CheckEqualsIgnoringVersion(reply2->Record.GetConfig(), config2); + CheckEqualsIgnoringVersion(reply2->Record.GetConfig(), config2); } void TestConfigSubscriberBase(bool useService) diff --git a/ydb/core/cms/console/ut/ya.make b/ydb/core/cms/console/ut/ya.make index 56e16788e4..9f42e18427 100644 --- a/ydb/core/cms/console/ut/ya.make +++ b/ydb/core/cms/console/ut/ya.make @@ -27,7 +27,7 @@ PEERDIR( YQL_LAST_ABI_VERSION() SRCS( - configs_cache_ut.cpp + configs_cache_ut.cpp configs_dispatcher_ut.cpp console_ut_tenants.cpp console_ut_configs.cpp diff --git a/ydb/core/cms/console/ut_helpers.h b/ydb/core/cms/console/ut_helpers.h index d3c42b21e6..9faf6468fa 100644 --- a/ydb/core/cms/console/ut_helpers.h +++ b/ydb/core/cms/console/ut_helpers.h @@ -436,15 +436,15 @@ void AssignIds(const TVector<ui64> &ids, } -inline void CheckEqualsIgnoringVersion(NKikimrConfig::TAppConfig config1, NKikimrConfig::TAppConfig config2) -{ - config1.ClearVersion(); - config2.ClearVersion(); - - UNIT_ASSERT_VALUES_EQUAL(config1.ShortDebugString(), config2.ShortDebugString()); -} - - +inline void CheckEqualsIgnoringVersion(NKikimrConfig::TAppConfig config1, NKikimrConfig::TAppConfig config2) +{ + config1.ClearVersion(); + config2.ClearVersion(); + + UNIT_ASSERT_VALUES_EQUAL(config1.ShortDebugString(), config2.ShortDebugString()); +} + + } // namespace NUT } // namespace NConsole } // namesapce NKikimr diff --git a/ydb/core/cms/console/ya.make b/ydb/core/cms/console/ya.make index 66fc268d1d..e33d3fc19a 100644 --- a/ydb/core/cms/console/ya.make +++ b/ydb/core/cms/console/ya.make @@ -10,8 +10,8 @@ SRCS( config_helpers.h config_index.cpp config_index.h - configs_cache.cpp - configs_cache.h + configs_cache.cpp + configs_cache.h configs_config.cpp configs_config.h configs_dispatcher.cpp @@ -22,8 +22,8 @@ SRCS( console_configs_manager.h console_configs_provider.cpp console_configs_provider.h - console_configs_subscriber.cpp - console_configs_subscriber.h + console_configs_subscriber.cpp + console_configs_subscriber.h console_impl.h console_tenants_manager.cpp console_tenants_manager.h diff --git a/ydb/core/driver_lib/cli_utils/cli_cmds_server.cpp b/ydb/core/driver_lib/cli_utils/cli_cmds_server.cpp index 839f5d8b4c..6766dd3171 100644 --- a/ydb/core/driver_lib/cli_utils/cli_cmds_server.cpp +++ b/ydb/core/driver_lib/cli_utils/cli_cmds_server.cpp @@ -61,7 +61,7 @@ protected: bool NodeBrokerUseTls; bool FixedNodeID; bool IgnoreCmsConfigs; - bool HierarchicalCfg; + bool HierarchicalCfg; TString NodeAddress; TString NodeHost; TString NodeResolveHost; @@ -256,20 +256,20 @@ protected: ProxyBusSessionConfig.ConfigureLastGetopt(*config.Opts, "mbus-"); ProxyBusQueueConfig.ConfigureLastGetopt(*config.Opts, "mbus-"); - config.Opts->AddLongOption("hierarchic-cfg", "Use hierarchical approach for configuration parts overriding") - .NoArgument().SetFlag(&HierarchicalCfg); - + config.Opts->AddLongOption("hierarchic-cfg", "Use hierarchical approach for configuration parts overriding") + .NoArgument().SetFlag(&HierarchicalCfg); + config.SetFreeArgsMin(0); config.Opts->SetFreeArgDefaultTitle("PATH", "path to protobuf file; files are merged in order in which they are enlisted"); } template<typename TProto> - TProto *MutableConfigPart(TConfig& config, const char *optname, + TProto *MutableConfigPart(TConfig& config, const char *optname, bool (NKikimrConfig::TAppConfig::*hasConfig)() const, const TProto& (NKikimrConfig::TAppConfig::*getConfig)() const, TProto* (NKikimrConfig::TAppConfig::*mutableConfig)()) { TProto *res = nullptr; - if (!HierarchicalCfg && (AppConfig.*hasConfig)()) { + if (!HierarchicalCfg && (AppConfig.*hasConfig)()) { return nullptr; // this field is already provided in AppConfig, so we don't overwrite it } @@ -303,16 +303,16 @@ protected: virtual void Parse(TConfig& config) override { TClientCommand::Parse(config); -#define OPTION(NAME, FIELD) MutableConfigPart(config, NAME, &NKikimrConfig::TAppConfig::Has##FIELD, \ +#define OPTION(NAME, FIELD) MutableConfigPart(config, NAME, &NKikimrConfig::TAppConfig::Has##FIELD, \ &NKikimrConfig::TAppConfig::Get##FIELD, &NKikimrConfig::TAppConfig::Mutable##FIELD) #define OPTION_MERGE(NAME, FIELD) MutableConfigPartMerge(config, NAME, &NKikimrConfig::TAppConfig::Mutable##FIELD) - OPTION("auth-file", AuthConfig); - OPTION_MERGE("auth-token-file", AuthConfig); - - LoadBaseConfig(config); + OPTION("auth-file", AuthConfig); + OPTION_MERGE("auth-token-file", AuthConfig); + + LoadBaseConfig(config); LoadYamlConfig(); - + // start memorylog as soon as possible if (auto mem = OPTION("memorylog-file", MemoryLogConfig)) { if (mem->HasLogBufferSize() && mem->GetLogBufferSize() > 0) { @@ -664,74 +664,74 @@ protected: } } - inline bool LoadConfigFromCMS() { - TVector<TString> addrs; - FillClusterEndpoints(addrs); - - SetRandomSeed(TInstant::Now().MicroSeconds()); - - int minAttempts = 10; - int attempts = 0; - - TString error; - - while (attempts < minAttempts) { - for (const auto &addr : addrs) { - // Randomized backoff - if (attempts > 0) - Sleep(TDuration::MilliSeconds(500 + RandomNumber<ui64>(1000))); - + inline bool LoadConfigFromCMS() { + TVector<TString> addrs; + FillClusterEndpoints(addrs); + + SetRandomSeed(TInstant::Now().MicroSeconds()); + + int minAttempts = 10; + int attempts = 0; + + TString error; + + while (attempts < minAttempts) { + for (const auto &addr : addrs) { + // Randomized backoff + if (attempts > 0) + Sleep(TDuration::MilliSeconds(500 + RandomNumber<ui64>(1000))); + NClient::TKikimr kikimr(GetKikimr(addr)); - auto configurator = kikimr.GetNodeConfigurator(); - - Cout << "Trying to get configs from " << addr << Endl; - - auto result = configurator.SyncGetNodeConfig(RunConfig.NodeId, - FQDNHostName(), - TenantName, - NodeType, - DeduceNodeDomain(), - AppConfig.GetAuthConfig().GetStaffApiUserToken()); - - if (result.IsSuccess()) { - auto appConfig = result.GetConfig(); - - if (RunConfig.PathToConfigCacheFile) { - Cout << "Saving config to cache file " << RunConfig.PathToConfigCacheFile << Endl; - if (!SaveConfigForNodeToCache(appConfig)) { - Cout << "Failed to save config to cache file" << Endl; - } - } - - BaseConfig.Swap(&appConfig); - - Cout << "Success." << Endl; - - return true; - } - - error = result.GetErrorMessage(); - Cerr << "Configuration error: " << error << Endl; - ++attempts; - } - } - - return false; - } - - inline bool LoadConfigFromCache() { - if (RunConfig.PathToConfigCacheFile) { - NKikimrConfig::TAppConfig config; - if (GetCachedConfig(config)) { - BaseConfig.Swap(&config); - - return true; - } - } - - return false; - } - + auto configurator = kikimr.GetNodeConfigurator(); + + Cout << "Trying to get configs from " << addr << Endl; + + auto result = configurator.SyncGetNodeConfig(RunConfig.NodeId, + FQDNHostName(), + TenantName, + NodeType, + DeduceNodeDomain(), + AppConfig.GetAuthConfig().GetStaffApiUserToken()); + + if (result.IsSuccess()) { + auto appConfig = result.GetConfig(); + + if (RunConfig.PathToConfigCacheFile) { + Cout << "Saving config to cache file " << RunConfig.PathToConfigCacheFile << Endl; + if (!SaveConfigForNodeToCache(appConfig)) { + Cout << "Failed to save config to cache file" << Endl; + } + } + + BaseConfig.Swap(&appConfig); + + Cout << "Success." << Endl; + + return true; + } + + error = result.GetErrorMessage(); + Cerr << "Configuration error: " << error << Endl; + ++attempts; + } + } + + return false; + } + + inline bool LoadConfigFromCache() { + if (RunConfig.PathToConfigCacheFile) { + NKikimrConfig::TAppConfig config; + if (GetCachedConfig(config)) { + BaseConfig.Swap(&config); + + return true; + } + } + + return false; + } + inline void LoadYamlConfig() { for(const TString& yamlConfigFile: YamlConfigFiles) { auto yamlConfig = TFileInput(yamlConfigFile); @@ -762,32 +762,32 @@ protected: inline bool LoadBootstrapConfig(TConfig& config) { bool res = false; - for (const TString& path : config.ParseResult->GetFreeArgs()) { - NKikimrConfig::TAppConfig parsedConfig; - const bool result = ParsePBFromFile(path, &parsedConfig); - Y_VERIFY(result); - BaseConfig.MergeFrom(parsedConfig); - res = true; - } - - return res; - } - - void LoadBaseConfig(TConfig& config) { - if (HierarchicalCfg) { - if (LoadConfigFromCMS()) - return; - if (LoadConfigFromCache()) - return; - if (LoadBootstrapConfig(config)) - return; - - ythrow yexception() << "cannot load configuration"; - } else { - LoadBootstrapConfig(config); - } - } - + for (const TString& path : config.ParseResult->GetFreeArgs()) { + NKikimrConfig::TAppConfig parsedConfig; + const bool result = ParsePBFromFile(path, &parsedConfig); + Y_VERIFY(result); + BaseConfig.MergeFrom(parsedConfig); + res = true; + } + + return res; + } + + void LoadBaseConfig(TConfig& config) { + if (HierarchicalCfg) { + if (LoadConfigFromCMS()) + return; + if (LoadConfigFromCache()) + return; + if (LoadBootstrapConfig(config)) + return; + + ythrow yexception() << "cannot load configuration"; + } else { + LoadBootstrapConfig(config); + } + } + TString DeduceTenantDomain() { if (TenantDomain) return TenantDomain; @@ -846,13 +846,13 @@ protected: if (!NodeId) ythrow yexception() << "Either --node [NUM|'static'] or --node-broker[-port] should be specified"; - if (!HierarchicalCfg && RunConfig.PathToConfigCacheFile) + if (!HierarchicalCfg && RunConfig.PathToConfigCacheFile) LoadCachedConfigsForStaticNode(); return; } RegisterDynamicNode(); - if (!HierarchicalCfg && !IgnoreCmsConfigs) + if (!HierarchicalCfg && !IgnoreCmsConfigs) LoadConfigForDynamicNode(); } diff --git a/ydb/core/driver_lib/run/config.h b/ydb/core/driver_lib/run/config.h index daa471ef53..faf1797413 100644 --- a/ydb/core/driver_lib/run/config.h +++ b/ydb/core/driver_lib/run/config.h @@ -59,7 +59,7 @@ union TBasicKikimrServicesMask { bool EnableSysViewService:1; bool EnableMeteringWriter:1; bool EnableSchemeBoardMonitoring:1; - bool EnableConfigsCache:1; + bool EnableConfigsCache:1; bool EnableLongTxService:1; bool EnableHealthCheckService:1; bool EnableYandexQuery:1; diff --git a/ydb/core/driver_lib/run/kikimr_services_initializers.cpp b/ydb/core/driver_lib/run/kikimr_services_initializers.cpp index 3712a88c65..819c1478d1 100644 --- a/ydb/core/driver_lib/run/kikimr_services_initializers.cpp +++ b/ydb/core/driver_lib/run/kikimr_services_initializers.cpp @@ -1037,7 +1037,7 @@ void TLoggerInitializer::InitializeServices( setup->LocalServices.push_back(loggerActorPair); IActor *configurator; - if (PathToConfigCacheFile && !appData->FeatureFlags.GetEnableConfigurationCache()) { + if (PathToConfigCacheFile && !appData->FeatureFlags.GetEnableConfigurationCache()) { configurator = NConsole::CreateLogSettingsConfigurator(PathToConfigCacheFile); } else { configurator = NConsole::CreateLogSettingsConfigurator(); @@ -2126,21 +2126,21 @@ void TConfigsDispatcherInitializer::InitializeServices(NActors::TActorSystemSetu TActorSetupCmd(actor, TMailboxType::HTSwap, appData->UserPoolId))); } -TConfigsCacheInitializer::TConfigsCacheInitializer(const TKikimrRunConfig& runConfig) - : IKikimrServicesInitializer(runConfig) - , PathToConfigCacheFile(runConfig.PathToConfigCacheFile) -{ -} - -void TConfigsCacheInitializer::InitializeServices(NActors::TActorSystemSetup* setup, const NKikimr::TAppData* appData) { - if (PathToConfigCacheFile && appData->FeatureFlags.GetEnableConfigurationCache()) { - IActor* actor = NConsole::CreateConfigsCacheActor(PathToConfigCacheFile); - setup->LocalServices.push_back(std::pair<TActorId, TActorSetupCmd>( - NConsole::MakeConfigsCacheActorID(NodeId), - TActorSetupCmd(actor, TMailboxType::HTSwap, appData->UserPoolId))); - } -} - +TConfigsCacheInitializer::TConfigsCacheInitializer(const TKikimrRunConfig& runConfig) + : IKikimrServicesInitializer(runConfig) + , PathToConfigCacheFile(runConfig.PathToConfigCacheFile) +{ +} + +void TConfigsCacheInitializer::InitializeServices(NActors::TActorSystemSetup* setup, const NKikimr::TAppData* appData) { + if (PathToConfigCacheFile && appData->FeatureFlags.GetEnableConfigurationCache()) { + IActor* actor = NConsole::CreateConfigsCacheActor(PathToConfigCacheFile); + setup->LocalServices.push_back(std::pair<TActorId, TActorSetupCmd>( + NConsole::MakeConfigsCacheActorID(NodeId), + TActorSetupCmd(actor, TMailboxType::HTSwap, appData->UserPoolId))); + } +} + // TTabletInfoInitializer TTabletInfoInitializer::TTabletInfoInitializer(const TKikimrRunConfig& runConfig) diff --git a/ydb/core/driver_lib/run/kikimr_services_initializers.h b/ydb/core/driver_lib/run/kikimr_services_initializers.h index 55162e6ffb..407ce1bb7b 100644 --- a/ydb/core/driver_lib/run/kikimr_services_initializers.h +++ b/ydb/core/driver_lib/run/kikimr_services_initializers.h @@ -428,15 +428,15 @@ public: void InitializeServices(NActors::TActorSystemSetup* setup, const NKikimr::TAppData* appData) override; }; -class TConfigsCacheInitializer : public IKikimrServicesInitializer { -private: - TString PathToConfigCacheFile; -public: - TConfigsCacheInitializer(const TKikimrRunConfig& runConfig); - - void InitializeServices(NActors::TActorSystemSetup* setup, const NKikimr::TAppData* appData) override; -}; - +class TConfigsCacheInitializer : public IKikimrServicesInitializer { +private: + TString PathToConfigCacheFile; +public: + TConfigsCacheInitializer(const TKikimrRunConfig& runConfig); + + void InitializeServices(NActors::TActorSystemSetup* setup, const NKikimr::TAppData* appData) override; +}; + class TTabletInfoInitializer : public IKikimrServicesInitializer { public: TTabletInfoInitializer(const TKikimrRunConfig& runConfig); diff --git a/ydb/core/driver_lib/run/run.cpp b/ydb/core/driver_lib/run/run.cpp index 233e70588e..a4f74aa4e0 100644 --- a/ydb/core/driver_lib/run/run.cpp +++ b/ydb/core/driver_lib/run/run.cpp @@ -204,7 +204,7 @@ public: appData->FeatureFlags = Config.GetFeatureFlags(); appData->AllowHugeKeyValueDeletes = Config.GetFeatureFlags().GetAllowHugeKeyValueDeletes(); appData->EnableKqpSpilling = Config.GetTableServiceConfig().GetSpillingServiceConfig().GetLocalFileConfig().GetEnable(); - + appData->CompactionConfig = Config.GetCompactionConfig(); } }; @@ -1284,10 +1284,10 @@ TIntrusivePtr<TServiceInitializersList> TKikimrRunner::CreateServiceInitializers sil->AddServiceInitializer(new TConfigsDispatcherInitializer(runConfig)); } - if (serviceMask.EnableConfigsCache) { - sil->AddServiceInitializer(new TConfigsCacheInitializer(runConfig)); - } - + if (serviceMask.EnableConfigsCache) { + sil->AddServiceInitializer(new TConfigsCacheInitializer(runConfig)); + } + if (serviceMask.EnableTabletInfo) { sil->AddServiceInitializer(new TTabletInfoInitializer(runConfig)); } diff --git a/ydb/core/engine/minikql/flat_local_minikql_host.h b/ydb/core/engine/minikql/flat_local_minikql_host.h index c288ff46ad..edfd182286 100644 --- a/ydb/core/engine/minikql/flat_local_minikql_host.h +++ b/ydb/core/engine/minikql/flat_local_minikql_host.h @@ -29,11 +29,11 @@ private: return Factory->GetWriteVersion(tableId); } - TRowVersion GetReadVersion(const TTableId& tableId) const override - { - return Factory->GetReadVersion(tableId); - } - + TRowVersion GetReadVersion(const TTableId& tableId) const override + { + return Factory->GetReadVersion(tableId); + } + IChangeCollector* GetChangeCollector(const TTableId& tableId) const override { return Factory->GetChangeCollector(tableId); diff --git a/ydb/core/engine/minikql/flat_local_tx_factory.cpp b/ydb/core/engine/minikql/flat_local_tx_factory.cpp index d13df9469d..d23f4d8bc7 100644 --- a/ydb/core/engine/minikql/flat_local_tx_factory.cpp +++ b/ydb/core/engine/minikql/flat_local_tx_factory.cpp @@ -33,17 +33,17 @@ TRowVersion TMiniKQLFactory::GetWriteVersion(const TTableId& tableId) const return TRowVersion::Min(); } -TRowVersion TMiniKQLFactory::GetReadVersion(const TTableId& tableId) const -{ - Y_UNUSED(tableId); - return TRowVersion::Max(); +TRowVersion TMiniKQLFactory::GetReadVersion(const TTableId& tableId) const +{ + Y_UNUSED(tableId); + return TRowVersion::Max(); } - + IChangeCollector* TMiniKQLFactory::GetChangeCollector(const TTableId& tableId) const { Y_UNUSED(tableId); return nullptr; } -} +} } diff --git a/ydb/core/engine/minikql/flat_local_tx_factory.h b/ydb/core/engine/minikql/flat_local_tx_factory.h index 0aeae30553..200d21b369 100644 --- a/ydb/core/engine/minikql/flat_local_tx_factory.h +++ b/ydb/core/engine/minikql/flat_local_tx_factory.h @@ -16,7 +16,7 @@ namespace NMiniKQL { TAutoPtr<ITransaction> Make(TEvTablet::TEvLocalReadColumns::TPtr &ev) override; virtual TRowVersion GetWriteVersion(const TTableId& tableId) const; - virtual TRowVersion GetReadVersion(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/minikql_engine_host.cpp b/ydb/core/engine/minikql/minikql_engine_host.cpp index 2935f6c36d..36c35f32cc 100644 --- a/ydb/core/engine/minikql/minikql_engine_host.cpp +++ b/ydb/core/engine/minikql/minikql_engine_host.cpp @@ -250,8 +250,8 @@ void TEngineHost::PinPages(const TVector<THolder<TKeyDesc>>& keys, ui64 pageFaul Settings.DisableByKeyFilter ? (ui64)NTable::NoByKey : 0, adjustLimit(key.RangeLimits.ItemsLimit), adjustLimit(key.RangeLimits.BytesLimit), - key.Reverse ? NTable::EDirection::Reverse : NTable::EDirection::Forward, - GetReadVersion(key.TableId)); + key.Reverse ? NTable::EDirection::Reverse : NTable::EDirection::Forward, + GetReadVersion(key.TableId)); ret &= ready; } @@ -295,12 +295,12 @@ NUdf::TUnboxedValue TEngineHost::SelectRow(const TTableId& tableId, const TArray Counters.NSelectRow++; Settings.KeyAccessSampler->AddSample(tableId, row); - NTable::TSelectStats stats; + NTable::TSelectStats stats; ui64 flags = Settings.DisableByKeyFilter ? (ui64)NTable::NoByKey : 0; - const auto ready = Db.Select(localTid, key, tags, dbRow, stats, flags, GetReadVersion(tableId)); - - Counters.InvisibleRowSkips += stats.Invisible; - + const auto ready = Db.Select(localTid, key, tags, dbRow, stats, flags, GetReadVersion(tableId)); + + Counters.InvisibleRowSkips += stats.Invisible; + if (NTable::EReady::Page == ready) { if (auto collector = GetChangeCollector(tableId)) { collector->Reset(); @@ -504,9 +504,9 @@ public: List.EngineHost.GetCounters().SelectRangeDeletedRowSkips += std::exchange(Iter->Stats.DeletedRowSkips, 0); - List.EngineHost.GetCounters().InvisibleRowSkips - += std::exchange(Iter->Stats.InvisibleRowSkips, 0); - + List.EngineHost.GetCounters().InvisibleRowSkips + += std::exchange(Iter->Stats.InvisibleRowSkips, 0); + // Skip null keys Y_VERIFY(List.SkipNullKeys.size() <= tuple.ColumnCount); bool skipRow = false; @@ -569,7 +569,7 @@ public: } List.EngineHost.GetCounters().SelectRangeDeletedRowSkips += std::exchange(Iter->Stats.DeletedRowSkips, 0); - List.EngineHost.GetCounters().InvisibleRowSkips += std::exchange(Iter->Stats.InvisibleRowSkips, 0); + List.EngineHost.GetCounters().InvisibleRowSkips += std::exchange(Iter->Stats.InvisibleRowSkips, 0); if (Iter->Last() == NTable::EReady::Page) { if (auto collector = List.EngineHost.GetChangeCollector(List.TableId)) { @@ -661,13 +661,13 @@ public: keyRange.MinInclusive = tableRange.InclusiveFrom; keyRange.MaxInclusive = tableRange.InclusiveTo; if (Reverse) { - auto read = Db.IterateRangeReverse(LocalTid, keyRange, Tags, EngineHost.GetReadVersion(TableId)); + auto read = Db.IterateRangeReverse(LocalTid, keyRange, Tags, EngineHost.GetReadVersion(TableId)); return NUdf::TUnboxedValuePod( new TIterator<NTable::TTableReverseIt>(GetMemInfo(), *this, std::move(read), SystemColumnTags, ShardId) ); } else { - auto read = Db.IterateRange(LocalTid, keyRange, Tags, EngineHost.GetReadVersion(TableId)); + auto read = Db.IterateRange(LocalTid, keyRange, Tags, EngineHost.GetReadVersion(TableId)); return NUdf::TUnboxedValuePod( new TIterator<NTable::TTableIt>(GetMemInfo(), *this, std::move(read), SystemColumnTags, ShardId) diff --git a/ydb/core/engine/minikql/minikql_engine_host.h b/ydb/core/engine/minikql/minikql_engine_host.h index e410999413..012ee6891b 100644 --- a/ydb/core/engine/minikql/minikql_engine_host.h +++ b/ydb/core/engine/minikql/minikql_engine_host.h @@ -26,8 +26,8 @@ struct TEngineHostCounters { ui64 UpdateRowBytes = 0; ui64 EraseRowBytes = 0; - ui64 InvisibleRowSkips = 0; - + ui64 InvisibleRowSkips = 0; + TEngineHostCounters& operator+=(const TEngineHostCounters& other) { NSelectRow += other.NSelectRow; NSelectRange += other.NSelectRange; @@ -57,7 +57,7 @@ struct TEngineHostCounters { << ", UpdateRowBytes: " << UpdateRowBytes << ", EraseRowBytes: " << EraseRowBytes << ", SelectRangeDeletedRowSkips: " << SelectRangeDeletedRowSkips - << ", InvisibleRowSkips: " << InvisibleRowSkips + << ", InvisibleRowSkips: " << InvisibleRowSkips << "}"; } }; @@ -124,9 +124,9 @@ public: TEngineHostCounters& GetCounters() const { return Counters; } - virtual TRowVersion GetWriteVersion(const TTableId& tableId) const = 0; - virtual TRowVersion GetReadVersion(const TTableId& tableId) const = 0; - + virtual TRowVersion GetWriteVersion(const TTableId& tableId) const = 0; + virtual TRowVersion GetReadVersion(const TTableId& tableId) const = 0; + virtual IChangeCollector* GetChangeCollector(const TTableId& tableId) const = 0; protected: @@ -151,11 +151,11 @@ public: Y_UNUSED(tableId); return TRowVersion::Min(); } - - TRowVersion GetReadVersion(const TTableId& tableId) const override { - Y_UNUSED(tableId); - return TRowVersion::Max(); - } + + TRowVersion GetReadVersion(const TTableId& tableId) const override { + Y_UNUSED(tableId); + return TRowVersion::Max(); + } IChangeCollector* GetChangeCollector(const TTableId& tableId) const override { Y_UNUSED(tableId); diff --git a/ydb/core/kqp/common/kqp_common.h b/ydb/core/kqp/common/kqp_common.h index cd933d0672..f9379ad129 100644 --- a/ydb/core/kqp/common/kqp_common.h +++ b/ydb/core/kqp/common/kqp_common.h @@ -53,7 +53,7 @@ struct TKqpSnapshotEvents { enum EKqpSnapshotEvents { EvCreateSnapshotRequest = EventSpaceBegin(TKikimrEvents::ES_KQP) + 150, EvCreateSnapshotResponse, - EvDiscardSnapshot + EvDiscardSnapshot }; }; diff --git a/ydb/core/kqp/common/kqp_gateway.h b/ydb/core/kqp/common/kqp_gateway.h index 7e97eaa028..1e06beca39 100644 --- a/ydb/core/kqp/common/kqp_gateway.h +++ b/ydb/core/kqp/common/kqp_gateway.h @@ -120,7 +120,7 @@ public: NYql::NDqProto::EDqStatsMode StatsMode = NYql::NDqProto::DQ_STATS_MODE_NONE; bool DisableLlvmForUdfStages = false; bool LlvmEnabled = true; - TKqpSnapshot Snapshot = TKqpSnapshot(); + TKqpSnapshot Snapshot = TKqpSnapshot(); NKikimrKqp::EIsolationLevel IsolationLevel = NKikimrKqp::ISOLATION_LEVEL_UNDEFINED; TMaybe<NKikimrKqp::TRlPath> RlPath; }; @@ -149,8 +149,8 @@ public: virtual void DiscardPersistentSnapshot(const TKqpSnapshotHandle& handle) = 0; - virtual NThreading::TFuture<TKqpSnapshotHandle> AcquireMvccSnapshot(TDuration queryTimeout) = 0; - + virtual NThreading::TFuture<TKqpSnapshotHandle> AcquireMvccSnapshot(TDuration queryTimeout) = 0; + /* Physical */ virtual NThreading::TFuture<TExecPhysicalResult> ExecutePhysical(TExecPhysicalRequest&& request, const NActors::TActorId& target) = 0; diff --git a/ydb/core/kqp/common/kqp_transform.h b/ydb/core/kqp/common/kqp_transform.h index 3038918731..457c424801 100644 --- a/ydb/core/kqp/common/kqp_transform.h +++ b/ydb/core/kqp/common/kqp_transform.h @@ -59,23 +59,23 @@ struct TKqpTxLocks { NKikimrMiniKQL::TListType LocksListType; THashMap<TKqpTxLock::TKey, TKqpTxLock> LocksMap; - TMaybe<NYql::TIssue> LockIssue; - + TMaybe<NYql::TIssue> LockIssue; + bool HasLocks() const { return !LocksMap.empty(); } - bool Broken() const { return LockIssue.Defined(); } - void MarkBroken(NYql::TIssue lockIssue) { LockIssue.ConstructInPlace(std::move(lockIssue)); } + bool Broken() const { return LockIssue.Defined(); } + void MarkBroken(NYql::TIssue lockIssue) { LockIssue.ConstructInPlace(std::move(lockIssue)); } ui64 GetLockTxId() const { return HasLocks() ? LocksMap.begin()->second.GetLockId() : 0; } size_t Size() const { return LocksMap.size(); } - void ReportIssues(NYql::TExprContext& ctx) { - if (LockIssue) - ctx.AddError(*LockIssue); - } - - void Clear() { - LocksMap.clear(); - LockIssue.Clear(); - } + void ReportIssues(NYql::TExprContext& ctx) { + if (LockIssue) + ctx.AddError(*LockIssue); + } + + void Clear() { + LocksMap.clear(); + LockIssue.Clear(); + } }; using TParamValueMap = THashMap<TString, NKikimrMiniKQL::TParams>; @@ -178,10 +178,10 @@ public: return DeferredEffects.Add(physicalTx, std::move(params)); } - const IKqpGateway::TKqpSnapshot& GetSnapshot() const { - return SnapshotHandle.Snapshot; - } - + const IKqpGateway::TKqpSnapshot& GetSnapshot() const { + return SnapshotHandle.Snapshot; + } + void Finish() final { YQL_ENSURE(DeferredEffects.Empty()); YQL_ENSURE(!Locks.HasLocks()); diff --git a/ydb/core/kqp/executer/kqp_data_executer.cpp b/ydb/core/kqp/executer/kqp_data_executer.cpp index bb94fda550..003d4ffa20 100644 --- a/ydb/core/kqp/executer/kqp_data_executer.cpp +++ b/ydb/core/kqp/executer/kqp_data_executer.cpp @@ -1184,27 +1184,27 @@ private: << ", lockTxId: " << lockTxId << ", locks: " << dataTransaction.GetKqpTransaction().GetLocks().ShortDebugString()); - TEvDataShard::TEvProposeTransaction* ev; + TEvDataShard::TEvProposeTransaction* ev; if (Request.Snapshot.IsValid() && ReadOnlyTx) { - ev = new TEvDataShard::TEvProposeTransaction( + ev = new TEvDataShard::TEvProposeTransaction( NKikimrTxDataShard::TX_KIND_DATA, SelfId(), TxId, dataTransaction.SerializeAsString(), - Request.Snapshot.Step, - Request.Snapshot.TxId, + Request.Snapshot.Step, + Request.Snapshot.TxId, ImmediateTx ? NTxDataShard::TTxFlags::Immediate : 0); - } else { - ev = new TEvDataShard::TEvProposeTransaction( - NKikimrTxDataShard::TX_KIND_DATA, - SelfId(), - TxId, - dataTransaction.SerializeAsString(), + } else { + ev = new TEvDataShard::TEvProposeTransaction( + NKikimrTxDataShard::TX_KIND_DATA, + SelfId(), + TxId, + dataTransaction.SerializeAsString(), ImmediateTx ? NTxDataShard::TTxFlags::Immediate : 0); - } + } Send(MakePipePeNodeCacheID(UseFollowers), new TEvPipeCache::TEvForward(ev, shardId, true)); - + auto result = ShardStates.emplace(shardId, std::move(shardState)); YQL_ENSURE(result.second); } diff --git a/ydb/core/kqp/executer/kqp_scan_executer.cpp b/ydb/core/kqp/executer/kqp_scan_executer.cpp index 17787be875..07c29f64e2 100644 --- a/ydb/core/kqp/executer/kqp_scan_executer.cpp +++ b/ydb/core/kqp/executer/kqp_scan_executer.cpp @@ -899,7 +899,7 @@ private: LOG_D("Total tasks: " << TasksGraph.GetTasks().size() << ", readonly: true" << ", " << nScanTasks << " scan tasks on " << scanTasks.size() << " nodes" << ", totalShardScans: " << nShardScans << ", execType: Scan" - << ", snapshot: {" << Request.Snapshot.TxId << ", " << Request.Snapshot.Step << "}"); + << ", snapshot: {" << Request.Snapshot.TxId << ", " << Request.Snapshot.Step << "}"); ExecuteScanTx(std::move(computeTasks), std::move(scanTasks)); @@ -919,7 +919,7 @@ private: } auto planner = CreateKqpPlanner(TxId, SelfId(), std::move(computeTasks), - std::move(scanTasks), Request.Snapshot, + std::move(scanTasks), Request.Snapshot, Database, UserToken, Deadline.GetOrElse(TInstant::Zero()), Request.StatsMode, Request.DisableLlvmForUdfStages, Request.LlvmEnabled, AppData()->EnableKqpSpilling, Request.RlPath); RegisterWithSameMailbox(planner); diff --git a/ydb/core/kqp/host/kqp_host_impl.h b/ydb/core/kqp/host/kqp_host_impl.h index 0f3ba169bd..fb1fb139cd 100644 --- a/ydb/core/kqp/host/kqp_host_impl.h +++ b/ydb/core/kqp/host/kqp_host_impl.h @@ -278,9 +278,9 @@ TAutoPtr<NYql::IGraphTransformer> CreateKqpExecutePreparedTransformer(TIntrusive const TString& cluster, TIntrusivePtr<TKqpTransactionState> txState, TIntrusivePtr<TKqlTransformContext> transformCtx); -TAutoPtr<NYql::IGraphTransformer> CreateKqpAcquireMvccSnapshotTransformer(TIntrusivePtr<IKqpGateway> gateway, - TIntrusivePtr<TKqpTransactionState> txState, TIntrusivePtr<TKqlTransformContext> transformCtx, bool newEngine = false); - +TAutoPtr<NYql::IGraphTransformer> CreateKqpAcquireMvccSnapshotTransformer(TIntrusivePtr<IKqpGateway> gateway, + TIntrusivePtr<TKqpTransactionState> txState, TIntrusivePtr<TKqlTransformContext> transformCtx, bool newEngine = false); + TAutoPtr<NYql::IGraphTransformer> CreateKqpExecutePhysicalDataTransformer(TIntrusivePtr<IKqpGateway> gateway, const TString& cluster, TIntrusivePtr<TKqpTransactionState> txState, TIntrusivePtr<TKqlTransformContext> transformCtx); diff --git a/ydb/core/kqp/host/kqp_run_data.cpp b/ydb/core/kqp/host/kqp_run_data.cpp index b241b0733b..b2bc80d71b 100644 --- a/ydb/core/kqp/host/kqp_run_data.cpp +++ b/ydb/core/kqp/host/kqp_run_data.cpp @@ -49,8 +49,8 @@ protected: } if (commit) { - Y_VERIFY_DEBUG(txState.DeferredEffects.Empty() || !txState.Locks.Broken()); - + Y_VERIFY_DEBUG(txState.DeferredEffects.Empty() || !txState.Locks.Broken()); + for (const auto& effect : txState.DeferredEffects) { YQL_ENSURE(!effect.Node); YQL_ENSURE(effect.PhysicalTx.GetType() == NKqpProto::TKqpPhyTx::TYPE_DATA); @@ -62,15 +62,15 @@ protected: } if (txState.Locks.HasLocks()) { - request.ValidateLocks = !(txState.GetSnapshot().IsValid() && txState.DeferredEffects.Empty()); + request.ValidateLocks = !(txState.GetSnapshot().IsValid() && txState.DeferredEffects.Empty()); request.EraseLocks = true; for (auto& [lockId, lock] : txState.Locks.LocksMap) { request.Locks.emplace_back(lock.GetValueRef(txState.Locks.LockType)); } } - } else if (ShouldAcquireLocks()) { - request.AcquireLocksTxId = txState.Locks.GetLockTxId(); + } else if (ShouldAcquireLocks()) { + request.AcquireLocksTxId = txState.Locks.GetLockTxId(); } ExecuteFuture = Gateway->ExecutePhysical(std::move(request), {}); @@ -135,42 +135,42 @@ private: request.MaxAffectedShards = TransformCtx->QueryCtx->Limits.PhaseLimits.AffectedShardsLimit; request.TotalReadSizeLimitBytes = TransformCtx->QueryCtx->Limits.PhaseLimits.TotalReadSizeLimitBytes; request.MkqlMemoryLimit = TransformCtx->QueryCtx->Limits.PhaseLimits.ComputeNodeMemoryLimitBytes; - request.Snapshot = TxState->Tx().GetSnapshot(); + request.Snapshot = TxState->Tx().GetSnapshot(); request.IsolationLevel = *TxState->Tx().EffectiveIsolationLevel; return request; } - bool ShouldAcquireLocks() { - if (*TxState->Tx().EffectiveIsolationLevel != NKikimrKqp::ISOLATION_LEVEL_SERIALIZABLE) { - return false; - } - - if (TxState->Tx().Locks.Broken()) { - return false; // Do not acquire locks after first lock issue - } - + bool ShouldAcquireLocks() { + if (*TxState->Tx().EffectiveIsolationLevel != NKikimrKqp::ISOLATION_LEVEL_SERIALIZABLE) { + return false; + } + + if (TxState->Tx().Locks.Broken()) { + return false; // Do not acquire locks after first lock issue + } + if (!TxState->Tx().DeferredEffects.Empty()) { - return true; // Acquire locks in read write tx - } - + return true; // Acquire locks in read write tx + } + for (auto& tx : TransformCtx->PhysicalQuery->GetTransactions()) { if (tx.GetHasEffects()) { return true; // Acquire locks in read write tx } } - if (!TransformCtx->Settings.GetCommitTx()) { - return true; // Is not a commit tx - } - - if (TxState->Tx().GetSnapshot().IsValid()) { - return false; // It is a read only tx with snapshot, no need to acquire locks - } - - return true; - } - + if (!TransformCtx->Settings.GetCommitTx()) { + return true; // Is not a commit tx + } + + if (TxState->Tx().GetSnapshot().IsValid()) { + return false; // It is a read only tx with snapshot, no need to acquire locks + } + + return true; + } + TKqpParamsMap GetParamsRefMap(const TParamValueMap& map) { TKqpParamsMap paramsMap(TransformState); for (auto& pair : map) { diff --git a/ydb/core/kqp/host/kqp_run_physical.cpp b/ydb/core/kqp/host/kqp_run_physical.cpp index ad2b583b5c..e6bd601eef 100644 --- a/ydb/core/kqp/host/kqp_run_physical.cpp +++ b/ydb/core/kqp/host/kqp_run_physical.cpp @@ -35,9 +35,9 @@ IGraphTransformer::TStatus TKqpExecutePhysicalTransformerBase::DoTransform(TExpr } else { if (CurrentTxIndex >= txsCount) { if (!txState.DeferredEffects.Empty() && TxState->Tx().Locks.Broken()) { - TxState->Tx().Locks.ReportIssues(ctx); - return TStatus::Error; - } + TxState->Tx().Locks.ReportIssues(ctx); + return TStatus::Error; + } if (settings.GetCommitTx()) { status = Execute(nullptr, /* commit */ true, ctx); diff --git a/ydb/core/kqp/host/kqp_run_prepared.cpp b/ydb/core/kqp/host/kqp_run_prepared.cpp index 601853b19d..e71a3bacee 100644 --- a/ydb/core/kqp/host/kqp_run_prepared.cpp +++ b/ydb/core/kqp/host/kqp_run_prepared.cpp @@ -35,7 +35,7 @@ public: const auto& mkql = kql.GetMkqls(CurrentMkqlIndex); - AcquireLocks = ShouldAcquireLocks(kql); + AcquireLocks = ShouldAcquireLocks(kql); Promise = NewPromise(); @@ -142,7 +142,7 @@ private: future = Gateway->ExecuteMkqlPrepared(Cluster, mkql.GetProgram(), std::move(execParams), TransformCtx->GetMkqlSettings(false, Gateway->GetCurrentTime()), - TxState->Tx().GetSnapshot()); + TxState->Tx().GetSnapshot()); return true; } @@ -156,34 +156,34 @@ private: return CompileExpr(*astRes.Root, expr, ctx, nullptr); } - bool ShouldAcquireLocks(const NKikimrKqp::TPreparedKql& kql) { - if (*TxState->Tx().EffectiveIsolationLevel != NKikimrKqp::ISOLATION_LEVEL_SERIALIZABLE) { - return false; - } - - if (TxState->Tx().Locks.Broken()) { - return false; // Do not acquire locks after first lock issue - } - - if (!TxState->Tx().DeferredEffects.Empty() || !kql.GetEffects().empty()) { - return true; // Acquire locks in read write tx - } - - if (!TransformCtx->Settings.GetCommitTx()) { - return true; // It is not a commit tx - } - - if (TxState->Tx().GetSnapshot().IsValid()) { - return false; // Read only tx with snapshot, no need to acquire locks - } - - if (CurrentMkqlIndex == kql.MkqlsSize() - 1 && !TxState->Tx().Locks.HasLocks()) { - return false; // Final phase of read only tx, no need to acquire locks - } - - return true; - } - + bool ShouldAcquireLocks(const NKikimrKqp::TPreparedKql& kql) { + if (*TxState->Tx().EffectiveIsolationLevel != NKikimrKqp::ISOLATION_LEVEL_SERIALIZABLE) { + return false; + } + + if (TxState->Tx().Locks.Broken()) { + return false; // Do not acquire locks after first lock issue + } + + if (!TxState->Tx().DeferredEffects.Empty() || !kql.GetEffects().empty()) { + return true; // Acquire locks in read write tx + } + + if (!TransformCtx->Settings.GetCommitTx()) { + return true; // It is not a commit tx + } + + if (TxState->Tx().GetSnapshot().IsValid()) { + return false; // Read only tx with snapshot, no need to acquire locks + } + + if (CurrentMkqlIndex == kql.MkqlsSize() - 1 && !TxState->Tx().Locks.HasLocks()) { + return false; // Final phase of read only tx, no need to acquire locks + } + + return true; + } + private: TIntrusivePtr<IKqpGateway> Gateway; TString Cluster; diff --git a/ydb/core/kqp/host/kqp_run_scan.cpp b/ydb/core/kqp/host/kqp_run_scan.cpp index 78c70bf04c..7c91ae8200 100644 --- a/ydb/core/kqp/host/kqp_run_scan.cpp +++ b/ydb/core/kqp/host/kqp_run_scan.cpp @@ -35,7 +35,7 @@ protected: request.StatsMode = GetStatsMode(TransformCtx->QueryCtx->StatsMode); request.DisableLlvmForUdfStages = TransformCtx->Config->DisableLlvmForUdfStages(); request.LlvmEnabled = TransformCtx->Config->GetEnableLlvm() != EOptionalFlag::Disabled; - request.Snapshot = TxState->Tx().GetSnapshot(); + request.Snapshot = TxState->Tx().GetSnapshot(); switch (tx->GetType()) { case NKqpProto::TKqpPhyTx::TYPE_COMPUTE: @@ -165,7 +165,7 @@ public: TStatus DoTransform(NYql::TExprNode::TPtr input, NYql::TExprNode::TPtr& output, NYql::TExprContext&) { output = input; - if (TxState->Tx().GetSnapshot().IsValid()) { + if (TxState->Tx().GetSnapshot().IsValid()) { Gateway->DiscardPersistentSnapshot(TxState->Tx().SnapshotHandle); } diff --git a/ydb/core/kqp/host/kqp_runner.cpp b/ydb/core/kqp/host/kqp_runner.cpp index d3712b0505..42b4eca7c6 100644 --- a/ydb/core/kqp/host/kqp_runner.cpp +++ b/ydb/core/kqp/host/kqp_runner.cpp @@ -183,7 +183,7 @@ public: PreparedRunTransformer = TTransformationPipeline(typesCtx) .Add(TLogExprTransformer::Sync("PreparedRun iteration", logComp, logLevel), "KqlPreparedRun") - .Add(CreateKqpAcquireMvccSnapshotTransformer(Gateway, TxState, TransformCtx), "AcquireMvccSnapshot") + .Add(CreateKqpAcquireMvccSnapshotTransformer(Gateway, TxState, TransformCtx), "AcquireMvccSnapshot") .Add(CreateKqpExecutePreparedTransformer(Gateway, Cluster, TxState, TransformCtx), "ExecutePrepared") .Add(CreateKqpFinalizeTransformer(Gateway, Cluster, TxState, TransformCtx), "Finalize") .Build(false); @@ -238,7 +238,7 @@ public: .Build(false); PhysicalRunQueryTransformer = TTransformationPipeline(typesCtx) - .Add(CreateKqpAcquireMvccSnapshotTransformer(Gateway, TxState, TransformCtx, true), "AcquireMvccSnapshot") + .Add(CreateKqpAcquireMvccSnapshotTransformer(Gateway, TxState, TransformCtx, true), "AcquireMvccSnapshot") .Add(CreateKqpExecutePhysicalDataTransformer(Gateway, Cluster, TxState, TransformCtx), "ExecutePhysical") .Build(false); @@ -598,7 +598,7 @@ private: TransformCtx->PhysicalQuery = &phyQuery; TransformCtx->ReplyTarget = target; - Y_ASSERT(!TxState->Tx().GetSnapshot().IsValid()); + Y_ASSERT(!TxState->Tx().GetSnapshot().IsValid()); return MakeIntrusive<TScanAsyncRunResult>(world, ctx, *ScanRunQueryTransformer); } @@ -640,55 +640,55 @@ private: TAutoPtr<IGraphTransformer> ScanRunQueryTransformer; }; -class TKqpAcquireMvccSnapshotTransformer : public TGraphTransformerBase { -public: - TKqpAcquireMvccSnapshotTransformer(TIntrusivePtr<IKqpGateway> gateway, TIntrusivePtr<TKqlTransformContext> transformCtx, - TIntrusivePtr<TKqpTransactionState> txState, bool newEngine) - : Gateway(std::move(gateway)) - , TransformCtx(std::move(transformCtx)) - , NewEngine(newEngine) - , TxState(std::move(txState)) - {} - - TStatus DoTransform(NYql::TExprNode::TPtr input, NYql::TExprNode::TPtr& output, NYql::TExprContext&) override { - output = input; - - if (!NeedSnapshot()) - return TStatus::Ok; - - auto timeout = TransformCtx->QueryCtx->Deadlines.TimeoutAt - Gateway->GetCurrentTime(); - if (!timeout) { - // TODO: Just cancel request. - timeout = TDuration::MilliSeconds(1); - } - SnapshotFuture = Gateway->AcquireMvccSnapshot(timeout); - - Promise = NewPromise(); - - SnapshotFuture.Apply([promise = Promise](const TFuture<IKqpGateway::TKqpSnapshotHandle> future) mutable { - YQL_ENSURE(future.HasValue()); - promise.SetValue(); - }); - - return TStatus::Async; - } - - NThreading::TFuture<void> DoGetAsyncFuture(const NYql::TExprNode&) override { - return Promise.GetFuture(); - } - - TStatus DoApplyAsyncChanges(NYql::TExprNode::TPtr input, NYql::TExprNode::TPtr& output, NYql::TExprContext& ctx) override { - output = input; - - auto handle = SnapshotFuture.ExtractValue(); - - if (handle.Snapshot.IsValid()) { - TxState->Tx().SnapshotHandle = handle; - - return TStatus::Ok; - } - - TIssue issue("Failed to acquire snapshot"); +class TKqpAcquireMvccSnapshotTransformer : public TGraphTransformerBase { +public: + TKqpAcquireMvccSnapshotTransformer(TIntrusivePtr<IKqpGateway> gateway, TIntrusivePtr<TKqlTransformContext> transformCtx, + TIntrusivePtr<TKqpTransactionState> txState, bool newEngine) + : Gateway(std::move(gateway)) + , TransformCtx(std::move(transformCtx)) + , NewEngine(newEngine) + , TxState(std::move(txState)) + {} + + TStatus DoTransform(NYql::TExprNode::TPtr input, NYql::TExprNode::TPtr& output, NYql::TExprContext&) override { + output = input; + + if (!NeedSnapshot()) + return TStatus::Ok; + + auto timeout = TransformCtx->QueryCtx->Deadlines.TimeoutAt - Gateway->GetCurrentTime(); + if (!timeout) { + // TODO: Just cancel request. + timeout = TDuration::MilliSeconds(1); + } + SnapshotFuture = Gateway->AcquireMvccSnapshot(timeout); + + Promise = NewPromise(); + + SnapshotFuture.Apply([promise = Promise](const TFuture<IKqpGateway::TKqpSnapshotHandle> future) mutable { + YQL_ENSURE(future.HasValue()); + promise.SetValue(); + }); + + return TStatus::Async; + } + + NThreading::TFuture<void> DoGetAsyncFuture(const NYql::TExprNode&) override { + return Promise.GetFuture(); + } + + TStatus DoApplyAsyncChanges(NYql::TExprNode::TPtr input, NYql::TExprNode::TPtr& output, NYql::TExprContext& ctx) override { + output = input; + + auto handle = SnapshotFuture.ExtractValue(); + + if (handle.Snapshot.IsValid()) { + TxState->Tx().SnapshotHandle = handle; + + return TStatus::Ok; + } + + TIssue issue("Failed to acquire snapshot"); switch (handle.Status) { case NKikimrIssues::TStatusIds::SCHEME_ERROR: issue.SetCode(NYql::TIssuesIds::KIKIMR_SCHEME_ERROR, NYql::TSeverityIds::S_ERROR); @@ -706,35 +706,35 @@ public: } for (const auto& subIssue: handle.Issues()) { - issue.AddSubIssue(MakeIntrusive<TIssue>(subIssue)); - } - ctx.AddError(issue); - return TStatus::Error; - } - -private: - bool NeedSnapshot() { - if (*TxState->Tx().EffectiveIsolationLevel != NKikimrKqp::ISOLATION_LEVEL_SERIALIZABLE) - return false; - - if (!TransformCtx->Config->FeatureFlags.GetEnableMvccSnapshotReads()) - return false; - - if (TxState->Tx().GetSnapshot().IsValid()) - return false; - - auto settings = TransformCtx->Settings; - if (settings.GetRollbackTx()) - return false; - if (!settings.GetCommitTx()) - return true; - + issue.AddSubIssue(MakeIntrusive<TIssue>(subIssue)); + } + ctx.AddError(issue); + return TStatus::Error; + } + +private: + bool NeedSnapshot() { + if (*TxState->Tx().EffectiveIsolationLevel != NKikimrKqp::ISOLATION_LEVEL_SERIALIZABLE) + return false; + + if (!TransformCtx->Config->FeatureFlags.GetEnableMvccSnapshotReads()) + return false; + + if (TxState->Tx().GetSnapshot().IsValid()) + return false; + + auto settings = TransformCtx->Settings; + if (settings.GetRollbackTx()) + return false; + if (!settings.GetCommitTx()) + return true; + size_t readPhases = 0; bool hasEffects = false; - if (NewEngine) { - YQL_ENSURE(TransformCtx->PhysicalQuery); - auto &query = *TransformCtx->PhysicalQuery; + if (NewEngine) { + YQL_ENSURE(TransformCtx->PhysicalQuery); + auto &query = *TransformCtx->PhysicalQuery; for (const auto &tx : query.GetTransactions()) { switch (tx.GetType()) { @@ -758,8 +758,8 @@ private: readPhases += kql.GetMkqls().size(); hasEffects = !kql.GetEffects().empty(); - } - + } + // We don't want snapshot when there are effects at the moment, // because it hurts performance when there are multiple single-shard // reads and a single distributed commit. Taking snapshot costs @@ -776,26 +776,26 @@ private: // for read-only transactions, and costs less than a final distributed // commit. return readPhases > 1; - } - -private: - TIntrusivePtr<IKqpGateway> Gateway; - TIntrusivePtr<TKqlTransformContext> TransformCtx; - - bool NewEngine; - - NThreading::TFuture<IKqpGateway::TKqpSnapshotHandle> SnapshotFuture; - NThreading::TPromise<void> Promise; - TIntrusivePtr<TKqpTransactionState> TxState; -}; - + } + +private: + TIntrusivePtr<IKqpGateway> Gateway; + TIntrusivePtr<TKqlTransformContext> TransformCtx; + + bool NewEngine; + + NThreading::TFuture<IKqpGateway::TKqpSnapshotHandle> SnapshotFuture; + NThreading::TPromise<void> Promise; + TIntrusivePtr<TKqpTransactionState> TxState; +}; + } // namespace -TAutoPtr<NYql::IGraphTransformer> CreateKqpAcquireMvccSnapshotTransformer(TIntrusivePtr<IKqpGateway> gateway, - TIntrusivePtr<TKqpTransactionState> txState, TIntrusivePtr<TKqlTransformContext> transformCtx, bool newEngine) { - return new TKqpAcquireMvccSnapshotTransformer(gateway, transformCtx, txState, newEngine); -} - +TAutoPtr<NYql::IGraphTransformer> CreateKqpAcquireMvccSnapshotTransformer(TIntrusivePtr<IKqpGateway> gateway, + TIntrusivePtr<TKqpTransactionState> txState, TIntrusivePtr<TKqlTransformContext> transformCtx, bool newEngine) { + return new TKqpAcquireMvccSnapshotTransformer(gateway, transformCtx, txState, newEngine); +} + TIntrusivePtr<IKqpRunner> CreateKqpRunner(TIntrusivePtr<IKqpGateway> gateway, const TString& cluster, TIntrusivePtr<TTypeAnnotationContext> typesCtx, TIntrusivePtr<TKikimrSessionContext> sessionCtx, const NMiniKQL::IFunctionRegistry& funcRegistry) diff --git a/ydb/core/kqp/kqp_ic_gateway.cpp b/ydb/core/kqp/kqp_ic_gateway.cpp index a7834935e4..47489a9bd5 100644 --- a/ydb/core/kqp/kqp_ic_gateway.cpp +++ b/ydb/core/kqp/kqp_ic_gateway.cpp @@ -1597,13 +1597,13 @@ public: TFuture<TMkqlResult> ExecuteMkql(const TString& cluster, const TString& program, TKqpParamsMap&& params, const TMkqlSettings& settings, const TKqpSnapshot& snapshot) override { - return RunInternal(cluster, program, std::move(params), false, false, settings, snapshot); + return RunInternal(cluster, program, std::move(params), false, false, settings, snapshot); } TFuture<TMkqlResult> ExecuteMkqlPrepared(const TString& cluster, const TString& program, TKqpParamsMap&& params, const TMkqlSettings& settings, const TKqpSnapshot& snapshot) override { - return RunInternal(cluster, program, std::move(params), false, true, settings, snapshot); + return RunInternal(cluster, program, std::move(params), false, true, settings, snapshot); } TFuture<TMkqlResult> PrepareMkql(const TString& cluster, const TString& program) override { @@ -1876,34 +1876,34 @@ public: ); } - NThreading::TFuture<TKqpSnapshotHandle> AcquireMvccSnapshot(TDuration queryTimeout) override { - auto* snapMgr = CreateKqpSnapshotManager(Database, queryTimeout); - auto snapMgrActorId = RegisterActor(snapMgr); - - auto ev = MakeHolder<TEvKqpSnapshot::TEvCreateSnapshotRequest>(); - - return SendActorRequest< - TEvKqpSnapshot::TEvCreateSnapshotRequest, - TEvKqpSnapshot::TEvCreateSnapshotResponse, - IKqpGateway::TKqpSnapshotHandle> - ( - snapMgrActorId, - ev.Release(), - [](TPromise<IKqpGateway::TKqpSnapshotHandle> promise, - TEvKqpSnapshot::TEvCreateSnapshotResponse&& response) mutable - { - IKqpGateway::TKqpSnapshotHandle handle; - handle.Snapshot = response.Snapshot; + NThreading::TFuture<TKqpSnapshotHandle> AcquireMvccSnapshot(TDuration queryTimeout) override { + auto* snapMgr = CreateKqpSnapshotManager(Database, queryTimeout); + auto snapMgrActorId = RegisterActor(snapMgr); + + auto ev = MakeHolder<TEvKqpSnapshot::TEvCreateSnapshotRequest>(); + + return SendActorRequest< + TEvKqpSnapshot::TEvCreateSnapshotRequest, + TEvKqpSnapshot::TEvCreateSnapshotResponse, + IKqpGateway::TKqpSnapshotHandle> + ( + snapMgrActorId, + ev.Release(), + [](TPromise<IKqpGateway::TKqpSnapshotHandle> promise, + TEvKqpSnapshot::TEvCreateSnapshotResponse&& response) mutable + { + IKqpGateway::TKqpSnapshotHandle handle; + handle.Snapshot = response.Snapshot; handle.Status = response.Status; handle.AddIssues(response.Issues); - promise.SetValue(handle); - } - ); - } - + promise.SetValue(handle); + } + ); + } + void DiscardPersistentSnapshot(const TKqpSnapshotHandle& handle) override { - if (handle.ManagingActor) - ActorSystem->Send(handle.ManagingActor, new TEvKqpSnapshot::TEvDiscardSnapshot(handle.Snapshot)); + if (handle.ManagingActor) + ActorSystem->Send(handle.ManagingActor, new TEvKqpSnapshot::TEvDiscardSnapshot(handle.Snapshot)); } TInstant GetCurrentTime() const override { @@ -2036,7 +2036,7 @@ private: } TFuture<TMkqlResult> RunInternal(const TString& cluster, const TString& program, TKqpParamsMap&& params, - bool compileOnly, bool prepared, const TMkqlSettings& settings, const TKqpSnapshot& snapshot = TKqpSnapshot::InvalidSnapshot) + bool compileOnly, bool prepared, const TMkqlSettings& settings, const TKqpSnapshot& snapshot = TKqpSnapshot::InvalidSnapshot) { using TRequest = TEvTxUserProxy::TEvProposeTransaction; @@ -2094,11 +2094,11 @@ private: if (limits.TotalReadSizeLimitBytes) { mkqlTx.MutableLimits()->SetTotalReadSizeLimitBytes(limits.TotalReadSizeLimitBytes); } - - if (snapshot.IsValid()) { - mkqlTx.SetSnapshotStep(snapshot.Step); - mkqlTx.SetSnapshotTxId(snapshot.TxId); - } + + if (snapshot.IsValid()) { + mkqlTx.SetSnapshotStep(snapshot.Step); + mkqlTx.SetSnapshotTxId(snapshot.TxId); + } } if (settings.CollectStats) { diff --git a/ydb/core/kqp/prepare/kqp_query_exec.cpp b/ydb/core/kqp/prepare/kqp_query_exec.cpp index 44c7969236..bc2d4e94ce 100644 --- a/ydb/core/kqp/prepare/kqp_query_exec.cpp +++ b/ydb/core/kqp/prepare/kqp_query_exec.cpp @@ -542,10 +542,10 @@ bool AddDeferredEffect(NNodes::TExprBase effect, const TVector<NKikimrKqp::TPara newEffect.AddBindings()->CopyFrom(binding); } } else { - if (txState.Tx().Locks.Broken()) { - txState.Tx().Locks.ReportIssues(ctx); - return false; - } + if (txState.Tx().Locks.Broken()) { + txState.Tx().Locks.ReportIssues(ctx); + return false; + } THashMap<TString, NKikimrKqp::TParameterBinding> bindingsMap; for (auto& binding : bindings) { bindingsMap.emplace(binding.GetName(), binding); @@ -727,11 +727,11 @@ std::pair<bool, std::vector<TIssue>> MergeLocks(const NKikimrMiniKQL::TType& typ YQL_ENSURE(lockType.GetMember(5).GetName() == "SchemeShard"); res.first = true; - for (auto& lockValue : value.GetList()) { - TKqpTxLock txLock(lockValue); - if (auto counter = txLock.GetCounter(); counter >= NKikimr::TSysTables::TLocksTable::TLock::ErrorMin) { + for (auto& lockValue : value.GetList()) { + TKqpTxLock txLock(lockValue); + if (auto counter = txLock.GetCounter(); counter >= NKikimr::TSysTables::TLocksTable::TLock::ErrorMin) { switch (counter) { - case NKikimr::TSysTables::TLocksTable::TLock::ErrorAlreadyBroken: + case NKikimr::TSysTables::TLocksTable::TLock::ErrorAlreadyBroken: case NKikimr::TSysTables::TLocksTable::TLock::ErrorBroken: res.second.emplace_back(GetLocksInvalidatedIssue(txCtx, txLock)); break; @@ -741,18 +741,18 @@ std::pair<bool, std::vector<TIssue>> MergeLocks(const NKikimrMiniKQL::TType& typ } res.first = false; - } else if (auto curTxLock = locks.LocksMap.FindPtr(txLock.GetKey())) { + } else if (auto curTxLock = locks.LocksMap.FindPtr(txLock.GetKey())) { if (curTxLock->Invalidated(txLock)) { res.second.emplace_back(GetLocksInvalidatedIssue(txCtx, txLock)); res.first = false; } } else { - // despite there were some errors we need to proceed merge to erase remaining locks properly + // despite there were some errors we need to proceed merge to erase remaining locks properly locks.LocksMap.insert(std::make_pair(txLock.GetKey(), txLock)); } } - return res; + return res; } bool MergeLocks(const NKikimrMiniKQL::TType& type, const NKikimrMiniKQL::TValue& value, TKqpTransactionContext& txCtx, @@ -778,17 +778,17 @@ bool MergeLocks(const NKikimrMiniKQL::TType& type, const NKikimrMiniKQL::TValue& bool UnpackMergeLocks(const NKikimrMiniKQL::TResult& result, TKqpTransactionContext& txCtx, TExprContext& ctx) { auto structType = result.GetType().GetStruct(); ui32 locksIndex; - bool found = GetRunResultIndex(structType, TString(NKikimr::NMiniKQL::TxLocksResultLabel2), locksIndex); + bool found = GetRunResultIndex(structType, TString(NKikimr::NMiniKQL::TxLocksResultLabel2), locksIndex); YQL_ENSURE(found ^ txCtx.Locks.Broken()); - if (found) { - auto locksType = structType.GetMember(locksIndex).GetType().GetOptional().GetItem(); - auto locksValue = result.GetValue().GetStruct(locksIndex).GetOptional(); + if (found) { + auto locksType = structType.GetMember(locksIndex).GetType().GetOptional().GetItem(); + auto locksValue = result.GetValue().GetStruct(locksIndex).GetOptional(); return MergeLocks(locksType, locksValue, txCtx, ctx); - } - - return false; + } + + return false; } void LogMkqlResult(const NKikimrMiniKQL::TResult& result, TExprContext& ctx) { diff --git a/ydb/core/kqp/prepare/kqp_query_finalize.cpp b/ydb/core/kqp/prepare/kqp_query_finalize.cpp index d662737cea..5e442780f7 100644 --- a/ydb/core/kqp/prepare/kqp_query_finalize.cpp +++ b/ydb/core/kqp/prepare/kqp_query_finalize.cpp @@ -181,7 +181,7 @@ public: return TStatus::Ok; } - return ExecuteProgram(program, ctx, hasDataEffects, ShouldWaitForResults(hasDataEffects)); + return ExecuteProgram(program, ctx, hasDataEffects, ShouldWaitForResults(hasDataEffects)); } TFuture<void> DoGetAsyncFuture(const TExprNode& input) final { @@ -262,28 +262,28 @@ private: RollbackOnErrorInProgress }; - TStatus ExecuteProgram(TKiProgram program, TExprContext& ctx, bool hasDataEffects, bool waitForResults) { - if (waitForResults) { - Promise = NewPromise(); + TStatus ExecuteProgram(TKiProgram program, TExprContext& ctx, bool hasDataEffects, bool waitForResults) { + if (waitForResults) { + Promise = NewPromise(); MkqlExecuteResult = ExecuteMkql(program, Gateway, Cluster, ctx, TxState, TransformCtx, hasDataEffects); - auto promise = Promise; - MkqlExecuteResult.Future.Apply([promise](const TFuture<IKqpGateway::TMkqlResult> future) mutable { - YQL_ENSURE(future.HasValue()); - promise.SetValue(); - }); - - return TStatus::Async; - } - - YQL_ENSURE(!hasDataEffects); - + auto promise = Promise; + MkqlExecuteResult.Future.Apply([promise](const TFuture<IKqpGateway::TMkqlResult> future) mutable { + YQL_ENSURE(future.HasValue()); + promise.SetValue(); + }); + + return TStatus::Async; + } + + YQL_ENSURE(!hasDataEffects); + ExecuteMkql(program, Gateway, Cluster, ctx, TxState, TransformCtx, false); - - ResetTxState(true); - State = EFinalizeState::Initial; - - return TStatus::Ok; + + ResetTxState(true); + State = EFinalizeState::Initial; + + return TStatus::Ok; } TStatus RollbackOnError(TExprContext& ctx) { @@ -306,7 +306,7 @@ private: } State = EFinalizeState::RollbackOnErrorInProgress; - return ExecuteProgram(program, ctx, false, true); + return ExecuteProgram(program, ctx, false, true); } TExprList GetResultsNode(TExprBase program, TExprContext& ctx) { @@ -429,8 +429,8 @@ private: TExprBase GetCommitEffects(TPositionHandle pos, TExprContext& ctx, bool& hasDataEffects) { hasDataEffects = !TxState->Tx().DeferredEffects.Empty(); - Y_VERIFY_DEBUG(!hasDataEffects || !TxState->Tx().Locks.Broken()); - + Y_VERIFY_DEBUG(!hasDataEffects || !TxState->Tx().Locks.Broken()); + auto deferredEffects = GetDeferredEffectsList(TxState->Tx().DeferredEffects, pos, ctx); if (!TxState->Tx().Locks.HasLocks()) { @@ -446,9 +446,9 @@ private: .Type(ExpandType(pos, *GetTxLockListType(ctx), ctx)) .Done(); - if (!hasDataEffects && TxState->Tx().GetSnapshot().IsValid()) - return GetEraseLocksEffects(Cluster, pos, locksParamNode, ctx); - + if (!hasDataEffects && TxState->Tx().GetSnapshot().IsValid()) + return GetEraseLocksEffects(Cluster, pos, locksParamNode, ctx); + auto lockArg = Build<TCoArgument>(ctx, pos) .Name("lockArg") .Done(); @@ -570,26 +570,26 @@ private: return effects; } - bool ShouldWaitForResults(bool hasDataEffects) { - if (State != EFinalizeState::CommitInProgress) { - return true; - } - - if (hasDataEffects) { - return true; - } - - if (!TxState->Tx().GetSnapshot().IsValid()) { - return true; - } - - if (HasProgramResults) { - return true; - } - - return false; - } - + bool ShouldWaitForResults(bool hasDataEffects) { + if (State != EFinalizeState::CommitInProgress) { + return true; + } + + if (hasDataEffects) { + return true; + } + + if (!TxState->Tx().GetSnapshot().IsValid()) { + return true; + } + + if (HasProgramResults) { + return true; + } + + return false; + } + private: TIntrusivePtr<IKqpGateway> Gateway; TString Cluster; diff --git a/ydb/core/kqp/provider/yql_kikimr_gateway_ut.cpp b/ydb/core/kqp/provider/yql_kikimr_gateway_ut.cpp index 92e2818f5c..791a617c08 100644 --- a/ydb/core/kqp/provider/yql_kikimr_gateway_ut.cpp +++ b/ydb/core/kqp/provider/yql_kikimr_gateway_ut.cpp @@ -143,7 +143,7 @@ void TestRunSimpleCommon(TIntrusivePtr<IKqpGateway> gateway) { )"); auto responseFuture = gateway->ExecuteMkql(TestCluster, program, TKqpParamsMap(), - IKqpGateway::TMkqlSettings(), IKqpGateway::TKqpSnapshot::InvalidSnapshot); + IKqpGateway::TMkqlSettings(), IKqpGateway::TKqpSnapshot::InvalidSnapshot); responseFuture.Wait(); auto response = responseFuture.GetValue(); response.Issues().PrintTo(Cerr); diff --git a/ydb/core/kqp/rm/kqp_snapshot_manager.cpp b/ydb/core/kqp/rm/kqp_snapshot_manager.cpp index 6a9eb2cd9e..e461d85ab9 100644 --- a/ydb/core/kqp/rm/kqp_snapshot_manager.cpp +++ b/ydb/core/kqp/rm/kqp_snapshot_manager.cpp @@ -45,38 +45,38 @@ private: void Handle(TEvKqpSnapshot::TEvCreateSnapshotRequest::TPtr& ev) { ClientActorId = ev->Sender; Tables = ev->Get()->Tables; - MvccSnapshot = ev->Get()->MvccSnapshot; + MvccSnapshot = ev->Get()->MvccSnapshot; LOG_D("KqpSnapshotManager: got snapshot request from " << ClientActorId); - if (MvccSnapshot) { - auto longTxService = NLongTxService::MakeLongTxServiceID(SelfId().NodeId()); - Send(longTxService, new NLongTxService::TEvLongTxService::TEvAcquireReadSnapshot(Database)); - - Become(&TThis::StateAwaitAcquireResult); - } else { - auto req = MakeHolder<TEvTxUserProxy::TEvProposeTransaction>(); - req->Record.SetExecTimeoutPeriod(RequestTimeout.MilliSeconds()); - req->Record.SetDatabaseName(Database); - auto* createSnapshot = req->Record.MutableTransaction()->MutableCreateVolatileSnapshot(); - for (const TString& tablePath : Tables) { - createSnapshot->AddTables()->SetTablePath(tablePath); - } - createSnapshot->SetTimeoutMs(SnapshotTimeout.MilliSeconds()); - createSnapshot->SetIgnoreSystemViews(true); - - Send(MakeTxProxyID(), req.Release()); - Become(&TThis::StateAwaitCreation); + if (MvccSnapshot) { + auto longTxService = NLongTxService::MakeLongTxServiceID(SelfId().NodeId()); + Send(longTxService, new NLongTxService::TEvLongTxService::TEvAcquireReadSnapshot(Database)); + + Become(&TThis::StateAwaitAcquireResult); + } else { + auto req = MakeHolder<TEvTxUserProxy::TEvProposeTransaction>(); + req->Record.SetExecTimeoutPeriod(RequestTimeout.MilliSeconds()); + req->Record.SetDatabaseName(Database); + auto* createSnapshot = req->Record.MutableTransaction()->MutableCreateVolatileSnapshot(); + for (const TString& tablePath : Tables) { + createSnapshot->AddTables()->SetTablePath(tablePath); + } + createSnapshot->SetTimeoutMs(SnapshotTimeout.MilliSeconds()); + createSnapshot->SetIgnoreSystemViews(true); + + Send(MakeTxProxyID(), req.Release()); + Become(&TThis::StateAwaitCreation); + } + } + + STATEFN(StateAwaitAcquireResult) { + switch (ev->GetTypeRewrite()) { + hFunc(NLongTxService::TEvLongTxService::TEvAcquireReadSnapshotResult, Handle); + hFunc(TEvents::TEvPoison, HandlePoison); + default: + HandleUnexpectedEvent("AwaitAcquireResult", ev->GetTypeRewrite()); } - } - - STATEFN(StateAwaitAcquireResult) { - switch (ev->GetTypeRewrite()) { - hFunc(NLongTxService::TEvLongTxService::TEvAcquireReadSnapshotResult, Handle); - hFunc(TEvents::TEvPoison, HandlePoison); - default: - HandleUnexpectedEvent("AwaitAcquireResult", ev->GetTypeRewrite()); - } } STATEFN(StateAwaitCreation) { @@ -88,33 +88,33 @@ private: } } - void Handle(NLongTxService::TEvLongTxService::TEvAcquireReadSnapshotResult::TPtr& ev) { - Y_VERIFY(MvccSnapshot); - Y_VERIFY(Tables.empty()); - - const auto& record = ev->Get()->Record; - if (record.GetStatus() == Ydb::StatusIds::SUCCESS) { - Snapshot = IKqpGateway::TKqpSnapshot(record.GetSnapshotStep(), record.GetSnapshotTxId()); - - LOG_D("KqpSnapshotManager: snapshot " << Snapshot.Step << ":" << Snapshot.TxId << " acquired"); - - bool sent = Send(ClientActorId, new TEvKqpSnapshot::TEvCreateSnapshotResponse( - Snapshot, NKikimrIssues::TStatusIds::SUCCESS, /* issues */ {})); - Y_VERIFY_DEBUG(sent); - - PassAway(); - } else { - NYql::TIssues issues; - NYql::IssuesFromMessage(record.GetIssues(), issues); - LOG_E("KqpSnapshotManager: CreateSnapshot got unexpected status=" - << record.GetStatus() << ", issues:" << issues.ToString()); - ReplyErrorAndDie(NKikimrIssues::TStatusIds::ERROR, std::move(issues)); - } - } - + void Handle(NLongTxService::TEvLongTxService::TEvAcquireReadSnapshotResult::TPtr& ev) { + Y_VERIFY(MvccSnapshot); + Y_VERIFY(Tables.empty()); + + const auto& record = ev->Get()->Record; + if (record.GetStatus() == Ydb::StatusIds::SUCCESS) { + Snapshot = IKqpGateway::TKqpSnapshot(record.GetSnapshotStep(), record.GetSnapshotTxId()); + + LOG_D("KqpSnapshotManager: snapshot " << Snapshot.Step << ":" << Snapshot.TxId << " acquired"); + + bool sent = Send(ClientActorId, new TEvKqpSnapshot::TEvCreateSnapshotResponse( + Snapshot, NKikimrIssues::TStatusIds::SUCCESS, /* issues */ {})); + Y_VERIFY_DEBUG(sent); + + PassAway(); + } else { + NYql::TIssues issues; + NYql::IssuesFromMessage(record.GetIssues(), issues); + LOG_E("KqpSnapshotManager: CreateSnapshot got unexpected status=" + << record.GetStatus() << ", issues:" << issues.ToString()); + ReplyErrorAndDie(NKikimrIssues::TStatusIds::ERROR, std::move(issues)); + } + } + void Handle(TEvTxUserProxy::TEvProposeTransactionStatus::TPtr& ev) { - Y_VERIFY(!MvccSnapshot); - + Y_VERIFY(!MvccSnapshot); + using EStatus = TEvTxUserProxy::TEvProposeTransactionStatus::EStatus; const auto* msg = ev->Get(); @@ -222,7 +222,7 @@ private: } void ReplyErrorAndDie(NKikimrIssues::TStatusIds::EStatusCode status, NYql::TIssues&& issues) { - if (CurrentStateFunc() == &TThis::StateAwaitCreation || CurrentStateFunc() == &TThis::StateAwaitAcquireResult) { + if (CurrentStateFunc() == &TThis::StateAwaitCreation || CurrentStateFunc() == &TThis::StateAwaitAcquireResult) { Send(ClientActorId, new TEvKqpSnapshot::TEvCreateSnapshotResponse( IKqpGateway::TKqpSnapshot::InvalidSnapshot, status, std::move(issues))); } else { @@ -237,8 +237,8 @@ private: TActorId ClientActorId; IKqpGateway::TKqpSnapshot Snapshot; - bool MvccSnapshot = false; - + bool MvccSnapshot = false; + TSchedulerCookieHolder RequestTimeoutCookieHolder_; const double SnapshotToRequestTimeoutRatio = 1.5; diff --git a/ydb/core/kqp/rm/kqp_snapshot_manager.h b/ydb/core/kqp/rm/kqp_snapshot_manager.h index c4f21b8500..ee56469308 100644 --- a/ydb/core/kqp/rm/kqp_snapshot_manager.h +++ b/ydb/core/kqp/rm/kqp_snapshot_manager.h @@ -14,15 +14,15 @@ struct TEvKqpSnapshot { TKqpSnapshotEvents::EvCreateSnapshotRequest> { explicit TEvCreateSnapshotRequest(const TVector<TString>& tables) - : Tables(tables) - , MvccSnapshot(false){} + : Tables(tables) + , MvccSnapshot(false){} + + explicit TEvCreateSnapshotRequest() + : Tables({}) + , MvccSnapshot(true){} - explicit TEvCreateSnapshotRequest() - : Tables({}) - , MvccSnapshot(true){} - const TVector<TString> Tables; - const bool MvccSnapshot; + const bool MvccSnapshot; }; struct TEvCreateSnapshotResponse : public TEventLocal<TEvCreateSnapshotResponse, diff --git a/ydb/core/kqp/ut/common/kqp_ut_common.cpp b/ydb/core/kqp/ut/common/kqp_ut_common.cpp index 5410309844..9bc7889f92 100644 --- a/ydb/core/kqp/ut/common/kqp_ut_common.cpp +++ b/ydb/core/kqp/ut/common/kqp_ut_common.cpp @@ -105,7 +105,7 @@ TKikimrRunner::TKikimrRunner(const TKikimrSettings& settings) { ServerSettings->SetNodeCount(settings.NodeCount); ServerSettings->SetEnableKqpSpilling(enableSpilling); ServerSettings->SetEnableDataColumnForIndexTable(true); - ServerSettings->SetKeepSnapshotTimeout(settings.KeepSnapshotTimeout); + ServerSettings->SetKeepSnapshotTimeout(settings.KeepSnapshotTimeout); ServerSettings->SetFrFactory(&UdfFrFactory); ServerSettings->SetEnableSchemeTransactionsAtSchemeShard(true); ServerSettings->SetEnableNotNullColumns(true); @@ -170,17 +170,17 @@ TKikimrRunner::TKikimrRunner(const TString& authToken, const TString& domainRoot .SetDomainRoot(domainRoot) .SetNodeCount(nodeCount)) {} -void TKikimrRunner::CreateSampleTables() { - Client->CreateTable("/Root", R"( +void TKikimrRunner::CreateSampleTables() { + Client->CreateTable("/Root", R"( Name: "TwoShard" Columns { Name: "Key", Type: "Uint32" } Columns { Name: "Value1", Type: "String" } Columns { Name: "Value2", Type: "Int32" } KeyColumnNames: ["Key"] UniformPartitionsCount: 2 - )"); + )"); - Client->CreateTable("/Root", R"( + Client->CreateTable("/Root", R"( Name: "EightShard" Columns { Name: "Key", Type: "Uint64" } Columns { Name: "Text", Type: "String" } @@ -193,9 +193,9 @@ void TKikimrRunner::CreateSampleTables() { SplitBoundary { KeyPrefix { Tuple { Optional { Uint64: 500 } } } } SplitBoundary { KeyPrefix { Tuple { Optional { Uint64: 600 } } } } SplitBoundary { KeyPrefix { Tuple { Optional { Uint64: 700 } } } } - )"); + )"); - Client->CreateTable("/Root", R"( + Client->CreateTable("/Root", R"( Name: "Logs" Columns { Name: "App", Type: "Utf8" } Columns { Name: "Message", Type: "Utf8" } @@ -204,9 +204,9 @@ void TKikimrRunner::CreateSampleTables() { KeyColumnNames: ["App", "Ts", "Host"], SplitBoundary { KeyPrefix { Tuple { Optional { Text: "a" } } } } SplitBoundary { KeyPrefix { Tuple { Optional { Text: "b" } } } } - )"); + )"); - Client->CreateTable("/Root", R"( + Client->CreateTable("/Root", R"( Name: "BatchUpload" Columns { Name: "Key1" @@ -234,7 +234,7 @@ void TKikimrRunner::CreateSampleTables() { } KeyColumnNames: ["Key1", "Key2"] UniformPartitionsCount: 10 - )"); + )"); // TODO: Reuse driver (YDB-626) NYdb::TDriver driver(NYdb::TDriverConfig().SetEndpoint(Endpoint).SetDatabase("/Root")); @@ -372,7 +372,7 @@ void TKikimrRunner::CreateSampleTables() { (106, "One", "Name3", "Value29"), (108, "One", NULL, "Value31"); )", TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()).GetValueSync()); - + } void TKikimrRunner::Initialize(const TKikimrSettings& settings) { @@ -405,7 +405,7 @@ void TKikimrRunner::Initialize(const TKikimrSettings& settings) { NKikimr::NKqp::WaitForKqpProxyInit(GetDriver()); if (settings.WithSampleTables) { - CreateSampleTables(); + CreateSampleTables(); } } diff --git a/ydb/core/kqp/ut/common/kqp_ut_common.h b/ydb/core/kqp/ut/common/kqp_ut_common.h index 6b0ff3525f..c1d64b65c3 100644 --- a/ydb/core/kqp/ut/common/kqp_ut_common.h +++ b/ydb/core/kqp/ut/common/kqp_ut_common.h @@ -79,7 +79,7 @@ struct TKikimrSettings: public TTestFeatureFlagsHolder<TKikimrSettings> { TString DomainRoot = KikimrDefaultUtDomainRoot; ui32 NodeCount = 1; bool WithSampleTables = true; - TDuration KeepSnapshotTimeout = TDuration::Zero(); + TDuration KeepSnapshotTimeout = TDuration::Zero(); IOutputStream* LogStream = nullptr; TKikimrSettings& SetAppConfig(const NKikimrConfig::TAppConfig& value) { AppConfig = value; return *this; } @@ -89,9 +89,9 @@ struct TKikimrSettings: public TTestFeatureFlagsHolder<TKikimrSettings> { TKikimrSettings& SetDomainRoot(const TString& value) { DomainRoot = value; return *this; } TKikimrSettings& SetNodeCount(ui32 value) { NodeCount = value; return *this; } TKikimrSettings& SetWithSampleTables(bool value) { WithSampleTables = value; return *this; } - TKikimrSettings& SetKeepSnapshotTimeout(TDuration value) { KeepSnapshotTimeout = value; return *this; } + TKikimrSettings& SetKeepSnapshotTimeout(TDuration value) { KeepSnapshotTimeout = value; return *this; } TKikimrSettings& SetLogStream(IOutputStream* follower) { LogStream = follower; return *this; }; - + }; class TKikimrRunner { @@ -139,7 +139,7 @@ public: private: void Initialize(const TKikimrSettings& settings); void WaitForKqpProxyInit(); - void CreateSampleTables(); + void CreateSampleTables(); private: THolder<Tests::TServerSettings> ServerSettings; diff --git a/ydb/core/kqp/ut/kqp_indexes_ut.cpp b/ydb/core/kqp/ut/kqp_indexes_ut.cpp index c7c9cad48e..505cf09e6b 100644 --- a/ydb/core/kqp/ut/kqp_indexes_ut.cpp +++ b/ydb/core/kqp/ut/kqp_indexes_ut.cpp @@ -108,12 +108,12 @@ Y_UNIT_TEST_SUITE(KqpIndexMetadata) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); - + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); + auto& server = kikimr.GetTestServer(); auto gateway = GetIcGateway(server); const TString& indexName = "value_index"; @@ -175,11 +175,11 @@ Y_UNIT_TEST_SUITE(KqpIndexMetadata) { using namespace NYql::NNodes; auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto& server = kikimr.GetTestServer(); auto gateway = GetIcGateway(server); @@ -438,11 +438,11 @@ Y_UNIT_TEST_SUITE(KqpIndexes) { Y_UNIT_TEST_QUAD(DataColumnWriteNull, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); CreateSampleTablesWithIndex(session); @@ -909,11 +909,11 @@ Y_UNIT_TEST_SUITE(KqpIndexes) { Y_UNIT_TEST_QUAD(DataColumnSelect, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); CreateSampleTablesWithIndex(session); @@ -1031,7 +1031,7 @@ Y_UNIT_TEST_SUITE(KqpIndexes) { if (WithMvcc && !UseNewEngine) { phaseCount--; } - UNIT_ASSERT_VALUES_EQUAL(stats.query_phases().size(), phaseCount); + UNIT_ASSERT_VALUES_EQUAL(stats.query_phases().size(), phaseCount); UNIT_ASSERT_VALUES_EQUAL(stats.query_phases(0).table_access().size(), 1); UNIT_ASSERT_VALUES_EQUAL(stats.query_phases(0).table_access(0).name(), "/Root/SecondaryKeys"); @@ -1070,7 +1070,7 @@ Y_UNIT_TEST_SUITE(KqpIndexes) { if (UseNewEngine) { phaseCount++; } - UNIT_ASSERT_VALUES_EQUAL(stats.query_phases().size(), phaseCount); + UNIT_ASSERT_VALUES_EQUAL(stats.query_phases().size(), phaseCount); int idx = 0; if (UseNewEngine) { @@ -1093,11 +1093,11 @@ Y_UNIT_TEST_SUITE(KqpIndexes) { Y_UNIT_TEST_QUAD(SelectConcurentTX, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -1168,98 +1168,98 @@ Y_UNIT_TEST_SUITE(KqpIndexes) { query2, TTxControl::Tx(result1.GetTransaction().GetRef()).CommitTx()) .ExtractValueSync(); - // read only tx should succeed in MVCC case + // read only tx should succeed in MVCC case UNIT_ASSERT_VALUES_EQUAL_C(result2.GetStatus(), WithMvcc ? NYdb::EStatus::SUCCESS : NYdb::EStatus::ABORTED, result2.GetIssues().ToString()); - } - + } + Y_UNIT_TEST_QUAD(SelectConcurentTX2, WithMvcc, UseNewEngine) { - auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto setting = NKikimrKqp::TKqpSetting(); + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); - auto db = kikimr.GetTableClient(); - auto session = db.CreateSession().GetValueSync().GetSession(); - - { - auto tableBuilder = db.GetTableBuilder(); - tableBuilder - .AddNullableColumn("Key", EPrimitiveType::String) - .AddNullableColumn("Index2", EPrimitiveType::String) - .AddNullableColumn("Value", EPrimitiveType::String); - tableBuilder.SetPrimaryKeyColumns(TVector<TString>{"Key"}); - tableBuilder.AddSecondaryIndex("Index", TVector<TString>{"Index2"}); - auto result = session.CreateTable("/Root/TestTable", tableBuilder.Build()).ExtractValueSync(); - UNIT_ASSERT_VALUES_EQUAL(result.IsTransportError(), false); - UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::SUCCESS); - } - - { + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); + auto db = kikimr.GetTableClient(); + auto session = db.CreateSession().GetValueSync().GetSession(); + + { + auto tableBuilder = db.GetTableBuilder(); + tableBuilder + .AddNullableColumn("Key", EPrimitiveType::String) + .AddNullableColumn("Index2", EPrimitiveType::String) + .AddNullableColumn("Value", EPrimitiveType::String); + tableBuilder.SetPrimaryKeyColumns(TVector<TString>{"Key"}); + tableBuilder.AddSecondaryIndex("Index", TVector<TString>{"Index2"}); + auto result = session.CreateTable("/Root/TestTable", tableBuilder.Build()).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL(result.IsTransportError(), false); + UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::SUCCESS); + } + + { const TString query1(Q_(R"( UPSERT INTO `/Root/TestTable` (Key, Index2, Value) VALUES - ("Primary1", "Secondary1", "Value1"), - ("Primary2", "Secondary2", "Value2"), - ("Primary3", "Secondary3", "Value3"); + ("Primary1", "Secondary1", "Value1"), + ("Primary2", "Secondary2", "Value2"), + ("Primary3", "Secondary3", "Value3"); )")); - - auto result = session.ExecuteDataQuery( - query1, - TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()) - .ExtractValueSync(); - UNIT_ASSERT(result.IsSuccess()); - } - + + auto result = session.ExecuteDataQuery( + query1, + TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()) + .ExtractValueSync(); + UNIT_ASSERT(result.IsSuccess()); + } + const TString query1 = Q1_(R"( SELECT Index2 FROM `/Root/TestTable` VIEW Index WHERE Index2 = "Secondary1"; - )"); - - // Start tx1, select from table by index - auto result1 = session.ExecuteDataQuery( - query1, - TTxControl::BeginTx(TTxSettings::SerializableRW())) - .ExtractValueSync(); - UNIT_ASSERT_VALUES_EQUAL(result1.GetStatus(), NYdb::EStatus::SUCCESS); - { - auto yson = NYdb::FormatResultSetYson(result1.GetResultSet(0)); - UNIT_ASSERT_VALUES_EQUAL(yson, R"([[["Secondary1"]]])"); - } - - { - // In other tx, update string + )"); + + // Start tx1, select from table by index + auto result1 = session.ExecuteDataQuery( + query1, + TTxControl::BeginTx(TTxSettings::SerializableRW())) + .ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL(result1.GetStatus(), NYdb::EStatus::SUCCESS); + { + auto yson = NYdb::FormatResultSetYson(result1.GetResultSet(0)); + UNIT_ASSERT_VALUES_EQUAL(yson, R"([[["Secondary1"]]])"); + } + + { + // In other tx, update string const TString query(Q_(R"( UPSERT INTO `/Root/TestTable` (Key, Index2, Value) VALUES - ("Primary1", "Secondary1New", "Value1New") + ("Primary1", "Secondary1New", "Value1New") )")); - - auto result = session.ExecuteDataQuery( - query, - TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()) - .ExtractValueSync(); - UNIT_ASSERT(result.IsSuccess()); - } - + + auto result = session.ExecuteDataQuery( + query, + TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()) + .ExtractValueSync(); + UNIT_ASSERT(result.IsSuccess()); + } + const TString query2(Q_(R"( UPSERT INTO `/Root/TestTable` (Key, Index2, Value) VALUES - ("Primary4", "Secondary4", "Value4") + ("Primary4", "Secondary4", "Value4") )")); - - UNIT_ASSERT(result1.GetTransaction()); - // Continue tx1, write to table should fail in both MVCC and non-MVCC scenarios - auto result2 = session.ExecuteDataQuery( - query2, - TTxControl::Tx(result1.GetTransaction().GetRef()).CommitTx()) - .ExtractValueSync(); + + UNIT_ASSERT(result1.GetTransaction()); + // Continue tx1, write to table should fail in both MVCC and non-MVCC scenarios + auto result2 = session.ExecuteDataQuery( + query2, + TTxControl::Tx(result1.GetTransaction().GetRef()).CommitTx()) + .ExtractValueSync(); UNIT_ASSERT_VALUES_EQUAL_C(result2.GetStatus(), NYdb::EStatus::ABORTED, result2.GetIssues().ToString().c_str()); } Y_UNIT_TEST_QUAD(UpsertWithoutExtraNullDelete, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -1484,13 +1484,13 @@ Y_UNIT_TEST_SUITE(KqpIndexes) { } - Y_UNIT_TEST_TWIN(KeyIndex, WithMvcc) { + Y_UNIT_TEST_TWIN(KeyIndex, WithMvcc) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -1667,13 +1667,13 @@ Y_UNIT_TEST_SUITE(KqpIndexes) { } } - Y_UNIT_TEST_TWIN(KeyIndex2, WithMvcc) { + Y_UNIT_TEST_TWIN(KeyIndex2, WithMvcc) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -1804,13 +1804,13 @@ Y_UNIT_TEST_SUITE(KqpIndexes) { } } - Y_UNIT_TEST_TWIN(ReplaceWithoutExtraNullDelete, WithMvcc) { + Y_UNIT_TEST_TWIN(ReplaceWithoutExtraNullDelete, WithMvcc) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -1897,11 +1897,11 @@ Y_UNIT_TEST_SUITE(KqpIndexes) { Y_UNIT_TEST_QUAD(SecondaryIndexUpsert1DeleteUpdate, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -2085,11 +2085,11 @@ Y_UNIT_TEST_SUITE(KqpIndexes) { Y_UNIT_TEST_QUAD(SecondaryIndexUpsert2Update, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -2176,11 +2176,11 @@ Y_UNIT_TEST_SUITE(KqpIndexes) { Y_UNIT_TEST_QUAD(SecondaryIndexUpdateOnUsingIndex, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -2243,11 +2243,11 @@ Y_UNIT_TEST_SUITE(KqpIndexes) { Y_UNIT_TEST_QUAD(SecondaryIndexSelect, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); CreateSampleTablesWithIndex(session); @@ -2445,11 +2445,11 @@ Y_UNIT_TEST_SUITE(KqpIndexes) { Y_UNIT_TEST_QUAD(SecondaryIndexOrderBy, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -3008,11 +3008,11 @@ Y_UNIT_TEST_SUITE(KqpIndexes) { Y_UNIT_TEST_QUAD(SecondaryIndexReplace, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -3087,11 +3087,11 @@ R"([[#;#;["Primary1"];[41u]];[["Secondary2"];[2u];["Primary2"];[42u]];[["Seconda Y_UNIT_TEST_QUAD(SecondaryIndexInsert1, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -3133,11 +3133,11 @@ R"([[#;#;["Primary1"];[41u]];[["Secondary2"];[2u];["Primary2"];[42u]];[["Seconda Y_UNIT_TEST_QUAD(MultipleSecondaryIndex, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -3198,11 +3198,11 @@ R"([[#;#;["Primary1"];[41u]];[["Secondary2"];[2u];["Primary2"];[42u]];[["Seconda Y_UNIT_TEST_QUAD(MultipleSecondaryIndexWithSameComulns, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -3536,11 +3536,11 @@ R"([[#;#;["Primary1"];[41u]];[["Secondary2"];[2u];["Primary2"];[42u]];[["Seconda Y_UNIT_TEST_QUAD(SecondaryIndexWithPrimaryKeySameComulns, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -3808,13 +3808,13 @@ R"([[#;#;["Primary1"];[41u]];[["Secondary2"];[2u];["Primary2"];[42u]];[["Seconda } } - Y_UNIT_TEST_TWIN(DeleteOnWithSubquery, WithMvcc) { + Y_UNIT_TEST_TWIN(DeleteOnWithSubquery, WithMvcc) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); CreateSampleTablesWithIndex(session); @@ -3866,11 +3866,11 @@ R"([[#;#;["Primary1"];[41u]];[["Secondary2"];[2u];["Primary2"];[42u]];[["Seconda Y_UNIT_TEST_QUAD(SecondaryIndexUsingInJoin, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -4056,11 +4056,11 @@ R"([[#;#;["Primary1"];[41u]];[["Secondary2"];[2u];["Primary2"];[42u]];[["Seconda Y_UNIT_TEST_QUAD(SecondaryIndexUsingInJoin2, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -4193,11 +4193,11 @@ R"([[#;#;["Primary1"];[41u]];[["Secondary2"];[2u];["Primary2"];[42u]];[["Seconda Y_UNIT_TEST_QUAD(ForbidViewModification, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -4279,13 +4279,13 @@ R"([[#;#;["Primary1"];[41u]];[["Secondary2"];[2u];["Primary2"];[42u]];[["Seconda } - Y_UNIT_TEST_TWIN(ForbidDirectIndexTableCreation, WithMvcc) { + Y_UNIT_TEST_TWIN(ForbidDirectIndexTableCreation, WithMvcc) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto scheme = kikimr.GetSchemeClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -4332,11 +4332,11 @@ R"([[#;#;["Primary1"];[41u]];[["Secondary2"];[2u];["Primary2"];[42u]];[["Seconda Y_UNIT_TEST_QUAD(DuplicateUpsert, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -4369,11 +4369,11 @@ R"([[#;#;["Primary1"];[41u]];[["Secondary2"];[2u];["Primary2"];[42u]];[["Seconda Y_UNIT_TEST_QUAD(DuplicateUpsertInterleave, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -4407,11 +4407,11 @@ R"([[#;#;["Primary1"];[41u]];[["Secondary2"];[2u];["Primary2"];[42u]];[["Seconda Y_UNIT_TEST_QUAD(DuplicateUpsertInterleaveParams, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -4495,11 +4495,11 @@ R"([[#;#;["Primary1"];[41u]];[["Secondary2"];[2u];["Primary2"];[42u]];[["Seconda Y_UNIT_TEST_QUAD(MultipleModifications, WithMvcc, UseNewEngine) { auto setting = NKikimrKqp::TKqpSetting(); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -4547,11 +4547,11 @@ R"([[#;#;["Primary1"];[41u]];[["Secondary2"];[2u];["Primary2"];[42u]];[["Seconda kqpSetting.SetName("_KqpYqlSyntaxVersion"); kqpSetting.SetValue("1"); - auto settings = TKikimrSettings() + auto settings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) .SetEnableAsyncIndexes(enableAsyncIndexes) - .SetKqpSettings({kqpSetting}); + .SetKqpSettings({kqpSetting}); TKikimrRunner kikimr(settings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); @@ -4712,11 +4712,11 @@ R"([[#;#;["Primary1"];[41u]];[["Secondary2"];[2u];["Primary2"];[42u]];[["Seconda auto setting = NKikimrKqp::TKqpSetting(); setting.SetName("_KqpYqlSyntaxVersion"); setting.SetValue("1"); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); CreateSampleTablesWithIndex(session); @@ -4798,11 +4798,11 @@ R"([[#;#;["Primary1"];[41u]];[["Secondary2"];[2u];["Primary2"];[42u]];[["Seconda auto setting = NKikimrKqp::TKqpSetting(); setting.SetName("_KqpYqlSyntaxVersion"); setting.SetValue("1"); - auto serverSettings = TKikimrSettings() + auto serverSettings = TKikimrSettings() .SetEnableMvcc(WithMvcc) .SetEnableMvccSnapshotReads(WithMvcc) - .SetKqpSettings({setting}); - TKikimrRunner kikimr(serverSettings); + .SetKqpSettings({setting}); + TKikimrRunner kikimr(serverSettings); auto db = kikimr.GetTableClient(); auto session = db.CreateSession().GetValueSync().GetSession(); diff --git a/ydb/core/kqp/ut/kqp_mvcc_ut.cpp b/ydb/core/kqp/ut/kqp_mvcc_ut.cpp index b423c92f78..571b39df3a 100644 --- a/ydb/core/kqp/ut/kqp_mvcc_ut.cpp +++ b/ydb/core/kqp/ut/kqp_mvcc_ut.cpp @@ -1,307 +1,307 @@ #include <ydb/core/kqp/ut/common/kqp_ut_common.h> - + #include <ydb/public/sdk/cpp/client/ydb_proto/accessor.h> - -namespace NKikimr { -namespace NKqp { - -using namespace NYdb; -using namespace NYdb::NTable; - -Y_UNIT_TEST_SUITE(KqpSnapshotRead) { + +namespace NKikimr { +namespace NKqp { + +using namespace NYdb; +using namespace NYdb::NTable; + +Y_UNIT_TEST_SUITE(KqpSnapshotRead) { Y_UNIT_TEST_NEW_ENGINE(TestSnapshotExpiration) { - TKikimrRunner kikimr(TKikimrSettings() + TKikimrRunner kikimr(TKikimrSettings() .SetEnableMvcc(true) .SetEnableMvccSnapshotReads(true) - .SetKeepSnapshotTimeout(TDuration::Seconds(1))); - + .SetKeepSnapshotTimeout(TDuration::Seconds(1))); + // kikimr.GetTestServer().GetRuntime()->SetLogPriority(NKikimrServices::KQP_BLOBS_STORAGE, NActors::NLog::PRI_DEBUG); // kikimr.GetTestServer().GetRuntime()->SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_DEBUG); - - auto db = kikimr.GetTableClient(); - auto session1 = db.CreateSession().GetValueSync().GetSession(); - auto session2 = db.CreateSession().GetValueSync().GetSession(); - + + auto db = kikimr.GetTableClient(); + auto session1 = db.CreateSession().GetValueSync().GetSession(); + auto session2 = db.CreateSession().GetValueSync().GetSession(); + auto result = session1.ExecuteDataQuery(Q_(R"( - SELECT * FROM `/Root/TwoShard` WHERE Key = 1u OR Key = 4000000001u; + SELECT * FROM `/Root/TwoShard` WHERE Key = 1u OR Key = 4000000001u; )"), TTxControl::BeginTx(TTxSettings::SerializableRW())).ExtractValueSync(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - CompareYson(R"([ - [[1u];["One"];[-1]]; - [[4000000001u];["BigOne"];[-1]] - ])", FormatResultSetYson(result.GetResultSet(0))); - - auto tx = result.GetTransaction(); - + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + CompareYson(R"([ + [[1u];["One"];[-1]]; + [[4000000001u];["BigOne"];[-1]] + ])", FormatResultSetYson(result.GetResultSet(0))); + + auto tx = result.GetTransaction(); + result = session2.ExecuteDataQuery(Q_(R"( - UPSERT INTO `/Root/TwoShard` (Key, Value1, Value2) VALUES (1u, "ChangedOne", 1); + UPSERT INTO `/Root/TwoShard` (Key, Value1, Value2) VALUES (1u, "ChangedOne", 1); )"), TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()).ExtractValueSync(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - - auto deadline = TInstant::Now() + TDuration::Seconds(30); + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + + auto deadline = TInstant::Now() + TDuration::Seconds(30); auto caught = false; - do { - Sleep(TDuration::Seconds(1)); + do { + Sleep(TDuration::Seconds(1)); auto result = session1.ExecuteDataQuery(Q_(R"( - SELECT * FROM `/Root/TwoShard` WHERE Key = 1u OR Key = 4000000001u; + SELECT * FROM `/Root/TwoShard` WHERE Key = 1u OR Key = 4000000001u; )"), TTxControl::Tx(*tx)).ExtractValueSync(); - if (result.GetStatus() == EStatus::SUCCESS) - continue; - + if (result.GetStatus() == EStatus::SUCCESS) + continue; + UNIT_ASSERT_C(HasIssue(result.GetIssues(), NYql::TIssuesIds::DEFAULT_ERROR, - [](const NYql::TIssue& issue){ - return issue.Message.Contains("stale snapshot"); - }), result.GetIssues().ToString()); - + [](const NYql::TIssue& issue){ + return issue.Message.Contains("stale snapshot"); + }), result.GetIssues().ToString()); + caught = true; - break; - } while (TInstant::Now() < deadline); + break; + } while (TInstant::Now() < deadline); UNIT_ASSERT_C(caught, "Failed to wait for snapshot expiration."); - } - - Y_UNIT_TEST_NEW_ENGINE(ReadOnlyTxCommitsOnConcurrentWrite) { + } + + Y_UNIT_TEST_NEW_ENGINE(ReadOnlyTxCommitsOnConcurrentWrite) { TKikimrRunner kikimr(TKikimrSettings().SetEnableMvcc(true).SetEnableMvccSnapshotReads(true)); - + // kikimr.GetTestServer().GetRuntime()->SetLogPriority(NKikimrServices::KQP_COMPUTE, NActors::NLog::PRI_DEBUG); // kikimr.GetTestServer().GetRuntime()->SetLogPriority(NKikimrServices::KQP_BLOBS_STORAGE, NActors::NLog::PRI_DEBUG); // kikimr.GetTestServer().GetRuntime()->SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_DEBUG); - - auto db = kikimr.GetTableClient(); - auto session1 = db.CreateSession().GetValueSync().GetSession(); - auto session2 = db.CreateSession().GetValueSync().GetSession(); - - auto result = session1.ExecuteDataQuery(Q_(R"( + + auto db = kikimr.GetTableClient(); + auto session1 = db.CreateSession().GetValueSync().GetSession(); + auto session2 = db.CreateSession().GetValueSync().GetSession(); + + auto result = session1.ExecuteDataQuery(Q_(R"( SELECT * FROM `/Root/TwoShard` WHERE Key = 1u OR Key = 4000000001u; - )"), TTxControl::BeginTx(TTxSettings::SerializableRW())).ExtractValueSync(); - - auto tx = result.GetTransaction(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - CompareYson(R"([ - [[1u];["One"];[-1]]; - [[4000000001u];["BigOne"];[-1]] - ])", FormatResultSetYson(result.GetResultSet(0))); - - result = session2.ExecuteDataQuery(Q_(R"( + )"), TTxControl::BeginTx(TTxSettings::SerializableRW())).ExtractValueSync(); + + auto tx = result.GetTransaction(); + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + CompareYson(R"([ + [[1u];["One"];[-1]]; + [[4000000001u];["BigOne"];[-1]] + ])", FormatResultSetYson(result.GetResultSet(0))); + + result = session2.ExecuteDataQuery(Q_(R"( UPSERT INTO `/Root/TwoShard` (Key, Value1, Value2) VALUES (1u, "ChangedOne", 1); - )"), TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()).ExtractValueSync(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - - result = session2.ExecuteDataQuery(Q_(R"( + )"), TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()).ExtractValueSync(); + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + + result = session2.ExecuteDataQuery(Q_(R"( SELECT * FROM `/Root/TwoShard` WHERE Key = 1u; - )"), TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()).ExtractValueSync(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - CompareYson(R"([ - [[1u];["ChangedOne"];[1]]; - ])", FormatResultSetYson(result.GetResultSet(0))); - - result = session1.ExecuteDataQuery(Q_(R"( + )"), TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()).ExtractValueSync(); + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + CompareYson(R"([ + [[1u];["ChangedOne"];[1]]; + ])", FormatResultSetYson(result.GetResultSet(0))); + + result = session1.ExecuteDataQuery(Q_(R"( SELECT * FROM `/Root/TwoShard` WHERE Key = 1u; - )"), TTxControl::Tx(*tx)).ExtractValueSync(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - CompareYson(R"([ - [[1u];["One"];[-1]]; - ])", FormatResultSetYson(result.GetResultSet(0))); - - result = session1.ExecuteDataQuery(Q_(R"( + )"), TTxControl::Tx(*tx)).ExtractValueSync(); + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + CompareYson(R"([ + [[1u];["One"];[-1]]; + ])", FormatResultSetYson(result.GetResultSet(0))); + + result = session1.ExecuteDataQuery(Q_(R"( SELECT * FROM `/Root/TwoShard` WHERE Key = 2u OR Key = 4000000002u; - )"), TTxControl::Tx(*tx).CommitTx()).ExtractValueSync(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - CompareYson(R"([ - [[2u];["Two"];[0]]; - [[4000000002u];["BigTwo"];[0]] - ])", FormatResultSetYson(result.GetResultSet(0))); - } - + )"), TTxControl::Tx(*tx).CommitTx()).ExtractValueSync(); + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + CompareYson(R"([ + [[2u];["Two"];[0]]; + [[4000000002u];["BigTwo"];[0]] + ])", FormatResultSetYson(result.GetResultSet(0))); + } + Y_UNIT_TEST_NEW_ENGINE(ReadOnlyTxWithIndexCommitsOnConcurrentWrite) { TKikimrRunner kikimr(TKikimrSettings().SetEnableMvcc(true).SetEnableMvccSnapshotReads(true)); - + // kikimr.GetTestServer().GetRuntime()->SetLogPriority(NKikimrServices::KQP_COMPUTE, NActors::NLog::PRI_DEBUG); // kikimr.GetTestServer().GetRuntime()->SetLogPriority(NKikimrServices::KQP_BLOBS_STORAGE, NActors::NLog::PRI_DEBUG); // kikimr.GetTestServer().GetRuntime()->SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_DEBUG); - - auto db = kikimr.GetTableClient(); - auto session1 = db.CreateSession().GetValueSync().GetSession(); - auto session2 = db.CreateSession().GetValueSync().GetSession(); - - CreateSampleTablesWithIndex(session1); - + + auto db = kikimr.GetTableClient(); + auto session1 = db.CreateSession().GetValueSync().GetSession(); + auto session2 = db.CreateSession().GetValueSync().GetSession(); + + CreateSampleTablesWithIndex(session1); + auto result = session1.ExecuteDataQuery(Q_(R"( UPSERT INTO `/Root/SecondaryWithDataColumns` (Key, Index2, Value) VALUES - ("Pk1", "Fk1", "One"), - ("Pk2", "Fk2", "Two"), - ("Pk3", "Fk3", "Three"), - ("Pk4", "Fk4", "Four"), - ("Pk5", "Fk5", "Five"), - ("Pk6", "Fk6", "Six"); + ("Pk1", "Fk1", "One"), + ("Pk2", "Fk2", "Two"), + ("Pk3", "Fk3", "Three"), + ("Pk4", "Fk4", "Four"), + ("Pk5", "Fk5", "Five"), + ("Pk6", "Fk6", "Six"); )"), TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()).ExtractValueSync(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + result = session1.ExecuteDataQuery(Q1_(R"( SELECT Value FROM `/Root/SecondaryWithDataColumns` view Index WHERE Index2 = "Fk1"; )"), TTxControl::BeginTx(TTxSettings::SerializableRW())).ExtractValueSync(); - - auto tx = result.GetTransaction(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - CompareYson(R"([ - [["One"]] - ])", FormatResultSetYson(result.GetResultSet(0))); - + + auto tx = result.GetTransaction(); + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + CompareYson(R"([ + [["One"]] + ])", FormatResultSetYson(result.GetResultSet(0))); + result = session2.ExecuteDataQuery(Q_(R"( UPSERT INTO `/Root/SecondaryWithDataColumns` (Key, Index2, Value) VALUES ("Pk1", "Fk1", "ChangedOne"); )"), TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()).ExtractValueSync(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + result = session2.ExecuteDataQuery(Q1_(R"( SELECT Value FROM `/Root/SecondaryWithDataColumns` view Index WHERE Index2 = "Fk1"; )"), TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()).ExtractValueSync(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - CompareYson(R"([ - [["ChangedOne"]] - ])", FormatResultSetYson(result.GetResultSet(0))); - + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + CompareYson(R"([ + [["ChangedOne"]] + ])", FormatResultSetYson(result.GetResultSet(0))); + result = session1.ExecuteDataQuery(Q1_(R"( SELECT Value FROM `/Root/SecondaryWithDataColumns` view Index WHERE Index2 = "Fk1"; )"), TTxControl::Tx(*tx).CommitTx()).ExtractValueSync(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - CompareYson(R"([ - [["One"]] - ])", FormatResultSetYson(result.GetResultSet(0))); - } - - Y_UNIT_TEST_NEW_ENGINE(ReadWriteTxFailsOnConcurrentWrite1) { + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + CompareYson(R"([ + [["One"]] + ])", FormatResultSetYson(result.GetResultSet(0))); + } + + Y_UNIT_TEST_NEW_ENGINE(ReadWriteTxFailsOnConcurrentWrite1) { TKikimrRunner kikimr(TKikimrSettings().SetEnableMvcc(true).SetEnableMvccSnapshotReads(true)); - + // kikimr.GetTestServer().GetRuntime()->SetLogPriority(NKikimrServices::KQP_COMPUTE, NActors::NLog::PRI_DEBUG); // kikimr.GetTestServer().GetRuntime()->SetLogPriority(NKikimrServices::KQP_BLOBS_STORAGE, NActors::NLog::PRI_DEBUG); // kikimr.GetTestServer().GetRuntime()->SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_DEBUG); - - auto db = kikimr.GetTableClient(); - auto session1 = db.CreateSession().GetValueSync().GetSession(); - auto session2 = db.CreateSession().GetValueSync().GetSession(); - - auto result = session1.ExecuteDataQuery(Q_(R"( + + auto db = kikimr.GetTableClient(); + auto session1 = db.CreateSession().GetValueSync().GetSession(); + auto session2 = db.CreateSession().GetValueSync().GetSession(); + + auto result = session1.ExecuteDataQuery(Q_(R"( SELECT * FROM `/Root/TwoShard` WHERE Key = 1u OR Key = 4000000001u; - )"), TTxControl::BeginTx(TTxSettings::SerializableRW())).ExtractValueSync(); - - auto tx = result.GetTransaction(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - CompareYson(R"([ - [[1u];["One"];[-1]]; - [[4000000001u];["BigOne"];[-1]] - ])", FormatResultSetYson(result.GetResultSet(0))); - - result = session2.ExecuteDataQuery(Q_(R"( + )"), TTxControl::BeginTx(TTxSettings::SerializableRW())).ExtractValueSync(); + + auto tx = result.GetTransaction(); + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + CompareYson(R"([ + [[1u];["One"];[-1]]; + [[4000000001u];["BigOne"];[-1]] + ])", FormatResultSetYson(result.GetResultSet(0))); + + result = session2.ExecuteDataQuery(Q_(R"( UPSERT INTO `/Root/TwoShard` (Key, Value1, Value2) VALUES (1u, "ChangedOne", 1); - )"), TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()).ExtractValueSync(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - - result = session1.ExecuteDataQuery(Q_(R"( + )"), TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()).ExtractValueSync(); + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + + result = session1.ExecuteDataQuery(Q_(R"( UPSERT INTO `/Root/TwoShard` (Key, Value1, Value2) VALUES (1u, "TwiceChangedOne", 2); - )"), TTxControl::Tx(*tx).CommitTx()).ExtractValueSync(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::ABORTED, result.GetIssues().ToString()); - UNIT_ASSERT_C(HasIssue(result.GetIssues(), NYql::TIssuesIds::KIKIMR_LOCKS_INVALIDATED), result.GetIssues().ToString()); - } - - Y_UNIT_TEST_NEW_ENGINE(ReadWriteTxFailsOnConcurrentWrite2) { + )"), TTxControl::Tx(*tx).CommitTx()).ExtractValueSync(); + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::ABORTED, result.GetIssues().ToString()); + UNIT_ASSERT_C(HasIssue(result.GetIssues(), NYql::TIssuesIds::KIKIMR_LOCKS_INVALIDATED), result.GetIssues().ToString()); + } + + Y_UNIT_TEST_NEW_ENGINE(ReadWriteTxFailsOnConcurrentWrite2) { TKikimrRunner kikimr(TKikimrSettings().SetEnableMvcc(true).SetEnableMvccSnapshotReads(true)); - + // kikimr.GetTestServer().GetRuntime()->SetLogPriority(NKikimrServices::KQP_COMPUTE, NActors::NLog::PRI_DEBUG); // kikimr.GetTestServer().GetRuntime()->SetLogPriority(NKikimrServices::KQP_BLOBS_STORAGE, NActors::NLog::PRI_DEBUG); // kikimr.GetTestServer().GetRuntime()->SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_DEBUG); - - auto db = kikimr.GetTableClient(); - auto session1 = db.CreateSession().GetValueSync().GetSession(); - auto session2 = db.CreateSession().GetValueSync().GetSession(); - - auto result = session1.ExecuteDataQuery(Q_(R"( + + auto db = kikimr.GetTableClient(); + auto session1 = db.CreateSession().GetValueSync().GetSession(); + auto session2 = db.CreateSession().GetValueSync().GetSession(); + + auto result = session1.ExecuteDataQuery(Q_(R"( SELECT * FROM `/Root/TwoShard` WHERE Key = 1u OR Key = 4000000001u; - )"), TTxControl::BeginTx(TTxSettings::SerializableRW())).ExtractValueSync(); - - auto tx = result.GetTransaction(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - CompareYson(R"([ - [[1u];["One"];[-1]]; - [[4000000001u];["BigOne"];[-1]] - ])", FormatResultSetYson(result.GetResultSet(0))); - - result = session2.ExecuteDataQuery(Q_(R"( + )"), TTxControl::BeginTx(TTxSettings::SerializableRW())).ExtractValueSync(); + + auto tx = result.GetTransaction(); + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + CompareYson(R"([ + [[1u];["One"];[-1]]; + [[4000000001u];["BigOne"];[-1]] + ])", FormatResultSetYson(result.GetResultSet(0))); + + result = session2.ExecuteDataQuery(Q_(R"( UPSERT INTO `/Root/EightShard` (Key, Text) VALUES (101u, "SomeText"); - )"), TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()).ExtractValueSync(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - - result = session1.ExecuteDataQuery(Q_(R"( + )"), TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()).ExtractValueSync(); + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + + result = session1.ExecuteDataQuery(Q_(R"( UPDATE `/Root/TwoShard` SET Value2 = 2 WHERE Key = 1u; UPDATE `/Root/EightShard` SET Text = "AnotherString" WHERE Key = 101u; - )"), TTxControl::Tx(*tx).CommitTx()).ExtractValueSync(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::ABORTED, result.GetIssues().ToString()); - UNIT_ASSERT_C(HasIssue(result.GetIssues(), NYql::TIssuesIds::KIKIMR_LOCKS_INVALIDATED), result.GetIssues().ToString()); - } - - Y_UNIT_TEST_NEW_ENGINE(ReadWriteTxFailsOnConcurrentWrite3) { + )"), TTxControl::Tx(*tx).CommitTx()).ExtractValueSync(); + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::ABORTED, result.GetIssues().ToString()); + UNIT_ASSERT_C(HasIssue(result.GetIssues(), NYql::TIssuesIds::KIKIMR_LOCKS_INVALIDATED), result.GetIssues().ToString()); + } + + Y_UNIT_TEST_NEW_ENGINE(ReadWriteTxFailsOnConcurrentWrite3) { TKikimrRunner kikimr(TKikimrSettings().SetEnableMvcc(true).SetEnableMvccSnapshotReads(true)); - + // kikimr.GetTestServer().GetRuntime()->SetLogPriority(NKikimrServices::KQP_COMPUTE, NActors::NLog::PRI_DEBUG); // kikimr.GetTestServer().GetRuntime()->SetLogPriority(NKikimrServices::KQP_BLOBS_STORAGE, NActors::NLog::PRI_DEBUG); // kikimr.GetTestServer().GetRuntime()->SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_DEBUG); - - auto db = kikimr.GetTableClient(); - auto session1 = db.CreateSession().GetValueSync().GetSession(); - auto session2 = db.CreateSession().GetValueSync().GetSession(); - - auto result = session1.ExecuteDataQuery(Q_(R"( + + auto db = kikimr.GetTableClient(); + auto session1 = db.CreateSession().GetValueSync().GetSession(); + auto session2 = db.CreateSession().GetValueSync().GetSession(); + + auto result = session1.ExecuteDataQuery(Q_(R"( SELECT * FROM `/Root/TwoShard` WHERE Key = 1u OR Key = 4000000001u; - )"), TTxControl::BeginTx(TTxSettings::SerializableRW())).ExtractValueSync(); - - auto tx = result.GetTransaction(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - CompareYson(R"([ - [[1u];["One"];[-1]]; - [[4000000001u];["BigOne"];[-1]] - ])", FormatResultSetYson(result.GetResultSet(0))); - - result = session2.ExecuteDataQuery(Q_(R"( + )"), TTxControl::BeginTx(TTxSettings::SerializableRW())).ExtractValueSync(); + + auto tx = result.GetTransaction(); + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + CompareYson(R"([ + [[1u];["One"];[-1]]; + [[4000000001u];["BigOne"];[-1]] + ])", FormatResultSetYson(result.GetResultSet(0))); + + result = session2.ExecuteDataQuery(Q_(R"( UPSERT INTO `/Root/TwoShard` (Key, Value1, Value2) VALUES (2u, "ChangedTwo", 1); - )"), TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()).ExtractValueSync(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - - result = session1.ExecuteDataQuery(Q_(R"( + )"), TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()).ExtractValueSync(); + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + + result = session1.ExecuteDataQuery(Q_(R"( SELECT * FROM `/Root/TwoShard` WHERE Key = 2u OR Key = 4000000002u; - )"), TTxControl::Tx(*tx)).ExtractValueSync(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - CompareYson(R"([ - [[2u];["Two"];[0]]; - [[4000000002u];["BigTwo"];[0]] - ])", FormatResultSetYson(result.GetResultSet(0))); - - result = session1.ExecuteDataQuery(Q_(R"( + )"), TTxControl::Tx(*tx)).ExtractValueSync(); + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + CompareYson(R"([ + [[2u];["Two"];[0]]; + [[4000000002u];["BigTwo"];[0]] + ])", FormatResultSetYson(result.GetResultSet(0))); + + result = session1.ExecuteDataQuery(Q_(R"( UPSERT INTO `/Root/TwoShard` (Key, Value1, Value2) VALUES (2u, "TwiceChangedTwo", 1); - )"), TTxControl::Tx(*tx).CommitTx()).ExtractValueSync(); - - UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::ABORTED, result.GetIssues().ToString()); - UNIT_ASSERT_C(HasIssue(result.GetIssues(), NYql::TIssuesIds::KIKIMR_LOCKS_INVALIDATED), result.GetIssues().ToString()); - } -} - -} // namespace NKqp -} // namespace NKikimr + )"), TTxControl::Tx(*tx).CommitTx()).ExtractValueSync(); + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::ABORTED, result.GetIssues().ToString()); + UNIT_ASSERT_C(HasIssue(result.GetIssues(), NYql::TIssuesIds::KIKIMR_LOCKS_INVALIDATED), result.GetIssues().ToString()); + } +} + +} // namespace NKqp +} // namespace NKikimr diff --git a/ydb/core/kqp/ut/ya.make b/ydb/core/kqp/ut/ya.make index 3132b42b58..609ec3237f 100644 --- a/ydb/core/kqp/ut/ya.make +++ b/ydb/core/kqp/ut/ya.make @@ -32,7 +32,7 @@ SRCS( kqp_limits_ut.cpp kqp_locks_ut.cpp kqp_merge_connection_ut.cpp - kqp_mvcc_ut.cpp + kqp_mvcc_ut.cpp kqp_newengine_effects_ut.cpp kqp_newengine_flowcontrol_ut.cpp kqp_newengine_ut.cpp diff --git a/ydb/core/protos/config.proto b/ydb/core/protos/config.proto index 0f5b32c3a2..d64169d4fc 100644 --- a/ydb/core/protos/config.proto +++ b/ydb/core/protos/config.proto @@ -607,12 +607,12 @@ message TDynamicNodeConfig { } message TFeatureFlags { - enum Tribool { - UNSET = 0; - VALUE_TRUE = 1; - VALUE_FALSE = 2; - } - + enum Tribool { + UNSET = 0; + VALUE_TRUE = 1; + VALUE_FALSE = 2; + } + optional bool EnableSeparateSolomonShardForPDisk = 1 [default = true]; optional bool UseForsetiSchedulerByDefaultForPDisk = 2 [default = true]; optional bool EnableSeparateTrimThreadForPDisk = 3 [default = true]; @@ -650,7 +650,7 @@ message TFeatureFlags { optional bool AllowServerlessStorageBillingForSchemeShard = 35 [default = false]; optional bool EnableGracefulShutdown = 36 [default = true]; optional bool EnableDrainOnShutdown = 37 [default = true]; - optional bool EnableConfigurationCache = 38 [default = false]; + optional bool EnableConfigurationCache = 38 [default = false]; optional bool EnableDbCounters = 39 [default = false]; optional bool EnableClockGettimeForUserCpuAccounting = 40 [default = false]; optional bool EnableAsyncIndexes = 41 [default = true]; @@ -1320,16 +1320,16 @@ message TNamedConfig { optional bytes Config = 2; } -message TConfigItemVersion { - optional uint32 Kind = 1; - optional uint64 Id = 2; - optional uint64 Generation = 3; -} - -message TConfigVersion { - repeated TConfigItemVersion Items = 1; -} - +message TConfigItemVersion { + optional uint32 Kind = 1; + optional uint64 Id = 2; + optional uint64 Generation = 3; +} + +message TConfigVersion { + repeated TConfigItemVersion Items = 1; +} + message TAppConfig { optional TActorSystemConfig ActorSystemConfig = 1; optional TLogConfig LogConfig = 2; @@ -1382,6 +1382,6 @@ message TAppConfig { repeated TNamedConfig NamedConfigs = 100; optional string ClusterYamlConfig = 101; - - optional TConfigVersion Version = 102; + + optional TConfigVersion Version = 102; } diff --git a/ydb/core/protos/console_config.proto b/ydb/core/protos/console_config.proto index 30d32a2cae..d5a32d05c6 100644 --- a/ydb/core/protos/console_config.proto +++ b/ydb/core/protos/console_config.proto @@ -297,34 +297,34 @@ message TConfigId { repeated TConfigItemId ItemIds = 1; } -message TConfigSubscriptionRequest { - optional uint64 Generation = 1; - optional TNodeAttributes Options = 2; - repeated uint32 ConfigItemKinds = 3; - optional NKikimrConfig.TConfigVersion KnownVersion = 4; -} - -message TConfigSubscriptionResponse { - optional uint64 Generation = 1; - optional TStatus Status = 2; -} - -message TConfigSubscriptionError { - optional Ydb.StatusIds.StatusCode Code = 2; - optional string Reason = 3; -} - -message TConfigSubscriptionCanceled { - optional uint64 Generation = 1; -} - -message TConfigSubscriptionNotification { - optional uint64 Order = 1; - optional uint64 Generation = 2; - optional NKikimrConfig.TAppConfig Config = 3; - repeated uint32 AffectedKinds = 4; -} - +message TConfigSubscriptionRequest { + optional uint64 Generation = 1; + optional TNodeAttributes Options = 2; + repeated uint32 ConfigItemKinds = 3; + optional NKikimrConfig.TConfigVersion KnownVersion = 4; +} + +message TConfigSubscriptionResponse { + optional uint64 Generation = 1; + optional TStatus Status = 2; +} + +message TConfigSubscriptionError { + optional Ydb.StatusIds.StatusCode Code = 2; + optional string Reason = 3; +} + +message TConfigSubscriptionCanceled { + optional uint64 Generation = 1; +} + +message TConfigSubscriptionNotification { + optional uint64 Order = 1; + optional uint64 Generation = 2; + optional NKikimrConfig.TAppConfig Config = 3; + repeated uint32 AffectedKinds = 4; +} + message TSubscription { // Subscription id. optional uint64 Id = 1; diff --git a/ydb/core/protos/counters_datashard.proto b/ydb/core/protos/counters_datashard.proto index 2acce0751e..956a136937 100644 --- a/ydb/core/protos/counters_datashard.proto +++ b/ydb/core/protos/counters_datashard.proto @@ -7,19 +7,19 @@ option java_package = "ru.yandex.kikimr.proto"; option (TabletTypeName) = "DataShard"; // Used as prefix for all counters enum ESimpleCounters { - COUNTER_TX_IN_FLY = 0 [(CounterOpts) = {Name: "TxInFly"}]; - COUNTER_STATE_WORK = 1 [(CounterOpts) = {Name: "StateWork"}]; - COUNTER_TX_COMPLETE_LAG = 2 [(CounterOpts) = {Name: "TxCompleteLag"}]; - COUNTER_OUT_READSETS_IN_FLIGHT = 3 [(CounterOpts) = {Name: "OutReadSetsInFlight"}]; - COUNTER_IMMEDIATE_TX_IN_FLY = 4 [(CounterOpts) = {Name: "ImmediateTxInFly"}]; - COUNTER_IMMEDIATE_TX_DELAYED = 5 [(CounterOpts) = {Name: "ImmediateTxDelayed"}]; - COUNTER_SCAN_TX_COMPLETE_LAG = 6 [(CounterOpts) = {Name: "ScanTxCompleteLag"}]; - COUNTER_PROPOSE_QUEUE_SIZE = 7 [(CounterOpts) = {Name: "ProposeQueueSize"}]; - COUNTER_SPLIT_SRC_WAIT_TX_IN_FLY = 8 [(CounterOpts) = {Name: "SplitSrcWaitTxInFly"}]; - COUNTER_SPLIT_SRC_WAIT_IMMEDIATE_TX_IN_FLY = 9 [(CounterOpts) = {Name: "SplitSrcWaitImmediateTxInFly"}]; - COUNTER_MVCC_STATE_CHANGE_WAIT_TX_IN_FLY = 10 [(CounterOpts) = {Name: "MvccStateChangeWaitTxInFly"}]; - COUNTER_MVCC_STATE_CHANGE_WAIT_IMMEDIATE_TX_IN_FLY = 11 [(CounterOpts) = {Name: "MvccStateChangeWaitImmediateTxInFly"}]; - COUNTER_MVCC_ENABLED = 12 [(CounterOpts) = {Name: "MvccEnabled"}]; + COUNTER_TX_IN_FLY = 0 [(CounterOpts) = {Name: "TxInFly"}]; + COUNTER_STATE_WORK = 1 [(CounterOpts) = {Name: "StateWork"}]; + COUNTER_TX_COMPLETE_LAG = 2 [(CounterOpts) = {Name: "TxCompleteLag"}]; + COUNTER_OUT_READSETS_IN_FLIGHT = 3 [(CounterOpts) = {Name: "OutReadSetsInFlight"}]; + COUNTER_IMMEDIATE_TX_IN_FLY = 4 [(CounterOpts) = {Name: "ImmediateTxInFly"}]; + COUNTER_IMMEDIATE_TX_DELAYED = 5 [(CounterOpts) = {Name: "ImmediateTxDelayed"}]; + COUNTER_SCAN_TX_COMPLETE_LAG = 6 [(CounterOpts) = {Name: "ScanTxCompleteLag"}]; + COUNTER_PROPOSE_QUEUE_SIZE = 7 [(CounterOpts) = {Name: "ProposeQueueSize"}]; + COUNTER_SPLIT_SRC_WAIT_TX_IN_FLY = 8 [(CounterOpts) = {Name: "SplitSrcWaitTxInFly"}]; + COUNTER_SPLIT_SRC_WAIT_IMMEDIATE_TX_IN_FLY = 9 [(CounterOpts) = {Name: "SplitSrcWaitImmediateTxInFly"}]; + COUNTER_MVCC_STATE_CHANGE_WAIT_TX_IN_FLY = 10 [(CounterOpts) = {Name: "MvccStateChangeWaitTxInFly"}]; + COUNTER_MVCC_STATE_CHANGE_WAIT_IMMEDIATE_TX_IN_FLY = 11 [(CounterOpts) = {Name: "MvccStateChangeWaitImmediateTxInFly"}]; + COUNTER_MVCC_ENABLED = 12 [(CounterOpts) = {Name: "MvccEnabled"}]; } enum ECumulativeCounters { @@ -406,7 +406,7 @@ enum ETxTypes { TXTYPE_REMOVE_CHANGE_RECORDS = 57 [(TxTypeOpts) = {Name: "TxRemoveChangeRecords"}]; TXTYPE_CHANGE_EXCHANGE_HANDSHAKE = 58 [(TxTypeOpts) = {Name: "TxChangeExchangeHandshake"}]; TXTYPE_APPLY_CHANGE_RECORDS = 59 [(TxTypeOpts) = {Name: "TxApplyChangeRecords"}]; - TXTYPE_EXECUTE_MVCC_STATE_CHANGE = 60 [(TxTypeOpts) = {Name: "TxExecuteMvccStateChange"}]; + TXTYPE_EXECUTE_MVCC_STATE_CHANGE = 60 [(TxTypeOpts) = {Name: "TxExecuteMvccStateChange"}]; TXTYPE_CHANGE_S3_UPLOAD_STATUS = 61 [(TxTypeOpts) = {Name: "TxChangeS3UploadStatus"}]; TXTYPE_ACTIVATE_CHANGE_SENDER = 62 [(TxTypeOpts) = {Name: "TxActivateChangeSender"}]; TXTYPE_ACTIVATE_CHANGE_SENDER_ACK = 63 [(TxTypeOpts) = {Name: "TxActivateChangeSenderAck"}]; diff --git a/ydb/core/protos/flat_scheme_op.proto b/ydb/core/protos/flat_scheme_op.proto index f3feaa7ada..33e598c1c2 100644 --- a/ydb/core/protos/flat_scheme_op.proto +++ b/ydb/core/protos/flat_scheme_op.proto @@ -64,12 +64,12 @@ enum EFreezeState { Unfreeze = 2; } -enum EMvccState { - MvccUnspecified = 0; - MvccEnabled = 1; - MvccDisabled = 2; -} - +enum EMvccState { + MvccUnspecified = 0; + MvccEnabled = 1; + MvccDisabled = 2; +} + message TColumnDescription { optional string Name = 1; optional string Type = 2; @@ -271,8 +271,8 @@ message TPartitionConfig { optional EFreezeState FreezeState = 21; optional bool ShadowData = 22; // Table has separate shadow data for later merging repeated NKikimrHive.TFollowerGroup FollowerGroups = 23; - reserved 24; // EMvccState MvccState = 24; no longer used - optional uint64 KeepSnapshotTimeout = 25; // milliseconds + reserved 24; // EMvccState MvccState = 24; no longer used + optional uint64 KeepSnapshotTimeout = 25; // milliseconds } message TSplitBoundary { diff --git a/ydb/core/protos/node_whiteboard.proto b/ydb/core/protos/node_whiteboard.proto index 5424ebbd4a..b96713ca29 100644 --- a/ydb/core/protos/node_whiteboard.proto +++ b/ydb/core/protos/node_whiteboard.proto @@ -237,11 +237,11 @@ message TEvBSGroupStateResponse { optional uint32 ResponseDuration = 3; // filled during collect } -enum EConfigState { - Consistent = 0; - Outdated = 1; -} - +enum EConfigState { + Consistent = 0; + Outdated = 1; +} + message TSystemStateInfo { message TPoolStats { optional string Name = 1; @@ -285,7 +285,7 @@ message TSystemStateInfo { optional string ClusterName = 25; optional uint64 MemoryUsed = 26; optional uint64 MemoryLimit = 27; - optional EConfigState ConfigState = 28 [default = Consistent]; + optional EConfigState ConfigState = 28 [default = Consistent]; optional uint64 MemoryUsedInAlloc = 29; optional double MaxDiskUsage = 30; optional NActorsInterconnect.TNodeLocation Location = 31; diff --git a/ydb/core/protos/services.proto b/ydb/core/protos/services.proto index 416de4ca19..c17c8a7dc3 100644 --- a/ydb/core/protos/services.proto +++ b/ydb/core/protos/services.proto @@ -229,7 +229,7 @@ enum EServiceKikimr { KESUS_TABLET = 553; CONFIGS_DISPATCHER = 560; - CONFIGS_CACHE = 561; + CONFIGS_CACHE = 561; // SchemeBoard section SCHEME_BOARD_REPLICA = 570; diff --git a/ydb/core/protos/tx_datashard.proto b/ydb/core/protos/tx_datashard.proto index 66303c55d5..89863b2540 100644 --- a/ydb/core/protos/tx_datashard.proto +++ b/ydb/core/protos/tx_datashard.proto @@ -282,12 +282,12 @@ message TSnapshotTransferReadSet { optional bytes BorrowedSnapshot = 1; optional uint64 MinWriteVersionStep = 2; optional uint64 MinWriteVersionTxId = 3; - optional uint64 MvccCompleteEdgeStep = 4; - optional uint64 MvccCompleteEdgeTxId = 5; - optional uint64 MvccIncompleteEdgeStep = 6; - optional uint64 MvccIncompleteEdgeTxId = 7; - optional uint64 MvccLowWatermarkStep = 8; - optional uint64 MvccLowWatermarkTxId = 9; + optional uint64 MvccCompleteEdgeStep = 4; + optional uint64 MvccCompleteEdgeTxId = 5; + optional uint64 MvccIncompleteEdgeStep = 6; + optional uint64 MvccIncompleteEdgeTxId = 7; + optional uint64 MvccLowWatermarkStep = 8; + optional uint64 MvccLowWatermarkTxId = 9; } message TSnapshotTransferInfo { @@ -464,11 +464,11 @@ enum ETransactionKind { // kinds. See NKikimr::NDataShard::EOperationKind. } -message TMvccSnapshot { - optional uint64 Step = 10; - optional uint64 TxId = 11; -} - +message TMvccSnapshot { + optional uint64 Step = 10; + optional uint64 TxId = 11; +} + message TEvProposeTransaction { optional ETransactionKind TxKind = 1; optional NActorsProto.TActorId Source = 2; @@ -479,7 +479,7 @@ message TEvProposeTransaction { optional uint64 SchemeShardId = 7; optional NKikimrSubDomains.TProcessingParams ProcessingParams = 8; optional uint64 SubDomainPathId = 9; // LocalPathId (SchemeShardId is the OwnerId) - optional TMvccSnapshot MvccSnapshot = 10; + optional TMvccSnapshot MvccSnapshot = 10; } message TEvCancelTransactionProposal { @@ -676,12 +676,12 @@ message TEvSplitTransferSnapshot { optional uint64 MinWriteVersionStep = 5; optional uint64 MinWriteVersionTxId = 6; repeated TPersistentSnapshot PersistentSnapshots = 7; - optional uint64 MvccCompleteEdgeStep = 8; - optional uint64 MvccCompleteEdgeTxId = 9; - optional uint64 MvccIncompleteEdgeStep = 10; - optional uint64 MvccIncompleteEdgeTxId = 11; - optional uint64 MvccLowWatermarkStep = 12; - optional uint64 MvccLowWatermarkTxId = 13; + optional uint64 MvccCompleteEdgeStep = 8; + optional uint64 MvccCompleteEdgeTxId = 9; + optional uint64 MvccIncompleteEdgeStep = 10; + optional uint64 MvccIncompleteEdgeTxId = 11; + optional uint64 MvccLowWatermarkStep = 12; + optional uint64 MvccLowWatermarkTxId = 13; optional bool WaitForActivation = 14; // Generation of the sender tablet diff --git a/ydb/core/protos/tx_proxy.proto b/ydb/core/protos/tx_proxy.proto index 826f96e4c5..dedd2f9cbb 100644 --- a/ydb/core/protos/tx_proxy.proto +++ b/ydb/core/protos/tx_proxy.proto @@ -156,8 +156,8 @@ message TMiniKQLTransaction { optional uint64 PerShardKeysSizeLimitBytes = 54; optional bool CollectStats = 55; optional TLimits Limits = 56; - optional uint64 SnapshotStep = 9; - optional uint64 SnapshotTxId = 10; + optional uint64 SnapshotStep = 9; + optional uint64 SnapshotTxId = 10; }; message TMiniKQLCompileResults { diff --git a/ydb/core/tablet_flat/flat_database.cpp b/ydb/core/tablet_flat/flat_database.cpp index a239cd891f..c459119515 100644 --- a/ydb/core/tablet_flat/flat_database.cpp +++ b/ydb/core/tablet_flat/flat_database.cpp @@ -151,28 +151,28 @@ EReady TDatabase::Select(ui32 table, TRawVals key, TTagsRef tags, TRowState &row Change->Stats.SelectSieved += res.Sieved; Change->Stats.SelectWeeded += res.Weeded; Change->Stats.SelectNoKey += res.NoKey; - Change->Stats.SelectInvisible += res.Invisible; + Change->Stats.SelectInvisible += res.Invisible; return res.Ready; } -EReady TDatabase::Select(ui32 table, TRawVals key, TTagsRef tags, TRowState &row, TSelectStats& stats, ui64 flg, TRowVersion snapshot) const noexcept -{ - TempIterators.clear(); - Y_VERIFY(!NoMoreReadsFlag, "Trying to read after reads prohibited, table %u", table); +EReady TDatabase::Select(ui32 table, TRawVals key, TTagsRef tags, TRowState &row, TSelectStats& stats, ui64 flg, TRowVersion snapshot) const noexcept +{ + TempIterators.clear(); + 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.SelectInvisible += res.Invisible; - - stats.Sieved += res.Sieved; - stats.Weeded += res.Weeded; - stats.NoKey += res.NoKey; - stats.Invisible += res.Invisible; - - return res.Ready; -} - + Change->Stats.SelectSieved += res.Sieved; + Change->Stats.SelectWeeded += res.Weeded; + Change->Stats.SelectNoKey += res.NoKey; + Change->Stats.SelectInvisible += res.Invisible; + + stats.Sieved += res.Sieved; + stats.Weeded += res.Weeded; + stats.NoKey += res.NoKey; + stats.Invisible += res.Invisible; + + return res.Ready; +} + void TDatabase::CalculateReadSize(TSizeEnv& env, ui32 table, TRawVals minKey, TRawVals maxKey, TTagsRef tags, ui64 flg, ui64 items, ui64 bytes, EDirection direction, TRowVersion snapshot) diff --git a/ydb/core/tablet_flat/flat_database.h b/ydb/core/tablet_flat/flat_database.h index bf9faa2aad..98baa8f438 100644 --- a/ydb/core/tablet_flat/flat_database.h +++ b/ydb/core/tablet_flat/flat_database.h @@ -79,9 +79,9 @@ public: EReady Select(ui32 table, TRawVals key, TTagsRef tags, TRowState& row, ui64 readFlags = 0, TRowVersion snapshot = TRowVersion::Max()) const noexcept; - EReady Select(ui32 table, TRawVals key, TTagsRef tags, TRowState& row, TSelectStats& stats, - ui64 readFlags = 0, TRowVersion snapshot = TRowVersion::Max()) const noexcept; - + EReady Select(ui32 table, TRawVals key, TTagsRef tags, TRowState& row, TSelectStats& stats, + ui64 readFlags = 0, TRowVersion snapshot = TRowVersion::Max()) const noexcept; + bool Precharge(ui32 table, TRawVals minKey, TRawVals maxKey, TTagsRef tags, ui64 readFlags, ui64 itemsLimit, ui64 bytesLimit, EDirection direction = EDirection::Forward, diff --git a/ydb/core/tablet_flat/flat_dbase_change.h b/ydb/core/tablet_flat/flat_dbase_change.h index e6e75e76ef..641e08b63d 100644 --- a/ydb/core/tablet_flat/flat_dbase_change.h +++ b/ydb/core/tablet_flat/flat_dbase_change.h @@ -25,7 +25,7 @@ namespace NTable { ui64 SelectSieved = 0; ui64 SelectWeeded = 0; ui64 SelectNoKey = 0; - ui64 SelectInvisible = 0; + ui64 SelectInvisible = 0; }; struct TRemovedRowVersions { diff --git a/ydb/core/tablet_flat/flat_iterator.h b/ydb/core/tablet_flat/flat_iterator.h index f2cb38014c..60195c17b4 100644 --- a/ydb/core/tablet_flat/flat_iterator.h +++ b/ydb/core/tablet_flat/flat_iterator.h @@ -24,7 +24,7 @@ enum class ENext { struct TIteratorStats { ui64 DeletedRowSkips = 0; - ui64 InvisibleRowSkips = 0; + ui64 InvisibleRowSkips = 0; }; template<class TIteratorOps> @@ -61,28 +61,28 @@ class TTableItBase : TNonCopyable { FreeKey(&FirstErased); } - void OnEraseKey(TArrayRef<const TCell> key, TRowVersion version) { - if (!Cache) + void OnEraseKey(TArrayRef<const TCell> key, TRowVersion version) { + if (!Cache) + return; + + if (FutureEntryValid && Cache.CrossedAtRight(FutureEntry, key)) { + // The iterator is still in future range, will skip all checks return; - - if (FutureEntryValid && Cache.CrossedAtRight(FutureEntry, key)) { - // The iterator is still in future range, will skip all checks - return; } - FutureEntryValid = false; - - if (NextEntryValid && Cache.CrossedAtLeft(NextEntry, key)) { + FutureEntryValid = false; + + if (NextEntryValid && Cache.CrossedAtLeft(NextEntry, key)) { // We have just crossed the gap into the next entry FreeKey(&LastErased); if (PrevEntryValid) { // Merge the two adjacent entries that we have Y_VERIFY_DEBUG(!FirstErased); - Y_VERIFY_DEBUG(MaxVersion >= PrevEntry->MaxVersion); - NextEntry = Cache.MergeAdjacent(PrevEntry, NextEntry, ::Max(MaxVersion, version)); + Y_VERIFY_DEBUG(MaxVersion >= PrevEntry->MaxVersion); + NextEntry = Cache.MergeAdjacent(PrevEntry, NextEntry, ::Max(MaxVersion, version)); } else if (FirstErased) { // Extend the next entry with an earlier key - Cache.ExtendBackward(NextEntry, TakeKey(&FirstErased), true, ::Max(MaxVersion, version)); + Cache.ExtendBackward(NextEntry, TakeKey(&FirstErased), true, ::Max(MaxVersion, version)); } Cache.Touch(NextEntry); Cache.EvictOld(); @@ -90,18 +90,18 @@ class TTableItBase : TNonCopyable { PrevEntryValid = false; NextEntryValid = false; ErasedCount = 0; - MaxVersion = TRowVersion::Min(); + MaxVersion = TRowVersion::Min(); Y_VERIFY_DEBUG(!FirstErased); Y_VERIFY_DEBUG(!LastErased); - if (NextEntry->MaxVersion > It->SnapshotVersion) { - // The range is in future, the iterator cannot use it - FutureEntry = NextEntry; - FutureEntryValid = true; - return; - } - + if (NextEntry->MaxVersion > It->SnapshotVersion) { + // The range is in future, the iterator cannot use it + FutureEntry = NextEntry; + FutureEntryValid = true; + return; + } + if (!TOps::EndKey(NextEntry)) { // We know that everything to +inf is erased It->Iterators.clear(); @@ -120,14 +120,14 @@ class TTableItBase : TNonCopyable { PrevEntryValid = true; NextEntry = Cache.Next(PrevEntry); NextEntryValid = true; - MaxVersion = PrevEntry->MaxVersion; + MaxVersion = PrevEntry->MaxVersion; return; } if (PrevEntryValid || FirstErased) { FreeKey(&LastErased); LastErased = Cache.AllocateKey(key); - MaxVersion = ::Max(MaxVersion, version); + MaxVersion = ::Max(MaxVersion, version); ++ErasedCount; return; } @@ -140,19 +140,19 @@ class TTableItBase : TNonCopyable { return; } - Y_VERIFY_DEBUG(!PrevEntryValid); - Y_VERIFY_DEBUG(!NextEntryValid); - + Y_VERIFY_DEBUG(!PrevEntryValid); + Y_VERIFY_DEBUG(!NextEntryValid); + // Check if this key is an already known erase key auto res = Cache.FindKey(key); if (res.second) { - if (res.first->MaxVersion > It->SnapshotVersion) { - // The range is in future, the iterator cannot use it - FutureEntry = res.first; - FutureEntryValid = true; - return; - } - + if (res.first->MaxVersion > It->SnapshotVersion) { + // The range is in future, the iterator cannot use it + FutureEntry = res.first; + FutureEntryValid = true; + return; + } + Cache.Touch(res.first); if (!It->SkipTo(TOps::EndKey(res.first), !TOps::EndInclusive(res.first))) { // We've got some missing page, cannot iterate further @@ -162,7 +162,7 @@ class TTableItBase : TNonCopyable { PrevEntryValid = true; NextEntry = Cache.Next(PrevEntry); NextEntryValid = true; - MaxVersion = PrevEntry->MaxVersion; + MaxVersion = PrevEntry->MaxVersion; return; } @@ -174,7 +174,7 @@ class TTableItBase : TNonCopyable { } FirstErased = Cache.AllocateKey(key); - MaxVersion = version; + MaxVersion = version; ++ErasedCount; } @@ -186,12 +186,12 @@ class TTableItBase : TNonCopyable { if (ErasedCount > 0 && LastErased) { if (PrevEntryValid) { Y_VERIFY_DEBUG(!FirstErased); - Cache.ExtendForward(PrevEntry, TakeKey(&LastErased), true, MaxVersion); + Cache.ExtendForward(PrevEntry, TakeKey(&LastErased), true, MaxVersion); Cache.EvictOld(); } else if (ErasedCount >= Cache.MinRows()) { // We have enough erased rows to make a new cache entry Y_VERIFY_DEBUG(FirstErased); - Cache.AddRange(TakeKey(&FirstErased), TakeKey(&LastErased), MaxVersion); + Cache.AddRange(TakeKey(&FirstErased), TakeKey(&LastErased), MaxVersion); Cache.EvictOld(); } } @@ -200,9 +200,9 @@ class TTableItBase : TNonCopyable { FreeKey(&FirstErased); PrevEntryValid = false; NextEntryValid = false; - FutureEntryValid = false; + FutureEntryValid = false; ErasedCount = 0; - MaxVersion = TRowVersion::Min(); + MaxVersion = TRowVersion::Min(); } private: @@ -224,14 +224,14 @@ class TTableItBase : TNonCopyable { TOps Cache; TKeyRangeCache::const_iterator PrevEntry; TKeyRangeCache::const_iterator NextEntry; - TKeyRangeCache::const_iterator FutureEntry; + TKeyRangeCache::const_iterator FutureEntry; TArrayRef<TCell> FirstErased; TArrayRef<TCell> LastErased; size_t ErasedCount = 0; - TRowVersion MaxVersion = TRowVersion::Min(); + TRowVersion MaxVersion = TRowVersion::Min(); bool PrevEntryValid = false; bool NextEntryValid = false; - bool FutureEntryValid = false; + bool FutureEntryValid = false; }; public: @@ -262,7 +262,7 @@ public: { TEraseCachingState eraseCache(this); - bool isHead = true; + bool isHead = true; for (Ready = EReady::Data; Ready == EReady::Data; ) { if (Stage == EStage::Seek) { Ready = Start(); @@ -288,12 +288,12 @@ public: } else { ++Stats.DeletedRowSkips; /* skip internal technical row states w/o data */ if (ErasedKeysCache) { - if (isHead) { - eraseCache.OnEraseKey(GetKey().Cells(), GetRowVersion()); - } else { - eraseCache.Flush(); - isHead = true; - } + if (isHead) { + eraseCache.OnEraseKey(GetKey().Cells(), GetRowVersion()); + } else { + eraseCache.Flush(); + isHead = true; + } } } } @@ -782,15 +782,15 @@ inline EReady TTableItBase<TIteratorOps>::Snap(TRowVersion rowVersion) noexcept switch (ai.Type) { case EType::Mem: { auto ready = MemIters[ai.Index]->SkipToRowVersion(rowVersion, CommittedTransactions); - Stats.InvisibleRowSkips += std::exchange(MemIters[ai.Index]->InvisibleRowSkips, 0); - if (ready) { + Stats.InvisibleRowSkips += std::exchange(MemIters[ai.Index]->InvisibleRowSkips, 0); + if (ready) { return EReady::Data; } break; } case EType::Run: { auto ready = RunIters[ai.Index]->SkipToRowVersion(rowVersion, CommittedTransactions); - Stats.InvisibleRowSkips += std::exchange(RunIters[ai.Index]->InvisibleRowSkips, 0); + Stats.InvisibleRowSkips += std::exchange(RunIters[ai.Index]->InvisibleRowSkips, 0); if (ready == EReady::Data) { return EReady::Data; } else if (ready != EReady::Gone) { diff --git a/ydb/core/tablet_flat/flat_iterator_ops.h b/ydb/core/tablet_flat/flat_iterator_ops.h index 2272c9a8b5..fadddafccf 100644 --- a/ydb/core/tablet_flat/flat_iterator_ops.h +++ b/ydb/core/tablet_flat/flat_iterator_ops.h @@ -83,52 +83,52 @@ struct TTableItOps { public: using TEraseCacheOpsCommon::TEraseCacheOpsCommon; - inline bool CrossedAtLeft( + inline bool CrossedAtLeft( TKeyRangeCache::const_iterator it, TArrayRef<const TCell> key) { - return !IsEnd(it) && Cache->InsideLeft(it, key); + return !IsEnd(it) && Cache->InsideLeft(it, key); + } + + inline bool CrossedAtRight( + TKeyRangeCache::const_iterator it, + TArrayRef<const TCell> key) + { + return !IsEnd(it) && Cache->InsideRight(it, key); } - inline bool CrossedAtRight( - TKeyRangeCache::const_iterator it, - TArrayRef<const TCell> key) - { - return !IsEnd(it) && Cache->InsideRight(it, key); - } - inline TKeyRangeCache::const_iterator MergeAdjacent( TKeyRangeCache::const_iterator prev, - TKeyRangeCache::const_iterator next, - TRowVersion version) + TKeyRangeCache::const_iterator next, + TRowVersion version) { - return Cache->Merge(prev, next, version); + return Cache->Merge(prev, next, version); } inline void ExtendForward( TKeyRangeCache::const_iterator it, TArrayRef<TCell> key, - bool inclusive, - TRowVersion version) + bool inclusive, + TRowVersion version) { - Cache->ExtendRight(it, key, inclusive, version); + Cache->ExtendRight(it, key, inclusive, version); } inline void ExtendBackward( TKeyRangeCache::const_iterator it, TArrayRef<TCell> key, - bool inclusive, - TRowVersion version) + bool inclusive, + TRowVersion version) { - Cache->ExtendLeft(it, key, inclusive, version); + Cache->ExtendLeft(it, key, inclusive, version); } inline void AddRange( TArrayRef<TCell> first, - TArrayRef<TCell> last, - TRowVersion version) + TArrayRef<TCell> last, + TRowVersion version) { - Cache->Add(TKeyRangeEntry(first, last, true, true, version)); + Cache->Add(TKeyRangeEntry(first, last, true, true, version)); } inline std::pair<TKeyRangeCache::const_iterator, bool> FindKey( @@ -142,10 +142,10 @@ struct TTableItOps { return it; } - inline bool IsEnd(TKeyRangeCache::const_iterator it) { - return it == Cache->end(); - } - + inline bool IsEnd(TKeyRangeCache::const_iterator it) { + return it == Cache->end(); + } + static inline TArrayRef<const TCell> EndKey(TKeyRangeCache::const_iterator it) { return it->ToKey; } @@ -185,52 +185,52 @@ struct TTableItReverseOps { public: using TEraseCacheOpsCommon::TEraseCacheOpsCommon; - inline bool CrossedAtLeft( + inline bool CrossedAtLeft( TKeyRangeCache::const_iterator it, TArrayRef<const TCell> key) { - return !IsEnd(it) && Cache->InsideRight(it, key); + return !IsEnd(it) && Cache->InsideRight(it, key); + } + + inline bool CrossedAtRight( + TKeyRangeCache::const_iterator it, + TArrayRef<const TCell> key) + { + return !IsEnd(it) && Cache->InsideLeft(it, key); } - inline bool CrossedAtRight( - TKeyRangeCache::const_iterator it, - TArrayRef<const TCell> key) - { - return !IsEnd(it) && Cache->InsideLeft(it, key); - } - inline TKeyRangeCache::const_iterator MergeAdjacent( TKeyRangeCache::const_iterator prev, - TKeyRangeCache::const_iterator next, - TRowVersion version) + TKeyRangeCache::const_iterator next, + TRowVersion version) { - return Cache->Merge(next, prev, version); + return Cache->Merge(next, prev, version); } inline void ExtendForward( TKeyRangeCache::const_iterator it, TArrayRef<TCell> key, - bool inclusive, - TRowVersion version) + bool inclusive, + TRowVersion version) { - Cache->ExtendLeft(it, key, inclusive, version); + Cache->ExtendLeft(it, key, inclusive, version); } inline void ExtendBackward( TKeyRangeCache::const_iterator it, TArrayRef<TCell> key, - bool inclusive, - TRowVersion version) + bool inclusive, + TRowVersion version) { - Cache->ExtendRight(it, key, inclusive, version); + Cache->ExtendRight(it, key, inclusive, version); } inline void AddRange( TArrayRef<TCell> first, - TArrayRef<TCell> last, - TRowVersion version) + TArrayRef<TCell> last, + TRowVersion version) { - Cache->Add(TKeyRangeEntry(last, first, true, true, version)); + Cache->Add(TKeyRangeEntry(last, first, true, true, version)); } inline std::pair<TKeyRangeCache::const_iterator, bool> FindKey( @@ -247,10 +247,10 @@ struct TTableItReverseOps { return it; } - inline bool IsEnd(TKeyRangeCache::const_iterator it) { - return it == Cache->end(); - } - + inline bool IsEnd(TKeyRangeCache::const_iterator it) { + return it == Cache->end(); + } + static inline TArrayRef<const TCell> EndKey(TKeyRangeCache::const_iterator it) { return it->FromKey; } diff --git a/ydb/core/tablet_flat/flat_mem_iter.h b/ydb/core/tablet_flat/flat_mem_iter.h index 404239cf49..5d1c4fdf25 100644 --- a/ydb/core/tablet_flat/flat_mem_iter.h +++ b/ydb/core/tablet_flat/flat_mem_iter.h @@ -254,8 +254,8 @@ namespace NTable { } } - InvisibleRowSkips++; - + InvisibleRowSkips++; + while ((chain = chain->Next)) { if (chain->RowVersion.Step != Max<ui64>()) { if (chain->RowVersion <= rowVersion) { @@ -352,7 +352,7 @@ namespace NTable { const TIntrusiveConstPtr<TKeyNulls> Nulls; const TRemap* Remap = nullptr; IPages * const Env = nullptr; - ui64 InvisibleRowSkips = 0; + ui64 InvisibleRowSkips = 0; private: NMem::TTreeIterator RowIt; diff --git a/ydb/core/tablet_flat/flat_part_iter_multi.h b/ydb/core/tablet_flat/flat_part_iter_multi.h index 016514ef1c..b26d83b378 100644 --- a/ydb/core/tablet_flat/flat_part_iter_multi.h +++ b/ydb/core/tablet_flat/flat_part_iter_multi.h @@ -869,7 +869,7 @@ namespace NTable { return EReady::Data; } SkipEraseVersion = true; - InvisibleRowSkips++; + InvisibleRowSkips++; } TRowVersion current = data->IsVersioned() ? data->GetMinVersion(info) : Part->MinRowVersion; @@ -878,8 +878,8 @@ namespace NTable { return EReady::Data; } - InvisibleRowSkips++; - + InvisibleRowSkips++; + if (!data->HasHistory()) { // There is no history, reset SkipEraseVersion = false; @@ -1168,7 +1168,7 @@ namespace NTable { public: const TPart* const Part; IPages* const Env; - ui64 InvisibleRowSkips = 0; + ui64 InvisibleRowSkips = 0; private: const TPinout Pinout; @@ -1499,8 +1499,8 @@ namespace NTable { { Y_VERIFY_DEBUG(CurrentIt); auto ready = CurrentIt->SkipToRowVersion(rowVersion, committedTransactions); - InvisibleRowSkips += std::exchange(CurrentIt->InvisibleRowSkips, 0); - return ready; + InvisibleRowSkips += std::exchange(CurrentIt->InvisibleRowSkips, 0); + return ready; } bool IsDelta() const noexcept @@ -1584,7 +1584,7 @@ namespace NTable { TTagsRef const Tags; TIntrusiveConstPtr<TKeyNulls> const Nulls; IPages* const Env; - ui64 InvisibleRowSkips = 0; + ui64 InvisibleRowSkips = 0; private: TRun::const_iterator Current; diff --git a/ydb/core/tablet_flat/flat_range_cache.cpp b/ydb/core/tablet_flat/flat_range_cache.cpp index 255ef6eca4..dbac2c7981 100644 --- a/ydb/core/tablet_flat/flat_range_cache.cpp +++ b/ydb/core/tablet_flat/flat_range_cache.cpp @@ -78,37 +78,37 @@ void TKeyRangeCache::DeallocateKey(TArrayRef<TCell> key) { Pool->Deallocate((void*)key.data(), sizeof(TCell) * key.size()); } -void TKeyRangeCache::ExtendLeft(const_iterator it, TArrayRef<TCell> newLeft, bool leftInclusive, TRowVersion version) { +void TKeyRangeCache::ExtendLeft(const_iterator it, TArrayRef<TCell> newLeft, bool leftInclusive, TRowVersion version) { Y_VERIFY_DEBUG(it != end()); TKeyRangeEntryLRU& entry = const_cast<TKeyRangeEntryLRU&>(*it); DeallocateKey(entry.FromKey); entry.FromKey = newLeft; entry.FromInclusive = leftInclusive; - entry.MaxVersion = ::Max(entry.MaxVersion, version); + entry.MaxVersion = ::Max(entry.MaxVersion, version); } -void TKeyRangeCache::ExtendRight(const_iterator it, TArrayRef<TCell> newRight, bool rightInclusive, TRowVersion version) { +void TKeyRangeCache::ExtendRight(const_iterator it, TArrayRef<TCell> newRight, bool rightInclusive, TRowVersion version) { Y_VERIFY_DEBUG(it != end()); TKeyRangeEntryLRU& entry = const_cast<TKeyRangeEntryLRU&>(*it); DeallocateKey(entry.ToKey); entry.ToKey = newRight; entry.ToInclusive = rightInclusive; - entry.MaxVersion = ::Max(entry.MaxVersion, version); + entry.MaxVersion = ::Max(entry.MaxVersion, version); } -TKeyRangeCache::const_iterator TKeyRangeCache::Merge(const_iterator left, const_iterator right, TRowVersion version) { +TKeyRangeCache::const_iterator TKeyRangeCache::Merge(const_iterator left, const_iterator right, TRowVersion version) { Y_VERIFY_DEBUG(left != end()); Y_VERIFY_DEBUG(right != end()); Y_VERIFY_DEBUG(left != right); TKeyRangeEntry rightCopy = *right; Entries.erase(right); DeallocateKey(rightCopy.FromKey); - ExtendRight(left, rightCopy.ToKey, rightCopy.ToInclusive, ::Max(rightCopy.MaxVersion, version)); + ExtendRight(left, rightCopy.ToKey, rightCopy.ToInclusive, ::Max(rightCopy.MaxVersion, version)); return left; } TKeyRangeCache::const_iterator TKeyRangeCache::Add(TKeyRangeEntry entry) { - auto res = Entries.emplace(entry.FromKey, entry.ToKey, entry.FromInclusive, entry.ToInclusive, entry.MaxVersion); + auto res = Entries.emplace(entry.FromKey, entry.ToKey, entry.FromInclusive, entry.ToInclusive, entry.MaxVersion); Y_VERIFY_DEBUG(res.second); TKeyRangeEntryLRU& newEntry = const_cast<TKeyRangeEntryLRU&>(*res.first); Fresh.PushBack(&newEntry); diff --git a/ydb/core/tablet_flat/flat_range_cache.h b/ydb/core/tablet_flat/flat_range_cache.h index 63777400da..2005831095 100644 --- a/ydb/core/tablet_flat/flat_range_cache.h +++ b/ydb/core/tablet_flat/flat_range_cache.h @@ -23,16 +23,16 @@ struct TKeyRangeEntry { TArrayRef<TCell> ToKey; bool FromInclusive; bool ToInclusive; - TRowVersion MaxVersion; + TRowVersion MaxVersion; TKeyRangeEntry() = default; - TKeyRangeEntry(TArrayRef<TCell> fromKey, TArrayRef<TCell> toKey, bool fromInclusive, bool toInclusive, TRowVersion maxVersion) + TKeyRangeEntry(TArrayRef<TCell> fromKey, TArrayRef<TCell> toKey, bool fromInclusive, bool toInclusive, TRowVersion maxVersion) : FromKey(fromKey) , ToKey(toKey) , FromInclusive(fromInclusive) , ToInclusive(toInclusive) - , MaxVersion(maxVersion) + , MaxVersion(maxVersion) { } }; @@ -476,7 +476,7 @@ public: } else { --it; } - + bool found = it != end() && InsideRight(it, key); return { it, found }; } @@ -492,17 +492,17 @@ public: /** * Extends left side of the entry up to the specified key */ - void ExtendLeft(const_iterator it, TArrayRef<TCell> newLeft, bool leftInclusive, TRowVersion version); + void ExtendLeft(const_iterator it, TArrayRef<TCell> newLeft, bool leftInclusive, TRowVersion version); /** * Extends right side of the entry up to the specified key */ - void ExtendRight(const_iterator it, TArrayRef<TCell> newRight, bool rightInclusive, TRowVersion version); + void ExtendRight(const_iterator it, TArrayRef<TCell> newRight, bool rightInclusive, TRowVersion version); /** * Merges adjacent entries left and right */ - const_iterator Merge(const_iterator left, const_iterator right, TRowVersion version); + const_iterator Merge(const_iterator left, const_iterator right, TRowVersion version); /** * Adds a new entry with specified boundaries diff --git a/ydb/core/tablet_flat/flat_range_cache_ut.cpp b/ydb/core/tablet_flat/flat_range_cache_ut.cpp index aa6832bb35..b5211519d9 100644 --- a/ydb/core/tablet_flat/flat_range_cache_ut.cpp +++ b/ydb/core/tablet_flat/flat_range_cache_ut.cpp @@ -51,7 +51,7 @@ Y_UNIT_TEST_SUITE(TFlatEraseCacheTest) { // Empty default config TKeyRangeCache cache(*nulls, { }); // Empty keys, both inclusive - TKeyRangeEntry entry({ }, { }, true, true, TRowVersion::Min()); + TKeyRangeEntry entry({ }, { }, true, true, TRowVersion::Min()); // This will allocate a single node in the map cache.Add(entry); // This should be the size of that single node diff --git a/ydb/core/tablet_flat/flat_table.cpp b/ydb/core/tablet_flat/flat_table.cpp index 2abf4a2b5b..686a404268 100644 --- a/ydb/core/tablet_flat/flat_table.cpp +++ b/ydb/core/tablet_flat/flat_table.cpp @@ -707,7 +707,7 @@ TAutoPtr<TTableIt> TTable::Iterate(TRawVals key_, TTagsRef tags, IPages* env, ES } } - if (EraseCacheEnabled) { + if (EraseCacheEnabled) { if (!ErasedKeysCache) { ErasedKeysCache = new TKeyRangeCache(*Scheme->Keys, EraseCacheConfig); } @@ -745,7 +745,7 @@ TAutoPtr<TTableReverseIt> TTable::IterateReverse(TRawVals key_, TTagsRef tags, I } } - if (EraseCacheEnabled) { + if (EraseCacheEnabled) { if (!ErasedKeysCache) { ErasedKeysCache = new TKeyRangeCache(*Scheme->Keys, EraseCacheConfig); } @@ -788,7 +788,7 @@ TTable::TReady TTable::Select(TRawVals key_, TTagsRef tags, IPages* env, TRowSta snapshotFound = true; it->Apply(row, CommittedTransactions); } - result.Invisible += it->InvisibleRowSkips; + result.Invisible += it->InvisibleRowSkips; } } @@ -803,7 +803,7 @@ TTable::TReady TTable::Select(TRawVals key_, TTagsRef tags, IPages* env, TRowSta snapshotFound = true; it->Apply(row, CommittedTransactions); } - result.Invisible += it->InvisibleRowSkips; + result.Invisible += it->InvisibleRowSkips; } } @@ -826,7 +826,7 @@ TTable::TReady TTable::Select(TRawVals key_, TTagsRef tags, IPages* env, TRowSta lastEpoch = part->Epoch; if (!snapshotFound) { res = it.SkipToRowVersion(snapshot, CommittedTransactions); - result.Invisible += std::exchange(it.InvisibleRowSkips, 0); + result.Invisible += std::exchange(it.InvisibleRowSkips, 0); if (res == EReady::Data) { // N.B. stop looking for snapshot after the first hit snapshotFound = true; @@ -850,8 +850,8 @@ TTable::TReady TTable::Select(TRawVals key_, TTagsRef tags, IPages* env, TRowSta } } - Y_VERIFY_DEBUG(result.Invisible == 0 || !snapshot.IsMax()); - + Y_VERIFY_DEBUG(result.Invisible == 0 || !snapshot.IsMax()); + if (!ready || row.Need()) { result.Ready = EReady::Page; } else if (row == ERowOp::Erase || row == ERowOp::Absent) { diff --git a/ydb/core/tablet_flat/flat_table.h b/ydb/core/tablet_flat/flat_table.h index 5199576e34..a1fdeb9709 100644 --- a/ydb/core/tablet_flat/flat_table.h +++ b/ydb/core/tablet_flat/flat_table.h @@ -58,7 +58,7 @@ public: ui64 Weeded = 0; ui64 Sieved = 0; ui64 NoKey = 0; /* Examined TPart without the key */ - ui64 Invisible = 0; /* Skipped invisible versions */ + ui64 Invisible = 0; /* Skipped invisible versions */ }; explicit TTable(TEpoch); diff --git a/ydb/core/tablet_flat/flat_table_stats.h b/ydb/core/tablet_flat/flat_table_stats.h index 5e534ea7a6..5b600dcf13 100644 --- a/ydb/core/tablet_flat/flat_table_stats.h +++ b/ydb/core/tablet_flat/flat_table_stats.h @@ -31,13 +31,13 @@ namespace NTable { TPartStats& operator-=(const TPartStats& rhs); }; - struct TSelectStats { - ui64 Sieved = 0; - ui64 Weeded = 0; - ui64 NoKey = 0; - ui64 Invisible = 0; - }; - + struct TSelectStats { + ui64 Sieved = 0; + ui64 Weeded = 0; + ui64 NoKey = 0; + ui64 Invisible = 0; + }; + struct TCompactionStats { THashSet<ui64> PartOwners; ui64 PartCount = 0; diff --git a/ydb/core/testlib/tenant_runtime.cpp b/ydb/core/testlib/tenant_runtime.cpp index 3c15c20afa..974cc166d0 100644 --- a/ydb/core/testlib/tenant_runtime.cpp +++ b/ydb/core/testlib/tenant_runtime.cpp @@ -784,7 +784,7 @@ void TTenantTestRuntime::Setup(bool createTenantPools) SetLogPriority(NKikimrServices::CMS_CONFIGS, NLog::PRI_TRACE); SetLogPriority(NKikimrServices::CMS_TENANTS, NLog::PRI_TRACE); SetLogPriority(NKikimrServices::CONFIGS_DISPATCHER, NLog::PRI_TRACE); - SetLogPriority(NKikimrServices::CONFIGS_CACHE, NLog::PRI_TRACE); + SetLogPriority(NKikimrServices::CONFIGS_CACHE, NLog::PRI_TRACE); SetLogPriority(NKikimrServices::HIVE, NLog::PRI_DEBUG); SetLogPriority(NKikimrServices::BS_CONTROLLER, NLog::PRI_DEBUG); SetLogPriority(NKikimrServices::FLAT_TX_SCHEMESHARD, NLog::PRI_DEBUG); diff --git a/ydb/core/testlib/test_client.cpp b/ydb/core/testlib/test_client.cpp index 2823be52d7..d4907c26f1 100644 --- a/ydb/core/testlib/test_client.cpp +++ b/ydb/core/testlib/test_client.cpp @@ -160,7 +160,7 @@ namespace Tests { TAppPrepare app; /* will cook TAppData */ app.SetNetDataSourceUrl(Settings->NetClassifierConfig.GetUpdaterConfig().GetNetDataSourceUrl()); app.SetEnableKqpSpilling(Settings->EnableKqpSpilling); - app.SetKeepSnapshotTimeout(Settings->KeepSnapshotTimeout); + app.SetKeepSnapshotTimeout(Settings->KeepSnapshotTimeout); app.SetChangesQueueItemsLimit(Settings->ChangesQueueItemsLimit); app.SetChangesQueueBytesLimit(Settings->ChangesQueueBytesLimit); app.CompactionConfig = Settings->CompactionConfig; diff --git a/ydb/core/testlib/test_client.h b/ydb/core/testlib/test_client.h index a1ab4d4a9a..2064752ab4 100644 --- a/ydb/core/testlib/test_client.h +++ b/ydb/core/testlib/test_client.h @@ -113,7 +113,7 @@ namespace Tests { bool UseRealThreads = true; bool EnableKqpSpilling = false; bool EnableYq = false; - TDuration KeepSnapshotTimeout = TDuration::Zero(); + TDuration KeepSnapshotTimeout = TDuration::Zero(); ui64 ChangesQueueItemsLimit = 0; ui64 ChangesQueueBytesLimit = 0; NKikimrConfig::TAppConfig AppConfig; @@ -155,7 +155,7 @@ namespace Tests { TServerSettings& SetCompactionConfig(const NKikimrConfig::TCompactionConfig& value) { CompactionConfig = value; return *this; } TServerSettings& SetEnableDbCounters(bool value) { FeatureFlags.SetEnableDbCounters(value); return *this; } TServerSettings& SetEnableYq(bool value) { EnableYq = value; return *this; } - TServerSettings& SetKeepSnapshotTimeout(TDuration value) { KeepSnapshotTimeout = value; return *this; } + TServerSettings& SetKeepSnapshotTimeout(TDuration value) { KeepSnapshotTimeout = value; return *this; } TServerSettings& SetChangesQueueItemsLimit(ui64 value) { ChangesQueueItemsLimit = value; return *this; } TServerSettings& SetChangesQueueBytesLimit(ui64 value) { ChangesQueueBytesLimit = value; return *this; } TServerSettings& SetMeteringFilePath(const TString& path) { EnableMetering = true; MeteringFilePath = path; return *this; } diff --git a/ydb/core/tx/datashard/alter_table_unit.cpp b/ydb/core/tx/datashard/alter_table_unit.cpp index 3a24d77286..78786adae7 100644 --- a/ydb/core/tx/datashard/alter_table_unit.cpp +++ b/ydb/core/tx/datashard/alter_table_unit.cpp @@ -147,7 +147,7 @@ EExecutionStatus TAlterTableUnit::Execute(TOperation::TPtr op, tableId.LocalPathId = pathId.GetLocalId(); } - TUserTable::TPtr info = DataShard.AlterUserTable(ctx, txc, alterTableTx); + TUserTable::TPtr info = DataShard.AlterUserTable(ctx, txc, alterTableTx); DataShard.AddUserTable(tableId, info); diff --git a/ydb/core/tx/datashard/build_and_wait_dependencies_unit.cpp b/ydb/core/tx/datashard/build_and_wait_dependencies_unit.cpp index 6a9d8e89ae..7eb786866a 100644 --- a/ydb/core/tx/datashard/build_and_wait_dependencies_unit.cpp +++ b/ydb/core/tx/datashard/build_and_wait_dependencies_unit.cpp @@ -49,7 +49,7 @@ bool TBuildAndWaitDependenciesUnit::IsReadyToExecute(TOperation::TPtr op) const { // Dependencies were not built yet. Allow to execute to build dependencies. if (!op->IsWaitingDependencies()) - return true; + return true; // Perform fast checks for existing blockers if (HasDirectBlockers(op)) @@ -129,8 +129,8 @@ EExecutionStatus TBuildAndWaitDependenciesUnit::Execute(TOperation::TPtr op, if (hadWrites) { return EExecutionStatus::ExecutedNoMoreRestarts; } - } - + } + return EExecutionStatus::Executed; } @@ -144,7 +144,7 @@ void TBuildAndWaitDependenciesUnit::BuildDependencies(const TOperation::TPtr &op // don't preserve schema, so dropping columns or tables is unsafe until // they are completed. if (op->IsSchemeTx() && !op->IsReadOnly()) { - auto *tx = dynamic_cast<TActiveTransaction*>(op.Get()); + auto *tx = dynamic_cast<TActiveTransaction*>(op.Get()); Y_VERIFY_S(tx, "cannot cast operation of kind " << op->GetKind()); for (const auto &pr : Pipeline.GetActivePlannedOps()) { @@ -158,7 +158,7 @@ void TBuildAndWaitDependenciesUnit::BuildDependencies(const TOperation::TPtr &op // For DropTable we must also wait for all immediate operations to complete auto &schemeTx = tx->GetSchemeTx(); - if (schemeTx.HasDropTable()) { + if (schemeTx.HasDropTable()) { for (const auto &pr : Pipeline.GetImmediateOps()) { op->AddSpecialDependency(pr.second); } diff --git a/ydb/core/tx/datashard/build_data_tx_out_rs_unit.cpp b/ydb/core/tx/datashard/build_data_tx_out_rs_unit.cpp index c78b3beb3f..cd8d3dab69 100644 --- a/ydb/core/tx/datashard/build_data_tx_out_rs_unit.cpp +++ b/ydb/core/tx/datashard/build_data_tx_out_rs_unit.cpp @@ -60,7 +60,7 @@ EExecutionStatus TBuildDataTxOutRSUnit::Execute(TOperation::TPtr op, } } - tx->GetDataTx()->SetReadVersion(DataShard.GetReadWriteVersions(tx).ReadVersion); + tx->GetDataTx()->SetReadVersion(DataShard.GetReadWriteVersions(tx).ReadVersion); IEngineFlat *engine = tx->GetDataTx()->GetEngine(); try { auto &outReadSets = op->OutReadSets(); diff --git a/ydb/core/tx/datashard/build_kqp_data_tx_out_rs_unit.cpp b/ydb/core/tx/datashard/build_kqp_data_tx_out_rs_unit.cpp index cc24770c0b..50a3c1f401 100644 --- a/ydb/core/tx/datashard/build_kqp_data_tx_out_rs_unit.cpp +++ b/ydb/core/tx/datashard/build_kqp_data_tx_out_rs_unit.cpp @@ -92,7 +92,7 @@ EExecutionStatus TBuildKqpDataTxOutRSUnit::Execute(TOperation::TPtr op, TTransac LOG_T("Operation " << *op << " (build_kqp_data_tx_out_rs) at " << tabletId << " set memory limit " << (txc.GetMemoryLimit() - dataTx->GetTxSize())); - dataTx->SetReadVersion(DataShard.GetReadWriteVersions(tx).ReadVersion); + dataTx->SetReadVersion(DataShard.GetReadWriteVersions(tx).ReadVersion); if (dataTx->GetKqpComputeCtx().HasPersistentChannels()) { auto result = KqpRunTransaction(ctx, op->GetTxId(), dataTx->GetKqpTasks(), tasksRunner); diff --git a/ydb/core/tx/datashard/build_scheme_tx_out_rs_unit.cpp b/ydb/core/tx/datashard/build_scheme_tx_out_rs_unit.cpp index c4fc1d4f24..7f63253157 100644 --- a/ydb/core/tx/datashard/build_scheme_tx_out_rs_unit.cpp +++ b/ydb/core/tx/datashard/build_scheme_tx_out_rs_unit.cpp @@ -72,17 +72,17 @@ EExecutionStatus TBuildSchemeTxOutRSUnit::Execute(TOperation::TPtr op, bool extended = false; const bool mvcc = DataShard.IsMvccEnabled(); - - TRowVersion minVersion = mvcc ? TRowVersion(op->GetStep(), op->GetTxId()).Next() - : DataShard.GetSnapshotManager().GetMinWriteVersion(); - TRowVersion completeEdge = mvcc ? DataShard.GetSnapshotManager().GetCompleteEdge() - : TRowVersion::Min(); - TRowVersion incompleteEdge = mvcc ? DataShard.GetSnapshotManager().GetIncompleteEdge() - : TRowVersion::Min(); - TRowVersion lowWatermark = mvcc ? DataShard.GetSnapshotManager().GetLowWatermark() : - TRowVersion::Min(); - - if (minVersion || completeEdge || incompleteEdge || lowWatermark) + + TRowVersion minVersion = mvcc ? TRowVersion(op->GetStep(), op->GetTxId()).Next() + : DataShard.GetSnapshotManager().GetMinWriteVersion(); + TRowVersion completeEdge = mvcc ? DataShard.GetSnapshotManager().GetCompleteEdge() + : TRowVersion::Min(); + TRowVersion incompleteEdge = mvcc ? DataShard.GetSnapshotManager().GetIncompleteEdge() + : TRowVersion::Min(); + TRowVersion lowWatermark = mvcc ? DataShard.GetSnapshotManager().GetLowWatermark() : + TRowVersion::Min(); + + if (minVersion || completeEdge || incompleteEdge || lowWatermark) extended = true; // Must use an extended format if (extended) { @@ -95,26 +95,26 @@ EExecutionStatus TBuildSchemeTxOutRSUnit::Execute(TOperation::TPtr op, // TODO: make it possible to send multiple tables rs.SetBorrowedSnapshot(compressedBody); - if (minVersion) { - rs.SetMinWriteVersionStep(minVersion.Step); - rs.SetMinWriteVersionTxId(minVersion.TxId); - } - - if (completeEdge) { - rs.SetMvccCompleteEdgeStep(completeEdge.Step); - rs.SetMvccCompleteEdgeTxId(completeEdge.TxId); - } - - if (incompleteEdge) { - rs.SetMvccIncompleteEdgeStep(incompleteEdge.Step); - rs.SetMvccIncompleteEdgeTxId(incompleteEdge.TxId); - } - - if (lowWatermark) { - rs.SetMvccLowWatermarkStep(lowWatermark.Step); - rs.SetMvccLowWatermarkTxId(lowWatermark.TxId); - } - + if (minVersion) { + rs.SetMinWriteVersionStep(minVersion.Step); + rs.SetMinWriteVersionTxId(minVersion.TxId); + } + + if (completeEdge) { + rs.SetMvccCompleteEdgeStep(completeEdge.Step); + rs.SetMvccCompleteEdgeTxId(completeEdge.TxId); + } + + if (incompleteEdge) { + rs.SetMvccIncompleteEdgeStep(incompleteEdge.Step); + rs.SetMvccIncompleteEdgeTxId(incompleteEdge.TxId); + } + + if (lowWatermark) { + rs.SetMvccLowWatermarkStep(lowWatermark.Step); + rs.SetMvccLowWatermarkTxId(lowWatermark.TxId); + } + rsBody.reserve(SnapshotTransferReadSetMagic.size() + rs.ByteSizeLong()); rsBody.append(SnapshotTransferReadSetMagic); Y_PROTOBUF_SUPPRESS_NODISCARD rs.AppendToString(&rsBody); diff --git a/ydb/core/tx/datashard/check_data_tx_unit.cpp b/ydb/core/tx/datashard/check_data_tx_unit.cpp index c395ee3168..deb9f1f903 100644 --- a/ydb/core/tx/datashard/check_data_tx_unit.cpp +++ b/ydb/core/tx/datashard/check_data_tx_unit.cpp @@ -84,35 +84,35 @@ EExecutionStatus TCheckDataTxUnit::Execute(TOperation::TPtr op, return EExecutionStatus::Executed; } - if (tx->IsMvccSnapshotRead()) { - auto snapshot = tx->GetMvccSnapshot(); + if (tx->IsMvccSnapshotRead()) { + auto snapshot = tx->GetMvccSnapshot(); if (!DataShard.IsMvccEnabled()) { - TString err = TStringBuilder() - << "Operation " << *op << " reads from snapshot " << snapshot - << " with MVCC feature disabled at " << DataShard.TabletID(); - - BuildResult(op, NKikimrTxDataShard::TEvProposeTransactionResult::BAD_REQUEST) - ->AddError(NKikimrTxDataShard::TError::BAD_ARGUMENT, err); - op->Abort(EExecutionUnitKind::FinishPropose); - - LOG_ERROR_S(ctx, NKikimrServices::TX_DATASHARD, err); - - return EExecutionStatus::Executed; - } else if (snapshot < DataShard.GetSnapshotManager().GetLowWatermark()) { - TString err = TStringBuilder() - << "Operation " << *op << " reads from stale snapshot " << snapshot - << " at " << DataShard.TabletID(); - - BuildResult(op, NKikimrTxDataShard::TEvProposeTransactionResult::BAD_REQUEST) - ->AddError(NKikimrTxDataShard::TError::BAD_ARGUMENT, err); - op->Abort(EExecutionUnitKind::FinishPropose); - - LOG_ERROR_S(ctx, NKikimrServices::TX_DATASHARD, err); - - return EExecutionStatus::Executed; - } - } - + TString err = TStringBuilder() + << "Operation " << *op << " reads from snapshot " << snapshot + << " with MVCC feature disabled at " << DataShard.TabletID(); + + BuildResult(op, NKikimrTxDataShard::TEvProposeTransactionResult::BAD_REQUEST) + ->AddError(NKikimrTxDataShard::TError::BAD_ARGUMENT, err); + op->Abort(EExecutionUnitKind::FinishPropose); + + LOG_ERROR_S(ctx, NKikimrServices::TX_DATASHARD, err); + + return EExecutionStatus::Executed; + } else if (snapshot < DataShard.GetSnapshotManager().GetLowWatermark()) { + TString err = TStringBuilder() + << "Operation " << *op << " reads from stale snapshot " << snapshot + << " at " << DataShard.TabletID(); + + BuildResult(op, NKikimrTxDataShard::TEvProposeTransactionResult::BAD_REQUEST) + ->AddError(NKikimrTxDataShard::TError::BAD_ARGUMENT, err); + op->Abort(EExecutionUnitKind::FinishPropose); + + LOG_ERROR_S(ctx, NKikimrServices::TX_DATASHARD, err); + + return EExecutionStatus::Executed; + } + } + TEngineBay::TSizes txReads; if (op->IsDataTx()) { diff --git a/ydb/core/tx/datashard/complete_data_tx_unit.cpp b/ydb/core/tx/datashard/complete_data_tx_unit.cpp index 5967559d7b..c086fa7011 100644 --- a/ydb/core/tx/datashard/complete_data_tx_unit.cpp +++ b/ydb/core/tx/datashard/complete_data_tx_unit.cpp @@ -106,7 +106,7 @@ void TCompleteOperationUnit::CompleteOperation(TOperation::TPtr op, void TCompleteOperationUnit::Complete(TOperation::TPtr op, const TActorContext &ctx) { - Pipeline.RemoveCommittingOp(op); + Pipeline.RemoveCommittingOp(op); Pipeline.RemoveTx(op->GetStepOrder()); DataShard.IncCounter(COUNTER_PLANNED_TX_COMPLETE); if (!op->IsDirty()) diff --git a/ydb/core/tx/datashard/create_table_unit.cpp b/ydb/core/tx/datashard/create_table_unit.cpp index 2234317139..85f38d456a 100644 --- a/ydb/core/tx/datashard/create_table_unit.cpp +++ b/ydb/core/tx/datashard/create_table_unit.cpp @@ -63,7 +63,7 @@ EExecutionStatus TCreateTableUnit::Execute(TOperation::TPtr op, << " tableId# " << tableId << " schema version# " << schemaVersion); - TUserTable::TPtr info = DataShard.CreateUserTable(txc, schemeTx.GetCreateTable()); + TUserTable::TPtr info = DataShard.CreateUserTable(txc, schemeTx.GetCreateTable()); DataShard.AddUserTable(tableId, info); for (const auto& [indexPathId, indexInfo] : info->Indexes) { @@ -80,7 +80,7 @@ EExecutionStatus TCreateTableUnit::Execute(TOperation::TPtr op, if (DataShard.GetState() == TShardState::WaitScheme) { txc.DB.NoMoreReadsForTx(); DataShard.SetPersistState(TShardState::Ready, txc); - DataShard.CheckMvccStateChangeCanStart(ctx); // Recheck + DataShard.CheckMvccStateChangeCanStart(ctx); // Recheck } return EExecutionStatus::DelayCompleteNoMoreRestarts; diff --git a/ydb/core/tx/datashard/create_volatile_snapshot_unit.cpp b/ydb/core/tx/datashard/create_volatile_snapshot_unit.cpp index 1131f1a0fe..9de1520481 100644 --- a/ydb/core/tx/datashard/create_volatile_snapshot_unit.cpp +++ b/ydb/core/tx/datashard/create_volatile_snapshot_unit.cpp @@ -50,8 +50,8 @@ public: op->Result()->SetStepOrderId(op->GetStepOrder().ToPair()); if (added) { - DataShard.GetSnapshotManager().InitSnapshotExpireTime(key, ctx.Now()); - if (DataShard.GetSnapshotManager().HasExpiringSnapshots()) + DataShard.GetSnapshotManager().InitSnapshotExpireTime(key, ctx.Now()); + if (DataShard.GetSnapshotManager().HasExpiringSnapshots()) DataShard.PlanCleanup(ctx); return EExecutionStatus::ExecutedNoMoreRestarts; diff --git a/ydb/core/tx/datashard/datashard.cpp b/ydb/core/tx/datashard/datashard.cpp index 9e1229c7d0..d86568b4a1 100644 --- a/ydb/core/tx/datashard/datashard.cpp +++ b/ydb/core/tx/datashard/datashard.cpp @@ -56,25 +56,25 @@ public: } // Write user tables with a minimal safe version (avoiding snapshots) - return Self->GetLocalReadWriteVersions().WriteVersion; + return Self->GetLocalReadWriteVersions().WriteVersion; } - TRowVersion GetReadVersion(const TTableId& tableId) const override { + TRowVersion GetReadVersion(const TTableId& tableId) const override { using Schema = TDataShard::Schema; - - Y_VERIFY_S(tableId.PathId.OwnerId == Self->TabletID(), - "Unexpected table " << tableId.PathId.OwnerId << ":" << tableId.PathId.LocalPathId - << " for datashard " << Self->TabletID() - << " in a local minikql tx"); - - if (tableId.PathId.LocalPathId < Schema::MinLocalTid) { - // System tables are not versioned - return TRowVersion::Max(); - } - - return Self->GetLocalReadWriteVersions().ReadVersion; - } - + + Y_VERIFY_S(tableId.PathId.OwnerId == Self->TabletID(), + "Unexpected table " << tableId.PathId.OwnerId << ":" << tableId.PathId.LocalPathId + << " for datashard " << Self->TabletID() + << " in a local minikql tx"); + + if (tableId.PathId.LocalPathId < Schema::MinLocalTid) { + // System tables are not versioned + return TRowVersion::Max(); + } + + return Self->GetLocalReadWriteVersions().ReadVersion; + } + private: TDataShard* const Self; }; @@ -103,7 +103,7 @@ TDataShard::TDataShard(const TActorId &tablet, TTabletStorageInfo *info) , LastKnownMediator(INVALID_TABLET_ID) , RegistrationSended(false) , LoanReturnTracker(info->TabletID) - , MvccSwitchState(TSwitchState::READY) + , MvccSwitchState(TSwitchState::READY) , SplitSnapshotStarted(false) , SplitSrcSnapshotSender(this) , DstSplitOpId(0) @@ -843,9 +843,9 @@ TUserTable::TPtr TDataShard::CreateUserTable(TTransactionContext& txc, Pipeline.UpdateConfig(db, partConfig.GetPipelineConfig()); - if (partConfig.HasKeepSnapshotTimeout()) - SnapshotManager.SetKeepSnapshotTimeout(db, partConfig.GetKeepSnapshotTimeout()); - + if (partConfig.HasKeepSnapshotTimeout()) + SnapshotManager.SetKeepSnapshotTimeout(db, partConfig.GetKeepSnapshotTimeout()); + PersistSys(db, Schema::Sys_LastLocalTid, LastLocalTid); PersistUserTable(db, tableId, *tableInfo); @@ -958,9 +958,9 @@ TUserTable::TPtr TDataShard::AlterUserTable(const TActorContext& ctx, TTransacti } tableInfo->SetSchema(tableDescr); - - if (configDelta.HasKeepSnapshotTimeout()) - SnapshotManager.SetKeepSnapshotTimeout(db, configDelta.GetKeepSnapshotTimeout()); + + if (configDelta.HasKeepSnapshotTimeout()) + SnapshotManager.SetKeepSnapshotTimeout(db, configDelta.GetKeepSnapshotTimeout()); } PersistUserTable(db, tableId, *tableInfo); @@ -1193,15 +1193,15 @@ bool TDataShard::IsMvccEnabled() const { TReadWriteVersions TDataShard::GetLocalReadWriteVersions() const { if (!IsMvccEnabled()) - return {TRowVersion::Max(), SnapshotManager.GetMinWriteVersion()}; - - TRowVersion edge = Max(SnapshotManager.GetCompleteEdge(), SnapshotManager.GetIncompleteEdge()); - if (auto nextOp = Pipeline.GetNextPlannedOp(edge.Step, edge.TxId)) - return TRowVersion(nextOp->GetStep(), nextOp->GetTxId()); - - return TRowVersion((++edge).Step, ::Max<ui64>()); -} - + return {TRowVersion::Max(), SnapshotManager.GetMinWriteVersion()}; + + TRowVersion edge = Max(SnapshotManager.GetCompleteEdge(), SnapshotManager.GetIncompleteEdge()); + if (auto nextOp = Pipeline.GetNextPlannedOp(edge.Step, edge.TxId)) + return TRowVersion(nextOp->GetStep(), nextOp->GetTxId()); + + return TRowVersion((++edge).Step, ::Max<ui64>()); +} + TRowVersion TDataShard::GetMvccTxVersion(EMvccTxMode mode, TOperation* op) const { Y_VERIFY_DEBUG(IsMvccEnabled()); @@ -1209,12 +1209,12 @@ TRowVersion TDataShard::GetMvccTxVersion(EMvccTxMode mode, TOperation* op) const if (op->IsMvccSnapshotRead()) { return op->GetMvccSnapshot(); } - + if (op->GetStep()) { return TRowVersion(op->GetStep(), op->GetTxId()); } } - + TRowVersion edge; TRowVersion readEdge = SnapshotManager.GetCompleteEdge(); TRowVersion writeEdge = Max(readEdge, SnapshotManager.GetIncompleteEdge()); @@ -1233,21 +1233,21 @@ TRowVersion TDataShard::GetMvccTxVersion(EMvccTxMode mode, TOperation* op) const edge = writeEdge; break; } - + // If there's any planned operation that is above our edge, it would be a // suitable version for a new immediate operation. We effectively try to // execute "before" that point if possible. - if (auto nextOp = Pipeline.GetNextPlannedOp(edge.Step, edge.TxId)) - return TRowVersion(nextOp->GetStep(), nextOp->GetTxId()); - + if (auto nextOp = Pipeline.GetNextPlannedOp(edge.Step, edge.TxId)) + return TRowVersion(nextOp->GetStep(), nextOp->GetTxId()); + // This is currently active step for immediate writes, not that when // writeEdge is equal to some (PlanStep, Max<ui64>()) that means everything // up to this point is "fixed" and cannot be changed. In that case we // choose at least PlanStep + 1 for new writes. ui64 writeStep = Max(MediatorTimeCastEntry ? MediatorTimeCastEntry->Get(TabletID()) : 0, (++writeEdge).Step); - return TRowVersion(writeStep, ::Max<ui64>()); -} - + return TRowVersion(writeStep, ::Max<ui64>()); +} + TReadWriteVersions TDataShard::GetReadWriteVersions(TOperation* op) const { if (!IsMvccEnabled()) return {TRowVersion::Max(), SnapshotManager.GetMinWriteVersion()}; @@ -1385,11 +1385,11 @@ bool TDataShard::CheckDataTxReject(const TString& opDescr, reject = true; rejectStatus = NKikimrTxDataShard::TEvProposeTransactionResult::ERROR; rejectReasons.push_back("is in a pre/offline state assuming this is due to a finished split (wrong shard state)"); - } else if (MvccSwitchState == TSwitchState::SWITCHING) { - reject = true; - rejectReasons.push_back(TStringBuilder() - << "is in process of mvcc state change" - << " state " << DatashardStateName(State)); + } else if (MvccSwitchState == TSwitchState::SWITCHING) { + reject = true; + rejectReasons.push_back(TStringBuilder() + << "is in process of mvcc state change" + << " state " << DatashardStateName(State)); } if (Pipeline.HasDrop()) { @@ -1415,7 +1415,7 @@ bool TDataShard::CheckDataTxReject(const TString& opDescr, rejectReasons.push_back("decided to reject due to given RejectProbability"); } - size_t totalInFly = (TxInFly() + ImmediateInFly() + ProposeQueue.Size() + TxWaiting()); + size_t totalInFly = (TxInFly() + ImmediateInFly() + ProposeQueue.Size() + TxWaiting()); if (totalInFly > GetMaxTxInFly()) { reject = true; rejectReasons.push_back("MaxTxInFly was exceeded"); @@ -1498,15 +1498,15 @@ void TDataShard::Handle(TEvDataShard::TEvProposeTransaction::TPtr &ev, const TAc return; } - if (CheckTxNeedWait(ev)) { - LOG_DEBUG_S(ctx, NKikimrServices::TX_DATASHARD, - "Handle TEvProposeTransaction delayed at " << TabletID() << " until interesting plan step will come"); - if (Pipeline.AddWaitingTxOp(ev, ctx)) { + if (CheckTxNeedWait(ev)) { + LOG_DEBUG_S(ctx, NKikimrServices::TX_DATASHARD, + "Handle TEvProposeTransaction delayed at " << TabletID() << " until interesting plan step will come"); + if (Pipeline.AddWaitingTxOp(ev, ctx)) { UpdateProposeQueueSize(); - return; - } - } - + return; + } + } + IncCounter(COUNTER_PREPARE_REQUEST); if (CheckDataTxRejectAndReply(ev->Get(), ctx)) { @@ -1901,51 +1901,51 @@ void TDataShard::Handle(TEvMediatorTimecast::TEvRegisterTabletResult::TPtr& ev, Y_VERIFY(ev->Get()->TabletId == TabletID()); MediatorTimeCastEntry = ev->Get()->Entry; Y_VERIFY(MediatorTimeCastEntry); - - Pipeline.ActivateWaitingTxOps(ctx); + + Pipeline.ActivateWaitingTxOps(ctx); } void TDataShard::Handle(TEvMediatorTimecast::TEvNotifyPlanStep::TPtr& ev, const TActorContext& ctx) { - const auto* msg = ev->Get(); - Y_VERIFY(msg->TabletId == TabletID()); - - Y_VERIFY(MediatorTimeCastEntry); - ui64 step = MediatorTimeCastEntry->Get(TabletID()); - LOG_DEBUG_S(ctx, NKikimrServices::TX_DATASHARD, "Notified by mediator time cast with PlanStep# " << step << " at tablet " << TabletID()); - - for (auto it = MediatorTimeCastWaitingSteps.begin(); it != MediatorTimeCastWaitingSteps.end() && *it <= step;) - it = MediatorTimeCastWaitingSteps.erase(it); - - Pipeline.ActivateWaitingTxOps(ctx); -} - + const auto* msg = ev->Get(); + Y_VERIFY(msg->TabletId == TabletID()); + + Y_VERIFY(MediatorTimeCastEntry); + ui64 step = MediatorTimeCastEntry->Get(TabletID()); + LOG_DEBUG_S(ctx, NKikimrServices::TX_DATASHARD, "Notified by mediator time cast with PlanStep# " << step << " at tablet " << TabletID()); + + for (auto it = MediatorTimeCastWaitingSteps.begin(); it != MediatorTimeCastWaitingSteps.end() && *it <= step;) + it = MediatorTimeCastWaitingSteps.erase(it); + + Pipeline.ActivateWaitingTxOps(ctx); +} + bool TDataShard::WaitPlanStep(ui64 step) { - if (step <= Pipeline.GetLastPlannedTx().Step) - return false; - - if (MediatorTimeCastEntry && step <= MediatorTimeCastEntry->Get(TabletID())) - return false; - - if (!RegistrationSended) - return false; - - if (MediatorTimeCastWaitingSteps.empty() || step < *MediatorTimeCastWaitingSteps.begin()) { - MediatorTimeCastWaitingSteps.insert(step); - Send(MakeMediatorTimecastProxyID(), new TEvMediatorTimecast::TEvWaitPlanStep(TabletID(), step)); - LOG_DEBUG_S(*TlsActivationContext, NKikimrServices::TX_DATASHARD, "Waiting for PlanStep# " << step << " from mediator time cast"); - return true; - } - - return false; -} - + if (step <= Pipeline.GetLastPlannedTx().Step) + return false; + + if (MediatorTimeCastEntry && step <= MediatorTimeCastEntry->Get(TabletID())) + return false; + + if (!RegistrationSended) + return false; + + if (MediatorTimeCastWaitingSteps.empty() || step < *MediatorTimeCastWaitingSteps.begin()) { + MediatorTimeCastWaitingSteps.insert(step); + Send(MakeMediatorTimecastProxyID(), new TEvMediatorTimecast::TEvWaitPlanStep(TabletID(), step)); + LOG_DEBUG_S(*TlsActivationContext, NKikimrServices::TX_DATASHARD, "Waiting for PlanStep# " << step << " from mediator time cast"); + return true; + } + + return false; +} + bool TDataShard::CheckTxNeedWait(const TEvDataShard::TEvProposeTransaction::TPtr& ev) const { if (MvccSwitchState == TSwitchState::SWITCHING) { LOG_TRACE_S(*TlsActivationContext, NKikimrServices::TX_DATASHARD, "New transaction needs to wait because of mvcc state switching"); - return true; + return true; } - - auto &rec = ev->Get()->Record; + + auto &rec = ev->Get()->Record; if (rec.HasMvccSnapshot()) { TRowVersion rowVersion(rec.GetMvccSnapshot().GetStep(), rec.GetMvccSnapshot().GetTxId()); TRowVersion unreadableEdge = Pipeline.GetUnreadableEdge(); @@ -1956,8 +1956,8 @@ bool TDataShard::CheckTxNeedWait(const TEvDataShard::TEvProposeTransaction::TPtr } return false; -} - +} + bool TDataShard::CheckChangesQueueOverflow() const { const auto* appData = AppData(); const auto sizeLimit = appData->DataShardConfig.GetChangesQueueItemsLimit(); @@ -2591,7 +2591,7 @@ void TDataShard::ExecuteProgressTx(TOperation::TPtr op, const TActorContext& ctx TDuration TDataShard::CleanupTimeout() const { const TDuration pipelineTimeout = Pipeline.CleanupTimeout(); - const TDuration snapshotTimeout = SnapshotManager.CleanupTimeout(); + const TDuration snapshotTimeout = SnapshotManager.CleanupTimeout(); const TDuration minTimeout = TDuration::Seconds(1); const TDuration maxTimeout = TDuration::MilliSeconds(DefaultTxStepDeadline() / 2); return Max(minTimeout, Min(pipelineTimeout, snapshotTimeout, maxTimeout)); diff --git a/ydb/core/tx/datashard/datashard.h b/ydb/core/tx/datashard/datashard.h index 5d5a8a708c..5a93c03502 100644 --- a/ydb/core/tx/datashard/datashard.h +++ b/ydb/core/tx/datashard/datashard.h @@ -114,10 +114,10 @@ namespace NDataShard { Stored = 1ULL << 42, // Operation is waiting for async job to finish WaitingForAsyncJob = 1ULL << 43, - // Operation must complete before results sending - WaitCompletion = 1ULL << 44, + // Operation must complete before results sending + WaitCompletion = 1ULL << 44, - LastFlag = WaitCompletion, + LastFlag = WaitCompletion, PrivateFlagsMask = 0xFFFFFFFFFFFF0000ULL, PreservedPrivateFlagsMask = ReadOnly | ProposeBlocker | NeedDiagnostics | GlobalReader @@ -416,21 +416,21 @@ struct TEvDataShard { Record.SetFlags(flags); } - TEvProposeTransaction(NKikimrTxDataShard::ETransactionKind txKind, const TActorId& source, ui64 txId, + TEvProposeTransaction(NKikimrTxDataShard::ETransactionKind txKind, const TActorId& source, ui64 txId, const TStringBuf& txBody, ui64 snapshotStep, ui64 snapshotTxId, ui32 flags = NDataShard::TTxFlags::Default) - : TEvProposeTransaction(txKind, source, txId, txBody, flags) - { - auto &snapshot = *Record.MutableMvccSnapshot(); - snapshot.SetStep(snapshotStep); - snapshot.SetTxId(snapshotTxId); - } - - TEvProposeTransaction(NKikimrTxDataShard::ETransactionKind txKind, const TActorId& source, ui64 txId, + : TEvProposeTransaction(txKind, source, txId, txBody, flags) + { + auto &snapshot = *Record.MutableMvccSnapshot(); + snapshot.SetStep(snapshotStep); + snapshot.SetTxId(snapshotTxId); + } + + TEvProposeTransaction(NKikimrTxDataShard::ETransactionKind txKind, const TActorId& source, ui64 txId, const TStringBuf& txBody, const TRowVersion& snapshot, ui32 flags = NDataShard::TTxFlags::Default) - : TEvProposeTransaction(txKind, source, txId, txBody, snapshot.Step, snapshot.TxId, flags) - { - } - + : TEvProposeTransaction(txKind, source, txId, txBody, snapshot.Step, snapshot.TxId, flags) + { + } + TEvProposeTransaction(NKikimrTxDataShard::ETransactionKind txKind, ui64 ssId, const TActorId& source, ui64 txId, const TStringBuf& txBody, const NKikimrSubDomains::TProcessingParams &processingParams, ui32 flags = NDataShard::TTxFlags::Default) : TEvProposeTransaction(txKind, source, txId, txBody, flags) diff --git a/ydb/core/tx/datashard/datashard__engine_host.cpp b/ydb/core/tx/datashard/datashard__engine_host.cpp index 092b26cbe8..876c337093 100644 --- a/ydb/core/tx/datashard/datashard__engine_host.cpp +++ b/ydb/core/tx/datashard/datashard__engine_host.cpp @@ -302,16 +302,16 @@ public: return WriteVersion; } - void SetReadVersion(TRowVersion readVersion) { - ReadVersion = readVersion; - } - - TRowVersion GetReadVersion(const TTableId& tableId) const override { - Y_UNUSED(tableId); - Y_VERIFY(!ReadVersion.IsMin(), "Cannot perform reads without ReadVersion set"); - return ReadVersion; - } - + void SetReadVersion(TRowVersion readVersion) { + ReadVersion = readVersion; + } + + TRowVersion GetReadVersion(const TTableId& tableId) const override { + Y_UNUSED(tableId); + Y_VERIFY(!ReadVersion.IsMin(), "Cannot perform reads without ReadVersion set"); + return ReadVersion; + } + void SetIsImmediateTx() { IsImmediateTx = true; } @@ -502,7 +502,7 @@ private: bool IsImmediateTx = false; TInstant Now; TRowVersion WriteVersion = TRowVersion::Max(); - TRowVersion ReadVersion = TRowVersion::Min(); + TRowVersion ReadVersion = TRowVersion::Min(); mutable THashMap<TTableId, THolder<IChangeCollector>> ChangeCollectors; }; @@ -646,16 +646,16 @@ void TEngineBay::SetWriteVersion(TRowVersion writeVersion) { host->SetWriteVersion(writeVersion); } -void TEngineBay::SetReadVersion(TRowVersion readVersion) { - Y_VERIFY(EngineHost); - +void TEngineBay::SetReadVersion(TRowVersion readVersion) { + Y_VERIFY(EngineHost); + auto* host = static_cast<TDataShardEngineHost*>(EngineHost.Get()); - host->SetReadVersion(readVersion); - - Y_VERIFY(ComputeCtx); - ComputeCtx->SetReadVersion(readVersion); -} - + host->SetReadVersion(readVersion); + + Y_VERIFY(ComputeCtx); + ComputeCtx->SetReadVersion(readVersion); +} + void TEngineBay::SetIsImmediateTx() { Y_VERIFY(EngineHost); diff --git a/ydb/core/tx/datashard/datashard__engine_host.h b/ydb/core/tx/datashard/datashard__engine_host.h index a492810338..8e3064c83d 100644 --- a/ydb/core/tx/datashard/datashard__engine_host.h +++ b/ydb/core/tx/datashard/datashard__engine_host.h @@ -91,7 +91,7 @@ public: TEngineBay::TSizes CalcSizes(bool needsTotalKeysSize) const; void SetWriteVersion(TRowVersion writeVersion); - void SetReadVersion(TRowVersion readVersion); + void SetReadVersion(TRowVersion readVersion); void SetIsImmediateTx(); TVector<NMiniKQL::IChangeCollector::TChange> GetCollectedChanges() const; diff --git a/ydb/core/tx/datashard/datashard__init.cpp b/ydb/core/tx/datashard/datashard__init.cpp index a05d5f4b24..dc12c49959 100644 --- a/ydb/core/tx/datashard/datashard__init.cpp +++ b/ydb/core/tx/datashard/datashard__init.cpp @@ -81,15 +81,15 @@ void TDataShard::TTxInit::Complete(const TActorContext &ctx) { // path filled for user tables. Resolve path for them. Self->ResolveTablePath(ctx); - // Plan cleanup if needed + // Plan cleanup if needed if (Self->State == TShardState::Ready || Self->State == TShardState::SplitSrcWaitForNoTxInFlight || Self->State == TShardState::SplitSrcMakeSnapshot) { - // Initialize snapshot expiration queue with current context time - Self->GetSnapshotManager().InitExpireQueue(ctx.Now()); - - if (Self->GetSnapshotManager().HasExpiringSnapshots()) + // Initialize snapshot expiration queue with current context time + Self->GetSnapshotManager().InitExpireQueue(ctx.Now()); + + if (Self->GetSnapshotManager().HasExpiringSnapshots()) Self->PlanCleanup(ctx); } @@ -101,7 +101,7 @@ void TDataShard::TTxInit::Complete(const TActorContext &ctx) { Self->StartFindSubDomainPathId(); } } - + Self->CreateChangeSender(ctx); Self->EnqueueChangeRecords(std::move(ChangeRecords)); Self->MaybeActivateChangeSender(ctx); @@ -118,8 +118,8 @@ void TDataShard::TTxInit::Complete(const TActorContext &ctx) { } } - // Switch mvcc state if needed - Self->CheckMvccStateChangeCanStart(ctx); + // Switch mvcc state if needed + Self->CheckMvccStateChangeCanStart(ctx); } #define LOAD_SYS_UI64(db, row, value) if (!TDataShard::SysGetUi64(db, row, value)) return false; @@ -520,21 +520,21 @@ public: txc.DB.Alter().SetExecutorLogFlushPeriod(TDuration::MicroSeconds(500)); Self->PersistSys(db, Schema::Sys_State, Self->State); - + if (AppData(ctx)->FeatureFlags.GetEnableMvcc()) { auto state = *AppData(ctx)->FeatureFlags.GetEnableMvcc() ? EMvccState::MvccEnabled : EMvccState::MvccDisabled; - Self->PersistSys(db, Schema::SysMvcc_State, (ui32)state); - - LOG_DEBUG(ctx, NKikimrServices::TX_DATASHARD, TStringBuilder() << "TxInitSchema.Execute" + Self->PersistSys(db, Schema::SysMvcc_State, (ui32)state); + + LOG_DEBUG(ctx, NKikimrServices::TX_DATASHARD, TStringBuilder() << "TxInitSchema.Execute" << " MVCC state switched to" << (*AppData(ctx)->FeatureFlags.GetEnableMvcc() ? " enabled" : " disabled") << " state"); - } - - Self->MvccSwitchState = TSwitchState::DONE; + } + + Self->MvccSwitchState = TSwitchState::DONE; } //remove this code after all datashards upgrade Sys_SubDomainInfo row in Sys - if (Self->State == TShardState::Ready || - Self->State == TShardState::SplitSrcWaitForNoTxInFlight) { + if (Self->State == TShardState::Ready || + Self->State == TShardState::SplitSrcWaitForNoTxInFlight) { TString rawProcessingParams; LOAD_SYS_BYTES(db, Schema::Sys_SubDomainInfo, rawProcessingParams) diff --git a/ydb/core/tx/datashard/datashard__progress_tx.cpp b/ydb/core/tx/datashard/datashard__progress_tx.cpp index 6f738d5a35..3f1fab6b46 100644 --- a/ydb/core/tx/datashard/datashard__progress_tx.cpp +++ b/ydb/core/tx/datashard/datashard__progress_tx.cpp @@ -41,7 +41,7 @@ bool TDataShard::TTxProgressTransaction::Execute(TTransactionContext &txc, const // Allow another concurrent progress tx Self->PlanQueue.Reset(ctx); - Self->Pipeline.ActivateWaitingTxOps(ctx); + Self->Pipeline.ActivateWaitingTxOps(ctx); ActiveOp = Self->Pipeline.GetNextActiveOp(false); if (!ActiveOp) { @@ -132,7 +132,7 @@ void TDataShard::TTxProgressTransaction::Complete(const TActorContext &ctx) { } Self->CheckSplitCanStart(ctx); - Self->CheckMvccStateChangeCanStart(ctx); + Self->CheckMvccStateChangeCanStart(ctx); } }} diff --git a/ydb/core/tx/datashard/datashard__propose_tx_base.cpp b/ydb/core/tx/datashard/datashard__propose_tx_base.cpp index 9136e2a6df..7dfb1a294e 100644 --- a/ydb/core/tx/datashard/datashard__propose_tx_base.cpp +++ b/ydb/core/tx/datashard/datashard__propose_tx_base.cpp @@ -180,7 +180,7 @@ void TDataShard::TTxProposeTransactionBase::Complete(const TActorContext &ctx) { } Self->CheckSplitCanStart(ctx); - Self->CheckMvccStateChangeCanStart(ctx); + Self->CheckMvccStateChangeCanStart(ctx); } }} diff --git a/ydb/core/tx/datashard/datashard_active_transaction.h b/ydb/core/tx/datashard/datashard_active_transaction.h index 27e5f09637..43abd525e1 100644 --- a/ydb/core/tx/datashard/datashard_active_transaction.h +++ b/ydb/core/tx/datashard/datashard_active_transaction.h @@ -174,7 +174,7 @@ public: bool CheckCancelled(); void SetWriteVersion(TRowVersion writeVersion) { EngineBay.SetWriteVersion(writeVersion); } - void SetReadVersion(TRowVersion readVersion) { EngineBay.SetReadVersion(readVersion); } + void SetReadVersion(TRowVersion readVersion) { EngineBay.SetReadVersion(readVersion); } TVector<NMiniKQL::IChangeCollector::TChange> GetCollectedChanges() const { return EngineBay.GetCollectedChanges(); } diff --git a/ydb/core/tx/datashard/datashard_common_upload.cpp b/ydb/core/tx/datashard/datashard_common_upload.cpp index 9d9429bb8a..088da2b521 100644 --- a/ydb/core/tx/datashard/datashard_common_upload.cpp +++ b/ydb/core/tx/datashard/datashard_common_upload.cpp @@ -130,7 +130,7 @@ bool TCommonUploadOps<TEvRequest, TEvResponse>::Execute(TDataShard* self, TTrans if (readForTableShadow) { rowState.Init(tagsForSelect.size()); - auto ready = txc.DB.Select(localTableId, key, tagsForSelect, rowState, 0 /* readFlags */, readVersion); + auto ready = txc.DB.Select(localTableId, key, tagsForSelect, rowState, 0 /* readFlags */, readVersion); if (ready == NTable::EReady::Page) { pageFault = true; } diff --git a/ydb/core/tx/datashard/datashard_dep_tracker.cpp b/ydb/core/tx/datashard/datashard_dep_tracker.cpp index 56de1cf698..b7c3706937 100644 --- a/ydb/core/tx/datashard/datashard_dep_tracker.cpp +++ b/ydb/core/tx/datashard/datashard_dep_tracker.cpp @@ -39,14 +39,14 @@ namespace { range.InclusiveTo || !range.To); } } - + bool IsLess(const TOperation& a, const TRowVersion& b) { return a.GetStep() < b.Step || (a.GetStep() == b.Step && a.GetTxId() < b.TxId); } bool IsLessEqual(const TOperation& a, const TRowVersion& b) { - return a.GetStep() < b.Step || (a.GetStep() == b.Step && a.GetTxId() <= b.TxId); - } + return a.GetStep() < b.Step || (a.GetStep() == b.Step && a.GetTxId() <= b.TxId); + } } void TDependencyTracker::UpdateSchema(const TPathId& tableId, const TUserTable& tableInfo) noexcept { @@ -137,14 +137,14 @@ void TDependencyTracker::FlushImmediateWrites() noexcept { } } -const TDependencyTracker::TDependencyTrackingLogic& TDependencyTracker::GetTrackingLogic() const noexcept { +const TDependencyTracker::TDependencyTrackingLogic& TDependencyTracker::GetTrackingLogic() const noexcept { if (Self->IsMvccEnabled()) - return MvccLogic; - - return DefaultLogic; -} - -void TDependencyTracker::TDefaultDependencyTrackingLogic::AddOperation(const TOperation::TPtr& op) const noexcept { + return MvccLogic; + + return DefaultLogic; +} + +void TDependencyTracker::TDefaultDependencyTrackingLogic::AddOperation(const TOperation::TPtr& op) const noexcept { if (op->IsUsingSnapshot()) { return; } @@ -164,10 +164,10 @@ void TDependencyTracker::TDefaultDependencyTrackingLogic::AddOperation(const TOp // Non-immediate snapshot operations cannot be reordered if (!op->IsImmediate() && op->IsSnapshotTx()) { - if (Parent.LastSnapshotOp) { - op->AddDependency(Parent.LastSnapshotOp); + if (Parent.LastSnapshotOp) { + op->AddDependency(Parent.LastSnapshotOp); } - Parent.LastSnapshotOp = op; + Parent.LastSnapshotOp = op; } // First pass, gather all reads/writes expanded with locks, add lock based dependencies @@ -179,7 +179,7 @@ void TDependencyTracker::TDefaultDependencyTrackingLogic::AddOperation(const TOp const auto& locksCache = op->LocksCache(); for (const auto& vk : keysInfo.Keys) { const auto& k = *vk.Key; - if (Parent.Self->IsUserTable(k.TableId)) { + if (Parent.Self->IsUserTable(k.TableId)) { const ui64 tableId = k.TableId.PathId.LocalPathId; if (!tooManyKeys && ++keysCount > MAX_REORDER_TX_KEYS) { tooManyKeys = true; @@ -187,20 +187,20 @@ void TDependencyTracker::TDefaultDependencyTrackingLogic::AddOperation(const TOp if (vk.IsWrite) { haveWrites = true; if (!tooManyKeys && !isGlobalWriter) { - Parent.TmpWrite.emplace_back(tableId, k.Range); + Parent.TmpWrite.emplace_back(tableId, k.Range); } } else { haveReads = true; if (!tooManyKeys && !isGlobalReader) { - Parent.TmpRead.emplace_back(tableId, k.Range); + Parent.TmpRead.emplace_back(tableId, k.Range); } } } else if (TSysTables::IsLocksTable(k.TableId)) { Y_VERIFY(k.Range.Point, "Unexpected non-point read from the locks table"); - const ui64 lockTxId = Parent.Self->SysLocksTable().ExtractLockTxId(k.Range.From); + const ui64 lockTxId = Parent.Self->SysLocksTable().ExtractLockTxId(k.Range.From); // Add hard dependency on all operations that worked with the same lock - auto& lastLockOp = Parent.LastLockOps[lockTxId]; + auto& lastLockOp = Parent.LastLockOps[lockTxId]; if (lastLockOp != op) { op->AddAffectedLock(lockTxId); if (lastLockOp) { @@ -217,7 +217,7 @@ void TDependencyTracker::TDefaultDependencyTrackingLogic::AddOperation(const TOp // now we cannot know which keys it translated to, and // have to assume "whole shard" worst case. isGlobalReader = true; - } else if (auto it = Parent.Locks.find(lockTxId); it != Parent.Locks.end()) { + } else if (auto it = Parent.Locks.find(lockTxId); it != Parent.Locks.end()) { haveReads = true; if (!tooManyKeys && (keysCount += it->second.Keys.size()) > MAX_REORDER_TX_KEYS) { tooManyKeys = true; @@ -226,11 +226,11 @@ void TDependencyTracker::TDefaultDependencyTrackingLogic::AddOperation(const TOp if (it->second.WholeShard) { isGlobalReader = true; } else { - Parent.TmpRead.insert(Parent.TmpRead.end(), it->second.Keys.begin(), it->second.Keys.end()); + Parent.TmpRead.insert(Parent.TmpRead.end(), it->second.Keys.begin(), it->second.Keys.end()); } } - } else if (auto lock = Parent.Self->SysLocksTable().GetRawLock(lockTxId)) { - Y_ASSERT(!lock->IsBroken()); + } else if (auto lock = Parent.Self->SysLocksTable().GetRawLock(lockTxId)) { + Y_ASSERT(!lock->IsBroken()); haveReads = true; if (!tooManyKeys && (keysCount += (lock->NumPoints() + lock->NumRanges())) > MAX_REORDER_TX_KEYS) { tooManyKeys = true; @@ -262,12 +262,12 @@ void TDependencyTracker::TDefaultDependencyTrackingLogic::AddOperation(const TOp } if (haveReads && isGlobalReader) { - Parent.ClearTmpRead(); + Parent.ClearTmpRead(); haveReads = false; } if (haveWrites && isGlobalWriter) { - Parent.ClearTmpWrite(); + Parent.ClearTmpWrite(); haveWrites = false; } } @@ -288,37 +288,37 @@ void TDependencyTracker::TDefaultDependencyTrackingLogic::AddOperation(const TOp if (isGlobalWriter) { // We are potentially writing to all keys in all tables, thus we conflict with everything if (op->IsImmediate()) { - for (auto& item : Parent.AllPlannedReaders) { + for (auto& item : Parent.AllPlannedReaders) { TOperation::From(item)->AddImmediateConflict(op); } - for (auto& item : Parent.AllPlannedWriters) { + for (auto& item : Parent.AllPlannedWriters) { TOperation::From(item)->AddImmediateConflict(op); } } else { - for (auto& item : Parent.AllPlannedReaders) { + for (auto& item : Parent.AllPlannedReaders) { op->AddDependency(TOperation::From(item)); } - for (auto& item : Parent.AllPlannedWriters) { + for (auto& item : Parent.AllPlannedWriters) { op->AddDependency(TOperation::From(item)); } - for (auto& item : Parent.AllImmediateReaders) { + for (auto& item : Parent.AllImmediateReaders) { op->AddImmediateConflict(TOperation::From(item)); } - for (auto& item : Parent.AllImmediateWriters) { + for (auto& item : Parent.AllImmediateWriters) { op->AddImmediateConflict(TOperation::From(item)); } } } else { if (haveWrites) { // Each write may conflict with previous reads or writes - Parent.FlushPlannedReads(); - Parent.FlushPlannedWrites(); + Parent.FlushPlannedReads(); + Parent.FlushPlannedWrites(); if (!op->IsImmediate()) { - Parent.FlushImmediateReads(); - Parent.FlushImmediateWrites(); + Parent.FlushImmediateReads(); + Parent.FlushImmediateWrites(); } - for (const auto& write : Parent.TmpWrite) { - if (auto it = Parent.Tables.find(write.TableId); it != Parent.Tables.end()) { + for (const auto& write : Parent.TmpWrite) { + if (auto it = Parent.Tables.find(write.TableId); it != Parent.Tables.end()) { auto searchRange = MakeSearchRange(write.Key); if (op->IsImmediate()) { it->second.PlannedReads.EachIntersection(searchRange, processImmediatePlanned); @@ -334,23 +334,23 @@ void TDependencyTracker::TDefaultDependencyTrackingLogic::AddOperation(const TOp // If we have any reads we conflict with global reads or writes if (op->IsImmediate()) { - for (auto& item : Parent.GlobalPlannedReaders) { + for (auto& item : Parent.GlobalPlannedReaders) { TOperation::From(item)->AddImmediateConflict(op); } - for (auto& item : Parent.GlobalPlannedWriters) { + for (auto& item : Parent.GlobalPlannedWriters) { TOperation::From(item)->AddImmediateConflict(op); } } else { - for (auto& item : Parent.GlobalPlannedReaders) { + for (auto& item : Parent.GlobalPlannedReaders) { op->AddDependency(TOperation::From(item)); } - for (auto& item : Parent.GlobalPlannedWriters) { + for (auto& item : Parent.GlobalPlannedWriters) { op->AddDependency(TOperation::From(item)); } - for (auto& item : Parent.GlobalImmediateReaders) { + for (auto& item : Parent.GlobalImmediateReaders) { op->AddImmediateConflict(TOperation::From(item)); } - for (auto& item : Parent.GlobalImmediateWriters) { + for (auto& item : Parent.GlobalImmediateWriters) { op->AddImmediateConflict(TOperation::From(item)); } } @@ -359,25 +359,25 @@ void TDependencyTracker::TDefaultDependencyTrackingLogic::AddOperation(const TOp if (isGlobalReader) { // We are potentially reading all keys in all tables, thus we conflict with all writes if (op->IsImmediate()) { - for (auto& item : Parent.AllPlannedWriters) { + for (auto& item : Parent.AllPlannedWriters) { TOperation::From(item)->AddImmediateConflict(op); } } else { - for (auto& item : Parent.AllPlannedWriters) { + for (auto& item : Parent.AllPlannedWriters) { op->AddDependency(TOperation::From(item)); } - for (auto& item : Parent.AllImmediateWriters) { + for (auto& item : Parent.AllImmediateWriters) { op->AddImmediateConflict(TOperation::From(item)); } } } else if (haveReads) { // Each read may conflict with previous writes - Parent.FlushPlannedWrites(); + Parent.FlushPlannedWrites(); if (!op->IsImmediate()) { - Parent.FlushImmediateWrites(); + Parent.FlushImmediateWrites(); } - for (const auto& read : Parent.TmpRead) { - if (auto it = Parent.Tables.find(read.TableId); it != Parent.Tables.end()) { + for (const auto& read : Parent.TmpRead) { + if (auto it = Parent.Tables.find(read.TableId); it != Parent.Tables.end()) { auto searchRange = MakeSearchRange(read.Key); if (op->IsImmediate()) { it->second.PlannedWrites.EachIntersection(searchRange, processImmediatePlanned); @@ -392,14 +392,14 @@ void TDependencyTracker::TDefaultDependencyTrackingLogic::AddOperation(const TOp // But if we also have writes, then we already added them above if (!haveWrites) { if (op->IsImmediate()) { - for (auto& item : Parent.GlobalPlannedWriters) { + for (auto& item : Parent.GlobalPlannedWriters) { TOperation::From(item)->AddImmediateConflict(op); } } else { - for (auto& item : Parent.GlobalPlannedWriters) { + for (auto& item : Parent.GlobalPlannedWriters) { op->AddDependency(TOperation::From(item)); } - for (auto& item : Parent.GlobalImmediateWriters) { + for (auto& item : Parent.GlobalImmediateWriters) { op->AddImmediateConflict(TOperation::From(item)); } } @@ -412,49 +412,49 @@ void TDependencyTracker::TDefaultDependencyTrackingLogic::AddOperation(const TOp // Global writer transactions conflict with everything, so we only add them once // If it op is also is global reader it is shadowed by being a global writer if (op->IsImmediate()) { - Parent.GlobalImmediateWriters.PushBack(op.Get()); + Parent.GlobalImmediateWriters.PushBack(op.Get()); } else { - Parent.GlobalPlannedWriters.PushBack(op.Get()); + Parent.GlobalPlannedWriters.PushBack(op.Get()); } } else { if (haveWrites) { if (op->IsImmediate()) { if (DelayImmediateRanges) { - op->SetDelayedKnownWrites(Parent.TmpWrite); - Parent.DelayedImmediateWrites.PushBack(op.Get()); + op->SetDelayedKnownWrites(Parent.TmpWrite); + Parent.DelayedImmediateWrites.PushBack(op.Get()); } else { - Parent.AddImmediateWrites(op, Parent.TmpWrite); + Parent.AddImmediateWrites(op, Parent.TmpWrite); } } else { if (DelayPlannedRanges) { - op->SetDelayedKnownWrites(Parent.TmpWrite); - Parent.DelayedPlannedWrites.PushBack(op.Get()); + op->SetDelayedKnownWrites(Parent.TmpWrite); + Parent.DelayedPlannedWrites.PushBack(op.Get()); } else { - Parent.AddPlannedWrites(op, Parent.TmpWrite); + Parent.AddPlannedWrites(op, Parent.TmpWrite); } } } if (isGlobalReader) { if (op->IsImmediate()) { - Parent.GlobalImmediateReaders.PushBack(op.Get()); + Parent.GlobalImmediateReaders.PushBack(op.Get()); } else { - Parent.GlobalPlannedReaders.PushBack(op.Get()); + Parent.GlobalPlannedReaders.PushBack(op.Get()); } } else if (haveReads) { if (op->IsImmediate()) { if (DelayImmediateRanges) { - op->SetDelayedKnownReads(Parent.TmpRead); - Parent.DelayedImmediateReads.PushBack(op.Get()); + op->SetDelayedKnownReads(Parent.TmpRead); + Parent.DelayedImmediateReads.PushBack(op.Get()); } else { - Parent.AddImmediateReads(op, Parent.TmpRead); + Parent.AddImmediateReads(op, Parent.TmpRead); } } else { if (DelayPlannedRanges) { - op->SetDelayedKnownReads(Parent.TmpRead); - Parent.DelayedPlannedReads.PushBack(op.Get()); + op->SetDelayedKnownReads(Parent.TmpRead); + Parent.DelayedPlannedReads.PushBack(op.Get()); } else { - Parent.AddPlannedReads(op, Parent.TmpRead); + Parent.AddPlannedReads(op, Parent.TmpRead); } } } @@ -462,21 +462,21 @@ void TDependencyTracker::TDefaultDependencyTrackingLogic::AddOperation(const TOp if (isGlobalWriter || haveWrites) { if (op->IsImmediate()) { - Parent.AllImmediateWriters.PushBack(op.Get()); + Parent.AllImmediateWriters.PushBack(op.Get()); } else { - Parent.AllPlannedWriters.PushBack(op.Get()); + Parent.AllPlannedWriters.PushBack(op.Get()); } } else if (isGlobalReader || haveReads) { if (op->IsImmediate()) { - Parent.AllImmediateReaders.PushBack(op.Get()); + Parent.AllImmediateReaders.PushBack(op.Get()); } else { - Parent.AllPlannedReaders.PushBack(op.Get()); + Parent.AllPlannedReaders.PushBack(op.Get()); } } if (const ui64 lockTxId = op->LockTxId()) { // Add hard dependency on all operations that worked with the same lock - auto& lastLockOp = Parent.LastLockOps[lockTxId]; + auto& lastLockOp = Parent.LastLockOps[lockTxId]; if (lastLockOp != op) { op->AddAffectedLock(lockTxId); if (lastLockOp) { @@ -487,7 +487,7 @@ void TDependencyTracker::TDefaultDependencyTrackingLogic::AddOperation(const TOp // Update lock state with worst case prediction if (isGlobalReader) { - auto& lockState = Parent.Locks[lockTxId]; + auto& lockState = Parent.Locks[lockTxId]; if (!lockState.Initialized) { lockState.WholeShard = true; lockState.Initialized = true; @@ -496,9 +496,9 @@ void TDependencyTracker::TDefaultDependencyTrackingLogic::AddOperation(const TOp lockState.WholeShard = true; } } else if (haveReads) { - auto lock = Parent.Self->SysLocksTable().GetRawLock(lockTxId); - Y_ASSERT(!lock || !lock->IsBroken()); - auto& lockState = Parent.Locks[lockTxId]; + auto lock = Parent.Self->SysLocksTable().GetRawLock(lockTxId); + Y_ASSERT(!lock || !lock->IsBroken()); + auto& lockState = Parent.Locks[lockTxId]; if (!lockState.Initialized) { if (lock) { if (lock->IsBroken()) { @@ -515,214 +515,214 @@ void TDependencyTracker::TDefaultDependencyTrackingLogic::AddOperation(const TOp } } lockState.Initialized = true; - } - if (!lockState.WholeShard && !lockState.Broken) { - lockState.Keys.insert(lockState.Keys.end(), Parent.TmpRead.begin(), Parent.TmpRead.end()); - } - } - } - - if (haveReads) { - Parent.ClearTmpRead(); - } - - if (haveWrites) { - Parent.ClearTmpWrite(); - } -} - -void TDependencyTracker::TDefaultDependencyTrackingLogic::RemoveOperation(const TOperation::TPtr& op) const noexcept { - if (Parent.LastSnapshotOp == op) { - Parent.LastSnapshotOp = nullptr; - } - - for (ui64 lockTxId : op->GetAffectedLocks()) { - auto it = Parent.LastLockOps.find(lockTxId); - if (it != Parent.LastLockOps.end() && it->second == op) { - Parent.Locks.erase(lockTxId); - Parent.LastLockOps.erase(it); - } - } - - TOperationAllListItem* allListItem = op.Get(); - TOperationGlobalListItem* globalListItem = op.Get(); - TOperationDelayedReadListItem* delayedReadListItem = op.Get(); - TOperationDelayedWriteListItem* delayedWriteListItem = op.Get(); - - allListItem->Unlink(); - globalListItem->Unlink(); - - if (!delayedReadListItem->Empty()) { - delayedReadListItem->Unlink(); - op->RemoveDelayedKnownReads(); - } else { - for (auto& kv : Parent.Tables) { - if (op->IsImmediate()) { - kv.second.ImmediateReads.RemoveRanges(op); - } else { - kv.second.PlannedReads.RemoveRanges(op); - } - } - } - - if (!delayedWriteListItem->Empty()) { - delayedWriteListItem->Unlink(); - op->RemoveDelayedKnownWrites(); - } else { - for (auto& kv : Parent.Tables) { - if (op->IsImmediate()) { - kv.second.ImmediateWrites.RemoveRanges(op); - } else { - kv.second.PlannedWrites.RemoveRanges(op); - } - } - } -} - -void TDependencyTracker::TMvccDependencyTrackingLogic::AddOperation(const TOperation::TPtr& op) const noexcept { - if (op->IsUsingSnapshot()) { - return; - } - - // WARNING: kqp scan transactions don't have known keys, that means - // we must assume they are global reader and must be careful not to - // look into extracted keys for these transactions. - bool haveKeys = !op->IsKqpScanTransaction(); - - bool isGlobalReader = op->IsGlobalReader(); - bool isGlobalWriter = op->IsGlobalWriter(); - - bool tooManyKeys = false; - if (haveKeys && op->KeysCount() > MAX_REORDER_TX_KEYS) { - tooManyKeys = true; - } - - // Non-immediate snapshot operations cannot be reordered - if (!op->IsImmediate() && op->IsSnapshotTx()) { - if (Parent.LastSnapshotOp) { - op->AddDependency(Parent.LastSnapshotOp); - } - Parent.LastSnapshotOp = op; - } - + } + if (!lockState.WholeShard && !lockState.Broken) { + lockState.Keys.insert(lockState.Keys.end(), Parent.TmpRead.begin(), Parent.TmpRead.end()); + } + } + } + + if (haveReads) { + Parent.ClearTmpRead(); + } + + if (haveWrites) { + Parent.ClearTmpWrite(); + } +} + +void TDependencyTracker::TDefaultDependencyTrackingLogic::RemoveOperation(const TOperation::TPtr& op) const noexcept { + if (Parent.LastSnapshotOp == op) { + Parent.LastSnapshotOp = nullptr; + } + + for (ui64 lockTxId : op->GetAffectedLocks()) { + auto it = Parent.LastLockOps.find(lockTxId); + if (it != Parent.LastLockOps.end() && it->second == op) { + Parent.Locks.erase(lockTxId); + Parent.LastLockOps.erase(it); + } + } + + TOperationAllListItem* allListItem = op.Get(); + TOperationGlobalListItem* globalListItem = op.Get(); + TOperationDelayedReadListItem* delayedReadListItem = op.Get(); + TOperationDelayedWriteListItem* delayedWriteListItem = op.Get(); + + allListItem->Unlink(); + globalListItem->Unlink(); + + if (!delayedReadListItem->Empty()) { + delayedReadListItem->Unlink(); + op->RemoveDelayedKnownReads(); + } else { + for (auto& kv : Parent.Tables) { + if (op->IsImmediate()) { + kv.second.ImmediateReads.RemoveRanges(op); + } else { + kv.second.PlannedReads.RemoveRanges(op); + } + } + } + + if (!delayedWriteListItem->Empty()) { + delayedWriteListItem->Unlink(); + op->RemoveDelayedKnownWrites(); + } else { + for (auto& kv : Parent.Tables) { + if (op->IsImmediate()) { + kv.second.ImmediateWrites.RemoveRanges(op); + } else { + kv.second.PlannedWrites.RemoveRanges(op); + } + } + } +} + +void TDependencyTracker::TMvccDependencyTrackingLogic::AddOperation(const TOperation::TPtr& op) const noexcept { + if (op->IsUsingSnapshot()) { + return; + } + + // WARNING: kqp scan transactions don't have known keys, that means + // we must assume they are global reader and must be careful not to + // look into extracted keys for these transactions. + bool haveKeys = !op->IsKqpScanTransaction(); + + bool isGlobalReader = op->IsGlobalReader(); + bool isGlobalWriter = op->IsGlobalWriter(); + + bool tooManyKeys = false; + if (haveKeys && op->KeysCount() > MAX_REORDER_TX_KEYS) { + tooManyKeys = true; + } + + // Non-immediate snapshot operations cannot be reordered + if (!op->IsImmediate() && op->IsSnapshotTx()) { + if (Parent.LastSnapshotOp) { + op->AddDependency(Parent.LastSnapshotOp); + } + Parent.LastSnapshotOp = op; + } + // We use an optimistic readVersion assuming this transaction is read-only. // If it happens that this transaction is not read-only we would include // some locked keys in conflicts that are actually broken, but it's not // a problem. TRowVersion readVersion = Parent.Self->GetMvccTxVersion(EMvccTxMode::ReadOnly, op.Get()); - - // First pass, gather all reads/writes expanded with locks, add lock based dependencies - bool haveReads = false; - bool haveWrites = false; - if (haveKeys) { - size_t keysCount = 0; - const auto& keysInfo = op->GetKeysInfo(); - const auto& locksCache = op->LocksCache(); - for (const auto& vk : keysInfo.Keys) { - const auto& k = *vk.Key; - if (Parent.Self->IsUserTable(k.TableId)) { - const ui64 tableId = k.TableId.PathId.LocalPathId; - if (!tooManyKeys && ++keysCount > MAX_REORDER_TX_KEYS) { - tooManyKeys = true; - } - if (vk.IsWrite) { - haveWrites = true; - if (!tooManyKeys && !isGlobalWriter) { - Parent.TmpWrite.emplace_back(tableId, k.Range); - } - } else { - haveReads = true; - if (!tooManyKeys && !isGlobalReader) { - Parent.TmpRead.emplace_back(tableId, k.Range); - } - } - } else if (TSysTables::IsLocksTable(k.TableId)) { - Y_VERIFY(k.Range.Point, "Unexpected non-point read from the locks table"); - const ui64 lockTxId = Parent.Self->SysLocksTable().ExtractLockTxId(k.Range.From); - - // Add hard dependency on all operations that worked with the same lock - auto& lastLockOp = Parent.LastLockOps[lockTxId]; - if (lastLockOp != op) { - op->AddAffectedLock(lockTxId); - if (lastLockOp) { - op->AddDependency(lastLockOp); - } - lastLockOp = op; - } - - // Reading a lock means checking it for validity, i.e. "reading" those predicted keys - if (!vk.IsWrite) { - if (auto it = locksCache.Locks.find(lockTxId); it != locksCache.Locks.end()) { - // This transaction uses locks cache, so lock check - // outcome was persisted and restored. Unfortunately - // now we cannot know which keys it translated to, and - // have to assume "whole shard" worst case. - isGlobalReader = true; - } else if (auto it = Parent.Locks.find(lockTxId); it != Parent.Locks.end()) { - haveReads = true; - if (!tooManyKeys && (keysCount += it->second.Keys.size()) > MAX_REORDER_TX_KEYS) { - tooManyKeys = true; - } - if (!tooManyKeys && !isGlobalReader) { - if (it->second.WholeShard) { - isGlobalReader = true; - } else { - Parent.TmpRead.insert(Parent.TmpRead.end(), it->second.Keys.begin(), it->second.Keys.end()); - } - } - } else if (auto lock = Parent.Self->SysLocksTable().GetRawLock(lockTxId, readVersion)) { - Y_ASSERT(!lock->IsBroken(readVersion)); - haveReads = true; - if (!tooManyKeys && (keysCount += (lock->NumPoints() + lock->NumRanges())) > MAX_REORDER_TX_KEYS) { - tooManyKeys = true; - } - if (!tooManyKeys && !isGlobalReader) { - if (lock->IsShardLock()) { - isGlobalReader = true; - } else { - for (const auto& point : lock->GetPoints()) { + + // First pass, gather all reads/writes expanded with locks, add lock based dependencies + bool haveReads = false; + bool haveWrites = false; + if (haveKeys) { + size_t keysCount = 0; + const auto& keysInfo = op->GetKeysInfo(); + const auto& locksCache = op->LocksCache(); + for (const auto& vk : keysInfo.Keys) { + const auto& k = *vk.Key; + if (Parent.Self->IsUserTable(k.TableId)) { + const ui64 tableId = k.TableId.PathId.LocalPathId; + if (!tooManyKeys && ++keysCount > MAX_REORDER_TX_KEYS) { + tooManyKeys = true; + } + if (vk.IsWrite) { + haveWrites = true; + if (!tooManyKeys && !isGlobalWriter) { + Parent.TmpWrite.emplace_back(tableId, k.Range); + } + } else { + haveReads = true; + if (!tooManyKeys && !isGlobalReader) { + Parent.TmpRead.emplace_back(tableId, k.Range); + } + } + } else if (TSysTables::IsLocksTable(k.TableId)) { + Y_VERIFY(k.Range.Point, "Unexpected non-point read from the locks table"); + const ui64 lockTxId = Parent.Self->SysLocksTable().ExtractLockTxId(k.Range.From); + + // Add hard dependency on all operations that worked with the same lock + auto& lastLockOp = Parent.LastLockOps[lockTxId]; + if (lastLockOp != op) { + op->AddAffectedLock(lockTxId); + if (lastLockOp) { + op->AddDependency(lastLockOp); + } + lastLockOp = op; + } + + // Reading a lock means checking it for validity, i.e. "reading" those predicted keys + if (!vk.IsWrite) { + if (auto it = locksCache.Locks.find(lockTxId); it != locksCache.Locks.end()) { + // This transaction uses locks cache, so lock check + // outcome was persisted and restored. Unfortunately + // now we cannot know which keys it translated to, and + // have to assume "whole shard" worst case. + isGlobalReader = true; + } else if (auto it = Parent.Locks.find(lockTxId); it != Parent.Locks.end()) { + haveReads = true; + if (!tooManyKeys && (keysCount += it->second.Keys.size()) > MAX_REORDER_TX_KEYS) { + tooManyKeys = true; + } + if (!tooManyKeys && !isGlobalReader) { + if (it->second.WholeShard) { + isGlobalReader = true; + } else { + Parent.TmpRead.insert(Parent.TmpRead.end(), it->second.Keys.begin(), it->second.Keys.end()); + } + } + } else if (auto lock = Parent.Self->SysLocksTable().GetRawLock(lockTxId, readVersion)) { + Y_ASSERT(!lock->IsBroken(readVersion)); + haveReads = true; + if (!tooManyKeys && (keysCount += (lock->NumPoints() + lock->NumRanges())) > MAX_REORDER_TX_KEYS) { + tooManyKeys = true; + } + if (!tooManyKeys && !isGlobalReader) { + if (lock->IsShardLock()) { + isGlobalReader = true; + } else { + for (const auto& point : lock->GetPoints()) { Parent.TmpRead.emplace_back(point.Table->GetTableId().LocalPathId, point.ToOwnedTableRange()); - } - for (const auto& range : lock->GetRanges()) { + } + for (const auto& range : lock->GetRanges()) { Parent.TmpRead.emplace_back(range.Table->GetTableId().LocalPathId, range.ToOwnedTableRange()); - } - } - } - } - } - } - } - - if (tooManyKeys) { - if (haveReads) { - isGlobalReader = true; - } - if (haveWrites) { - isGlobalWriter = true; - } - } - - if (haveReads && isGlobalReader) { - Parent.ClearTmpRead(); - haveReads = false; - } - - if (haveWrites && isGlobalWriter) { - Parent.ClearTmpWrite(); - haveWrites = false; - } - } - - TRowVersion snapshot = TRowVersion::Max(); + } + } + } + } + } + } + } + + if (tooManyKeys) { + if (haveReads) { + isGlobalReader = true; + } + if (haveWrites) { + isGlobalWriter = true; + } + } + + if (haveReads && isGlobalReader) { + Parent.ClearTmpRead(); + haveReads = false; + } + + if (haveWrites && isGlobalWriter) { + Parent.ClearTmpWrite(); + haveWrites = false; + } + } + + TRowVersion snapshot = TRowVersion::Max(); bool snapshotRepeatable = false; if (op->IsMvccSnapshotRead()) { - snapshot = op->GetMvccSnapshot(); + snapshot = op->GetMvccSnapshot(); snapshotRepeatable = op->IsMvccSnapshotRepeatable(); } else if (op->IsImmediate() && (op->IsReadTable() || op->IsDataTx() && !haveWrites && !isGlobalWriter)) { snapshot = readVersion; op->SetMvccSnapshot(snapshot, /* repeatable */ false); } - + auto onImmediateConflict = [&](TOperation& conflict) { Y_VERIFY(!conflict.IsImmediate()); if (snapshot.IsMax()) { @@ -732,248 +732,248 @@ void TDependencyTracker::TMvccDependencyTrackingLogic::AddOperation(const TOpera } }; - auto processImmediatePlanned = [&](const TRangeTreeBase::TRange&, const TOperation::TPtr& conflict) { + auto processImmediatePlanned = [&](const TRangeTreeBase::TRange&, const TOperation::TPtr& conflict) { onImmediateConflict(*conflict); - }; - - auto processPlannedPlanned = [&](const TRangeTreeBase::TRange&, const TOperation::TPtr& conflict) { - op->AddDependency(conflict); - }; - - auto processPlannedImmediate = [&](const TRangeTreeBase::TRange&, const TOperation::TPtr& conflict) { - op->AddImmediateConflict(conflict); - }; - - // Second pass, add dependencies - if (isGlobalWriter) { - Y_ASSERT(snapshot.IsMax()); - - // We are potentially writing to all keys in all tables, thus we conflict with everything - if (op->IsImmediate()) { - for (auto& item : Parent.AllPlannedWriters) { - TOperation::From(item)->AddImmediateConflict(op); - } - } else { - for (auto& item : Parent.AllPlannedWriters) { - op->AddDependency(TOperation::From(item)); - } - for (auto& item : Parent.AllImmediateWriters) { - op->AddImmediateConflict(TOperation::From(item)); - } - // In mvcc case we skip immediate readers because they read at a fixed time point, - // so that they already calculated all their dependencies and cannot have new ones, - // however we are interesting in immediate readers who are immediate writers as well, - // but we already processed such transactions in the previous loop. - } - } else { - if (haveWrites) { - Y_ASSERT(snapshot.IsMax()); - - // Each write may conflict with previous writes - Parent.FlushPlannedWrites(); - if (!op->IsImmediate()) { - Parent.FlushImmediateReads(); - Parent.FlushImmediateWrites(); - } - for (const auto& write : Parent.TmpWrite) { - if (auto it = Parent.Tables.find(write.TableId); it != Parent.Tables.end()) { - auto searchRange = MakeSearchRange(write.Key); - if (op->IsImmediate()) { - it->second.PlannedWrites.EachIntersection(searchRange, processImmediatePlanned); - } else { - it->second.PlannedWrites.EachIntersection(searchRange, processPlannedPlanned); - // You should consider immediate reads as reads in scope of a writing immediate transaction - it->second.ImmediateReads.EachIntersection(searchRange, processPlannedImmediate); - it->second.ImmediateWrites.EachIntersection(searchRange, processPlannedImmediate); - } - } - } - - // If we have any reads or writes we conflict with global writes - if (op->IsImmediate()) { - for (auto& item : Parent.GlobalPlannedWriters) { - TOperation::From(item)->AddImmediateConflict(op); - } - } else { - for (auto& item : Parent.GlobalPlannedWriters) { - op->AddDependency(TOperation::From(item)); - } - // Here we have immediate writers who are global readers as well - for (auto& item : Parent.GlobalImmediateReaders) { - op->AddImmediateConflict(TOperation::From(item)); - } - for (auto& item : Parent.GlobalImmediateWriters) { - op->AddImmediateConflict(TOperation::From(item)); - } - } - } - - if (isGlobalReader) { - // We are potentially reading all keys in all tables, thus we conflict with all writes - if (op->IsImmediate()) { - for (auto& item : Parent.AllPlannedWriters) { + }; + + auto processPlannedPlanned = [&](const TRangeTreeBase::TRange&, const TOperation::TPtr& conflict) { + op->AddDependency(conflict); + }; + + auto processPlannedImmediate = [&](const TRangeTreeBase::TRange&, const TOperation::TPtr& conflict) { + op->AddImmediateConflict(conflict); + }; + + // Second pass, add dependencies + if (isGlobalWriter) { + Y_ASSERT(snapshot.IsMax()); + + // We are potentially writing to all keys in all tables, thus we conflict with everything + if (op->IsImmediate()) { + for (auto& item : Parent.AllPlannedWriters) { + TOperation::From(item)->AddImmediateConflict(op); + } + } else { + for (auto& item : Parent.AllPlannedWriters) { + op->AddDependency(TOperation::From(item)); + } + for (auto& item : Parent.AllImmediateWriters) { + op->AddImmediateConflict(TOperation::From(item)); + } + // In mvcc case we skip immediate readers because they read at a fixed time point, + // so that they already calculated all their dependencies and cannot have new ones, + // however we are interesting in immediate readers who are immediate writers as well, + // but we already processed such transactions in the previous loop. + } + } else { + if (haveWrites) { + Y_ASSERT(snapshot.IsMax()); + + // Each write may conflict with previous writes + Parent.FlushPlannedWrites(); + if (!op->IsImmediate()) { + Parent.FlushImmediateReads(); + Parent.FlushImmediateWrites(); + } + for (const auto& write : Parent.TmpWrite) { + if (auto it = Parent.Tables.find(write.TableId); it != Parent.Tables.end()) { + auto searchRange = MakeSearchRange(write.Key); + if (op->IsImmediate()) { + it->second.PlannedWrites.EachIntersection(searchRange, processImmediatePlanned); + } else { + it->second.PlannedWrites.EachIntersection(searchRange, processPlannedPlanned); + // You should consider immediate reads as reads in scope of a writing immediate transaction + it->second.ImmediateReads.EachIntersection(searchRange, processPlannedImmediate); + it->second.ImmediateWrites.EachIntersection(searchRange, processPlannedImmediate); + } + } + } + + // If we have any reads or writes we conflict with global writes + if (op->IsImmediate()) { + for (auto& item : Parent.GlobalPlannedWriters) { + TOperation::From(item)->AddImmediateConflict(op); + } + } else { + for (auto& item : Parent.GlobalPlannedWriters) { + op->AddDependency(TOperation::From(item)); + } + // Here we have immediate writers who are global readers as well + for (auto& item : Parent.GlobalImmediateReaders) { + op->AddImmediateConflict(TOperation::From(item)); + } + for (auto& item : Parent.GlobalImmediateWriters) { + op->AddImmediateConflict(TOperation::From(item)); + } + } + } + + if (isGlobalReader) { + // We are potentially reading all keys in all tables, thus we conflict with all writes + if (op->IsImmediate()) { + for (auto& item : Parent.AllPlannedWriters) { onImmediateConflict(*TOperation::From(item)); - } - } else { - for (auto& item : Parent.AllPlannedWriters) { - op->AddDependency(TOperation::From(item)); - } - // Since each happened read moves incomplete edge, neither immediate write cannot affect - // such read, that's why a planned reader cannot be a dependency for any immediate write - } - } else if (haveReads) { - // Each read may conflict with previous writes - Parent.FlushPlannedWrites(); - for (const auto& read : Parent.TmpRead) { - if (auto it = Parent.Tables.find(read.TableId); it != Parent.Tables.end()) { - auto searchRange = MakeSearchRange(read.Key); - if (op->IsImmediate()) { - it->second.PlannedWrites.EachIntersection(searchRange, processImmediatePlanned); - } else { - it->second.PlannedWrites.EachIntersection(searchRange, processPlannedPlanned); - } - } - } - - // If we have any reads we conflict with previous global writes - // But if we also have writes, then we already added them above. - if (!haveWrites) { - if (op->IsImmediate()) { - for (auto& item : Parent.GlobalPlannedWriters) { + } + } else { + for (auto& item : Parent.AllPlannedWriters) { + op->AddDependency(TOperation::From(item)); + } + // Since each happened read moves incomplete edge, neither immediate write cannot affect + // such read, that's why a planned reader cannot be a dependency for any immediate write + } + } else if (haveReads) { + // Each read may conflict with previous writes + Parent.FlushPlannedWrites(); + for (const auto& read : Parent.TmpRead) { + if (auto it = Parent.Tables.find(read.TableId); it != Parent.Tables.end()) { + auto searchRange = MakeSearchRange(read.Key); + if (op->IsImmediate()) { + it->second.PlannedWrites.EachIntersection(searchRange, processImmediatePlanned); + } else { + it->second.PlannedWrites.EachIntersection(searchRange, processPlannedPlanned); + } + } + } + + // If we have any reads we conflict with previous global writes + // But if we also have writes, then we already added them above. + if (!haveWrites) { + if (op->IsImmediate()) { + for (auto& item : Parent.GlobalPlannedWriters) { onImmediateConflict(*TOperation::From(item)); - } - } else { - for (auto& item : Parent.GlobalPlannedWriters) { - op->AddDependency(TOperation::From(item)); - } - // Since each happened read moves incomplete edge, neither immediate write cannot affect - // such read, that's why a planned reader cannot be a dependency for any immediate write - } - } - } - } - - // Third pass, add new operation to relevant tables - if (isGlobalWriter) { - // Global writer transactions conflict with everything, so we only add them once - // If the op is also a reader it's shadowed by being a global writer - if (op->IsImmediate()) { - Parent.GlobalImmediateWriters.PushBack(op.Get()); - } else { - Parent.GlobalPlannedWriters.PushBack(op.Get()); - } - } else { - if (haveWrites) { - if (op->IsImmediate()) { - if (DelayImmediateRanges) { - op->SetDelayedKnownWrites(Parent.TmpWrite); - Parent.DelayedImmediateWrites.PushBack(op.Get()); - } else { - Parent.AddImmediateWrites(op, Parent.TmpWrite); - } - - // In mvcc case we don't track reads, but sice a writing immediate transaction may be - // rescheduled, a read in scope of the writing immediate transaction is an exception - if (isGlobalReader) { - Parent.GlobalImmediateReaders.PushBack(op.Get()); - } else if (haveReads) { - if (DelayImmediateRanges) { - op->SetDelayedKnownReads(Parent.TmpRead); - Parent.DelayedImmediateReads.PushBack(op.Get()); - } else { - Parent.AddImmediateReads(op, Parent.TmpRead); - } - } - } else { - if (DelayPlannedRanges) { - op->SetDelayedKnownWrites(Parent.TmpWrite); - Parent.DelayedPlannedWrites.PushBack(op.Get()); - } else { - Parent.AddPlannedWrites(op, Parent.TmpWrite); - } - } - } - // In mvcc case we don't track planned reads, immediate reads - // are tracked in a special case, this is already done above - } - - if (isGlobalWriter || haveWrites) { - if (op->IsImmediate()) { - Parent.AllImmediateWriters.PushBack(op.Get()); - } else { - Parent.AllPlannedWriters.PushBack(op.Get()); - } - } - // In mvcc case we don't track planned reads, immediate reads - // are tracked in a special case, this is already done above - - if (const ui64 lockTxId = op->LockTxId()) { - // Add hard dependency on all operations that worked with the same lock - auto& lastLockOp = Parent.LastLockOps[lockTxId]; - if (lastLockOp != op) { - op->AddAffectedLock(lockTxId); - if (lastLockOp) { - op->AddDependency(lastLockOp); - } - lastLockOp = op; - } - - // Update lock state with worst case prediction - if (isGlobalReader) { - auto& lockState = Parent.Locks[lockTxId]; - if (!lockState.Initialized) { - lockState.WholeShard = true; - lockState.Initialized = true; - } else if (!lockState.WholeShard && !lockState.Broken) { - SwapConsume(lockState.Keys); - lockState.WholeShard = true; - } - } else if (haveReads) { - auto lock = Parent.Self->SysLocksTable().GetRawLock(lockTxId, readVersion); - Y_ASSERT(!lock || !lock->IsBroken(readVersion)); - auto& lockState = Parent.Locks[lockTxId]; - if (!lockState.Initialized) { - if (lock) { - if (lock->IsBroken(readVersion)) { - lockState.Broken = true; - } else if (lock->IsShardLock()) { - lockState.WholeShard = true; - } else { - for (const auto& point : lock->GetPoints()) { + } + } else { + for (auto& item : Parent.GlobalPlannedWriters) { + op->AddDependency(TOperation::From(item)); + } + // Since each happened read moves incomplete edge, neither immediate write cannot affect + // such read, that's why a planned reader cannot be a dependency for any immediate write + } + } + } + } + + // Third pass, add new operation to relevant tables + if (isGlobalWriter) { + // Global writer transactions conflict with everything, so we only add them once + // If the op is also a reader it's shadowed by being a global writer + if (op->IsImmediate()) { + Parent.GlobalImmediateWriters.PushBack(op.Get()); + } else { + Parent.GlobalPlannedWriters.PushBack(op.Get()); + } + } else { + if (haveWrites) { + if (op->IsImmediate()) { + if (DelayImmediateRanges) { + op->SetDelayedKnownWrites(Parent.TmpWrite); + Parent.DelayedImmediateWrites.PushBack(op.Get()); + } else { + Parent.AddImmediateWrites(op, Parent.TmpWrite); + } + + // In mvcc case we don't track reads, but sice a writing immediate transaction may be + // rescheduled, a read in scope of the writing immediate transaction is an exception + if (isGlobalReader) { + Parent.GlobalImmediateReaders.PushBack(op.Get()); + } else if (haveReads) { + if (DelayImmediateRanges) { + op->SetDelayedKnownReads(Parent.TmpRead); + Parent.DelayedImmediateReads.PushBack(op.Get()); + } else { + Parent.AddImmediateReads(op, Parent.TmpRead); + } + } + } else { + if (DelayPlannedRanges) { + op->SetDelayedKnownWrites(Parent.TmpWrite); + Parent.DelayedPlannedWrites.PushBack(op.Get()); + } else { + Parent.AddPlannedWrites(op, Parent.TmpWrite); + } + } + } + // In mvcc case we don't track planned reads, immediate reads + // are tracked in a special case, this is already done above + } + + if (isGlobalWriter || haveWrites) { + if (op->IsImmediate()) { + Parent.AllImmediateWriters.PushBack(op.Get()); + } else { + Parent.AllPlannedWriters.PushBack(op.Get()); + } + } + // In mvcc case we don't track planned reads, immediate reads + // are tracked in a special case, this is already done above + + if (const ui64 lockTxId = op->LockTxId()) { + // Add hard dependency on all operations that worked with the same lock + auto& lastLockOp = Parent.LastLockOps[lockTxId]; + if (lastLockOp != op) { + op->AddAffectedLock(lockTxId); + if (lastLockOp) { + op->AddDependency(lastLockOp); + } + lastLockOp = op; + } + + // Update lock state with worst case prediction + if (isGlobalReader) { + auto& lockState = Parent.Locks[lockTxId]; + if (!lockState.Initialized) { + lockState.WholeShard = true; + lockState.Initialized = true; + } else if (!lockState.WholeShard && !lockState.Broken) { + SwapConsume(lockState.Keys); + lockState.WholeShard = true; + } + } else if (haveReads) { + auto lock = Parent.Self->SysLocksTable().GetRawLock(lockTxId, readVersion); + Y_ASSERT(!lock || !lock->IsBroken(readVersion)); + auto& lockState = Parent.Locks[lockTxId]; + if (!lockState.Initialized) { + if (lock) { + if (lock->IsBroken(readVersion)) { + lockState.Broken = true; + } else if (lock->IsShardLock()) { + lockState.WholeShard = true; + } else { + for (const auto& point : lock->GetPoints()) { lockState.Keys.emplace_back(point.Table->GetTableId().LocalPathId, point.ToOwnedTableRange()); - } - for (const auto& range : lock->GetRanges()) { + } + for (const auto& range : lock->GetRanges()) { lockState.Keys.emplace_back(range.Table->GetTableId().LocalPathId, range.ToOwnedTableRange()); - } - } - } - lockState.Initialized = true; - } + } + } + } + lockState.Initialized = true; + } if (!lockState.WholeShard && !lockState.Broken) { - lockState.Keys.insert(lockState.Keys.end(), Parent.TmpRead.begin(), Parent.TmpRead.end()); + lockState.Keys.insert(lockState.Keys.end(), Parent.TmpRead.begin(), Parent.TmpRead.end()); } } } if (haveReads) { - Parent.ClearTmpRead(); + Parent.ClearTmpRead(); } if (haveWrites) { - Parent.ClearTmpWrite(); + Parent.ClearTmpWrite(); } } -void TDependencyTracker::TMvccDependencyTrackingLogic::RemoveOperation(const TOperation::TPtr& op) const noexcept { - if (Parent.LastSnapshotOp == op) { - Parent.LastSnapshotOp = nullptr; +void TDependencyTracker::TMvccDependencyTrackingLogic::RemoveOperation(const TOperation::TPtr& op) const noexcept { + if (Parent.LastSnapshotOp == op) { + Parent.LastSnapshotOp = nullptr; } for (ui64 lockTxId : op->GetAffectedLocks()) { - auto it = Parent.LastLockOps.find(lockTxId); - if (it != Parent.LastLockOps.end() && it->second == op) { - Parent.Locks.erase(lockTxId); - Parent.LastLockOps.erase(it); + auto it = Parent.LastLockOps.find(lockTxId); + if (it != Parent.LastLockOps.end() && it->second == op) { + Parent.Locks.erase(lockTxId); + Parent.LastLockOps.erase(it); } } @@ -989,7 +989,7 @@ void TDependencyTracker::TMvccDependencyTrackingLogic::RemoveOperation(const TOp delayedReadListItem->Unlink(); op->RemoveDelayedKnownReads(); } else { - for (auto& kv : Parent.Tables) { + for (auto& kv : Parent.Tables) { if (op->IsImmediate()) { kv.second.ImmediateReads.RemoveRanges(op); } else { @@ -1002,7 +1002,7 @@ void TDependencyTracker::TMvccDependencyTrackingLogic::RemoveOperation(const TOp delayedWriteListItem->Unlink(); op->RemoveDelayedKnownWrites(); } else { - for (auto& kv : Parent.Tables) { + for (auto& kv : Parent.Tables) { if (op->IsImmediate()) { kv.second.ImmediateWrites.RemoveRanges(op); } else { diff --git a/ydb/core/tx/datashard/datashard_dep_tracker.h b/ydb/core/tx/datashard/datashard_dep_tracker.h index c8a8791b19..856c71411c 100644 --- a/ydb/core/tx/datashard/datashard_dep_tracker.h +++ b/ydb/core/tx/datashard/datashard_dep_tracker.h @@ -52,40 +52,40 @@ private: TRangeTreap<TOperation::TPtr, TOperationPtrTraits> ImmediateWrites; }; - struct TDependencyTrackingLogic { - TDependencyTracker& Parent; - - explicit TDependencyTrackingLogic(TDependencyTracker& parent) - : Parent(parent) {} - - // Adds operation to the tracker - virtual void AddOperation(const TOperation::TPtr& op) const noexcept = 0; - - // Removes operation from the tracker, no future operations may conflict with it - virtual void RemoveOperation(const TOperation::TPtr& op) const noexcept = 0; - }; - - struct TDefaultDependencyTrackingLogic : public TDependencyTrackingLogic { - explicit TDefaultDependencyTrackingLogic(TDependencyTracker& parent) - : TDependencyTrackingLogic(parent) {} - - void AddOperation(const TOperation::TPtr& op) const noexcept override; - void RemoveOperation(const TOperation::TPtr& op) const noexcept override; - }; - - struct TMvccDependencyTrackingLogic : public TDependencyTrackingLogic { - explicit TMvccDependencyTrackingLogic(TDependencyTracker& parent) - : TDependencyTrackingLogic(parent) {} - - void AddOperation(const TOperation::TPtr& op) const noexcept override; - void RemoveOperation(const TOperation::TPtr& op) const noexcept override; - }; - + struct TDependencyTrackingLogic { + TDependencyTracker& Parent; + + explicit TDependencyTrackingLogic(TDependencyTracker& parent) + : Parent(parent) {} + + // Adds operation to the tracker + virtual void AddOperation(const TOperation::TPtr& op) const noexcept = 0; + + // Removes operation from the tracker, no future operations may conflict with it + virtual void RemoveOperation(const TOperation::TPtr& op) const noexcept = 0; + }; + + struct TDefaultDependencyTrackingLogic : public TDependencyTrackingLogic { + explicit TDefaultDependencyTrackingLogic(TDependencyTracker& parent) + : TDependencyTrackingLogic(parent) {} + + void AddOperation(const TOperation::TPtr& op) const noexcept override; + void RemoveOperation(const TOperation::TPtr& op) const noexcept override; + }; + + struct TMvccDependencyTrackingLogic : public TDependencyTrackingLogic { + explicit TMvccDependencyTrackingLogic(TDependencyTracker& parent) + : TDependencyTrackingLogic(parent) {} + + void AddOperation(const TOperation::TPtr& op) const noexcept override; + void RemoveOperation(const TOperation::TPtr& op) const noexcept override; + }; + public: TDependencyTracker(TDataShard* self) : Self(self) - , DefaultLogic(*this) - , MvccLogic(*this) + , DefaultLogic(*this) + , MvccLogic(*this) { } public: @@ -96,14 +96,14 @@ public: void RemoveSchema(const TPathId& tableId) noexcept; // Adds operation to the tracker - void AddOperation(const TOperation::TPtr& op) noexcept { - GetTrackingLogic().AddOperation(op); - } + void AddOperation(const TOperation::TPtr& op) noexcept { + GetTrackingLogic().AddOperation(op); + } // Removes operation from the tracker, no future operations may conflict with it - void RemoveOperation(const TOperation::TPtr& op) noexcept { - GetTrackingLogic().RemoveOperation(op); - } + void RemoveOperation(const TOperation::TPtr& op) noexcept { + GetTrackingLogic().RemoveOperation(op); + } private: void ClearTmpRead() noexcept; @@ -119,8 +119,8 @@ private: void FlushImmediateReads() noexcept; void FlushImmediateWrites() noexcept; - const TDependencyTrackingLogic& GetTrackingLogic() const noexcept; - + const TDependencyTrackingLogic& GetTrackingLogic() const noexcept; + private: TDataShard* Self; // Temporary vectors for building dependencies @@ -149,9 +149,9 @@ private: TIntrusiveList<TOperationDelayedReadListItem> DelayedImmediateReads; TIntrusiveList<TOperationDelayedWriteListItem> DelayedPlannedWrites; TIntrusiveList<TOperationDelayedWriteListItem> DelayedImmediateWrites; - - const TDefaultDependencyTrackingLogic DefaultLogic; - const TMvccDependencyTrackingLogic MvccLogic; + + const TDefaultDependencyTrackingLogic DefaultLogic; + const TMvccDependencyTrackingLogic MvccLogic; }; } // namespace NDataShard diff --git a/ydb/core/tx/datashard/datashard_direct_transaction.cpp b/ydb/core/tx/datashard/datashard_direct_transaction.cpp index 27b4fbef65..145f0936cd 100644 --- a/ydb/core/tx/datashard/datashard_direct_transaction.cpp +++ b/ydb/core/tx/datashard/datashard_direct_transaction.cpp @@ -31,12 +31,12 @@ void TDirectTransaction::BuildExecutionPlan(bool loaded) } bool TDirectTransaction::Execute(TDataShard* self, TTransactionContext& txc) { - auto [readVersion, writeVersion] = self->GetReadWriteVersions(); - if (!Impl->Execute(self, txc, readVersion, writeVersion)) - return false; - + auto [readVersion, writeVersion] = self->GetReadWriteVersions(); + if (!Impl->Execute(self, txc, readVersion, writeVersion)) + return false; + self->PromoteCompleteEdge(writeVersion.Step, txc); - return true; + return true; } void TDirectTransaction::SendResult(TDataShard* self, const TActorContext& ctx) { diff --git a/ydb/core/tx/datashard/datashard_impl.h b/ydb/core/tx/datashard/datashard_impl.h index ebd1f5d339..11313474f8 100644 --- a/ydb/core/tx/datashard/datashard_impl.h +++ b/ydb/core/tx/datashard/datashard_impl.h @@ -79,14 +79,14 @@ private: // For Split class TSplitSnapshotContext : public NTabletFlatExecutor::TTableSnapshotContext { public: - TSplitSnapshotContext(ui64 txId, TVector<ui32> &&tables, - TRowVersion completeEdge = TRowVersion::Min(), - TRowVersion incompleteEdge = TRowVersion::Min(), - TRowVersion lowWatermark = TRowVersion::Min()) + TSplitSnapshotContext(ui64 txId, TVector<ui32> &&tables, + TRowVersion completeEdge = TRowVersion::Min(), + TRowVersion incompleteEdge = TRowVersion::Min(), + TRowVersion lowWatermark = TRowVersion::Min()) : TxId(txId) - , CompleteEdge(completeEdge) - , IncompleteEdge(incompleteEdge) - , LowWatermark(lowWatermark) + , CompleteEdge(completeEdge) + , IncompleteEdge(incompleteEdge) + , LowWatermark(lowWatermark) , Tables(tables) {} @@ -95,9 +95,9 @@ public: } ui64 TxId; - TRowVersion CompleteEdge; - TRowVersion IncompleteEdge; - TRowVersion LowWatermark; + TRowVersion CompleteEdge; + TRowVersion IncompleteEdge; + TRowVersion LowWatermark; private: TVector<ui32> Tables; @@ -109,29 +109,29 @@ public: virtual void OnFinished(TDataShard* self) = 0; }; -struct TReadWriteVersions { - TReadWriteVersions(const TRowVersion& readVersion, const TRowVersion& writeVersion) - : ReadVersion(readVersion) - , WriteVersion(writeVersion) - {} - - TReadWriteVersions(const TRowVersion& version) - : ReadVersion(version) - , WriteVersion(version) - {} - - const TRowVersion ReadVersion; - const TRowVersion WriteVersion; -}; - -enum class TSwitchState { - READY, - SWITCHING, - DONE -}; - +struct TReadWriteVersions { + TReadWriteVersions(const TRowVersion& readVersion, const TRowVersion& writeVersion) + : ReadVersion(readVersion) + , WriteVersion(writeVersion) + {} + + TReadWriteVersions(const TRowVersion& version) + : ReadVersion(version) + , WriteVersion(version) + {} + + const TRowVersion ReadVersion; + const TRowVersion WriteVersion; +}; + +enum class TSwitchState { + READY, + SWITCHING, + DONE +}; + class TDataShardEngineHost; -struct TSetupSysLocks; +struct TSetupSysLocks; /// class TDataShard @@ -194,7 +194,7 @@ class TDataShard class TTxGetS3DownloadInfo; class TTxStoreS3DownloadInfo; class TTxUnsafeUploadRows; - class TTxExecuteMvccStateChange; + class TTxExecuteMvccStateChange; class TTxGetRemovedRowVersions; class TTxCompactBorrowed; class TTxCompactTable; @@ -255,11 +255,11 @@ class TDataShard friend class TS3UploadsManager; friend class TS3DownloadsManager; friend class TS3Downloader; - friend struct TSetupSysLocks; + friend struct TSetupSysLocks; + + friend class TTxStartMvccStateChange; + friend class TTxExecuteMvccStateChange; - friend class TTxStartMvccStateChange; - friend class TTxExecuteMvccStateChange; - class TFindSubDomainPathIdActor; class TTxPersistSubDomainPathId; class TTxPersistSubDomainOutOfSpace; @@ -789,15 +789,15 @@ class TDataShard Sys_MinWriteVersionTxId, // 23 Minimum TxId for new writes (past known snapshots) Sys_PathOwnerId, // TabletID of the schmemeshard that allocated the TPathId(ownerId,localId) - SysMvcc_State, - SysMvcc_CompleteEdgeStep, - SysMvcc_CompleteEdgeTxId, - SysMvcc_IncompleteEdgeStep, - SysMvcc_IncompleteEdgeTxId, - SysMvcc_LowWatermarkStep, - SysMvcc_LowWatermarkTxId, - SysMvcc_KeepSnapshotTimeout, - + SysMvcc_State, + SysMvcc_CompleteEdgeStep, + SysMvcc_CompleteEdgeTxId, + SysMvcc_IncompleteEdgeStep, + SysMvcc_IncompleteEdgeTxId, + SysMvcc_LowWatermarkStep, + SysMvcc_LowWatermarkTxId, + SysMvcc_KeepSnapshotTimeout, + Sys_SubDomainOwnerId, // 33 OwnerId of the subdomain path id Sys_SubDomainLocalPathId, // 34 LocalPathId of the subdomain path id Sys_SubDomainOutOfSpace, // 35 Boolean flag indicating database is out of space @@ -904,7 +904,7 @@ class TDataShard void Handle(TEvTabletPipe::TEvServerConnected::TPtr &ev, const TActorContext &ctx); void Handle(TEvTabletPipe::TEvServerDisconnected::TPtr &ev, const TActorContext &ctx); void Handle(TEvMediatorTimecast::TEvRegisterTabletResult::TPtr& ev, const TActorContext& ctx); - void Handle(TEvMediatorTimecast::TEvNotifyPlanStep::TPtr& ev, const TActorContext& ctx); + void Handle(TEvMediatorTimecast::TEvNotifyPlanStep::TPtr& ev, const TActorContext& ctx); void Handle(TEvDataShard::TEvCancelTransactionProposal::TPtr &ev, const TActorContext &ctx); void Handle(TEvDataShard::TEvReturnBorrowedPart::TPtr& ev, const TActorContext& ctx); void Handle(TEvDataShard::TEvReturnBorrowedPartAck::TPtr& ev, const TActorContext& ctx); @@ -1053,10 +1053,10 @@ class TDataShard NTabletFlatExecutor::ITransaction* CreateTxInitiateBorrowedPartsReturn(); NTabletFlatExecutor::ITransaction* CreateTxCheckInReadSets(); NTabletFlatExecutor::ITransaction* CreateTxRemoveOldInReadSets(); - NTabletFlatExecutor::ITransaction* CreateTxExecuteMvccStateChange(); + NTabletFlatExecutor::ITransaction* CreateTxExecuteMvccStateChange(); + + TReadWriteVersions GetLocalReadWriteVersions() const; - TReadWriteVersions GetLocalReadWriteVersions() const; - public: static constexpr NKikimrServices::TActivity::EType ActorActivityType() { return NKikimrServices::TActivity::TX_DATASHARD_ACTOR; @@ -1138,13 +1138,13 @@ public: ui64 TxPlanned() const { return TransQueue.TxPlanned(); } ui64 TxPlanWaiting() const { return TransQueue.TxPlanWaiting(); } ui64 ImmediateInFly() const { return Pipeline.ImmediateInFly(); } - ui64 TxWaiting() const { return Pipeline.WaitingTxs(); } + ui64 TxWaiting() const { return Pipeline.WaitingTxs(); } + + inline TRowVersion LastCompleteTxVersion() const { + auto order = Pipeline.GetLastCompleteTx(); + return TRowVersion(order.Step, order.TxId); + } - inline TRowVersion LastCompleteTxVersion() const { - auto order = Pipeline.GetLastCompleteTx(); - return TRowVersion(order.Step, order.TxId); - } - bool CanDrop() const { Y_VERIFY(State != TShardState::Offline, "Unexpexted repeated drop"); return (TxInFly() == 1) && OutReadSets.Empty() && (State != TShardState::PreOffline); @@ -1276,10 +1276,10 @@ public: void CheckInitiateBorrowedPartsReturn(const TActorContext& ctx); void CheckStateChange(const TActorContext& ctx); void CheckSplitCanStart(const TActorContext& ctx); - void CheckMvccStateChangeCanStart(const TActorContext& ctx); + void CheckMvccStateChangeCanStart(const TActorContext& ctx); ui32 GetState() const { return State; } - TSwitchState GetMvccSwitchState() { return MvccSwitchState; } + TSwitchState GetMvccSwitchState() { return MvccSwitchState; } void SetPersistState(ui32 state, TTransactionContext &txc) { NIceDb::TNiceDb db(txc.DB); @@ -1306,7 +1306,7 @@ public: void PersistOwnerPathId(ui64 id, NTabletFlatExecutor::TTransactionContext &txc); - TDuration CleanupTimeout() const; + TDuration CleanupTimeout() const; void PlanCleanup(const TActorContext &ctx) { CleanupQueue.Schedule(ctx, CleanupTimeout()); } @@ -1373,7 +1373,7 @@ public: const TPathId& streamPathId); TUserTable::TPtr CreateUserTable(TTransactionContext& txc, const NKikimrSchemeOp::TTableDescription& tableScheme); - TUserTable::TPtr AlterUserTable(const TActorContext& ctx, TTransactionContext& txc, + TUserTable::TPtr AlterUserTable(const TActorContext& ctx, TTransactionContext& txc, const NKikimrSchemeOp::TTableDescription& tableScheme); static THashMap<TPathId, TPathId> GetRemapIndexes(const NKikimrTxDataShard::TMoveTable& move); TUserTable::TPtr MoveUserTable(const TActorContext& ctx, TTransactionContext& txc, const NKikimrTxDataShard::TMoveTable& move); @@ -1419,7 +1419,7 @@ public: // Returns a suitable row version for performing a transaction TRowVersion GetMvccTxVersion(EMvccTxMode mode, TOperation* op = nullptr) const; - TReadWriteVersions GetReadWriteVersions(TOperation* op = nullptr) const; + TReadWriteVersions GetReadWriteVersions(TOperation* op = nullptr) const; void FillExecutionStats(const TExecutionProfile& execProfile, TEvDataShard::TEvProposeTransactionResult& result) const; @@ -1438,9 +1438,9 @@ public: void StopWatchingSubDomainPathId(); void StartWatchingSubDomainPathId(); - bool WaitPlanStep(ui64 step); - bool CheckTxNeedWait(const TEvDataShard::TEvProposeTransaction::TPtr& ev) const; - + bool WaitPlanStep(ui64 step); + bool CheckTxNeedWait(const TEvDataShard::TEvProposeTransaction::TPtr& ev) const; + bool CheckChangesQueueOverflow() const; private: @@ -1916,7 +1916,7 @@ private: TLoanReturnTracker LoanReturnTracker; TFollowerState FollowerState; - TSwitchState MvccSwitchState; + TSwitchState MvccSwitchState; bool SplitSnapshotStarted; // Non-persistent flag that is used to restart snapshot in case of datashard restart TSplitSrcSnapshotSender SplitSrcSnapshotSender; // TODO: make this persitent @@ -1970,7 +1970,7 @@ private: TS3DownloadsManager S3Downloads; TIntrusivePtr<TMediatorTimecastEntry> MediatorTimeCastEntry; - TSet<ui64> MediatorTimeCastWaitingSteps; + TSet<ui64> MediatorTimeCastWaitingSteps; TControlWrapper DisableByKeyFilter; TControlWrapper MaxTxInFly; @@ -2165,7 +2165,7 @@ protected: HFuncTraced(TEvTabletPipe::TEvServerConnected, Handle); HFuncTraced(TEvTabletPipe::TEvServerDisconnected, Handle); HFuncTraced(TEvMediatorTimecast::TEvRegisterTabletResult, Handle); - HFuncTraced(TEvMediatorTimecast::TEvNotifyPlanStep, Handle); + HFuncTraced(TEvMediatorTimecast::TEvNotifyPlanStep, Handle); HFuncTraced(TEvDataShard::TEvCancelTransactionProposal, Handle); HFuncTraced(NSchemeShard::TEvSchemeShard::TEvDescribeSchemeResult, Handle); HFunc(TEvDataShard::TEvReturnBorrowedPart, Handle); diff --git a/ydb/core/tx/datashard/datashard_kqp_compute.cpp b/ydb/core/tx/datashard/datashard_kqp_compute.cpp index a26c774741..edd6ca8e19 100644 --- a/ydb/core/tx/datashard/datashard_kqp_compute.cpp +++ b/ydb/core/tx/datashard/datashard_kqp_compute.cpp @@ -160,11 +160,11 @@ void TKqpDatashardComputeContext::ReadTable(const TTableId& tableId, const TArra Shard->SetTableAccessTime(tableId, Now); } -void TKqpDatashardComputeContext::BreakSetLocks() const { - MKQL_ENSURE_S(Shard); - Shard->SysLocksTable().BreakSetLocks(LockTxId); -} - +void TKqpDatashardComputeContext::BreakSetLocks() const { + MKQL_ENSURE_S(Shard); + Shard->SysLocksTable().BreakSetLocks(LockTxId); +} + void TKqpDatashardComputeContext::SetLockTxId(ui64 lockTxId) { LockTxId = lockTxId; } @@ -173,16 +173,16 @@ ui64 TKqpDatashardComputeContext::GetShardId() const { return Shard->TabletID(); } -void TKqpDatashardComputeContext::SetReadVersion(TRowVersion readVersion) { - ReadVersion = readVersion; -} - -TRowVersion TKqpDatashardComputeContext::GetReadVersion() const { - Y_VERIFY(!ReadVersion.IsMin(), "Cannot perform reads without ReadVersion set"); - - return ReadVersion; -} - +void TKqpDatashardComputeContext::SetReadVersion(TRowVersion readVersion) { + ReadVersion = readVersion; +} + +TRowVersion TKqpDatashardComputeContext::GetReadVersion() const { + Y_VERIFY(!ReadVersion.IsMin(), "Cannot perform reads without ReadVersion set"); + + return ReadVersion; +} + void TKqpDatashardComputeContext::SetTaskOutputChannel(ui64 taskId, ui64 channelId, TActorId actorId) { OutputChannels.emplace(std::make_pair(taskId, channelId), actorId); } @@ -259,7 +259,7 @@ bool TKqpDatashardComputeContext::PinPages(const TVector<IEngineFlat::TValidated adjustLimit(key.RangeLimits.ItemsLimit), adjustLimit(key.RangeLimits.BytesLimit), key.Reverse ? NTable::EDirection::Reverse : NTable::EDirection::Forward, - GetReadVersion()); + GetReadVersion()); LOG_TRACE_S(*TlsActivationContext, NKikimrServices::TX_DATASHARD, "Run precharge on table " << tableInfo->Name << ", columns: [" << JoinSeq(", ", columnTags) << "]" diff --git a/ydb/core/tx/datashard/datashard_kqp_compute.h b/ydb/core/tx/datashard/datashard_kqp_compute.h index a742658064..4bbb8fa0de 100644 --- a/ydb/core/tx/datashard/datashard_kqp_compute.h +++ b/ydb/core/tx/datashard/datashard_kqp_compute.h @@ -32,7 +32,7 @@ public: const NDataShard::TUserTable* GetTable(const TTableId& tableId) const; void ReadTable(const TTableId& tableId, const TTableRange& range) const; void ReadTable(const TTableId& tableId, const TArrayRef<const TCell>& key) const; - void BreakSetLocks() const; + void BreakSetLocks() const; void SetLockTxId(ui64 lockTxId); ui64 GetShardId() const; @@ -49,9 +49,9 @@ public: void Clear(); - void SetReadVersion(TRowVersion readVersion); - TRowVersion GetReadVersion() const; - + void SetReadVersion(TRowVersion readVersion); + TRowVersion GetReadVersion() const; + TEngineHostCounters& GetTaskCounters(ui64 taskId) { return TaskCounters[taskId]; } TEngineHostCounters& GetDatashardCounters() { return DatashardCounters; } @@ -69,7 +69,7 @@ private: ui64 LockTxId = 0; bool PersistentChannels = false; bool TabletNotReady = false; - TRowVersion ReadVersion = TRowVersion::Min(); + TRowVersion ReadVersion = TRowVersion::Min(); THashMap<std::pair<ui64, ui64>, TActorId> OutputChannels; }; diff --git a/ydb/core/tx/datashard/datashard_kqp_lookup_table.cpp b/ydb/core/tx/datashard/datashard_kqp_lookup_table.cpp index 2630e7c474..24582c2664 100644 --- a/ydb/core/tx/datashard/datashard_kqp_lookup_table.cpp +++ b/ydb/core/tx/datashard/datashard_kqp_lookup_table.cpp @@ -127,12 +127,12 @@ public: ComputeCtx.ReadTable(ParseResult.TableId, keyCells); NTable::TRowState dbRow; - NTable::TSelectStats stats; + NTable::TSelectStats stats; ui64 flags = 0; // TODO: Check DisableByKeyFilter - auto ready = ComputeCtx.Database->Select(LocalTid, keyValues, ColumnTags, dbRow, stats, flags, ComputeCtx.GetReadVersion()); - if (stats.Invisible) - ComputeCtx.BreakSetLocks(); - + auto ready = ComputeCtx.Database->Select(LocalTid, keyValues, ColumnTags, dbRow, stats, flags, ComputeCtx.GetReadVersion()); + if (stats.Invisible) + ComputeCtx.BreakSetLocks(); + switch (ready) { case EReady::Page: ComputeCtx.SetTabletNotReady(); @@ -247,7 +247,7 @@ public: keyRange.MaxInclusive = range.InclusiveTo; ComputeCtx.ReadTable(ParseResult.TableId, range); - Iterator = ComputeCtx.Database->IterateRange(LocalTid, keyRange, ColumnTags, ComputeCtx.GetReadVersion()); + Iterator = ComputeCtx.Database->IterateRange(LocalTid, keyRange, ColumnTags, ComputeCtx.GetReadVersion()); break; } @@ -265,7 +265,7 @@ public: auto fetched = TryFetchRow(*Iterator, result, ctx, tableStats, ComputeCtx, SystemColumnTags, ParseResult.SkipNullKeys); if (Iterator->Stats.InvisibleRowSkips) { - ComputeCtx.BreakSetLocks(); + ComputeCtx.BreakSetLocks(); } ShardTableStats += tableStats; @@ -280,7 +280,7 @@ public: TaskTableStats.SelectRangeDeletedRowSkips += deletedRowSkips; TaskTableStats.InvisibleRowSkips += invisibleRowSkips; - if (fetched) { + if (fetched) { return result; } diff --git a/ydb/core/tx/datashard/datashard_kqp_read_table.cpp b/ydb/core/tx/datashard/datashard_kqp_read_table.cpp index dbc0e935c8..9fbd8ef0ad 100644 --- a/ydb/core/tx/datashard/datashard_kqp_read_table.cpp +++ b/ydb/core/tx/datashard/datashard_kqp_read_table.cpp @@ -221,10 +221,10 @@ protected: virtual EFetchResult ReadValue(TComputationContext& ctx, NUdf::TUnboxedValue* const* output) const = 0; EFetchResult ReadNext(NUdf::TUnboxedValue* const* output) const { - bool breakLocks = false; + bool breakLocks = false; while (Iterator->Next(NTable::ENext::Data) == NTable::EReady::Data) { if (!breakLocks && (breakLocks = bool(Iterator->Stats.InvisibleRowSkips))) { - ComputeCtx.BreakSetLocks(); + ComputeCtx.BreakSetLocks(); } TDbTupleRef rowKey = Iterator->GetKey(); @@ -293,12 +293,12 @@ protected: } if (!breakLocks && bool(Iterator->Stats.InvisibleRowSkips)) { - ComputeCtx.BreakSetLocks(); + ComputeCtx.BreakSetLocks(); } - + auto deletedRowSkips = std::exchange(Iterator->Stats.DeletedRowSkips, 0); auto invisibleRowSkips = std::exchange(Iterator->Stats.InvisibleRowSkips, 0); - + ShardTableStats.SelectRangeDeletedRowSkips += deletedRowSkips; ShardTableStats.InvisibleRowSkips += invisibleRowSkips; diff --git a/ydb/core/tx/datashard/datashard_locks.cpp b/ydb/core/tx/datashard/datashard_locks.cpp index 29cbb2e4b9..aa5fc3876b 100644 --- a/ydb/core/tx/datashard/datashard_locks.cpp +++ b/ydb/core/tx/datashard/datashard_locks.cpp @@ -44,18 +44,18 @@ bool TLockInfo::AddRange(const TRangeKey& range) { return !ShardLock; } -void TLockInfo::SetBroken(const TRowVersion& at) { +void TLockInfo::SetBroken(const TRowVersion& at) { #if 1 // optimisation: remove at next Remove - if (!IsBroken(at)) - Locker->ScheduleLockCleanup(LockId, at); + if (!IsBroken(at)) + Locker->ScheduleLockCleanup(LockId, at); #endif - - if (!BreakVersion || at < *BreakVersion) - BreakVersion.emplace(at.Step, at.TxId); - - if (at) - return; // if break version is not TrowVersion::Min() we will postpone actual ranges removal - + + if (!BreakVersion || at < *BreakVersion) + BreakVersion.emplace(at.Step, at.TxId); + + if (at) + return; // if break version is not TrowVersion::Min() we will postpone actual ranges removal + Points.clear(); Ranges.clear(); } @@ -94,9 +94,9 @@ void TTableLocks::RemoveLock(const TLockInfo::TPtr& lock) { Ranges.RemoveRanges(lock.Get()); } -void TTableLocks::BreakLocks(TConstArrayRef<TCell> key, const TRowVersion& at) { - Ranges.EachIntersection(key, [&](const TRangeTreeBase::TRange&, TLockInfo* lock) { - lock->SetBroken(at); +void TTableLocks::BreakLocks(TConstArrayRef<TCell> key, const TRowVersion& at) { + Ranges.EachIntersection(key, [&](const TRangeTreeBase::TRange&, TLockInfo* lock) { + lock->SetBroken(at); }); } @@ -110,7 +110,7 @@ void TTableLocks::BreakAllLocks(const TRowVersion& at) { TLockInfo::TPtr TLockLocker::AddShardLock(ui64 lockTxId, const THashSet<TPathId>& affectedTables, const TRowVersion& at) { TLockInfo::TPtr lock = GetOrAddLock(lockTxId); - if (!lock || lock->IsBroken(at)) + if (!lock || lock->IsBroken(at)) return lock; ShardLocks.insert(lockTxId); @@ -121,9 +121,9 @@ TLockInfo::TPtr TLockLocker::AddShardLock(ui64 lockTxId, const THashSet<TPathId> return lock; } -TLockInfo::TPtr TLockLocker::AddPointLock(ui64 lockId, const TPointKey& point, const TRowVersion& at) { +TLockInfo::TPtr TLockLocker::AddPointLock(ui64 lockId, const TPointKey& point, const TRowVersion& at) { TLockInfo::TPtr lock = GetOrAddLock(lockId); - if (!lock || lock->IsBroken(at)) + if (!lock || lock->IsBroken(at)) return lock; if (lock->AddPoint(point)) { @@ -132,9 +132,9 @@ TLockInfo::TPtr TLockLocker::AddPointLock(ui64 lockId, const TPointKey& point, c return lock; } -TLockInfo::TPtr TLockLocker::AddRangeLock(ui64 lockId, const TRangeKey& range, const TRowVersion& at) { +TLockInfo::TPtr TLockLocker::AddRangeLock(ui64 lockId, const TRangeKey& range, const TRowVersion& at) { TLockInfo::TPtr lock = GetOrAddLock(lockId); - if (!lock || lock->IsBroken(at)) + if (!lock || lock->IsBroken(at)) return lock; if (lock->AddRange(range)) { @@ -143,30 +143,30 @@ TLockInfo::TPtr TLockLocker::AddRangeLock(ui64 lockId, const TRangeKey& range, c return lock; } -TLockInfo::TPtr TLockLocker::GetLock(ui64 lockTxId, const TRowVersion& at) const { +TLockInfo::TPtr TLockLocker::GetLock(ui64 lockTxId, const TRowVersion& at) const { auto it = Locks.find(lockTxId); if (it != Locks.end()) { TLockInfo::TPtr lock = it->second; - if (!lock->IsBroken(at)) + if (!lock->IsBroken(at)) return lock; } return nullptr; } -void TLockLocker::BreakShardLocks(const TRowVersion& at) { +void TLockLocker::BreakShardLocks(const TRowVersion& at) { for (ui64 lockId : ShardLocks) { auto it = Locks.find(lockId); if (it != Locks.end()) { - it->second->SetBroken(at); + it->second->SetBroken(at); } } - if (!at) - ShardLocks.clear(); + if (!at) + ShardLocks.clear(); RemoveBrokenRanges(); } -void TLockLocker::BreakLocks(const TPointKey& point, const TRowVersion& at) { - point.Table->BreakLocks(point.Key, at); +void TLockLocker::BreakLocks(const TPointKey& point, const TRowVersion& at) { + point.Table->BreakLocks(point.Key, at); RemoveBrokenRanges(); } @@ -195,32 +195,32 @@ void TLockLocker::RemoveBrokenRanges() { } } CleanupPending.clear(); - - if (CleanupCandidates.empty()) - return; - - auto till = Self->LastCompleteTxVersion(); - while (!CleanupCandidates.empty() && CleanupCandidates.top().Version <= till) { - ui64 lockId = CleanupCandidates.top().LockId; - CleanupCandidates.pop(); - - auto it = Locks.find(lockId); - if (it != Locks.end()) { - const TLockInfo::TPtr& lock = it->second; - - lock->BreakVersion = TRowVersion::Min(); - lock->Points.clear(); - lock->Ranges.clear(); - - if (!lock->IsShardLock()) { + + if (CleanupCandidates.empty()) + return; + + auto till = Self->LastCompleteTxVersion(); + while (!CleanupCandidates.empty() && CleanupCandidates.top().Version <= till) { + ui64 lockId = CleanupCandidates.top().LockId; + CleanupCandidates.pop(); + + auto it = Locks.find(lockId); + if (it != Locks.end()) { + const TLockInfo::TPtr& lock = it->second; + + lock->BreakVersion = TRowVersion::Min(); + lock->Points.clear(); + lock->Ranges.clear(); + + if (!lock->IsShardLock()) { for (const TPathId& tableId : lock->GetAffectedTables()) { - Tables[tableId]->RemoveLock(lock); - } - } else { - ShardLocks.erase(lockId); - } - } - } + Tables[tableId]->RemoveLock(lock); + } + } else { + ShardLocks.erase(lockId); + } + } + } } TLockInfo::TPtr TLockLocker::GetOrAddLock(ui64 lockId) { @@ -264,24 +264,24 @@ void TLockLocker::RemoveBrokenLocks() { RemoveOneLock(lockId); } BrokenLocks.clear(); - - if (BrokenCandidates.empty()) - return; - - auto till = Self->LastCompleteTxVersion(); - while (!BrokenCandidates.empty() && BrokenCandidates.top().Version <= till) { - RemoveOneLock(BrokenCandidates.top().LockId); - BrokenCandidates.pop(); - } -} - -void TLockLocker::BreakLock(ui64 lockId, const TRowVersion& at) { - if (auto lock = GetLock(lockId, at)) - lock->SetBroken(at); - - RemoveBrokenLocks(); -} - + + if (BrokenCandidates.empty()) + return; + + auto till = Self->LastCompleteTxVersion(); + while (!BrokenCandidates.empty() && BrokenCandidates.top().Version <= till) { + RemoveOneLock(BrokenCandidates.top().LockId); + BrokenCandidates.pop(); + } +} + +void TLockLocker::BreakLock(ui64 lockId, const TRowVersion& at) { + if (auto lock = GetLock(lockId, at)) + lock->SetBroken(at); + + RemoveBrokenLocks(); +} + void TLockLocker::RemoveLock(ui64 lockId) { RemoveBrokenLocks(); RemoveOneLock(lockId); @@ -309,15 +309,15 @@ bool TLockLocker::ForceShardLock(const THashSet<TPathId>& rangeTables) const { return false; } -void TLockLocker::ScheduleLockCleanup(ui64 lockId, const TRowVersion& at) { - if (at) { - BrokenCandidates.emplace(lockId, at); - CleanupCandidates.emplace(lockId, at); - } else { - BrokenLocks.push_back(lockId); - CleanupPending.push_back(lockId); - } - +void TLockLocker::ScheduleLockCleanup(ui64 lockId, const TRowVersion& at) { + if (at) { + BrokenCandidates.emplace(lockId, at); + CleanupCandidates.emplace(lockId, at); + } else { + BrokenLocks.push_back(lockId); + CleanupPending.push_back(lockId); + } + if (Self->TabletCounters) { Self->IncCounter(COUNTER_LOCKS_BROKEN); } @@ -365,16 +365,16 @@ TVector<TSysLocks::TLock> TSysLocks::ApplyLocks() { TMicrosecTimerCounter measureApplyLocks(*Self, COUNTER_APPLY_LOCKS_USEC); - auto &checkVersion = Update->CheckVersion; - auto &breakVersion = Update->BreakVersion; - + auto &checkVersion = Update->CheckVersion; + auto &breakVersion = Update->BreakVersion; + if (Update->ShardBreak) { - Locker.BreakShardLocks(breakVersion); + Locker.BreakShardLocks(breakVersion); } if (Update->PointBreaks.size()) { for (const auto& key : Update->PointBreaks) { - Locker.BreakLocks(key, breakVersion); + Locker.BreakLocks(key, breakVersion); } } @@ -390,10 +390,10 @@ TVector<TSysLocks::TLock> TSysLocks::ApplyLocks() { for (ui64 lockId : Update->Erases) { Y_VERIFY(!Update->HasLocks(), "Can't erase and set locks in one Tx"); - if (breakVersion) - Locker.BreakLock(lockId, breakVersion); - else - Locker.RemoveLock(lockId); + if (breakVersion) + Locker.BreakLock(lockId, breakVersion); + else + Locker.RemoveLock(lockId); } if (!Update->HasLocks()) @@ -404,32 +404,32 @@ TVector<TSysLocks::TLock> TSysLocks::ApplyLocks() { ui64 counter = TLock::ErrorNotSet; ui32 numNotSet = 0; - if (Update->BreakOwn) { - counter = TLock::ErrorAlreadyBroken; - } else if (Update->ShardLock) { - TLockInfo::TPtr lock = Locker.AddShardLock(Update->LockTxId, Update->AffectedTables, checkVersion); + if (Update->BreakOwn) { + counter = TLock::ErrorAlreadyBroken; + } else if (Update->ShardLock) { + TLockInfo::TPtr lock = Locker.AddShardLock(Update->LockTxId, Update->AffectedTables, checkVersion); if (lock) { - Y_VERIFY(counter == lock->GetCounter(checkVersion) || TLock::IsNotSet(counter)); - counter = lock->GetCounter(checkVersion); + Y_VERIFY(counter == lock->GetCounter(checkVersion) || TLock::IsNotSet(counter)); + counter = lock->GetCounter(checkVersion); } else { ++numNotSet; } } else { for (const auto& key : Update->PointLocks) { - TLockInfo::TPtr lock = Locker.AddPointLock(Update->LockTxId, key, checkVersion); + TLockInfo::TPtr lock = Locker.AddPointLock(Update->LockTxId, key, checkVersion); if (lock) { - Y_VERIFY(counter == lock->GetCounter(checkVersion) || TLock::IsNotSet(counter)); - counter = lock->GetCounter(checkVersion); + Y_VERIFY(counter == lock->GetCounter(checkVersion) || TLock::IsNotSet(counter)); + counter = lock->GetCounter(checkVersion); } else { ++numNotSet; } } for (const auto& key : Update->RangeLocks) { - TLockInfo::TPtr lock = Locker.AddRangeLock(Update->LockTxId, key, checkVersion); + TLockInfo::TPtr lock = Locker.AddRangeLock(Update->LockTxId, key, checkVersion); if (lock) { - Y_VERIFY(counter == lock->GetCounter(checkVersion) || TLock::IsNotSet(counter)); - counter = lock->GetCounter(checkVersion); + Y_VERIFY(counter == lock->GetCounter(checkVersion) || TLock::IsNotSet(counter)); + counter = lock->GetCounter(checkVersion); } else { ++numNotSet; } @@ -488,15 +488,15 @@ TSysLocks::TLock TSysLocks::GetLock(const TArrayRef<const TCell>& key) const { return TLock(); } - Y_VERIFY(Update); - - auto &checkVersion = Update->CheckVersion; - TLockInfo::TPtr txLock = Locker.GetLock(lockTxId, checkVersion); + Y_VERIFY(Update); + + auto &checkVersion = Update->CheckVersion; + TLockInfo::TPtr txLock = Locker.GetLock(lockTxId, checkVersion); if (txLock) { const auto& tableIds = txLock->GetAffectedTables(); if (key.size() == 2) { // locks v1 Y_VERIFY(tableIds.size() == 1); - return MakeAndLogLock(lockTxId, txLock->GetCounter(checkVersion), *tableIds.begin()); + return MakeAndLogLock(lockTxId, txLock->GetCounter(checkVersion), *tableIds.begin()); } else { // locks v2 Y_VERIFY(key.size() == 4); TPathId tableId; @@ -563,13 +563,13 @@ void TSysLocks::BreakAllLocks(const TTableId& tableId) { Update->BreakShardLock(); } -void TSysLocks::BreakSetLocks(ui64 lockTxId) { - Y_VERIFY(Update); - - if (lockTxId) - Update->BreakSetLocks(lockTxId); -} - +void TSysLocks::BreakSetLocks(ui64 lockTxId) { + Y_VERIFY(Update); + + if (lockTxId) + Update->BreakSetLocks(lockTxId); +} + bool TSysLocks::IsMyKey(const TArrayRef<const TCell>& key) const { ui64 tabletId; bool ok = TLocksTable::ExtractKey(key, TLocksTable::EColumns::DataShard, tabletId); diff --git a/ydb/core/tx/datashard/datashard_locks.h b/ydb/core/tx/datashard/datashard_locks.h index e4d2bc2f2e..19c68c4d88 100644 --- a/ydb/core/tx/datashard/datashard_locks.h +++ b/ydb/core/tx/datashard/datashard_locks.h @@ -8,7 +8,7 @@ #include <ydb/core/tablet/tablet_counters.h> #include <library/cpp/cache/cache.h> -#include <util/generic/queue.h> +#include <util/generic/queue.h> #include <util/generic/set.h> #include <util/system/valgrind.h> @@ -38,7 +38,7 @@ public: virtual ui64 TabletID() const = 0; virtual bool IsUserTable(const TTableId& tableId) const = 0; virtual ui32 Generation() const = 0; - virtual TRowVersion LastCompleteTxVersion() const = 0; + virtual TRowVersion LastCompleteTxVersion() const = 0; TTabletCountersBase* const &TabletCounters; }; @@ -86,11 +86,11 @@ public: return Self->Generation(); } - TRowVersion LastCompleteTxVersion() const override - { - return Self->LastCompleteTxVersion(); - } - + TRowVersion LastCompleteTxVersion() const override + { + return Self->LastCompleteTxVersion(); + } + private: const T *Self; }; @@ -122,19 +122,19 @@ struct TRangeKey { } }; -struct TVersionedLockId { - TVersionedLockId(ui64 lockId, TRowVersion version) - : LockId(lockId) - , Version(version) {} - - ui64 LockId; - TRowVersion Version; - - bool operator<(const TVersionedLockId& other) const { - return Version < other.Version; - } -}; - +struct TVersionedLockId { + TVersionedLockId(ui64 lockId, TRowVersion version) + : LockId(lockId) + , Version(version) {} + + ui64 LockId; + TRowVersion Version; + + bool operator<(const TVersionedLockId& other) const { + return Version < other.Version; + } +}; + /// Aggregates shard, point and range locks class TLockInfo : public TSimpleRefCount<TLockInfo> { friend class TTableLocks; @@ -146,8 +146,8 @@ public: TLockInfo(TLockLocker * locker, ui64 lockId); ~TLockInfo(); - ui64 GetCounter(const TRowVersion& at = TRowVersion::Max()) const { return !BreakVersion || at < *BreakVersion ? Counter : Max<ui64>(); } - bool IsBroken(const TRowVersion& at = TRowVersion::Max()) const { return GetCounter(at) == Max<ui64>(); } + ui64 GetCounter(const TRowVersion& at = TRowVersion::Max()) const { return !BreakVersion || at < *BreakVersion ? Counter : Max<ui64>(); } + bool IsBroken(const TRowVersion& at = TRowVersion::Max()) const { return GetCounter(at) == Max<ui64>(); } size_t NumPoints() const { return Points.size(); } size_t NumRanges() const { return Ranges.size(); } @@ -168,7 +168,7 @@ private: void AddShardLock(const THashSet<TPathId>& affectedTables); bool AddPoint(const TPointKey& point); bool AddRange(const TRangeKey& range); - void SetBroken(const TRowVersion& at); + void SetBroken(const TRowVersion& at); private: TLockLocker * Locker; @@ -179,8 +179,8 @@ private: TVector<TPointKey> Points; TVector<TRangeKey> Ranges; bool ShardLock = false; - - std::optional<TRowVersion> BreakVersion; + + std::optional<TRowVersion> BreakVersion; }; /// @@ -199,7 +199,7 @@ public: void AddPointLock(const TPointKey& point, const TLockInfo::TPtr& lock); void AddRangeLock(const TRangeKey& range, const TLockInfo::TPtr& lock); void RemoveLock(const TLockInfo::TPtr& lock); - void BreakLocks(TConstArrayRef<TCell> key, const TRowVersion& at); + void BreakLocks(TConstArrayRef<TCell> key, const TRowVersion& at); void BreakAllLocks(const TRowVersion& at); ui64 NumKeyColumns() const { @@ -281,17 +281,17 @@ public: } TLockInfo::TPtr AddShardLock(ui64 lockTxId, const THashSet<TPathId>& affectedTables, const TRowVersion& at); - TLockInfo::TPtr AddPointLock(ui64 lockTxId, const TPointKey& key, const TRowVersion& at); - TLockInfo::TPtr AddRangeLock(ui64 lockTxId, const TRangeKey& key, const TRowVersion& at); - TLockInfo::TPtr GetLock(ui64 lockTxId, const TRowVersion& at) const; + TLockInfo::TPtr AddPointLock(ui64 lockTxId, const TPointKey& key, const TRowVersion& at); + TLockInfo::TPtr AddRangeLock(ui64 lockTxId, const TRangeKey& key, const TRowVersion& at); + TLockInfo::TPtr GetLock(ui64 lockTxId, const TRowVersion& at) const; ui64 LocksCount() const { return Locks.size(); } - ui64 BrokenLocksCount() const { return BrokenLocks.size() + BrokenCandidates.size(); } + ui64 BrokenLocksCount() const { return BrokenLocks.size() + BrokenCandidates.size(); } - void BreakShardLocks(const TRowVersion& at); - void BreakLocks(const TPointKey& point, const TRowVersion& at); + void BreakShardLocks(const TRowVersion& at); + void BreakLocks(const TPointKey& point, const TRowVersion& at); void BreakAllLocks(const TPathId& pathId, const TRowVersion& at); - void BreakLock(ui64 lockTxId, const TRowVersion& at); + void BreakLock(ui64 lockTxId, const TRowVersion& at); void RemoveLock(ui64 lockTxId); bool TableHasLocks(const TTableId& tableId) const { @@ -324,7 +324,7 @@ public: bool ForceShardLock(const THashSet<TPathId>& rangeTables) const; // optimisation: set to remove broken lock at next Remove() - void ScheduleLockCleanup(ui64 lockId, const TRowVersion& at); + void ScheduleLockCleanup(ui64 lockId, const TRowVersion& at); ui64 IncCounter() { return Counter++; }; @@ -335,8 +335,8 @@ private: THashSet<ui64> ShardLocks; TVector<ui64> BrokenLocks; // LockIds of broken locks (optimisation) TVector<ui64> CleanupPending; // LockIds of broken locks with pending cleanup - TPriorityQueue<TVersionedLockId> BrokenCandidates; - TPriorityQueue<TVersionedLockId> CleanupCandidates; + TPriorityQueue<TVersionedLockId> BrokenCandidates; + TPriorityQueue<TVersionedLockId> CleanupCandidates; TLockLimiter Limiter; ui64 Counter; @@ -366,11 +366,11 @@ struct TLocksUpdate { THashSet<TPathId> AffectedTables; THashSet<TPathId> RangeTables; - TRowVersion CheckVersion = TRowVersion::Max(); - TRowVersion BreakVersion = TRowVersion::Min(); - - bool BreakOwn = false; - + TRowVersion CheckVersion = TRowVersion::Max(); + TRowVersion BreakVersion = TRowVersion::Min(); + + bool BreakOwn = false; + void Clear() { LockTxId = 0; ShardLock = false; @@ -413,11 +413,11 @@ struct TLocksUpdate { void EraseLock(ui64 lockId) { Erases.push_back(lockId); } - - void BreakSetLocks(ui64 lockId) { - Y_VERIFY(LockTxId == lockId); - BreakOwn = true; - } + + void BreakSetLocks(ui64 lockId) { + Y_VERIFY(LockTxId == lockId); + BreakOwn = true; + } }; struct TLocksCache { @@ -472,20 +472,20 @@ public: void SetLock(const TTableId& tableId, const TTableRange& range, ui64 lockTxId); void BreakLock(const TTableId& tableId, const TArrayRef<const TCell>& key); void BreakAllLocks(const TTableId& tableId); - void BreakSetLocks(ui64 lockTxId); + void BreakSetLocks(ui64 lockTxId); bool IsMyKey(const TArrayRef<const TCell>& key) const; ui64 LocksCount() const { return Locker.LocksCount(); } ui64 BrokenLocksCount() const { return Locker.BrokenLocksCount(); } - TLockInfo::TPtr GetRawLock(ui64 lockTxId, const TRowVersion& at = TRowVersion::Max()) const { - return Locker.GetLock(lockTxId, at); + TLockInfo::TPtr GetRawLock(ui64 lockTxId, const TRowVersion& at = TRowVersion::Max()) const { + return Locker.GetLock(lockTxId, at); } - bool IsBroken(ui64 lockTxId, const TRowVersion& at = TRowVersion::Max()) const { - TLockInfo::TPtr txLock = Locker.GetLock(lockTxId, at); + bool IsBroken(ui64 lockTxId, const TRowVersion& at = TRowVersion::Max()) const { + TLockInfo::TPtr txLock = Locker.GetLock(lockTxId, at); if (txLock) - return txLock->IsBroken(at); + return txLock->IsBroken(at); return true; } diff --git a/ydb/core/tx/datashard/datashard_pipeline.cpp b/ydb/core/tx/datashard/datashard_pipeline.cpp index b471c5a2a5..3498162c17 100644 --- a/ydb/core/tx/datashard/datashard_pipeline.cpp +++ b/ydb/core/tx/datashard/datashard_pipeline.cpp @@ -372,7 +372,7 @@ TOperation::TPtr TPipeline::GetNextActiveOp(bool dryRun) return nullptr; } -TOperation::TPtr TPipeline::GetNextPlannedOp(ui64 step, ui64 txId) const { +TOperation::TPtr TPipeline::GetNextPlannedOp(ui64 step, ui64 txId) const { TOperation::TPtr op; while (!op) { if (!Self->TransQueue.GetNextPlannedTxId(step, txId)) @@ -841,7 +841,7 @@ bool TPipeline::PlanTxs(ui64 step, AddCandidateUnit(EExecutionUnitKind::PlanQueue); MaybeActivateWaitingSchemeOps(ctx); - ActivateWaitingTxOps(ctx); + ActivateWaitingTxOps(ctx); return true; } @@ -872,7 +872,7 @@ void TPipeline::CompleteTx(const TOperation::TPtr op, TTransactionContext& txc, MarkPlannedLogicallyCompleteUpTo(TRowVersion(op->GetStep(), op->GetTxId()), txc); Self->PromoteCompleteEdge(op.Get(), txc); } - + Y_VERIFY(ActivePlannedOps); if (ActivePlannedOps.begin()->first == op->GetStepOrder()) { LastCompleteTx = op->GetStepOrder(); @@ -903,7 +903,7 @@ void TPipeline::CompleteTx(const TOperation::TPtr op, TTransactionContext& txc, // FIXME: probably not needed, (txinfly - planned) does not change on completion MaybeActivateWaitingSchemeOps(ctx); - ActivateWaitingTxOps(ctx); + ActivateWaitingTxOps(ctx); } void TPipeline::PreserveSchema(NIceDb::TNiceDb& db, ui64 step) { @@ -1274,53 +1274,53 @@ TOperation::TPtr TPipeline::BuildOperation(TEvDataShard::TEvProposeTransaction:: tx->SetForceDirtyFlag(); } } - - if (!tx->IsMvccSnapshotRead()) { - // No op - } else if (tx->IsReadTable() && dataTx->GetReadTableTransaction().HasSnapshotStep() && dataTx->GetReadTableTransaction().HasSnapshotTxId()) { - tx->SetAbortedFlag(); - TString err = "Ambiguous snapshot info. Cannot use both MVCC and read table snapshots in one transaction"; + + if (!tx->IsMvccSnapshotRead()) { + // No op + } else if (tx->IsReadTable() && dataTx->GetReadTableTransaction().HasSnapshotStep() && dataTx->GetReadTableTransaction().HasSnapshotTxId()) { + tx->SetAbortedFlag(); + TString err = "Ambiguous snapshot info. Cannot use both MVCC and read table snapshots in one transaction"; tx->Result().Reset(new TEvDataShard::TEvProposeTransactionResult(rec.GetTxKind(), - Self->TabletID(), - tx->GetTxId(), + Self->TabletID(), + tx->GetTxId(), NKikimrTxDataShard::TEvProposeTransactionResult::BAD_REQUEST)); - tx->Result()->SetProcessError(NKikimrTxDataShard::TError::BAD_ARGUMENT, err); - LOG_ERROR_S(TActivationContext::AsActorContext(), NKikimrServices::TX_DATASHARD, err); - - return tx; - } else if (tx->IsKqpScanTransaction() && dataTx->GetKqpTransaction().HasSnapshot()) { - tx->SetAbortedFlag(); - TString err = "Ambiguous snapshot info. Cannot use both MVCC and kqp scan snapshots in one transaction"; + tx->Result()->SetProcessError(NKikimrTxDataShard::TError::BAD_ARGUMENT, err); + LOG_ERROR_S(TActivationContext::AsActorContext(), NKikimrServices::TX_DATASHARD, err); + + return tx; + } else if (tx->IsKqpScanTransaction() && dataTx->GetKqpTransaction().HasSnapshot()) { + tx->SetAbortedFlag(); + TString err = "Ambiguous snapshot info. Cannot use both MVCC and kqp scan snapshots in one transaction"; tx->Result().Reset(new TEvDataShard::TEvProposeTransactionResult(rec.GetTxKind(), - Self->TabletID(), - tx->GetTxId(), + Self->TabletID(), + tx->GetTxId(), NKikimrTxDataShard::TEvProposeTransactionResult::BAD_REQUEST)); - tx->Result()->SetProcessError(NKikimrTxDataShard::TError::BAD_ARGUMENT,err); - LOG_ERROR_S(TActivationContext::AsActorContext(), NKikimrServices::TX_DATASHARD, err); - - return tx; - } - - if(tx->IsMvccSnapshotRead() && (!tx->IsImmediate() || !tx->IsReadOnly())) { - tx->SetAbortedFlag(); - TString err = "Snapshot read must be an immediate read only transaction"; + tx->Result()->SetProcessError(NKikimrTxDataShard::TError::BAD_ARGUMENT,err); + LOG_ERROR_S(TActivationContext::AsActorContext(), NKikimrServices::TX_DATASHARD, err); + + return tx; + } + + if(tx->IsMvccSnapshotRead() && (!tx->IsImmediate() || !tx->IsReadOnly())) { + tx->SetAbortedFlag(); + TString err = "Snapshot read must be an immediate read only transaction"; tx->Result().Reset(new TEvDataShard::TEvProposeTransactionResult(rec.GetTxKind(), - Self->TabletID(), - tx->GetTxId(), + Self->TabletID(), + tx->GetTxId(), NKikimrTxDataShard::TEvProposeTransactionResult::BAD_REQUEST)); - tx->Result()->SetProcessError(NKikimrTxDataShard::TError::BAD_ARGUMENT,err); - LOG_ERROR_S(TActivationContext::AsActorContext(), NKikimrServices::TX_DATASHARD, err); - - return tx; - } - + tx->Result()->SetProcessError(NKikimrTxDataShard::TError::BAD_ARGUMENT,err); + LOG_ERROR_S(TActivationContext::AsActorContext(), NKikimrServices::TX_DATASHARD, err); + + return tx; + } + if (!tx->IsImmediate() || !Self->IsMvccEnabled()) { - // No op - } else if (tx->IsKqpScanTransaction() && dataTx->GetKqpTransaction().HasSnapshot()) { - // to be consistent while dependencies calculation - auto snapshot = dataTx->GetKqpTransaction().GetSnapshot(); - tx->SetMvccSnapshot(TRowVersion(snapshot.GetStep(), snapshot.GetTxId())); - } + // No op + } else if (tx->IsKqpScanTransaction() && dataTx->GetKqpTransaction().HasSnapshot()) { + // to be consistent while dependencies calculation + auto snapshot = dataTx->GetKqpTransaction().GetSnapshot(); + tx->SetMvccSnapshot(TRowVersion(snapshot.GetStep(), snapshot.GetTxId())); + } } return tx; @@ -1572,56 +1572,56 @@ void TPipeline::MaybeActivateWaitingSchemeOps(const TActorContext& ctx) const { } } -bool TPipeline::AddWaitingTxOp(TEvDataShard::TEvProposeTransaction::TPtr& ev, const TActorContext& ctx) { - // check in-flight limit - size_t totalInFly = (Self->TxInFly() + Self->ImmediateInFly() + Self->ProposeQueue.Size() + WaitingDataTxOps.size()); - if (totalInFly > Self->GetMaxTxInFly()) - return false; // let tx to be rejected - - if (Self->MvccSwitchState == TSwitchState::SWITCHING) { - WaitingDataTxOps.emplace(TRowVersion::Min(), std::move(ev)); // postpone tx processing till mvcc state switch is finished - } else { - Y_VERIFY_DEBUG(ev->Get()->Record.HasMvccSnapshot()); - TRowVersion snapshot(ev->Get()->Record.GetMvccSnapshot().GetStep(), ev->Get()->Record.GetMvccSnapshot().GetTxId()); - WaitingDataTxOps.emplace(snapshot, std::move(ev)); +bool TPipeline::AddWaitingTxOp(TEvDataShard::TEvProposeTransaction::TPtr& ev, const TActorContext& ctx) { + // check in-flight limit + size_t totalInFly = (Self->TxInFly() + Self->ImmediateInFly() + Self->ProposeQueue.Size() + WaitingDataTxOps.size()); + if (totalInFly > Self->GetMaxTxInFly()) + return false; // let tx to be rejected + + if (Self->MvccSwitchState == TSwitchState::SWITCHING) { + WaitingDataTxOps.emplace(TRowVersion::Min(), std::move(ev)); // postpone tx processing till mvcc state switch is finished + } else { + Y_VERIFY_DEBUG(ev->Get()->Record.HasMvccSnapshot()); + TRowVersion snapshot(ev->Get()->Record.GetMvccSnapshot().GetStep(), ev->Get()->Record.GetMvccSnapshot().GetTxId()); + WaitingDataTxOps.emplace(snapshot, std::move(ev)); TRowVersion unreadableEdge; if (!Self->WaitPlanStep(snapshot.Step + 1) && snapshot < (unreadableEdge = GetUnreadableEdge())) { ActivateWaitingTxOps(unreadableEdge, ctx); // Async MediatorTimeCastEntry update, need to reschedule the op } - } - - return true; -} - + } + + return true; +} + void TPipeline::ActivateWaitingTxOps(TRowVersion edge, const TActorContext& ctx) { - if (WaitingDataTxOps.empty() || Self->MvccSwitchState == TSwitchState::SWITCHING) - return; - + if (WaitingDataTxOps.empty() || Self->MvccSwitchState == TSwitchState::SWITCHING) + return; + bool activated = false; for (;;) { - auto minWait = TRowVersion::Max(); - for (auto it = WaitingDataTxOps.begin(); it != WaitingDataTxOps.end();) { - if (it->first > TRowVersion::Min() && it->first >= edge) { - minWait = it->first; - break; - } - ctx.Send(it->second.Release()); - it = WaitingDataTxOps.erase(it); + auto minWait = TRowVersion::Max(); + for (auto it = WaitingDataTxOps.begin(); it != WaitingDataTxOps.end();) { + if (it->first > TRowVersion::Min() && it->first >= edge) { + minWait = it->first; + break; + } + ctx.Send(it->second.Release()); + it = WaitingDataTxOps.erase(it); activated = true; - } - + } + if (minWait == TRowVersion::Max() || Self->WaitPlanStep(minWait.Step + 1) || minWait >= (edge = GetUnreadableEdge())) - break; - - // Async MediatorTimeCastEntry update, need to rerun activation - } + break; + + // Async MediatorTimeCastEntry update, need to rerun activation + } if (activated) { Self->UpdateProposeQueueSize(); } -} - +} + void TPipeline::ActivateWaitingTxOps(const TActorContext& ctx) { if (WaitingDataTxOps.empty() || Self->MvccSwitchState == TSwitchState::SWITCHING) return; @@ -1629,22 +1629,22 @@ void TPipeline::ActivateWaitingTxOps(const TActorContext& ctx) { ActivateWaitingTxOps(GetUnreadableEdge(), ctx); } -TRowVersion TPipeline::GetReadEdge() const { - if (Self->TransQueue.PlannedTxs) { - for (auto order : Self->TransQueue.PlannedTxs) { - if (!Self->TransQueue.FindTxInFly(order.TxId)->IsReadOnly()) - return TRowVersion(order.Step, order.TxId); - } - return TRowVersion(Self->TransQueue.PlannedTxs.rbegin()->Step, Max<ui64>()); - } - - ui64 step = LastCompleteTx.Step; - if (Self->MediatorTimeCastEntry) - step = Max(step, Self->MediatorTimeCastEntry->Get(Self->TabletID())); - - return TRowVersion(step, Max<ui64>()); -} - +TRowVersion TPipeline::GetReadEdge() const { + if (Self->TransQueue.PlannedTxs) { + for (auto order : Self->TransQueue.PlannedTxs) { + if (!Self->TransQueue.FindTxInFly(order.TxId)->IsReadOnly()) + return TRowVersion(order.Step, order.TxId); + } + return TRowVersion(Self->TransQueue.PlannedTxs.rbegin()->Step, Max<ui64>()); + } + + ui64 step = LastCompleteTx.Step; + if (Self->MediatorTimeCastEntry) + step = Max(step, Self->MediatorTimeCastEntry->Get(Self->TabletID())); + + return TRowVersion(step, Max<ui64>()); +} + TRowVersion TPipeline::GetUnreadableEdge() const { auto last = TRowVersion( GetLastActivePlannedOpStep(), @@ -1686,38 +1686,38 @@ TOperation::TPtr TPipeline::FindCompletingOp(ui64 txId) const { return nullptr; } -void TPipeline::AddCommittingOp(const TOperation::TPtr& op) { +void TPipeline::AddCommittingOp(const TOperation::TPtr& op) { if (!Self->IsMvccEnabled() || op->IsReadOnly()) - return; - - TRowVersion version = Self->GetReadWriteVersions(op.Get()).WriteVersion; - if (op->IsImmediate()) - CommittingOps.Add(op->GetTxId(), version); - else - CommittingOps.Add(version); -} - -void TPipeline::RemoveCommittingOp(const TOperation::TPtr& op) { + return; + + TRowVersion version = Self->GetReadWriteVersions(op.Get()).WriteVersion; + if (op->IsImmediate()) + CommittingOps.Add(op->GetTxId(), version); + else + CommittingOps.Add(version); +} + +void TPipeline::RemoveCommittingOp(const TOperation::TPtr& op) { if (!Self->IsMvccEnabled() || op->IsReadOnly()) - return; - - if (op->IsImmediate()) - CommittingOps.Remove(op->GetTxId()); - else - CommittingOps.Remove(TRowVersion(op->GetStep(), op->GetTxId())); -} - -bool TPipeline::WaitCompletion(const TOperation::TPtr& op) const { + return; + + if (op->IsImmediate()) + CommittingOps.Remove(op->GetTxId()); + else + CommittingOps.Remove(TRowVersion(op->GetStep(), op->GetTxId())); +} + +bool TPipeline::WaitCompletion(const TOperation::TPtr& op) const { if (!Self->IsMvccEnabled() || !op->IsMvccSnapshotRead() || op->HasWaitCompletionFlag()) - return true; - - // don't send errors early - if(!op->Result() || op->Result()->GetStatus() != NKikimrTxDataShard::TEvProposeTransactionResult::COMPLETE) - return true; - - return CommittingOps.HasOpsBelow(op->GetMvccSnapshot()); -} - + return true; + + // don't send errors early + if(!op->Result() || op->Result()->GetStatus() != NKikimrTxDataShard::TEvProposeTransactionResult::COMPLETE) + return true; + + return CommittingOps.HasOpsBelow(op->GetMvccSnapshot()); +} + bool TPipeline::MarkPlannedLogicallyCompleteUpTo(const TRowVersion& version, TTransactionContext& txc) { bool hadWrites = false; auto processOp = [&](const auto& pr) -> bool { diff --git a/ydb/core/tx/datashard/datashard_pipeline.h b/ydb/core/tx/datashard/datashard_pipeline.h index 771edad29b..67c35260b2 100644 --- a/ydb/core/tx/datashard/datashard_pipeline.h +++ b/ydb/core/tx/datashard/datashard_pipeline.h @@ -114,7 +114,7 @@ public: // tx activity - TOperation::TPtr GetNextPlannedOp(ui64 step, ui64 txId) const; + TOperation::TPtr GetNextPlannedOp(ui64 step, ui64 txId) const; TOperation::TPtr GetNextActiveOp(bool dryRun); bool IsReadyOp(TOperation::TPtr op); @@ -327,22 +327,22 @@ public: void ActivateWaitingSchemeOps(const TActorContext& ctx) const; void MaybeActivateWaitingSchemeOps(const TActorContext& ctx) const; - ui64 WaitingTxs() const { return WaitingDataTxOps.size(); } - bool AddWaitingTxOp(TEvDataShard::TEvProposeTransaction::TPtr& ev, const TActorContext& ctx); + ui64 WaitingTxs() const { return WaitingDataTxOps.size(); } + bool AddWaitingTxOp(TEvDataShard::TEvProposeTransaction::TPtr& ev, const TActorContext& ctx); void ActivateWaitingTxOps(TRowVersion edge, const TActorContext& ctx); - void ActivateWaitingTxOps(const TActorContext& ctx); - - TRowVersion GetReadEdge() const; + void ActivateWaitingTxOps(const TActorContext& ctx); + + TRowVersion GetReadEdge() const; TRowVersion GetUnreadableEdge() const; - + void AddCompletingOp(const TOperation::TPtr& op); void RemoveCompletingOp(const TOperation::TPtr& op); TOperation::TPtr FindCompletingOp(ui64 txId) const; - void AddCommittingOp(const TOperation::TPtr& op); - void RemoveCommittingOp(const TOperation::TPtr& op); - bool WaitCompletion(const TOperation::TPtr& op) const; - + void AddCommittingOp(const TOperation::TPtr& op); + void RemoveCommittingOp(const TOperation::TPtr& op); + bool WaitCompletion(const TOperation::TPtr& op) const; + /** * Marks all active planned transactions before this version as logically "complete" */ @@ -359,66 +359,66 @@ private: TVector<std::pair<EExecutionUnitKind, TExecutionProfile::TUnitProfile>> UnitProfiles; }; - class TCommittingDataTxOps { - private: - struct TItem { - ui64 Step; - ui64 TxId; - mutable ui32 Counter; - - TItem(const TRowVersion& from) - : Step(from.Step) - , TxId(from.TxId) - , Counter(1u) - {} - - friend constexpr bool operator<(const TItem& a, const TItem& b) { - return a.Step < b.Step || (a.Step == b.Step && a.TxId < b.TxId); - } - - friend constexpr bool operator<(const TItem& a, const TRowVersion& b) { - return a.Step < b.Step || (a.Step == b.Step && a.TxId < b.TxId); - } - }; - - using TItemsSet = TSet<TItem>; - using TTxIdMap = THashMap<ui64, TItemsSet::iterator>; - public: - inline void Add(ui64 txId, TRowVersion version) { - auto res = ItemsSet.emplace(version); - if (!res.second) - res.first->Counter += 1; - TxIdMap.emplace(txId, res.first); - } - - inline void Add(TRowVersion version) { - auto res = ItemsSet.emplace(version); - if (!res.second) - res.first->Counter += 1; - } - - inline void Remove(ui64 txId) { - if (auto it = TxIdMap.find(txId); it != TxIdMap.end()) { - if (--it->second->Counter == 0) - ItemsSet.erase(it->second); - TxIdMap.erase(it); - } - } - - inline void Remove(TRowVersion version) { - if (auto it = ItemsSet.find(version); it != ItemsSet.end() && --it->Counter == 0) - ItemsSet.erase(it); - } - - inline bool HasOpsBelow(TRowVersion upperBound) const { - return bool(ItemsSet) && *ItemsSet.begin() < upperBound; - } - - private: - TTxIdMap TxIdMap; - TItemsSet ItemsSet; - }; - + class TCommittingDataTxOps { + private: + struct TItem { + ui64 Step; + ui64 TxId; + mutable ui32 Counter; + + TItem(const TRowVersion& from) + : Step(from.Step) + , TxId(from.TxId) + , Counter(1u) + {} + + friend constexpr bool operator<(const TItem& a, const TItem& b) { + return a.Step < b.Step || (a.Step == b.Step && a.TxId < b.TxId); + } + + friend constexpr bool operator<(const TItem& a, const TRowVersion& b) { + return a.Step < b.Step || (a.Step == b.Step && a.TxId < b.TxId); + } + }; + + using TItemsSet = TSet<TItem>; + using TTxIdMap = THashMap<ui64, TItemsSet::iterator>; + public: + inline void Add(ui64 txId, TRowVersion version) { + auto res = ItemsSet.emplace(version); + if (!res.second) + res.first->Counter += 1; + TxIdMap.emplace(txId, res.first); + } + + inline void Add(TRowVersion version) { + auto res = ItemsSet.emplace(version); + if (!res.second) + res.first->Counter += 1; + } + + inline void Remove(ui64 txId) { + if (auto it = TxIdMap.find(txId); it != TxIdMap.end()) { + if (--it->second->Counter == 0) + ItemsSet.erase(it->second); + TxIdMap.erase(it); + } + } + + inline void Remove(TRowVersion version) { + if (auto it = ItemsSet.find(version); it != ItemsSet.end() && --it->Counter == 0) + ItemsSet.erase(it); + } + + inline bool HasOpsBelow(TRowVersion upperBound) const { + return bool(ItemsSet) && *ItemsSet.begin() < upperBound; + } + + private: + TTxIdMap TxIdMap; + TItemsSet ItemsSet; + }; + using TSortedOps = TMap<TStepOrder, TOperation::TPtr>; /// @@ -456,9 +456,9 @@ private: TWaitingSchemeOpsOrder WaitingSchemeOpsOrder; TWaitingSchemeOps WaitingSchemeOps; - TMultiMap<TRowVersion, TEvDataShard::TEvProposeTransaction::TPtr> WaitingDataTxOps; - TCommittingDataTxOps CommittingOps; - + TMultiMap<TRowVersion, TEvDataShard::TEvProposeTransaction::TPtr> WaitingDataTxOps; + TCommittingDataTxOps CommittingOps; + THashMap<ui64, TOperation::TPtr> CompletingOps; bool GetPlannedTx(NIceDb::TNiceDb& db, ui64& step, ui64& txId); diff --git a/ydb/core/tx/datashard/datashard_snapshots.cpp b/ydb/core/tx/datashard/datashard_snapshots.cpp index 42ad5c0a33..da1219bb9e 100644 --- a/ydb/core/tx/datashard/datashard_snapshots.cpp +++ b/ydb/core/tx/datashard/datashard_snapshots.cpp @@ -10,12 +10,12 @@ namespace NDataShard { void TSnapshotManager::Reset() { MinWriteVersion = TRowVersion::Min(); - MvccState = EMvccState::MvccUnspecified; - KeepSnapshotTimeout = 0; - IncompleteEdge = TRowVersion::Min(); - CompleteEdge = TRowVersion::Min(); - LowWatermark = TRowVersion::Min(); - + MvccState = EMvccState::MvccUnspecified; + KeepSnapshotTimeout = 0; + IncompleteEdge = TRowVersion::Min(); + CompleteEdge = TRowVersion::Min(); + LowWatermark = TRowVersion::Min(); + CommittedCompleteEdge = TRowVersion::Min(); Snapshots.clear(); @@ -27,13 +27,13 @@ bool TSnapshotManager::Reload(NIceDb::TNiceDb& db) { bool ready = true; TRowVersion minWriteVersion = TRowVersion::Min(); - TRowVersion completeEdge = TRowVersion::Min(); - TRowVersion incompleteEdge = TRowVersion::Min(); - TRowVersion lowWatermark = TRowVersion::Min(); - - ui32 mvccState = 0; - ui64 keepSnapshotTimeout = 0; - + TRowVersion completeEdge = TRowVersion::Min(); + TRowVersion incompleteEdge = TRowVersion::Min(); + TRowVersion lowWatermark = TRowVersion::Min(); + + ui32 mvccState = 0; + ui64 keepSnapshotTimeout = 0; + TSnapshotMap snapshots; ready &= Self->SysGetUi64(db, Schema::Sys_MinWriteVersionStep, minWriteVersion.Step); @@ -84,23 +84,23 @@ bool TSnapshotManager::Reload(NIceDb::TNiceDb& db) { if (ready) { // We have a consistent view of snapshots table, apply MinWriteVersion = minWriteVersion; - MvccState = static_cast<EMvccState>(mvccState); - KeepSnapshotTimeout = keepSnapshotTimeout; - CompleteEdge = completeEdge; - IncompleteEdge = incompleteEdge; - LowWatermark = lowWatermark; + MvccState = static_cast<EMvccState>(mvccState); + KeepSnapshotTimeout = keepSnapshotTimeout; + CompleteEdge = completeEdge; + IncompleteEdge = incompleteEdge; + LowWatermark = lowWatermark; CommittedCompleteEdge = completeEdge; Snapshots = std::move(snapshots); } - if (ready) { + if (ready) { Self->SetCounter(COUNTER_MVCC_ENABLED, IsMvccEnabled() ? 1 : 0); - } - + } + return ready; } -void TSnapshotManager::InitExpireQueue(TInstant now) { +void TSnapshotManager::InitExpireQueue(TInstant now) { if (ExpireQueue) { // Remove all snapshots already in the queue while (auto* snapshot = ExpireQueue.Top()) { @@ -131,38 +131,38 @@ void TSnapshotManager::SetMinWriteVersion(NIceDb::TNiceDb& db, TRowVersion write MinWriteVersion = writeVersion; } -TRowVersion TSnapshotManager::GetCompleteEdge() const { - return CompleteEdge; -} - +TRowVersion TSnapshotManager::GetCompleteEdge() const { + return CompleteEdge; +} + TRowVersion TSnapshotManager::GetCommittedCompleteEdge() const { return CommittedCompleteEdge; } -void TSnapshotManager::SetCompleteEdge(NIceDb::TNiceDb& db, const TRowVersion& version) { +void TSnapshotManager::SetCompleteEdge(NIceDb::TNiceDb& db, const TRowVersion& version) { using Schema = TDataShard::Schema; - - Self->PersistSys(db, Schema::SysMvcc_CompleteEdgeStep, version.Step); - Self->PersistSys(db, Schema::SysMvcc_CompleteEdgeTxId, version.TxId); - CompleteEdge = version; -} - + + Self->PersistSys(db, Schema::SysMvcc_CompleteEdgeStep, version.Step); + Self->PersistSys(db, Schema::SysMvcc_CompleteEdgeTxId, version.TxId); + CompleteEdge = version; +} + bool TSnapshotManager::PromoteCompleteEdge(const TRowVersion& version, TTransactionContext& txc) { if (!IsMvccEnabled()) - return false; - + return false; + if (CompleteEdge >= version) - return false; - - NIceDb::TNiceDb db(txc.DB); + return false; + + NIceDb::TNiceDb db(txc.DB); SetCompleteEdge(db, version); txc.OnCommitted([this, edge = CompleteEdge] { this->CommittedCompleteEdge = edge; }); - - return true; -} - + + return true; +} + bool TSnapshotManager::PromoteCompleteEdge(TOperation* op, TTransactionContext& txc) { if (!IsMvccEnabled()) return false; @@ -180,100 +180,100 @@ bool TSnapshotManager::PromoteCompleteEdge(ui64 writeStep, TTransactionContext& return PromoteCompleteEdge(TRowVersion(writeStep, 0), txc); } -TRowVersion TSnapshotManager::GetIncompleteEdge() const { - return IncompleteEdge; -} - -void TSnapshotManager::SetIncompleteEdge(NIceDb::TNiceDb& db, const TRowVersion& version) { +TRowVersion TSnapshotManager::GetIncompleteEdge() const { + return IncompleteEdge; +} + +void TSnapshotManager::SetIncompleteEdge(NIceDb::TNiceDb& db, const TRowVersion& version) { using Schema = TDataShard::Schema; - - Self->PersistSys(db, Schema::SysMvcc_IncompleteEdgeStep, version.Step); - Self->PersistSys(db, Schema::SysMvcc_IncompleteEdgeTxId, version.TxId); - IncompleteEdge = version; -} - -bool TSnapshotManager::PromoteIncompleteEdge(TOperation* op, TTransactionContext& txc) { + + Self->PersistSys(db, Schema::SysMvcc_IncompleteEdgeStep, version.Step); + Self->PersistSys(db, Schema::SysMvcc_IncompleteEdgeTxId, version.TxId); + IncompleteEdge = version; +} + +bool TSnapshotManager::PromoteIncompleteEdge(TOperation* op, TTransactionContext& txc) { if (!IsMvccEnabled()) - return false; - - Y_ASSERT(op && op->GetStep()); - - if (TRowVersion version(op->GetStep(), op->GetTxId()); version > IncompleteEdge) { - NIceDb::TNiceDb db(txc.DB); - SetIncompleteEdge(db, version); - - return true; - } - - return false; -} - -void TSnapshotManager::SetKeepSnapshotTimeout(NIceDb::TNiceDb& db, ui64 keepSnapshotTimeout) { + return false; + + Y_ASSERT(op && op->GetStep()); + + if (TRowVersion version(op->GetStep(), op->GetTxId()); version > IncompleteEdge) { + NIceDb::TNiceDb db(txc.DB); + SetIncompleteEdge(db, version); + + return true; + } + + return false; +} + +void TSnapshotManager::SetKeepSnapshotTimeout(NIceDb::TNiceDb& db, ui64 keepSnapshotTimeout) { using Schema = TDataShard::Schema; - - // TODO validate new value - Self->PersistSys(db, Schema::SysMvcc_KeepSnapshotTimeout, keepSnapshotTimeout); - KeepSnapshotTimeout = keepSnapshotTimeout; -} - -TRowVersion TSnapshotManager::GetLowWatermark() const { - return LowWatermark; -} - -void TSnapshotManager::SetLowWatermark(NIceDb::TNiceDb& db, TRowVersion watermark) { + + // TODO validate new value + Self->PersistSys(db, Schema::SysMvcc_KeepSnapshotTimeout, keepSnapshotTimeout); + KeepSnapshotTimeout = keepSnapshotTimeout; +} + +TRowVersion TSnapshotManager::GetLowWatermark() const { + return LowWatermark; +} + +void TSnapshotManager::SetLowWatermark(NIceDb::TNiceDb& db, TRowVersion watermark) { using Schema = TDataShard::Schema; - - Self->PersistSys(db, Schema::SysMvcc_LowWatermarkStep, watermark.Step); - Self->PersistSys(db, Schema::SysMvcc_LowWatermarkTxId, watermark.TxId); - - LowWatermark = watermark; -} - -bool TSnapshotManager::AdvanceWatermark(NTable::TDatabase& db, const TRowVersion& to) { - if (LowWatermark >= to) - return false; - - RemoveRowVersions(db, LowWatermark, to); - - NIceDb::TNiceDb nicedb(db); - SetLowWatermark(nicedb, to); - - return true; -} - -void TSnapshotManager::RemoveRowVersions(NTable::TDatabase& db, const TRowVersion& from, const TRowVersion& to) { - for (auto& it : Self->GetUserTables()) { - auto begin = Snapshots.lower_bound(TSnapshotKey(Self->GetPathOwnerId(), it.first, from.Step, from.TxId)); - auto end = Snapshots.upper_bound(TSnapshotKey(Self->GetPathOwnerId(), it.first, to.Step, to.TxId)); - TRowVersion from0 = from; + + Self->PersistSys(db, Schema::SysMvcc_LowWatermarkStep, watermark.Step); + Self->PersistSys(db, Schema::SysMvcc_LowWatermarkTxId, watermark.TxId); + + LowWatermark = watermark; +} + +bool TSnapshotManager::AdvanceWatermark(NTable::TDatabase& db, const TRowVersion& to) { + if (LowWatermark >= to) + return false; + + RemoveRowVersions(db, LowWatermark, to); + + NIceDb::TNiceDb nicedb(db); + SetLowWatermark(nicedb, to); + + return true; +} + +void TSnapshotManager::RemoveRowVersions(NTable::TDatabase& db, const TRowVersion& from, const TRowVersion& to) { + for (auto& it : Self->GetUserTables()) { + auto begin = Snapshots.lower_bound(TSnapshotKey(Self->GetPathOwnerId(), it.first, from.Step, from.TxId)); + auto end = Snapshots.upper_bound(TSnapshotKey(Self->GetPathOwnerId(), it.first, to.Step, to.TxId)); + TRowVersion from0 = from; for (auto it0 = begin; it0 != end && from0 < to; it0++) { - auto to0 = TRowVersion(it0->first.Step, it0->first.TxId); - if (from0 < to0) - db.RemoveRowVersions(it.second->LocalTid, from0, to0); - from0 = to0.Next(); - } - if (from0 < to) - db.RemoveRowVersions(it.second->LocalTid, from0, to); - } -} - -ui64 TSnapshotManager::GetKeepSnapshotTimeout() const { - return KeepSnapshotTimeout ? KeepSnapshotTimeout : AppData()->DataShardConfig.GetKeepSnapshotTimeout(); -} - + auto to0 = TRowVersion(it0->first.Step, it0->first.TxId); + if (from0 < to0) + db.RemoveRowVersions(it.second->LocalTid, from0, to0); + from0 = to0.Next(); + } + if (from0 < to) + db.RemoveRowVersions(it.second->LocalTid, from0, to); + } +} + +ui64 TSnapshotManager::GetKeepSnapshotTimeout() const { + return KeepSnapshotTimeout ? KeepSnapshotTimeout : AppData()->DataShardConfig.GetKeepSnapshotTimeout(); +} + TDuration TSnapshotManager::GetCleanupSnapshotPeriod() const { return TDuration::MilliSeconds(AppData()->DataShardConfig.GetCleanupSnapshotPeriod()); } bool TSnapshotManager::ChangeMvccState(ui64 step, ui64 txId, TTransactionContext& txc, EMvccState state) { - Y_VERIFY(state != EMvccState::MvccUnspecified); - - if (MvccState == state) - return false; - + Y_VERIFY(state != EMvccState::MvccUnspecified); + + if (MvccState == state) + return false; + using Schema = TDataShard::Schema; - const TRowVersion opVersion(step, txId); - + const TRowVersion opVersion(step, txId); + // We need to choose a version that is at least as large as all previous edges TRowVersion nextVersion = Max(opVersion, MinWriteVersion, CompleteEdge, IncompleteEdge); @@ -291,49 +291,49 @@ bool TSnapshotManager::ChangeMvccState(ui64 step, ui64 txId, TTransactionContext RemoveRowVersions(txc.DB, MinWriteVersion, nextVersion); } - switch (state) { - case EMvccState::MvccEnabled: { + switch (state) { + case EMvccState::MvccEnabled: { NIceDb::TNiceDb nicedb(txc.DB); - - Self->PersistSys(nicedb, Schema::SysMvcc_State, (ui32)state); - MvccState = state; - + + Self->PersistSys(nicedb, Schema::SysMvcc_State, (ui32)state); + MvccState = state; + SetCompleteEdge(nicedb, nextVersion); SetIncompleteEdge(nicedb, nextVersion); SetLowWatermark(nicedb, nextVersion); - - break; - } - - case EMvccState::MvccDisabled: { + + break; + } + + case EMvccState::MvccDisabled: { NIceDb::TNiceDb nicedb(txc.DB); - + SetMinWriteVersion(nicedb, nextVersion); - - Self->PersistSys(nicedb, Schema::SysMvcc_State, (ui32)state); - MvccState = state; - + + Self->PersistSys(nicedb, Schema::SysMvcc_State, (ui32)state); + MvccState = state; + const auto minVersion = TRowVersion::Min(); - SetCompleteEdge(nicedb, minVersion); - SetIncompleteEdge(nicedb, minVersion); - SetLowWatermark(nicedb, minVersion); - - break; - } - - default: - Y_FAIL("Unexpected mvcc state# %d", (ui32)state); - } - + SetCompleteEdge(nicedb, minVersion); + SetIncompleteEdge(nicedb, minVersion); + SetLowWatermark(nicedb, minVersion); + + break; + } + + default: + Y_FAIL("Unexpected mvcc state# %d", (ui32)state); + } + txc.OnCommitted([this, edge = CompleteEdge] { this->CommittedCompleteEdge = edge; }); - + Self->SetCounter(COUNTER_MVCC_ENABLED, IsMvccEnabled() ? 1 : 0); - return true; -} - + return true; +} + const TSnapshot* TSnapshotManager::FindAvailable(const TSnapshotKey& key) const { auto it = Snapshots.find(key); if (it != Snapshots.end() && !it->second.HasFlags(TSnapshot::FlagRemoved)) { @@ -485,7 +485,7 @@ void TSnapshotManager::DoRemoveSnapshot(NTable::TDatabase& db, const TSnapshotKe // Mark snapshot as no longer accessible in local database const TRowVersion rowVersion(key.Step, key.TxId); if (!IsMvccEnabled() || rowVersion < LowWatermark) - db.RemoveRowVersions(localTableId, rowVersion, rowVersion.Next()); + db.RemoveRowVersions(localTableId, rowVersion, rowVersion.Next()); } bool TSnapshotManager::CleanupRemovedSnapshots(NTable::TDatabase& db) { @@ -509,7 +509,7 @@ bool TSnapshotManager::CleanupRemovedSnapshots(NTable::TDatabase& db) { return removed; } -void TSnapshotManager::InitSnapshotExpireTime(const TSnapshotKey& key, TInstant now) { +void TSnapshotManager::InitSnapshotExpireTime(const TSnapshotKey& key, TInstant now) { auto it = Snapshots.find(key); if (it != Snapshots.end() && it->second.HasFlags(TSnapshot::FlagTimeout) && @@ -533,15 +533,15 @@ bool TSnapshotManager::RefreshSnapshotExpireTime(const TSnapshotKey& key, TInsta return false; } -TDuration TSnapshotManager::CleanupTimeout() const { - TInstant now = NActors::TActivationContext::Now(); +TDuration TSnapshotManager::CleanupTimeout() const { + TInstant now = NActors::TActivationContext::Now(); + + TDuration snapshotTimeout = TDuration::Max(); + TDuration mvccGcTimeout = TDuration::Max(); + + if (auto* snapshot = ExpireQueue.Top()) + snapshotTimeout = snapshot->ExpireTime - now; - TDuration snapshotTimeout = TDuration::Max(); - TDuration mvccGcTimeout = TDuration::Max(); - - if (auto* snapshot = ExpireQueue.Top()) - snapshotTimeout = snapshot->ExpireTime - now; - if (IsMvccEnabled()) { if (LowWatermark == CompleteEdge) { mvccGcTimeout = GetCleanupSnapshotPeriod(); @@ -557,9 +557,9 @@ TDuration TSnapshotManager::CleanupTimeout() const { } } } - } - - return Min(snapshotTimeout, mvccGcTimeout); + } + + return Min(snapshotTimeout, mvccGcTimeout); } bool TSnapshotManager::HasExpiringSnapshots() const { @@ -583,24 +583,24 @@ bool TSnapshotManager::RemoveExpiredSnapshots(NTable::TDatabase& db, TInstant no } if (!IsMvccEnabled()) - return removed; - - ui64 keepSnapshotTimeout = GetKeepSnapshotTimeout(); - TRowVersion proposed = TRowVersion(Max(now.MilliSeconds(), keepSnapshotTimeout) - keepSnapshotTimeout, 0); - TRowVersion leastPlanned = TRowVersion::Max(); - if (auto it = Self->Pipeline.GetPlan().begin(); it != Self->Pipeline.GetPlan().end()) - leastPlanned = TRowVersion(it->Step, it->TxId); - - // holds current snapshot operations - TRowVersion leastAcquired = TRowVersion::Max(); - for (auto &it : Self->Pipeline.GetImmediateOps()) { - if (it.second->IsMvccSnapshotRead()) + return removed; + + ui64 keepSnapshotTimeout = GetKeepSnapshotTimeout(); + TRowVersion proposed = TRowVersion(Max(now.MilliSeconds(), keepSnapshotTimeout) - keepSnapshotTimeout, 0); + TRowVersion leastPlanned = TRowVersion::Max(); + if (auto it = Self->Pipeline.GetPlan().begin(); it != Self->Pipeline.GetPlan().end()) + leastPlanned = TRowVersion(it->Step, it->TxId); + + // holds current snapshot operations + TRowVersion leastAcquired = TRowVersion::Max(); + for (auto &it : Self->Pipeline.GetImmediateOps()) { + if (it.second->IsMvccSnapshotRead()) leastAcquired = Min(leastAcquired, it.second->GetMvccSnapshot()); - } - - removed |= AdvanceWatermark(db, Min(proposed, leastPlanned, leastAcquired, CompleteEdge)); + } + + removed |= AdvanceWatermark(db, Min(proposed, leastPlanned, leastAcquired, CompleteEdge)); LastAdvanceWatermark = NActors::TActivationContext::Monotonic(); - + return removed; } diff --git a/ydb/core/tx/datashard/datashard_snapshots.h b/ydb/core/tx/datashard/datashard_snapshots.h index 96022469f0..8746834112 100644 --- a/ydb/core/tx/datashard/datashard_snapshots.h +++ b/ydb/core/tx/datashard/datashard_snapshots.h @@ -1,11 +1,11 @@ #pragma once -#include "const.h" +#include "const.h" #include "snapshot_key.h" - + #include <ydb/core/tablet_flat/flat_cxx_database.h> #include <ydb/core/tablet_flat/tablet_flat_executor.h> - + #include <ydb/core/util/intrusive_heap.h> #include <util/generic/hash.h> @@ -15,9 +15,9 @@ namespace NKikimr { namespace NDataShard { -using NTabletFlatExecutor::TTransactionContext; - -class TOperation; +using NTabletFlatExecutor::TTransactionContext; + +class TOperation; class TDataShard; class TSnapshot { @@ -75,12 +75,12 @@ public: }; }; -enum class EMvccState { - MvccUnspecified = 0, - MvccEnabled = 1, - MvccDisabled = 2 -}; - +enum class EMvccState { + MvccUnspecified = 0, + MvccEnabled = 1, + MvccDisabled = 2 +}; + class TSnapshotManager { public: using TSnapshotMap = TMap<TSnapshotKey, TSnapshot, TLess<void>>; @@ -110,51 +110,51 @@ public: bool Reload(NIceDb::TNiceDb& db); - void InitExpireQueue(TInstant now); + void InitExpireQueue(TInstant now); TRowVersion GetMinWriteVersion() const; void SetMinWriteVersion(NIceDb::TNiceDb& db, TRowVersion writeVersion); - TRowVersion GetCompleteEdge() const; + TRowVersion GetCompleteEdge() const; TRowVersion GetCommittedCompleteEdge() const; - - void SetCompleteEdge(NIceDb::TNiceDb& db, const TRowVersion& version); - + + void SetCompleteEdge(NIceDb::TNiceDb& db, const TRowVersion& version); + bool PromoteCompleteEdge(const TRowVersion& version, TTransactionContext& txc); - bool PromoteCompleteEdge(TOperation* op, TTransactionContext& txc); + bool PromoteCompleteEdge(TOperation* op, TTransactionContext& txc); bool PromoteCompleteEdge(ui64 writeStep, TTransactionContext& txc); - - TRowVersion GetIncompleteEdge() const; - - void SetIncompleteEdge(NIceDb::TNiceDb& db, const TRowVersion& version); - - bool PromoteIncompleteEdge(TOperation* op, TTransactionContext& txc); - + + TRowVersion GetIncompleteEdge() const; + + void SetIncompleteEdge(NIceDb::TNiceDb& db, const TRowVersion& version); + + bool PromoteIncompleteEdge(TOperation* op, TTransactionContext& txc); + EMvccState GetMvccState() const { return MvccState; } - + bool IsMvccEnabled() const { // Note: mvcc is disabled during MvccUnspecified return MvccState == EMvccState::MvccEnabled; } - + bool ChangeMvccState(ui64 step, ui64 txId, TTransactionContext& txc, EMvccState state); - ui64 GetKeepSnapshotTimeout() const; + ui64 GetKeepSnapshotTimeout() const; TDuration GetCleanupSnapshotPeriod() const; - - void SetKeepSnapshotTimeout(NIceDb::TNiceDb& db, ui64 keepSnapshotTimeout); - - TRowVersion GetLowWatermark() const; - - void SetLowWatermark(NIceDb::TNiceDb &db, TRowVersion watermark); - - bool AdvanceWatermark(NTable::TDatabase& db, const TRowVersion& to); - - void RemoveRowVersions(NTable::TDatabase &db, const TRowVersion &from, const TRowVersion &to); - + + void SetKeepSnapshotTimeout(NIceDb::TNiceDb& db, ui64 keepSnapshotTimeout); + + TRowVersion GetLowWatermark() const; + + void SetLowWatermark(NIceDb::TNiceDb &db, TRowVersion watermark); + + bool AdvanceWatermark(NTable::TDatabase& db, const TRowVersion& to); + + void RemoveRowVersions(NTable::TDatabase &db, const TRowVersion &from, const TRowVersion &to); + const TSnapshotMap& GetSnapshots() const { return Snapshots; } @@ -178,10 +178,10 @@ public: bool RemoveSnapshot(NTable::TDatabase& db, const TSnapshotKey& key); bool CleanupRemovedSnapshots(NTable::TDatabase& db); - void InitSnapshotExpireTime(const TSnapshotKey& key, TInstant now); + void InitSnapshotExpireTime(const TSnapshotKey& key, TInstant now); bool RefreshSnapshotExpireTime(const TSnapshotKey& key, TInstant now); - TDuration CleanupTimeout() const; + TDuration CleanupTimeout() const; bool HasExpiringSnapshots() const; bool RemoveExpiredSnapshots(NTable::TDatabase& db, TInstant now); @@ -201,12 +201,12 @@ private: TDataShard* const Self; TRowVersion MinWriteVersion; - EMvccState MvccState = EMvccState::MvccUnspecified; - ui64 KeepSnapshotTimeout = 0; - TRowVersion IncompleteEdge = TRowVersion::Min(); - TRowVersion CompleteEdge = TRowVersion::Min(); - TRowVersion LowWatermark = TRowVersion::Min(); - + EMvccState MvccState = EMvccState::MvccUnspecified; + ui64 KeepSnapshotTimeout = 0; + TRowVersion IncompleteEdge = TRowVersion::Min(); + TRowVersion CompleteEdge = TRowVersion::Min(); + TRowVersion LowWatermark = TRowVersion::Min(); + TRowVersion CommittedCompleteEdge = TRowVersion::Min(); TSnapshotMap Snapshots; diff --git a/ydb/core/tx/datashard/datashard_split_dst.cpp b/ydb/core/tx/datashard/datashard_split_dst.cpp index 3e901e0e50..6575081001 100644 --- a/ydb/core/tx/datashard/datashard_split_dst.cpp +++ b/ydb/core/tx/datashard/datashard_split_dst.cpp @@ -45,7 +45,7 @@ public: tableId.OwnerId = Ev->Get()->Record.GetSchemeshardTabletId(); } - auto info = Self->CreateUserTable(txc, createTable); + auto info = Self->CreateUserTable(txc, createTable); Self->AddUserTable(tableId, info); if (Self->GetPathOwnerId() == INVALID_TABLET_ID) { @@ -147,7 +147,7 @@ public: newTableScheme.SetPartitionRangeBeginIsInclusive(true); newTableScheme.SetPartitionRangeEndIsInclusive(false); - Self->CreateUserTable(txc, newTableScheme); + Self->CreateUserTable(txc, newTableScheme); } } @@ -180,22 +180,22 @@ public: NIceDb::TNiceDb db(txc.DB); // Choose the highest write version, so we won't overwrite any important data - TRowVersion minWriteVersion(record.GetMinWriteVersionStep(), record.GetMinWriteVersionTxId()); + TRowVersion minWriteVersion(record.GetMinWriteVersionStep(), record.GetMinWriteVersionTxId()); + + if (Self->GetSnapshotManager().GetMinWriteVersion() < minWriteVersion) + Self->GetSnapshotManager().SetMinWriteVersion(db, minWriteVersion); - if (Self->GetSnapshotManager().GetMinWriteVersion() < minWriteVersion) - Self->GetSnapshotManager().SetMinWriteVersion(db, minWriteVersion); - const bool mvcc = Self->IsMvccEnabled(); - if (mvcc) { - TRowVersion completeEdge(record.GetMvccCompleteEdgeStep(), record.GetMvccCompleteEdgeTxId()); - if (Self->GetSnapshotManager().GetCompleteEdge() < completeEdge) - Self->GetSnapshotManager().SetCompleteEdge(db, completeEdge); - TRowVersion incompleteEdge(record.GetMvccIncompleteEdgeStep(), record.GetMvccIncompleteEdgeTxId()); - if (Self->GetSnapshotManager().GetIncompleteEdge() < incompleteEdge) - Self->GetSnapshotManager().SetIncompleteEdge(db, incompleteEdge); - TRowVersion lowWatermark(record.GetMvccLowWatermarkStep(), record.GetMvccLowWatermarkTxId()); - if (Self->GetSnapshotManager().GetLowWatermark() < lowWatermark) - Self->GetSnapshotManager().SetLowWatermark(db, lowWatermark); + if (mvcc) { + TRowVersion completeEdge(record.GetMvccCompleteEdgeStep(), record.GetMvccCompleteEdgeTxId()); + if (Self->GetSnapshotManager().GetCompleteEdge() < completeEdge) + Self->GetSnapshotManager().SetCompleteEdge(db, completeEdge); + TRowVersion incompleteEdge(record.GetMvccIncompleteEdgeStep(), record.GetMvccIncompleteEdgeTxId()); + if (Self->GetSnapshotManager().GetIncompleteEdge() < incompleteEdge) + Self->GetSnapshotManager().SetIncompleteEdge(db, incompleteEdge); + TRowVersion lowWatermark(record.GetMvccLowWatermarkStep(), record.GetMvccLowWatermarkTxId()); + if (Self->GetSnapshotManager().GetLowWatermark() < lowWatermark) + Self->GetSnapshotManager().SetLowWatermark(db, lowWatermark); } // Would be true for the first snapshot we receive, e.g. during a merge @@ -242,8 +242,8 @@ public: if (Self->ReceiveSnapshotsFrom.empty()) { LastSnapshotReceived = true; - const auto minVersion = mvcc ? Self->GetSnapshotManager().GetLowWatermark() - : Self->GetSnapshotManager().GetMinWriteVersion(); + const auto minVersion = mvcc ? Self->GetSnapshotManager().GetLowWatermark() + : Self->GetSnapshotManager().GetMinWriteVersion(); // Mark versions not accessible via snapshots as deleted for (const auto& kv : Self->GetUserTables()) { @@ -261,8 +261,8 @@ public: vlower = vupper.Next(); } - if (vlower < minVersion) { - txc.DB.RemoveRowVersions(localTableId, vlower, minVersion); + if (vlower < minVersion) { + txc.DB.RemoveRowVersions(localTableId, vlower, minVersion); } } diff --git a/ydb/core/tx/datashard/datashard_split_src.cpp b/ydb/core/tx/datashard/datashard_split_src.cpp index e3e75746ae..a7349fc9cf 100644 --- a/ydb/core/tx/datashard/datashard_split_src.cpp +++ b/ydb/core/tx/datashard/datashard_split_src.cpp @@ -173,16 +173,16 @@ public: } } - TIntrusivePtr<NTabletFlatExecutor::TTableSnapshotContext> snapContext; + TIntrusivePtr<NTabletFlatExecutor::TTableSnapshotContext> snapContext; if (Self->IsMvccEnabled()) { - snapContext = new TSplitSnapshotContext(opId, std::move(tablesToSnapshot), - Self->GetSnapshotManager().GetCompleteEdge(), - Self->GetSnapshotManager().GetIncompleteEdge(), - Self->GetSnapshotManager().GetLowWatermark()); - } else { - snapContext = new TSplitSnapshotContext(opId, std::move(tablesToSnapshot)); - } - + snapContext = new TSplitSnapshotContext(opId, std::move(tablesToSnapshot), + Self->GetSnapshotManager().GetCompleteEdge(), + Self->GetSnapshotManager().GetIncompleteEdge(), + Self->GetSnapshotManager().GetLowWatermark()); + } else { + snapContext = new TSplitSnapshotContext(opId, std::move(tablesToSnapshot)); + } + txc.Env.MakeSnapshot(snapContext); Self->SplitSnapshotStarted = true; @@ -311,20 +311,20 @@ public: if (!needToReadPages) { // Send version at which data is not protected by persistent snapshots - if (auto minVersion = Self->GetSnapshotManager().GetMinWriteVersion()) { + if (auto minVersion = Self->GetSnapshotManager().GetMinWriteVersion()) { snapshot->SetMinWriteVersionStep(minVersion.Step); snapshot->SetMinWriteVersionTxId(minVersion.TxId); } if (Self->IsMvccEnabled()) { - snapshot->SetMvccLowWatermarkStep(SnapContext->LowWatermark.Step); - snapshot->SetMvccLowWatermarkTxId(SnapContext->LowWatermark.TxId); - snapshot->SetMvccCompleteEdgeStep(SnapContext->CompleteEdge.Step); - snapshot->SetMvccCompleteEdgeTxId(SnapContext->CompleteEdge.TxId); - snapshot->SetMvccIncompleteEdgeStep(SnapContext->IncompleteEdge.Step); - snapshot->SetMvccIncompleteEdgeTxId(SnapContext->IncompleteEdge.TxId); - } - + snapshot->SetMvccLowWatermarkStep(SnapContext->LowWatermark.Step); + snapshot->SetMvccLowWatermarkTxId(SnapContext->LowWatermark.TxId); + snapshot->SetMvccCompleteEdgeStep(SnapContext->CompleteEdge.Step); + snapshot->SetMvccCompleteEdgeTxId(SnapContext->CompleteEdge.TxId); + snapshot->SetMvccIncompleteEdgeStep(SnapContext->IncompleteEdge.Step); + snapshot->SetMvccIncompleteEdgeTxId(SnapContext->IncompleteEdge.TxId); + } + // Send info about existing persistent snapshots for (const auto& kv : Self->GetSnapshotManager().GetSnapshots()) { if (kv.second.HasFlags(TSnapshot::FlagRemoved)) { diff --git a/ydb/core/tx/datashard/datashard_switch_mvcc_state.cpp b/ydb/core/tx/datashard/datashard_switch_mvcc_state.cpp index af9b2aa924..04c09cf74b 100644 --- a/ydb/core/tx/datashard/datashard_switch_mvcc_state.cpp +++ b/ydb/core/tx/datashard/datashard_switch_mvcc_state.cpp @@ -1,104 +1,104 @@ -#include "datashard_txs.h" - +#include "datashard_txs.h" + namespace NKikimr::NDataShard { - + void TDataShard::CheckMvccStateChangeCanStart(const TActorContext& ctx) { - switch (MvccSwitchState) { - case TSwitchState::READY: - switch (State) { - case TShardState::WaitScheme: - case TShardState::SplitDstReceivingSnapshot: - // Recheck after while - return; - - case TShardState::Ready: - case TShardState::Frozen: { + switch (MvccSwitchState) { + case TSwitchState::READY: + switch (State) { + case TShardState::WaitScheme: + case TShardState::SplitDstReceivingSnapshot: + // Recheck after while + return; + + case TShardState::Ready: + case TShardState::Frozen: { const auto enable = AppData(ctx)->FeatureFlags.GetEnableMvcc(); if (enable && *enable != IsMvccEnabled()) { - MvccSwitchState = TSwitchState::SWITCHING; - } else { - MvccSwitchState = TSwitchState::DONE; - return; - } - - break; - } - - case TShardState::Uninitialized: - case TShardState::Unknown: - // We cannot start checking before shard initialization - - Y_VERIFY_DEBUG(false, "Unexpected shard state State:%d", State); + MvccSwitchState = TSwitchState::SWITCHING; + } else { + MvccSwitchState = TSwitchState::DONE; + return; + } + + break; + } + + case TShardState::Uninitialized: + case TShardState::Unknown: + // We cannot start checking before shard initialization + + Y_VERIFY_DEBUG(false, "Unexpected shard state State:%d", State); [[fallthrough]]; - - case TShardState::Readonly: + + case TShardState::Readonly: // Don't switch the state on follower [[fallthrough]]; - - case TShardState::Offline: - case TShardState::PreOffline: - case TShardState::SplitSrcWaitForNoTxInFlight: - case TShardState::SplitSrcMakeSnapshot: - case TShardState::SplitSrcSendingSnapshot: - case TShardState::SplitSrcWaitForPartitioningChanged: - // Don't switch the state while splitting or stopping + + case TShardState::Offline: + case TShardState::PreOffline: + case TShardState::SplitSrcWaitForNoTxInFlight: + case TShardState::SplitSrcMakeSnapshot: + case TShardState::SplitSrcSendingSnapshot: + case TShardState::SplitSrcWaitForPartitioningChanged: + // Don't switch the state while splitting or stopping [[fallthrough]]; - - default: - // How we ran into it?? - - MvccSwitchState = TSwitchState::DONE; - - return; - } + + default: + // How we ran into it?? + + MvccSwitchState = TSwitchState::DONE; + + return; + } [[fallthrough]]; - - case TSwitchState::SWITCHING: { - ui64 txInFly = TxInFly(); - ui64 immediateTxInFly = ImmediateInFly(); - SetCounter(COUNTER_MVCC_STATE_CHANGE_WAIT_TX_IN_FLY, txInFly); - SetCounter(COUNTER_MVCC_STATE_CHANGE_WAIT_IMMEDIATE_TX_IN_FLY, immediateTxInFly); - if (txInFly == 0 && immediateTxInFly == 0 && !Pipeline.HasWaitingSchemeOps()) - Execute(CreateTxExecuteMvccStateChange(), ctx); + + case TSwitchState::SWITCHING: { + ui64 txInFly = TxInFly(); + ui64 immediateTxInFly = ImmediateInFly(); + SetCounter(COUNTER_MVCC_STATE_CHANGE_WAIT_TX_IN_FLY, txInFly); + SetCounter(COUNTER_MVCC_STATE_CHANGE_WAIT_IMMEDIATE_TX_IN_FLY, immediateTxInFly); + if (txInFly == 0 && immediateTxInFly == 0 && !Pipeline.HasWaitingSchemeOps()) + Execute(CreateTxExecuteMvccStateChange(), ctx); break; - } - case TSwitchState::DONE: - return; - } -} - + } + case TSwitchState::DONE: + return; + } +} + TDataShard::TTxExecuteMvccStateChange::TTxExecuteMvccStateChange(TDataShard* ds) - : TBase(ds) {} - + : TBase(ds) {} + bool TDataShard::TTxExecuteMvccStateChange::Execute(TTransactionContext& txc, const TActorContext& ctx) { - if (Self->MvccSwitchState == TSwitchState::DONE) - return true; // already switched - - if (Self->State == TShardState::Ready || Self->State == TShardState::Frozen) { - Y_VERIFY(Self->TxInFly() == 0 && Self->ImmediateInFly() == 0); - - auto [step, txId] = Self->LastCompleteTxVersion(); + if (Self->MvccSwitchState == TSwitchState::DONE) + return true; // already switched + + if (Self->State == TShardState::Ready || Self->State == TShardState::Frozen) { + Y_VERIFY(Self->TxInFly() == 0 && Self->ImmediateInFly() == 0); + + auto [step, txId] = Self->LastCompleteTxVersion(); Self->SnapshotManager.ChangeMvccState(step, txId, txc, *AppData(ctx)->FeatureFlags.GetEnableMvcc() ? EMvccState::MvccEnabled : EMvccState::MvccDisabled); - - LOG_DEBUG(ctx, NKikimrServices::TX_DATASHARD, TStringBuilder() << "TTxExecuteMvccStateChange.Execute" + + LOG_DEBUG(ctx, NKikimrServices::TX_DATASHARD, TStringBuilder() << "TTxExecuteMvccStateChange.Execute" << " MVCC state switched to" << (*AppData(ctx)->FeatureFlags.GetEnableMvcc() ? " enabled" : " disabled") << " state"); - - ActivateWaitingOps = true; - } - - Self->MvccSwitchState = TSwitchState::DONE; - - return true; -} - + + ActivateWaitingOps = true; + } + + Self->MvccSwitchState = TSwitchState::DONE; + + return true; +} + void TDataShard::TTxExecuteMvccStateChange::Complete(const TActorContext& ctx) { - if (ActivateWaitingOps) - Self->Pipeline.ActivateWaitingTxOps(ctx); -} - + if (ActivateWaitingOps) + Self->Pipeline.ActivateWaitingTxOps(ctx); +} + NTabletFlatExecutor::ITransaction* TDataShard::CreateTxExecuteMvccStateChange() { - return new TTxExecuteMvccStateChange(this); -} - -} + return new TTxExecuteMvccStateChange(this); +} + +} diff --git a/ydb/core/tx/datashard/datashard_trans_queue.h b/ydb/core/tx/datashard/datashard_trans_queue.h index 88e9532cff..1d392676da 100644 --- a/ydb/core/tx/datashard/datashard_trans_queue.h +++ b/ydb/core/tx/datashard/datashard_trans_queue.h @@ -46,7 +46,7 @@ public: ui64 TxInFly() const { return TxsInFly.size(); } void AddTxInFly(TOperation::TPtr op); void RemoveTxInFly(ui64 txId); - TOperation::TPtr FindTxInFly(ui64 txId) const + TOperation::TPtr FindTxInFly(ui64 txId) const { auto it = TxsInFly.find(txId); if (it != TxsInFly.end()) diff --git a/ydb/core/tx/datashard/datashard_txs.h b/ydb/core/tx/datashard/datashard_txs.h index e6f9e77ca9..4a9ab00878 100644 --- a/ydb/core/tx/datashard/datashard_txs.h +++ b/ydb/core/tx/datashard/datashard_txs.h @@ -285,13 +285,13 @@ public: }; class TDataShard::TTxExecuteMvccStateChange: public NTabletFlatExecutor::TTransactionBase<TDataShard> { -public: +public: TTxExecuteMvccStateChange(TDataShard* ds); - bool Execute(TTransactionContext& txc, const TActorContext& ctx) override; - void Complete(const TActorContext& ctx) override; - TTxType GetTxType() const override { return TXTYPE_EXECUTE_MVCC_STATE_CHANGE; } -private: - bool ActivateWaitingOps = false; -}; - + bool Execute(TTransactionContext& txc, const TActorContext& ctx) override; + void Complete(const TActorContext& ctx) override; + TTxType GetTxType() const override { return TXTYPE_EXECUTE_MVCC_STATE_CHANGE; } +private: + bool ActivateWaitingOps = false; +}; + }} diff --git a/ydb/core/tx/datashard/datashard_unsafe_upload.cpp b/ydb/core/tx/datashard/datashard_unsafe_upload.cpp index 64fa5e54ea..273952a06d 100644 --- a/ydb/core/tx/datashard/datashard_unsafe_upload.cpp +++ b/ydb/core/tx/datashard/datashard_unsafe_upload.cpp @@ -10,12 +10,12 @@ TDataShard::TTxUnsafeUploadRows::TTxUnsafeUploadRows(TDataShard* ds, TEvDataShar } bool TDataShard::TTxUnsafeUploadRows::Execute(TTransactionContext& txc, const TActorContext&) { - auto [readVersion, writeVersion] = Self->GetReadWriteVersions(); + auto [readVersion, writeVersion] = Self->GetReadWriteVersions(); if (!TCommonUploadOps::Execute(Self, txc, readVersion, writeVersion)) - return false; - + return false; + Self->PromoteCompleteEdge(writeVersion.Step, txc); - return true; + return true; } void TDataShard::TTxUnsafeUploadRows::Complete(const TActorContext& ctx) { diff --git a/ydb/core/tx/datashard/datashard_ut_common.cpp b/ydb/core/tx/datashard/datashard_ut_common.cpp index 980f51b7d4..d754f7ad0e 100644 --- a/ydb/core/tx/datashard/datashard_ut_common.cpp +++ b/ydb/core/tx/datashard/datashard_ut_common.cpp @@ -28,7 +28,7 @@ using namespace Tests; const bool ENABLE_DATASHARD_LOG = true; const bool DUMP_RESULT = false; -void TTester::Setup(TTestActorRuntime& runtime, const TOptions& opts) { +void TTester::Setup(TTestActorRuntime& runtime, const TOptions& opts) { if (ENABLE_DATASHARD_LOG) { runtime.SetLogPriority(NKikimrServices::TX_DATASHARD, NActors::NLog::PRI_TRACE); } @@ -39,8 +39,8 @@ void TTester::Setup(TTestActorRuntime& runtime, const TOptions& opts) { TAppPrepare app; - app.SetEnableMvcc(opts.Mvcc); - + app.SetEnableMvcc(opts.Mvcc); + auto domain = TDomainsInfo::TDomain::ConstructDomainWithExplicitTabletIds( "dc-1", domainId, FAKE_SCHEMESHARD_TABLET_ID, domainId, domainId, TVector<ui32>{domainId}, @@ -63,7 +63,7 @@ TTester::TTester(ESchema schema, const TOptions& opts) , LastTxId(0) , LastStep(opts.FirstStep) { - Setup(Runtime, opts); + Setup(Runtime, opts); Sender = Runtime.AllocateEdgeActor(); // Schemeshard is only used to receive notifications @@ -78,7 +78,7 @@ TTester::TTester(ESchema schema, const TString& dispatchName, std::function<void , LastTxId(0) , LastStep(1) { - Setup(Runtime, opts); + Setup(Runtime, opts); setup(Runtime); Sender = Runtime.AllocateEdgeActor(); AllowIncompleteResult = (dispatchName != INITIAL_TEST_DISPATCH_NAME); diff --git a/ydb/core/tx/datashard/datashard_ut_common.h b/ydb/core/tx/datashard/datashard_ut_common.h index 50b0348ab4..4b5d7fe4ea 100644 --- a/ydb/core/tx/datashard/datashard_ut_common.h +++ b/ydb/core/tx/datashard/datashard_ut_common.h @@ -51,7 +51,7 @@ public: bool DelayReadSet; bool DelayData; bool RebootOnDelay; - std::optional<bool> Mvcc; + std::optional<bool> Mvcc; ui64 ExecutorCacheSize; TOptions(ui64 firstStep = 0) @@ -66,7 +66,7 @@ public: void EnableOutOfOrder(ui32 num = 8) { NumActiveTx = num; } void EnableSoftUpdates() { SoftUpdates = true; } - void EnableMvcc(std::optional<bool> enabled = {true}) { Mvcc = enabled; } + void EnableMvcc(std::optional<bool> enabled = {true}) { Mvcc = enabled; } TString PartConfig() const { TString pipelineConfig = Sprintf(R"(PipelineConfig { @@ -82,7 +82,7 @@ public: return Sprintf(R"(PartitionConfig { %s %s - })", cacheSize.data(), pipelineConfig.data()); + })", cacheSize.data(), pipelineConfig.data()); } }; @@ -98,7 +98,7 @@ public: TTester(ESchema schema, const TString& dispatchName, std::function<void (TTestActorRuntime&)> setup, bool& activeZone, const TOptions& opts = TOptions()); - static void Setup(TTestActorRuntime& runtime, const TOptions& opts = TOptions()); + static void Setup(TTestActorRuntime& runtime, const TOptions& opts = TOptions()); private: ESchema Schema; @@ -422,21 +422,21 @@ struct TShardedTableOptions { #undef TABLE_OPTION_IMPL }; -#define Y_UNIT_TEST_WITH_MVCC_IMPL(N, OPT) \ - template<bool OPT> void N(NUnitTest::TTestContext&); \ - struct TTestRegistration##N { \ - TTestRegistration##N() { \ - TCurrentTest::AddTest(#N, static_cast<void (*)(NUnitTest::TTestContext&)>(&N<false>), false); \ - TCurrentTest::AddTest("Mvcc" #N, static_cast<void (*)(NUnitTest::TTestContext&)>(&N<true>), false); \ - } \ - }; \ - static TTestRegistration##N testRegistration##N; \ - template<bool OPT> \ - void N(NUnitTest::TTestContext&) - -#define Y_UNIT_TEST_WITH_MVCC(N) Y_UNIT_TEST_WITH_MVCC_IMPL(N, UseMvcc) -#define WithMvcc UseMvcc - +#define Y_UNIT_TEST_WITH_MVCC_IMPL(N, OPT) \ + template<bool OPT> void N(NUnitTest::TTestContext&); \ + struct TTestRegistration##N { \ + TTestRegistration##N() { \ + TCurrentTest::AddTest(#N, static_cast<void (*)(NUnitTest::TTestContext&)>(&N<false>), false); \ + TCurrentTest::AddTest("Mvcc" #N, static_cast<void (*)(NUnitTest::TTestContext&)>(&N<true>), false); \ + } \ + }; \ + static TTestRegistration##N testRegistration##N; \ + template<bool OPT> \ + void N(NUnitTest::TTestContext&) + +#define Y_UNIT_TEST_WITH_MVCC(N) Y_UNIT_TEST_WITH_MVCC_IMPL(N, UseMvcc) +#define WithMvcc UseMvcc + #define Y_UNIT_TEST_QUAD(N, OPT1, OPT2) \ template<bool OPT1, bool OPT2> void N(NUnitTest::TTestContext&); \ struct TTestRegistration##N { \ diff --git a/ydb/core/tx/datashard/datashard_ut_erase_rows.cpp b/ydb/core/tx/datashard/datashard_ut_erase_rows.cpp index 1a2a67dce5..87a51ef80a 100644 --- a/ydb/core/tx/datashard/datashard_ut_erase_rows.cpp +++ b/ydb/core/tx/datashard/datashard_ut_erase_rows.cpp @@ -44,7 +44,7 @@ struct TUnit { namespace { void CreateTable(TServer::TPtr server, const TActorId& sender, const TString& root, - const TString& name, const TString& ttlColType = "Timestamp") { + const TString& name, const TString& ttlColType = "Timestamp") { auto opts = TShardedTableOptions() .EnableOutOfOrder(false) .Columns({ @@ -359,7 +359,7 @@ Y_UNIT_TEST_SUITE(EraseRowsTests) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings - .SetEnableMvcc(enableMvcc) + .SetEnableMvcc(enableMvcc) .SetDomainName("Root") .SetUseRealThreads(false); @@ -370,7 +370,7 @@ Y_UNIT_TEST_SUITE(EraseRowsTests) { runtime.SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_DEBUG); InitRoot(server, sender); - CreateTable(server, sender, "/Root", "table-1"); + CreateTable(server, sender, "/Root", "table-1"); ExecSQL(server, sender, R"( UPSERT INTO [/Root/table-1] (key, value) VALUES (1, CAST("1970-01-01T00:00:00.000000Z" AS Timestamp)), @@ -386,15 +386,15 @@ Y_UNIT_TEST_SUITE(EraseRowsTests) { UNIT_ASSERT_STRINGS_EQUAL(StripInPlace(content), "key = 3, value = 2020-04-15T00:00:00.000000Z"); } - Y_UNIT_TEST_WITH_MVCC(EraseRowsShouldSuccess) { + Y_UNIT_TEST_WITH_MVCC(EraseRowsShouldSuccess) { EraseRowsShouldSuccess(Nothing(), WithMvcc); } - Y_UNIT_TEST_WITH_MVCC(EraseRowsShouldFailOnVariousErrors) { + Y_UNIT_TEST_WITH_MVCC(EraseRowsShouldFailOnVariousErrors) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetDomainName("Root") .SetUseRealThreads(false); @@ -405,7 +405,7 @@ Y_UNIT_TEST_SUITE(EraseRowsTests) { runtime.SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_DEBUG); InitRoot(server, sender); - CreateTable(server, sender, "/Root", "table-1"); + CreateTable(server, sender, "/Root", "table-1"); auto tableId = ResolveTableId(server, sender, "/Root/table-1"); EraseRows(server, sender, "/Root/table-1", TTableId(), {1}, SerializeKeys({1, 2}), @@ -427,13 +427,13 @@ Y_UNIT_TEST_SUITE(EraseRowsTests) { TProto::TEvEraseResponse::SCHEME_ERROR, "Cell count doesn't match row scheme"); } - void ConditionalEraseShouldSuccess(const TString& ttlColType, EUnit unit, const TString& toUpload, const TString& afterErase, bool enableMvcc = false) { + void ConditionalEraseShouldSuccess(const TString& ttlColType, EUnit unit, const TString& toUpload, const TString& afterErase, bool enableMvcc = false) { using TEvResponse = TEvDataShard::TEvConditionalEraseRowsResponse; TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings - .SetEnableMvcc(enableMvcc) + .SetEnableMvcc(enableMvcc) .SetDomainName("Root") .SetUseRealThreads(false); @@ -444,7 +444,7 @@ Y_UNIT_TEST_SUITE(EraseRowsTests) { runtime.SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_DEBUG); InitRoot(server, sender); - CreateTable(server, sender, "/Root", "table-1", ttlColType); + CreateTable(server, sender, "/Root", "table-1", ttlColType); ExecSQL(server, sender, toUpload); auto tableId = ResolveTableId(server, sender, "/Root/table-1"); @@ -457,7 +457,7 @@ Y_UNIT_TEST_SUITE(EraseRowsTests) { UNIT_ASSERT_STRINGS_EQUAL(StripInPlace(content), Strip(afterErase)); } - Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldErase) { + Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldErase) { ConditionalEraseShouldSuccess("Timestamp", TUnit::AUTO, R"( UPSERT INTO [/Root/table-1] (key, value) VALUES (1, CAST("1970-01-01T00:00:00.000000Z" AS Timestamp)), @@ -467,10 +467,10 @@ UPSERT INTO [/Root/table-1] (key, value) VALUES )", R"( key = 3, value = 2030-04-15T00:00:00.000000Z key = 4, value = (empty maybe) - )", WithMvcc); + )", WithMvcc); } - Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldNotErase) { + Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldNotErase) { ConditionalEraseShouldSuccess("Timestamp", TUnit::AUTO, R"( UPSERT INTO [/Root/table-1] (key, value) VALUES (1, CAST("2030-04-15T00:00:00.000000Z" AS Timestamp)), @@ -480,10 +480,10 @@ UPSERT INTO [/Root/table-1] (key, value) VALUES key = 1, value = 2030-04-15T00:00:00.000000Z key = 2, value = 2030-04-15T00:00:00.000000Z key = 3, value = 2030-04-15T00:00:00.000000Z - )", WithMvcc); + )", WithMvcc); } - Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldEraseOnUint32) { + Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldEraseOnUint32) { ConditionalEraseShouldSuccess("Uint32", TUnit::SECONDS, R"( UPSERT INTO [/Root/table-1] (key, value) VALUES (1, 0), @@ -493,10 +493,10 @@ UPSERT INTO [/Root/table-1] (key, value) VALUES )", R"( key = 3, value = 1902441600 key = 4, value = (empty maybe) - )", WithMvcc); + )", WithMvcc); } - Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldEraseOnUint64Seconds) { + Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldEraseOnUint64Seconds) { ConditionalEraseShouldSuccess("Uint64", TUnit::SECONDS, R"( UPSERT INTO [/Root/table-1] (key, value) VALUES (1, 0), @@ -506,10 +506,10 @@ UPSERT INTO [/Root/table-1] (key, value) VALUES )", R"( key = 3, value = 1902441600 key = 4, value = (empty maybe) - )", WithMvcc); + )", WithMvcc); } - Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldEraseOnUint64MilliSeconds) { + Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldEraseOnUint64MilliSeconds) { ConditionalEraseShouldSuccess("Uint64", TUnit::MILLISECONDS, R"( UPSERT INTO [/Root/table-1] (key, value) VALUES (1, 0), @@ -519,10 +519,10 @@ UPSERT INTO [/Root/table-1] (key, value) VALUES )", R"( key = 3, value = 1902441600000 key = 4, value = (empty maybe) - )", WithMvcc); + )", WithMvcc); } - Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldEraseOnUint64MicroSeconds) { + Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldEraseOnUint64MicroSeconds) { ConditionalEraseShouldSuccess("Uint64", TUnit::MICROSECONDS, R"( UPSERT INTO [/Root/table-1] (key, value) VALUES (1, 0), @@ -532,10 +532,10 @@ UPSERT INTO [/Root/table-1] (key, value) VALUES )", R"( key = 3, value = 1902441600000000 key = 4, value = (empty maybe) - )", WithMvcc); + )", WithMvcc); } - Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldEraseOnUint64NanoSeconds) { + Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldEraseOnUint64NanoSeconds) { ConditionalEraseShouldSuccess("Uint64", TUnit::NANOSECONDS, R"( UPSERT INTO [/Root/table-1] (key, value) VALUES (1, 0), @@ -545,10 +545,10 @@ UPSERT INTO [/Root/table-1] (key, value) VALUES )", R"( key = 3, value = 1902441600000000000 key = 4, value = (empty maybe) - )", WithMvcc); + )", WithMvcc); } - Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldEraseOnDyNumberSeconds) { + Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldEraseOnDyNumberSeconds) { ConditionalEraseShouldSuccess("DyNumber", TUnit::SECONDS, R"( --!syntax_v1 UPSERT INTO `/Root/table-1` (key, value) VALUES @@ -563,10 +563,10 @@ UPSERT INTO `/Root/table-1` (key, value) VALUES key = 5, value = .190244160e10 key = 6, value = .63624960000e12 key = 7, value = (empty maybe) - )", WithMvcc); + )", WithMvcc); } - Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldEraseOnDyNumberMilliSeconds) { + Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldEraseOnDyNumberMilliSeconds) { ConditionalEraseShouldSuccess("DyNumber", TUnit::MILLISECONDS, R"( --!syntax_v1 UPSERT INTO `/Root/table-1` (key, value) VALUES @@ -579,10 +579,10 @@ UPSERT INTO `/Root/table-1` (key, value) VALUES key = 3, value = .1902441600000e13 key = 4, value = .636249600000000e15 key = 5, value = (empty maybe) - )", WithMvcc); + )", WithMvcc); } - Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldEraseOnDyNumberMicroSeconds) { + Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldEraseOnDyNumberMicroSeconds) { ConditionalEraseShouldSuccess("DyNumber", TUnit::MICROSECONDS, R"( --!syntax_v1 UPSERT INTO `/Root/table-1` (key, value) VALUES @@ -598,10 +598,10 @@ UPSERT INTO `/Root/table-1` (key, value) VALUES key = 6, value = .190244160000000e16 key = 7, value = .99999999999999999999999999999999999999e126 key = 8, value = (empty maybe) - )", WithMvcc); + )", WithMvcc); } - Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldEraseOnDyNumberNanoSeconds) { + Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldEraseOnDyNumberNanoSeconds) { ConditionalEraseShouldSuccess("DyNumber", TUnit::NANOSECONDS, R"( --!syntax_v1 UPSERT INTO `/Root/table-1` (key, value) VALUES @@ -612,16 +612,16 @@ UPSERT INTO `/Root/table-1` (key, value) VALUES )", R"( key = 3, value = .1902441600000000000e19 key = 4, value = (empty maybe) - )", WithMvcc); + )", WithMvcc); } - Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldFailOnVariousErrors) { + Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldFailOnVariousErrors) { using TEvResponse = TEvDataShard::TEvConditionalEraseRowsResponse; TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetDomainName("Root") .SetUseRealThreads(false); @@ -637,7 +637,7 @@ key = 4, value = (empty maybe) const auto tableName = Sprintf("table-%i", tableNum++); const auto tablePath = Sprintf("/Root/%s", tableName.data()); - CreateTable(server, sender, "/Root", tableName, TString(ct)); + CreateTable(server, sender, "/Root", tableName, TString(ct)); auto tableId = ResolveTableId(server, sender, tablePath); ConditionalEraseRows(server, sender, tablePath, TTableId(), 2, 0, TUnit::AUTO, {}, {}, @@ -661,13 +661,13 @@ key = 4, value = (empty maybe) } } - Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldBreakLocks) { + Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldBreakLocks) { using TEvResponse = TEvDataShard::TEvConditionalEraseRowsResponse; TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetDomainName("Root") .SetUseRealThreads(false); @@ -678,7 +678,7 @@ key = 4, value = (empty maybe) runtime.SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_DEBUG); InitRoot(server, sender); - CreateTable(server, sender, "/Root", "table-1"); + CreateTable(server, sender, "/Root", "table-1"); ExecSQL(server, sender, R"( UPSERT INTO [/Root/table-1] (key, value) VALUES (1, CAST("1970-01-01T00:00:00.000000Z" AS Timestamp)), @@ -724,13 +724,13 @@ key = 4, value = (empty maybe) } } - Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldNotEraseModifiedRows) { + Y_UNIT_TEST_WITH_MVCC(ConditionalEraseRowsShouldNotEraseModifiedRows) { using TEvResponse = TEvDataShard::TEvConditionalEraseRowsResponse; TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetDomainName("Root") .SetUseRealThreads(false); @@ -741,7 +741,7 @@ key = 4, value = (empty maybe) runtime.SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_DEBUG); InitRoot(server, sender); - CreateTable(server, sender, "/Root", "table-1"); + CreateTable(server, sender, "/Root", "table-1"); ExecSQL(server, sender, R"( UPSERT INTO [/Root/table-1] (key, value) VALUES (1, CAST("1970-01-01T00:00:00.000000Z" AS Timestamp)), diff --git a/ydb/core/tx/datashard/datashard_ut_init.cpp b/ydb/core/tx/datashard/datashard_ut_init.cpp index d48835a08b..818e30ab0c 100644 --- a/ydb/core/tx/datashard/datashard_ut_init.cpp +++ b/ydb/core/tx/datashard/datashard_ut_init.cpp @@ -51,48 +51,48 @@ TString GetTablePath(TTestActorRuntime &runtime, } Y_UNIT_TEST_SUITE(TTxDataShardTestInit) { - Y_UNIT_TEST(TestMvccStateSwitch) { - TPortManager pm; - TServerSettings serverSettings(pm.GetPort(2134)); - serverSettings.SetDomainName("Root") - .SetEnableMvcc(true) - .SetUseRealThreads(false); - - Tests::TServer::TPtr server = new TServer(serverSettings); - auto &runtime = *server->GetRuntime(); - auto sender = runtime.AllocateEdgeActor(); - runtime.SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_DEBUG); - InitRoot(server, sender); - - CreateShardedTable(server, sender, "/Root", "table-1", 1); - - auto tabletId = GetTableShards(server, sender, "/Root/table-1")[0]; - auto actorId = ResolveTablet(runtime, tabletId); + Y_UNIT_TEST(TestMvccStateSwitch) { + TPortManager pm; + TServerSettings serverSettings(pm.GetPort(2134)); + serverSettings.SetDomainName("Root") + .SetEnableMvcc(true) + .SetUseRealThreads(false); + + Tests::TServer::TPtr server = new TServer(serverSettings); + auto &runtime = *server->GetRuntime(); + auto sender = runtime.AllocateEdgeActor(); + runtime.SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_DEBUG); + InitRoot(server, sender); + + CreateShardedTable(server, sender, "/Root", "table-1", 1); + + auto tabletId = GetTableShards(server, sender, "/Root/table-1")[0]; + auto actorId = ResolveTablet(runtime, tabletId); auto datashard = dynamic_cast<NDataShard::TDataShard*>(runtime.FindActor(actorId)); - + UNIT_ASSERT_EQUAL(datashard->GetSnapshotManager().GetMvccState(), NDataShard::EMvccState::MvccEnabled); - + runtime.GetAppData().FeatureFlags.SetEnableMvccForTest(false); - - GracefulRestartTablet(runtime, tabletId, sender); - - auto waitFor = [&](const auto& condition, const TString& description) { - if (!condition()) { - Cerr << "... waiting for " << description << Endl; - TDispatchOptions options; - options.CustomFinalCondition = [&]() { - return condition(); - }; - runtime.DispatchEvents(options); - UNIT_ASSERT_C(condition(), "... failed to wait for " << description); - } - }; - - actorId = ResolveTablet(runtime, tabletId); + + GracefulRestartTablet(runtime, tabletId, sender); + + auto waitFor = [&](const auto& condition, const TString& description) { + if (!condition()) { + Cerr << "... waiting for " << description << Endl; + TDispatchOptions options; + options.CustomFinalCondition = [&]() { + return condition(); + }; + runtime.DispatchEvents(options); + UNIT_ASSERT_C(condition(), "... failed to wait for " << description); + } + }; + + actorId = ResolveTablet(runtime, tabletId); datashard = dynamic_cast<NDataShard::TDataShard*>(runtime.FindActor(actorId)); - + waitFor([&]{ return datashard->GetSnapshotManager().GetMvccState() == NDataShard::EMvccState::MvccDisabled; }, "mvcc disabled"); - } + } Y_UNIT_TEST(TestGetShardStateAfterInitialization) { TTestBasicRuntime runtime; diff --git a/ydb/core/tx/datashard/datashard_ut_kqp_scan.cpp b/ydb/core/tx/datashard/datashard_ut_kqp_scan.cpp index 5bf8689fe2..b2b14de190 100644 --- a/ydb/core/tx/datashard/datashard_ut_kqp_scan.cpp +++ b/ydb/core/tx/datashard/datashard_ut_kqp_scan.cpp @@ -47,7 +47,7 @@ Y_UNIT_TEST_SUITE(KqpScan) { * kill tablet after that. So in order to complete scan ComputeActor need to handle scan restart after * each ScanData. */ - Y_UNIT_TEST_WITH_MVCC(ScanRetryRead) { + Y_UNIT_TEST_WITH_MVCC(ScanRetryRead) { NKikimrConfig::TAppConfig appCfg; auto* rm = appCfg.MutableTableServiceConfig()->MutableResourceManager(); @@ -58,7 +58,7 @@ Y_UNIT_TEST_SUITE(KqpScan) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetNodeCount(2) .SetAppConfig(appCfg) .SetUseRealThreads(false); @@ -70,7 +70,7 @@ Y_UNIT_TEST_SUITE(KqpScan) { // EnableLogging(runtime); InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); ExecSQL(server, sender, FillTableQuery()); TSet<TActorId> scans; @@ -136,7 +136,7 @@ Y_UNIT_TEST_SUITE(KqpScan) { Cerr << (TStringBuilder() << "-- EvScanData from " << ev->Sender << ": pass" << Endl); Cerr.Flush(); } - + break; } @@ -157,13 +157,13 @@ Y_UNIT_TEST_SUITE(KqpScan) { /* * Force remote scans by meddling with EvShardsResolveStatus. Check that remote scan actually took place. */ - Y_UNIT_TEST_WITH_MVCC(RemoteShardScan) { + Y_UNIT_TEST_WITH_MVCC(RemoteShardScan) { NKikimrConfig::TAppConfig appCfg; TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetNodeCount(2) .SetAppConfig(appCfg) .SetUseRealThreads(false); @@ -175,7 +175,7 @@ Y_UNIT_TEST_SUITE(KqpScan) { // EnableLogging(runtime); InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 7); + CreateShardedTable(server, sender, "/Root", "table-1", 7); ExecSQL(server, sender, FillTableQuery()); ui64 firstNodeId = server->GetRuntime()->GetNodeId(0); @@ -243,7 +243,7 @@ Y_UNIT_TEST_SUITE(KqpScan) { UNIT_ASSERT_VALUES_EQUAL(result, 596400); } - Y_UNIT_TEST_WITH_MVCC(ScanDuringSplit) { + Y_UNIT_TEST_WITH_MVCC(ScanDuringSplit) { NKikimrConfig::TAppConfig appCfg; auto* rm = appCfg.MutableTableServiceConfig()->MutableResourceManager(); @@ -254,7 +254,7 @@ Y_UNIT_TEST_SUITE(KqpScan) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetNodeCount(2) .SetAppConfig(appCfg) .SetUseRealThreads(false); @@ -269,7 +269,7 @@ Y_UNIT_TEST_SUITE(KqpScan) { SetSplitMergePartCountLimit(&runtime, -1); InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); ExecSQL(server, sender, FillTableQuery()); auto shards = GetTableShards(server, sender, "/Root/table-1"); @@ -356,7 +356,7 @@ Y_UNIT_TEST_SUITE(KqpScan) { Cerr << (TStringBuilder() << "-- EvScanData from new tablet" << ev->Sender << ": pass" << Endl); Cerr.Flush(); } - + break; } diff --git a/ydb/core/tx/datashard/datashard_ut_locks.cpp b/ydb/core/tx/datashard/datashard_ut_locks.cpp index d5bcc1b38a..1d25c39f99 100644 --- a/ydb/core/tx/datashard/datashard_ut_locks.cpp +++ b/ydb/core/tx/datashard/datashard_ut_locks.cpp @@ -29,7 +29,7 @@ namespace NTest { public: ui64 PathOwnerId = 0; ui64 CurrentSchemeShardId = 0; - TRowVersion CompleteVersion = TRowVersion::Min(); + TRowVersion CompleteVersion = TRowVersion::Min(); TFakeDataShard() { InitSchema(); @@ -37,7 +37,7 @@ namespace NTest { static ui64 TabletID() { return 0; } static ui32 Generation() { return 0; } - TRowVersion LastCompleteTxVersion() const { return CompleteVersion; } + TRowVersion LastCompleteTxVersion() const { return CompleteVersion; } bool IsUserTable(const TTableId& tableId) const; @@ -141,17 +141,17 @@ namespace NTest { , Locks(&DataShard) { ui64 tid = tableId.PathId.LocalPathId; - ui64 sid = tableId.PathId.OwnerId; - - TmpLock.PathId = tid; - TmpLock.SchemeShard = sid; - - TmpLockVec.reserve(4); - TmpLockVec.emplace_back(TCell::Make(TmpLock.LockId)); - TmpLockVec.emplace_back(TCell::Make(TmpLock.DataShard)); - TmpLockVec.emplace_back(TCell::Make(TmpLock.SchemeShard)); - TmpLockVec.emplace_back(TCell::Make(TmpLock.PathId)); - + ui64 sid = tableId.PathId.OwnerId; + + TmpLock.PathId = tid; + TmpLock.SchemeShard = sid; + + TmpLockVec.reserve(4); + TmpLockVec.emplace_back(TCell::Make(TmpLock.LockId)); + TmpLockVec.emplace_back(TCell::Make(TmpLock.DataShard)); + TmpLockVec.emplace_back(TCell::Make(TmpLock.SchemeShard)); + TmpLockVec.emplace_back(TCell::Make(TmpLock.PathId)); + Locks.UpdateSchema(tableId.PathId, DataShard.TableInfos[tid]); } @@ -172,10 +172,10 @@ namespace NTest { Locks.BreakLock(TableId, key.GetRow()); } - void BreakSetLocks() { - Locks.BreakSetLocks(LockId()); - } - + void BreakSetLocks() { + Locks.BreakSetLocks(LockId()); + } + // void EraseLock(ui64 lockId) { @@ -189,58 +189,58 @@ namespace NTest { // - void StartTx(TLocksUpdate& update) { - update.LockTxId = 0; - Locks.SetTxUpdater(&update); - } - + void StartTx(TLocksUpdate& update) { + update.LockTxId = 0; + Locks.SetTxUpdater(&update); + } + void StartTx(ui64 lockTxId, TLocksUpdate& update) { update.LockTxId = lockTxId; Locks.SetTxUpdater(&update); } - TVector<TSysLocks::TLock> ApplyTxLocks() { - auto locks = Locks.ApplyLocks(); + TVector<TSysLocks::TLock> ApplyTxLocks() { + auto locks = Locks.ApplyLocks(); Locks.SetTxUpdater(nullptr); - return locks; + return locks; + } + + template <typename T> + void Select(const TVector<T>& selects, bool breakSetLocks = false) { + for (auto& value : selects) { + SetLock(TLockTester::TPointKey<T>(value)); + } + if (breakSetLocks) + BreakSetLocks(); + } + + template <typename T> + void Select(const TVector<std::pair<T, T>>& rangeSelects, ui32 rangeFlags = 0) { + for (auto& range : rangeSelects) { + SetLock(TLockTester::TRangeKey<T>(range.first, range.second, rangeFlags)); + } + } + + template <typename T> + void Select(const TVector<std::pair<T, T>>& rangeSelects, bool breakSetLocks, ui32 rangeFlags = 0) { + for (auto& range : rangeSelects) { + SetLock(TLockTester::TRangeKey<T>(range.first, range.second, rangeFlags)); + } + if (breakSetLocks) + BreakSetLocks(); + } + + template <typename T> + void Update(const TVector<T>& updates) { + for (auto& value : updates) { + BreakLock(TLockTester::TPointKey<T>(value)); + } + } + + void PromoteCompleteVersion(const TRowVersion& completeVersion) { + DataShard.CompleteVersion = Max(DataShard.CompleteVersion, completeVersion); } - template <typename T> - void Select(const TVector<T>& selects, bool breakSetLocks = false) { - for (auto& value : selects) { - SetLock(TLockTester::TPointKey<T>(value)); - } - if (breakSetLocks) - BreakSetLocks(); - } - - template <typename T> - void Select(const TVector<std::pair<T, T>>& rangeSelects, ui32 rangeFlags = 0) { - for (auto& range : rangeSelects) { - SetLock(TLockTester::TRangeKey<T>(range.first, range.second, rangeFlags)); - } - } - - template <typename T> - void Select(const TVector<std::pair<T, T>>& rangeSelects, bool breakSetLocks, ui32 rangeFlags = 0) { - for (auto& range : rangeSelects) { - SetLock(TLockTester::TRangeKey<T>(range.first, range.second, rangeFlags)); - } - if (breakSetLocks) - BreakSetLocks(); - } - - template <typename T> - void Update(const TVector<T>& updates) { - for (auto& value : updates) { - BreakLock(TLockTester::TPointKey<T>(value)); - } - } - - void PromoteCompleteVersion(const TRowVersion& completeVersion) { - DataShard.CompleteVersion = Max(DataShard.CompleteVersion, completeVersion); - } - private: TTableId TableId; NTest::TFakeDataShard DataShard; @@ -251,8 +251,8 @@ namespace NTest { ui64 LockId() const { return Locks.CurrentLockTxId(); } TArrayRef<const TCell> LockAsRowKey(ui64 lockId) { - TmpLockVec[0] = TCell::Make(TmpLock.LockId = lockId); - + TmpLockVec[0] = TCell::Make(TmpLock.LockId = lockId); + return TArrayRef<const TCell>(TmpLockVec.data(), TmpLockVec.size()); } @@ -266,9 +266,9 @@ namespace NTest { TLocksUpdate txLocks; tester.StartTx(lockTxId, txLocks); - tester.Select(selects); - tester.Update(updates); - tester.Select(rangeSelects, rangeFlags); + tester.Select(selects); + tester.Update(updates); + tester.Select(rangeSelects, rangeFlags); tester.ApplyTxLocks(); } @@ -296,181 +296,181 @@ namespace NTest { // TODO: correctness, times Y_UNIT_TEST_SUITE(TDataShardLocksTest) { -Y_UNIT_TEST(MvccTestOooTxDoesntBreakPrecedingReadersLocks) { - NTest::TLockTester tester; - - { - // lock tx - TLocksUpdate update; - update.CheckVersion = TRowVersion(1, 1); - tester.StartTx(10, update); - tester.Select(TVector<ui32>({10, 15, 25, 30})); - for (auto lock : tester.ApplyTxLocks()) - UNIT_ASSERT(!lock.IsError()); - } - - { - // Ooo write - TLocksUpdate update; - update.BreakVersion = TRowVersion(1, 10); - tester.StartTx(update); - tester.Update(TVector<ui32>({15, 25})); - tester.ApplyTxLocks(); - } - - { - // Check locks - TLocksUpdate update; - update.CheckVersion = TRowVersion(1, 5); - tester.StartTx(update); - UNIT_ASSERT(tester.CheckLock(10)); - } -} - -Y_UNIT_TEST(MvccTestOutdatedLocksRemove) { - NTest::TLockTester tester; - - { - // Lock tx - TLocksUpdate update; - update.CheckVersion = TRowVersion(1, 1); - tester.StartTx(10, update); - tester.Select(TVector<ui32>({10})); - for (auto lock : tester.ApplyTxLocks()) - UNIT_ASSERT(!lock.IsError()); - } - - { - // Ooo write breaks set lock - TLocksUpdate update; - update.BreakVersion = TRowVersion(1, 10); - tester.StartTx(update); - tester.Update(TVector<ui32>({10})); - tester.ApplyTxLocks(); - } - - { - // Another lock - TLocksUpdate update; - update.CheckVersion = TRowVersion(1, 15); - tester.StartTx(12, update); - tester.Select(TVector<ui32>({22})); - for (auto lock : tester.ApplyTxLocks()) - UNIT_ASSERT(!lock.IsError()); - } - - tester.PromoteCompleteVersion(TRowVersion(1, 10)); - - { - // lock is ready to be deleted but still in place - TLocksUpdate update; - update.CheckVersion = TRowVersion(1, 5); - tester.StartTx(update); - UNIT_ASSERT(tester.CheckLock(10)); - tester.ApplyTxLocks(); - } - - { - // erase triggers outdated locks cleanup - TLocksUpdate update; - tester.StartTx(update); - tester.EraseLock(12); - tester.ApplyTxLocks(); - } - - { - // lock is removed - TLocksUpdate update; - update.CheckVersion = TRowVersion(1, 5); - tester.StartTx(update); - UNIT_ASSERT(!tester.CheckLock(10)); - } -} - -Y_UNIT_TEST(MvccTestBreakEdge) { - NTest::TLockTester tester; - - { - // lock tx - TLocksUpdate update; - update.CheckVersion = TRowVersion(1, 1); - tester.StartTx(10, update); - tester.Select(TVector<ui32>({10, 15, 25, 30})); - for (auto lock : tester.ApplyTxLocks()) - UNIT_ASSERT(!lock.IsError()); - } - - { - // Ooo write - TLocksUpdate update; - update.BreakVersion = TRowVersion(1, 10); - tester.StartTx(update); - tester.Update(TVector<ui32>({15, 25})); - tester.ApplyTxLocks(); - } - - { - // Check locks - TLocksUpdate update; - update.CheckVersion = TRowVersion(1, 5); - tester.StartTx(update); - UNIT_ASSERT(tester.CheckLock(10)); - tester.ApplyTxLocks(); - } - - { - // At this point lock is broken - TLocksUpdate update; - update.CheckVersion = TRowVersion(1, 15); - tester.StartTx(update); - UNIT_ASSERT(!tester.CheckLock(10)); - } -} - -Y_UNIT_TEST(MvccTestWriteBreaksLocks) { - NTest::TLockTester tester; - - { - // lock tx - TLocksUpdate update; - update.CheckVersion = TRowVersion(1, 1); - tester.StartTx(10, update); - tester.Select(TVector<ui32>({10, 15, 25, 30})); - for (auto lock : tester.ApplyTxLocks()) - UNIT_ASSERT(!lock.IsError()); - } - - { - // subsequent write - TLocksUpdate update; - tester.StartTx(update); - tester.Update(TVector<ui32>({15, 25})); - tester.ApplyTxLocks(); - } - - { - // lock is broken permanently - TLocksUpdate update; - update.CheckVersion = TRowVersion(1, 5); - tester.StartTx(update); - UNIT_ASSERT(!tester.CheckLock(10)); - } -} - -Y_UNIT_TEST(MvccTestAlreadyBrokenLocks) { - NTest::TLockTester tester; - - { - // lock tx - TLocksUpdate update; - update.CheckVersion = TRowVersion(1, 1); - tester.StartTx(10, update); - tester.Select(TVector<ui32>({10, 15, 25, 30}), true); - for (auto lock : tester.ApplyTxLocks()) - UNIT_ASSERT(lock.IsError() && lock.Counter == TSysTables::TLocksTable::TLock::ErrorAlreadyBroken); - } -} - +Y_UNIT_TEST(MvccTestOooTxDoesntBreakPrecedingReadersLocks) { + NTest::TLockTester tester; + + { + // lock tx + TLocksUpdate update; + update.CheckVersion = TRowVersion(1, 1); + tester.StartTx(10, update); + tester.Select(TVector<ui32>({10, 15, 25, 30})); + for (auto lock : tester.ApplyTxLocks()) + UNIT_ASSERT(!lock.IsError()); + } + + { + // Ooo write + TLocksUpdate update; + update.BreakVersion = TRowVersion(1, 10); + tester.StartTx(update); + tester.Update(TVector<ui32>({15, 25})); + tester.ApplyTxLocks(); + } + + { + // Check locks + TLocksUpdate update; + update.CheckVersion = TRowVersion(1, 5); + tester.StartTx(update); + UNIT_ASSERT(tester.CheckLock(10)); + } +} + +Y_UNIT_TEST(MvccTestOutdatedLocksRemove) { + NTest::TLockTester tester; + + { + // Lock tx + TLocksUpdate update; + update.CheckVersion = TRowVersion(1, 1); + tester.StartTx(10, update); + tester.Select(TVector<ui32>({10})); + for (auto lock : tester.ApplyTxLocks()) + UNIT_ASSERT(!lock.IsError()); + } + + { + // Ooo write breaks set lock + TLocksUpdate update; + update.BreakVersion = TRowVersion(1, 10); + tester.StartTx(update); + tester.Update(TVector<ui32>({10})); + tester.ApplyTxLocks(); + } + + { + // Another lock + TLocksUpdate update; + update.CheckVersion = TRowVersion(1, 15); + tester.StartTx(12, update); + tester.Select(TVector<ui32>({22})); + for (auto lock : tester.ApplyTxLocks()) + UNIT_ASSERT(!lock.IsError()); + } + + tester.PromoteCompleteVersion(TRowVersion(1, 10)); + + { + // lock is ready to be deleted but still in place + TLocksUpdate update; + update.CheckVersion = TRowVersion(1, 5); + tester.StartTx(update); + UNIT_ASSERT(tester.CheckLock(10)); + tester.ApplyTxLocks(); + } + + { + // erase triggers outdated locks cleanup + TLocksUpdate update; + tester.StartTx(update); + tester.EraseLock(12); + tester.ApplyTxLocks(); + } + + { + // lock is removed + TLocksUpdate update; + update.CheckVersion = TRowVersion(1, 5); + tester.StartTx(update); + UNIT_ASSERT(!tester.CheckLock(10)); + } +} + +Y_UNIT_TEST(MvccTestBreakEdge) { + NTest::TLockTester tester; + + { + // lock tx + TLocksUpdate update; + update.CheckVersion = TRowVersion(1, 1); + tester.StartTx(10, update); + tester.Select(TVector<ui32>({10, 15, 25, 30})); + for (auto lock : tester.ApplyTxLocks()) + UNIT_ASSERT(!lock.IsError()); + } + + { + // Ooo write + TLocksUpdate update; + update.BreakVersion = TRowVersion(1, 10); + tester.StartTx(update); + tester.Update(TVector<ui32>({15, 25})); + tester.ApplyTxLocks(); + } + + { + // Check locks + TLocksUpdate update; + update.CheckVersion = TRowVersion(1, 5); + tester.StartTx(update); + UNIT_ASSERT(tester.CheckLock(10)); + tester.ApplyTxLocks(); + } + + { + // At this point lock is broken + TLocksUpdate update; + update.CheckVersion = TRowVersion(1, 15); + tester.StartTx(update); + UNIT_ASSERT(!tester.CheckLock(10)); + } +} + +Y_UNIT_TEST(MvccTestWriteBreaksLocks) { + NTest::TLockTester tester; + + { + // lock tx + TLocksUpdate update; + update.CheckVersion = TRowVersion(1, 1); + tester.StartTx(10, update); + tester.Select(TVector<ui32>({10, 15, 25, 30})); + for (auto lock : tester.ApplyTxLocks()) + UNIT_ASSERT(!lock.IsError()); + } + + { + // subsequent write + TLocksUpdate update; + tester.StartTx(update); + tester.Update(TVector<ui32>({15, 25})); + tester.ApplyTxLocks(); + } + + { + // lock is broken permanently + TLocksUpdate update; + update.CheckVersion = TRowVersion(1, 5); + tester.StartTx(update); + UNIT_ASSERT(!tester.CheckLock(10)); + } +} + +Y_UNIT_TEST(MvccTestAlreadyBrokenLocks) { + NTest::TLockTester tester; + + { + // lock tx + TLocksUpdate update; + update.CheckVersion = TRowVersion(1, 1); + tester.StartTx(10, update); + tester.Select(TVector<ui32>({10, 15, 25, 30}), true); + for (auto lock : tester.ApplyTxLocks()) + UNIT_ASSERT(lock.IsError() && lock.Counter == TSysTables::TLocksTable::TLock::ErrorAlreadyBroken); + } +} + Y_UNIT_TEST(Points_OneTx) { NTest::TLockTester tester; diff --git a/ydb/core/tx/datashard/datashard_ut_order.cpp b/ydb/core/tx/datashard/datashard_ut_order.cpp index 7509fee845..32472dce59 100644 --- a/ydb/core/tx/datashard/datashard_ut_order.cpp +++ b/ydb/core/tx/datashard/datashard_ut_order.cpp @@ -215,29 +215,29 @@ static void ZigZag(const TTester::TOptions& opts, bool symmetric, ui32 limit = 4 ZigZag(proxy, symmetric, limit); } -Y_UNIT_TEST_WITH_MVCC(ZigZag) { - TTester::TOptions opts; - opts.EnableMvcc(WithMvcc); - ZigZag(opts, true); - ZigZag(opts, false); +Y_UNIT_TEST_WITH_MVCC(ZigZag) { + TTester::TOptions opts; + opts.EnableMvcc(WithMvcc); + ZigZag(opts, true); + ZigZag(opts, false); } -Y_UNIT_TEST_WITH_MVCC(ZigZag_oo) { +Y_UNIT_TEST_WITH_MVCC(ZigZag_oo) { TVector<ui32> variants = {4, 8, 16}; for (ui32 var : variants) { TTester::TOptions opts; opts.EnableOutOfOrder(var); - opts.EnableMvcc(WithMvcc); + opts.EnableMvcc(WithMvcc); ZigZag(opts, true); ZigZag(opts, false); } } -Y_UNIT_TEST_WITH_MVCC(ZigZag_oo8_dirty) { +Y_UNIT_TEST_WITH_MVCC(ZigZag_oo8_dirty) { TTester::TOptions opts; opts.EnableOutOfOrder(8); opts.EnableSoftUpdates(); - opts.EnableMvcc(WithMvcc); + opts.EnableMvcc(WithMvcc); ZigZag(opts, true); ZigZag(opts, false); } @@ -313,48 +313,48 @@ static void ImmediateBetweenOnline(const TTester::TOptions& opts, bool forceOnli proxy.ExecQueue(); } -Y_UNIT_TEST_WITH_MVCC(ImmediateBetweenOnline) { - TTester::TOptions opts; - opts.EnableMvcc(WithMvcc); - ImmediateBetweenOnline(opts, false); +Y_UNIT_TEST_WITH_MVCC(ImmediateBetweenOnline) { + TTester::TOptions opts; + opts.EnableMvcc(WithMvcc); + ImmediateBetweenOnline(opts, false); } -Y_UNIT_TEST_WITH_MVCC(ImmediateBetweenOnline_Init) { - TTester::TOptions opts; - opts.EnableMvcc(WithMvcc); - ImmediateBetweenOnline(opts, false); +Y_UNIT_TEST_WITH_MVCC(ImmediateBetweenOnline_Init) { + TTester::TOptions opts; + opts.EnableMvcc(WithMvcc); + ImmediateBetweenOnline(opts, false); } -Y_UNIT_TEST_WITH_MVCC(ForceOnlineBetweenOnline) { - TTester::TOptions opts; - opts.EnableMvcc(WithMvcc); - ImmediateBetweenOnline(opts, true); +Y_UNIT_TEST_WITH_MVCC(ForceOnlineBetweenOnline) { + TTester::TOptions opts; + opts.EnableMvcc(WithMvcc); + ImmediateBetweenOnline(opts, true); } -Y_UNIT_TEST_WITH_MVCC(ImmediateBetweenOnline_oo8) { +Y_UNIT_TEST_WITH_MVCC(ImmediateBetweenOnline_oo8) { TTester::TOptions opts; - opts.EnableMvcc(WithMvcc); + opts.EnableMvcc(WithMvcc); opts.EnableOutOfOrder(8); ImmediateBetweenOnline(opts, false); } -Y_UNIT_TEST_WITH_MVCC(ImmediateBetweenOnline_Init_oo8) { +Y_UNIT_TEST_WITH_MVCC(ImmediateBetweenOnline_Init_oo8) { TTester::TOptions opts(1); - opts.EnableMvcc(WithMvcc); + opts.EnableMvcc(WithMvcc); opts.EnableOutOfOrder(8); ImmediateBetweenOnline(opts, false); } -Y_UNIT_TEST_WITH_MVCC(ForceOnlineBetweenOnline_oo8) { +Y_UNIT_TEST_WITH_MVCC(ForceOnlineBetweenOnline_oo8) { TTester::TOptions opts; - opts.EnableMvcc(WithMvcc); + opts.EnableMvcc(WithMvcc); opts.EnableOutOfOrder(8); ImmediateBetweenOnline(opts, true); } -Y_UNIT_TEST_WITH_MVCC(ImmediateBetweenOnline_oo8_dirty) { +Y_UNIT_TEST_WITH_MVCC(ImmediateBetweenOnline_oo8_dirty) { TTester::TOptions opts; - opts.EnableMvcc(WithMvcc); + opts.EnableMvcc(WithMvcc); opts.EnableOutOfOrder(8); opts.EnableSoftUpdates(); ImmediateBetweenOnline(opts, false); @@ -379,9 +379,9 @@ static void EvictShardCache(TFakeMiniKQLProxy& proxy, ui32 count = 500) { proxy.ExecQueue(); } -Y_UNIT_TEST_WITH_MVCC(DelayData) { +Y_UNIT_TEST_WITH_MVCC(DelayData) { TTester::TOptions opts; - opts.EnableMvcc(WithMvcc); + opts.EnableMvcc(WithMvcc); opts.EnableOutOfOrder(2); opts.ExecutorCacheSize = 0; TTester t(TTester::ESchema_MultiShardKV, opts); @@ -408,10 +408,10 @@ Y_UNIT_TEST_WITH_MVCC(DelayData) { proxy.ExecQueue(); } -Y_UNIT_TEST_WITH_MVCC(ReadWriteReorder) { +Y_UNIT_TEST_WITH_MVCC(ReadWriteReorder) { TTester::TOptions opts; opts.EnableOutOfOrder(10); - opts.EnableMvcc(WithMvcc); + opts.EnableMvcc(WithMvcc); TTester t(TTester::ESchema_MultiShardKV, opts); TFakeMiniKQLProxy proxy(t); @@ -785,12 +785,12 @@ static void RandomTxDeps(const TTester::TOptions& opts, ui32 numTxs, ui32 maxKey static constexpr ui32 NumRun() { return 2; } -Y_UNIT_TEST_WITH_MVCC(RandomPoints_ReproducerDelayData1) { +Y_UNIT_TEST_WITH_MVCC(RandomPoints_ReproducerDelayData1) { TTester::TOptions opts; opts.DelayData = true; opts.ExecutorCacheSize = 0; opts.EnableOutOfOrder(8); - opts.EnableMvcc(WithMvcc); + opts.EnableMvcc(WithMvcc); RandomTxDeps(opts, 8, 8, false, false, {5, 5, 6, 7, 3, 6, 5, 6}, @@ -798,11 +798,11 @@ Y_UNIT_TEST_WITH_MVCC(RandomPoints_ReproducerDelayData1) { {11, 30, 10, 12, 5, 23, 30, 32}); } -Y_UNIT_TEST_WITH_MVCC(RandomPoints_ReproducerDelayRS1) { +Y_UNIT_TEST_WITH_MVCC(RandomPoints_ReproducerDelayRS1) { TTester::TOptions opts; opts.DelayReadSet = true; opts.EnableOutOfOrder(8); - opts.EnableMvcc(WithMvcc); + opts.EnableMvcc(WithMvcc); RandomTxDeps(opts, 8, 8, true, false, {2, 7, 7, 7, 6, 3, 2, 4}, @@ -810,11 +810,11 @@ Y_UNIT_TEST_WITH_MVCC(RandomPoints_ReproducerDelayRS1) { {0, 40, 2, 33, 8, 4, 1, 3}); } -Y_UNIT_TEST_WITH_MVCC(RandomPoints_DelayRS) { +Y_UNIT_TEST_WITH_MVCC(RandomPoints_DelayRS) { TTester::TOptions opts; opts.DelayReadSet = true; opts.EnableOutOfOrder(8); - opts.EnableMvcc(WithMvcc); + opts.EnableMvcc(WithMvcc); TVector<std::pair<ui32, ui32>> variants; variants.push_back({8, 8}); @@ -834,11 +834,11 @@ Y_UNIT_TEST_WITH_MVCC(RandomPoints_DelayRS) { } } -Y_UNIT_TEST_WITH_MVCC(RandomDotRanges_DelayRS) { +Y_UNIT_TEST_WITH_MVCC(RandomDotRanges_DelayRS) { TTester::TOptions opts; opts.DelayReadSet = true; opts.EnableOutOfOrder(8); - opts.EnableMvcc(WithMvcc); + opts.EnableMvcc(WithMvcc); TVector<std::pair<ui32, ui32>> variants; variants.push_back({8, 8}); @@ -858,12 +858,12 @@ Y_UNIT_TEST_WITH_MVCC(RandomDotRanges_DelayRS) { } } -Y_UNIT_TEST_WITH_MVCC(RandomPoints_DelayRS_Reboot) { +Y_UNIT_TEST_WITH_MVCC(RandomPoints_DelayRS_Reboot) { TTester::TOptions opts; opts.DelayReadSet = true; opts.RebootOnDelay = true; opts.EnableOutOfOrder(8); - opts.EnableMvcc(WithMvcc); + opts.EnableMvcc(WithMvcc); TVector<std::pair<ui32, ui32>> variants; variants.push_back({8, 8}); @@ -883,13 +883,13 @@ Y_UNIT_TEST_WITH_MVCC(RandomPoints_DelayRS_Reboot) { } } -Y_UNIT_TEST_WITH_MVCC(RandomPoints_DelayRS_Reboot_Dirty) { +Y_UNIT_TEST_WITH_MVCC(RandomPoints_DelayRS_Reboot_Dirty) { TTester::TOptions opts; opts.DelayReadSet = true; opts.RebootOnDelay = true; opts.EnableSoftUpdates(); opts.EnableOutOfOrder(8); - opts.EnableMvcc(WithMvcc); + opts.EnableMvcc(WithMvcc); TVector<std::pair<ui32, ui32>> variants; variants.push_back({8, 8}); @@ -909,12 +909,12 @@ Y_UNIT_TEST_WITH_MVCC(RandomPoints_DelayRS_Reboot_Dirty) { } } -Y_UNIT_TEST_WITH_MVCC(RandomPoints_DelayData) { +Y_UNIT_TEST_WITH_MVCC(RandomPoints_DelayData) { TTester::TOptions opts; opts.DelayData = true; opts.ExecutorCacheSize = 0; opts.EnableOutOfOrder(8); - opts.EnableMvcc(WithMvcc); + opts.EnableMvcc(WithMvcc); TVector<std::pair<ui32, ui32>> variants; variants.push_back({8, 8}); @@ -1135,11 +1135,11 @@ static void RandomPointsAndRanges(const TTester::TOptions& opts, ui32 numTxs, ui RandomPointsAndRanges(proxy, numTxs, maxWrites, maxReads, maxRanges); } -Y_UNIT_TEST_WITH_MVCC(RandomPointsAndRanges) { +Y_UNIT_TEST_WITH_MVCC(RandomPointsAndRanges) { TTester::TOptions opts; opts.ExecutorCacheSize = 0; opts.EnableOutOfOrder(8); - opts.EnableMvcc(WithMvcc); + opts.EnableMvcc(WithMvcc); TVector<TVector<ui32>> variants; variants.push_back(TVector<ui32>() = {100, 20, 20, 20}); @@ -1156,11 +1156,11 @@ Y_UNIT_TEST_WITH_MVCC(RandomPointsAndRanges) { /// Y_UNIT_TEST_SUITE(DataShardScan) { -Y_UNIT_TEST_WITH_MVCC(ScanFollowedByUpdate) { +Y_UNIT_TEST_WITH_MVCC(ScanFollowedByUpdate) { TTester::TOptions opts; opts.ExecutorCacheSize = 0; opts.EnableOutOfOrder(8); - opts.EnableMvcc(WithMvcc); + opts.EnableMvcc(WithMvcc); TTester t(TTester::ESchema_MultiShardKV, opts); TFakeMiniKQLProxy proxy(t); @@ -1233,7 +1233,7 @@ Y_UNIT_TEST_QUAD(TestDelayedTxWaitsForWriteActiveTxOnly, UseMvcc, UseNewEngine) TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -1251,8 +1251,8 @@ Y_UNIT_TEST_QUAD(TestDelayedTxWaitsForWriteActiveTxOnly, UseMvcc, UseNewEngine) InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1); - CreateShardedTable(server, sender, "/Root", "table-2", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-2", 1); ExecSQL(server, sender, Q_("UPSERT INTO `/Root/table-1` (key, value) VALUES (1, 1), (3, 3);")); ExecSQL(server, sender, Q_("UPSERT INTO `/Root/table-2` (key, value) VALUES (2, 2);")); @@ -1329,7 +1329,7 @@ Y_UNIT_TEST_QUAD(TestOnlyDataTxLagCausesRejects, UseMvcc, UseNewEngine) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -1343,7 +1343,7 @@ Y_UNIT_TEST_QUAD(TestOnlyDataTxLagCausesRejects, UseMvcc, UseNewEngine) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 2); + CreateShardedTable(server, sender, "/Root", "table-1", 2); //auto shards = GetTableShards(server, sender, "/Root/table-1"); ExecSQL(server, sender, Q_("UPSERT INTO `/Root/table-1` (key, value) VALUES (1, 3000000001), (3000000003, 3)")); @@ -1405,7 +1405,7 @@ Y_UNIT_TEST_QUAD(TestOutOfOrderLockLost, UseMvcc, UseNewEngine) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -1417,8 +1417,8 @@ Y_UNIT_TEST_QUAD(TestOutOfOrderLockLost, UseMvcc, UseNewEngine) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1); - CreateShardedTable(server, sender, "/Root", "table-2", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-2", 1); ExecSQL(server, sender, Q_("UPSERT INTO `/Root/table-1` (key, value) VALUES (1, 1);")); ExecSQL(server, sender, Q_("UPSERT INTO `/Root/table-2` (key, value) VALUES (2, 1);")); @@ -1535,74 +1535,74 @@ Y_UNIT_TEST_QUAD(TestOutOfOrderLockLost, UseMvcc, UseNewEngine) { } Y_UNIT_TEST_NEW_ENGINE(TestMvccReadDoesntBlockWrites) { - TPortManager pm; - TServerSettings serverSettings(pm.GetPort(2134)); - serverSettings.SetDomainName("Root") - .SetEnableMvcc(true) - .SetUseRealThreads(false); - - Tests::TServer::TPtr server = new TServer(serverSettings); - auto &runtime = *server->GetRuntime(); - - auto sender = runtime.AllocateEdgeActor(); - auto sender2 = runtime.AllocateEdgeActor(); - auto sender3 = runtime.AllocateEdgeActor(); - - runtime.SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_TRACE); + TPortManager pm; + TServerSettings serverSettings(pm.GetPort(2134)); + serverSettings.SetDomainName("Root") + .SetEnableMvcc(true) + .SetUseRealThreads(false); + + Tests::TServer::TPtr server = new TServer(serverSettings); + auto &runtime = *server->GetRuntime(); + + auto sender = runtime.AllocateEdgeActor(); + auto sender2 = runtime.AllocateEdgeActor(); + auto sender3 = runtime.AllocateEdgeActor(); + + runtime.SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_TRACE); runtime.SetLogPriority(UseNewEngine ? NKikimrServices::KQP_EXECUTER : NKikimrServices::TX_PROXY, NLog::PRI_DEBUG); - - InitRoot(server, sender); - - CreateShardedTable(server, sender, "/Root", "table-1", 1); - CreateShardedTable(server, sender, "/Root", "table-2", 1); - + + InitRoot(server, sender); + + CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-2", 1); + ExecSQL(server, sender, Q_("UPSERT INTO `/Root/table-1` (key, value) VALUES (1, 1);")); ExecSQL(server, sender, Q_("UPSERT INTO `/Root/table-2` (key, value) VALUES (2, 2);")); - - TString sessionId = CreateSession(runtime, sender); - - TString txId; - { + + TString sessionId = CreateSession(runtime, sender); + + TString txId; + { auto ev = ExecRequest(runtime, sender, MakeBeginRequest(sessionId, Q_(R"( SELECT * FROM `/Root/table-1` UNION ALL SELECT * FROM `/Root/table-2`)"))); - auto& response = ev->Get()->Record.GetRef(); - UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); - txId = response.GetResponse().GetTxMeta().id(); - UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults().size(), 1u); - } - - // Capture and block all readset messages - TVector<THolder<IEventHandle>> readSets; - auto captureRS = [&](TTestActorRuntimeBase&, - TAutoPtr<IEventHandle> &event) -> auto { - if (event->GetTypeRewrite() == TEvTxProcessing::EvReadSet) { + auto& response = ev->Get()->Record.GetRef(); + UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); + txId = response.GetResponse().GetTxMeta().id(); + UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults().size(), 1u); + } + + // Capture and block all readset messages + TVector<THolder<IEventHandle>> readSets; + auto captureRS = [&](TTestActorRuntimeBase&, + TAutoPtr<IEventHandle> &event) -> auto { + if (event->GetTypeRewrite() == TEvTxProcessing::EvReadSet) { readSets.push_back(std::move(event)); - return TTestActorRuntime::EEventAction::DROP; - } - return TTestActorRuntime::EEventAction::PROCESS; - }; - auto prevObserverFunc = runtime.SetObserverFunc(captureRS); - - // Send a commit request, it would block on readset exchange + return TTestActorRuntime::EEventAction::DROP; + } + return TTestActorRuntime::EEventAction::PROCESS; + }; + auto prevObserverFunc = runtime.SetObserverFunc(captureRS); + + // Send a commit request, it would block on readset exchange SendRequest(runtime, sender2, MakeCommitRequest(sessionId, txId, Q_(R"( UPSERT INTO `/Root/table-1` (key, value) VALUES (3, 2); UPSERT INTO `/Root/table-2` (key, value) VALUES (4, 2);)"))); - - // Wait until we captured both readsets - { - TDispatchOptions options; - options.FinalEvents.emplace_back( - [&](IEventHandle &) -> bool { - return readSets.size() >= 2; - }); - runtime.DispatchEvents(options); - UNIT_ASSERT_VALUES_EQUAL(readSets.size(), 2u); - } - runtime.SetObserverFunc(prevObserverFunc); - - // it will be blocked by previous transaction that is waiting for its readsets + + // Wait until we captured both readsets + { + TDispatchOptions options; + options.FinalEvents.emplace_back( + [&](IEventHandle &) -> bool { + return readSets.size() >= 2; + }); + runtime.DispatchEvents(options); + UNIT_ASSERT_VALUES_EQUAL(readSets.size(), 2u); + } + runtime.SetObserverFunc(prevObserverFunc); + + // it will be blocked by previous transaction that is waiting for its readsets SendRequest(runtime, sender, MakeSimpleRequest(Q_(R"( $rows = ( SELECT * FROM `/Root/table-1` WHERE key = 3 OR key = 5 @@ -1610,48 +1610,48 @@ Y_UNIT_TEST_NEW_ENGINE(TestMvccReadDoesntBlockWrites) { SELECT * FROM `/Root/table-2` WHERE key = 4 OR key = 6 ); SELECT key, value FROM $rows ORDER BY key)"))); - - // wait for the tx is planned - TDispatchOptions opts; - opts.FinalEvents.push_back(TDispatchOptions::TFinalEventCondition(TEvTxProcessing::EEv::EvPlanStep, 2)); - runtime.DispatchEvents(opts); - - { - // despite it's writing into the key that previous transaction reads this write should finish successfully + + // wait for the tx is planned + TDispatchOptions opts; + opts.FinalEvents.push_back(TDispatchOptions::TFinalEventCondition(TEvTxProcessing::EEv::EvPlanStep, 2)); + runtime.DispatchEvents(opts); + + { + // despite it's writing into the key that previous transaction reads this write should finish successfully auto ev = ExecRequest(runtime, sender3, MakeSimpleRequest(Q_(R"( UPSERT INTO `/Root/table-1` (key, value) VALUES (5, 10); UPSERT INTO `/Root/table-2` (key, value) VALUES (6, 10))"))); - auto& response = ev->Get()->Record.GetRef(); - UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); - } - - // resend readsets, it will unblock both commit tx and read - for (auto& ev : readSets) { - runtime.Send(ev.Release(), 0, /* via actor system */ true); - } - readSets.clear(); - - // Read the commit reply next, it must succeed - { - auto ev = runtime.GrabEdgeEventRethrow<NKqp::TEvKqp::TEvQueryResponse>(sender2); - auto& response = ev->Get()->Record.GetRef(); - UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); - } - - { - // Read should finish successfully and it doesn't see the write - auto ev = runtime.GrabEdgeEventRethrow<NKqp::TEvKqp::TEvQueryResponse>(sender); - auto& response = ev->Get()->Record.GetRef(); - UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); - TString expected = "Struct { " - "List { Struct { Optional { Uint32: 3 } } Struct { Optional { Uint32: 2 } } } " - "List { Struct { Optional { Uint32: 4 } } Struct { Optional { Uint32: 2 } } } " - "} Struct { Bool: false }"; - UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults()[0].GetValue().ShortDebugString(), expected); - } - - { - // Now we see the write + auto& response = ev->Get()->Record.GetRef(); + UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); + } + + // resend readsets, it will unblock both commit tx and read + for (auto& ev : readSets) { + runtime.Send(ev.Release(), 0, /* via actor system */ true); + } + readSets.clear(); + + // Read the commit reply next, it must succeed + { + auto ev = runtime.GrabEdgeEventRethrow<NKqp::TEvKqp::TEvQueryResponse>(sender2); + auto& response = ev->Get()->Record.GetRef(); + UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); + } + + { + // Read should finish successfully and it doesn't see the write + auto ev = runtime.GrabEdgeEventRethrow<NKqp::TEvKqp::TEvQueryResponse>(sender); + auto& response = ev->Get()->Record.GetRef(); + UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); + TString expected = "Struct { " + "List { Struct { Optional { Uint32: 3 } } Struct { Optional { Uint32: 2 } } } " + "List { Struct { Optional { Uint32: 4 } } Struct { Optional { Uint32: 2 } } } " + "} Struct { Bool: false }"; + UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults()[0].GetValue().ShortDebugString(), expected); + } + + { + // Now we see the write auto ev = ExecRequest(runtime, sender, MakeSimpleRequest(Q_(R"( $rows = ( SELECT * FROM `/Root/table-1` WHERE key = 3 OR key = 5 @@ -1659,26 +1659,26 @@ Y_UNIT_TEST_NEW_ENGINE(TestMvccReadDoesntBlockWrites) { SELECT * FROM `/Root/table-2` WHERE key = 4 OR key = 6 ); SELECT key, value FROM $rows ORDER BY key)"))); - auto& response = ev->Get()->Record.GetRef(); - UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); - UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults().size(), 1u); - TString expected = "Struct { " - "List { Struct { Optional { Uint32: 3 } } Struct { Optional { Uint32: 2 } } } " - "List { Struct { Optional { Uint32: 4 } } Struct { Optional { Uint32: 2 } } } " - "List { Struct { Optional { Uint32: 5 } } Struct { Optional { Uint32: 10 } } } " - "List { Struct { Optional { Uint32: 6 } } Struct { Optional { Uint32: 10 } } } " - "} Struct { Bool: false }"; - UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults()[0].GetValue().ShortDebugString(), expected); - } -} - + auto& response = ev->Get()->Record.GetRef(); + UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); + UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults().size(), 1u); + TString expected = "Struct { " + "List { Struct { Optional { Uint32: 3 } } Struct { Optional { Uint32: 2 } } } " + "List { Struct { Optional { Uint32: 4 } } Struct { Optional { Uint32: 2 } } } " + "List { Struct { Optional { Uint32: 5 } } Struct { Optional { Uint32: 10 } } } " + "List { Struct { Optional { Uint32: 6 } } Struct { Optional { Uint32: 10 } } } " + "} Struct { Bool: false }"; + UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults()[0].GetValue().ShortDebugString(), expected); + } +} + Y_UNIT_TEST_QUAD(TestOutOfOrderReadOnlyAllowed, UseMvcc, UseNewEngine) { - TPortManager pm; - TServerSettings serverSettings(pm.GetPort(2134)); - serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) - .SetUseRealThreads(false); - + TPortManager pm; + TServerSettings serverSettings(pm.GetPort(2134)); + serverSettings.SetDomainName("Root") + .SetEnableMvcc(WithMvcc) + .SetUseRealThreads(false); + Tests::TServer::TPtr server = new TServer(serverSettings); auto &runtime = *server->GetRuntime(); auto sender = runtime.AllocateEdgeActor(); @@ -1688,8 +1688,8 @@ Y_UNIT_TEST_QUAD(TestOutOfOrderReadOnlyAllowed, UseMvcc, UseNewEngine) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1); - CreateShardedTable(server, sender, "/Root", "table-2", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-2", 1); ExecSQL(server, sender, Q_("UPSERT INTO `/Root/table-1` (key, value) VALUES (1, 1);")); ExecSQL(server, sender, Q_("UPSERT INTO `/Root/table-2` (key, value) VALUES (2, 1);")); @@ -1786,7 +1786,7 @@ Y_UNIT_TEST_QUAD(TestOutOfOrderNonConflictingWrites, UseMvcc, UseNewEngine) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -1798,8 +1798,8 @@ Y_UNIT_TEST_QUAD(TestOutOfOrderNonConflictingWrites, UseMvcc, UseNewEngine) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1); - CreateShardedTable(server, sender, "/Root", "table-2", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-2", 1); ExecSQL(server, sender, Q_("UPSERT INTO `/Root/table-1` (key, value) VALUES (1, 1);")); ExecSQL(server, sender, Q_("UPSERT INTO `/Root/table-2` (key, value) VALUES (2, 1);")); @@ -2047,7 +2047,7 @@ Y_UNIT_TEST_NEW_ENGINE(MvccTestOutOfOrderRestartLocksSingleWithoutBarrier) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(true) + .SetEnableMvcc(true) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -2062,8 +2062,8 @@ Y_UNIT_TEST_NEW_ENGINE(MvccTestOutOfOrderRestartLocksSingleWithoutBarrier) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1); - CreateShardedTable(server, sender, "/Root", "table-2", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-2", 1); auto table1shards = GetTableShards(server, sender, "/Root/table-1"); auto table2shards = GetTableShards(server, sender, "/Root/table-2"); @@ -2079,143 +2079,143 @@ Y_UNIT_TEST_NEW_ENGINE(MvccTestOutOfOrderRestartLocksSingleWithoutBarrier) { SELECT * FROM `/Root/table-1` WHERE key = 1 UNION ALL SELECT * FROM `/Root/table-2` WHERE key = 2)"))); - auto& response = ev->Get()->Record.GetRef(); - UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); - txId = response.GetResponse().GetTxMeta().id(); - UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults().size(), 1u); - } - - // Capture and block all readset messages - TVector<THolder<IEventHandle>> readSets; - auto captureRS = [&](TTestActorRuntimeBase&, - TAutoPtr<IEventHandle> &event) -> auto { - if (event->GetTypeRewrite() == TEvTxProcessing::EvReadSet) { + auto& response = ev->Get()->Record.GetRef(); + UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); + txId = response.GetResponse().GetTxMeta().id(); + UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults().size(), 1u); + } + + // Capture and block all readset messages + TVector<THolder<IEventHandle>> readSets; + auto captureRS = [&](TTestActorRuntimeBase&, + TAutoPtr<IEventHandle> &event) -> auto { + if (event->GetTypeRewrite() == TEvTxProcessing::EvReadSet) { readSets.push_back(std::move(event)); - return TTestActorRuntime::EEventAction::DROP; - } - return TTestActorRuntime::EEventAction::PROCESS; - }; - auto prevObserverFunc = runtime.SetObserverFunc(captureRS); - - // Send a commit request, it would block on readset exchange - auto sender2 = runtime.AllocateEdgeActor(); + return TTestActorRuntime::EEventAction::DROP; + } + return TTestActorRuntime::EEventAction::PROCESS; + }; + auto prevObserverFunc = runtime.SetObserverFunc(captureRS); + + // Send a commit request, it would block on readset exchange + auto sender2 = runtime.AllocateEdgeActor(); SendRequest(runtime, sender2, MakeCommitRequest(sessionId, txId, Q_(R"( UPSERT INTO `/Root/table-1` (key, value) VALUES (3, 2); UPSERT INTO `/Root/table-2` (key, value) VALUES (4, 2))"))); - - // Wait until we captured both readsets - if (readSets.size() < 2) { - TDispatchOptions options; - options.FinalEvents.emplace_back( - [&](IEventHandle &) -> bool { - return readSets.size() >= 2; - }); - runtime.DispatchEvents(options); - } - UNIT_ASSERT_VALUES_EQUAL(readSets.size(), 2u); - - // Reboot table-1 tablet - readSets.clear(); + + // Wait until we captured both readsets + if (readSets.size() < 2) { + TDispatchOptions options; + options.FinalEvents.emplace_back( + [&](IEventHandle &) -> bool { + return readSets.size() >= 2; + }); + runtime.DispatchEvents(options); + } + UNIT_ASSERT_VALUES_EQUAL(readSets.size(), 2u); + + // Reboot table-1 tablet + readSets.clear(); RebootTablet(runtime, table1shards[0], sender); - - // Wait until we captured both readsets again - if (readSets.size() < 2) { - TDispatchOptions options; - options.FinalEvents.emplace_back( - [&](IEventHandle &) -> bool { - return readSets.size() >= 2; - }); - runtime.DispatchEvents(options); - } - UNIT_ASSERT_VALUES_EQUAL(readSets.size(), 2u); - - // Select keys 1 and 3, we expect this immediate tx to succeed - // Note that key 3 is not written yet, but we pretend immediate tx - // executes before that waiting transaction (no key 3 yet). - { - auto sender3 = runtime.AllocateEdgeActor(); + + // Wait until we captured both readsets again + if (readSets.size() < 2) { + TDispatchOptions options; + options.FinalEvents.emplace_back( + [&](IEventHandle &) -> bool { + return readSets.size() >= 2; + }); + runtime.DispatchEvents(options); + } + UNIT_ASSERT_VALUES_EQUAL(readSets.size(), 2u); + + // Select keys 1 and 3, we expect this immediate tx to succeed + // Note that key 3 is not written yet, but we pretend immediate tx + // executes before that waiting transaction (no key 3 yet). + { + auto sender3 = runtime.AllocateEdgeActor(); auto ev = ExecRequest(runtime, sender3, MakeSimpleRequest(Q_( "SELECT key, value FROM `/Root/table-1` WHERE key = 1 OR key = 3;"))); - auto& response = ev->Get()->Record.GetRef(); - UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); - UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults().size(), 1u); - TString expected = "Struct { List { Struct { Optional { Uint32: 1 } } Struct { Optional { Uint32: 1 } } } } Struct { Bool: false }"; - UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults()[0].GetValue().ShortDebugString(), expected); - } - - // Upsert key 1, we expect this immediate tx to be executed successfully because it lies to the right on the global timeline - { - auto sender4 = runtime.AllocateEdgeActor(); + auto& response = ev->Get()->Record.GetRef(); + UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); + UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults().size(), 1u); + TString expected = "Struct { List { Struct { Optional { Uint32: 1 } } Struct { Optional { Uint32: 1 } } } } Struct { Bool: false }"; + UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults()[0].GetValue().ShortDebugString(), expected); + } + + // Upsert key 1, we expect this immediate tx to be executed successfully because it lies to the right on the global timeline + { + auto sender4 = runtime.AllocateEdgeActor(); auto req = MakeSimpleRequest(Q_("UPSERT INTO `/Root/table-1` (key, value) VALUES (1, 3);")); - req->Record.MutableRequest()->SetCancelAfterMs(1000); - req->Record.MutableRequest()->SetTimeoutMs(1000); - auto ev = ExecRequest(runtime, sender4, std::move(req)); - auto& response = ev->Get()->Record.GetRef(); - UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); - } - - // Upsert key 5, this immediate tx should be executed successfully too - { - auto sender4 = runtime.AllocateEdgeActor(); + req->Record.MutableRequest()->SetCancelAfterMs(1000); + req->Record.MutableRequest()->SetTimeoutMs(1000); + auto ev = ExecRequest(runtime, sender4, std::move(req)); + auto& response = ev->Get()->Record.GetRef(); + UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); + } + + // Upsert key 5, this immediate tx should be executed successfully too + { + auto sender4 = runtime.AllocateEdgeActor(); auto req = MakeSimpleRequest(Q_("UPSERT INTO `/Root/table-1` (key, value) VALUES (5, 3);")); - req->Record.MutableRequest()->SetCancelAfterMs(1000); - req->Record.MutableRequest()->SetTimeoutMs(1000); - auto ev = ExecRequest(runtime, sender4, std::move(req)); - auto& response = ev->Get()->Record.GetRef(); - UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); - } - - // Release readsets allowing tx to progress - runtime.SetObserverFunc(prevObserverFunc); - for (auto& ev : readSets) { - runtime.Send(ev.Release(), 0, /* viaActorSystem */ true); - } - - // Select key 3, we expect a success - { - auto sender9 = runtime.AllocateEdgeActor(); + req->Record.MutableRequest()->SetCancelAfterMs(1000); + req->Record.MutableRequest()->SetTimeoutMs(1000); + auto ev = ExecRequest(runtime, sender4, std::move(req)); + auto& response = ev->Get()->Record.GetRef(); + UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); + } + + // Release readsets allowing tx to progress + runtime.SetObserverFunc(prevObserverFunc); + for (auto& ev : readSets) { + runtime.Send(ev.Release(), 0, /* viaActorSystem */ true); + } + + // Select key 3, we expect a success + { + auto sender9 = runtime.AllocateEdgeActor(); auto ev = ExecRequest(runtime, sender9, MakeSimpleRequest(Q_( "SELECT key, value FROM `/Root/table-1` WHERE key = 3;"))); - auto& response = ev->Get()->Record.GetRef(); - UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); - UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults().size(), 1u); - TString expected = "Struct { List { Struct { Optional { Uint32: 3 } } Struct { Optional { Uint32: 2 } } } } Struct { Bool: false }"; - UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults()[0].GetValue().ShortDebugString(), expected); - } -} - + auto& response = ev->Get()->Record.GetRef(); + UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); + UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults().size(), 1u); + TString expected = "Struct { List { Struct { Optional { Uint32: 3 } } Struct { Optional { Uint32: 2 } } } } Struct { Bool: false }"; + UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults()[0].GetValue().ShortDebugString(), expected); + } +} + Y_UNIT_TEST_QUAD(TestOutOfOrderRestartLocksReorderedWithoutBarrier, UseMvcc, UseNewEngine) { - TPortManager pm; - TServerSettings serverSettings(pm.GetPort(2134)); - serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) - .SetUseRealThreads(false); - - Tests::TServer::TPtr server = new TServer(serverSettings); - auto &runtime = *server->GetRuntime(); - auto sender = runtime.AllocateEdgeActor(); - - // This test requires barrier to be disabled - runtime.GetAppData().FeatureFlags.SetDisableDataShardBarrier(true); - - runtime.SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_TRACE); + TPortManager pm; + TServerSettings serverSettings(pm.GetPort(2134)); + serverSettings.SetDomainName("Root") + .SetEnableMvcc(WithMvcc) + .SetUseRealThreads(false); + + Tests::TServer::TPtr server = new TServer(serverSettings); + auto &runtime = *server->GetRuntime(); + auto sender = runtime.AllocateEdgeActor(); + + // This test requires barrier to be disabled + runtime.GetAppData().FeatureFlags.SetDisableDataShardBarrier(true); + + runtime.SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_TRACE); runtime.SetLogPriority(UseNewEngine ? NKikimrServices::KQP_EXECUTER : NKikimrServices::TX_PROXY, NLog::PRI_DEBUG); - - InitRoot(server, sender); - - CreateShardedTable(server, sender, "/Root", "table-1", 1); - CreateShardedTable(server, sender, "/Root", "table-2", 1); - auto table1shards = GetTableShards(server, sender, "/Root/table-1"); - auto table2shards = GetTableShards(server, sender, "/Root/table-2"); - + + InitRoot(server, sender); + + CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-2", 1); + auto table1shards = GetTableShards(server, sender, "/Root/table-1"); + auto table2shards = GetTableShards(server, sender, "/Root/table-2"); + ExecSQL(server, sender, Q_("UPSERT INTO `/Root/table-1` (key, value) VALUES (1, 1);")); ExecSQL(server, sender, Q_("UPSERT INTO `/Root/table-2` (key, value) VALUES (2, 1);")); - - TString sessionId = CreateSession(runtime, sender); - - TString txId; - { - auto sender1 = runtime.AllocateEdgeActor(); + + TString sessionId = CreateSession(runtime, sender); + + TString txId; + { + auto sender1 = runtime.AllocateEdgeActor(); auto ev = ExecRequest(runtime, sender1, MakeBeginRequest(sessionId, Q_(R"( SELECT * FROM `/Root/table-1` WHERE key = 1 UNION ALL @@ -2334,7 +2334,7 @@ Y_UNIT_TEST_QUAD(TestOutOfOrderNoBarrierRestartImmediateLongTail, UseMvcc, UseNe TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -2349,8 +2349,8 @@ Y_UNIT_TEST_QUAD(TestOutOfOrderNoBarrierRestartImmediateLongTail, UseMvcc, UseNe InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1); - CreateShardedTable(server, sender, "/Root", "table-2", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-2", 1); auto table1shards = GetTableShards(server, sender, "/Root/table-1"); auto table2shards = GetTableShards(server, sender, "/Root/table-2"); @@ -2550,7 +2550,7 @@ Y_UNIT_TEST_QUAD(TestCopyTableNoDeadlock, UseMvcc, UseNewEngine) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -2562,8 +2562,8 @@ Y_UNIT_TEST_QUAD(TestCopyTableNoDeadlock, UseMvcc, UseNewEngine) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1); - CreateShardedTable(server, sender, "/Root", "table-2", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-2", 1); ExecSQL(server, sender, Q_("UPSERT INTO `/Root/table-1` (key, value) VALUES (1, 1);")); ExecSQL(server, sender, Q_("UPSERT INTO `/Root/table-2` (key, value) VALUES (2, 1);")); @@ -3427,7 +3427,7 @@ Y_UNIT_TEST_QUAD(TestReadTableSingleShardImmediate, WithMvcc, UseNewEngine) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -3440,7 +3440,7 @@ Y_UNIT_TEST_QUAD(TestReadTableSingleShardImmediate, WithMvcc, UseNewEngine) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); ExecSQL(server, sender, Q_("UPSERT INTO `/Root/table-1` (key, value) VALUES (1, 1);")); @@ -3639,11 +3639,11 @@ Y_UNIT_TEST_NEW_ENGINE(TestImmediateQueueThenSplit) { << failures << " failures"); } -void TestLateKqpQueryAfterColumnDrop(bool dataQuery, const TString& query, bool enableMvcc = false) { +void TestLateKqpQueryAfterColumnDrop(bool dataQuery, const TString& query, bool enableMvcc = false) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(enableMvcc) + .SetEnableMvcc(enableMvcc) .SetUseRealThreads(false); if (dataQuery) { @@ -3751,144 +3751,144 @@ void TestLateKqpQueryAfterColumnDrop(bool dataQuery, const TString& query, bool UNIT_ASSERT_STRINGS_EQUAL(issue.message(), "Table \'/Root/table-1\' scheme changed."); } -Y_UNIT_TEST_WITH_MVCC(TestLateKqpScanAfterColumnDrop) { - TestLateKqpQueryAfterColumnDrop(false, "SELECT SUM(value2) FROM `/Root/table-1`", WithMvcc); +Y_UNIT_TEST_WITH_MVCC(TestLateKqpScanAfterColumnDrop) { + TestLateKqpQueryAfterColumnDrop(false, "SELECT SUM(value2) FROM `/Root/table-1`", WithMvcc); } -Y_UNIT_TEST_WITH_MVCC(TestLateKqpDataReadAfterColumnDrop) { +Y_UNIT_TEST_WITH_MVCC(TestLateKqpDataReadAfterColumnDrop) { TestLateKqpQueryAfterColumnDrop(true, R"( PRAGMA kikimr.UseNewEngine = "true"; SELECT SUM(value2) FROM `/Root/table-1` - )", WithMvcc); + )", WithMvcc); } Y_UNIT_TEST_NEW_ENGINE(MvccTestSnapshotRead) { - TPortManager pm; - TServerSettings serverSettings(pm.GetPort(2134)); - serverSettings.SetDomainName("Root") - .SetEnableMvcc(true) - .SetUseRealThreads(false); - - Tests::TServer::TPtr server = new TServer(serverSettings); - auto &runtime = *server->GetRuntime(); - auto sender = runtime.AllocateEdgeActor(); - - runtime.SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_TRACE); + TPortManager pm; + TServerSettings serverSettings(pm.GetPort(2134)); + serverSettings.SetDomainName("Root") + .SetEnableMvcc(true) + .SetUseRealThreads(false); + + Tests::TServer::TPtr server = new TServer(serverSettings); + auto &runtime = *server->GetRuntime(); + auto sender = runtime.AllocateEdgeActor(); + + runtime.SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_TRACE); runtime.SetLogPriority(UseNewEngine ? NKikimrServices::KQP_EXECUTER : NKikimrServices::TX_PROXY, NLog::PRI_DEBUG); - - InitRoot(server, sender); - - CreateShardedTable(server, sender, "/Root", "table-1", 1); - + + InitRoot(server, sender); + + CreateShardedTable(server, sender, "/Root", "table-1", 1); + ExecSQL(server, sender, Q_("UPSERT INTO `/Root/table-1` (key, value) VALUES (0, 0), (1, 1), (2, 2), (3, 3);")); - - auto waitFor = [&](const auto& condition, const TString& description) { - if (!condition()) { - Cerr << "... waiting for " << description << Endl; - TDispatchOptions options; - options.CustomFinalCondition = [&]() { - return condition(); - }; - runtime.DispatchEvents(options); - UNIT_ASSERT_C(condition(), "... failed to wait for " << description); - } - }; - - bool captureTimecast = false; - bool rewritten = false; - bool rescheduled = false; - - TRowVersion snapshot = TRowVersion::Min(); - ui64 lastStep = 0; - - auto captureEvents = [&](TTestActorRuntimeBase&, TAutoPtr<IEventHandle> &event) -> auto { - switch (event->GetTypeRewrite()) { - case TEvMediatorTimecast::EvUpdate: { - if (captureTimecast) { - auto update = event->Get<TEvMediatorTimecast::TEvUpdate>(); - lastStep = update->Record.GetTimeBarrier(); - Cerr << "---- dropped EvUpdate ----" << Endl; - return TTestActorRuntime::EEventAction::DROP; - } - break; - } - case TEvDataShard::EvProposeTransaction: { - if (!snapshot) - break; - auto &propose = event->Get<TEvDataShard::TEvProposeTransaction>()->Record; - if (!propose.HasMvccSnapshot()) { - auto mutableSnapshot = propose.MutableMvccSnapshot(); - mutableSnapshot->SetStep(snapshot.Step); - mutableSnapshot->SetTxId(snapshot.TxId); - Cerr << "---- rewrite EvProposeTransaction ----" << Endl; - rewritten = true; - } else if (propose.HasMvccSnapshot() && propose.GetMvccSnapshot().GetStep() == snapshot.Step && - propose.GetMvccSnapshot().GetTxId() == snapshot.TxId) { - Cerr << "---- EvProposeTransaction rescheduled----" << Endl; - rescheduled = true; - } - break; - } - } - return TTestActorRuntime::EEventAction::PROCESS; - }; - auto prevObserverFunc = runtime.SetObserverFunc(captureEvents); - - // check transaction waits for proper plan step - captureTimecast = true; - - waitFor([&]{ return lastStep != 0; }, "intercepted TEvUpdate"); - - // future snapshot - snapshot = TRowVersion(lastStep + 1000, Max<ui64>()); - + + auto waitFor = [&](const auto& condition, const TString& description) { + if (!condition()) { + Cerr << "... waiting for " << description << Endl; + TDispatchOptions options; + options.CustomFinalCondition = [&]() { + return condition(); + }; + runtime.DispatchEvents(options); + UNIT_ASSERT_C(condition(), "... failed to wait for " << description); + } + }; + + bool captureTimecast = false; + bool rewritten = false; + bool rescheduled = false; + + TRowVersion snapshot = TRowVersion::Min(); + ui64 lastStep = 0; + + auto captureEvents = [&](TTestActorRuntimeBase&, TAutoPtr<IEventHandle> &event) -> auto { + switch (event->GetTypeRewrite()) { + case TEvMediatorTimecast::EvUpdate: { + if (captureTimecast) { + auto update = event->Get<TEvMediatorTimecast::TEvUpdate>(); + lastStep = update->Record.GetTimeBarrier(); + Cerr << "---- dropped EvUpdate ----" << Endl; + return TTestActorRuntime::EEventAction::DROP; + } + break; + } + case TEvDataShard::EvProposeTransaction: { + if (!snapshot) + break; + auto &propose = event->Get<TEvDataShard::TEvProposeTransaction>()->Record; + if (!propose.HasMvccSnapshot()) { + auto mutableSnapshot = propose.MutableMvccSnapshot(); + mutableSnapshot->SetStep(snapshot.Step); + mutableSnapshot->SetTxId(snapshot.TxId); + Cerr << "---- rewrite EvProposeTransaction ----" << Endl; + rewritten = true; + } else if (propose.HasMvccSnapshot() && propose.GetMvccSnapshot().GetStep() == snapshot.Step && + propose.GetMvccSnapshot().GetTxId() == snapshot.TxId) { + Cerr << "---- EvProposeTransaction rescheduled----" << Endl; + rescheduled = true; + } + break; + } + } + return TTestActorRuntime::EEventAction::PROCESS; + }; + auto prevObserverFunc = runtime.SetObserverFunc(captureEvents); + + // check transaction waits for proper plan step + captureTimecast = true; + + waitFor([&]{ return lastStep != 0; }, "intercepted TEvUpdate"); + + // future snapshot + snapshot = TRowVersion(lastStep + 1000, Max<ui64>()); + SendRequest(runtime, sender, MakeSimpleRequest(Q_("SELECT key, value FROM `/Root/table-1` WHERE key = 2 ORDER BY key"))); - - waitFor([&]{ return rewritten; }, "EvProposeTransaction rewritten"); - - captureTimecast = false; - - waitFor([&]{ return rescheduled; }, "EvProposeTransaction rescheduled"); - - { - auto ev = runtime.GrabEdgeEventRethrow<NKqp::TEvKqp::TEvQueryResponse>(sender); - auto& response = ev->Get()->Record.GetRef(); - UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); - UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults().size(), 1u); - TString expected = "Struct { List { Struct { Optional { Uint32: 2 } } Struct { Optional { Uint32: 2 } } } } Struct { Bool: false }"; - UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults()[0].GetValue().ShortDebugString(), expected); - } - - auto tmp = std::exchange(snapshot, TRowVersion::Min()); - - // check transaction reads from snapshot - + + waitFor([&]{ return rewritten; }, "EvProposeTransaction rewritten"); + + captureTimecast = false; + + waitFor([&]{ return rescheduled; }, "EvProposeTransaction rescheduled"); + + { + auto ev = runtime.GrabEdgeEventRethrow<NKqp::TEvKqp::TEvQueryResponse>(sender); + auto& response = ev->Get()->Record.GetRef(); + UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); + UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults().size(), 1u); + TString expected = "Struct { List { Struct { Optional { Uint32: 2 } } Struct { Optional { Uint32: 2 } } } } Struct { Bool: false }"; + UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults()[0].GetValue().ShortDebugString(), expected); + } + + auto tmp = std::exchange(snapshot, TRowVersion::Min()); + + // check transaction reads from snapshot + ExecSQL(server, sender, Q_("UPSERT INTO `/Root/table-1` (key, value) VALUES (2, 10);")); - - { + + { auto ev = ExecRequest(runtime, sender, MakeSimpleRequest(Q_("SELECT key, value FROM `/Root/table-1` WHERE key = 2 ORDER BY key"))); - auto& response = ev->Get()->Record.GetRef(); - UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); - UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults().size(), 1u); - TString expected = "Struct { List { Struct { Optional { Uint32: 2 } } Struct { Optional { Uint32: 10 } } } } Struct { Bool: false }"; - UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults()[0].GetValue().ShortDebugString(), expected); - } - - snapshot = tmp; - rescheduled = false; - - { + auto& response = ev->Get()->Record.GetRef(); + UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); + UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults().size(), 1u); + TString expected = "Struct { List { Struct { Optional { Uint32: 2 } } Struct { Optional { Uint32: 10 } } } } Struct { Bool: false }"; + UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults()[0].GetValue().ShortDebugString(), expected); + } + + snapshot = tmp; + rescheduled = false; + + { auto ev = ExecRequest(runtime, sender, MakeSimpleRequest(Q_("SELECT key, value FROM `/Root/table-1` WHERE key = 2 ORDER BY key"))); - auto& response = ev->Get()->Record.GetRef(); - UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); - UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults().size(), 1u); - TString expected = "Struct { List { Struct { Optional { Uint32: 2 } } Struct { Optional { Uint32: 2 } } } } Struct { Bool: false }"; - UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults()[0].GetValue().ShortDebugString(), expected); - } - - UNIT_ASSERT(!rescheduled); -} - + auto& response = ev->Get()->Record.GetRef(); + UNIT_ASSERT_VALUES_EQUAL(response.GetYdbStatus(), Ydb::StatusIds::SUCCESS); + UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults().size(), 1u); + TString expected = "Struct { List { Struct { Optional { Uint32: 2 } } Struct { Optional { Uint32: 2 } } } } Struct { Bool: false }"; + UNIT_ASSERT_VALUES_EQUAL(response.GetResponse().GetResults()[0].GetValue().ShortDebugString(), expected); + } + + UNIT_ASSERT(!rescheduled); +} + Y_UNIT_TEST_NEW_ENGINE(TestSecondaryClearanceAfterShardRestartRace) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); @@ -4097,7 +4097,7 @@ Y_UNIT_TEST_QUAD(TestShardRestartPlannedCommitShouldSucceed, UseMvcc, UseNewEngi TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -4114,8 +4114,8 @@ Y_UNIT_TEST_QUAD(TestShardRestartPlannedCommitShouldSucceed, UseMvcc, UseNewEngi InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1); - CreateShardedTable(server, sender, "/Root", "table-2", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-2", 1); auto table1shards = GetTableShards(server, sender, "/Root/table-1"); ExecSQL(server, sender, Q_("UPSERT INTO `/Root/table-1` (key, value) VALUES (1, 1)")); diff --git a/ydb/core/tx/datashard/datashard_ut_read_table.cpp b/ydb/core/tx/datashard/datashard_ut_read_table.cpp index c1650572e7..c11e21f2f2 100644 --- a/ydb/core/tx/datashard/datashard_ut_read_table.cpp +++ b/ydb/core/tx/datashard/datashard_ut_read_table.cpp @@ -11,11 +11,11 @@ using namespace NDataShardReadTableTest; Y_UNIT_TEST_SUITE(DataShardReadTableSnapshots) { - Y_UNIT_TEST_WITH_MVCC(ReadTableSnapshot) { + Y_UNIT_TEST_WITH_MVCC(ReadTableSnapshot) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -28,7 +28,7 @@ Y_UNIT_TEST_SUITE(DataShardReadTableSnapshots) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); auto shards = GetTableShards(server, sender, "/Root/table-1"); ExecSQL(server, sender, "UPSERT INTO [/Root/table-1] (key, value) VALUES (1, 1), (2, 2), (3, 3);"); @@ -55,11 +55,11 @@ Y_UNIT_TEST_SUITE(DataShardReadTableSnapshots) { "key = 3, value = 3\n"); } - Y_UNIT_TEST_WITH_MVCC(ReadTableSplitAfter) { + Y_UNIT_TEST_WITH_MVCC(ReadTableSplitAfter) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -72,7 +72,7 @@ Y_UNIT_TEST_SUITE(DataShardReadTableSnapshots) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); auto shards = GetTableShards(server, sender, "/Root/table-1"); ExecSQL(server, sender, "UPSERT INTO [/Root/table-1] (key, value) VALUES (1, 11), (2, 22), (3, 33), (4, 44);"); @@ -106,11 +106,11 @@ Y_UNIT_TEST_SUITE(DataShardReadTableSnapshots) { "key = 4, value = 44\n"); } - Y_UNIT_TEST_WITH_MVCC(ReadTableSplitBefore) { + Y_UNIT_TEST_WITH_MVCC(ReadTableSplitBefore) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -123,7 +123,7 @@ Y_UNIT_TEST_SUITE(DataShardReadTableSnapshots) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); auto shards = GetTableShards(server, sender, "/Root/table-1"); ExecSQL(server, sender, "UPSERT INTO [/Root/table-1] (key, value) VALUES (1, 11), (2, 22), (3, 33), (4, 44);"); @@ -159,11 +159,11 @@ Y_UNIT_TEST_SUITE(DataShardReadTableSnapshots) { "key = 4, value = 44\n"); } - Y_UNIT_TEST_WITH_MVCC(ReadTableSplitFinished) { + Y_UNIT_TEST_WITH_MVCC(ReadTableSplitFinished) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -179,7 +179,7 @@ Y_UNIT_TEST_SUITE(DataShardReadTableSnapshots) { // Split would fail otherwise :( SetSplitMergePartCountLimit(server->GetRuntime(), -1); - CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); auto shards = GetTableShards(server, sender, "/Root/table-1"); UNIT_ASSERT_VALUES_EQUAL(shards.size(), 1u); @@ -242,11 +242,11 @@ Y_UNIT_TEST_SUITE(DataShardReadTableSnapshots) { "key = 6, value = 66\n"); } - Y_UNIT_TEST_WITH_MVCC(ReadTableDropColumn) { + Y_UNIT_TEST_WITH_MVCC(ReadTableDropColumn) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -262,7 +262,7 @@ Y_UNIT_TEST_SUITE(DataShardReadTableSnapshots) { // Split would fail otherwise :( SetSplitMergePartCountLimit(server->GetRuntime(), -1); - CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); auto shards = GetTableShards(server, sender, "/Root/table-1"); UNIT_ASSERT_VALUES_EQUAL(shards.size(), 1u); @@ -296,11 +296,11 @@ Y_UNIT_TEST_SUITE(DataShardReadTableSnapshots) { "ERROR: ResolveError\n"); } - Y_UNIT_TEST_WITH_MVCC(ReadTableDropColumnLatePropose) { + Y_UNIT_TEST_WITH_MVCC(ReadTableDropColumnLatePropose) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -316,7 +316,7 @@ Y_UNIT_TEST_SUITE(DataShardReadTableSnapshots) { // Split would fail otherwise :( SetSplitMergePartCountLimit(server->GetRuntime(), -1); - CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); auto shards = GetTableShards(server, sender, "/Root/table-1"); UNIT_ASSERT_VALUES_EQUAL(shards.size(), 1u); @@ -389,11 +389,11 @@ Y_UNIT_TEST_SUITE(DataShardReadTableSnapshots) { "ERROR: ResolveError\n"); } - Y_UNIT_TEST_WITH_MVCC(ReadTableMaxRows) { + Y_UNIT_TEST_WITH_MVCC(ReadTableMaxRows) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -409,7 +409,7 @@ Y_UNIT_TEST_SUITE(DataShardReadTableSnapshots) { // Split would fail otherwise :( SetSplitMergePartCountLimit(server->GetRuntime(), -1); - CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); auto shards = GetTableShards(server, sender, "/Root/table-1"); UNIT_ASSERT_VALUES_EQUAL(shards.size(), 1u); diff --git a/ydb/core/tx/datashard/datashard_ut_snapshot.cpp b/ydb/core/tx/datashard/datashard_ut_snapshot.cpp index 43eddaf1dc..ca3bc867fa 100644 --- a/ydb/core/tx/datashard/datashard_ut_snapshot.cpp +++ b/ydb/core/tx/datashard/datashard_ut_snapshot.cpp @@ -152,11 +152,11 @@ namespace { Y_UNIT_TEST_SUITE(DataShardSnapshots) { - Y_UNIT_TEST_WITH_MVCC(VolatileSnapshotSplit) { + Y_UNIT_TEST_WITH_MVCC(VolatileSnapshotSplit) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); RegisterFormats(serverSettings); @@ -169,8 +169,8 @@ Y_UNIT_TEST_SUITE(DataShardSnapshots) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1); - CreateShardedTable(server, sender, "/Root", "table-2", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-2", 1); ExecSQL(server, sender, "UPSERT INTO [/Root/table-1] (key, value) VALUES (1, 1), (2, 2), (3, 3);"); ExecSQL(server, sender, "UPSERT INTO [/Root/table-2] (key, value) VALUES (10, 10), (20, 20), (30, 30);"); @@ -209,11 +209,11 @@ Y_UNIT_TEST_SUITE(DataShardSnapshots) { UNIT_ASSERT_VALUES_EQUAL(table1headAfterSplit, "key = 1, value = 11\nkey = 2, value = 22\nkey = 3, value = 33\nkey = 4, value = 44\n"); } - Y_UNIT_TEST_WITH_MVCC(VolatileSnapshotMerge) { + Y_UNIT_TEST_WITH_MVCC(VolatileSnapshotMerge) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); RegisterFormats(serverSettings); @@ -226,8 +226,8 @@ Y_UNIT_TEST_SUITE(DataShardSnapshots) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1); - CreateShardedTable(server, sender, "/Root", "table-2", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-2", 1); // Split/merge would fail otherwise :( SetSplitMergePartCountLimit(server->GetRuntime(), -1); @@ -276,11 +276,11 @@ Y_UNIT_TEST_SUITE(DataShardSnapshots) { UNIT_ASSERT_VALUES_EQUAL(table1snapshotAfterMerge, "key = 1, value = 1\nkey = 2, value = 2\nkey = 3, value = 3\n"); } - Y_UNIT_TEST_WITH_MVCC(VolatileSnapshotAndLocalMKQLUpdate) { + Y_UNIT_TEST_WITH_MVCC(VolatileSnapshotAndLocalMKQLUpdate) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); RegisterFormats(serverSettings); @@ -293,8 +293,8 @@ Y_UNIT_TEST_SUITE(DataShardSnapshots) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1); - CreateShardedTable(server, sender, "/Root", "table-2", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-2", 1); ExecSQL(server, sender, "UPSERT INTO [/Root/table-1] (key, value) VALUES (1, 1), (2, 2), (3, 3);"); ExecSQL(server, sender, "UPSERT INTO [/Root/table-2] (key, value) VALUES (10, 10), (20, 20), (30, 30);"); @@ -340,11 +340,11 @@ Y_UNIT_TEST_SUITE(DataShardSnapshots) { "key = 3, value = 3\n"); } - Y_UNIT_TEST_WITH_MVCC(VolatileSnapshotReadTable) { + Y_UNIT_TEST_WITH_MVCC(VolatileSnapshotReadTable) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -357,8 +357,8 @@ Y_UNIT_TEST_SUITE(DataShardSnapshots) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 2); - CreateShardedTable(server, sender, "/Root", "table-2", 2); + CreateShardedTable(server, sender, "/Root", "table-1", 2); + CreateShardedTable(server, sender, "/Root", "table-2", 2); ExecSQL(server, sender, "UPSERT INTO [/Root/table-1] (key, value) VALUES (1, 1), (2, 2), (3, 3);"); ExecSQL(server, sender, "UPSERT INTO [/Root/table-2] (key, value) VALUES (10, 10), (20, 20), (30, 30);"); @@ -427,11 +427,11 @@ Y_UNIT_TEST_SUITE(DataShardSnapshots) { UNIT_ASSERT_VALUES_EQUAL(table1snapshotdiscarded, "ERROR: WrongRequest\n"); } - Y_UNIT_TEST_WITH_MVCC(VolatileSnapshotRefreshDiscard) { + Y_UNIT_TEST_WITH_MVCC(VolatileSnapshotRefreshDiscard) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -444,8 +444,8 @@ Y_UNIT_TEST_SUITE(DataShardSnapshots) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 2); - CreateShardedTable(server, sender, "/Root", "table-2", 2); + CreateShardedTable(server, sender, "/Root", "table-1", 2); + CreateShardedTable(server, sender, "/Root", "table-2", 2); ExecSQL(server, sender, "UPSERT INTO [/Root/table-1] (key, value) VALUES (1, 1), (2, 2), (3, 3);"); ExecSQL(server, sender, "UPSERT INTO [/Root/table-2] (key, value) VALUES (10, 10), (20, 20), (30, 30);"); @@ -478,11 +478,11 @@ Y_UNIT_TEST_SUITE(DataShardSnapshots) { UNIT_ASSERT(!DiscardVolatileSnapshot(server, { "/Root/table-1", "/Root/table-2" }, snapshot)); } - Y_UNIT_TEST_WITH_MVCC(VolatileSnapshotTimeout) { + Y_UNIT_TEST_WITH_MVCC(VolatileSnapshotTimeout) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false) .SetDomainPlanResolution(1000); @@ -496,8 +496,8 @@ Y_UNIT_TEST_SUITE(DataShardSnapshots) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 2); - CreateShardedTable(server, sender, "/Root", "table-2", 2); + CreateShardedTable(server, sender, "/Root", "table-1", 2); + CreateShardedTable(server, sender, "/Root", "table-2", 2); ExecSQL(server, sender, "UPSERT INTO [/Root/table-1] (key, value) VALUES (1, 1), (2, 2), (3, 3);"); ExecSQL(server, sender, "UPSERT INTO [/Root/table-2] (key, value) VALUES (10, 10), (20, 20), (30, 30);"); @@ -521,11 +521,11 @@ Y_UNIT_TEST_SUITE(DataShardSnapshots) { "ERROR: WrongRequest\n"); } - Y_UNIT_TEST_WITH_MVCC(VolatileSnapshotTimeoutRefresh) { + Y_UNIT_TEST_WITH_MVCC(VolatileSnapshotTimeoutRefresh) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false) .SetDomainPlanResolution(1000); @@ -539,8 +539,8 @@ Y_UNIT_TEST_SUITE(DataShardSnapshots) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 2); - CreateShardedTable(server, sender, "/Root", "table-2", 2); + CreateShardedTable(server, sender, "/Root", "table-1", 2); + CreateShardedTable(server, sender, "/Root", "table-2", 2); const auto shards1 = GetTableShards(server, sender, "/Root/table-1"); @@ -593,11 +593,11 @@ Y_UNIT_TEST_SUITE(DataShardSnapshots) { UNIT_ASSERT_VALUES_EQUAL(GetSnapshotCount(runtime, shards1[0]), 1u); } - Y_UNIT_TEST_WITH_MVCC(VolatileSnapshotCleanupOnReboot) { + Y_UNIT_TEST_WITH_MVCC(VolatileSnapshotCleanupOnReboot) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false) .SetDomainPlanResolution(1000); @@ -611,8 +611,8 @@ Y_UNIT_TEST_SUITE(DataShardSnapshots) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1); - CreateShardedTable(server, sender, "/Root", "table-2", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-2", 1); const auto shards1 = GetTableShards(server, sender, "/Root/table-1"); @@ -657,11 +657,11 @@ Y_UNIT_TEST_SUITE(DataShardSnapshots) { UNIT_ASSERT_VALUES_EQUAL(GetSnapshotCount(runtime, shards1[0]), 0u); } - Y_UNIT_TEST_WITH_MVCC(VolatileSnapshotCleanupOnFinish) { + Y_UNIT_TEST_WITH_MVCC(VolatileSnapshotCleanupOnFinish) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false) .SetDomainPlanResolution(1000); @@ -675,8 +675,8 @@ Y_UNIT_TEST_SUITE(DataShardSnapshots) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1); - CreateShardedTable(server, sender, "/Root", "table-2", 1); + CreateShardedTable(server, sender, "/Root", "table-1", 1); + CreateShardedTable(server, sender, "/Root", "table-2", 1); const auto shards1 = GetTableShards(server, sender, "/Root/table-1"); diff --git a/ydb/core/tx/datashard/datashard_ut_upload_rows.cpp b/ydb/core/tx/datashard/datashard_ut_upload_rows.cpp index 1176740b67..ab1c586d30 100644 --- a/ydb/core/tx/datashard/datashard_ut_upload_rows.cpp +++ b/ydb/core/tx/datashard/datashard_ut_upload_rows.cpp @@ -124,11 +124,11 @@ static void DoUploadRows( Y_UNIT_TEST_SUITE(TTxDataShardUploadRows) { - Y_UNIT_TEST_WITH_MVCC(TestUploadRows) { + Y_UNIT_TEST_WITH_MVCC(TestUploadRows) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -139,7 +139,7 @@ Y_UNIT_TEST_SUITE(TTxDataShardUploadRows) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 4, false); + CreateShardedTable(server, sender, "/Root", "table-1", 4, false); DoUploadTestRows(server, sender, "/Root/table-1", Ydb::Type::UINT32, Ydb::StatusIds::SUCCESS); @@ -148,11 +148,11 @@ Y_UNIT_TEST_SUITE(TTxDataShardUploadRows) { DoUploadTestRows(server, sender, "/Root/table-1", Ydb::Type::INT32, Ydb::StatusIds::SCHEME_ERROR); } - Y_UNIT_TEST_WITH_MVCC(TestUploadRowsDropColumnRace) { + Y_UNIT_TEST_WITH_MVCC(TestUploadRowsDropColumnRace) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -163,7 +163,7 @@ Y_UNIT_TEST_SUITE(TTxDataShardUploadRows) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 4, false); + CreateShardedTable(server, sender, "/Root", "table-1", 4, false); auto waitFor = [&](const auto& condition, const TString& description) { if (!condition()) { @@ -207,11 +207,11 @@ Y_UNIT_TEST_SUITE(TTxDataShardUploadRows) { DoWaitUploadTestRows(server, sender, Ydb::StatusIds::SCHEME_ERROR); } - Y_UNIT_TEST_WITH_MVCC(TestUploadRowsLocks) { + Y_UNIT_TEST_WITH_MVCC(TestUploadRowsLocks) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -222,7 +222,7 @@ Y_UNIT_TEST_SUITE(TTxDataShardUploadRows) { InitRoot(server, sender); - CreateShardedTable(server, sender, "/Root", "table-1", 1, false); + CreateShardedTable(server, sender, "/Root", "table-1", 1, false); // Upsert some initial values ExecSQL(server, sender, "UPSERT INTO [/Root/table-1] (key, value) VALUES (1, 100), (3, 300), (5, 500);"); @@ -260,11 +260,11 @@ Y_UNIT_TEST_SUITE(TTxDataShardUploadRows) { } } - Y_UNIT_TEST_WITH_MVCC(TestUploadShadowRows) { + Y_UNIT_TEST_WITH_MVCC(TestUploadShadowRows) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -278,7 +278,7 @@ Y_UNIT_TEST_SUITE(TTxDataShardUploadRows) { auto policy = NLocalDb::CreateDefaultUserTablePolicy(); policy->KeepEraseMarkers = true; - CreateShardedTable(server, sender, "/Root", "table-1", 1, false, policy.Get()); + CreateShardedTable(server, sender, "/Root", "table-1", 1, false, policy.Get()); // Apply some blind operations on an incomplete table ExecSQL(server, sender, "UPSERT INTO [/Root/table-1] (key, value) VALUES (1, 100), (3, 300), (5, 500);"); @@ -325,11 +325,11 @@ Y_UNIT_TEST_SUITE(TTxDataShardUploadRows) { "key = 10, value = (empty maybe)\n"); } - Y_UNIT_TEST_WITH_MVCC(TestUploadShadowRowsShadowData) { + Y_UNIT_TEST_WITH_MVCC(TestUploadShadowRowsShadowData) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -344,7 +344,7 @@ Y_UNIT_TEST_SUITE(TTxDataShardUploadRows) { auto policy = NLocalDb::CreateDefaultUserTablePolicy(); policy->KeepEraseMarkers = true; - CreateShardedTable(server, sender, "/Root", "table-1", 1, false, policy.Get(), EShadowDataMode::Enabled); + CreateShardedTable(server, sender, "/Root", "table-1", 1, false, policy.Get(), EShadowDataMode::Enabled); // Apply some blind operations on an incomplete table ExecSQL(server, sender, "UPSERT INTO [/Root/table-1] (key, value) VALUES (1, 100), (3, 300), (5, 500);"); @@ -406,11 +406,11 @@ Y_UNIT_TEST_SUITE(TTxDataShardUploadRows) { "key = 10, value = (empty maybe)\n"); } - Y_UNIT_TEST_WITH_MVCC(TestUploadShadowRowsShadowDataSplitThenPublish) { + Y_UNIT_TEST_WITH_MVCC(TestUploadShadowRowsShadowDataSplitThenPublish) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -425,7 +425,7 @@ Y_UNIT_TEST_SUITE(TTxDataShardUploadRows) { auto policy = NLocalDb::CreateDefaultUserTablePolicy(); policy->KeepEraseMarkers = true; - CreateShardedTable(server, sender, "/Root", "table-1", 1, false, policy.Get(), EShadowDataMode::Enabled); + CreateShardedTable(server, sender, "/Root", "table-1", 1, false, policy.Get(), EShadowDataMode::Enabled); // Apply some blind operations on an incomplete table ExecSQL(server, sender, "UPSERT INTO [/Root/table-1] (key, value) VALUES (1, 100), (3, 300), (5, 500);"); @@ -505,11 +505,11 @@ Y_UNIT_TEST_SUITE(TTxDataShardUploadRows) { "key = 10, value = (empty maybe)\n"); } - Y_UNIT_TEST_WITH_MVCC(TestUploadShadowRowsShadowDataPublishThenSplit) { + Y_UNIT_TEST_WITH_MVCC(TestUploadShadowRowsShadowDataPublishThenSplit) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -524,7 +524,7 @@ Y_UNIT_TEST_SUITE(TTxDataShardUploadRows) { auto policy = NLocalDb::CreateDefaultUserTablePolicy(); policy->KeepEraseMarkers = true; - CreateShardedTable(server, sender, "/Root", "table-1", 1, false, policy.Get(), EShadowDataMode::Enabled); + CreateShardedTable(server, sender, "/Root", "table-1", 1, false, policy.Get(), EShadowDataMode::Enabled); // Apply some blind operations on an incomplete table ExecSQL(server, sender, "UPSERT INTO [/Root/table-1] (key, value) VALUES (1, 100), (3, 300), (5, 500);"); @@ -607,11 +607,11 @@ Y_UNIT_TEST_SUITE(TTxDataShardUploadRows) { "key = 10, value = (empty maybe)\n"); } - Y_UNIT_TEST_WITH_MVCC(TestUploadShadowRowsShadowDataAlterSplitThenPublish) { + Y_UNIT_TEST_WITH_MVCC(TestUploadShadowRowsShadowDataAlterSplitThenPublish) { TPortManager pm; TServerSettings serverSettings(pm.GetPort(2134)); serverSettings.SetDomainName("Root") - .SetEnableMvcc(WithMvcc) + .SetEnableMvcc(WithMvcc) .SetUseRealThreads(false); Tests::TServer::TPtr server = new TServer(serverSettings); @@ -626,7 +626,7 @@ Y_UNIT_TEST_SUITE(TTxDataShardUploadRows) { auto policy = NLocalDb::CreateDefaultUserTablePolicy(); policy->KeepEraseMarkers = true; - CreateShardedTable(server, sender, "/Root", "table-1", 1, false, policy.Get(), EShadowDataMode::Enabled); + CreateShardedTable(server, sender, "/Root", "table-1", 1, false, policy.Get(), EShadowDataMode::Enabled); // Apply some blind operations on an incomplete table ExecSQL(server, sender, "UPSERT INTO [/Root/table-1] (key, value) VALUES (1, 100), (3, 300), (5, 500);"); diff --git a/ydb/core/tx/datashard/direct_tx_unit.cpp b/ydb/core/tx/datashard/direct_tx_unit.cpp index 01edb89799..1284b1f6ad 100644 --- a/ydb/core/tx/datashard/direct_tx_unit.cpp +++ b/ydb/core/tx/datashard/direct_tx_unit.cpp @@ -54,7 +54,7 @@ public: void Complete(TOperation::TPtr op, const TActorContext& ctx) override { Pipeline.RemoveCommittingOp(op); DataShard.EnqueueChangeRecords(std::move(op->ChangeRecords())); - + TDirectTransaction* tx = dynamic_cast<TDirectTransaction*>(op.Get()); Y_VERIFY(tx != nullptr); diff --git a/ydb/core/tx/datashard/execute_data_tx_unit.cpp b/ydb/core/tx/datashard/execute_data_tx_unit.cpp index d5cea52764..b32f635cc0 100644 --- a/ydb/core/tx/datashard/execute_data_tx_unit.cpp +++ b/ydb/core/tx/datashard/execute_data_tx_unit.cpp @@ -169,7 +169,7 @@ EExecutionStatus TExecuteDataTxUnit::Execute(TOperation::TPtr op, } void TExecuteDataTxUnit::ExecuteDataTx(TOperation::TPtr op, - TTransactionContext& txc, + TTransactionContext& txc, const TActorContext& ctx) { TActiveTransaction* tx = dynamic_cast<TActiveTransaction*>(op.Get()); IEngineFlat* engine = tx->GetDataTx()->GetEngine(); @@ -177,10 +177,10 @@ void TExecuteDataTxUnit::ExecuteDataTx(TOperation::TPtr op, DataShard.ReleaseCache(*tx); tx->GetDataTx()->ResetCounters(); - auto [readVersion, writeVersion] = DataShard.GetReadWriteVersions(tx); - tx->GetDataTx()->SetReadVersion(readVersion); - tx->GetDataTx()->SetWriteVersion(writeVersion); - + auto [readVersion, writeVersion] = DataShard.GetReadWriteVersions(tx); + tx->GetDataTx()->SetReadVersion(readVersion); + tx->GetDataTx()->SetWriteVersion(writeVersion); + // TODO: is it required to always prepare outgoing read sets? if (!engine->IsAfterOutgoingReadsetsExtracted()) { engine->PrepareOutgoingReadsets(); @@ -236,8 +236,8 @@ void TExecuteDataTxUnit::ExecuteDataTx(TOperation::TPtr op, result->SetExecutionError(ConvertErrCode(engineResult), engine->GetErrors()); } else { result->SetTxResult(engine->GetShardReply(DataShard.TabletID())); - - if (op->IsImmediate() && !op->IsReadOnly()) + + if (op->IsImmediate() && !op->IsReadOnly()) DataShard.PromoteCompleteEdge(writeVersion.Step, txc); if (auto changes = tx->GetDataTx()->GetCollectedChanges()) { @@ -264,12 +264,12 @@ void TExecuteDataTxUnit::ExecuteDataTx(TOperation::TPtr op, } if (counters.InvisibleRowSkips) { - DataShard.SysLocksTable().BreakSetLocks(op->LockTxId()); + DataShard.SysLocksTable().BreakSetLocks(op->LockTxId()); } - + AddLocksToResult(op); - - Pipeline.AddCommittingOp(op); + + Pipeline.AddCommittingOp(op); } void TExecuteDataTxUnit::AddLocksToResult(TOperation::TPtr op) { diff --git a/ydb/core/tx/datashard/execute_distributed_erase_tx_unit.cpp b/ydb/core/tx/datashard/execute_distributed_erase_tx_unit.cpp index 99451fa344..3c9a86e06b 100644 --- a/ydb/core/tx/datashard/execute_distributed_erase_tx_unit.cpp +++ b/ydb/core/tx/datashard/execute_distributed_erase_tx_unit.cpp @@ -83,7 +83,7 @@ public: BuildResult(op, NKikimrTxDataShard::TEvProposeTransactionResult::COMPLETE); DataShard.SysLocksTable().ApplyLocks(); - Pipeline.AddCommittingOp(op); + Pipeline.AddCommittingOp(op); return EExecutionStatus::ExecutedNoMoreRestarts; } diff --git a/ydb/core/tx/datashard/execute_kqp_data_tx_unit.cpp b/ydb/core/tx/datashard/execute_kqp_data_tx_unit.cpp index f42daefd53..70e7be3662 100644 --- a/ydb/core/tx/datashard/execute_kqp_data_tx_unit.cpp +++ b/ydb/core/tx/datashard/execute_kqp_data_tx_unit.cpp @@ -126,9 +126,9 @@ EExecutionStatus TExecuteKqpDataTxUnit::Execute(TOperation::TPtr op, TTransactio auto execCtx = DefaultKqpExecutionContext(); tasksRunner.Prepare(DefaultKqpDataReqMemoryLimits(), *execCtx); - auto [readVersion, writeVersion] = DataShard.GetReadWriteVersions(tx); - dataTx->SetReadVersion(readVersion); - dataTx->SetWriteVersion(writeVersion); + auto [readVersion, writeVersion] = DataShard.GetReadWriteVersions(tx); + dataTx->SetReadVersion(readVersion); + dataTx->SetWriteVersion(writeVersion); auto& computeCtx = tx->GetDataTx()->GetKqpComputeCtx(); @@ -154,7 +154,7 @@ EExecutionStatus TExecuteKqpDataTxUnit::Execute(TOperation::TPtr op, TTransactio if (op->IsImmediate() && !op->IsReadOnly()) { DataShard.PromoteCompleteEdge(writeVersion.Step, txc); } - + if (auto changes = dataTx->GetCollectedChanges()) { op->ChangeRecords().reserve(changes.size()); for (const auto& change : changes) { @@ -196,8 +196,8 @@ EExecutionStatus TExecuteKqpDataTxUnit::Execute(TOperation::TPtr op, TTransactio } } - Pipeline.AddCommittingOp(op); - + Pipeline.AddCommittingOp(op); + DataShard.IncCounter(COUNTER_WAIT_EXECUTE_LATENCY_MS, waitExecuteLatency.MilliSeconds()); DataShard.IncCounter(COUNTER_WAIT_TOTAL_LATENCY_MS, waitTotalLatency.MilliSeconds()); op->ResetCurrentTimer(); diff --git a/ydb/core/tx/datashard/execution_unit.cpp b/ydb/core/tx/datashard/execution_unit.cpp index df1b4c0d0c..9f6e13fa5c 100644 --- a/ydb/core/tx/datashard/execution_unit.cpp +++ b/ydb/core/tx/datashard/execution_unit.cpp @@ -181,20 +181,20 @@ bool TExecutionUnit::CheckRejectDataTx(TOperation::TPtr op, const TActorContext& return true; } - if (DataShard.GetMvccSwitchState() == TSwitchState::SWITCHING) { - TString err = TStringBuilder() - << "Wrong shard state: " << (TShardState)DataShard.GetState() - << " tablet id: " << DataShard.TabletID(); - BuildResult(op, NKikimrTxDataShard::TEvProposeTransactionResult::OVERLOADED) - ->AddError(NKikimrTxDataShard::TError::WRONG_SHARD_STATE, err); - - LOG_NOTICE_S(ctx, NKikimrServices::TX_DATASHARD, - "Tablet " << DataShard.TabletID() << " rejecting tx due to mvcc state change"); - - op->Abort(); - return true; - } - + if (DataShard.GetMvccSwitchState() == TSwitchState::SWITCHING) { + TString err = TStringBuilder() + << "Wrong shard state: " << (TShardState)DataShard.GetState() + << " tablet id: " << DataShard.TabletID(); + BuildResult(op, NKikimrTxDataShard::TEvProposeTransactionResult::OVERLOADED) + ->AddError(NKikimrTxDataShard::TError::WRONG_SHARD_STATE, err); + + LOG_NOTICE_S(ctx, NKikimrServices::TX_DATASHARD, + "Tablet " << DataShard.TabletID() << " rejecting tx due to mvcc state change"); + + op->Abort(); + return true; + } + if (!op->IsReadOnly() && DataShard.CheckChangesQueueOverflow()) { TString err = TStringBuilder() << "Can't execute at blocked shard: " << " tablet id: " << DataShard.TabletID(); @@ -231,11 +231,11 @@ bool TExecutionUnit::WillRejectDataTx(TOperation::TPtr op) const { return true; } - if (DataShard.GetMvccSwitchState() == TSwitchState::SWITCHING) - { - return true; - } - + if (DataShard.GetMvccSwitchState() == TSwitchState::SWITCHING) + { + return true; + } + if (!op->IsReadOnly() && DataShard.CheckChangesQueueOverflow()) { return true; } diff --git a/ydb/core/tx/datashard/finish_propose_unit.cpp b/ydb/core/tx/datashard/finish_propose_unit.cpp index 5a88393658..de0e9e4ad2 100644 --- a/ydb/core/tx/datashard/finish_propose_unit.cpp +++ b/ydb/core/tx/datashard/finish_propose_unit.cpp @@ -75,7 +75,7 @@ EExecutionStatus TFinishProposeUnit::Execute(TOperation::TPtr op, } } - if (!op->HasResultSentFlag() && (op->IsDirty() || !Pipeline.WaitCompletion(op))) + if (!op->HasResultSentFlag() && (op->IsDirty() || !Pipeline.WaitCompletion(op))) CompleteRequest(op, ctx); if (!DataShard.IsFollower()) @@ -113,7 +113,7 @@ void TFinishProposeUnit::Complete(TOperation::TPtr op, Pipeline.ForgetUnproposedTx(op->GetTxId()); if (op->IsImmediate()) { - Pipeline.RemoveCommittingOp(op); + Pipeline.RemoveCommittingOp(op); Pipeline.RemoveActiveOp(op); DataShard.EnqueueChangeRecords(std::move(op->ChangeRecords())); @@ -149,7 +149,7 @@ void TFinishProposeUnit::CompleteRequest(TOperation::TPtr op, DataShard.IncCounter(COUNTER_PREPARE_SUCCESS_COMPLETE_LATENCY, duration); } else { DataShard.CheckSplitCanStart(ctx); - DataShard.CheckMvccStateChangeCanStart(ctx); + DataShard.CheckMvccStateChangeCanStart(ctx); } if (op->HasNeedDiagnosticsFlag()) diff --git a/ydb/core/tx/datashard/operation.h b/ydb/core/tx/datashard/operation.h index 6d2338bfeb..0f4b713e91 100644 --- a/ydb/core/tx/datashard/operation.h +++ b/ydb/core/tx/datashard/operation.h @@ -149,7 +149,7 @@ public: EOperationKind GetKind() const { return Kind; } bool IsDataTx() const { return Kind == EOperationKind::DataTx; } - bool IsDirectTx() const { return Kind == EOperationKind::DirectTx; } + bool IsDirectTx() const { return Kind == EOperationKind::DirectTx; } bool IsSchemeTx() const { return Kind == EOperationKind::SchemeTx; } bool IsReadTable() const { return Kind == EOperationKind::ReadTable; } bool IsSnapshotTx() const { return Kind == EOperationKind::Snapshot; } @@ -331,9 +331,9 @@ public: bool HasStoredFlag() const { return HasFlag(TTxFlags::Stored); } void SetStoredFlag(bool val = true) { SetFlag(TTxFlags::Stored, val); } - bool HasWaitCompletionFlag() const { return HasFlag(TTxFlags::WaitCompletion); } - void SetWaitCompletionFlag(bool val = true) { SetFlag(TTxFlags::WaitCompletion, val); } - + bool HasWaitCompletionFlag() const { return HasFlag(TTxFlags::WaitCompletion); } + void SetWaitCompletionFlag(bool val = true) { SetFlag(TTxFlags::WaitCompletion, val); } + /////////////////////////////////// // OPERATION ID AND PLAN // /////////////////////////////////// @@ -373,7 +373,7 @@ public: MvccSnapshot = snapshot; MvccSnapshotRepeatable = isRepeatable; } - + /////////////////////////////////// // DEBUG AND MONITORING // /////////////////////////////////// diff --git a/ydb/core/tx/datashard/receive_snapshot_unit.cpp b/ydb/core/tx/datashard/receive_snapshot_unit.cpp index 70ac7f8965..26f92f65f4 100644 --- a/ydb/core/tx/datashard/receive_snapshot_unit.cpp +++ b/ydb/core/tx/datashard/receive_snapshot_unit.cpp @@ -50,9 +50,9 @@ EExecutionStatus TReceiveSnapshotUnit::Execute(TOperation::TPtr op, NIceDb::TNiceDb db(txc.DB); Y_VERIFY(schemeTx.HasCreateTable()); - + const bool mvcc = DataShard.IsMvccEnabled(); - + for (auto &pr : op->InReadSets()) { for (auto& rsdata : pr.second) { NKikimrTxDataShard::TSnapshotTransferReadSet rs; @@ -73,19 +73,19 @@ EExecutionStatus TReceiveSnapshotUnit::Execute(TOperation::TPtr op, snapBody = NBlockCodecs::Codec("lz4fast")->Decode(compressedBody); TRowVersion minVersion(rs.GetMinWriteVersionStep(), rs.GetMinWriteVersionTxId()); - if (DataShard.GetSnapshotManager().GetMinWriteVersion() < minVersion) - DataShard.GetSnapshotManager().SetMinWriteVersion(db, minVersion); - - if (mvcc) { - TRowVersion completeEdge(rs.GetMvccCompleteEdgeStep(), rs.GetMvccCompleteEdgeTxId()); - if (DataShard.GetSnapshotManager().GetCompleteEdge() < completeEdge) - DataShard.GetSnapshotManager().SetCompleteEdge(db, completeEdge); - TRowVersion incompleteEdge(rs.GetMvccIncompleteEdgeStep(), rs.GetMvccIncompleteEdgeTxId()); - if (DataShard.GetSnapshotManager().GetIncompleteEdge() < incompleteEdge) - DataShard.GetSnapshotManager().SetIncompleteEdge(db, incompleteEdge); - TRowVersion lowWatermark(rs.GetMvccLowWatermarkStep(), rs.GetMvccLowWatermarkTxId()); - if (DataShard.GetSnapshotManager().GetLowWatermark() < lowWatermark) - DataShard.GetSnapshotManager().SetLowWatermark(db, lowWatermark); + if (DataShard.GetSnapshotManager().GetMinWriteVersion() < minVersion) + DataShard.GetSnapshotManager().SetMinWriteVersion(db, minVersion); + + if (mvcc) { + TRowVersion completeEdge(rs.GetMvccCompleteEdgeStep(), rs.GetMvccCompleteEdgeTxId()); + if (DataShard.GetSnapshotManager().GetCompleteEdge() < completeEdge) + DataShard.GetSnapshotManager().SetCompleteEdge(db, completeEdge); + TRowVersion incompleteEdge(rs.GetMvccIncompleteEdgeStep(), rs.GetMvccIncompleteEdgeTxId()); + if (DataShard.GetSnapshotManager().GetIncompleteEdge() < incompleteEdge) + DataShard.GetSnapshotManager().SetIncompleteEdge(db, incompleteEdge); + TRowVersion lowWatermark(rs.GetMvccLowWatermarkStep(), rs.GetMvccLowWatermarkTxId()); + if (DataShard.GetSnapshotManager().GetLowWatermark() < lowWatermark) + DataShard.GetSnapshotManager().SetLowWatermark(db, lowWatermark); } } @@ -96,11 +96,11 @@ EExecutionStatus TReceiveSnapshotUnit::Execute(TOperation::TPtr op, Y_VERIFY(DataShard.GetSnapshotManager().GetSnapshots().empty(), "Found unexpected persistent snapshots at CopyTable destination"); - const auto minVersion = mvcc ? DataShard.GetSnapshotManager().GetLowWatermark() - : DataShard.GetSnapshotManager().GetMinWriteVersion(); - + const auto minVersion = mvcc ? DataShard.GetSnapshotManager().GetLowWatermark() + : DataShard.GetSnapshotManager().GetMinWriteVersion(); + // If MinWriteVersion is not zero, then all versions below it are inaccessible - if (minVersion) { + if (minVersion) { for (const auto& kv : DataShard.GetUserTables()) { ui32 localTableId = kv.second->LocalTid; txc.DB.RemoveRowVersions(localTableId, TRowVersion::Min(), minVersion); diff --git a/ydb/core/tx/datashard/setup_sys_locks.h b/ydb/core/tx/datashard/setup_sys_locks.h index f06dfa3a23..1774533dba 100644 --- a/ydb/core/tx/datashard/setup_sys_locks.h +++ b/ydb/core/tx/datashard/setup_sys_locks.h @@ -13,26 +13,26 @@ struct TSetupSysLocks { TDataShard &self) : SysLocksTable(self.SysLocksTable()) { - TLocksUpdate &update = op->LocksUpdate(); + TLocksUpdate &update = op->LocksUpdate(); + + update.Clear(); + update.LockTxId = op->LockTxId(); - update.Clear(); - update.LockTxId = op->LockTxId(); - if (self.IsMvccEnabled()) { - auto [readVersion, writeVersion] = self.GetReadWriteVersions(op.Get()); - - // check whether the current operation is a part of an out-of-order Tx - bool outOfOrder = false; - if (auto &activeOps = self.Pipeline.GetActivePlannedOps()) { - if (auto it = activeOps.begin(); writeVersion != TRowVersion(it->first.Step, it->first.TxId)) - outOfOrder = true; - } - - update.CheckVersion = readVersion; - update.BreakVersion = outOfOrder ? writeVersion : TRowVersion::Min(); - } - - SysLocksTable.SetTxUpdater(&update); + auto [readVersion, writeVersion] = self.GetReadWriteVersions(op.Get()); + + // check whether the current operation is a part of an out-of-order Tx + bool outOfOrder = false; + if (auto &activeOps = self.Pipeline.GetActivePlannedOps()) { + if (auto it = activeOps.begin(); writeVersion != TRowVersion(it->first.Step, it->first.TxId)) + outOfOrder = true; + } + + update.CheckVersion = readVersion; + update.BreakVersion = outOfOrder ? writeVersion : TRowVersion::Min(); + } + + SysLocksTable.SetTxUpdater(&update); if (!op->LocksCache().Locks.empty()) SysLocksTable.SetCache(&op->LocksCache()); else diff --git a/ydb/core/tx/datashard/sys_tables.h b/ydb/core/tx/datashard/sys_tables.h index 53bb7ac1ff..e9887bd8db 100644 --- a/ydb/core/tx/datashard/sys_tables.h +++ b/ydb/core/tx/datashard/sys_tables.h @@ -49,7 +49,7 @@ struct TSysTables { struct TLock { enum ESetErrors : ui64 { ErrorMin = Max<ui64>() - 255, - ErrorAlreadyBroken = Max<ui64>() - 3, + ErrorAlreadyBroken = Max<ui64>() - 3, ErrorNotSet = Max<ui64>() - 2, ErrorTooMuch = Max<ui64>() - 1, ErrorBroken = Max<ui64>() diff --git a/ydb/core/tx/datashard/ya.make b/ydb/core/tx/datashard/ya.make index 0300028352..9c98e8e79b 100644 --- a/ydb/core/tx/datashard/ya.make +++ b/ydb/core/tx/datashard/ya.make @@ -78,7 +78,7 @@ SRCS( datashard_locks.cpp datashard_split_dst.cpp datashard_split_src.cpp - datashard_switch_mvcc_state.cpp + datashard_switch_mvcc_state.cpp datashard_trans_queue.cpp datashard_trans_queue.h datashard_outreadset.cpp diff --git a/ydb/core/tx/schemeshard/schemeshard_info_types.cpp b/ydb/core/tx/schemeshard/schemeshard_info_types.cpp index 7f9d3dfb11..fcb564b606 100644 --- a/ydb/core/tx/schemeshard/schemeshard_info_types.cpp +++ b/ydb/core/tx/schemeshard/schemeshard_info_types.cpp @@ -565,10 +565,10 @@ bool TPartitionConfigMerger::ApplyChanges( result.SetShadowData(changes.GetShadowData()); } - if (changes.HasKeepSnapshotTimeout()) { - result.SetKeepSnapshotTimeout(changes.GetKeepSnapshotTimeout()); - } - + if (changes.HasKeepSnapshotTimeout()) { + result.SetKeepSnapshotTimeout(changes.GetKeepSnapshotTimeout()); + } + return true; } @@ -1181,9 +1181,9 @@ void TTableInfo::FinishAlter() { partitionConfig.ClearColumnFamilies(); partitionConfig.AddColumnFamilies()->CopyFrom(*newConfig.GetColumnFamilies().rbegin()); } - if (newConfig.HasKeepSnapshotTimeout()) { - partitionConfig.SetKeepSnapshotTimeout(newConfig.GetKeepSnapshotTimeout()); - } + if (newConfig.HasKeepSnapshotTimeout()) { + partitionConfig.SetKeepSnapshotTimeout(newConfig.GetKeepSnapshotTimeout()); + } } // Avoid ShadowData==false in the resulting config diff --git a/ydb/core/tx/schemeshard/schemeshard_utils.cpp b/ydb/core/tx/schemeshard/schemeshard_utils.cpp index c1406f020f..4ee28e3543 100644 --- a/ydb/core/tx/schemeshard/schemeshard_utils.cpp +++ b/ydb/core/tx/schemeshard/schemeshard_utils.cpp @@ -450,9 +450,9 @@ NKikimrSchemeOp::TPartitionConfig PartitionConfigForIndexes( if (baseTablePartitionConfig.HasEraseCacheMaxBytes()) { result.SetEraseCacheMaxBytes(baseTablePartitionConfig.GetEraseCacheMaxBytes()); } - if (baseTablePartitionConfig.HasKeepSnapshotTimeout()) { - result.SetKeepSnapshotTimeout(baseTablePartitionConfig.GetKeepSnapshotTimeout()); - } + if (baseTablePartitionConfig.HasKeepSnapshotTimeout()) { + result.SetKeepSnapshotTimeout(baseTablePartitionConfig.GetKeepSnapshotTimeout()); + } // skip repeated NKikimrStorageSettings.TStorageRoom StorageRooms = 17; // skip optional NKikimrHive.TFollowerGroup FollowerGroup = 23; diff --git a/ydb/core/tx/tx_proxy/datareq.cpp b/ydb/core/tx/tx_proxy/datareq.cpp index 21b2b8c3a9..af48b42d60 100644 --- a/ydb/core/tx/tx_proxy/datareq.cpp +++ b/ydb/core/tx/tx_proxy/datareq.cpp @@ -55,7 +55,7 @@ struct TFlatMKQLRequest : public TThrRefBase { bool ReadOnlyProgram; TMaybe<ui64> PerShardKeysSizeLimitBytes; NKikimrTxUserProxy::TMiniKQLTransaction::TLimits Limits; - TRowVersion Snapshot = TRowVersion::Min(); + TRowVersion Snapshot = TRowVersion::Min(); TMap<ui64, TAutoPtr<TBalanceCoverageBuilder>> BalanceCoverageBuilders; @@ -963,7 +963,7 @@ void TDataReq::ProcessFlatMKQLResolve(NSchemeCache::TSchemeCacheRequest *cacheRe TxProxyMon->TxPrepareBuildShardProgramsHgram->Collect((afterBuild - beforeBuild).MicroSeconds()); - if (engine.GetAffectedShardCount() > 1 || FlatMKQLRequest->Snapshot) // TODO KIKIMR-11912 + if (engine.GetAffectedShardCount() > 1 || FlatMKQLRequest->Snapshot) // TODO KIKIMR-11912 CanUseFollower = false; TDuration shardCancelAfter = ExecTimeoutPeriod; @@ -981,7 +981,7 @@ void TDataReq::ProcessFlatMKQLResolve(NSchemeCache::TSchemeCacheRequest *cacheRe NKikimrTxDataShard::TDataTransaction dataTransaction; dataTransaction.SetMiniKQL(shardData.Program); - dataTransaction.SetImmediate(shardData.Immediate || FlatMKQLRequest->Snapshot && FlatMKQLRequest->ReadOnlyProgram); + dataTransaction.SetImmediate(shardData.Immediate || FlatMKQLRequest->Snapshot && FlatMKQLRequest->ReadOnlyProgram); dataTransaction.SetReadOnly(FlatMKQLRequest->ReadOnlyProgram); dataTransaction.SetCancelAfterMs(shardCancelAfter.MilliSeconds()); dataTransaction.SetCancelDeadlineMs(shardCancelDeadline.MilliSeconds()); @@ -1047,16 +1047,16 @@ void TDataReq::ProcessFlatMKQLResolve(NSchemeCache::TSchemeCacheRequest *cacheRe << " followers " << (CanUseFollower ? "allowed" : "disallowed") << " marker# P4"); const TActorId pipeCache = CanUseFollower ? Services.FollowerPipeCache : Services.LeaderPipeCache; - TEvDataShard::TEvProposeTransaction* ev; - if (FlatMKQLRequest->Snapshot && FlatMKQLRequest->ReadOnlyProgram) { - ev = new TEvDataShard::TEvProposeTransaction(NKikimrTxDataShard::TX_KIND_DATA, - ctx.SelfID, TxId, transactionBuffer, FlatMKQLRequest->Snapshot, TxFlags | NTxDataShard::TTxFlags::Immediate); - } else { - ev = new TEvDataShard::TEvProposeTransaction(NKikimrTxDataShard::TX_KIND_DATA, - ctx.SelfID, TxId, transactionBuffer, TxFlags | (shardData.Immediate ? NTxDataShard::TTxFlags::Immediate : 0)); - } + TEvDataShard::TEvProposeTransaction* ev; + if (FlatMKQLRequest->Snapshot && FlatMKQLRequest->ReadOnlyProgram) { + ev = new TEvDataShard::TEvProposeTransaction(NKikimrTxDataShard::TX_KIND_DATA, + ctx.SelfID, TxId, transactionBuffer, FlatMKQLRequest->Snapshot, TxFlags | NTxDataShard::TTxFlags::Immediate); + } else { + ev = new TEvDataShard::TEvProposeTransaction(NKikimrTxDataShard::TX_KIND_DATA, + ctx.SelfID, TxId, transactionBuffer, TxFlags | (shardData.Immediate ? NTxDataShard::TTxFlags::Immediate : 0)); + } - Send(pipeCache, new TEvPipeCache::TEvForward(ev, shardData.ShardId, true)); + Send(pipeCache, new TEvPipeCache::TEvForward(ev, shardData.ShardId, true)); FlatMKQLRequest->BalanceCoverageBuilders[shardData.ShardId] = new TBalanceCoverageBuilder(); } @@ -1289,8 +1289,8 @@ void TDataReq::Handle(TEvTxProxyReq::TEvMakeRequest::TPtr &ev, const TActorConte if (mkqlTxBody.HasLimits()) { FlatMKQLRequest->Limits.CopyFrom(mkqlTxBody.GetLimits()); } - if (mkqlTxBody.HasSnapshotStep() && mkqlTxBody.HasSnapshotTxId()) - FlatMKQLRequest->Snapshot = TRowVersion(mkqlTxBody.GetSnapshotStep(), mkqlTxBody.GetSnapshotTxId()); + if (mkqlTxBody.HasSnapshotStep() && mkqlTxBody.HasSnapshotTxId()) + FlatMKQLRequest->Snapshot = TRowVersion(mkqlTxBody.GetSnapshotStep(), mkqlTxBody.GetSnapshotTxId()); NMiniKQL::TEngineFlatSettings settings(NMiniKQL::IEngineFlat::EProtocol::V1, functionRegistry, *TAppData::RandomProvider, *TAppData::TimeProvider, nullptr, TxProxyMon->AllocPoolCounters); diff --git a/ydb/core/viewer/content/v2/node.js b/ydb/core/viewer/content/v2/node.js index 216f535ac1..422249c57c 100644 --- a/ydb/core/viewer/content/v2/node.js +++ b/ydb/core/viewer/content/v2/node.js @@ -149,10 +149,10 @@ Node.prototype.updateToolTip = function() { }); tooltip += endpoints; } - - if (sysInfo.ConfigState !== undefined) { - tooltip += '<tr><td>Configuration</td><td>' + sysInfo.ConfigState + '</td></tr>'; - } + + if (sysInfo.ConfigState !== undefined) { + tooltip += '<tr><td>Configuration</td><td>' + sysInfo.ConfigState + '</td></tr>'; + } } tooltip += '</table>' this.domElementHostLink.setAttribute('data-original-title', tooltip); @@ -678,10 +678,10 @@ Node.prototype.updateSysInfo = function(update) { tip += '</table></html>'; memBlock.domElement.setAttribute('data-original-title', tip); } - - if (sysInfo.ConfigState === 'Outdated') { - this.domElementNodeIcons.innerHTML = this.getIcon('exclamation-sign', red); - } + + if (sysInfo.ConfigState === 'Outdated') { + this.domElementNodeIcons.innerHTML = this.getIcon('exclamation-sign', red); + } this.domElementHostLink.setAttribute('href', this.getBaseUrl()); } |