Skip to content

Commit 176a6e1

Browse files
obdevob-robot
authored andcommitted
[CP] [vector index] fix timer scan full schema issue
1 parent c42e5f7 commit 176a6e1

10 files changed

Lines changed: 152 additions & 79 deletions

src/share/schema/ob_schema_getter_guard.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6310,6 +6310,51 @@ GET_SIMPLE_SCHEMAS_IN_DATABASE_FUNC_DEFINE(package, ObSimplePackageSchema);
63106310
GET_SIMPLE_SCHEMAS_IN_DATABASE_FUNC_DEFINE(routine, ObSimpleRoutineSchema);
63116311
GET_SIMPLE_SCHEMAS_IN_DATABASE_FUNC_DEFINE(mock_fk_parent_table, ObSimpleMockFKParentTableSchema);
63126312

6313+
int ObSchemaGetterGuard::get_vector_info_index_ids_in_tenant(const uint64_t tenant_id,
6314+
bool &has_ivf_index,
6315+
ObIArray<uint64_t> &table_ids)
6316+
{
6317+
int ret = OB_SUCCESS;
6318+
const ObSchemaMgr *mgr = NULL;
6319+
ObArray<const ObSimpleTableSchemaV2 *> schemas;
6320+
table_ids.reset();
6321+
has_ivf_index = false;
6322+
if (!check_inner_stat()) {
6323+
ret = OB_INNER_STAT_ERROR;
6324+
LOG_WARN("inner stat error", KR(ret));
6325+
} else if (OB_INVALID_ID == tenant_id) {
6326+
ret = OB_INVALID_ARGUMENT;
6327+
LOG_WARN("invalid argument", KR(ret), K(tenant_id));
6328+
} else if (OB_FAIL(check_tenant_schema_guard(tenant_id))) {
6329+
LOG_WARN("fail to check tenant schema guard", KR(ret), K(tenant_id), K_(tenant_id));
6330+
} else if (OB_FAIL(get_schema_mgr(tenant_id, mgr))) {
6331+
if (OB_TENANT_NOT_EXIST == ret) {
6332+
ret = ignore_tenant_not_exist_error(tenant_id) ? OB_SUCCESS : ret;
6333+
}
6334+
if (OB_FAIL(ret)) {
6335+
LOG_WARN("fail to get schema mgr", KR(ret), K(tenant_id));
6336+
}
6337+
} else if (OB_ISNULL(mgr)) {
6338+
ret = OB_SCHEMA_EAGAIN;
6339+
LOG_WARN("get simple schema in lazy mode not supported", KR(ret), K(tenant_id));
6340+
} else if (OB_FAIL(mgr->get_vector_index_schemas_in_tenant(tenant_id, schemas))) {
6341+
LOG_WARN("get table schemas in tenant failed", KR(ret), K(tenant_id));
6342+
} else {
6343+
FOREACH_CNT_X(schema, schemas, OB_SUCC(ret)) {
6344+
const ObSimpleTableSchemaV2 *tmp_schema = *schema;
6345+
if (OB_ISNULL(tmp_schema)) {
6346+
ret = OB_ERR_UNEXPECTED;
6347+
LOG_WARN("NULL ptr", KR(ret), KP(tmp_schema));
6348+
} else if (OB_FAIL(table_ids.push_back(tmp_schema->get_table_id()))) {
6349+
LOG_WARN("push back table id failed", KR(ret));
6350+
} else if (!has_ivf_index && tmp_schema->is_vec_ivf_index()) {
6351+
has_ivf_index = true;
6352+
}
6353+
}
6354+
}
6355+
return ret;
6356+
}
6357+
63136358
} //end of namespace schema
63146359
} //end of namespace share
63156360
} //end of namespace oceanbase

src/share/schema/ob_schema_getter_guard.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,10 @@ typedef common::ObSEArray<ObSchemaMgrInfo, DEFAULT_RESERVE_SIZE> SchemaMgrInfos;
897897
GET_SIMPLE_SCHEMAS_IN_DATABASE_FUNC_DECLARE(routine, ObSimpleRoutineSchema);
898898
GET_SIMPLE_SCHEMAS_IN_DATABASE_FUNC_DECLARE(mock_fk_parent_table, ObSimpleMockFKParentTableSchema);
899899

900+
int get_vector_info_index_ids_in_tenant(const uint64_t tenant_id,
901+
bool &has_ivf_index,
902+
ObIArray<uint64_t> &table_ids);
903+
900904
int check_routine_priv(const ObSessionPrivInfo &session_priv,
901905
const common::ObIArray<uint64_t> &enable_role_id_array,
902906
const ObNeedPriv &routine_need_priv);

src/share/schema/ob_schema_mgr.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3866,6 +3866,38 @@ int ObSchemaMgr::get_table_schemas_in_tenant(
38663866
return ret;
38673867
}
38683868

3869+
int ObSchemaMgr::get_vector_index_schemas_in_tenant(
3870+
const uint64_t tenant_id,
3871+
ObIArray<const ObSimpleTableSchemaV2*> &schema_array) const
3872+
{
3873+
int ret = OB_SUCCESS;
3874+
schema_array.reset();
3875+
if (!check_inner_stat()) {
3876+
ret = OB_NOT_INIT;
3877+
LOG_WARN("not init", K(ret));
3878+
} else if (OB_INVALID_ID == tenant_id) {
3879+
ret = OB_INVALID_ARGUMENT;
3880+
LOG_WARN("invalid argument", K(ret), K(tenant_id));
3881+
} else {
3882+
const ObSimpleTableSchemaV2 *schema = NULL;
3883+
ObTenantTableId tenant_index_schema_id_lower(tenant_id, OB_MIN_ID);
3884+
ConstTableIterator iter = index_infos_.lower_bound(tenant_index_schema_id_lower,
3885+
compare_with_tenant_table_id);
3886+
bool is_stop = false;
3887+
for (; OB_SUCC(ret) && iter != index_infos_.end() && !is_stop; iter++) {
3888+
if (OB_ISNULL(schema = *iter)) {
3889+
ret = OB_ERR_UNEXPECTED;
3890+
LOG_WARN("NULL ptr", K(ret), KP(schema));
3891+
} else if (tenant_id != schema->get_tenant_id()) {
3892+
is_stop = true;
3893+
} else if (schema->is_vec_index() && OB_FAIL(schema_array.push_back(schema))) {
3894+
LOG_WARN("failed to push back SCHEMA schema", K(ret));
3895+
}
3896+
}
3897+
}
3898+
return ret;
3899+
}
3900+
38693901
int ObSchemaMgr::check_database_exists_in_tablegroup(
38703902
const uint64_t tenant_id,
38713903
const uint64_t tablegroup_id,

src/share/schema/ob_schema_mgr.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,9 @@ typedef common::hash::ObPointerHashMap<ObConstraintInfoHashWrapper, ObSimpleCons
686686
const uint64_t tenant_id,
687687
common::ObIArray<const ObSimpleTableSchemaV2 *> &schema_array) const;
688688
#undef GET_TABLE_SCHEMAS_IN_DST_SCHEMA_FUNC_DECLARE
689+
int get_vector_index_schemas_in_tenant(
690+
const uint64_t tenant_id,
691+
common::ObIArray<const ObSimpleTableSchemaV2 *> &schema_array) const;
689692
int get_primary_table_schema_in_tablegroup(
690693
const uint64_t tenant_id,
691694
const uint64_t tablegroup_id,

src/share/vector_index/ob_ivf_async_task_executor.cpp

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -249,46 +249,6 @@ bool ObIvfAsyncTaskExector::check_operation_allow()
249249
return bret;
250250
}
251251

252-
int ObIvfAsyncTaskExector::check_has_ivf_index(bool &has_ivf_index)
253-
{
254-
int ret = OB_SUCCESS;
255-
ObSEArray<uint64_t, DEFAULT_TABLE_ID_ARRAY_SIZE> table_id_array;
256-
ObMemAttr memattr(tenant_id_, "IvfTaskExec");
257-
if (OB_FAIL(ObTTLUtil::get_tenant_table_ids(tenant_id_, table_id_array))) {
258-
LOG_WARN("fail to get tenant table ids", KR(ret), K_(tenant_id));
259-
}
260-
261-
int64_t start_idx = 0;
262-
int64_t end_idx = 0;
263-
has_ivf_index = false;
264-
while (OB_SUCC(ret) && start_idx < table_id_array.count() && !has_ivf_index) {
265-
ObSchemaGetterGuard schema_guard;
266-
start_idx = end_idx;
267-
end_idx = MIN(table_id_array.count(), start_idx + DEFAULT_TABLE_ID_ARRAY_SIZE);
268-
269-
if (OB_FAIL(ObMultiVersionSchemaService::get_instance().get_tenant_schema_guard(
270-
tenant_id_, schema_guard))) {
271-
LOG_WARN("fail to get schema guard", KR(ret), K_(tenant_id));
272-
}
273-
274-
const ObTableSchema *table_schema = nullptr;
275-
for (int64_t idx = start_idx; OB_SUCC(ret) && idx < end_idx && !has_ivf_index; ++idx) {
276-
const int64_t table_id = table_id_array.at(idx);
277-
if (is_sys_table(table_id)) {
278-
// do nothing
279-
} else if (OB_FAIL(schema_guard.get_table_schema(tenant_id_, table_id, table_schema))) {
280-
LOG_WARN("failed to get simple schema", KR(ret), K(table_id));
281-
} else if (OB_ISNULL(table_schema)) {
282-
ret = OB_TABLE_NOT_EXIST;
283-
LOG_WARN("table schema is null", KR(ret), K(table_id), K_(tenant_id));
284-
} else if (table_schema->is_vec_ivf_index()) {
285-
has_ivf_index = true;
286-
}
287-
}
288-
}
289-
return ret;
290-
}
291-
292252
int ObIvfAsyncTaskExector::check_and_set_thread_pool()
293253
{
294254
int ret = OB_SUCCESS;
@@ -305,11 +265,7 @@ int ObIvfAsyncTaskExector::check_and_set_thread_pool()
305265
ObIAllocator *allocator = index_ls_mgr->get_async_task_opt().get_allocator();
306266
ObVecIndexAsyncTaskHandler &thread_pool_handle =
307267
vector_index_service_->get_vec_async_task_handle();
308-
bool has_ivf_index = false;
309268
if (thread_pool_handle.get_tg_id() != INVALID_TG_ID) { // no need to init twice, skip
310-
} else if (OB_FAIL(check_has_ivf_index(has_ivf_index))) {
311-
LOG_WARN("fail to check has ivf index", K(ret));
312-
} else if (!has_ivf_index) { // no vector index exist, skip
313269
} else if (OB_FAIL(thread_pool_handle.init())) {
314270
LOG_WARN("fail to init vec async task handle", K(ret), K(tenant_id_));
315271
} else if (OB_FAIL(thread_pool_handle.start())) {

src/share/vector_index/ob_ivf_async_task_executor.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@ class ObIvfAsyncTaskExector final : public ObVecITaskExecutor
108108
};
109109

110110
bool check_operation_allow() override;
111-
int check_has_ivf_index(bool &has_ivf_index);
112111
int generate_aux_table_info_map(ObIvfAuxTableInfoMap &aux_table_info_map);
113112
int generate_aux_table_info_map(ObSchemaGetterGuard &schema_guard, const int64_t table_id,
114113
ObIvfAuxTableInfoMap &aux_table_info_map);

src/share/vector_index/ob_plugin_vector_index_scheduler.cpp

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ void ObPluginVectorIndexLoadScheduler::mark_tenant_need_check()
282282
LOG_DEBUG("finsh mark tenant need check", KR(ret), K(local_tenant_task_.need_check_));
283283
}
284284

285-
int ObPluginVectorIndexLoadScheduler::check_is_vector_index_table(const ObTableSchema &table_schema,
285+
int ObPluginVectorIndexLoadScheduler::check_is_vector_index_table(const ObSimpleTableSchemaV2 &table_schema,
286286
bool &is_vector_index_table,
287287
bool &is_shared_index_table)
288288
{
@@ -394,7 +394,7 @@ int ObPluginVectorIndexLoadScheduler::acquire_adapter_in_maintenance(
394394

395395
int ObPluginVectorIndexLoadScheduler::set_shared_table_info_in_maintenance(
396396
const int64_t table_id,
397-
const ObTableSchema *table_schema,
397+
const ObSimpleTableSchemaV2 *table_schema,
398398
ObVecIdxSharedTableInfoMap &shared_table_info_map)
399399
{
400400
int ret = OB_SUCCESS;
@@ -451,15 +451,22 @@ int ObPluginVectorIndexLoadScheduler::set_shared_table_info_in_maintenance(
451451
return ret;
452452
}
453453

454+
int ObPluginVectorIndexLoadScheduler::check_has_vector_index(bool &has_ivf_index, ObIArray<uint64_t> &vec_table_id_array)
455+
{
456+
int ret = OB_SUCCESS;
457+
if (OB_FAIL(ObPluginVectorIndexUtils::get_tenant_vector_index_ids(tenant_id_, has_ivf_index, vec_table_id_array))) {
458+
LOG_WARN("fail to get tenant table ids", KR(ret), K_(tenant_id));
459+
}
460+
return ret;
461+
}
454462

455463
// scan all vector tablet in current tenant/LS
456-
int ObPluginVectorIndexLoadScheduler::execute_adapter_maintenance()
464+
int ObPluginVectorIndexLoadScheduler::execute_adapter_maintenance(ObIArray<uint64_t> &vec_table_id_array)
457465
{
458466
int ret = OB_SUCCESS;
459467
ObTimeGuard guard("ObPluginVectorIndexLoadScheduler::check_and_generate_tablet_tasks",
460468
VEC_INDEX_LOAD_TIME_NORMAL_THRESHOLD);
461469
const schema::ObTableSchema *table_schema = nullptr;
462-
ObSEArray<uint64_t, DEFAULT_TABLE_ARRAY_SIZE> table_id_array;
463470

464471
ObVecIdxSharedTableInfoMap shared_table_info_map;
465472
ObMemAttr memattr(tenant_id_, "VecIdxInfo");
@@ -472,20 +479,18 @@ int ObPluginVectorIndexLoadScheduler::execute_adapter_maintenance()
472479

473480
if (current_memory_config_ != 0) { // has memory for new adapter
474481

475-
if (OB_FAIL(ObTTLUtil::get_tenant_table_ids(tenant_id_, table_id_array))) {
476-
LOG_WARN("fail to get tenant table ids", KR(ret), K_(tenant_id));
477-
} else if (!table_id_array.empty()
478-
&& OB_FAIL(shared_table_info_map.create(DEFAULT_TABLE_ARRAY_SIZE, memattr, memattr))) {
482+
if (!vec_table_id_array.empty()
483+
&& OB_FAIL(shared_table_info_map.create(DEFAULT_TABLE_ARRAY_SIZE, memattr, memattr))) {
479484
LOG_WARN("fail to create param map", KR(ret));
480485
}
481486

482487
int64_t start_idx = 0;
483488
int64_t end_idx = 0;
484489

485-
while (OB_SUCC(ret) && start_idx < table_id_array.count()) {
490+
while (OB_SUCC(ret) && start_idx < vec_table_id_array.count()) {
486491
ObSchemaGetterGuard schema_guard;
487492
start_idx = end_idx;
488-
end_idx = MIN(table_id_array.count(), start_idx + TBALE_GENERATE_BATCH_SIZE);
493+
end_idx = MIN(vec_table_id_array.count(), start_idx + TBALE_GENERATE_BATCH_SIZE);
489494

490495
bool is_vector_index = false;
491496
bool is_shared_index = false;
@@ -494,11 +499,11 @@ int ObPluginVectorIndexLoadScheduler::execute_adapter_maintenance()
494499
}
495500

496501
for (int64_t idx = start_idx; OB_SUCC(ret) && idx < end_idx; ++idx) {
497-
const int64_t table_id = table_id_array.at(idx);
498-
const ObTableSchema *table_schema = nullptr;
502+
const int64_t table_id = vec_table_id_array.at(idx);
503+
const ObSimpleTableSchemaV2 *table_schema = nullptr;
499504
if (is_sys_table(table_id)) {
500505
// do nothing
501-
} else if (OB_FAIL(schema_guard.get_table_schema(tenant_id_, table_id, table_schema))) {
506+
} else if (OB_FAIL(schema_guard.get_simple_table_schema(tenant_id_, table_id, table_schema))) {
502507
LOG_WARN("failed to get simple schema", KR(ret), K(table_id));
503508
} else if (OB_ISNULL(table_schema)) {
504509
ret = OB_TABLE_NOT_EXIST;
@@ -507,10 +512,17 @@ int ObPluginVectorIndexLoadScheduler::execute_adapter_maintenance()
507512
// do nothing
508513
} else if (OB_FAIL(check_is_vector_index_table(*table_schema, is_vector_index, is_shared_index))) {
509514
LOG_WARN("fail to check is vector index", KR(ret));
510-
} else if (is_vector_index
511-
&& OB_FAIL(acquire_adapter_in_maintenance(table_id, table_schema, shared_table_info_map))) {
512-
// for one vector_index table
513-
LOG_WARN("fail to create adapter in maintenance", KR(ret), K(table_id));
515+
} else if (is_vector_index) {
516+
const ObTableSchema *tmp_table_schema = nullptr;
517+
if (OB_FAIL(schema_guard.get_table_schema(tenant_id_, table_id, tmp_table_schema))) {
518+
LOG_WARN("failed to get simple schema", KR(ret), K(table_id));
519+
} else if (OB_ISNULL(tmp_table_schema)) {
520+
ret = OB_TABLE_NOT_EXIST;
521+
LOG_WARN("table schema is null", KR(ret), K(table_id), K_(tenant_id));
522+
} else if (OB_FAIL(acquire_adapter_in_maintenance(table_id, tmp_table_schema, shared_table_info_map))) {
523+
// for one vector_index table
524+
LOG_WARN("fail to create adapter in maintenance", KR(ret), K(table_id));
525+
}
514526
} else if (is_shared_index
515527
&& OB_FAIL(set_shared_table_info_in_maintenance(table_id,
516528
table_schema,
@@ -564,7 +576,7 @@ int read_tenant_task_status(uint64_t tenant_id,
564576
return ret;
565577
}
566578

567-
int ObPluginVectorIndexLoadScheduler::check_and_load_task_executors()
579+
int ObPluginVectorIndexLoadScheduler::check_and_load_task_executors(bool &has_ivf_index)
568580
{
569581
int ret = OB_SUCCESS;
570582
uint64_t task_trace_base_num = 0;
@@ -584,7 +596,7 @@ int ObPluginVectorIndexLoadScheduler::check_and_load_task_executors()
584596
if (OB_FAIL(ivf_task_exec_.check_schema_version_changed(schema_changed))) {
585597
//only when schema changed, load ivf task
586598
LOG_WARN("fail to check schema version changed", K(ret));
587-
} else if (!schema_changed) {
599+
} else if (!schema_changed || !has_ivf_index) {
588600
// schema not changed, only do cleanup if needed, skip thread pool check and task loading
589601
if (OB_FAIL(ivf_task_exec_.clear_old_task_ctx_if_need())) {
590602
LOG_WARN("fail to clear old ivf task ctx", K(ret));
@@ -606,7 +618,7 @@ int ObPluginVectorIndexLoadScheduler::check_and_load_task_executors()
606618
// read from sys table with tenant id, special table id & special tablet id, not implemented
607619
// 2. check if need mem load task
608620
// from log replay, or long time not processed
609-
int ObPluginVectorIndexLoadScheduler::reload_tenant_task()
621+
int ObPluginVectorIndexLoadScheduler::reload_tenant_task(bool &has_ivf_index)
610622
{
611623
int ret = OB_SUCCESS;
612624
ObVectorIndexTenantStatus tenant_task;
@@ -647,7 +659,7 @@ int ObPluginVectorIndexLoadScheduler::reload_tenant_task()
647659
// vector index async task
648660
int tmp_ret = OB_SUCCESS;
649661
if (is_stopped() || !is_leader_) { // skip
650-
} else if (OB_TMP_FAIL(check_and_load_task_executors())) {
662+
} else if (OB_TMP_FAIL(check_and_load_task_executors(has_ivf_index))) {
651663
LOG_WARN("fail to check and load task executors", K(tmp_ret));
652664
}
653665

@@ -938,7 +950,7 @@ int ObPluginVectorIndexLoadScheduler::check_ls_task_state(ObPluginVectorIndexMgr
938950
return ret;
939951
}
940952

941-
int ObPluginVectorIndexLoadScheduler::check_and_execute_adapter_maintenance_task(ObPluginVectorIndexMgr *&mgr)
953+
int ObPluginVectorIndexLoadScheduler::check_and_execute_adapter_maintenance_task(ObPluginVectorIndexMgr *&mgr, ObIArray<uint64_t> &vec_table_id_array)
942954
{
943955
int ret = OB_SUCCESS;
944956
bool need_check = false;
@@ -950,7 +962,7 @@ int ObPluginVectorIndexLoadScheduler::check_and_execute_adapter_maintenance_task
950962
} else if (OB_NOT_NULL(mgr) && OB_FAIL(check_index_adpter_exist(mgr))) {
951963
LOG_WARN("fail to check exist paritial index adapter", KR(ret));
952964
} else if (local_tenant_task_.need_check_) {
953-
if (OB_FAIL(execute_adapter_maintenance())) {
965+
if (OB_FAIL(execute_adapter_maintenance(vec_table_id_array))) {
954966
LOG_WARN("fail to generate tablet tasks", K_(tenant_id));
955967
}
956968
int tmp_ret = OB_SUCCESS;
@@ -1143,7 +1155,7 @@ int ObPluginVectorIndexLoadScheduler::start_task_executors()
11431155
return ret;
11441156
}
11451157

1146-
int ObPluginVectorIndexLoadScheduler::check_and_execute_tasks()
1158+
int ObPluginVectorIndexLoadScheduler::check_and_execute_tasks(ObIArray<uint64_t> &vec_table_id_array)
11471159
{
11481160
int ret = OB_SUCCESS;
11491161
ObTimeGuard guard("ObPluginVectorIndexLoadScheduler::check_and_handle_event",
@@ -1164,7 +1176,7 @@ int ObPluginVectorIndexLoadScheduler::check_and_execute_tasks()
11641176
} else {
11651177
// Notice: index_ls_mgr maybe null
11661178
// create / remove adapter, check need update & write mem sync log
1167-
if (can_schedule(ObVectorTaskScheduleType::ADAPTER_MAINTENANCE) && OB_FAIL(check_and_execute_adapter_maintenance_task(index_ls_mgr))) { // Tips: do merge
1179+
if (can_schedule(ObVectorTaskScheduleType::ADAPTER_MAINTENANCE) && OB_FAIL(check_and_execute_adapter_maintenance_task(index_ls_mgr, vec_table_id_array))) { // Tips: do merge
11681180
LOG_WARN("fail to check and execute adapter maintenance task",
11691181
KR(ret), K(tenant_id_), K(ls_->get_ls_id()));
11701182
}
@@ -1230,11 +1242,15 @@ void ObPluginVectorIndexLoadScheduler::run_task()
12301242
}
12311243
} else if (check_can_do_work()){
12321244
check_can_schedule();
1245+
bool has_ivf_index = false;
1246+
ObSEArray<uint64_t, DEFAULT_TABLE_ARRAY_SIZE> vec_table_id_array;
12331247
if (OB_FAIL(check_tenant_memory())) {
12341248
LOG_WARN("check vector index resource failed", KR(ret));
1235-
} else if (OB_FAIL(reload_tenant_task())) {
1249+
} else if (OB_FAIL(check_has_vector_index(has_ivf_index, vec_table_id_array))) {
1250+
LOG_WARN("check vector index schema failed", KR(ret));
1251+
} else if (OB_FAIL(reload_tenant_task(has_ivf_index))) {
12361252
LOG_WARN("fail to reload tenant task", KR(ret));
1237-
} else if (OB_FAIL(check_and_execute_tasks())) {
1253+
} else if (OB_FAIL(check_and_execute_tasks(vec_table_id_array))) {
12381254
LOG_WARN("fail to scan and handle all tenant event", KR(ret));
12391255
}
12401256
schedule_finish();

0 commit comments

Comments
 (0)