From d00a25299981b33bc1cfe52477fd31c5b1e3c6f8 Mon Sep 17 00:00:00 2001 From: BinChenn Date: Thu, 8 Aug 2024 13:51:39 +0000 Subject: [PATCH] [fix] reset previous learner_list to reduce the size of LogMeta --- src/logservice/palf/log_config_mgr.cpp | 16 +++++++++ src/logservice/palf/log_engine.cpp | 23 ++++++++++++ src/logservice/palf/log_engine.h | 1 + .../mock_log_engine.h | 19 ++++++++++ unittest/logservice/test_log_config_mgr.cpp | 27 ++++++++++++++ unittest/logservice/test_log_meta.cpp | 35 +++++++++++++++++++ 6 files changed, 121 insertions(+) diff --git a/src/logservice/palf/log_config_mgr.cpp b/src/logservice/palf/log_config_mgr.cpp index 6eea552888..b14b242964 100755 --- a/src/logservice/palf/log_config_mgr.cpp +++ b/src/logservice/palf/log_config_mgr.cpp @@ -1073,6 +1073,19 @@ int LogConfigMgr::check_config_change_args_(const LogConfigChangeArgs &args, boo ret = OB_INVALID_ARGUMENT; PALF_LOG(WARN, "can't change config, memberlist don't reach majority", KR(ret), K_(palf_id), K_(self), K(new_config_info), K(new_paxos_memberlist), K(new_paxos_replica_num), K(args)); + } else { + // ensure that serialization size of the LogMetaEntry is smaller than MAX_META_ENTRY_SIZE + LogConfigMeta config_meta = log_ms_meta_; + const int64_t curr_proposal_id = state_mgr_->get_proposal_id(); + if (OB_FAIL(config_meta.generate(curr_proposal_id, config_meta.curr_, new_config_info, + checking_barrier_.prev_log_proposal_id_, checking_barrier_.prev_lsn_, + checking_barrier_.prev_mode_pid_))) { + PALF_LOG(WARN, "generate LogConfigMeta failed", KR(ret), K_(palf_id), K_(self), K(args)); + } else if (FALSE_IT(config_meta.prev_.config_.learnerlist_.reset())) { + } else if (OB_FAIL(log_engine_->check_config_meta_size(config_meta))) { + PALF_LOG(WARN, "check_config_meta_size failed, too many learners", KR(ret), K_(palf_id), + K_(self), K(args), K(config_meta)); + } } } return ret; @@ -1574,6 +1587,9 @@ int LogConfigMgr::append_config_meta_(const int64_t curr_proposal_id, } else if (OB_FAIL(append_config_info_(new_config_info))) { PALF_LOG(WARN, "append_config_info_ failed", KR(ret), K_(palf_id), K_(self), K(new_config_info)); } else { + // To reduce the serialized size of LogMeta to 4KB, we reset the previous learner_list. + // It's safe because the previous learner_list is useless in our design. + log_ms_meta_.prev_.config_.learnerlist_.reset(); // log_ms_meta_ and reconfig_barrier_ must be updated atomically reconfig_barrier_ = checking_barrier_; // Note: can not generate committed_end_lsn while changing configs with arb. diff --git a/src/logservice/palf/log_engine.cpp b/src/logservice/palf/log_engine.cpp index 052e627c70..6a235b3be8 100644 --- a/src/logservice/palf/log_engine.cpp +++ b/src/logservice/palf/log_engine.cpp @@ -1876,5 +1876,28 @@ LogNetService& LogEngine::get_net_service() { return log_net_service_; } + +int LogEngine::check_config_meta_size(const LogConfigMeta &config_meta) const +{ + int ret = OB_SUCCESS; + ObSpinLockGuard guard(log_meta_lock_); + LogMeta log_meta = log_meta_; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + PALF_LOG(ERROR, "LogEnginenot inited!!!", K(ret)); + } else if (OB_FAIL(log_meta.update_log_config_meta(config_meta))) { + PALF_LOG(ERROR, "LogMeta update_log_config_meta failed", K(ret), K_(palf_id), K_(is_inited)); + } else { + LogMetaEntryHeader log_meta_entry_header; + const int64_t log_meta_entry_header_len = log_meta_entry_header.get_serialize_size(); + const int64_t log_meta_body_len = log_meta.get_serialize_size(); + if (log_meta_entry_header_len + log_meta_body_len > MAX_META_ENTRY_SIZE) { + ret = OB_INVALID_ARGUMENT; + PALF_LOG(WARN, "check_config_meta_size failed", K(ret), K_(palf_id), + K(log_meta_entry_header_len), K(log_meta_body_len), K(config_meta)); + } + } + return ret; +} } // end namespace palf } // end namespace oceanbase diff --git a/src/logservice/palf/log_engine.h b/src/logservice/palf/log_engine.h index 9b48abbe30..b23fcae5ce 100644 --- a/src/logservice/palf/log_engine.h +++ b/src/logservice/palf/log_engine.h @@ -160,6 +160,7 @@ public: int submit_purge_throttling_task(const PurgeThrottlingType purge_type); int submit_fill_cache_task(const LSN &lsn, const int64_t size); + virtual int check_config_meta_size(const LogConfigMeta &config_meta) const; // ==================== Submit aysnc task end ================== // ====================== LogStorage start ===================== diff --git a/unittest/logservice/mock_logservice_container/mock_log_engine.h b/unittest/logservice/mock_logservice_container/mock_log_engine.h index a456410888..705d355fde 100644 --- a/unittest/logservice/mock_logservice_container/mock_log_engine.h +++ b/unittest/logservice/mock_logservice_container/mock_log_engine.h @@ -565,6 +565,25 @@ public: candidate_list_.reset(); reg_ret_ = RegisterReturn::INVALID_REG_RET; } + + int check_config_meta_size(const LogConfigMeta &config_meta) const + { + int ret = OB_SUCCESS; + LogMeta log_meta; + if (OB_FAIL(log_meta.update_log_config_meta(config_meta))) { + PALF_LOG(ERROR, "LogMeta update_log_config_meta failed", K(ret), K_(palf_id), K_(is_inited)); + } else { + LogMetaEntryHeader log_meta_entry_header; + const int64_t log_meta_entry_header_len = log_meta_entry_header.get_serialize_size(); + const int64_t log_meta_body_len = log_meta.get_serialize_size(); + if (log_meta_entry_header_len + log_meta_body_len > MAX_META_ENTRY_SIZE) { + ret = OB_INVALID_ARGUMENT; + PALF_LOG(WARN, "check_config_meta_size failed", K(ret), K_(palf_id), + K(log_meta_entry_header_len), K(log_meta_body_len), K(config_meta)); + } + } + return ret; + } public: // register_parent_resp ret LogLearner parent_itself_; diff --git a/unittest/logservice/test_log_config_mgr.cpp b/unittest/logservice/test_log_config_mgr.cpp index 0a226b3fda..070008822d 100755 --- a/unittest/logservice/test_log_config_mgr.cpp +++ b/unittest/logservice/test_log_config_mgr.cpp @@ -2001,6 +2001,33 @@ TEST_F(TestLogConfigMgr, test_init_by_default_config_meta) mock_mode_mgr_, mock_reconfirm_, mock_plugins_)); } +TEST_F(TestLogConfigMgr, test_too_many_learners) +{ + ObMemberList init_member_list; + init_member_list.add_server(addr1); + init_member_list.add_server(addr2); + init_member_list.add_server(addr3); + LogConfigInfoV2 config_info; + GlobalLearnerList learner_list; + LogConfigVersion init_config_version; + init_config_version.generate(1, 1); + EXPECT_EQ(OB_SUCCESS, config_info.generate(init_member_list, 3, learner_list, init_config_version)); + LogConfigMgr cm; + init_test_log_config_env(addr1, config_info, cm, LEADER); + + ObAddr::VER ip_type = ObAddr::IPV4; + const char* addr_str = "255.255.255.255"; + const int32_t port = INT32_MAX; + for (int i = 0; i < 200; i++) { + EXPECT_EQ(OB_SUCCESS, cm.log_ms_meta_.curr_.config_.learnerlist_.add_server(ObAddr(ip_type, addr_str, port - i))); + } + + // test add_learner + LogConfigChangeArgs args(ObMember(addr4, -1), 0, ADD_LEARNER); + bool unused_bool = false; + EXPECT_EQ(OB_INVALID_ARGUMENT, cm.check_config_change_args_(args, unused_bool)); +} + } // end namespace unittest } // end namespace oceanbase diff --git a/unittest/logservice/test_log_meta.cpp b/unittest/logservice/test_log_meta.cpp index 37e75be227..f24f9b299d 100644 --- a/unittest/logservice/test_log_meta.cpp +++ b/unittest/logservice/test_log_meta.cpp @@ -152,6 +152,41 @@ TEST(TestLogMeta, test_log_meta_generate) EXPECT_EQ(meta1.log_snapshot_meta_.base_lsn_, base_info.curr_lsn_); EXPECT_EQ(meta1.log_snapshot_meta_.prev_log_info_, base_info.prev_log_info_); } + +TEST(TestLogMeta, test_max_length_learner_list) +{ + const int64_t init_log_proposal_id(0); + LogConfigMeta log_config_meta; + LogConfigInfoV2 init_config_info; + LogConfigVersion init_config_version; + EXPECT_EQ(OB_SUCCESS, init_config_version.generate(init_log_proposal_id, 0)); + EXPECT_EQ(OB_SUCCESS, init_config_info.generate(init_config_version)); + log_config_meta.version_ = LogConfigMeta::LOG_CONFIG_META_VERSION_INC; + log_config_meta.proposal_id_ = init_log_proposal_id; + log_config_meta.curr_ = init_config_info; + log_config_meta.prev_ = init_config_info; + LogMeta log_meta1; + EXPECT_EQ(OB_SUCCESS, log_meta1.update_log_config_meta(log_config_meta)); + + ObAddr::VER ip_type = ObAddr::IPV4; + const char* addr_str = "255.255.255.255"; + const int32_t port = INT32_MAX; + + for (int i = 0; i < OB_MAX_MEMBER_NUMBER; i++) { + log_meta1.log_config_meta_.curr_.config_.log_sync_memberlist_.add_member(ObMember(ObAddr(ip_type, addr_str, port - i), INT64_MAX)); + log_meta1.log_config_meta_.prev_.config_.log_sync_memberlist_.add_member(ObMember(ObAddr(ip_type, addr_str, port - i), INT64_MAX)); + log_meta1.log_config_meta_.curr_.config_.arbitration_member_ = ObMember(ObAddr(ip_type, addr_str, port - i), INT64_MAX); + log_meta1.log_config_meta_.prev_.config_.arbitration_member_ = ObMember(ObAddr(ip_type, addr_str, port - i), INT64_MAX); + } + PALF_LOG(INFO, "IPV4 base serialize size", "size", log_meta1.get_serialize_size()); + + for (int i = 0; i < 60; i++) { + log_meta1.log_config_meta_.curr_.config_.learnerlist_.add_server(ObAddr(ip_type, addr_str, port - i)); + } + const int64_t member_serialize_size = ObMember(ObAddr(ObAddr::IPV4, addr_str, port), INT64_MAX).get_serialize_size(); + const int64_t addr_serialize_size = ObAddr(ObAddr::IPV4, addr_str, port).get_serialize_size(); + PALF_LOG(INFO, "60 IPV4 serialize size", "size", log_meta1.get_serialize_size(), K(member_serialize_size), K(addr_serialize_size)); +} } }