diff --git a/src/meta/meta_split_service.cpp b/src/meta/meta_split_service.cpp index a4821a3caf..adba629e17 100644 --- a/src/meta/meta_split_service.cpp +++ b/src/meta/meta_split_service.cpp @@ -127,7 +127,6 @@ void meta_split_service::do_start_partition_split(std::shared_ptr app _state->get_app_path(*app), std::move(value), on_write_storage_complete); } -// TODO(heyuchen): refactor this function void meta_split_service::register_child_on_meta(register_child_rpc rpc) { const auto &request = rpc.request(); @@ -166,7 +165,16 @@ void meta_split_service::register_child_on_meta(register_child_rpc rpc) return; } - // TODO(heyuchen): pause/cancel split check + if (child_gpid.get_partition_index() >= app->partition_count) { + derror_f( + "app({}) partition({}) register child({}) failed, partition split has been canceled", + app_name, + parent_gpid, + child_gpid); + response.err = ERR_INVALID_STATE; + response.parent_config = parent_config; + return; + } auto iter = app->helpers->split_states.status.find(parent_gpid.get_partition_index()); if (iter == app->helpers->split_states.status.end()) { diff --git a/src/meta/server_state.cpp b/src/meta/server_state.cpp index f5a4b3bf47..7c671931cc 100644 --- a/src/meta/server_state.cpp +++ b/src/meta/server_state.cpp @@ -834,13 +834,24 @@ void server_state::on_config_sync(configuration_query_by_node_rpc rpc) rep.pid.get_partition_index()); std::shared_ptr app = get_app(rep.pid.get_app_id()); if (app == nullptr || rep.pid.get_partition_index() >= app->partition_count) { - // app is not recognized or partition is not recognized - dassert(false, - "gpid(%d.%d) on node(%s) is not exist on meta server, administrator " - "should check consistency of meta data", - rep.pid.get_app_id(), - rep.pid.get_partition_index(), - request.node.to_string()); + // This app has garbage partition after cancel split, the canceled child + // partition should be gc + if (app != nullptr && + rep.pid.get_partition_index() < app->partition_count * 2 && + rep.status == partition_status::PS_ERROR) { + response.gc_replicas.push_back(rep); + dwarn_f("notify node({}) to gc replica({}) because it is useless partition " + "which is caused by cancel split", + request.node.to_string(), + rep.pid); + } else { + // app is not recognized or partition is not recognized + dassert(false, + "gpid({}) on node({}) is not exist on meta server, administrator " + "should check consistency of meta data", + rep.pid, + request.node.to_string()); + } } else if (app->status == app_status::AS_DROPPED) { if (app->expire_second == 0) { ddebug("gpid(%d.%d) on node(%s) is of dropped table, but expire second is " diff --git a/src/meta/test/meta_split_service_test.cpp b/src/meta/test/meta_split_service_test.cpp index 7ad072dfbc..63551ae060 100644 --- a/src/meta/test/meta_split_service_test.cpp +++ b/src/meta/test/meta_split_service_test.cpp @@ -271,7 +271,7 @@ TEST_F(meta_split_service_test, register_child_test) // Test case: // - request is out-dated // - child has been registered - // - TODO(heyuchen): parent partition has been paused splitting + // - parent partition has been paused splitting // - parent partition is sync config to remote storage // - register child succeed struct register_test @@ -285,6 +285,7 @@ TEST_F(meta_split_service_test, register_child_test) } tests[] = { {PARENT_BALLOT - 1, false, false, false, ERR_INVALID_VERSION, false}, {PARENT_BALLOT, true, false, false, ERR_CHILD_REGISTERED, false}, + {PARENT_BALLOT, false, true, false, ERR_INVALID_STATE, false}, {PARENT_BALLOT, false, false, true, ERR_IO_PENDING, false}, {PARENT_BALLOT, false, false, false, ERR_OK, true}, }; @@ -295,7 +296,7 @@ TEST_F(meta_split_service_test, register_child_test) mock_child_registered(); } if (test.mock_parent_paused) { - // TODO(heyuchen): mock split paused + mock_split_states(split_status::PAUSED, PARENT_INDEX); } if (test.mock_pending) { app->helpers->contexts[PARENT_INDEX].stage = config_status::pending_remote_sync; @@ -330,13 +331,13 @@ TEST_F(meta_split_service_test, on_config_sync_test) // Test case: // - partition is splitting // - partition is not splitting - // - TODO(heyuchen): partition split is paused({false, true, 1}) + // - partition split is paused struct config_sync_test { bool mock_child_registered; bool mock_parent_paused; int32_t expected_count; - } tests[] = {{false, false, 1}, {true, false, 0}}; + } tests[] = {{false, false, 1}, {true, false, 0}, {false, true, 1}}; for (const auto &test : tests) { mock_app_partition_split_context(); @@ -344,7 +345,7 @@ TEST_F(meta_split_service_test, on_config_sync_test) mock_child_registered(); } if (test.mock_parent_paused) { - // TODO(heyuchen): TBD + mock_split_states(split_status::PAUSED, PARENT_INDEX); } ASSERT_EQ(on_config_sync(req), test.expected_count); } diff --git a/src/replica/split/replica_split_manager.cpp b/src/replica/split/replica_split_manager.cpp index 3a5c88d97b..4aa5f3cee7 100644 --- a/src/replica/split/replica_split_manager.cpp +++ b/src/replica/split/replica_split_manager.cpp @@ -1053,6 +1053,7 @@ void replica_split_manager::on_register_child_on_meta_reply( // update primary parent group partition_count update_local_partition_count(_replica->_app_info.partition_count * 2); + _meta_split_status = split_status::NOT_SPLIT; _replica->broadcast_group_check(); parent_cleanup_split_context();