From 09dd119b6ed7aa47f705a21b109eb5af88b78b2b Mon Sep 17 00:00:00 2001 From: BinChenn Date: Wed, 28 Jun 2023 09:12:09 +0000 Subject: [PATCH] [fix][PALF] consider degraded learners when setting replica_num --- src/logservice/palf/log_config_mgr.cpp | 57 ++++-- src/logservice/palf/log_config_mgr.h | 1 + unittest/logservice/CMakeLists.txt | 2 +- unittest/logservice/test_log_config_mgr.cpp | 205 ++++++++++++++++++-- 4 files changed, 236 insertions(+), 29 deletions(-) diff --git a/src/logservice/palf/log_config_mgr.cpp b/src/logservice/palf/log_config_mgr.cpp index 7d121b42c..4e0351d71 100755 --- a/src/logservice/palf/log_config_mgr.cpp +++ b/src/logservice/palf/log_config_mgr.cpp @@ -1150,10 +1150,18 @@ int LogConfigMgr::check_config_change_args_by_type_(const LogConfigChangeArgs &a if (is_in_degraded_learnerlist) { PALF_LOG(INFO, "member to be removed is a degraded learner", KR(ret), K_(palf_id), K_(self), K_(log_ms_meta), K(member), K(new_replica_num)); - } else if (args.type_ == REMOVE_MEMBER_AND_NUM || new_replica_num == curr_replica_num) { + } else if (args.type_ == REMOVE_MEMBER_AND_NUM || + new_replica_num == curr_replica_num || + (true == has_arb_replica && + 0 == degraded_learnerlist.get_member_number() && + log_sync_member_list.get_member_number() * 2 == new_replica_num)) { // config change has finished successfully, do not need change again + // Note: 2F1A, B has been degraded, permanent offline B, i.e. remove(B, 2). + // Previous remove(B, 2) has been executed successfully, another remove(B, 2) will + // be identified as invalid, because curr_replica_num is 1. For reentrany of the + // remove_member interface, we just return OB_SUCCESS; is_already_finished = true; - PALF_LOG(INFO, "member is already removed, don't need remove_member/replcae_member", KR(ret), K_(palf_id), K_(self), + PALF_LOG(INFO, "member is already removed, don't need remove_member", KR(ret), K_(palf_id), K_(self), K_(log_ms_meta), K(member), K(new_replica_num), K_(alive_paxos_replica_num)); } else { ret = OB_INVALID_ARGUMENT; @@ -1369,9 +1377,9 @@ bool LogConfigMgr::can_memberlist_majority_(const int64_t new_member_list_len, c // 2. len(member_list) >= replica_num / 2 + 1 bool bool_ret = false; if (new_member_list_len > new_replica_num) { - PALF_LOG_RET(WARN, OB_INVALID_ARGUMENT, "can't change config, replica_num too small", K_(palf_id), K_(self), K(new_replica_num), K(new_member_list_len)); + PALF_LOG_RET(WARN, OB_INVALID_ARGUMENT, "replica_num too small", K_(palf_id), K_(self), K(new_replica_num), K(new_member_list_len)); } else if (new_member_list_len < (new_replica_num / 2 + 1)) { - PALF_LOG_RET(WARN, OB_INVALID_ARGUMENT, "can't change config, replica_num too large", K_(palf_id), K_(self), K(new_replica_num), K(new_member_list_len)); + PALF_LOG_RET(WARN, OB_INVALID_ARGUMENT, "replica_num too large", K_(palf_id), K_(self), K(new_replica_num), K(new_member_list_len)); } else { bool_ret = true; } @@ -1622,11 +1630,20 @@ int LogConfigMgr::generate_new_config_info_(const int64_t proposal_id, // change replcia num int64_t new_log_sync_replica_num = curr_replica_num; if (is_may_change_replica_num(cc_type)) { + const bool is_remove_degraded_learner = is_remove_log_sync_member_list(args.type_) && + new_config_info.config_.degraded_learnerlist_.contains(member); if (is_use_replica_num_args(cc_type)) { - new_log_sync_replica_num = args.new_replica_num_; + // Note: consider the number of degraded learners when setting replica_num, + // and note that current number of degraded learners is not the eventual value + // if the request is going to remove a degraded learner. + int64_t degraded_cnt = new_config_info.config_.degraded_learnerlist_.get_member_number(); + degraded_cnt = (is_remove_degraded_learner)? degraded_cnt - 1: degraded_cnt; + new_log_sync_replica_num = args.new_replica_num_ - degraded_cnt; } else if (is_add_log_sync_member_list(cc_type)) { new_log_sync_replica_num = new_config_info.config_.log_sync_replica_num_ + 1; - } else if (is_remove_log_sync_member_list(cc_type)) { + } else if (is_remove_log_sync_member_list(cc_type) && true == is_remove_degraded_learner) { + new_log_sync_replica_num = new_config_info.config_.log_sync_replica_num_; + } else if (is_remove_log_sync_member_list(cc_type) && false == is_remove_degraded_learner) { new_log_sync_replica_num = new_config_info.config_.log_sync_replica_num_ - 1; } else if (is_arb_member_change_type(cc_type)) { new_log_sync_replica_num = new_config_info.config_.log_sync_replica_num_; @@ -1634,9 +1651,16 @@ int LogConfigMgr::generate_new_config_info_(const int64_t proposal_id, ret = OB_ERR_UNEXPECTED; PALF_LOG(ERROR, "unexpected config change type", KR(ret), K_(palf_id), K_(self), K(args), K(new_config_info)); } + if (OB_SUCC(ret) && is_remove_degraded_learner && + (new_config_info.config_.log_sync_memberlist_.get_member_number() * 2 == new_log_sync_replica_num)) { + // Note: 2F1A, B has been degraded, permanent offline B, i.e. remove(B, 2). + // Remaining F members (A) in member_list do not reach majority of replica_num(2), + // so we just remove it and do not update log_sync_replica_num_. + new_log_sync_replica_num = new_config_info.config_.log_sync_replica_num_; + } } // memberlist add, update replica number - if (is_add_member_list(cc_type)) { + if (OB_SUCC(ret) && is_add_member_list(cc_type)) { // update log_sync_member_list or arb_member if (is_add_log_sync_member_list(args.type_)) { if (OB_FAIL(new_config_info.config_.log_sync_memberlist_.add_member(member))) { @@ -1658,8 +1682,6 @@ int LogConfigMgr::generate_new_config_info_(const int64_t proposal_id, if (OB_FAIL(new_config_info.config_.degraded_learnerlist_.remove_learner(member))) { PALF_LOG(WARN, "new_member_list remove member failed", KR(ret), K_(palf_id), K_(self), K(args), K(new_config_info)); } - // If dst member is already degraded learner, just remove it and no need update log_sync_replica_num_. - new_log_sync_replica_num = new_config_info.config_.log_sync_replica_num_; } else { ret = OB_INVALID_ARGUMENT; PALF_LOG(WARN, "member to be removed does not exist", KR(ret), K_(palf_id), K_(self), K(args), K(new_config_info)); @@ -1668,14 +1690,6 @@ int LogConfigMgr::generate_new_config_info_(const int64_t proposal_id, new_config_info.config_.arbitration_member_.reset(); } } - if (OB_SUCC(ret) && FORCE_SINGLE_MEMBER == cc_type) { - // force set single member - new_config_info.config_.log_sync_memberlist_.reset(); - new_config_info.config_.degraded_learnerlist_.reset(); - new_config_info.config_.arbitration_member_.reset(); - new_config_info.config_.log_sync_memberlist_.add_member(member); - new_config_info.config_.log_sync_replica_num_ = new_log_sync_replica_num; - } // learnerlist add if (OB_SUCC(ret) && is_add_learner_list(cc_type)) { if (DEGRADE_ACCEPTOR_TO_LEARNER == cc_type) { @@ -1717,6 +1731,15 @@ int LogConfigMgr::generate_new_config_info_(const int64_t proposal_id, if (OB_SUCC(ret)) { new_config_info.config_.log_sync_replica_num_ = new_log_sync_replica_num; } + // Note: order is vital + if (OB_SUCC(ret) && FORCE_SINGLE_MEMBER == cc_type) { + // force set single member + new_config_info.config_.log_sync_memberlist_.reset(); + new_config_info.config_.degraded_learnerlist_.reset(); + new_config_info.config_.arbitration_member_.reset(); + new_config_info.config_.log_sync_memberlist_.add_member(member); + new_config_info.config_.log_sync_replica_num_ = args.new_replica_num_; + } } return ret; } diff --git a/src/logservice/palf/log_config_mgr.h b/src/logservice/palf/log_config_mgr.h index 74a5970d0..76847a3dc 100755 --- a/src/logservice/palf/log_config_mgr.h +++ b/src/logservice/palf/log_config_mgr.h @@ -91,6 +91,7 @@ inline const char *LogConfigChangeType2Str(const LogConfigChangeType state) CHECK_LOG_CONFIG_TYPE_STR(DEGRADE_ACCEPTOR_TO_LEARNER); CHECK_LOG_CONFIG_TYPE_STR(UPGRADE_LEARNER_TO_ACCEPTOR); CHECK_LOG_CONFIG_TYPE_STR(STARTWORKING); + CHECK_LOG_CONFIG_TYPE_STR(FORCE_SINGLE_MEMBER); default: return "Invalid"; } diff --git a/unittest/logservice/CMakeLists.txt b/unittest/logservice/CMakeLists.txt index b26d91119..c720e87d3 100644 --- a/unittest/logservice/CMakeLists.txt +++ b/unittest/logservice/CMakeLists.txt @@ -29,7 +29,7 @@ ob_unittest(test_ob_election_message_compat2) ob_unittest(test_ls_election_reference_info) ob_unittest(test_ob_tuple) #ob_unittest(test_ob_role_change_service) -#ob_unittest(test_log_config_mgr)TODO(yunlong.cb): fix it +ob_unittest(test_log_config_mgr) ob_unittest(test_clear_up_tmp_files) ob_unittest(test_log_dir_match) ob_unittest(test_server_log_block_mgr) diff --git a/unittest/logservice/test_log_config_mgr.cpp b/unittest/logservice/test_log_config_mgr.cpp index 282e9c830..f2e579e11 100755 --- a/unittest/logservice/test_log_config_mgr.cpp +++ b/unittest/logservice/test_log_config_mgr.cpp @@ -388,7 +388,7 @@ TEST_F(TestLogConfigMgr, test_config_change_lock) int tmp_ret = OB_SUCCESS; LSN prev_lsn; prev_lsn.val_ = PALF_INITIAL_LSN_VAL; - tmp_ret = cm.append_log_ms_meta_.1, arg_list[i], already_finished); + tmp_ret = cm.append_config_meta_(1, arg_list[i], already_finished); config_version = cm.log_ms_meta_.curr_.config_.config_version_; ASSERT_EQ(tmp_ret, expect_ret_list[i]) << "ret failed case: " << (i+1); ASSERT_EQ(already_finished, expect_finished_list[i]) << "finished failed case:" << (i+1); @@ -833,7 +833,7 @@ TEST_F(TestLogConfigMgr, test_apply_config_meta) expect_member_list.back().add_server(addr4); for (int i = 0; i < arg_list.size(); ++i) { - PALF_LOG(INFO, "test_check_config_change_args begin case", K(i)); + PALF_LOG(INFO, "test_check_config_change_args begin case", K(i+1)); LogConfigMgr cm; LogConfigVersion config_version, expect_config_version; init_test_log_config_env(addr1, config_info_list[i], cm); @@ -847,10 +847,10 @@ TEST_F(TestLogConfigMgr, test_apply_config_meta) LogConfigChangeArgs args; args = arg_list[i]; args.config_version_ = init_config_version; - tmp_ret = cm.append_log_ms_meta_.1, args, already_finished); + tmp_ret = cm.append_config_meta_(1, args, already_finished); config_version = cm.log_ms_meta_.curr_.config_.config_version_; - ASSERT_EQ(tmp_ret, expect_ret_list[i]) << "ret failed case: " << (i+1); - ASSERT_EQ(already_finished, expect_finished_list[i]) << "finished failed case:" << (i+1); + EXPECT_EQ(tmp_ret, expect_ret_list[i]) << "ret failed case: " << (i+1); + EXPECT_EQ(already_finished, expect_finished_list[i]) << "finished failed case:" << (i+1); // memberlist will not be applied right now when there is arb member, so use alive_paxos_memberlist_ bool member_equal = (cm.alive_paxos_memberlist_.member_addr_equal(expect_member_list[i])); EXPECT_TRUE(member_equal) << "ret failed case: " << (i+1); @@ -861,7 +861,7 @@ TEST_F(TestLogConfigMgr, test_apply_config_meta) EXPECT_EQ(config_version, expect_config_version) << i; } } - PALF_LOG(INFO, "test_check_config_change_args end case", K(i)); + PALF_LOG(INFO, "test_check_config_change_args end case", K(i+1)); } { // 26. 4F1A, remove(D, 5), remove(C, 5), @@ -874,7 +874,7 @@ TEST_F(TestLogConfigMgr, test_apply_config_meta) prev_lsn.val_ = PALF_INITIAL_LSN_VAL; // remove(D, 5) LogConfigChangeArgs remove_d_arg(ObMember(addr4, -1), 5, palf::REMOVE_MEMBER); - tmp_ret = cm.append_log_ms_meta_.1, remove_d_arg, already_finished); + tmp_ret = cm.append_config_meta_(1, remove_d_arg, already_finished); EXPECT_EQ(tmp_ret, OB_SUCCESS) << "remove(D, 5)"; EXPECT_EQ(already_finished, false) << "remove(D, 5)"; ObMemberList expect_member_list = four_f_member_list; @@ -886,7 +886,7 @@ TEST_F(TestLogConfigMgr, test_apply_config_meta) // remove(C, 5) cm.reset_status(); LogConfigChangeArgs remove_c_arg(ObMember(addr3, -1), 5, palf::REMOVE_MEMBER); - tmp_ret = cm.append_log_ms_meta_.1, remove_c_arg, already_finished); + tmp_ret = cm.append_config_meta_(1, remove_c_arg, already_finished); EXPECT_EQ(tmp_ret, OB_INVALID_ARGUMENT) << "remove(C, 5)"; PALF_LOG(INFO, "test_check_config_change_args end case 26"); } @@ -900,20 +900,203 @@ TEST_F(TestLogConfigMgr, test_apply_config_meta) bool already_finished = false; // add (D, 4) LogConfigChangeArgs add_d_arg(ObMember(addr4, -1), 4, config_version, palf::ADD_MEMBER); - EXPECT_EQ(OB_SUCCESS, cm.append_log_ms_meta_.1, add_d_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, add_d_arg, already_finished)); EXPECT_EQ(already_finished, false) << "add(D, 4)"; ObMemberList expect_member_list = default_config_info.config_.log_sync_memberlist_; expect_member_list.add_server(addr4); EXPECT_TRUE(cm.alive_paxos_memberlist_.member_addr_equal(expect_member_list)); // add (D, 4) again, success - EXPECT_EQ(OB_SUCCESS, cm.append_log_ms_meta_.1, add_d_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, add_d_arg, already_finished)); EXPECT_EQ(already_finished, true) << "add(D, 4)"; // add (D, 4) again with greater config_version , fail add_d_arg.config_version_.inc_update_version(2); - EXPECT_EQ(OB_ERR_UNEXPECTED, cm.append_log_ms_meta_.1, add_d_arg, already_finished)); + EXPECT_EQ(OB_ERR_UNEXPECTED, cm.append_config_meta_(1, add_d_arg, already_finished)); EXPECT_EQ(already_finished, false) << "add(D, 4)"; PALF_LOG(INFO, "test_check_config_change_args end case 27"); } + { + // 27. 2F1A, degrade B, add C, add D, upgrade B + PALF_LOG(INFO, "test_check_config_change_args begin case 27"); + LogConfigMgr cm; + init_test_log_config_env(addr1, two_f_one_a_config_info, cm); + bool already_finished = false; + ObMemberList expect_member_list; + int64_t expect_replica_num = 0; + LogConfigVersion config_version; + // degrade B + LogConfigChangeArgs degrade_b_arg(ObMember(addr2, -1), 0, palf::DEGRADE_ACCEPTOR_TO_LEARNER); + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, degrade_b_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.get_curr_member_list(expect_member_list, expect_replica_num)); + EXPECT_EQ(expect_replica_num, 2); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_replica_num_, 1); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_memberlist_.get_member_number(), 1); + // add C + EXPECT_EQ(OB_SUCCESS, cm.get_config_version(config_version)); + LogConfigChangeArgs add_c_arg(ObMember(addr4, -1), 3, config_version, palf::ADD_MEMBER); + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, add_c_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.get_curr_member_list(expect_member_list, expect_replica_num)); + EXPECT_EQ(expect_replica_num, 3); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_replica_num_, 2); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_memberlist_.get_member_number(), 2); + // add D + EXPECT_EQ(OB_SUCCESS, cm.get_config_version(config_version)); + LogConfigChangeArgs add_d_arg(ObMember(addr5, -1), 4, config_version, palf::ADD_MEMBER); + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, add_d_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.get_curr_member_list(expect_member_list, expect_replica_num)); + EXPECT_EQ(expect_replica_num, 4); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_replica_num_, 3); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_memberlist_.get_member_number(), 3); + // upgrade B + LogConfigChangeArgs upgrade_b_arg(ObMember(addr2, -1), 0, palf::UPGRADE_LEARNER_TO_ACCEPTOR); + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, upgrade_b_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.get_curr_member_list(expect_member_list, expect_replica_num)); + EXPECT_EQ(expect_replica_num, 4); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_replica_num_, 4); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_memberlist_.get_member_number(), 4); + PALF_LOG(INFO, "test_check_config_change_args end case 27"); + } + { + // 28. 2F1A, degrade B, set single replica + PALF_LOG(INFO, "test_check_config_change_args begin case 28"); + LogConfigMgr cm; + init_test_log_config_env(addr1, two_f_one_a_config_info, cm); + bool already_finished = false; + ObMemberList expect_member_list; + int64_t expect_replica_num = 0; + // degrade B + LogConfigChangeArgs degrade_b_arg(ObMember(addr2, -1), 0, palf::DEGRADE_ACCEPTOR_TO_LEARNER); + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, degrade_b_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.get_curr_member_list(expect_member_list, expect_replica_num)); + EXPECT_EQ(expect_replica_num, 2); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_replica_num_, 1); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_memberlist_.get_member_number(), 1); + // set single replica + LogConfigChangeArgs set_single_arg(ObMember(addr1, -1), 1, palf::FORCE_SINGLE_MEMBER); + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, set_single_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.get_curr_member_list(expect_member_list, expect_replica_num)); + EXPECT_EQ(expect_replica_num, 1); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_replica_num_, 1); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_memberlist_.get_member_number(), 1); + PALF_LOG(INFO, "test_check_config_change_args end case 28"); + } + { + // 29. 4F1A, degrade C and D, remove (C, 4), remove (D, 4) + PALF_LOG(INFO, "test_check_config_change_args begin case 29"); + LogConfigMgr cm; + init_test_log_config_env(addr1, four_f_one_a_config_info, cm); + bool already_finished = false; + ObMemberList expect_member_list; + int64_t expect_replica_num = 0; + // degrade C + LogConfigChangeArgs degrade_c_arg(ObMember(addr3, -1), 0, palf::DEGRADE_ACCEPTOR_TO_LEARNER); + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, degrade_c_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.get_curr_member_list(expect_member_list, expect_replica_num)); + EXPECT_EQ(expect_replica_num, 4); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_replica_num_, 3); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_memberlist_.get_member_number(), 3); + // degrade D + LogConfigChangeArgs degrade_d_arg(ObMember(addr4, -1), 0, palf::DEGRADE_ACCEPTOR_TO_LEARNER); + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, degrade_d_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.get_curr_member_list(expect_member_list, expect_replica_num)); + EXPECT_EQ(expect_replica_num, 4); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_replica_num_, 2); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_memberlist_.get_member_number(), 2); + // remove (C, 4) + LogConfigChangeArgs remove_c_arg(ObMember(addr3, -1), 4, palf::REMOVE_MEMBER); + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, remove_c_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.get_curr_member_list(expect_member_list, expect_replica_num)); + EXPECT_EQ(expect_replica_num, 4); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_replica_num_, 3); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_memberlist_.get_member_number(), 2); + // remove (C, 4), reentrant + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, remove_c_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.get_curr_member_list(expect_member_list, expect_replica_num)); + EXPECT_EQ(expect_replica_num, 4); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_replica_num_, 3); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_memberlist_.get_member_number(), 2); + // remove (D, 4) + LogConfigChangeArgs remove_d_arg(ObMember(addr4, -1), 4, palf::REMOVE_MEMBER); + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, remove_d_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.get_curr_member_list(expect_member_list, expect_replica_num)); + EXPECT_EQ(expect_replica_num, 3); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_replica_num_, 3); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_memberlist_.get_member_number(), 2); + // remove (D, 4), reentrant + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, remove_d_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.get_curr_member_list(expect_member_list, expect_replica_num)); + EXPECT_EQ(expect_replica_num, 3); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_replica_num_, 3); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_memberlist_.get_member_number(), 2); + PALF_LOG(INFO, "test_check_config_change_args end case 29"); + } + { + // 30. 4F1A, degrade C, remove (C, 4) + PALF_LOG(INFO, "test_check_config_change_args begin case 30"); + LogConfigMgr cm; + init_test_log_config_env(addr1, four_f_one_a_config_info, cm); + bool already_finished = false; + ObMemberList expect_member_list; + int64_t expect_replica_num = 0; + // degrade C + LogConfigChangeArgs degrade_c_arg(ObMember(addr3, -1), 0, palf::DEGRADE_ACCEPTOR_TO_LEARNER); + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, degrade_c_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.get_curr_member_list(expect_member_list, expect_replica_num)); + EXPECT_EQ(expect_replica_num, 4); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_replica_num_, 3); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_memberlist_.get_member_number(), 3); + // remove (C, 4) + LogConfigChangeArgs remove_c_arg(ObMember(addr3, -1), 4, palf::REMOVE_MEMBER); + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, remove_c_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.get_curr_member_list(expect_member_list, expect_replica_num)); + EXPECT_EQ(expect_replica_num, 4); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_replica_num_, 4); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_memberlist_.get_member_number(), 3); + } + { + // 31. 2F1A - abc, degrade b, migrate b to d: add d, remove degraded b. + PALF_LOG(INFO, "test_check_config_change_args begin case 31"); + LogConfigMgr cm; + init_test_log_config_env(addr1, two_f_one_a_config_info, cm); + bool already_finished = false; + ObMemberList expect_member_list; + int64_t expect_replica_num = 0; + // degrade B + LogConfigChangeArgs degrade_b_arg(ObMember(addr2, -1), 0, palf::DEGRADE_ACCEPTOR_TO_LEARNER); + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, degrade_b_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.get_curr_member_list(expect_member_list, expect_replica_num)); + EXPECT_EQ(expect_replica_num, 2); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_replica_num_, 1); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_memberlist_.get_member_number(), 1); + // add d and num + LogConfigVersion config_version; + EXPECT_EQ(OB_SUCCESS, cm.get_config_version(config_version)); + LogConfigChangeArgs add_d_arg(ObMember(addr4, -1), 0, config_version, palf::ADD_MEMBER_AND_NUM); + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, add_d_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.get_curr_member_list(expect_member_list, expect_replica_num)); + EXPECT_EQ(expect_replica_num, 3); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_replica_num_, 2); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_memberlist_.get_member_number(), 2); + // add d and num, reentrant + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, add_d_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.get_curr_member_list(expect_member_list, expect_replica_num)); + EXPECT_EQ(expect_replica_num, 3); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_replica_num_, 2); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_memberlist_.get_member_number(), 2); + // remove B and num + LogConfigChangeArgs remove_b_arg(ObMember(addr2, -1), 0, palf::REMOVE_MEMBER_AND_NUM); + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, remove_b_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.get_curr_member_list(expect_member_list, expect_replica_num)); + EXPECT_EQ(expect_replica_num, 2); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_replica_num_, 2); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_memberlist_.get_member_number(), 2); + // remove B and num, reentrant + EXPECT_EQ(OB_SUCCESS, cm.append_config_meta_(1, remove_b_arg, already_finished)); + EXPECT_EQ(OB_SUCCESS, cm.get_curr_member_list(expect_member_list, expect_replica_num)); + EXPECT_EQ(expect_replica_num, 2); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_replica_num_, 2); + EXPECT_EQ(cm.log_ms_meta_.curr_.config_.log_sync_memberlist_.get_member_number(), 2); + PALF_LOG(INFO, "test_check_config_change_args end case 31"); + } } TEST_F(TestLogConfigMgr, test_submit_start_working_log)