Skip to content

Commit 9bc84e7

Browse files
authored
[25-2] Do not crash on unknown enum values (state, build kind) during index build (#26228)
2 parents 6f336d0 + 9ca167a commit 9bc84e7

File tree

3 files changed

+161
-2
lines changed

3 files changed

+161
-2
lines changed

ydb/core/tx/schemeshard/schemeshard_info_types.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2440,6 +2440,47 @@ void TIndexBuildInfo::AddParent(const TSerializedTableRange& range, TShardIdx sh
24402440
Cluster2Shards.emplace_hint(itFrom, parentTo, TClusterShards{.From = parentFrom, .Shards = {shard}});
24412441
}
24422442

2443+
bool TIndexBuildInfo::IsValidState(EState value)
2444+
{
2445+
switch (value) {
2446+
case EState::Invalid:
2447+
case EState::AlterMainTable:
2448+
case EState::Locking:
2449+
case EState::GatheringStatistics:
2450+
case EState::Initiating:
2451+
case EState::Filling:
2452+
case EState::DropBuild:
2453+
case EState::CreateBuild:
2454+
case EState::LockBuild:
2455+
case EState::Applying:
2456+
case EState::Unlocking:
2457+
case EState::Done:
2458+
case EState::Cancellation_Applying:
2459+
case EState::Cancellation_Unlocking:
2460+
case EState::Cancellation_DroppingColumns:
2461+
case EState::Cancelled:
2462+
case EState::Rejection_Applying:
2463+
case EState::Rejection_Unlocking:
2464+
case EState::Rejection_DroppingColumns:
2465+
case EState::Rejected:
2466+
return true;
2467+
}
2468+
return false;
2469+
}
2470+
2471+
bool TIndexBuildInfo::IsValidBuildKind(EBuildKind value)
2472+
{
2473+
switch (value) {
2474+
case EBuildKind::BuildKindUnspecified:
2475+
case EBuildKind::BuildSecondaryIndex:
2476+
case EBuildKind::BuildVectorIndex:
2477+
case EBuildKind::BuildPrefixedVectorIndex:
2478+
case EBuildKind::BuildColumns:
2479+
return true;
2480+
}
2481+
return false;
2482+
}
2483+
24432484
TColumnFamiliesMerger::TColumnFamiliesMerger(NKikimrSchemeOp::TPartitionConfig &container)
24442485
: Container(container)
24452486
, DeduplicationById(TPartitionConfigMerger::DeduplicateColumnFamiliesById(Container))

ydb/core/tx/schemeshard/schemeshard_info_types.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3290,6 +3290,9 @@ struct TIndexBuildInfo: public TSimpleRefCount<TIndexBuildInfo> {
32903290
return result;
32913291
}
32923292

3293+
static bool IsValidState(EState value);
3294+
static bool IsValidBuildKind(EBuildKind value);
3295+
32933296
struct TClusterShards {
32943297
NTableIndex::TClusterId From = std::numeric_limits<NTableIndex::TClusterId>::max();
32953298
std::vector<TShardIdx> Shards;
@@ -3347,16 +3350,27 @@ struct TIndexBuildInfo: public TSimpleRefCount<TIndexBuildInfo> {
33473350
indexInfo->Id = id;
33483351
indexInfo->Uid = uid;
33493352

3350-
indexInfo->State = TIndexBuildInfo::EState(
3351-
row.template GetValue<Schema::IndexBuild::State>());
33523353
indexInfo->Issue =
33533354
row.template GetValueOrDefault<Schema::IndexBuild::Issue>();
33543355

3356+
indexInfo->State = TIndexBuildInfo::EState(
3357+
row.template GetValue<Schema::IndexBuild::State>());
3358+
if (!IsValidState(indexInfo->State)) {
3359+
indexInfo->IsBroken = true;
3360+
indexInfo->AddIssue(TStringBuilder() << "Unknown build state: " << ui32(indexInfo->State));
3361+
indexInfo->State = TIndexBuildInfo::EState::Invalid;
3362+
}
3363+
33553364
// note: please note that here we specify BuildSecondaryIndex as operation default,
33563365
// because previously this table was dedicated for build secondary index operations only.
33573366
indexInfo->BuildKind = TIndexBuildInfo::EBuildKind(
33583367
row.template GetValueOrDefault<Schema::IndexBuild::BuildKind>(
33593368
ui32(TIndexBuildInfo::EBuildKind::BuildSecondaryIndex)));
3369+
if (!IsValidBuildKind(indexInfo->BuildKind)) {
3370+
indexInfo->IsBroken = true;
3371+
indexInfo->AddIssue(TStringBuilder() << "Unknown build kind: " << ui32(indexInfo->BuildKind));
3372+
indexInfo->BuildKind = TIndexBuildInfo::EBuildKind::BuildKindUnspecified;
3373+
}
33603374

33613375
indexInfo->DomainPathId =
33623376
TPathId(row.template GetValue<Schema::IndexBuild::DomainOwnerId>(),

ydb/core/tx/schemeshard/ut_index_build/ut_vector_index_build.cpp

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,4 +1332,108 @@ Y_UNIT_TEST_SUITE(VectorIndexBuildTest) {
13321332
UNIT_ASSERT_STRING_CONTAINS(buildIndexOperation.DebugString(), "Processed: UploadRows: 0 UploadBytes: 0 ReadRows: 0 ReadBytes: 0");
13331333
}
13341334
}
1335+
1336+
Y_UNIT_TEST(UnknownState) {
1337+
TTestBasicRuntime runtime;
1338+
TTestEnv env(runtime);
1339+
ui64 txId = 100;
1340+
1341+
runtime.SetLogPriority(NKikimrServices::TX_DATASHARD, NLog::PRI_TRACE);
1342+
runtime.SetLogPriority(NKikimrServices::BUILD_INDEX, NLog::PRI_TRACE);
1343+
1344+
TestCreateTable(runtime, ++txId, "/MyRoot", R"(
1345+
Name: "vectors"
1346+
Columns { Name: "id" Type: "Uint64" }
1347+
Columns { Name: "embedding" Type: "String" }
1348+
KeyColumnNames: [ "id" ]
1349+
)");
1350+
env.TestWaitNotification(runtime, txId);
1351+
1352+
NYdb::NTable::TGlobalIndexSettings globalIndexSettings;
1353+
1354+
std::unique_ptr<NYdb::NTable::TKMeansTreeSettings> kmeansTreeSettings;
1355+
{
1356+
Ydb::Table::KMeansTreeSettings proto;
1357+
UNIT_ASSERT(google::protobuf::TextFormat::ParseFromString(R"(
1358+
settings {
1359+
metric: DISTANCE_COSINE
1360+
vector_type: VECTOR_TYPE_FLOAT
1361+
vector_dimension: 1024
1362+
}
1363+
levels: 5
1364+
clusters: 4
1365+
)", &proto));
1366+
using T = NYdb::NTable::TKMeansTreeSettings;
1367+
kmeansTreeSettings = std::make_unique<T>(T::FromProto(proto));
1368+
}
1369+
1370+
TBlockEvents<TEvDataShard::TEvLocalKMeansRequest> kmeansBlocker(runtime, [&](const auto& ) {
1371+
return true;
1372+
});
1373+
1374+
const ui64 buildIndexTx = ++txId;
1375+
AsyncBuildVectorIndex(runtime, buildIndexTx, TTestTxConfig::SchemeShard, "/MyRoot", "/MyRoot/vectors", "index1", {"embedding"});
1376+
1377+
runtime.WaitFor("LocalKMeansRequest", [&]{ return kmeansBlocker.size(); });
1378+
1379+
{
1380+
// set unknown State value
1381+
TString writeQuery = Sprintf(R"(
1382+
(
1383+
(let key '( '('Id (Uint64 '%lu)) ) )
1384+
(let value '('('State (Uint32 '999999)) ) )
1385+
(return (AsList (UpdateRow 'IndexBuild key value) ))
1386+
)
1387+
)", buildIndexTx);
1388+
NKikimrMiniKQL::TResult result;
1389+
TString err;
1390+
NKikimrProto::EReplyStatus status = LocalMiniKQL(runtime, TTestTxConfig::SchemeShard, writeQuery, result, err);
1391+
UNIT_ASSERT_VALUES_EQUAL_C(status, NKikimrProto::EReplyStatus::OK, err);
1392+
}
1393+
1394+
Cerr << "... rebooting scheme shard" << Endl;
1395+
RebootTablet(runtime, TTestTxConfig::SchemeShard, runtime.AllocateEdgeActor());
1396+
kmeansBlocker.Stop().Unblock();
1397+
1398+
{
1399+
auto buildIndexOperation = TestGetBuildIndex(runtime, TTestTxConfig::SchemeShard, "/MyRoot", buildIndexTx);
1400+
auto buildIndexHtml = TestGetBuildIndexHtml(runtime, TTestTxConfig::SchemeShard, buildIndexTx);
1401+
UNIT_ASSERT_VALUES_EQUAL_C(
1402+
buildIndexOperation.GetIndexBuild().GetState(), Ydb::Table::IndexBuildState::STATE_UNSPECIFIED,
1403+
buildIndexOperation.DebugString()
1404+
);
1405+
UNIT_ASSERT_STRING_CONTAINS(buildIndexOperation.DebugString(), "Unknown build state");
1406+
UNIT_ASSERT_STRING_CONTAINS(buildIndexHtml, "IsBroken: 1");
1407+
}
1408+
1409+
{
1410+
// set a known State but unknown BuildKind
1411+
TString writeQuery = Sprintf(R"(
1412+
(
1413+
(let key '( '('Id (Uint64 '%lu)) ) )
1414+
(let value '('('State (Uint32 '40)) '('BuildKind (Uint32 '999999)) ) )
1415+
(return (AsList (UpdateRow 'IndexBuild key value) ))
1416+
)
1417+
)", buildIndexTx);
1418+
NKikimrMiniKQL::TResult result;
1419+
TString err;
1420+
NKikimrProto::EReplyStatus status = LocalMiniKQL(runtime, TTestTxConfig::SchemeShard, writeQuery, result, err);
1421+
UNIT_ASSERT_VALUES_EQUAL_C(status, NKikimrProto::EReplyStatus::OK, err);
1422+
}
1423+
1424+
Cerr << "... rebooting scheme shard" << Endl;
1425+
RebootTablet(runtime, TTestTxConfig::SchemeShard, runtime.AllocateEdgeActor());
1426+
1427+
{
1428+
auto buildIndexOperation = TestGetBuildIndex(runtime, TTestTxConfig::SchemeShard, "/MyRoot", buildIndexTx);
1429+
auto buildIndexHtml = TestGetBuildIndexHtml(runtime, TTestTxConfig::SchemeShard, buildIndexTx);
1430+
UNIT_ASSERT_VALUES_EQUAL_C(
1431+
buildIndexOperation.GetIndexBuild().GetState(), Ydb::Table::IndexBuildState::STATE_TRANSFERING_DATA,
1432+
buildIndexOperation.DebugString()
1433+
);
1434+
UNIT_ASSERT_STRING_CONTAINS(buildIndexOperation.DebugString(), "Unknown build kind");
1435+
UNIT_ASSERT_STRING_CONTAINS(buildIndexHtml, "IsBroken: 1");
1436+
}
1437+
}
1438+
13351439
}

0 commit comments

Comments
 (0)