From 5f7e5f75326dfee227cc2a037801e530ceb6a612 Mon Sep 17 00:00:00 2001 From: Semyon Yentsov Date: Thu, 23 Jan 2025 18:58:15 +0300 Subject: [PATCH 1/5] allow missing tiers in schema --- ydb/core/kqp/ut/olap/helpers/get_value.cpp | 14 ++ ydb/core/kqp/ut/olap/helpers/get_value.h | 1 + ydb/core/kqp/ut/olap/tiering_ut.cpp | 76 +++++++++++ .../columnshard/blobs_action/tier/storage.cpp | 41 +++--- ydb/core/tx/columnshard/columnshard.cpp | 2 +- ydb/core/tx/columnshard/columnshard__init.cpp | 6 +- ydb/core/tx/columnshard/columnshard_impl.cpp | 7 +- ydb/core/tx/columnshard/columnshard_impl.h | 4 +- .../storage/actualizer/tiering/tiering.cpp | 7 - ydb/core/tx/columnshard/loading/stages.cpp | 29 +++++ ydb/core/tx/columnshard/loading/stages.h | 10 ++ ydb/core/tx/tiering/manager.cpp | 122 +++++++----------- ydb/core/tx/tiering/manager.h | 69 ++++++---- ydb/core/tx/tiering/ut/ut_tiers.cpp | 2 +- ydb/core/wrappers/events/get_object.h | 20 +++ ydb/core/wrappers/fake_storage.cpp | 25 +--- ydb/core/wrappers/s3_storage.cpp | 22 +--- ydb/core/wrappers/unavailable_storage.cpp | 4 + ydb/core/wrappers/unavailable_storage.h | 83 ++++++++++++ ydb/core/wrappers/ya.make | 1 + 20 files changed, 360 insertions(+), 185 deletions(-) create mode 100644 ydb/core/wrappers/unavailable_storage.cpp create mode 100644 ydb/core/wrappers/unavailable_storage.h diff --git a/ydb/core/kqp/ut/olap/helpers/get_value.cpp b/ydb/core/kqp/ut/olap/helpers/get_value.cpp index 542b1fd9a81e..617e78da59aa 100644 --- a/ydb/core/kqp/ut/olap/helpers/get_value.cpp +++ b/ydb/core/kqp/ut/olap/helpers/get_value.cpp @@ -26,6 +26,11 @@ void PrintValue(IOutputStream& out, const NYdb::TValue& v) { out << value.GetUint32(); break; } + case NYdb::EPrimitiveType::Int32: + { + out << value.GetInt32(); + break; + } case NYdb::EPrimitiveType::Uint64: { out << value.GetUint64(); @@ -72,6 +77,15 @@ ui64 GetUint32(const NYdb::TValue& v) { } } +i64 GetInt32(const NYdb::TValue& v) { + NYdb::TValueParser value(v); + if (value.GetKind() == NYdb::TTypeParser::ETypeKind::Optional) { + return *value.GetOptionalInt32(); + } else { + return value.GetInt32(); + } +} + ui64 GetUint64(const NYdb::TValue& v) { NYdb::TValueParser value(v); if (value.GetKind() == NYdb::TTypeParser::ETypeKind::Optional) { diff --git a/ydb/core/kqp/ut/olap/helpers/get_value.h b/ydb/core/kqp/ut/olap/helpers/get_value.h index d74f894a59ba..e607a152d668 100644 --- a/ydb/core/kqp/ut/olap/helpers/get_value.h +++ b/ydb/core/kqp/ut/olap/helpers/get_value.h @@ -8,6 +8,7 @@ void PrintRow(IOutputStream& out, const THashMap& fields) void PrintRows(IOutputStream& out, const TVector>& rows); ui64 GetUint32(const NYdb::TValue& v); +i64 GetInt32(const NYdb::TValue& v); ui64 GetUint64(const NYdb::TValue& v); TString GetUtf8(const NYdb::TValue& v); TInstant GetTimestamp(const NYdb::TValue& v); diff --git a/ydb/core/kqp/ut/olap/tiering_ut.cpp b/ydb/core/kqp/ut/olap/tiering_ut.cpp index 40b4c549542d..6c7ade548878 100644 --- a/ydb/core/kqp/ut/olap/tiering_ut.cpp +++ b/ydb/core/kqp/ut/olap/tiering_ut.cpp @@ -179,6 +179,82 @@ Y_UNIT_TEST_SUITE(KqpOlapTiering) { testHelper.SetTiering("/Root/olapStore/olapTable", "/Root/tier1", "timestamp"); } + + Y_UNIT_TEST(DeletedTier) { + auto csController = NYDBTest::TControllers::RegisterCSControllerGuard(); + csController->SetSkipSpecialCheckForEvict(true); + + TKikimrSettings runnerSettings; + runnerSettings.WithSampleTables = false; + TTestHelper testHelper(runnerSettings); + TLocalHelper localHelper(testHelper.GetKikimr()); + testHelper.GetRuntime().SetLogPriority(NKikimrServices::TX_TIERING, NActors::NLog::PRI_DEBUG); + NYdb::NTable::TTableClient tableClient = testHelper.GetKikimr().GetTableClient(); + Tests::NCommon::TLoggerInit(testHelper.GetKikimr()).Initialize(); + Singleton()->SetSecretKey("fakeSecret"); + + localHelper.CreateTestOlapTable(); + testHelper.CreateTier("tier1"); + + for (ui64 i = 0; i < 100; ++i) { + WriteTestData(testHelper.GetKikimr(), "/Root/olapStore/olapTable", 0, 3600000000 + i * 1000, 1000); + WriteTestData(testHelper.GetKikimr(), "/Root/olapStore/olapTable", 0, 3600000000 + i * 1000, 1000); + } + + testHelper.SetTiering("/Root/olapStore/olapTable", "/Root/tier1", "timestamp"); + csController->WaitCompactions(TDuration::Seconds(5)); + csController->WaitActualization(TDuration::Seconds(5)); + + csController->DisableBackground(NYDBTest::ICSController::EBackground::TTL); + testHelper.ResetTiering("/Root/olapStore/olapTable"); + testHelper.RebootTablets("/Root/olapStore/olapTable"); + + { + auto selectQuery = TString(R"( + SELECT + TierName, SUM(ColumnRawBytes) As RawBytes + FROM `/Root/olapStore/olapTable/.sys/primary_index_portion_stats` + WHERE Activity == 1 + GROUP BY TierName + )"); + + auto rows = ExecuteScanQuery(tableClient, selectQuery); + UNIT_ASSERT_VALUES_EQUAL(rows.size(), 1); + UNIT_ASSERT_VALUES_EQUAL(GetUtf8(rows[0].at("TierName")), "/Root/tier1"); + } + + ui64 maxLevelValue; + { + auto selectQuery = TString(R"(SELECT MAX(level) AS level FROM `/Root/olapStore/olapTable`)"); + auto rows = ExecuteScanQuery(tableClient, selectQuery); + UNIT_ASSERT_VALUES_EQUAL(rows.size(), 1); + maxLevelValue = GetInt32(rows[0].at("level")); + } + + { + auto result = testHelper.GetSession().ExecuteSchemeQuery(R"(DROP EXTERNAL DATA SOURCE `/Root/tier1`)").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), NYdb::EStatus::SUCCESS, result.GetIssues().ToString()); + } + testHelper.RebootTablets("/Root/olapStore/olapTable"); + + { + auto selectQuery = TString(R"(SELECT MAX(level) FROM `/Root/olapStore/olapTable`)"); + auto it = tableClient.StreamExecuteScanQuery(selectQuery, NYdb::NTable::TStreamExecScanQuerySettings()).GetValueSync(); + auto streamPart = it.ReadNext().GetValueSync(); + UNIT_ASSERT(!streamPart.IsSuccess()); + UNIT_ASSERT_STRING_CONTAINS(streamPart.GetIssues().ToString(), "cannot read blob range"); + } + + testHelper.CreateTier("tier1"); + testHelper.RebootTablets("/Root/olapStore/olapTable"); + + { + auto selectQuery = TString(R"(SELECT MAX(level) AS level FROM `/Root/olapStore/olapTable`)"); + auto rows = ExecuteScanQuery(tableClient, selectQuery); + UNIT_ASSERT_VALUES_EQUAL(rows.size(), 1); + UNIT_ASSERT_VALUES_EQUAL(GetInt32(rows[0].at("level")), maxLevelValue); + } + } } } // namespace NKikimr::NKqp diff --git a/ydb/core/tx/columnshard/blobs_action/tier/storage.cpp b/ydb/core/tx/columnshard/blobs_action/tier/storage.cpp index 2cb28089eb87..4184a47fce44 100644 --- a/ydb/core/tx/columnshard/blobs_action/tier/storage.cpp +++ b/ydb/core/tx/columnshard/blobs_action/tier/storage.cpp @@ -1,12 +1,14 @@ -#include "storage.h" #include "adapter.h" -#include "remove.h" -#include "write.h" -#include "read.h" #include "gc.h" #include "gc_actor.h" +#include "read.h" +#include "remove.h" +#include "storage.h" +#include "write.h" + #include #include +#include namespace NKikimr::NOlap::NBlobOperations::NTier { @@ -54,23 +56,28 @@ void TOperator::DoStartGCAction(const std::shared_ptr& action) c } void TOperator::InitNewExternalOperator(const NColumnShard::NTiers::TManager* tierManager) { - if (!tierManager || !tierManager->IsReady()) { + NWrappers::NExternalStorage::IExternalStorageOperator::TPtr extStorageOperator; + std::optional settings; + + if (tierManager && tierManager->IsReady()) { + settings = tierManager->GetS3Settings(); + { + TGuard changeLock(ChangeOperatorLock); + if (CurrentS3Settings && CurrentS3Settings->SerializeAsString() == settings->SerializeAsString()) { + return; + } + } + auto extStorageConfig = NWrappers::NExternalStorage::IExternalStorageConfig::Construct(*settings); + AFL_VERIFY(extStorageConfig); + extStorageOperator = extStorageConfig->ConstructStorageOperator(false); + } else { TGuard changeLock(ChangeOperatorLock); CurrentS3Settings.reset(); - ExternalStorageOperator = nullptr; - return; + extStorageOperator = std::make_shared( + NWrappers::NExternalStorage::TUnavailableExternalStorageOperator( + "tier_unavailable", TStringBuilder() << "Tier is not configured: " << GetStorageId())); } - NKikimrSchemeOp::TS3Settings settings = tierManager->GetS3Settings(); - { - TGuard changeLock(ChangeOperatorLock); - if (CurrentS3Settings && CurrentS3Settings->SerializeAsString() == settings.SerializeAsString()) { - return; - } - } - auto extStorageConfig = NWrappers::NExternalStorage::IExternalStorageConfig::Construct(settings); - AFL_VERIFY(extStorageConfig); - auto extStorageOperator = extStorageConfig->ConstructStorageOperator(false); extStorageOperator->InitReplyAdapter(std::make_shared(GetStorageId())); TGuard changeLock(ChangeOperatorLock); CurrentS3Settings = settings; diff --git a/ydb/core/tx/columnshard/columnshard.cpp b/ydb/core/tx/columnshard/columnshard.cpp index 904cac4f0346..762b9fb18c04 100644 --- a/ydb/core/tx/columnshard/columnshard.cpp +++ b/ydb/core/tx/columnshard/columnshard.cpp @@ -62,7 +62,7 @@ void TColumnShard::BecomeBroken(const TActorContext& ctx) { } void TColumnShard::TrySwitchToWork(const TActorContext& ctx) { - if (!Tiers->AreConfigsComplete()) { + if (Tiers->GetAwaitedConfigsCount()) { AFL_INFO(NKikimrServices::TX_COLUMNSHARD)("event", "skip_switch_to_work")("reason", "tiering_metadata_not_ready"); return; } diff --git a/ydb/core/tx/columnshard/columnshard__init.cpp b/ydb/core/tx/columnshard/columnshard__init.cpp index f8743854a384..f45dbe14cfed 100644 --- a/ydb/core/tx/columnshard/columnshard__init.cpp +++ b/ydb/core/tx/columnshard/columnshard__init.cpp @@ -69,6 +69,7 @@ std::shared_ptr TTxInit::BuildReader() { result->AddChildren(std::make_shared("bg_sessions", Self)); result->AddChildren(std::make_shared("sharing_sessions", Self)); result->AddChildren(std::make_shared("in_flight_reads", Self)); + result->AddChildren(std::make_shared("tiers_manager", Self)); return result; } @@ -106,11 +107,6 @@ void TTxInit::Complete(const TActorContext& ctx) { Self->Counters.GetCSCounters().Initialization.OnTxInitFinished(TMonotonic::Now() - StartInstant); AFL_VERIFY(!Self->IsTxInitFinished); Self->IsTxInitFinished = true; - - for (const auto& [pathId, tiering] : Self->TablesManager.GetTtl()) { - Self->Tiers->EnablePathId(pathId, tiering.GetUsedTiers()); - } - Self->TrySwitchToWork(ctx); } diff --git a/ydb/core/tx/columnshard/columnshard_impl.cpp b/ydb/core/tx/columnshard/columnshard_impl.cpp index 1af0925b46ae..9cfbf57d070c 100644 --- a/ydb/core/tx/columnshard/columnshard_impl.cpp +++ b/ydb/core/tx/columnshard/columnshard_impl.cpp @@ -1594,12 +1594,7 @@ void TColumnShard::Handle(NOlap::NBlobOperations::NEvents::TEvDeleteSharedBlobs: void TColumnShard::ActivateTiering(const ui64 pathId, const THashSet& usedTiers) { AFL_VERIFY(Tiers); - if (!usedTiers.empty()) { - AFL_INFO(NKikimrServices::TX_COLUMNSHARD)("event", "activate_tiering")("path_id", pathId)("tier_count", usedTiers.size()); - Tiers->EnablePathId(pathId, usedTiers); - } else { - Tiers->DisablePathId(pathId); - } + Tiers->ActivateTiers(usedTiers); OnTieringModified(pathId); } diff --git a/ydb/core/tx/columnshard/columnshard_impl.h b/ydb/core/tx/columnshard/columnshard_impl.h index 0b8d7c1c017c..b86b895eb2a7 100644 --- a/ydb/core/tx/columnshard/columnshard_impl.h +++ b/ydb/core/tx/columnshard/columnshard_impl.h @@ -117,6 +117,7 @@ class TSharingSessionsInitializer; class TInFlightReadsInitializer; class TSpecialValuesInitializer; class TTablesManagerInitializer; +class TTiersManagerInitializer; } // namespace NLoading extern bool gAllowLogBatchingDefaultValue; @@ -233,6 +234,7 @@ class TColumnShard: public TActor, public NTabletFlatExecutor::TTa friend class NLoading::TInFlightReadsInitializer; friend class NLoading::TSpecialValuesInitializer; friend class NLoading::TTablesManagerInitializer; + friend class NLoading::TTiersManagerInitializer; friend class TWriteTasksQueue; friend class TWriteTask; @@ -330,7 +332,7 @@ class TColumnShard: public TActor, public NTabletFlatExecutor::TTa putStatus.OnYellowChannels(Executor()); } - void ActivateTiering(const ui64 pathId, const THashSet& usedTiers); + void ActivateTiering(const ui64 pathId, const THashSet& tiers); void OnTieringModified(const std::optional pathId = {}); std::shared_ptr TabletActivityImpl = std::make_shared(0); diff --git a/ydb/core/tx/columnshard/engines/storage/actualizer/tiering/tiering.cpp b/ydb/core/tx/columnshard/engines/storage/actualizer/tiering/tiering.cpp index 25bb2f711131..ab0e0990f9f8 100644 --- a/ydb/core/tx/columnshard/engines/storage/actualizer/tiering/tiering.cpp +++ b/ydb/core/tx/columnshard/engines/storage/actualizer/tiering/tiering.cpp @@ -57,13 +57,6 @@ std::optional TTieringActualizer::Bu targetTierName = tieringInfo.GetNextTierNameVerified(); } if (d) { - if (targetTierName != NTiering::NCommon::DeleteTierName) { - if (const auto op = StoragesManager->GetOperatorOptional(targetTierName); !op || !op->IsReady()) { - AFL_WARN(NKikimrServices::TX_COLUMNSHARD)("event", "skip_eviction")("reason", "storage_not_ready")("tier", targetTierName)( - "portion", portion.GetPortionId()); - return std::nullopt; - } - } // if (currentTierName == "deploy_logs_s3" && targetTierName == IStoragesManager::DefaultStorageId) { // AFL_ERROR(NKikimrServices::TX_COLUMNSHARD)("tiering_info", tieringInfo.DebugString())("max", max->ToString())("now", now.ToString())("d", *d)("tiering", Tiering->GetDebugString())("pathId", PathId); // AFL_VERIFY(false)("tiering_info", tieringInfo.DebugString())("max", max->ToString())("now", now.ToString())("d", *d)("tiering", Tiering->GetDebugString())("pathId", PathId); diff --git a/ydb/core/tx/columnshard/loading/stages.cpp b/ydb/core/tx/columnshard/loading/stages.cpp index a0db85a87aaf..b230deebaab8 100644 --- a/ydb/core/tx/columnshard/loading/stages.cpp +++ b/ydb/core/tx/columnshard/loading/stages.cpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace NKikimr::NColumnShard::NLoading { @@ -228,4 +229,32 @@ bool TTablesManagerInitializer::DoPrecharge(NTabletFlatExecutor::TTransactionCon (int)Schema::Precharge(db, txc.DB.GetScheme()); } +bool TTiersManagerInitializer::DoExecute(NTabletFlatExecutor::TTransactionContext& txc, const TActorContext& /*ctx*/) { + NIceDb::TNiceDb db(txc.DB); + auto rowset = db.Table().Select(); + if (!rowset.IsReady()) { + return false; + } + + while (!rowset.EndOfSet()) { + NKikimrTxColumnShard::TTableVersionInfo versionInfo; + AFL_VERIFY(versionInfo.ParseFromString(rowset.GetValue())); + if (versionInfo.GetTtlSettings().HasEnabled()) { + NOlap::TTiering tiering; + tiering.DeserializeFromProto(versionInfo.GetTtlSettings().GetEnabled()).Validate(); + Self->Tiers->ActivateTiers(tiering.GetUsedTiers()); + } + + if (!rowset.Next()) { + return false; + } + } + return true; +} + +bool TTiersManagerInitializer::DoPrecharge(NTabletFlatExecutor::TTransactionContext& txc, const TActorContext& /*ctx*/) { + NIceDb::TNiceDb db(txc.DB); + return Schema::Precharge(db, txc.DB.GetScheme()); +} + } // namespace NKikimr::NColumnShard::NLoading diff --git a/ydb/core/tx/columnshard/loading/stages.h b/ydb/core/tx/columnshard/loading/stages.h index 7fced6b3eba4..7cc2bb783bce 100644 --- a/ydb/core/tx/columnshard/loading/stages.h +++ b/ydb/core/tx/columnshard/loading/stages.h @@ -138,4 +138,14 @@ class TTablesManagerInitializer: public ITxShardInitReader { using TBase::TBase; }; +class TTiersManagerInitializer: public ITxShardInitReader { +private: + using TBase = ITxShardInitReader; + virtual bool DoExecute(NTabletFlatExecutor::TTransactionContext& txc, const TActorContext& /*ctx*/) override; + virtual bool DoPrecharge(NTabletFlatExecutor::TTransactionContext& txc, const TActorContext& /*ctx*/) override; + +public: + using TBase::TBase; +}; + } // namespace NKikimr::NColumnShard::NLoading diff --git a/ydb/core/tx/tiering/manager.cpp b/ydb/core/tx/tiering/manager.cpp index 49915d241cf0..864e9be48b9f 100644 --- a/ydb/core/tx/tiering/manager.cpp +++ b/ydb/core/tx/tiering/manager.cpp @@ -28,11 +28,7 @@ class TTiersManager::TActor: public TActorBootstrapped { return NMetadata::NProvider::MakeServiceId(SelfId().NodeId()); } - void OnTierFetchingError(const NTiers::TExternalStorageId& tier) { - if (!Owner->TierRefCount.contains(tier)) { - ResetRetryState(tier); - return; - } + void RetryTierRequest(const NTiers::TExternalStorageId& tier) { AFL_DEBUG(NKikimrServices::TX_TIERING)("component", "tiers_manager")("event", "retry_watch_objects"); auto findRetryState = RetryStateByObject.find(tier); if (!findRetryState) { @@ -84,26 +80,33 @@ class TTiersManager::TActor: public TActorBootstrapped { NTiers::TTierConfig tier; if (const auto status = tier.DeserializeFromProto(description.GetExternalDataSourceDescription()); status.IsFail()) { AFL_WARN(NKikimrServices::TX_TIERING)("event", "fetched_invalid_tier_settings")("error", status.GetErrorMessage()); - OnTierFetchingError(tierId); + Owner->UpdateTierConfig(std::nullopt, tierId); return; } Owner->UpdateTierConfig(tier, tierId); } else { AFL_WARN(false)("error", "invalid_object_type")("type", static_cast(description.GetSelf().GetPathType()))("path", tierId.GetConfigPath()); - OnTierFetchingError(tierId); + Owner->UpdateTierConfig(std::nullopt, tierId); } } void Handle(NTiers::TEvNotifySchemeObjectDeleted::TPtr& ev) { AFL_DEBUG(NKikimrServices::TX_TIERING)("component", "tiering_manager")("event", "object_deleted")("name", ev->Get()->GetObjectPath()); - OnTierFetchingError(ev->Get()->GetObjectPath()); + Owner->UpdateTierConfig(std::nullopt, ev->Get()->GetObjectPath()); } void Handle(NTiers::TEvSchemeObjectResolutionFailed::TPtr& ev) { const TString objectPath = ev->Get()->GetObjectPath(); AFL_WARN(NKikimrServices::TX_TIERING)("event", "object_resolution_failed")("path", objectPath)( "reason", static_cast(ev->Get()->GetReason())); - OnTierFetchingError(objectPath); + switch (ev->Get()->GetReason()) { + case NTiers::TEvSchemeObjectResolutionFailed::NOT_FOUND: + Owner->UpdateTierConfig(std::nullopt, objectPath); + break; + case NTiers::TEvSchemeObjectResolutionFailed::LOOKUP_ERROR: + RetryTierRequest(objectPath); + break; + } } void Handle(NTiers::TEvWatchSchemeObject::TPtr& ev) { @@ -179,39 +182,19 @@ NArrow::NSerialization::TSerializerContainer ConvertCompression(const NKikimrSch } } -TTiersManager::TTierRefGuard::TTierRefGuard(const NTiers::TExternalStorageId& tierId, TTiersManager& owner) - : TierId(tierId) - , Owner(&owner) { - if (!Owner->TierRefCount.contains(TierId)) { - Owner->RegisterTier(tierId); - } - ++Owner->TierRefCount[TierId]; -} - -TTiersManager::TTierRefGuard::~TTierRefGuard() { - if (Owner) { - auto findTier = Owner->TierRefCount.FindPtr(TierId); - AFL_VERIFY(findTier); - --*findTier; - if (!*findTier) { - AFL_VERIFY(Owner->TierRefCount.erase(TierId)); - Owner->UnregisterTier(TierId); - } - } -} - void TTiersManager::OnConfigsUpdated(bool notifyShard) { for (auto& [tierId, manager] : Managers) { - auto* findTierConfig = TierConfigs.FindPtr(tierId); - if (Secrets && findTierConfig) { + auto* findTier = Tiers.FindPtr(tierId); + AFL_VERIFY(findTier)("id", tierId); + if (Secrets && findTier->HasConfig()) { if (manager.IsReady()) { - manager.Restart(*findTierConfig, Secrets); + manager.Restart(findTier->GetConfigVerified(), Secrets); } else { - manager.Start(*findTierConfig, Secrets); + manager.Start(findTier->GetConfigVerified(), Secrets); } } else { AFL_DEBUG(NKikimrServices::TX_TIERING)("event", "skip_tier_manager_reloading")("tier", tierId)("has_secrets", !!Secrets)( - "found_tier_config", !!findTierConfig); + "found_tier_config", !!findTier); } } @@ -222,20 +205,19 @@ void TTiersManager::OnConfigsUpdated(bool notifyShard) { AFL_DEBUG(NKikimrServices::TX_TIERING)("event", "configs_updated")("configs", DebugString()); } -void TTiersManager::RegisterTier(const NTiers::TExternalStorageId& tierId) { +void TTiersManager::RegisterTierManager(const NTiers::TExternalStorageId& tierId, std::optional config) { auto emplaced = Managers.emplace(tierId, NTiers::TManager(TabletId, TabletActorId, tierId)); AFL_VERIFY(emplaced.second); - auto* findConfig = TierConfigs.FindPtr(tierId); - if (Secrets && findConfig) { - emplaced.first->second.Start(*findConfig, Secrets); + if (Secrets && config) { + emplaced.first->second.Start(*config, Secrets); } else { AFL_DEBUG(NKikimrServices::TX_TIERING)("event", "skip_tier_manager_start")("tier", tierId)("has_secrets", !!Secrets)( - "found_tier_config", !!findConfig); + "tier_config", !!config); } } -void TTiersManager::UnregisterTier(const NTiers::TExternalStorageId& tierId) { +void TTiersManager::UnregisterTierManager(const NTiers::TExternalStorageId& tierId) { auto findManager = Managers.find(tierId); AFL_VERIFY(findManager != Managers.end()); findManager->second.Stop(); @@ -272,13 +254,11 @@ const NTiers::TManager* TTiersManager::GetManagerOptional(const NTiers::TExterna } } -void TTiersManager::EnablePathId(const ui64 pathId, const THashSet& usedTiers) { +void TTiersManager::ActivateTiers(const THashSet& usedTiers) { AFL_VERIFY(Actor)("error", "tiers_manager_is_not_started"); - auto& tierRefs = UsedTiers[pathId]; - tierRefs.clear(); for (const NTiers::TExternalStorageId& tierId : usedTiers) { - tierRefs.emplace_back(tierId, *this); - if (!TierConfigs.contains(tierId)) { + if (!Tiers.contains(tierId)) { + Tiers.emplace(tierId, TTierGuard(tierId, this)); const auto& actorContext = NActors::TActivationContext::AsActorContext(); AFL_VERIFY(&actorContext)("error", "no_actor_context"); actorContext.Send(Actor->SelfId(), new NTiers::TEvWatchSchemeObject({ tierId.GetConfigPath() })); @@ -287,11 +267,6 @@ void TTiersManager::EnablePathId(const ui64 pathId, const THashSet secrets) { AFL_INFO(NKikimrServices::TX_TIERING)("event", "update_secrets")("tablet", TabletId); AFL_VERIFY(secrets); @@ -299,19 +274,29 @@ void TTiersManager::UpdateSecretsSnapshot(std::shared_ptr config, const NTiers::TExternalStorageId& tierId, const bool notifyShard) { + AFL_INFO(NKikimrServices::TX_TIERING)("event", "update_tier_config")("name", tierId.ToString())("tablet", TabletId)("has_config", !!config); + if (config) { + TTierGuard* findTier = Tiers.FindPtr(tierId); + if (!findTier) { + findTier = &Tiers.emplace(tierId, TTierGuard(tierId, this)).first->second; + } + findTier->UpsertConfig(*config); + } else { + Tiers.erase(tierId); + } OnConfigsUpdated(notifyShard); } -bool TTiersManager::AreConfigsComplete() const { - for (const auto& [tier, cnt] : TierRefCount) { - if (!TierConfigs.contains(tier)) { - return false; +ui64 TTiersManager::GetAwaitedConfigsCount() const { + ui64 count = 0; + for (const auto& [id, tier] : Tiers) { + if (!tier.HasConfig()) { + ++count; } } - return true; + return count; } TActorId TTiersManager::GetActorId() const { @@ -325,23 +310,10 @@ TActorId TTiersManager::GetActorId() const { TString TTiersManager::DebugString() { TStringBuilder sb; sb << "TIERS="; - if (TierConfigs) { + for (const auto& [id, tier] : Tiers) { sb << "{"; - for (const auto& [id, config] : TierConfigs) { - sb << id << ";"; - } - sb << "}"; - } - sb << ";USED_TIERS="; - { - sb << "{"; - for (const auto& [pathId, tiers] : UsedTiers) { - sb << pathId << ":{"; - for (const auto& tierRef : tiers) { - sb << tierRef.GetTierId() << ";"; - } - sb << "}"; - } + sb << "id=" << id << ";"; + sb << "has_config=" << tier.HasConfig(); sb << "}"; } sb << ";SECRETS="; diff --git a/ydb/core/tx/tiering/manager.h b/ydb/core/tx/tiering/manager.h index 5594c8967312..8ed41860566f 100644 --- a/ydb/core/tx/tiering/manager.h +++ b/ydb/core/tx/tiering/manager.h @@ -7,11 +7,13 @@ #include #include -#include #include +#include #include #include +#include + #include namespace NKikimr::NColumnShard { @@ -45,29 +47,48 @@ class TManager { } class TTiersManager: public ITiersManager { -private: - friend class TTierRef; - class TTierRefGuard: public TMoveOnly { +public: + class TTierGuard : NNonCopyable::TMoveOnly { private: - NTiers::TExternalStorageId TierId; + NTiers::TExternalStorageId StorageId; + std::optional Config; TTiersManager* Owner; public: - const NTiers::TExternalStorageId& GetTierId() const { - return TierId; + bool HasConfig() const { + return !!Config; + } + + const NTiers::TTierConfig& GetConfigVerified() const { + return *TValidator::CheckNotNull(Config); } - TTierRefGuard(const NTiers::TExternalStorageId& tierId, TTiersManager& owner); - ~TTierRefGuard(); + void UpsertConfig(NTiers::TTierConfig config) { + Config = std::move(config); + } - TTierRefGuard(TTierRefGuard&& other) - : TierId(other.TierId) - , Owner(other.Owner) { + const NTiers::TExternalStorageId& GetStorageId() const { + return StorageId; + } + + TTierGuard(const NTiers::TExternalStorageId& storageId, TTiersManager* owner) : StorageId(storageId), Owner(owner) { + AFL_VERIFY(owner); + Owner->RegisterTierManager(StorageId, std::nullopt); + } + + ~TTierGuard() { + if (Owner) { + Owner->UnregisterTierManager(StorageId); + } + } + + TTierGuard(TTierGuard&& other) : StorageId(other.StorageId), Config(other.Config), Owner(other.Owner) { other.Owner = nullptr; } - TTierRefGuard& operator=(TTierRefGuard&& other) { + TTierGuard& operator=(TTierGuard&& other) { + std::swap(StorageId, other.StorageId); + std::swap(Config, other.Config); std::swap(Owner, other.Owner); - std::swap(TierId, other.TierId); return *this; } }; @@ -83,19 +104,14 @@ class TTiersManager: public ITiersManager { IActor* Actor = nullptr; TManagers Managers; - using TTierRefCount = THashMap; - using TTierRefsByPathId = THashMap>; - YDB_READONLY_DEF(TTierRefCount, TierRefCount); - YDB_READONLY_DEF(TTierRefsByPathId, UsedTiers); - - using TTierById = THashMap; - YDB_READONLY_DEF(TTierById, TierConfigs); + using TTierById = THashMap; + YDB_READONLY_DEF(TTierById, Tiers); YDB_READONLY_DEF(std::shared_ptr, Secrets); private: void OnConfigsUpdated(bool notifyShard = true); - void RegisterTier(const NTiers::TExternalStorageId& name); - void UnregisterTier(const NTiers::TExternalStorageId& name); + void RegisterTierManager(const NTiers::TExternalStorageId& name, std::optional config); + void UnregisterTierManager(const NTiers::TExternalStorageId& name); public: TTiersManager(const ui64 tabletId, const TActorId& tabletActorId, std::function shardCallback = {}) @@ -105,12 +121,11 @@ class TTiersManager: public ITiersManager { , Secrets(std::make_shared(TInstant::Zero())) { } TActorId GetActorId() const; - void EnablePathId(const ui64 pathId, const THashSet& usedTiers); - void DisablePathId(const ui64 pathId); + void ActivateTiers(const THashSet& usedTiers); void UpdateSecretsSnapshot(std::shared_ptr secrets); - void UpdateTierConfig(const NTiers::TTierConfig& config, const NTiers::TExternalStorageId& tierId, const bool notifyShard = true); - bool AreConfigsComplete() const; + void UpdateTierConfig(std::optional config, const NTiers::TExternalStorageId& tierId, const bool notifyShard = true); + ui64 GetAwaitedConfigsCount() const; TString DebugString(); diff --git a/ydb/core/tx/tiering/ut/ut_tiers.cpp b/ydb/core/tx/tiering/ut/ut_tiers.cpp index b7507199dcdf..89439c8d006e 100644 --- a/ydb/core/tx/tiering/ut/ut_tiers.cpp +++ b/ydb/core/tx/tiering/ut/ut_tiers.cpp @@ -190,7 +190,7 @@ Y_UNIT_TEST_SUITE(ColumnShardTiers) { Manager = std::make_shared(0, SelfId(), [](const TActorContext&) { }); Manager->Start(Manager); - Manager->EnablePathId(0, ExpectedTiers); + Manager->ActivateTiers(ExpectedTiers); } TTestCSEmulator(THashSet expectedTiers) diff --git a/ydb/core/wrappers/events/get_object.h b/ydb/core/wrappers/events/get_object.h index 12ebaa6ba8af..566909a2464b 100644 --- a/ydb/core/wrappers/events/get_object.h +++ b/ydb/core/wrappers/events/get_object.h @@ -36,6 +36,26 @@ class TEvGetObjectResponse: public TResponseWithBody& range) { + TStringBuf buf(str); + if (!buf.SkipPrefix("bytes=")) { + return false; + } + + ui64 start; + if (!TryFromString(buf.NextTok('-'), start)) { + return false; + } + + ui64 end; + if (!TryFromString(buf, end)) { + return false; + } + + range = std::make_pair(start, end); + return true; + } + explicit TEvGetObjectResponse(const TBase::TKey& key, const typename TBase::TOutcome& outcome) : TBase(key, outcome) { diff --git a/ydb/core/wrappers/fake_storage.cpp b/ydb/core/wrappers/fake_storage.cpp index 7b755514f752..be0760238a67 100644 --- a/ydb/core/wrappers/fake_storage.cpp +++ b/ydb/core/wrappers/fake_storage.cpp @@ -23,29 +23,6 @@ using namespace Aws::S3; using namespace Aws::S3::Model; using namespace Aws::Utils::Stream; -namespace { - -static bool TryParseRange(const TString& str, std::pair& range) { - TStringBuf buf(str); - if (!buf.SkipPrefix("bytes=")) { - return false; - } - - ui64 start; - if (!TryFromString(buf.NextTok('-'), start)) { - return false; - } - - ui64 end; - if (!TryFromString(buf, end)) { - return false; - } - - range = std::make_pair(start, end); - return true; -} -} - TEvListObjectsResponse::TResult TFakeExternalStorage::BuildListObjectsResult(const TEvListObjectsRequest::TRequest& request) const { auto& bucket = GetBucket(AwsToString(request.GetBucket())); auto& awsPrefix = request.GetPrefix(); @@ -84,7 +61,7 @@ void TFakeExternalStorage::Execute(TEvGetObjectRequest::TPtr& ev, const TReplyAd auto awsRange = ev->Get()->GetRequest().GetRange(); Y_ABORT_UNLESS(awsRange.size()); const TString strRange(awsRange.data(), awsRange.size()); - AFL_VERIFY(TryParseRange(strRange, range))("original", strRange); + AFL_VERIFY(TEvGetObjectResponse::TryParseRange(strRange, range))("original", strRange); if (!!object) { AFL_DEBUG(NKikimrServices::S3_WRAPPER)("method", "GetObject")("id", key)("range", strRange)("object_exists", true); diff --git a/ydb/core/wrappers/s3_storage.cpp b/ydb/core/wrappers/s3_storage.cpp index 431c35da5d15..a623f4875675 100644 --- a/ydb/core/wrappers/s3_storage.cpp +++ b/ydb/core/wrappers/s3_storage.cpp @@ -120,26 +120,6 @@ class TOutputStreamContext: public TGenericContext { } }; - static bool TryParseRange(const TString& str, std::pair& range) { - TStringBuf buf(str); - if (!buf.SkipPrefix("bytes=")) { - return false; - } - - ui64 start; - if (!TryFromString(buf.NextTok('-'), start)) { - return false; - } - - ui64 end; - if (!TryFromString(buf, end)) { - return false; - } - - range = std::make_pair(start, end); - return true; - } - public: using TGenericContext::TGenericContext; @@ -147,7 +127,7 @@ class TOutputStreamContext: public TGenericContext { auto& request = ev->Get()->Request; std::pair range; - Y_ABORT_UNLESS(request.RangeHasBeenSet() && TryParseRange(request.GetRange().c_str(), range)); + Y_ABORT_UNLESS(request.RangeHasBeenSet() && TEvGetObjectResponse::TryParseRange(request.GetRange().c_str(), range)); Range = range; Buffer.resize(range.second - range.first + 1); diff --git a/ydb/core/wrappers/unavailable_storage.cpp b/ydb/core/wrappers/unavailable_storage.cpp new file mode 100644 index 000000000000..772a55909d65 --- /dev/null +++ b/ydb/core/wrappers/unavailable_storage.cpp @@ -0,0 +1,4 @@ +#include "unavailable_storage.h" + +namespace NKikimr::NWrappers::NExternalStorage { +} \ No newline at end of file diff --git a/ydb/core/wrappers/unavailable_storage.h b/ydb/core/wrappers/unavailable_storage.h new file mode 100644 index 000000000000..f10ce0f01988 --- /dev/null +++ b/ydb/core/wrappers/unavailable_storage.h @@ -0,0 +1,83 @@ +#pragma once + +#ifndef KIKIMR_DISABLE_S3_OPS + +#include +#include + +namespace NKikimr::NWrappers::NExternalStorage { + +class TUnavailableExternalStorageOperator: public IExternalStorageOperator { +private: + const TString Exception; + const TString Reason; + + template + void ExecuteImpl(TRequestPtr& ev) const { + const Aws::S3::S3Error error = Aws::S3::S3Error( + Aws::Client::AWSError(Aws::Client::CoreErrors::SERVICE_UNAVAILABLE, Exception, Reason, false)); + std::unique_ptr response; + constexpr bool hasKey = requires(const TRequestPtr& r) { r->Get()->GetRequest().GetKey(); }; + constexpr bool hasRange = std::is_same_v; + if constexpr (hasRange) { + std::pair range; + AFL_VERIFY(TResponse::TryParseRange(TString(ev->Get()->GetRequest().GetRange()), range))( + "original", ev->Get()->GetRequest().GetRange()); + response = std::make_unique(TString(ev->Get()->GetRequest().GetKey()), range, error); + } else if constexpr (hasKey) { + response = std::make_unique(TString(ev->Get()->GetRequest().GetKey()), error); + } else { + response = std::make_unique(error); + } + ReplyAdapter.Reply(ev->Sender, std::move(response)); + } + + virtual TString DoDebugString() const override { + return "type:UNAVAILABLE;"; + } + +public: + TUnavailableExternalStorageOperator(const TString& exceptionName, const TString& unavailabilityReason) + : Exception(exceptionName) + , Reason(unavailabilityReason) { + } + virtual void Execute(TEvCheckObjectExistsRequest::TPtr& ev) const override { + ExecuteImpl(ev); + } + virtual void Execute(TEvListObjectsRequest::TPtr& ev) const override { + ExecuteImpl(ev); + } + virtual void Execute(TEvGetObjectRequest::TPtr& ev) const override { + ExecuteImpl(ev); + } + virtual void Execute(TEvHeadObjectRequest::TPtr& ev) const override { + ExecuteImpl(ev); + } + virtual void Execute(TEvPutObjectRequest::TPtr& ev) const override { + ExecuteImpl(ev); + } + virtual void Execute(TEvDeleteObjectRequest::TPtr& ev) const override { + ExecuteImpl(ev); + } + virtual void Execute(TEvDeleteObjectsRequest::TPtr& ev) const override { + ExecuteImpl(ev); + } + virtual void Execute(TEvCreateMultipartUploadRequest::TPtr& ev) const override { + ExecuteImpl(ev); + } + virtual void Execute(TEvUploadPartRequest::TPtr& ev) const override { + ExecuteImpl(ev); + } + virtual void Execute(TEvCompleteMultipartUploadRequest::TPtr& ev) const override { + ExecuteImpl(ev); + } + virtual void Execute(TEvAbortMultipartUploadRequest::TPtr& ev) const override { + ExecuteImpl(ev); + } + virtual void Execute(TEvUploadPartCopyRequest::TPtr& ev) const override { + ExecuteImpl(ev); + } +}; + +#endif // KIKIMR_DISABLE_S3_OPS +} diff --git a/ydb/core/wrappers/ya.make b/ydb/core/wrappers/ya.make index 1764c7a670e0..d980ab7f7757 100644 --- a/ydb/core/wrappers/ya.make +++ b/ydb/core/wrappers/ya.make @@ -12,6 +12,7 @@ ELSE() abstract.cpp fake_storage.cpp fake_storage_config.cpp + unavailable_storage.cpp ) PEERDIR( contrib/libs/aws-sdk-cpp/aws-cpp-sdk-s3 From 9fe3e88a140e03e94b53b305a74bd94c174268cc Mon Sep 17 00:00:00 2001 From: Semyon Yentsov Date: Thu, 23 Jan 2025 19:00:00 +0300 Subject: [PATCH 2/5] fix data race --- ydb/core/tx/columnshard/blobs_action/tier/storage.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/ydb/core/tx/columnshard/blobs_action/tier/storage.cpp b/ydb/core/tx/columnshard/blobs_action/tier/storage.cpp index 4184a47fce44..20a23bb0c0c0 100644 --- a/ydb/core/tx/columnshard/blobs_action/tier/storage.cpp +++ b/ydb/core/tx/columnshard/blobs_action/tier/storage.cpp @@ -71,8 +71,6 @@ void TOperator::InitNewExternalOperator(const NColumnShard::NTiers::TManager* ti AFL_VERIFY(extStorageConfig); extStorageOperator = extStorageConfig->ConstructStorageOperator(false); } else { - TGuard changeLock(ChangeOperatorLock); - CurrentS3Settings.reset(); extStorageOperator = std::make_shared( NWrappers::NExternalStorage::TUnavailableExternalStorageOperator( "tier_unavailable", TStringBuilder() << "Tier is not configured: " << GetStorageId())); From 66b075ab8c28e9a1b8f94422bf851d7f57d44288 Mon Sep 17 00:00:00 2001 From: Semyon Yentsov Date: Thu, 23 Jan 2025 19:16:44 +0300 Subject: [PATCH 3/5] fix invalid eds config case --- ydb/core/tx/tiering/fetcher.h | 8 +------- ydb/core/tx/tiering/manager.cpp | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/ydb/core/tx/tiering/fetcher.h b/ydb/core/tx/tiering/fetcher.h index 38fd08655374..86e4361cf44b 100644 --- a/ydb/core/tx/tiering/fetcher.h +++ b/ydb/core/tx/tiering/fetcher.h @@ -69,7 +69,6 @@ class TEvSchemeObjectResolutionFailed: public TEventLocal { private: TActorId Owner; - THashSet WatchedPathIds; private: THolder BuildSchemeCacheNavigateRequest( @@ -103,11 +102,7 @@ class TSchemeObjectWatcher: public TActorBootstrapped { } void WatchPathId(const TPathId& pathId) { - if (WatchedPathIds.emplace(pathId).second) { - Send(MakeSchemeCacheID(), new TEvTxProxySchemeCache::TEvWatchPathId(pathId), IEventHandle::FlagTrackDelivery); - } else { - AFL_DEBUG(NKikimrServices::TX_TIERING)("event", "skip_watch_path_id")("reason", "already_subscribed")("path", pathId.ToString()); - } + Send(MakeSchemeCacheID(), new TEvTxProxySchemeCache::TEvWatchPathId(pathId), IEventHandle::FlagTrackDelivery); } void Handle(TEvTxProxySchemeCache::TEvNavigateKeySetResult::TPtr& ev) { @@ -152,7 +147,6 @@ class TSchemeObjectWatcher: public TActorBootstrapped { const TString name = TString(ExtractBase(record->Path)); const TString storageDir = TString(ExtractParent(record->Path)); AFL_DEBUG(NKikimrServices::TX_TIERING)("event", "object_deleted")("path", record->Path); - AFL_VERIFY(WatchedPathIds.erase(record->PathId)); Send(Owner, new NTiers::TEvNotifySchemeObjectDeleted(record->Path)); } diff --git a/ydb/core/tx/tiering/manager.cpp b/ydb/core/tx/tiering/manager.cpp index 864e9be48b9f..add3368f009a 100644 --- a/ydb/core/tx/tiering/manager.cpp +++ b/ydb/core/tx/tiering/manager.cpp @@ -85,7 +85,7 @@ class TTiersManager::TActor: public TActorBootstrapped { } Owner->UpdateTierConfig(tier, tierId); } else { - AFL_WARN(false)("error", "invalid_object_type")("type", static_cast(description.GetSelf().GetPathType()))("path", tierId.GetConfigPath()); + AFL_WARN(NKikimrServices::TX_TIERING)("error", "invalid_object_type")("type", static_cast(description.GetSelf().GetPathType()))("path", tierId.GetConfigPath()); Owner->UpdateTierConfig(std::nullopt, tierId); } } From 2b0bc69f8732a98e2702ebf6e80c1dfdf40532ca Mon Sep 17 00:00:00 2001 From: Semyon Yentsov Date: Thu, 23 Jan 2025 19:40:34 +0300 Subject: [PATCH 4/5] nit --- ydb/core/wrappers/unavailable_storage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ydb/core/wrappers/unavailable_storage.cpp b/ydb/core/wrappers/unavailable_storage.cpp index 772a55909d65..da0cbbb0b7aa 100644 --- a/ydb/core/wrappers/unavailable_storage.cpp +++ b/ydb/core/wrappers/unavailable_storage.cpp @@ -1,4 +1,4 @@ #include "unavailable_storage.h" namespace NKikimr::NWrappers::NExternalStorage { -} \ No newline at end of file +} From 4e429560158972f328b8859068fae81584308349 Mon Sep 17 00:00:00 2001 From: Semyon Yentsov Date: Thu, 23 Jan 2025 19:49:35 +0300 Subject: [PATCH 5/5] fix text compilation --- ydb/core/tx/tiering/ut/ut_tiers.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ydb/core/tx/tiering/ut/ut_tiers.cpp b/ydb/core/tx/tiering/ut/ut_tiers.cpp index 89439c8d006e..eb091dbaa98a 100644 --- a/ydb/core/tx/tiering/ut/ut_tiers.cpp +++ b/ydb/core/tx/tiering/ut/ut_tiers.cpp @@ -174,14 +174,14 @@ Y_UNIT_TEST_SUITE(ColumnShardTiers) { return false; } THashSet notFoundTiers = ExpectedTiers; - for (const auto& [id, config] : Manager->GetTierConfigs()) { + for (const auto& [id, config] : Manager->GetTiers()) { notFoundTiers.erase(id); } return notFoundTiers.empty(); } - const THashMap& GetTierConfigs() { - return Manager->GetTierConfigs(); + const THashMap& GetTierConfigs() { + return Manager->GetTiers(); } void Bootstrap() { @@ -257,7 +257,7 @@ Y_UNIT_TEST_SUITE(ColumnShardTiers) { TTestCSEmulator* emulator = new TTestCSEmulator({ "/Root/tier1", "/Root/tier2" }); runtime.Register(emulator); emulator->CheckRuntime(runtime); - UNIT_ASSERT_EQUAL(emulator->GetTierConfigs().at(NTiers::TExternalStorageId("/Root/tier1")).GetProtoConfig().GetBucket(), "abc"); + UNIT_ASSERT_EQUAL(emulator->GetTierConfigs().at(NTiers::TExternalStorageId("/Root/tier1")).GetConfigVerified().GetProtoConfig().GetBucket(), "abc"); } Cerr << "Initialization finished" << Endl; { @@ -313,7 +313,7 @@ Y_UNIT_TEST_SUITE(ColumnShardTiers) { TTestCSEmulator* emulator = new TTestCSEmulator({ "/Root/tier1" }); runtime.Register(emulator); emulator->CheckRuntime(runtime); - UNIT_ASSERT_EQUAL(emulator->GetTierConfigs().at(NTiers::TExternalStorageId("/Root/tier1")).GetProtoConfig().GetBucket(), "abc1"); + UNIT_ASSERT_EQUAL(emulator->GetTierConfigs().at(NTiers::TExternalStorageId("/Root/tier1")).GetConfigVerified().GetProtoConfig().GetBucket(), "abc1"); } lHelper.CreateExternalDataSource("/Root/tier2", "http://fake.fake/abc2"); @@ -321,8 +321,8 @@ Y_UNIT_TEST_SUITE(ColumnShardTiers) { TTestCSEmulator* emulator = new TTestCSEmulator({ "/Root/tier1", "/Root/tier2" }); runtime.Register(emulator); emulator->CheckRuntime(runtime); - UNIT_ASSERT_EQUAL(emulator->GetTierConfigs().at(NTiers::TExternalStorageId("/Root/tier1")).GetProtoConfig().GetBucket(), "abc1"); - UNIT_ASSERT_EQUAL(emulator->GetTierConfigs().at(NTiers::TExternalStorageId("/Root/tier2")).GetProtoConfig().GetBucket(), "abc2"); + UNIT_ASSERT_EQUAL(emulator->GetTierConfigs().at(NTiers::TExternalStorageId("/Root/tier1")).GetConfigVerified().GetProtoConfig().GetBucket(), "abc1"); + UNIT_ASSERT_EQUAL(emulator->GetTierConfigs().at(NTiers::TExternalStorageId("/Root/tier2")).GetConfigVerified().GetProtoConfig().GetBucket(), "abc2"); } lHelper.CreateTestOlapTable("olapTable"); @@ -438,7 +438,7 @@ Y_UNIT_TEST_SUITE(ColumnShardTiers) { TTestCSEmulator* emulator = new TTestCSEmulator({ "/Root/tier1", "/Root/tier2" }); runtime.Register(emulator); emulator->CheckRuntime(runtime); - UNIT_ASSERT_VALUES_EQUAL(emulator->GetTierConfigs().at(NTiers::TExternalStorageId("/Root/tier1")).GetProtoConfig().GetEndpoint(), TierEndpoint); + UNIT_ASSERT_VALUES_EQUAL(emulator->GetTierConfigs().at(NTiers::TExternalStorageId("/Root/tier1")).GetConfigVerified().GetProtoConfig().GetEndpoint(), TierEndpoint); } lHelper.CreateTestOlapTable("olapTable", 2);