diff --git a/deps/oblib/src/lib/ob_define.h b/deps/oblib/src/lib/ob_define.h index 2c5b5d5524..128f1801f4 100644 --- a/deps/oblib/src/lib/ob_define.h +++ b/deps/oblib/src/lib/ob_define.h @@ -865,6 +865,7 @@ const char *const OB_ORA_CONNECT_ROLE_NAME = "CONNECT"; const char *const OB_ORA_RESOURCE_ROLE_NAME = "RESOURCE"; const char *const OB_ORA_DBA_ROLE_NAME = "DBA"; const char *const OB_ORA_PUBLIC_ROLE_NAME = "PUBLIC"; +const char *const OB_ORA_STANDBY_REPLICATION_ROLE_NAME = "STANDBY_REPLICATION"; const char *const OB_RESTORE_USER_NAME = "__oceanbase_inner_restore_user"; const char *const OB_DRC_USER_NAME = "__oceanbase_inner_drc_user"; const char *const OB_SYS_TENANT_NAME = "sys"; @@ -1141,6 +1142,7 @@ const uint64_t OB_ORA_RESOURCE_ROLE_ID = OB_MIN_INNER_USER_ID + 7; const uint64_t OB_ORA_DBA_ROLE_ID = OB_MIN_INNER_USER_ID + 8; const uint64_t OB_ORA_PUBLIC_ROLE_ID = OB_MIN_INNER_USER_ID + 9; const uint64_t OB_AUDIT_MOCK_USER_ID = OB_MIN_INNER_USER_ID + 10; +const uint64_t OB_ORA_STANDBY_REPLICATION_ROLE_ID = OB_MIN_INNER_USER_ID + 11; const char * const OB_PROXYRO_USERNAME = "proxyro"; const uint64_t OB_MAX_INNER_USER_ID = 201000; @@ -1194,6 +1196,11 @@ OB_INLINE bool is_ora_public_role(const uint64_t uid) return (uid == OB_ORA_PUBLIC_ROLE_ID); } +OB_INLINE bool is_ora_standby_replication_role(const uint64_t uid) +{ + return (uid == OB_ORA_STANDBY_REPLICATION_ROLE_ID); +} + /* * ################################################################################ * OBJECT_ID FOR DATABASE (201000, 202000) diff --git a/mittest/logservice/env/mock_ob_locality_manager.h b/mittest/logservice/env/mock_ob_locality_manager.h index e0c08bb029..d1797df0a3 100644 --- a/mittest/logservice/env/mock_ob_locality_manager.h +++ b/mittest/logservice/env/mock_ob_locality_manager.h @@ -11,27 +11,48 @@ */ #include "storage/ob_locality_manager.h" +#include "lib/hash/ob_hashmap.h" // ObHashMap +#include "logservice/palf/palf_callback.h" namespace oceanbase { using namespace storage; +using namespace palf; namespace unittest { -class MockObLocalityManager : public ObLocalityManager + +typedef common::hash::ObHashMap LogMemberRegionMap; + +class CallBack +{ + public: + void operator () (hash::HashMapPair &v) + { + v.second = v_; + }; + void set_v(common::ObRegion v) + { + v_ = v; + }; + private: + common::ObRegion v_; +}; + +class MockObLocalityManager : public palf::PalfLocalityInfoCb, public ObLocalityManager { public: - MockObLocalityManager(): self_(), is_inited_(false) { } + MockObLocalityManager(): is_inited_(false) { } ~MockObLocalityManager() { destroy(); } - int init(const common::ObAddr &self) + int init(LogMemberRegionMap *region_map) { int ret = OB_SUCCESS; if (IS_INIT) { ret = OB_INIT_TWICE; - } else if (self.is_valid() == false) { + } else if (OB_ISNULL(region_map)) { ret = OB_INVALID_ARGUMENT; - SERVER_LOG(WARN, "invalid argument", K(self)); + SERVER_LOG(WARN, "invalid argument", KP(region_map)); } else { - self_ = self; + region_map_ = region_map; is_inited_ = true; } return ret; @@ -39,21 +60,40 @@ public: void destroy() { is_inited_ = false; - self_.reset(); + region_map_ = NULL; } - int is_same_zone(const common::ObAddr &server, bool &is_same_zone) + int set_server_region(const common::ObAddr &server, + const common::ObRegion ®ion) { int ret = OB_SUCCESS; - UNUSED(server); - if (IS_NOT_INIT) { + if (OB_ISNULL(region_map_)) { ret = OB_NOT_INIT; + } else if (OB_FAIL(region_map_->set_refactored(server, region)) && ret != OB_HASH_EXIST) { + SERVER_LOG(WARN, "set_refactored failed", K(server), K(region)); } else { - is_same_zone = false; + CallBack callback; + callback.set_v(region); + if (OB_FAIL(region_map_->atomic_refactored(server, callback))) { + SERVER_LOG(WARN, "atomic_refactored failed", K(server), K(region)); + } + } + SERVER_LOG(INFO, "set_server_region finish", K(ret), K(server), K(region)); + return ret; + } + int get_server_region(const common::ObAddr &server, + common::ObRegion ®ion) const override final + { + int ret = OB_SUCCESS; + if (OB_ISNULL(region_map_)) { + ret = OB_ENTRY_NOT_EXIST; + } else if (OB_FAIL(region_map_->get_refactored(server, region))) { + ret = OB_ENTRY_NOT_EXIST; + SERVER_LOG(WARN, "get_server_region failed", K(server), K(region)); } return ret; } private: - common::ObAddr self_; + LogMemberRegionMap *region_map_; bool is_inited_; }; }// storage diff --git a/mittest/logservice/env/ob_simple_arb_server.cpp b/mittest/logservice/env/ob_simple_arb_server.cpp index 6301b5a746..8c39a37b2f 100644 --- a/mittest/logservice/env/ob_simple_arb_server.cpp +++ b/mittest/logservice/env/ob_simple_arb_server.cpp @@ -64,6 +64,7 @@ ObSimpleArbServer::~ObSimpleArbServer() int ObSimpleArbServer::simple_init(const std::string &cluster_name, const common::ObAddr &addr, const int64_t node_id, + LogMemberRegionMap *region_map, bool is_bootstrap) { const std::string logserver_dir = cluster_name + "/port_" + std::to_string(addr.get_port()); @@ -191,7 +192,7 @@ int ObSimpleArbServer::simple_restart(const std::string &cluster_name, srv_network_frame_.deliver_.stop(); palf_env_mgr_.destroy(); timer_.destroy(); - if (OB_FAIL(simple_init(cluster_name, self_, node_idx, false))) { + if (OB_FAIL(simple_init(cluster_name, self_, node_idx, NULL, false))) { CLOG_LOG(WARN, "simple_init failed", K(ret)); } else if (OB_FAIL(srv_network_frame_.deliver_.start(srv_network_frame_.normal_rpc_qhandler_, srv_network_frame_.server_rpc_qhandler_))) { diff --git a/mittest/logservice/env/ob_simple_arb_server.h b/mittest/logservice/env/ob_simple_arb_server.h index 27e21e9645..7b4a65ae22 100644 --- a/mittest/logservice/env/ob_simple_arb_server.h +++ b/mittest/logservice/env/ob_simple_arb_server.h @@ -173,10 +173,12 @@ public: } int update_server_log_disk(const int64_t log_disk_size) {return OB_SUCCESS;} + MockObLocalityManager *get_locality_manager() { return NULL; } public: int simple_init(const std::string &cluster_name, const common::ObAddr &addr, const int64_t node_id, + LogMemberRegionMap *region_map, bool is_bootstrap) override final; int simple_start(const bool is_bootstrap) override final; int simple_close(const bool is_shutdown) override final; diff --git a/mittest/logservice/env/ob_simple_log_cluster_env.cpp b/mittest/logservice/env/ob_simple_log_cluster_env.cpp index 499870eb5c..e71dc02acc 100644 --- a/mittest/logservice/env/ob_simple_log_cluster_env.cpp +++ b/mittest/logservice/env/ob_simple_log_cluster_env.cpp @@ -294,10 +294,10 @@ int ObSimpleLogClusterTestEnv::create_paxos_group(const int64_t id, } } handle->set_location_cache_cb(loc_cb); + handle->set_locality_cb(get_cluster()[0]->get_locality_manager()); const ObMemberList &member_list = get_member_list(); GlobalLearnerList learner_list; handle->set_initial_member_list(member_list, member_list.get_member_number(), learner_list); - handle->set_paxos_member_region_map(get_member_region_map()); CLOG_LOG(INFO, "set_initial_member_list success", K(id), "addr", svr->get_addr(), K(member_list)); } if (NULL != handle) { @@ -422,7 +422,7 @@ int ObSimpleLogClusterTestEnv::create_paxos_group_with_arb( } } handle->set_location_cache_cb(loc_cb); - handle->set_paxos_member_region_map(get_member_region_map()); + handle->set_locality_cb(get_cluster()[0]->get_locality_manager()); CLOG_LOG(INFO, "set_initial_member_list success", K(member_list)); } if (NULL == svr->get_palf_env()) { diff --git a/mittest/logservice/env/ob_simple_log_cluster_testbase.cpp b/mittest/logservice/env/ob_simple_log_cluster_testbase.cpp index daa5ee9c26..7b38261c46 100644 --- a/mittest/logservice/env/ob_simple_log_cluster_testbase.cpp +++ b/mittest/logservice/env/ob_simple_log_cluster_testbase.cpp @@ -29,7 +29,7 @@ namespace unittest std::vector ObSimpleLogClusterTestBase::cluster_; bool ObSimpleLogClusterTestBase::is_started_ = false; common::ObMemberList ObSimpleLogClusterTestBase::member_list_ = ObMemberList(); -common::ObArrayHashMap ObSimpleLogClusterTestBase::member_region_map_; +common::hash::ObHashMap ObSimpleLogClusterTestBase::member_region_map_; common::ObMemberList ObSimpleLogClusterTestBase::node_list_ = ObMemberList(); int64_t ObSimpleLogClusterTestBase::node_idx_base_ = 1002; char ObSimpleLogClusterTestBase::sig_buf_[sizeof(ObSignalWorker) + sizeof(observer::ObSignalHandle)]; @@ -77,7 +77,8 @@ int ObSimpleLogClusterTestBase::start() SERVER_LOG(ERROR, "Start signal worker error", K(ret)); } else if (signal_handle_ != nullptr && OB_FAIL(signal_handle_->start())) { SERVER_LOG(ERROR, "Start signal handle error", K(ret)); - } else if (OB_FAIL(member_region_map_.init("TestBase", OB_MAX_MEMBER_NUMBER))) { + } else if (OB_FAIL(member_region_map_.create(OB_MAX_MEMBER_NUMBER, + ObMemAttr(MTL_ID(), ObModIds::OB_HASH_NODE, ObCtxIds::DEFAULT_CTX_ID)))) { } else if (OB_FAIL(generate_sorted_server_list_(node_cnt_))) { } else { // 如果需要新增arb server,将其作为memberlist最后一项 @@ -93,7 +94,7 @@ int ObSimpleLogClusterTestBase::start() } common::ObAddr server; if (OB_FAIL(node_list_.get_server_by_index(i, server))) { - } else if (OB_FAIL(svr->simple_init(test_name_, server, node_id, true))) { + } else if (OB_FAIL(svr->simple_init(test_name_, server, node_id, &member_region_map_, true))) { SERVER_LOG(WARN, "simple_init failed", K(ret), K(i), K_(node_list)); } else if (OB_FAIL(svr->simple_start(true))) { SERVER_LOG(WARN, "simple_start failed", K(ret), K(i), K_(node_list)); @@ -104,7 +105,7 @@ int ObSimpleLogClusterTestBase::start() if (i < ObSimpleLogClusterTestBase::member_cnt_ && OB_SUCC(ret)) { common::ObMember member; if (OB_FAIL(member_list_.add_member(ObMember(server, 1)))) { - } else if (OB_FAIL(member_region_map_.insert(server, DEFAULT_REGION_NAME))) { + } else if (OB_FAIL(member_region_map_.set_refactored(server, DEFAULT_REGION_NAME))) { SERVER_LOG(WARN, "member_region_map_.insert failed", K(ret), K(server), K_(node_list)); } } diff --git a/mittest/logservice/env/ob_simple_log_cluster_testbase.h b/mittest/logservice/env/ob_simple_log_cluster_testbase.h index ef3993ae69..fed04bc599 100644 --- a/mittest/logservice/env/ob_simple_log_cluster_testbase.h +++ b/mittest/logservice/env/ob_simple_log_cluster_testbase.h @@ -69,7 +69,7 @@ public: } return ObMember(addr, 1); } - const common::ObArrayHashMap &get_member_region_map() const { return member_region_map_; } + common::hash::ObHashMap &get_member_region_map() const { return member_region_map_; } const ObMemberList &get_node_list() const {return node_list_;} int64_t get_node_cnt() const { return node_cnt_; } int64_t get_member_cnt() const { return member_cnt_; } @@ -86,7 +86,7 @@ public: static std::vector cluster_; static ObMemberList member_list_; static ObMemberList node_list_; - static common::ObArrayHashMap member_region_map_; + static common::hash::ObHashMap member_region_map_; static bool is_started_; static int64_t member_cnt_; static int64_t node_cnt_; diff --git a/mittest/logservice/env/ob_simple_log_server.cpp b/mittest/logservice/env/ob_simple_log_server.cpp index 39520d1618..2833dc0921 100644 --- a/mittest/logservice/env/ob_simple_log_server.cpp +++ b/mittest/logservice/env/ob_simple_log_server.cpp @@ -138,6 +138,7 @@ int ObSimpleLogServer::simple_init( const std::string &cluster_name, const common::ObAddr &addr, const int64_t node_id, + LogMemberRegionMap *region_map, const bool is_bootstrap = false) { int ret = OB_SUCCESS; @@ -160,6 +161,8 @@ int ObSimpleLogServer::simple_init( if (is_bootstrap && OB_FAIL(init_memory_dump_timer_())) { SERVER_LOG(ERROR, "init_memory_dump_timer_ failed", K(ret), K_(node_id)); + } else if (is_bootstrap && OB_FAIL(mock_locality_manager_.init(region_map))) { + SERVER_LOG(ERROR, "mock_locality_manager_ init fail", K(ret)); } else if (FALSE_IT(guard.click("init_memory_dump_timer_")) || OB_FAIL(init_network_(addr, is_bootstrap))) { SERVER_LOG(WARN, "init_network failed", K(ret), K(addr)); @@ -411,7 +414,7 @@ int ObSimpleLogServer::init_log_service_() if (OB_FAIL(net_keepalive_->init(&deliver_))) { } else if (OB_FAIL(log_service_.init(opts, clog_dir.c_str(), addr_, allocator_, transport_, &batch_rpc_, &ls_service_, - &location_service_, &reporter_, &log_block_pool_, &sql_proxy_, net_keepalive_))) { + &location_service_, &reporter_, &log_block_pool_, &sql_proxy_, net_keepalive_, &mock_locality_manager_))) { SERVER_LOG(ERROR, "init_log_service_ fail", K(ret)); } else if (OB_FAIL(log_block_pool_.create_tenant(opts.disk_options_.log_disk_usage_limit_size_))) { SERVER_LOG(ERROR, "crete tenant failed", K(ret)); @@ -469,6 +472,7 @@ int ObSimpleLogServer::simple_close(const bool is_shutdown = false) timer_handle_.stop_and_wait(); timer_.destroy(); + mock_locality_manager_.destroy(); } SERVER_LOG(INFO, "stop LogService success", K(ret), K(is_shutdown), K(guard)); return ret; @@ -481,7 +485,7 @@ int ObSimpleLogServer::simple_restart(const std::string &cluster_name, const int ObTimeGuard guard("simple_restart", 0); if (OB_FAIL(simple_close())) { SERVER_LOG(ERROR, "simple_close failed", K(ret)); - } else if (FALSE_IT(guard.click("simple_close")) || OB_FAIL(simple_init(cluster_name, addr_, node_idx))) { + } else if (FALSE_IT(guard.click("simple_close")) || OB_FAIL(simple_init(cluster_name, addr_, node_idx, NULL))) { SERVER_LOG(ERROR, "simple_init failed", K(ret)); } else if (FALSE_IT(guard.click("simple_init")) || OB_FAIL(simple_start())) { SERVER_LOG(ERROR, "simple_start failed", K(ret)); diff --git a/mittest/logservice/env/ob_simple_log_server.h b/mittest/logservice/env/ob_simple_log_server.h index e0644a3a92..04df5dcd10 100644 --- a/mittest/logservice/env/ob_simple_log_server.h +++ b/mittest/logservice/env/ob_simple_log_server.h @@ -238,6 +238,7 @@ public: virtual int simple_init(const std::string &cluster_name, const common::ObAddr &addr, const int64_t node_id, + LogMemberRegionMap *region_map, const bool is_bootstrap) = 0; virtual int simple_start(const bool is_bootstrap) = 0; virtual int simple_close(const bool is_shutdown) = 0; @@ -253,6 +254,7 @@ public: virtual int remove_mock_election(const int64_t palf_id) = 0; virtual int set_leader(const int64_t palf_id, const common::ObAddr &leader, const int64_t new_epoch = 0) = 0; virtual int update_server_log_disk(const int64_t log_disk_size) = 0; + virtual MockObLocalityManager *get_locality_manager() = 0; DECLARE_PURE_VIRTUAL_TO_STRING; }; @@ -278,6 +280,7 @@ public: int simple_init(const std::string &cluster_name, const common::ObAddr &addr, const int64_t node_id, + LogMemberRegionMap *region_map, const bool is_bootstrap) override final; int simple_start(const bool is_bootstrap) override final; int simple_close(const bool is_shutdown) override final; @@ -374,6 +377,7 @@ public: return ret; } int update_server_log_disk(const int64_t log_disk_size); + MockObLocalityManager *get_locality_manager() { return &mock_locality_manager_; } TO_STRING_KV(K_(node_id), K_(addr), KP(palf_env_)); protected: @@ -425,6 +429,7 @@ private: // 内部表中记录日志盘规格 palf::PalfDiskOptions inner_table_disk_opts_; ObLooper looper_; + MockObLocalityManager mock_locality_manager_; obrpc::ObBatchRpc batch_rpc_; int batch_rpc_tg_id_; }; diff --git a/mittest/logservice/test_ob_simple_log_access_mode.cpp b/mittest/logservice/test_ob_simple_log_access_mode.cpp index a8810b7bc0..1148c37eeb 100644 --- a/mittest/logservice/test_ob_simple_log_access_mode.cpp +++ b/mittest/logservice/test_ob_simple_log_access_mode.cpp @@ -196,21 +196,17 @@ TEST_F(TestObSimpleLogClusterAccessMode, add_member) std::vector palf_list; const int64_t CONFIG_CHANGE_TIMEOUT = 10 * 1000 * 1000 * 1000L; // 10s EXPECT_EQ(OB_SUCCESS, create_paxos_group(id, leader_idx, leader)); + EXPECT_EQ(OB_SUCCESS, get_cluster_palf_handle_guard(id, palf_list)); EXPECT_EQ(OB_SUCCESS, submit_log(leader, 200, id)); // set leader's region is different from follower, learner will // register itself to leader std::vector region_list; LogMemberRegionMap region_map; common::ObRegion default_region(DEFAULT_REGION_NAME); - EXPECT_EQ(OB_SUCCESS, region_map.init("localmap", OB_MAX_MEMBER_NUMBER)); - region_map.insert(get_cluster()[0]->get_addr(), default_region); - region_map.insert(get_cluster()[1]->get_addr(), ObRegion("SHANGHAI")); - region_map.insert(get_cluster()[2]->get_addr(), ObRegion("TIANJIN")); - EXPECT_EQ(OB_SUCCESS, leader.palf_handle_impl_->set_paxos_member_region_map(region_map)); - EXPECT_EQ(OB_SUCCESS, get_cluster_palf_handle_guard(id, palf_list)); - palf_list[1]->palf_handle_impl_->set_region(ObRegion("SHANGHAI")); - palf_list[2]->palf_handle_impl_->set_region(ObRegion("TIANJIN")); - + get_cluster()[0]->get_locality_manager()->set_server_region(get_cluster()[0]->get_addr(), default_region); + get_cluster()[0]->get_locality_manager()->set_server_region(get_cluster()[1]->get_addr(), ObRegion("SHANGHAI")); + get_cluster()[0]->get_locality_manager()->set_server_region(get_cluster()[2]->get_addr(), ObRegion("TIANJIN")); + for (auto palf_handle: palf_list) { palf_handle->palf_handle_impl_->update_self_region_(); } AccessMode curr_access_mode; int64_t mode_version, curr_proposal_id; ObRole unused_role; diff --git a/mittest/logservice/test_ob_simple_log_basic_func.cpp b/mittest/logservice/test_ob_simple_log_basic_func.cpp index 91e321fc58..3fd43d9a6a 100644 --- a/mittest/logservice/test_ob_simple_log_basic_func.cpp +++ b/mittest/logservice/test_ob_simple_log_basic_func.cpp @@ -414,7 +414,6 @@ TEST_F(TestObSimpleLogClusterBasicFunc, io_reducer_basic) EXPECT_EQ(OB_SUCCESS, create_paxos_group(id, leader_idx, leader)); LogIOWorker *iow = leader.palf_handle_impl_->log_engine_.log_io_worker_; - iow->batch_io_task_mgr_.has_batched_size_ = 0; iow->batch_io_task_mgr_.handle_count_ = 0; std::vector palf_list; EXPECT_EQ(OB_SUCCESS, get_cluster_palf_handle_guard(id, palf_list)); @@ -426,10 +425,8 @@ TEST_F(TestObSimpleLogClusterBasicFunc, io_reducer_basic) EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10000, leader_idx, 120)); const LSN max_lsn = leader.palf_handle_impl_->get_max_lsn(); wait_lsn_until_flushed(max_lsn, leader); - const int64_t has_batched_size = iow->batch_io_task_mgr_.has_batched_size_; const int64_t handle_count = iow->batch_io_task_mgr_.handle_count_; const int64_t log_id = leader.palf_handle_impl_->sw_.get_max_log_id(); - PALF_LOG_RET(ERROR, OB_ERR_UNEXPECTED, "batched_size", K(has_batched_size), K(log_id)); unblock_net(leader_idx, lag_follower_idx); unblock_net(lag_follower_idx, leader_idx); @@ -442,13 +439,10 @@ TEST_F(TestObSimpleLogClusterBasicFunc, io_reducer_basic) lag_follower_max_lsn = lag_follower.palf_handle_impl_->sw_.max_flushed_end_lsn_; } LogIOWorker *iow_follower = lag_follower.palf_handle_impl_->log_engine_.log_io_worker_; - const int64_t follower_has_batched_size = iow_follower->batch_io_task_mgr_.has_batched_size_; const int64_t follower_handle_count = iow_follower->batch_io_task_mgr_.handle_count_; EXPECT_EQ(OB_SUCCESS, revert_cluster_palf_handle_guard(palf_list)); int64_t cost_ts = ObTimeUtility::current_time() - start_ts; - PALF_LOG_RET(ERROR, OB_SUCCESS, "runlin trace performance", K(cost_ts), K(log_id), K(max_lsn), K(has_batched_size), K(handle_count), - K(follower_has_batched_size), K(follower_handle_count)); } TEST_F(TestObSimpleLogClusterBasicFunc, create_palf_via_middle_lsn) diff --git a/mittest/logservice/test_ob_simple_log_config_change.cpp b/mittest/logservice/test_ob_simple_log_config_change.cpp index b39a7fc1c4..03ff4e7af5 100644 --- a/mittest/logservice/test_ob_simple_log_config_change.cpp +++ b/mittest/logservice/test_ob_simple_log_config_change.cpp @@ -168,7 +168,7 @@ TEST_F(TestObSimpleLogClusterConfigChange, split_brain) EXPECT_EQ(OB_SUCCESS, get_cluster()[follower_C_idx]->get_palf_env()->remove_palf_handle_impl(id)); // step 5 const int64_t node_id = follower_B_idx * 2 + get_node_idx_base(); - EXPECT_EQ(OB_SUCCESS, get_cluster()[follower_B_idx]->simple_init(get_test_name(), follower_b_addr, node_id, false)); + EXPECT_EQ(OB_SUCCESS, get_cluster()[follower_B_idx]->simple_init(get_test_name(), follower_b_addr, node_id, NULL, false)); EXPECT_EQ(OB_SUCCESS, get_cluster()[follower_B_idx]->simple_start(false)); EXPECT_EQ(OB_SUCCESS, submit_log(leader, 100, id)); PalfBaseInfo palf_base_info; @@ -681,8 +681,6 @@ TEST_F(TestObSimpleLogClusterConfigChange, learner) std::vector palf_list; std::vector region_list; common::ObRegion default_region(DEFAULT_REGION_NAME); - LogMemberRegionMap region_map; - EXPECT_EQ(OB_SUCCESS, region_map.init("localmap", OB_MAX_MEMBER_NUMBER)); region_list.push_back(ObRegion("BEIJING")); region_list.push_back(ObRegion("SHANGHAI")); region_list.push_back(ObRegion("TIANJIN")); @@ -707,46 +705,33 @@ TEST_F(TestObSimpleLogClusterConfigChange, learner) EXPECT_EQ(OB_SUCCESS, leader.palf_handle_impl_->add_learner(added_learner, CONFIG_CHANGE_TIMEOUT)); } // check children_cnt - while (false == check_children_valid(palf_list, all_learner)) - { - sleep(1); - PALF_LOG(INFO, "check_children_valid 1"); - } + EXPECT_UNTIL_EQ(true, check_children_valid(palf_list, all_learner)); // change region of one follower bool has_change_region = false; int64_t diff_region_follower_idx = -1; int64_t another_follower_idx = -1; for (int i = 0; i < ObSimpleLogClusterTestBase::member_cnt_; i++) { - const bool not_leader = palf_list[i]->palf_handle_impl_->self_ != leader.palf_handle_impl_->self_; + const common::ObAddr addr = palf_list[i]->palf_handle_impl_->self_; + const bool not_leader = (addr != leader.palf_handle_impl_->self_); if (!has_change_region && not_leader) { - EXPECT_EQ(OB_SUCCESS, palf_list[i]->palf_handle_impl_->set_region(region_list[0])); - region_map.insert(palf_list[i]->palf_handle_impl_->self_, region_list[0]); + get_cluster()[0]->get_locality_manager()->set_server_region(addr, region_list[0]); has_change_region = true; diff_region_follower_idx = i; } else { if (not_leader) { another_follower_idx = i; } - region_map.insert(palf_list[0]->palf_handle_impl_->self_, default_region); + get_cluster()[0]->get_locality_manager()->set_server_region(addr, default_region); } } - // notify leader region of follower i has changed - EXPECT_EQ(OB_SUCCESS, leader.palf_handle_impl_->set_paxos_member_region_map(region_map)); + for (auto palf_handle: palf_list) { palf_handle->palf_handle_impl_->update_self_region_(); } // check children_cnt again - while (false == check_children_valid(palf_list, all_learner)) - { - sleep(1); - PALF_LOG(INFO, "check_children_valid 2"); - } + EXPECT_UNTIL_EQ(true, check_children_valid(palf_list, all_learner)); // after setting region of a follower, parents of all learners should be another follower EXPECT_GE(another_follower_idx, 0); EXPECT_LE(another_follower_idx, 2); ObAddr curr_parent = palf_list[another_follower_idx]->palf_handle_impl_->self_; - while (false == check_parent(palf_list, all_learner, curr_parent)) - { - sleep(1); - PALF_LOG(INFO, "check_parent 1"); - } + EXPECT_UNTIL_EQ(true, check_parent(palf_list, all_learner, curr_parent)); // continue submitting log EXPECT_EQ(OB_SUCCESS, submit_log(leader, 20, id)); PALF_LOG(INFO, "all_learner", K(all_learner)); @@ -757,11 +742,7 @@ TEST_F(TestObSimpleLogClusterConfigChange, learner) EXPECT_EQ(OB_SUCCESS, leader.palf_handle_impl_->switch_acceptor_to_learner(ObMember(curr_parent, 1), 2, CONFIG_CHANGE_TIMEOUT)); // after switch follower 1 to learner, a learner will be registered to leader, and other learners will // be registerd to this learner - while (false == check_children_valid(palf_list, all_learner)) - { - sleep(1); - PALF_LOG(INFO, "check_children_valid 3"); - } + EXPECT_UNTIL_EQ(true, check_children_valid(palf_list, all_learner)); // check learner topology ObAddr leaderschild; PalfHandleImplGuard leaderschild_handle; @@ -780,37 +761,21 @@ TEST_F(TestObSimpleLogClusterConfigChange, learner) PalfHandleImplGuard tmp_handle; common::ObMember learner; EXPECT_EQ(OB_SUCCESS, node_list.get_member_by_index(i, learner)); - EXPECT_EQ(OB_SUCCESS, get_palf_handle_guard(palf_list, learner.get_server(), tmp_handle)); - EXPECT_EQ(OB_SUCCESS, tmp_handle.palf_handle_impl_->set_region(region_list[i-2])); + get_cluster()[0]->get_locality_manager()->set_server_region(learner.get_server(), region_list[i-2]); } + for (auto palf_handle: palf_list) { palf_handle->palf_handle_impl_->update_self_region_(); } sleep(1); // check children_cnt - while (false == check_children_valid(palf_list, all_learner)) - { - sleep(1); - PALF_LOG(INFO, "check_children_valid 4"); - } - while (false == check_parent(palf_list, all_learner, leader.palf_handle_impl_->self_)) - { - sleep(1); - PALF_LOG(INFO, "check_parent 2"); - } + EXPECT_UNTIL_EQ(true, check_children_valid(palf_list, all_learner)); + EXPECT_UNTIL_EQ(true, check_parent(palf_list, all_learner, leader.palf_handle_impl_->self_)); // switch leader, after switching leader, the parent of all learners is the new leader const int64_t new_leader_idx = diff_region_follower_idx; PalfHandleImplGuard new_leader; EXPECT_EQ(OB_SUCCESS, switch_leader(id, 0, new_leader)); - while (false == check_children_valid(palf_list, all_learner)) - { - sleep(1); - PALF_LOG(INFO, "check_children_valid 5"); - } - while (false == check_parent(palf_list, all_learner, new_leader.palf_handle_impl_->self_)) - { - sleep(1); - PALF_LOG(INFO, "check_parent 3"); - } + EXPECT_UNTIL_EQ(true, check_children_valid(palf_list, all_learner)); + EXPECT_UNTIL_EQ(true, check_parent(palf_list, all_learner, new_leader.palf_handle_impl_->self_)); revert_cluster_palf_handle_guard(palf_list); PALF_LOG(INFO, "end test learner", K(id)); @@ -1037,17 +1002,18 @@ TEST_F(TestObSimpleLogClusterConfigChange, learner_loop) } // set region, version 42x - // for (int i = 0; i < ObSimpleLogClusterTestBase::node_cnt_; i++) { - // const common::ObAddr addr = palf_list[i]->palf_handle_impl_->self_; - // if (leader.palf_handle_impl_->config_mgr_.alive_paxos_memberlist_.contains(addr)) { - // get_cluster()[0]->get_locality_manager()->set_server_region(addr, beijing_region); - // } else { - // get_cluster()[0]->get_locality_manager()->set_server_region(addr, shanghai_region); - // } - // } - // for (auto palf_handle: palf_list) { palf_handle->palf_handle_impl_->update_self_region_(); } + for (int i = 0; i < ObSimpleLogClusterTestBase::node_cnt_; i++) { + const common::ObAddr addr = palf_list[i]->palf_handle_impl_->self_; + if (leader.palf_handle_impl_->config_mgr_.alive_paxos_memberlist_.contains(addr)) { + get_cluster()[0]->get_locality_manager()->set_server_region(addr, beijing_region); + } else { + get_cluster()[0]->get_locality_manager()->set_server_region(addr, shanghai_region); + } + } + for (auto palf_handle: palf_list) { palf_handle->palf_handle_impl_->update_self_region_(); } // set region, version 421, master + /* LogMemberRegionMap region_map; EXPECT_EQ(OB_SUCCESS, region_map.init("localmap", OB_MAX_MEMBER_NUMBER)); for (int i = 0; i < ObSimpleLogClusterTestBase::member_cnt_; i++) { @@ -1060,8 +1026,9 @@ TEST_F(TestObSimpleLogClusterConfigChange, learner_loop) region_map.insert(addr, shanghai_region); } } + */ // notify leader region of follower i has changed - EXPECT_EQ(OB_SUCCESS, leader.palf_handle_impl_->set_paxos_member_region_map(region_map)); + // EXPECT_EQ(OB_SUCCESS, leader.palf_handle_impl_->set_paxos_member_region_map(region_map)); // check topo EXPECT_UNTIL_EQ(true, check_children_valid(palf_list, all_learner)); @@ -1115,8 +1082,8 @@ TEST_F(TestObSimpleLogClusterConfigChange, learner_loop) for (auto palf_handle: palf_list) { const common::ObAddr addr = palf_handle->palf_handle_impl_->self_; if (true == all_learner.contains(addr) && addr != any_child) { - palf_handle->palf_handle_impl_->config_mgr_.retire_parent_(); - palf_handle->palf_handle_impl_->config_mgr_.register_parent_(); + palf_handle->palf_handle_impl_->config_mgr_.retire_parent_(LogConfigMgr::RetireParentReason::SELF_REGION_CHANGED); + palf_handle->palf_handle_impl_->config_mgr_.register_parent_(LogConfigMgr::RegisterParentReason::FIRST_REGISTER); } } diff --git a/mittest/logservice/test_ob_simple_log_disk_mgr.cpp b/mittest/logservice/test_ob_simple_log_disk_mgr.cpp old mode 100644 new mode 100755 index e2892d5c68..510b5e553e --- a/mittest/logservice/test_ob_simple_log_disk_mgr.cpp +++ b/mittest/logservice/test_ob_simple_log_disk_mgr.cpp @@ -63,6 +63,7 @@ int64_t ObSimpleLogClusterTestBase::member_cnt_ = 1; int64_t ObSimpleLogClusterTestBase::node_cnt_ = 1; std::string ObSimpleLogClusterTestBase::test_name_ = TEST_NAME; bool ObSimpleLogClusterTestBase::need_add_arb_server_ = false; +int64_t log_entry_size = 2 * 1024 * 1024 + 16 * 1024; TEST_F(TestObSimpleLogDiskMgr, out_of_disk_space) { @@ -78,19 +79,20 @@ TEST_F(TestObSimpleLogDiskMgr, out_of_disk_space) EXPECT_EQ(OB_SUCCESS, get_palf_env(server_idx, palf_env)); EXPECT_EQ(OB_SUCCESS, create_paxos_group(id, create_scn, leader_idx, leader)); update_disk_options(leader_idx, MIN_DISK_SIZE_PER_PALF_INSTANCE/PALF_PHY_BLOCK_SIZE + 2); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 8*31+1, id, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 8*31+1, id, log_entry_size)); LogStorage *log_storage = &leader.palf_handle_impl_->log_engine_.log_storage_; while (LSN(6*PALF_BLOCK_SIZE) > log_storage->log_tail_) { usleep(500); } - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 20, id, MAX_LOG_BODY_SIZE)); - while (LSN(6*PALF_BLOCK_SIZE + 20 * MAX_LOG_BODY_SIZE) > log_storage->log_tail_) { + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 20, id, log_entry_size)); + while (LSN(6*PALF_BLOCK_SIZE + 20 * log_entry_size) > log_storage->log_tail_) { usleep(500); } LSN max_lsn = leader.palf_handle_impl_->get_max_lsn(); wait_lsn_until_flushed(max_lsn, leader); PALF_LOG(INFO, "out of disk max_lsn", K(max_lsn)); usleep(palf::BlockGCTimerTask::BLOCK_GC_TIMER_INTERVAL_MS + 5*10000); + sleep(2); EXPECT_EQ(OB_LOG_OUTOF_DISK_SPACE, submit_log(leader, 1, id, MAX_LOG_BODY_SIZE)); // shrinking 后继续停写 update_disk_options(leader_idx, MIN_DISK_SIZE_PER_PALF_INSTANCE/PALF_PHY_BLOCK_SIZE); @@ -113,7 +115,7 @@ TEST_F(TestObSimpleLogDiskMgr, update_disk_options_basic) EXPECT_EQ(OB_SUCCESS, get_palf_env(leader_idx, palf_env)); // 提交1G的日志 - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 500, id, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 500, id, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_lsn_until_flushed(leader.palf_handle_impl_->get_max_lsn(), leader)); EXPECT_EQ(OB_SUCCESS, update_disk_options(leader_idx, 20)); @@ -234,7 +236,7 @@ TEST_F(TestObSimpleLogDiskMgr, update_disk_options_restart) palf_env->palf_env_impl_.disk_options_wrapper_.disk_opts_for_recycling_blocks_.log_disk_usage_limit_size_); } // 产生10个文件的数据 - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10*32, id, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10*32, id, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, leader.palf_handle_impl_->get_max_lsn())); // 最小的log_disk_size要求是存在8个日志文件 EXPECT_EQ(OB_SUCCESS, update_disk_options(leader_idx, 8)); @@ -349,7 +351,7 @@ TEST_F(TestObSimpleLogDiskMgr, overshelling) PalfHandleImplGuard leader; EXPECT_EQ(OB_SUCCESS, get_leader(id, leader, leader_idx)); // 生成10个文件 - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10*32, id, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10*32, id, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, leader.palf_handle_impl_->get_max_lsn())); EXPECT_EQ(OB_SUCCESS, update_disk_options(leader_idx, 10)); // 缩容一定不会成功,租户日志盘规格依旧为上限值 @@ -433,6 +435,42 @@ TEST_F(TestObSimpleLogDiskMgr, hidden_sys) EXPECT_NE(0, total_used_size); } +TEST_F(TestObSimpleLogDiskMgr, test_big_log) +{ + update_server_log_disk(10*1024*1024*1024ul); + update_disk_options(10*1024*1024*1024ul/palf::PALF_PHY_BLOCK_SIZE); + SET_CASE_LOG_FILE(TEST_NAME, "test_big_log"); + int64_t id = ATOMIC_AAF(&palf_id_, 1); + int server_idx = 0; + PalfEnv *palf_env = NULL; + int64_t leader_idx = 0; + PalfHandleImplGuard leader; + share::SCN create_scn = share::SCN::base_scn(); + EXPECT_EQ(OB_SUCCESS, get_palf_env(server_idx, palf_env)); + EXPECT_EQ(OB_SUCCESS, create_paxos_group(id, create_scn, leader_idx, leader)); + update_disk_options(leader_idx, MIN_DISK_SIZE_PER_PALF_INSTANCE/PALF_PHY_BLOCK_SIZE); + // write big log + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 11, id, MAX_LOG_BODY_SIZE)); + LogStorage *log_storage = &leader.palf_handle_impl_->log_engine_.log_storage_; + while(LSN(10*MAX_LOG_BODY_SIZE) > log_storage->log_tail_) { + usleep(500); + } + LSN max_lsn = leader.palf_handle_impl_->get_max_lsn(); + wait_lsn_until_flushed(max_lsn, leader); + PALF_LOG(INFO, "test_big_log max_lsn after writing big log", K(max_lsn)); + + // write small log + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 11, id, log_entry_size)); + while(LSN(10*log_entry_size) > log_storage->log_tail_) { + usleep(500); + } + + max_lsn = leader.palf_handle_impl_->get_max_lsn(); + wait_lsn_until_flushed(max_lsn, leader); + PALF_LOG(INFO, "test_big_log max_lsn after writing small log", K(max_lsn)); + EXPECT_EQ(OB_ITER_END, read_log(leader)); +} + } // namespace unittest } // namespace oceanbase diff --git a/mittest/logservice/test_ob_simple_log_engine.cpp b/mittest/logservice/test_ob_simple_log_engine.cpp index 7849223d10..81dc18c0f7 100644 --- a/mittest/logservice/test_ob_simple_log_engine.cpp +++ b/mittest/logservice/test_ob_simple_log_engine.cpp @@ -188,6 +188,7 @@ int64_t ObSimpleLogClusterTestBase::member_cnt_ = 1; int64_t ObSimpleLogClusterTestBase::node_cnt_ = 1; std::string ObSimpleLogClusterTestBase::test_name_ = TEST_NAME; bool ObSimpleLogClusterTestBase::need_add_arb_server_ = false; +int64_t log_entry_size = 2 * 1024 * 1024 + 16 * 1024; // 验证flashback过程中宕机重启 TEST_F(TestObSimpleLogClusterLogEngine, flashback_restart) @@ -392,6 +393,10 @@ TEST_F(TestObSimpleLogClusterLogEngine, exception_path) EXPECT_EQ(OB_ENTRY_NOT_EXIST, log_storage->get_block_id_range(min_block_id, max_block_id)); // truncate_prefix_block_id 和 prev_lsn对应的block_id一样 EXPECT_EQ(log_storage->log_tail_, LSN(truncate_prefix_block_id * PALF_BLOCK_SIZE)); + // truncate_prefxi_blocks后,min_block_info被置为无效 + EXPECT_EQ(false, is_valid_block_id(log_engine_->min_block_id_)); + EXPECT_EQ(false, log_engine_->min_block_min_scn_.is_valid()); + EXPECT_EQ(false, log_engine_->min_block_max_scn_.is_valid()); // 测试目录清空后,读数据是否正常报错 ReadBufGuard buf_guard("dummy", 100); @@ -411,6 +416,11 @@ TEST_F(TestObSimpleLogClusterLogEngine, exception_path) io_ctx)); // 测试目录清空后,重启是否正常 EXPECT_EQ(OB_SUCCESS, reload(log_engine_->log_storage_.log_tail_, log_engine_->log_meta_storage_.log_tail_, log_engine_->log_meta_.log_snapshot_meta_.base_lsn_)); + { + block_id_t tmp_block_id = LOG_INVALID_BLOCK_ID; + SCN tmp_scn; + EXPECT_EQ(OB_ENTRY_NOT_EXIST, log_engine_->get_min_block_info(tmp_block_id, tmp_scn)); + } PALF_LOG(INFO, "directory is empty"); // 测试目录清空后,写数据是否正常 @@ -455,7 +465,6 @@ TEST_F(TestObSimpleLogClusterLogEngine, io_reducer_basic_func) LogIOWorker *log_io_worker = leader_1.palf_handle_impl_->log_engine_.log_io_worker_; int64_t prev_log_id_1 = 0; - int64_t prev_has_batched_size = 0; LogEngine *log_engine = &leader_1.palf_handle_impl_->log_engine_; IOTaskCond io_task_cond_1(id_1, log_engine->palf_epoch_); IOTaskVerify io_task_verify_1(id_1, log_engine->palf_epoch_); @@ -470,9 +479,7 @@ TEST_F(TestObSimpleLogClusterLogEngine, io_reducer_basic_func) wait_lsn_until_flushed(max_lsn, leader_1); EXPECT_EQ(OB_ITER_END, read_log(leader_1)); // sw内部做了自适应freeze之后这个等式可能不成立, 因为上层可能基于写盘反馈触发提交下一个io_task -// EXPECT_EQ(log_id, log_io_worker->batch_io_task_mgr_.has_batched_size_); prev_log_id_1 = log_id; - prev_has_batched_size = log_io_worker->batch_io_task_mgr_.has_batched_size_; } // 单日志流场景 // 当聚合度为1的时候,应该走正常的提交流程,目前暂未实现,先通过has_batched_size不计算绕过 @@ -488,12 +495,8 @@ TEST_F(TestObSimpleLogClusterLogEngine, io_reducer_basic_func) LSN max_lsn = leader_1.palf_handle_impl_->sw_.get_max_lsn(); io_task_cond_1.cond_.signal(); wait_lsn_until_flushed(max_lsn, leader_1); -// EXPECT_EQ(log_id - 1, log_io_worker->batch_io_task_mgr_.has_batched_size_); EXPECT_EQ(2, io_task_verify_1.count_); -// EXPECT_EQ(log_io_worker->batch_io_task_mgr_.has_batched_size_ - prev_has_batched_size, -// log_id - prev_log_id_1 - 1); prev_log_id_1 = log_id; - prev_has_batched_size = log_io_worker->batch_io_task_mgr_.has_batched_size_; } // 多日志流场景 @@ -529,9 +532,6 @@ TEST_F(TestObSimpleLogClusterLogEngine, io_reducer_basic_func) EXPECT_EQ(1, io_task_verify_2.count_); // ls1已经有个一个log_id被忽略聚合了 -// EXPECT_EQ(log_io_worker->batch_io_task_mgr_.has_batched_size_ - prev_has_batched_size, -// log_id_1 - 1 + log_id_2 -1 - prev_log_id_1); - prev_has_batched_size = log_io_worker->batch_io_task_mgr_.has_batched_size_; prev_log_id_2 = log_id_2; prev_log_id_1 = log_id_1; } @@ -564,7 +564,6 @@ TEST_F(TestObSimpleLogClusterLogEngine, io_reducer_basic_func) // wait_lsn_until_flushed(max_lsn_1, leader_1); // wait_lsn_until_flushed(max_lsn_2, leader_2); // wait_lsn_until_flushed(max_lsn_3, leader_3); - // EXPECT_EQ(log_io_worker->batch_io_task_mgr_.has_batched_size_ - prev_has_batched_size, 0); // } // 验证切文件场景 int64_t id_3 = ATOMIC_AAF(&palf_id_, 1); @@ -593,8 +592,7 @@ TEST_F(TestObSimpleLogClusterLogEngine, io_reducer_basic_func) wait_lsn_until_flushed(max_lsn_1, leader_1); wait_lsn_until_flushed(max_lsn_2, leader_2); wait_lsn_until_flushed(max_lsn_3, leader_3); -// EXPECT_EQ(log_io_worker->batch_io_task_mgr_.has_batched_size_ - prev_has_batched_size, 2); - EXPECT_EQ(OB_SUCCESS, submit_log(leader_1, 31, leader_idx_1, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader_1, 31, leader_idx_1, log_entry_size)); EXPECT_EQ(OB_SUCCESS, submit_log(leader_1, 2, leader_idx_1, 900 *1024)); max_lsn_1 = leader_1.palf_handle_impl_->get_max_lsn(); wait_lsn_until_flushed(max_lsn_1, leader_1); @@ -676,58 +674,130 @@ TEST_F(TestObSimpleLogClusterLogEngine, io_reducer_basic_func) } PALF_LOG(INFO, "begin test sw full case"); - // 测试滑动窗口满场景 - // 聚合的两条日志分别在头尾部 - int64_t id_6 = ATOMIC_AAF(&palf_id_, 1); - int64_t leader_idx_6 = 0; - int64_t prev_log_id_6 = 0; - PalfHandleImplGuard leader_6; - IOTaskCond io_task_cond_6(id_6, log_engine->palf_epoch_); - IOTaskVerify io_task_verify_6(id_6, log_engine->palf_epoch_); - EXPECT_EQ(OB_SUCCESS, create_paxos_group(id_6, leader_idx_6, leader_6)); - { - LogIOWorker *log_io_worker = leader_6.palf_handle_impl_->log_engine_.log_io_worker_; - { - EXPECT_EQ(OB_SUCCESS, submit_log(leader_6, 15, id_6, MAX_LOG_BODY_SIZE)); - sleep(2); - LSN max_lsn = leader_6.palf_handle_impl_->sw_.get_max_lsn(); - wait_lsn_until_flushed(max_lsn, leader_6); - EXPECT_EQ(OB_SUCCESS, log_io_worker->submit_io_task(&io_task_cond_6)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader_6, 1, id_6, 10*1024)); - sleep(1); - LSN max_lsn1 = leader_6.palf_handle_impl_->sw_.get_max_lsn(); - int64_t remain_size = LEADER_DEFAULT_GROUP_BUFFER_SIZE - max_lsn1.val_ - LogGroupEntryHeader::HEADER_SER_SIZE - LogEntryHeader::HEADER_SER_SIZE; - EXPECT_EQ(OB_SUCCESS, submit_log(leader_6, 1, id_6, remain_size)); - sleep(1); - LSN max_lsn2 = leader_6.palf_handle_impl_->sw_.get_max_lsn(); - PALF_LOG_RET(ERROR, OB_SUCCESS, "runlin trace", K(max_lsn2), K(max_lsn1), K(remain_size), K(max_lsn)); - EXPECT_EQ(max_lsn2, LSN(LEADER_DEFAULT_GROUP_BUFFER_SIZE)); - io_task_cond_6.cond_.signal(); - wait_lsn_until_flushed(max_lsn2, leader_6); - } - EXPECT_EQ(OB_SUCCESS, submit_log(leader_6, 3, id_6, MAX_LOG_BODY_SIZE)); - sleep(2); - LSN max_lsn = leader_6.palf_handle_impl_->sw_.get_max_lsn(); - wait_lsn_until_flushed(max_lsn, leader_6); - EXPECT_EQ(OB_SUCCESS, log_io_worker->submit_io_task(&io_task_cond_6)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader_6, 1, id_6, 10*1024)); - sleep(1); - LSN max_lsn1 = leader_6.palf_handle_impl_->sw_.get_max_lsn(); - int64_t remain_size = FOLLOWER_DEFAULT_GROUP_BUFFER_SIZE - max_lsn1.val_ - LogGroupEntryHeader::HEADER_SER_SIZE - LogEntryHeader::HEADER_SER_SIZE; - EXPECT_EQ(OB_SUCCESS, submit_log(leader_6, 1, id_6, remain_size)); - sleep(1); - LSN max_lsn2 = leader_6.palf_handle_impl_->sw_.get_max_lsn(); - PALF_LOG_RET(ERROR, OB_SUCCESS, "runlin trace", K(max_lsn2), K(max_lsn1), K(remain_size), K(max_lsn)); - EXPECT_EQ(max_lsn2, LSN(FOLLOWER_DEFAULT_GROUP_BUFFER_SIZE)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader_6, 1, id_6, 100)); - sleep(1); - LSN max_lsn3 = leader_6.palf_handle_impl_->sw_.get_max_lsn(); - io_task_cond_6.cond_.signal(); - //EXPECT_EQ(max_lsn, leader_6.palf_handle_.palf_handle_impl_->log_engine_.log_storage_.log_tail_); - wait_lsn_until_flushed(max_lsn3, leader_6); - LSN log_tail = leader_6.palf_handle_impl_->log_engine_.log_storage_.log_tail_; - EXPECT_EQ(max_lsn3, log_tail); - } + // 测试滑动窗口满场景 + // 聚合的两条日志分别在头尾部 + int64_t id_6 = ATOMIC_AAF(&palf_id_, 1); + int64_t leader_idx_6 = 0; + int64_t prev_log_id_6 = 0; + PalfHandleImplGuard leader_6; + IOTaskCond io_task_cond_6(id_6, log_engine->palf_epoch_); + IOTaskVerify io_task_verify_6(id_6, log_engine->palf_epoch_); + EXPECT_EQ(OB_SUCCESS, create_paxos_group(id_6, leader_idx_6, leader_6)); + { + LogIOWorker *log_io_worker = leader_6.palf_handle_impl_->log_engine_.log_io_worker_; + { + EXPECT_EQ(OB_SUCCESS, submit_log(leader_6, 15, id_6, log_entry_size)); + sleep(2); + LSN max_lsn = leader_6.palf_handle_impl_->sw_.get_max_lsn(); + wait_lsn_until_flushed(max_lsn, leader_6); + EXPECT_EQ(OB_SUCCESS, log_io_worker->submit_io_task(&io_task_cond_6)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader_6, 1, id_6, 10*1024)); + sleep(1); + LSN max_lsn1 = leader_6.palf_handle_impl_->sw_.get_max_lsn(); + int64_t remain_size = LEADER_DEFAULT_GROUP_BUFFER_SIZE - max_lsn1.val_ - LogGroupEntryHeader::HEADER_SER_SIZE - LogEntryHeader::HEADER_SER_SIZE; + EXPECT_EQ(OB_SUCCESS, submit_log(leader_6, 1, id_6, remain_size)); + sleep(1); + LSN max_lsn2 = leader_6.palf_handle_impl_->sw_.get_max_lsn(); + PALF_LOG_RET(ERROR, OB_SUCCESS, "runlin trace", K(max_lsn2), K(max_lsn1), K(remain_size), K(max_lsn)); + EXPECT_EQ(max_lsn2, LSN(LEADER_DEFAULT_GROUP_BUFFER_SIZE)); + io_task_cond_6.cond_.signal(); + wait_lsn_until_flushed(max_lsn2, leader_6); + } + EXPECT_EQ(OB_SUCCESS, submit_log(leader_6, 3, id_6, log_entry_size)); + sleep(2); + LSN max_lsn = leader_6.palf_handle_impl_->sw_.get_max_lsn(); + wait_lsn_until_flushed(max_lsn, leader_6); + EXPECT_EQ(OB_SUCCESS, log_io_worker->submit_io_task(&io_task_cond_6)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader_6, 1, id_6, 10*1024)); + sleep(1); + LSN max_lsn1 = leader_6.palf_handle_impl_->sw_.get_max_lsn(); + int64_t remain_size = FOLLOWER_DEFAULT_GROUP_BUFFER_SIZE - max_lsn1.val_ - LogGroupEntryHeader::HEADER_SER_SIZE - LogEntryHeader::HEADER_SER_SIZE; + EXPECT_EQ(OB_SUCCESS, submit_log(leader_6, 1, id_6, remain_size)); + sleep(1); + LSN max_lsn2 = leader_6.palf_handle_impl_->sw_.get_max_lsn(); + PALF_LOG_RET(ERROR, OB_SUCCESS, "runlin trace", K(max_lsn2), K(max_lsn1), K(remain_size), K(max_lsn)); + EXPECT_EQ(max_lsn2, LSN(FOLLOWER_DEFAULT_GROUP_BUFFER_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader_6, 1, id_6, 100)); + sleep(1); + LSN max_lsn3 = leader_6.palf_handle_impl_->sw_.get_max_lsn(); + io_task_cond_6.cond_.signal(); + //EXPECT_EQ(max_lsn, leader_6.palf_handle_.palf_handle_impl_->log_engine_.log_storage_.log_tail_); + wait_lsn_until_flushed(max_lsn3, leader_6); + LSN log_tail = leader_6.palf_handle_impl_->log_engine_.log_storage_.log_tail_; + EXPECT_EQ(max_lsn3, log_tail); + } + +} + + +TEST_F(TestObSimpleLogClusterLogEngine, limit_reduce_task) +{ + SET_CASE_LOG_FILE(TEST_NAME, "limit_reduce_task"); + // 验证限制单个reduce task size为1M + int64_t id_7 = ATOMIC_AAF(&palf_id_, 1); + int64_t leader_idx_7 = 0; + int64_t prev_log_id_7 = 0; + PalfHandleImplGuard leader_7; + EXPECT_EQ(OB_SUCCESS, create_paxos_group(id_7, leader_idx_7, leader_7)); + LogEngine *log_engine = &leader_7.palf_handle_impl_->log_engine_; + IOTaskCond io_task_cond_7(id_7, log_engine->palf_epoch_); + IOTaskVerify io_task_verify_7(id_7, log_engine->palf_epoch_); + { + BatchLogIOFlushLogTask::SINGLE_TASK_MAX_SIZE = 1*1024*1024; + LogIOWorker *log_io_worker = leader_7.palf_handle_impl_->log_engine_.log_io_worker_; + log_io_worker->batch_io_task_mgr_.handle_count_ = 0; + // case1: 测试单条日志超过SINGLE_TASK_MAX_SIZE + // 阻塞提交 + EXPECT_EQ(OB_SUCCESS, log_io_worker->submit_io_task(&io_task_cond_7)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader_7, 15, id_7, log_entry_size)); + io_task_cond_7.cond_.signal(); + { + LSN max_lsn = leader_7.palf_handle_impl_->sw_.get_max_lsn(); + wait_lsn_until_flushed(max_lsn, leader_7); + } + // 单条日志超过SINGLE_TASK_MAX_SIZE,会reduce一次, 第二条日志不会被reduce + EXPECT_EQ(8, log_io_worker->batch_io_task_mgr_.handle_count_); + + PALF_LOG(INFO, "case 2"); + + // case2:测试日志大小混合场景 + // 阻塞提交 + EXPECT_EQ(OB_SUCCESS, log_io_worker->submit_io_task(&io_task_cond_7)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader_7, 15, id_7, 1024)); + io_task_cond_7.cond_.signal(); + { + LSN max_lsn = leader_7.palf_handle_impl_->sw_.get_max_lsn(); + wait_lsn_until_flushed(max_lsn, leader_7); + } + EXPECT_LE(8, log_io_worker->batch_io_task_mgr_.handle_count_); + int64_t prev_handle_count = log_io_worker->batch_io_task_mgr_.handle_count_; + EXPECT_EQ(OB_SUCCESS, submit_log(leader_7, 15, id_7, 1024)); + { + LSN max_lsn = leader_7.palf_handle_impl_->sw_.get_max_lsn(); + wait_lsn_until_flushed(max_lsn, leader_7); + } + EXPECT_LE(prev_handle_count, log_io_worker->batch_io_task_mgr_.handle_count_); + prev_handle_count = log_io_worker->batch_io_task_mgr_.handle_count_; + EXPECT_EQ(OB_SUCCESS, submit_log(leader_7, 1, id_7, log_entry_size)); + { + LSN max_lsn = leader_7.palf_handle_impl_->sw_.get_max_lsn(); + wait_lsn_until_flushed(max_lsn, leader_7); + } + EXPECT_EQ(prev_handle_count+1, log_io_worker->batch_io_task_mgr_.handle_count_); + prev_handle_count = log_io_worker->batch_io_task_mgr_.handle_count_; + PALF_LOG(INFO, "after first LT"); + + // case3:测试小日志场景 + EXPECT_EQ(OB_SUCCESS, log_io_worker->submit_io_task(&io_task_cond_7)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader_7, 30, id_7, 1024)); + io_task_cond_7.cond_.signal(); + { + LSN max_lsn = leader_7.palf_handle_impl_->sw_.get_max_lsn(); + wait_lsn_until_flushed(max_lsn, leader_7); + } + EXPECT_LE(prev_handle_count, log_io_worker->batch_io_task_mgr_.handle_count_); + PALF_LOG(INFO, "after second LT"); + } PALF_LOG(INFO, "end io_reducer_basic_func"); } @@ -741,13 +811,11 @@ TEST_F(TestObSimpleLogClusterLogEngine, io_reducer_basic_func) // int64_t leader_idx = 0; // PalfHandleImplGuard leader; // EXPECT_EQ(OB_SUCCESS, create_paxos_group(id, leader_idx, leader)); -// leader.palf_env_impl_->log_io_worker_.batch_io_task_mgr_.has_batched_size_ = 0; // leader.palf_env_impl_->log_io_worker_.batch_io_task_mgr_.handle_count_ = 0; // int64_t start_ts = ObTimeUtility::current_time(); // EXPECT_EQ(OB_SUCCESS, submit_log(leader, 40 * 10000, leader_idx, 100)); // const LSN max_lsn = leader.palf_handle_impl_->get_max_lsn(); // wait_lsn_until_flushed(max_lsn, leader); -// const int64_t has_batched_size = leader.palf_env_impl_->log_io_worker_.batch_io_task_mgr_.has_batched_size_; // const int64_t handle_count = leader.palf_env_impl_->log_io_worker_.batch_io_task_mgr_.handle_count_; // const int64_t log_id = leader.palf_handle_impl_->sw_.get_max_log_id(); // int64_t cost_ts = ObTimeUtility::current_time() - start_ts; diff --git a/mittest/logservice/test_ob_simple_log_replay.cpp b/mittest/logservice/test_ob_simple_log_replay.cpp index 34443299a7..3922c6728a 100644 --- a/mittest/logservice/test_ob_simple_log_replay.cpp +++ b/mittest/logservice/test_ob_simple_log_replay.cpp @@ -110,6 +110,7 @@ int64_t ObSimpleLogClusterTestBase::member_cnt_ = 1; int64_t ObSimpleLogClusterTestBase::node_cnt_ = 1; std::string ObSimpleLogClusterTestBase::test_name_ = TEST_NAME; bool ObSimpleLogClusterTestBase::need_add_arb_server_ = false; +int64_t log_entry_size = 2 * 1024 * 1024 + 16 * 1024; TEST_F(TestObSimpleLogReplayFunc, basic_replay) { @@ -155,7 +156,7 @@ TEST_F(TestObSimpleLogReplayFunc, basic_replay) ls_adapter.wait_replay_done(task_count); bool is_done = false; LSN end_lsn = leader.palf_handle_impl_->get_end_lsn(); - LSN max_lsn = leader.palf_handle_impl_->get_max_lsn();; + LSN max_lsn = leader.palf_handle_impl_->get_max_lsn(); EXPECT_EQ(end_lsn.val_, max_lsn.val_); while (!is_done) { rp_sv.is_replay_done(ls_id, end_lsn, is_done); @@ -251,17 +252,17 @@ TEST_F(TestObSimpleLogReplayFunc, test_flashback_to_padding) iterator.iterator_storage_.get_file_end_lsn_ = get_file_end_lsn; // 停止拉日志 rp_st->block_submit(); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 31, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 31, leader_idx, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, leader.get_palf_handle_impl()->get_max_lsn())); LogStorage *log_storage = &leader.get_palf_handle_impl()->log_engine_.log_storage_; LSN padding_header = log_storage->log_tail_; SCN padding_header_scn = leader.get_palf_handle_impl()->get_max_scn(); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, leader.get_palf_handle_impl()->get_max_lsn())); LSN log_tail = log_storage->log_tail_; SCN padding_tail_scn = leader.get_palf_handle_impl()->get_end_scn(); EXPECT_LE(padding_header, LSN(PALF_BLOCK_SIZE)); - EXPECT_GE(padding_header+MAX_LOG_BODY_SIZE, LSN(PALF_BLOCK_SIZE)); + EXPECT_GE(padding_header+log_entry_size, LSN(PALF_BLOCK_SIZE)); int64_t mode_version; switch_append_to_flashback(leader, mode_version); @@ -293,7 +294,7 @@ TEST_F(TestObSimpleLogReplayFunc, test_flashback_to_padding) iterator_end_lsn = LSN(100000000); // 停止拉日志 rp_st->block_submit(); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, log_entry_size)); padding_tail_scn = leader.get_palf_handle_impl()->get_max_scn(); LSN max_lsn = leader.get_palf_handle_impl()->get_max_lsn(); EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, max_lsn)); @@ -328,7 +329,7 @@ TEST_F(TestObSimpleLogReplayFunc, test_flashback_to_padding) switch_flashback_to_append(leader, mode_version); // 停止拉日志 rp_st->block_submit(); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, log_entry_size)); padding_tail_scn = leader.get_palf_handle_impl()->get_max_scn(); LSN max_lsn = leader.get_palf_handle_impl()->get_max_lsn(); EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, max_lsn)); @@ -368,7 +369,7 @@ TEST_F(TestObSimpleLogReplayFunc, test_flashback_to_padding) EXPECT_EQ(LSN(PALF_BLOCK_SIZE), rp_st->submit_log_task_.next_to_submit_lsn_); switch_flashback_to_append(leader, mode_version); rp_st->block_submit(); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, log_entry_size)); padding_tail_scn = leader.get_palf_handle_impl()->get_max_scn(); LSN max_lsn = leader.get_palf_handle_impl()->get_max_lsn(); EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, max_lsn)); @@ -414,7 +415,7 @@ TEST_F(TestObSimpleLogReplayFunc, test_wait_replay_done) } PalfBufferIterator &iterator = rp_st->submit_log_task_.iterator_; iterator.iterator_storage_.get_file_end_lsn_ = get_file_end_lsn; - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 31, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 31, leader_idx, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, leader.get_palf_handle_impl()->get_max_lsn())); int64_t remained_log_size = LSN(PALF_BLOCK_SIZE) - leader.get_palf_handle_impl()->get_max_lsn() - sizeof(LogGroupEntryHeader) - sizeof(LogEntryHeader); EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, remained_log_size)); @@ -426,15 +427,61 @@ TEST_F(TestObSimpleLogReplayFunc, test_wait_replay_done) rp_sv.is_replay_done(ls_id, LSN(PALF_BLOCK_SIZE), is_done); } iterator_end_lsn = LSN(2*PALF_BLOCK_SIZE); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 31, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 31, leader_idx, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, leader.get_palf_handle_impl()->get_max_lsn())); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, log_entry_size)); // 有padding日志,committed位点是文件头 is_done =false; while (!is_done) { rp_sv.is_replay_done(ls_id, LSN(PALF_BLOCK_SIZE), is_done); } } + +TEST_F(TestObSimpleLogReplayFunc, replay_big_log) +{ + SET_CASE_LOG_FILE(TEST_NAME, "replay_big_log"); + const int64_t task_count = 10; + const int64_t id = ATOMIC_AAF(&palf_id_, 1); + ObLSID ls_id(id); + int64_t leader_idx = 0; + LSN basic_lsn(0); + PalfHandleImplGuard leader; + share::SCN basic_scn = share::SCN::min_scn(); + CLOG_LOG(INFO, "test replay begin", K(id)); + EXPECT_EQ(OB_SUCCESS, create_paxos_group(id, leader_idx, leader)); + MockLSAdapter ls_adapter; + ls_adapter.init((ObLSService *)(0x1)); + ObLogReplayService rp_sv; + ObReplayStatus *rp_st = NULL; + PalfEnv *palf_env; + EXPECT_EQ(OB_SUCCESS, get_palf_env(leader_idx, palf_env)); + rp_sv.init(palf_env, &ls_adapter, get_cluster()[0]->get_allocator()); + rp_sv.start(); + get_cluster()[0]->get_tenant_base()->update_thread_cnt(10); + EXPECT_EQ(OB_SUCCESS, rp_sv.add_ls(ls_id)); + EXPECT_EQ(OB_SUCCESS, rp_sv.enable(ls_id, basic_lsn, basic_scn)); + { + ObReplayStatusGuard guard; + EXPECT_EQ(OB_SUCCESS, rp_sv.get_replay_status_(ls_id, guard)); + rp_st = guard.get_replay_status(); + ls_adapter.rp_st_ = rp_st; + } + LSN unused_lsn; + int64_t unused_ts = 0; + for (int i = 0; i < task_count; i++) + { + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, MAX_LOG_BODY_SIZE)); + } + ls_adapter.wait_replay_done(task_count); + bool is_done = false; + LSN end_lsn = leader.palf_handle_impl_->get_end_lsn(); + LSN max_lsn = leader.palf_handle_impl_->get_max_lsn(); + EXPECT_EQ(end_lsn.val_, max_lsn.val_); + while (!is_done) { + rp_sv.is_replay_done(ls_id, end_lsn, is_done); + } + EXPECT_EQ(0, rp_sv.get_pending_task_size()); +} } // unitest } // oceanbase diff --git a/mittest/logservice/test_ob_simple_log_restart.cpp b/mittest/logservice/test_ob_simple_log_restart.cpp index bbb326f006..465a59a974 100644 --- a/mittest/logservice/test_ob_simple_log_restart.cpp +++ b/mittest/logservice/test_ob_simple_log_restart.cpp @@ -64,7 +64,7 @@ int64_t ObSimpleLogClusterTestBase::node_cnt_ = 1; std::string ObSimpleLogClusterTestBase::test_name_ = TEST_NAME; bool ObSimpleLogClusterTestBase::need_add_arb_server_ = false; constexpr int64_t timeout_ts_us = 3 * 1000 * 1000; - +int64_t log_entry_size = 2 * 1024 * 1024 + 16 * 1024; TEST_F(TestObSimpleLogClusterRestart, read_block_in_flashback) { @@ -77,7 +77,7 @@ TEST_F(TestObSimpleLogClusterRestart, read_block_in_flashback) PalfEnv *palf_env = NULL; EXPECT_EQ(OB_SUCCESS, create_paxos_group(id, leader_idx, leader)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 2 * 32 + 2, id, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 2 * 32 + 2, id, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, leader.get_palf_handle_impl()->get_max_lsn())); block_id_t min_block_id, max_block_id; @@ -133,7 +133,7 @@ TEST_F(TestObSimpleLogClusterRestart, restart_when_first_log_block_is_empty) PalfHandleImplGuard leader; EXPECT_EQ(OB_SUCCESS, get_leader(id, leader, leader_idx)); EXPECT_EQ(LSN(PALF_INITIAL_LSN_VAL), leader.palf_handle_impl_->get_max_lsn()); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, id, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, id, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_lsn_until_flushed(leader.palf_handle_impl_->get_max_lsn(), leader)); EXPECT_EQ(OB_SUCCESS, leader.palf_handle_impl_->log_engine_.truncate(LSN(0))); } @@ -144,7 +144,7 @@ TEST_F(TestObSimpleLogClusterRestart, restart_when_first_log_block_is_empty) PalfHandleImplGuard leader; EXPECT_EQ(OB_SUCCESS, get_leader(id, leader, leader_idx)); EXPECT_EQ(LSN(PALF_INITIAL_LSN_VAL), leader.palf_handle_impl_->get_max_lsn()); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 40, id, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 40, id, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, leader.palf_handle_impl_->get_max_lsn())); PalfBaseInfo base_info; base_info.generate_by_default(); @@ -169,7 +169,7 @@ TEST_F(TestObSimpleLogClusterRestart, restart_when_first_log_block_is_empty) PalfHandleImplGuard leader; EXPECT_EQ(OB_SUCCESS, get_leader(id, leader, leader_idx)); EXPECT_EQ(rebuild_lsn, leader.palf_handle_impl_->get_max_lsn()); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, id, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, id, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, leader.palf_handle_impl_->get_max_lsn())); int64_t mode_version; switch_append_to_flashback(leader, mode_version); @@ -182,7 +182,7 @@ TEST_F(TestObSimpleLogClusterRestart, restart_when_first_log_block_is_empty) EXPECT_EQ(rebuild_lsn, leader.palf_handle_impl_->get_max_lsn()); int64_t mode_version; switch_flashback_to_append(leader, mode_version); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, id, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, id, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, leader.palf_handle_impl_->get_max_lsn())); } } @@ -198,7 +198,7 @@ TEST_F(TestObSimpleLogClusterRestart, test_restart) { PalfHandleImplGuard leader; EXPECT_EQ(OB_SUCCESS, create_paxos_group(id, leader_idx, leader)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, id, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, id, log_entry_size)); wait_lsn_until_flushed(leader.palf_handle_impl_->get_max_lsn(), leader); LogEngine *log_engine = &leader.palf_handle_impl_->log_engine_; char *meta_log_dir = log_engine->log_meta_storage_.block_mgr_.log_dir_; @@ -221,7 +221,7 @@ TEST_F(TestObSimpleLogClusterRestart, test_restart) PalfHandleImplGuard leader; EXPECT_EQ(OB_SUCCESS, create_paxos_group(id, leader_idx, leader)); EXPECT_EQ(OB_SUCCESS, get_leader(id, leader, leader_idx)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 33, id, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 33, id, log_entry_size)); wait_lsn_until_flushed(leader.palf_handle_impl_->get_max_lsn(), leader); block_id_t min_block_id, max_block_id; LogStorage *log_storage = &leader.palf_handle_impl_->log_engine_.log_storage_; @@ -240,7 +240,7 @@ TEST_F(TestObSimpleLogClusterRestart, test_restart) PalfHandleImplGuard leader; EXPECT_EQ(OB_SUCCESS, get_leader(id, leader, leader_idx)); //检查manifest是否为3 - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, id, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, id, log_entry_size)); LogStorage *meta_storage = &leader.get_palf_handle_impl()->log_engine_.log_meta_storage_; EXPECT_EQ(2, lsn_2_block(meta_storage->log_block_header_.min_lsn_, PALF_BLOCK_SIZE)); } @@ -251,7 +251,7 @@ TEST_F(TestObSimpleLogClusterRestart, test_restart) PalfHandleImplGuard leader; id = ATOMIC_AAF(&palf_id_, 1); EXPECT_EQ(OB_SUCCESS, create_paxos_group(id, leader_idx, leader)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 66, id, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 66, id, log_entry_size)); wait_lsn_until_flushed(leader.palf_handle_impl_->get_max_lsn(), leader); EXPECT_EQ(OB_ITER_END, read_log(leader)); } @@ -299,7 +299,7 @@ TEST_F(TestObSimpleLogClusterRestart, test_restart) EXPECT_EQ(OB_SUCCESS, log_storage->get_block_id_range(min_block_id, max_block_id)); EXPECT_EQ(2, max_block_id); EXPECT_EQ(3, lsn_2_block(meta_storage->log_block_header_.min_lsn_, PALF_BLOCK_SIZE)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, id, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, id, log_entry_size)); wait_lsn_until_flushed(leader.palf_handle_impl_->get_max_lsn(), leader); EXPECT_EQ(3, lsn_2_block(meta_storage->log_block_header_.min_lsn_, PALF_BLOCK_SIZE)); } @@ -312,7 +312,7 @@ TEST_F(TestObSimpleLogClusterRestart, test_restart) LogIOWorker *iow = leader.palf_handle_impl_->log_engine_.log_io_worker_; int64_t epoch = leader.palf_handle_impl_->log_engine_.palf_epoch_; int64_t palf_id = leader.palf_handle_impl_->palf_id_; - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 29, id, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 29, id, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_lsn_until_flushed(leader.palf_handle_impl_->get_max_lsn(), leader)); // 预期log_tail接近文件2的尾部 EXPECT_LE(LSN(3*PALF_BLOCK_SIZE) - log_storage->log_tail_, 5*1024*1024); @@ -323,7 +323,7 @@ TEST_F(TestObSimpleLogClusterRestart, test_restart) EXPECT_EQ(OB_SUCCESS, wait_lsn_until_flushed(leader.palf_handle_impl_->get_max_lsn(), leader)); IOTaskConsumeCond cond(palf_id, epoch); EXPECT_EQ(OB_SUCCESS, iow->submit_io_task(&cond)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10, id, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10, id, log_entry_size)); while (1) { if (leader.palf_handle_impl_->sw_.last_submit_end_lsn_ < leader.palf_handle_impl_->get_max_lsn()) { usleep(5000); @@ -353,7 +353,7 @@ TEST_F(TestObSimpleLogClusterRestart, test_restart) LogIOWorker *iow = leader.palf_handle_impl_->log_engine_.log_io_worker_; int64_t epoch = leader.palf_handle_impl_->log_engine_.palf_epoch_; int64_t palf_id = leader.palf_handle_impl_->palf_id_; - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10, id, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10, id, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, leader.palf_handle_impl_->get_end_lsn())); sleep(1); EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, id, 1000)); @@ -361,7 +361,7 @@ TEST_F(TestObSimpleLogClusterRestart, test_restart) EXPECT_EQ(OB_SUCCESS, wait_lsn_until_flushed(leader.palf_handle_impl_->get_max_lsn(), leader)); IOTaskConsumeCond cond(palf_id, epoch); EXPECT_EQ(OB_SUCCESS, iow->submit_io_task(&cond)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10, id, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10, id, log_entry_size)); while (1) { if (leader.palf_handle_impl_->sw_.last_submit_end_lsn_ < leader.palf_handle_impl_->get_max_lsn()) { usleep(5000); diff --git a/mittest/logservice/test_ob_simple_log_single_replica_func.cpp b/mittest/logservice/test_ob_simple_log_single_replica_func.cpp index e595e15748..ab6a08414b 100644 --- a/mittest/logservice/test_ob_simple_log_single_replica_func.cpp +++ b/mittest/logservice/test_ob_simple_log_single_replica_func.cpp @@ -66,6 +66,7 @@ int64_t ObSimpleLogClusterTestBase::node_cnt_ = 1; std::string ObSimpleLogClusterTestBase::test_name_ = TEST_NAME; bool ObSimpleLogClusterTestBase::need_add_arb_server_ = false; constexpr int64_t timeout_ts_us = 3 * 1000 * 1000; +int64_t log_entry_size = 2 * 1024 * 1024 + 16 * 1024; void read_padding_entry(PalfHandleImplGuard &leader, SCN padding_scn, LSN padding_log_lsn) { @@ -143,12 +144,12 @@ TEST_F(TestObSimpleLogClusterSingleReplica, single_replica_flashback) // flashback到PADDING日志 switch_flashback_to_append(leader, mode_version); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 31, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 31, leader_idx, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, leader.palf_handle_impl_->sw_.get_max_lsn())); EXPECT_EQ(OB_ITER_END, read_log(leader)); EXPECT_GT(LSN(PALF_BLOCK_SIZE), leader.palf_handle_impl_->sw_.get_max_lsn()); int remained_log_size = LSN(PALF_BLOCK_SIZE) - leader.palf_handle_impl_->sw_.get_max_lsn(); - EXPECT_LT(remained_log_size, MAX_LOG_BODY_SIZE); + EXPECT_LT(remained_log_size, log_entry_size); int need_log_size = remained_log_size - 5*1024; PALF_LOG(INFO, "runlin trace print sw1", K(leader.palf_handle_impl_->sw_)); // 保证末尾只剩小于1KB的空间 @@ -1151,10 +1152,10 @@ TEST_F(TestObSimpleLogClusterSingleReplica, test_gc_block) block_id_t min_block_id; share::SCN min_block_scn; EXPECT_EQ(OB_ENTRY_NOT_EXIST, log_engine->get_min_block_info_for_gc(min_block_id, min_block_scn)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 31, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 31, leader_idx, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_lsn_until_flushed(leader.palf_handle_impl_->get_max_lsn(), leader)); EXPECT_EQ(OB_ERR_OUT_OF_UPPER_BOUND, log_engine->get_min_block_info_for_gc(min_block_id, min_block_scn)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_lsn_until_flushed(leader.palf_handle_impl_->get_max_lsn(), leader)); block_id_t expect_block_id = 1; share::SCN expect_scn; @@ -1164,7 +1165,7 @@ TEST_F(TestObSimpleLogClusterSingleReplica, test_gc_block) EXPECT_EQ(OB_SUCCESS, log_engine->delete_block(0)); EXPECT_EQ(false, log_engine->min_block_max_scn_.is_valid()); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 100, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 100, leader_idx, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_lsn_until_flushed(leader.palf_handle_impl_->get_max_lsn(), leader)); expect_block_id = 2; EXPECT_EQ(OB_SUCCESS, log_engine->get_min_block_info_for_gc(min_block_id, min_block_scn)); @@ -1634,9 +1635,9 @@ TEST_F(TestObSimpleLogClusterSingleReplica, test_iterator_with_flashback) const int64_t append_id = ATOMIC_AAF(&palf_id_, 1); PalfHandleImplGuard append_leader; EXPECT_EQ(OB_SUCCESS, create_paxos_group(append_id, leader_idx, append_leader)); - EXPECT_EQ(OB_SUCCESS, submit_log(append_leader, 31, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(append_leader, 31, leader_idx, log_entry_size)); const LSN padding_start_lsn = append_leader.get_palf_handle_impl()->get_max_lsn(); - EXPECT_EQ(OB_SUCCESS, submit_log(append_leader, 1, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(append_leader, 1, leader_idx, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(append_leader, append_leader.get_palf_handle_impl()->get_max_lsn())); SCN padding_scn = append_leader.get_palf_handle_impl()->get_max_scn(); padding_scn = padding_scn.minus(padding_scn, 1); @@ -1737,7 +1738,7 @@ TEST_F(TestObSimpleLogClusterSingleReplica, test_iow_memleak) LogIOWorker *iow = leader.get_palf_handle_impl()->log_engine_.log_io_worker_; IPalfEnvImpl *palf_env_impl = leader.get_palf_handle_impl()->palf_env_impl_; ObILogAllocator *allocator = palf_env_impl->get_log_allocator(); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 32, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 32, leader_idx, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, leader.palf_handle_impl_->sw_.get_max_lsn())); LSN end_lsn = leader.get_palf_handle_impl()->get_end_lsn(); @@ -1745,16 +1746,16 @@ TEST_F(TestObSimpleLogClusterSingleReplica, test_iow_memleak) EXPECT_EQ(OB_SUCCESS, iow->submit_io_task(&cond)); sleep(1); EXPECT_EQ(OB_SUCCESS, leader.get_palf_handle_impl()->set_base_lsn(end_lsn)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, log_entry_size)); EXPECT_EQ(OB_SUCCESS, leader.get_palf_handle_impl()->log_engine_.submit_purge_throttling_task(PurgeThrottlingType::PURGE_BY_GET_MC_REQ)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 2, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 2, leader_idx, log_entry_size)); EXPECT_NE(0, allocator->flying_log_task_); EXPECT_NE(0, allocator->flying_meta_task_); leader.get_palf_handle_impl()->log_engine_.palf_epoch_++; EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10, leader_idx)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, log_entry_size)); EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10, leader_idx)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, log_entry_size)); leader.get_palf_handle_impl()->log_engine_.palf_epoch_++; cond.cond_.signal(); PALF_LOG(INFO, "runlin trace submit log 1"); @@ -1774,23 +1775,23 @@ TEST_F(TestObSimpleLogClusterSingleReplica, test_iow_memleak) LogIOWorker *iow = leader.get_palf_handle_impl()->log_engine_.log_io_worker_; IPalfEnvImpl *palf_env_impl = leader.get_palf_handle_impl()->palf_env_impl_; ObILogAllocator *allocator = palf_env_impl->get_log_allocator(); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 32, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 32, leader_idx, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, leader.palf_handle_impl_->sw_.get_max_lsn())); LSN end_lsn = leader.get_palf_handle_impl()->get_end_lsn(); IOTaskConsumeCond consume_cond(id, leader.palf_env_impl_->last_palf_epoch_); EXPECT_EQ(OB_SUCCESS, iow->submit_io_task(&consume_cond)); sleep(1); EXPECT_EQ(OB_SUCCESS, leader.get_palf_handle_impl()->set_base_lsn(end_lsn)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, log_entry_size)); EXPECT_EQ(OB_SUCCESS, leader.get_palf_handle_impl()->log_engine_.submit_purge_throttling_task(PurgeThrottlingType::PURGE_BY_GET_MC_REQ)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 2, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 2, leader_idx, log_entry_size)); EXPECT_NE(0, allocator->flying_log_task_); EXPECT_NE(0, allocator->flying_meta_task_); leader.get_palf_handle_impl()->log_engine_.palf_epoch_++; EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10, leader_idx)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, log_entry_size)); EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10, leader_idx)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, log_entry_size)); leader.get_palf_handle_impl()->log_engine_.palf_epoch_++; consume_cond.cond_.signal(); PALF_LOG(INFO, "runlin trace submit log 2"); @@ -1819,7 +1820,7 @@ TEST_F(TestObSimpleLogClusterSingleReplica, test_iow_memleak) } }); ObILogAllocator *allocator = palf_env_impl->get_log_allocator(); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 32, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 32, leader_idx, log_entry_size)); EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, leader.palf_handle_impl_->sw_.get_max_lsn())); LSN end_lsn = leader.get_palf_handle_impl()->get_end_lsn(); // case2: palf epoch has been changed during after_consume @@ -1827,16 +1828,16 @@ TEST_F(TestObSimpleLogClusterSingleReplica, test_iow_memleak) EXPECT_EQ(OB_SUCCESS, iow->submit_io_task(&consume_cond)); sleep(3); EXPECT_EQ(OB_SUCCESS, leader.get_palf_handle_impl()->set_base_lsn(end_lsn)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, log_entry_size)); EXPECT_EQ(OB_SUCCESS, leader.get_palf_handle_impl()->log_engine_.submit_purge_throttling_task(PurgeThrottlingType::PURGE_BY_GET_MC_REQ)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 2, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 2, leader_idx, log_entry_size)); EXPECT_NE(0, allocator->flying_log_task_); EXPECT_NE(0, allocator->flying_meta_task_); leader.get_palf_handle_impl()->log_engine_.palf_epoch_++; EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10, leader_idx)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, log_entry_size)); EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10, leader_idx)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, MAX_LOG_BODY_SIZE)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 1, leader_idx, log_entry_size)); leader.get_palf_handle_impl()->log_engine_.palf_epoch_++; consume_cond.cond_.signal(); PALF_LOG(INFO, "runlin trace submit log 3"); @@ -1890,6 +1891,75 @@ TEST_F(TestObSimpleLogClusterSingleReplica, test_log_service_interface) EXPECT_EQ(OB_SUCCESS, log_service->check_palf_exist(ls_id, is_exist)); } +TEST_F(TestObSimpleLogClusterSingleReplica, test_raw_read) +{ + SET_CASE_LOG_FILE(TEST_NAME, "test_raw_read"); + OB_LOGGER.set_log_level("TRACE"); + int64_t id = ATOMIC_AAF(&palf_id_, 1); + int64_t leader_idx = 0; + PalfHandleImplGuard leader; + const int64_t read_buf_ptr_len = PALF_BLOCK_SIZE; + char *read_buf_ptr = reinterpret_cast(mtl_malloc_align( + LOG_DIO_ALIGN_SIZE, PALF_BLOCK_SIZE + 2 * LOG_DIO_ALIGN_SIZE, "mittest")); + EXPECT_EQ(OB_SUCCESS, create_paxos_group(id, leader_idx, leader)); + leader.palf_handle_impl_->log_engine_.log_storage_.hot_cache_ = NULL; + // 提交100条日志, 每条日志大小为30K. + { + char *read_buf = read_buf_ptr; + int64_t nbytes = read_buf_ptr_len; + int64_t out_read_size = 0; + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 100, leader_idx, 1000)); + EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, leader.palf_handle_impl_->get_max_lsn())); + const int64_t curr_real_size = leader.palf_handle_impl_->get_max_lsn() - LSN(PALF_INITIAL_LSN_VAL); + + const LSN invalid_lsn(1); + char *invalid_read_buf = read_buf_ptr + 1; + const int64_t invalid_nbytes = 1; + + // 非DIO对齐度 + EXPECT_EQ(OB_INVALID_ARGUMENT, leader.palf_handle_impl_->raw_read( + invalid_lsn, invalid_read_buf, invalid_nbytes, out_read_size)); + EXPECT_EQ(OB_INVALID_ARGUMENT, leader.palf_handle_impl_->raw_read( + LSN(PALF_INITIAL_LSN_VAL), invalid_read_buf, invalid_nbytes, out_read_size)); + EXPECT_EQ(OB_INVALID_ARGUMENT, leader.palf_handle_impl_->raw_read( + LSN(PALF_INITIAL_LSN_VAL), read_buf, invalid_nbytes, out_read_size)); + PALF_LOG(INFO, "raw read success"); + + // 读取成功 + EXPECT_EQ(OB_SUCCESS, leader.palf_handle_impl_->raw_read(LSN(PALF_INITIAL_LSN_VAL), read_buf, PALF_BLOCK_SIZE, out_read_size)); + EXPECT_LE(out_read_size, PALF_BLOCK_SIZE); + EXPECT_EQ(out_read_size, curr_real_size); + + // 读取长度超过end_lsn + PALF_LOG(INFO, "raw read return OB_ERR_OUT_OF_UPPER_BOUND"); + LSN out_of_upper_bound(PALF_BLOCK_SIZE); + EXPECT_EQ(OB_ERR_OUT_OF_UPPER_BOUND, leader.palf_handle_impl_->raw_read( + out_of_upper_bound, read_buf, PALF_BLOCK_SIZE, out_read_size)); + + // 模拟生成2个文件 + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 40, leader_idx, log_entry_size)); + EXPECT_EQ(OB_SUCCESS, wait_until_has_committed(leader, leader.palf_handle_impl_->get_max_lsn())); + + // 模拟跨文件读 + PALF_LOG(INFO, "raw read cross file"); + LSN curr_read_lsn(lower_align(PALF_BLOCK_SIZE/2, LOG_DIO_ALIGN_SIZE)); + int64_t expected_read_size = LSN(PALF_BLOCK_SIZE) - curr_read_lsn; + EXPECT_EQ(OB_SUCCESS, leader.palf_handle_impl_->raw_read( + curr_read_lsn, read_buf, PALF_BLOCK_SIZE, out_read_size)); + EXPECT_EQ(out_read_size, expected_read_size); + + EXPECT_EQ(OB_SUCCESS, leader.palf_handle_impl_->delete_block(0)); + + // 模拟lower_bound + PALF_LOG(INFO, "raw read return OB_ERR_OUT_OF_LOWER_BOUND"); + LSN out_of_lower_bound(PALF_INITIAL_LSN_VAL); + EXPECT_EQ(OB_ERR_OUT_OF_LOWER_BOUND, leader.palf_handle_impl_->raw_read(out_of_lower_bound, read_buf, PALF_BLOCK_SIZE, out_read_size)); + if (NULL != read_buf_ptr) { + mtl_free_align(read_buf_ptr); + } + } +} + } // namespace unittest } // namespace oceanbase diff --git a/mittest/logservice/test_ob_simple_log_throttling.cpp b/mittest/logservice/test_ob_simple_log_throttling.cpp index 6e59e5d30f..70629722f1 100644 --- a/mittest/logservice/test_ob_simple_log_throttling.cpp +++ b/mittest/logservice/test_ob_simple_log_throttling.cpp @@ -238,7 +238,7 @@ TEST_F(TestObSimpleLogClusterLogThrottling, test_throttling_basic) max_lsn_1 = leader.palf_handle_impl_->sw_.get_max_lsn(); wait_lsn_until_flushed(max_lsn_1, leader); - int64_t prev_has_batched_size = log_io_worker->batch_io_task_mgr_.has_batched_size_; + int64_t prev_has_batched_size = log_io_worker->batch_io_task_mgr_.handle_count_; PALF_LOG(INFO, "[CASE 6] flush meta task no need throttling", K(max_lsn_1)); int64_t cur_ts = common::ObClockGenerator::getClock(); palf_env_impl.disk_options_wrapper_.disk_opts_for_stopping_writing_.log_disk_usage_limit_size_ = 300 * MB; @@ -274,7 +274,7 @@ TEST_F(TestObSimpleLogClusterLogThrottling, test_throttling_basic) ASSERT_EQ(0, throttle->stat_.total_throttling_task_cnt_); ASSERT_EQ(10, throttle->stat_.total_skipped_task_cnt_); ASSERT_EQ(10 * (log_size), throttle->stat_.total_skipped_size_); - int64_t cur_has_batched_size = log_io_worker->batch_io_task_mgr_.has_batched_size_; + int64_t cur_has_batched_size = log_io_worker->batch_io_task_mgr_.handle_count_; // no io reduce during writing throttling ASSERT_EQ(cur_has_batched_size, prev_has_batched_size); const double old_decay_factor = throttle->decay_factor_; @@ -371,12 +371,12 @@ TEST_F(TestObSimpleLogClusterLogThrottling, test_throttling_basic) usleep(100 * 1000); PALF_LOG(INFO, "[CASE 10] no io reduce during writing throttling", K(throttle)); - int64_t batched_size = log_io_worker->batch_io_task_mgr_.has_batched_size_; + int64_t batched_size = log_io_worker->batch_io_task_mgr_.handle_count_; leader.palf_handle_impl_->sw_.freeze_mode_ = PERIOD_FREEZE_MODE; EXPECT_EQ(OB_SUCCESS, submit_log(leader, 100, id, 128)); max_lsn_3 = leader.palf_handle_impl_->sw_.get_max_lsn(); wait_lsn_until_flushed(max_lsn_3, leader); - int64_t new_batched_size = log_io_worker->batch_io_task_mgr_.has_batched_size_; + int64_t new_batched_size = log_io_worker->batch_io_task_mgr_.handle_count_; EXPECT_EQ(batched_size, new_batched_size); PALF_LOG(INFO, "[CASE 11] need break from writing throttling while flashback task is submitted", K(throttle)); diff --git a/src/logservice/CMakeLists.txt b/src/logservice/CMakeLists.txt index d6a4421ed2..5f30e7b58b 100644 --- a/src/logservice/CMakeLists.txt +++ b/src/logservice/CMakeLists.txt @@ -25,6 +25,8 @@ ob_set_subtarget(ob_logservice archiveservice ob_set_subtarget(ob_logservice cdcservice cdcservice/ob_cdc_fetcher.cpp + cdcservice/ob_cdc_raw_log_req.cpp + cdcservice/ob_cdc_req_struct.cpp cdcservice/ob_cdc_req.cpp cdcservice/ob_cdc_rpc_processor.cpp cdcservice/ob_cdc_rpc_proxy.cpp @@ -54,6 +56,7 @@ ob_set_subtarget(ob_logservice common ob_log_monitor.cpp ob_log_external_storage_handler.cpp ob_log_external_storage_io_task.cpp + ob_locality_adapter.cpp ) ob_set_subtarget(ob_logservice common_mixed @@ -188,6 +191,7 @@ ob_set_subtarget(ob_logservice restoreservice restoreservice/ob_log_restore_archive_driver.cpp restoreservice/ob_restore_log_function.cpp restoreservice/ob_remote_log_writer.cpp + restoreservice/ob_remote_log_raw_reader.cpp ) ob_set_subtarget(ob_logservice data_dictionary diff --git a/src/logservice/cdcservice/ob_cdc_define.h b/src/logservice/cdcservice/ob_cdc_define.h index 198d7e22c7..18a2ed63e0 100644 --- a/src/logservice/cdcservice/ob_cdc_define.h +++ b/src/logservice/cdcservice/ob_cdc_define.h @@ -13,6 +13,7 @@ #ifndef OCEANBASE_LOGSERVICE_OB_CDC_DEFINE_ #define OCEANBASE_LOGSERVICE_OB_CDC_DEFINE_ +#include namespace oceanbase { namespace cdc diff --git a/src/logservice/cdcservice/ob_cdc_fetcher.cpp b/src/logservice/cdcservice/ob_cdc_fetcher.cpp index dbd97fe47a..8e6c2b778e 100644 --- a/src/logservice/cdcservice/ob_cdc_fetcher.cpp +++ b/src/logservice/cdcservice/ob_cdc_fetcher.cpp @@ -17,6 +17,7 @@ #include "ob_cdc_define.h" #include "storage/tx_storage/ob_ls_handle.h" #include "logservice/restoreservice/ob_remote_log_source_allocator.h" +#include "logservice/restoreservice/ob_remote_log_raw_reader.h" namespace oceanbase { @@ -30,6 +31,7 @@ namespace cdc ObCdcFetcher::ObCdcFetcher() : is_inited_(false), tenant_id_(OB_INVALID_TENANT_ID), + host_(NULL), ls_service_(NULL), large_buffer_pool_(NULL), log_ext_handler_(NULL) @@ -43,6 +45,7 @@ ObCdcFetcher::~ObCdcFetcher() int ObCdcFetcher::init(const uint64_t tenant_id, ObLSService *ls_service, + ObCdcService *host, archive::LargeBufferPool *buffer_pool, logservice::ObLogExternalStorageHandler *log_ext_handler) { @@ -53,12 +56,13 @@ int ObCdcFetcher::init(const uint64_t tenant_id, LOG_WARN("inited twice", KR(ret)); } else if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id) || OB_ISNULL(ls_service) || OB_ISNULL(buffer_pool) - || OB_ISNULL(log_ext_handler)) { + || OB_ISNULL(log_ext_handler) || OB_ISNULL(host)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(ls_service), K(buffer_pool)); } else { is_inited_ = true; tenant_id_ = tenant_id; + host_ = host; ls_service_ = ls_service; large_buffer_pool_ = buffer_pool; log_ext_handler_ = log_ext_handler; @@ -72,6 +76,7 @@ void ObCdcFetcher::destroy() if (is_inited_) { is_inited_ = false; tenant_id_ = OB_INVALID_TENANT_ID; + host_ = NULL; ls_service_ = NULL; large_buffer_pool_ = NULL; log_ext_handler_ = NULL; @@ -101,46 +106,30 @@ int ObCdcFetcher::fetch_log(const ObCdcLSFetchLogReq &req, PalfHandleGuard palf_handle_guard; PalfGroupBufferIterator group_iter; const ObCdcRpcId &rpc_id = req.get_client_id(); - ClientLSKey ls_key(rpc_id.get_addr(), rpc_id.get_pid(), req.get_tenant_id(), ls_id); - ClientLSCtxMap &ctx_map = MTL(ObLogService*)->get_cdc_service()->get_ls_ctx_map(); + ClientLSCtx *ls_ctx = NULL; int8_t fetch_log_flag = req.get_flag(); - // create ClientLSCtx when fetch_log for better maintainablity - // about the reason why not create ClientLSCtx when locating start lsn, considering the case: - // 1. Client locate lsn at server1 and server1 create the clientlsctx; - // 2. when client is about to fetch log in server1, server1 becomes unavailable; - // 3. then the client switch to server2 to fetch log; - // 4. server2 doesn't have the context of clientls, and need to create one - // So we just create ctx when fetching log - if (OB_FAIL(ctx_map.get(ls_key, ls_ctx))) { - if (OB_ENTRY_NOT_EXIST == ret) { - if (OB_FAIL(ctx_map.create(ls_key, ls_ctx))) { - LOG_WARN("create client ls ctx failed", KR(ret), K(ls_key)); - } else if (OB_FAIL(ls_ctx->init(req.get_progress()))) { - LOG_WARN("failed to init client ls ctx", KR(ret), K(req)); - } else { - // if test_switch_mode is enabled, set the init fetch mode to FETCHMODE_ARCHIVE - // so that the fetch mode could be switched to FETCHMODE_ONLINE in the next rpc in some test cases. - if (fetch_log_flag & ObCdcRpcTestFlag::OBCDC_RPC_TEST_SWITCH_MODE) { - ls_ctx->set_fetch_mode(FetchMode::FETCHMODE_ARCHIVE, "InitTestSwitchMode"); - } - LOG_INFO("create client ls ctx succ", K(ls_key), K(ls_ctx)); - } - } else { - LOG_ERROR("get client ls ctx from ctx map failed", KR(ret)); - } - } - - if (OB_SUCC(ret)) { + if (OB_FAIL(host_->get_or_create_client_ls_ctx(req.get_client_id(), + req.get_tenant_id(), ls_id, fetch_log_flag, + req.get_progress(), FetchLogProtocolType::LogGroupEntryProto, ls_ctx))) { + LOG_WARN("failed to get or create client ls ctx", K(req), KP(ls_ctx)); + } else if (OB_ISNULL(ls_ctx)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get null ctx afeter get_or_create_client_ls_ctx, unexpected", KP(ls_ctx), K(req)); + } else { ls_ctx->update_touch_ts(); if (OB_FAIL(do_fetch_log_(req, frt, resp, *ls_ctx, fetch_log_time_stat))) { - LOG_WARN("do fetch log error", KR(ret), K(req)); - } else {} - } + LOG_WARN("do fetch log error", KR(ret), K(req)); + } - if (OB_NOT_NULL(ls_ctx)) { - ctx_map.revert(ls_ctx); + if (OB_NOT_NULL(ls_ctx)) { + if (OB_FAIL(host_->revert_client_ls_ctx(ls_ctx))) { + LOG_WARN("failed to revert client ls ctx", K(req)); + } else { + ls_ctx = nullptr; + } + } } } @@ -163,6 +152,42 @@ int ObCdcFetcher::fetch_log(const ObCdcLSFetchLogReq &req, return ret; } +int ObCdcFetcher::fetch_raw_log(const ObCdcFetchRawLogReq &req, + ObCdcFetchRawLogResp &resp) +{ + int ret = OB_SUCCESS; + const int64_t cur_tstamp = ObTimeUtility::current_time(); + ObCdcFetchRawStatus &stat = resp.get_fetch_status(); + ClientLSCtx *ctx = nullptr; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + } else if (OB_FAIL(host_->get_or_create_client_ls_ctx(req.get_client_id(), + req.get_tenant_id(), req.get_ls_id(), req.get_flag(), + req.get_progress(), FetchLogProtocolType::RawLogDataProto, ctx))) { + LOG_WARN("failed to get or create client ls ctx when fetching raw log", K(req), KP(ctx)); + } else if (OB_ISNULL(ctx)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get null ctx afeter get_or_create_client_ls_ctx, unexpected", KP(ctx), K(req)); + } else { + ctx->update_touch_ts(); + if (OB_FAIL(do_fetch_raw_log_(req, resp, *ctx))) { + LOG_WARN("failed to fetch raw log", K(req), K(resp), KPC(ctx)); + } + + if (OB_NOT_NULL(ctx)) { + if (OB_FAIL(host_->revert_client_ls_ctx(ctx))) { + LOG_WARN("failed to revert client ls ctx", K(req)); + } else { + ctx = nullptr; + } + } + } + + LOG_INFO("fetch_raw_log done", K(req), K(resp)); + + return ret; +} + int ObCdcFetcher::fetch_missing_log(const obrpc::ObCdcLSFetchMissLogReq &req, obrpc::ObCdcLSFetchLogResp &resp) { @@ -351,7 +376,7 @@ int ObCdcFetcher::fetch_log_in_archive_( // always reserve 4K for archive header const int64_t SINGLE_READ_SIZE = 16 * 1024 * 1024L - 4 * 1024; const int64_t MAX_RETRY_COUNT = 4; - if (OB_ISNULL(ctx.get_source()) && OB_FAIL(ObCdcService::init_archive_source(ls_id, ctx))) { + if (OB_FAIL(host_->init_archive_source_if_needed(ls_id, ctx))) { LOG_WARN("init archive source failed", K(ctx), K(ls_id)); } else { const char *buf = NULL; @@ -389,6 +414,7 @@ int ObCdcFetcher::fetch_log_in_archive_( } int ObCdcFetcher::set_fetch_mode_before_fetch_log_(const ObLSID &ls_id, + const LSN &start_lsn, const bool test_switch_fetch_mode, bool &ls_exist_in_palf, palf::PalfHandleGuard &palf_guard, @@ -407,24 +433,33 @@ int ObCdcFetcher::set_fetch_mode_before_fetch_log_(const ObLSID &ls_id, LOG_WARN("logstream in sys tenant doesn't exist, unexpected", KR(ret), K(ls_id)); } } else if (FetchMode::FETCHMODE_ARCHIVE == ctx.get_fetch_mode()) { - int64_t end_ts_ns = OB_INVALID_TIMESTAMP; - int64_t time_diff = OB_INVALID_TIMESTAMP; - const int64_t ctx_progress = ctx.get_progress(); + // int64_t end_ts_ns = OB_INVALID_TIMESTAMP; + // int64_t time_diff = OB_INVALID_TIMESTAMP; + // const int64_t ctx_progress = ctx.get_progress(); + + // if the gap between start_lsn and begin_lsn is less thant 2 * palf_block_size + LSN begin_lsn; + constexpr offset_t lsn_diff = 2 * palf::PALF_BLOCK_SIZE; + if (OB_FAIL(palf_guard.get_begin_lsn(begin_lsn))) { + LOG_WARN("get palf begin lsn failed", K(ls_id)); + } else if (start_lsn > begin_lsn && start_lsn - begin_lsn >= lsn_diff) { + ctx.set_fetch_mode(FetchMode::FETCHMODE_ONLINE, "LogExistInPalf"); + } // if the gap between current progress and the latest is less than 1 min, which means // current fetch progress close to the latest log progress, try to switch fetch mode // set the switch interval to 10s in test switch fetch mode, the unit of measurement of log_ts(scn) is nano second. - const int64_t SECOND_NS = 1000L * 1000 * 1000; - SCN end_scn; - const int64_t SWITCH_INTERVAL = test_switch_fetch_mode ? 10L * SECOND_NS : 60 * SECOND_NS; //default 60s - if (OB_FAIL(palf_guard.get_end_scn(end_scn))) { - LOG_WARN("get palf end ts failed", KR(ret)); - } else { - end_ts_ns = end_scn.get_val_for_logservice(); - time_diff = end_ts_ns - ctx_progress; - if (time_diff <= SWITCH_INTERVAL) { - ctx.set_fetch_mode(FetchMode::FETCHMODE_ONLINE, "LogNearLatest"); - } - } + // const int64_t SECOND_NS = 1000L * 1000 * 1000; + // SCN end_scn; + // const int64_t SWITCH_INTERVAL = test_switch_fetch_mode ? 10L * SECOND_NS : 60 * SECOND_NS; //default 60s + // if (OB_FAIL(palf_guard.get_end_scn(end_scn))) { + // LOG_WARN("get palf end ts failed", KR(ret)); + // } else { + // end_ts_ns = end_scn.get_val_for_logservice(); + // time_diff = end_ts_ns - ctx_progress; + // if (time_diff <= SWITCH_INTERVAL) { + // ctx.set_fetch_mode(FetchMode::FETCHMODE_ONLINE, "LogNearLatest"); + // } + // } } else {} return ret; @@ -475,9 +510,10 @@ int ObCdcFetcher::ls_fetch_log_(const ObLSID &ls_id, const int64_t start_ls_fetch_log_time = ObTimeUtility::current_time(); PalfGroupBufferIterator palf_iter; PalfHandleGuard palf_guard; + int64_t version = 0; // use cached remote_iter - ObCdcGetSourceFunctor get_source_func(ctx); - ObCdcUpdateSourceFunctor update_source_func(ctx); + ObCdcUpdateSourceFunctor update_source_func(ctx, version); + ObCdcGetSourceFunctor get_source_func(ctx, version); ObRemoteLogGroupEntryIterator remote_iter(get_source_func, update_source_func); bool ls_exist_in_palf = true; // always reset remote_iter when need_init_iter is true @@ -494,7 +530,7 @@ int ObCdcFetcher::ls_fetch_log_(const ObLSID &ls_id, // the gap between progress in ctx and the latest log progress is less than 1 min if (OB_FAIL(get_replayable_point_scn_(ls_id, replayable_point_scn))) { LOG_WARN("get replayable point scn failed", KR(ret), K(ls_id)); - } else if (OB_FAIL(set_fetch_mode_before_fetch_log_(ls_id, test_switch_fetch_mode, + } else if (OB_FAIL(set_fetch_mode_before_fetch_log_(ls_id, resp.get_next_req_lsn(), test_switch_fetch_mode, ls_exist_in_palf, palf_guard, ctx))) { LOG_WARN("set fetch mode before fetch log failed", KR(ret), K(ls_id), K(tenant_id_)); } else if (fetch_archive_only) { @@ -575,7 +611,7 @@ int ObCdcFetcher::ls_fetch_log_(const ObLSID &ls_id, } } else { // exit - resp.set_feedback_type(obrpc::ObCdcLSFetchLogResp::ARCHIVE_ITER_END_BUT_LS_NOT_EXIST_IN_PALF); + resp.set_feedback_type(FeedbackType::ARCHIVE_ITER_END_BUT_LS_NOT_EXIST_IN_PALF); reach_max_lsn = true; LOG_INFO("reach max lsn in archive but ls not exists in this server, need switch server", K(ls_id)); } @@ -759,7 +795,7 @@ int ObCdcFetcher::handle_log_not_exist_(const ObLSID &ls_id, { int ret = OB_SUCCESS; - resp.set_feedback_type(ObCdcLSFetchLogResp::LOG_NOT_IN_THIS_SERVER); + resp.set_feedback_type(FeedbackType::LOG_NOT_IN_THIS_SERVER); LOG_INFO("handle log_not_exist feedback success", K(ls_id), "lsn", resp.get_next_req_lsn()); @@ -792,6 +828,24 @@ int ObCdcFetcher::check_lag_follower_(const ObLSID &ls_id, { int ret = OB_SUCCESS; ObRole role = INVALID_ROLE; + bool is_in_sync = true; + int64_t leader_epoch = OB_INVALID_TIMESTAMP; + if (OB_FAIL(check_ls_sync_status_(ls_id, palf_handle_guard, role, is_in_sync))) { + LOG_WARN("failed to check ls sync status", K(ls_id), K(role), K(is_in_sync)); + } else if (ObRole::FOLLOWER == role && ! is_in_sync) { + resp.set_feedback_type(FeedbackType::LAGGED_FOLLOWER); + LOG_INFO("catch a lag follower"); + } + + return ret; +} + +int ObCdcFetcher::check_ls_sync_status_(const ObLSID &ls_id, + palf::PalfHandleGuard &palf_handle_guard, + ObRole &role, + bool &in_sync) +{ + int ret = OB_SUCCESS; int64_t leader_epoch = OB_INVALID_TIMESTAMP; if (OB_FAIL(palf_handle_guard.get_role(role, leader_epoch))) { @@ -819,11 +873,11 @@ int ObCdcFetcher::check_lag_follower_(const ObLSID &ls_id, LOG_WARN("log_handler is NULL", KR(ret), K(ls_id)); } else if (OB_FAIL(log_handler->is_in_sync(is_sync, is_need_rebuild))) { LOG_WARN("log_handler is_in_sync fail", KR(ret), K(ls_id), K(is_sync)); - } else if (! is_sync) { - resp.set_feedback_type(ObCdcLSFetchLogResp::LAGGED_FOLLOWER); - LOG_INFO("catch a lag follower"); } - } else {} + } else { + // leader must be in_sync + in_sync = true; + } return ret; } @@ -848,7 +902,8 @@ int ObCdcFetcher::do_fetch_missing_log_(const obrpc::ObCdcLSFetchMissLogReq &req LOG_WARN("miss_log_array is not valid", KR(ret)); } else { PalfHandleGuard palf_guard; - GetSourceFunc get_source_func = ObCdcGetSourceFunctor(ctx); + int64_t version = 0; + ObCdcGetSourceFunctor get_source_func(ctx, version); bool ls_exist_in_palf = true; bool archive_is_on = true; bool need_init_iter = true; @@ -1016,7 +1071,7 @@ int ObCdcFetcher::prepare_berfore_fetch_missing_(const ObLSID &ls_id, } } - if (OB_SUCC(ret) && OB_ISNULL(ctx.get_source()) && OB_FAIL(ObCdcService::init_archive_source(ls_id, ctx))) { + if (OB_SUCC(ret) && OB_FAIL(host_->init_archive_source_if_needed(ls_id, ctx))) { if (OB_ALREADY_IN_NOARCHIVE_MODE == ret) { ret = OB_SUCCESS; archive_is_on = false; @@ -1029,6 +1084,230 @@ int ObCdcFetcher::prepare_berfore_fetch_missing_(const ObLSID &ls_id, return ret; } +int ObCdcFetcher::do_fetch_raw_log_(const obrpc::ObCdcFetchRawLogReq &req, + obrpc::ObCdcFetchRawLogResp &resp, + ClientLSCtx &ctx) +{ + int ret = OB_SUCCESS; + + const ObLSID &ls_id = req.get_ls_id(); + const LSN &start_lsn = req.get_start_lsn(); + const int64_t req_size = req.get_req_size(); + char *buffer = resp.get_log_buffer(); + SCN replayable_point_scn; + const int64_t buffer_len = resp.get_buffer_len(); + const int64_t progress = req.get_progress(); + ObCdcFetchRawStatus &status = resp.get_fetch_status(); + palf::PalfHandleGuard palf_guard; + palf::PalfHandle *palf_handle = nullptr; + + bool ls_exist_in_palf = true; + bool log_may_exist_in_palf = true; + + bool archive_is_on = false; + bool need_retry = true; + bool fetch_log_succ = false; + bool need_fetch_archive = false; + + constexpr int MAX_RETRY_COUNT = 3; + int retry_count = 0; + + int64_t read_palf_time = 0; + int64_t read_archive_time = 0; + + + while (retry_count < MAX_RETRY_COUNT && !fetch_log_succ && need_retry) { + int64_t fetch_palf_start_time = OB_INVALID_TIMESTAMP; + int64_t fetch_archive_start_time = OB_INVALID_TIMESTAMP; + need_fetch_archive = false; + + if (req_size > buffer_len) { + ret = OB_BUF_NOT_ENOUGH; + need_retry = false; + LOG_WARN("buffer not enough, cannot fetch log", K(req_size), K(buffer_len)); + } + + if (OB_SUCC(ret) && OB_FAIL(get_replayable_point_scn_(ls_id, replayable_point_scn))) { + LOG_WARN("failed to get replayable point scn", K(req)); + } + + if (OB_SUCC(ret) && log_may_exist_in_palf) { + fetch_palf_start_time = ObTimeUtility::current_time(); + if (OB_FAIL(fetch_raw_log_in_palf_(ls_id, start_lsn, req_size, resp, + ls_exist_in_palf, fetch_log_succ, ctx))) { + if (OB_ERR_OUT_OF_LOWER_BOUND == ret) { + ret = OB_SUCCESS; + need_fetch_archive = true; + log_may_exist_in_palf = false; + LOG_INFO("lowerbound, the requested log doesn't exist in palf, try fetch archive", K(start_lsn), + K(ls_id), K(req_size)); + } else if (OB_ERR_OUT_OF_UPPER_BOUND == ret) { + need_retry = false; + LOG_INFO("the requested log doesn't exist in palf, return", K(start_lsn), K(ls_id), K(req_size)); + } else { + need_fetch_archive = true; + LOG_WARN("fetch log from palf failed, try fetch archive", K(req)); + } + } else if (! ls_exist_in_palf) { + need_fetch_archive = true; + log_may_exist_in_palf = false; + LOG_INFO("logstream doesn't exist in palf", K(ls_id), K(start_lsn), K(req_size), K(ls_exist_in_palf)); + } else if (fetch_log_succ) { + status.set_source(ObCdcFetchRawSource::PALF); + if (FetchMode::FETCHMODE_ONLINE != ctx.get_fetch_mode()) { + ctx.set_fetch_mode(FetchMode::FETCHMODE_ONLINE, "RawReadPalfSucc"); + } + } + read_palf_time += ObTimeUtility::current_time() - fetch_palf_start_time; + } + + if (!fetch_log_succ && need_fetch_archive) { + int last_ret = ret; + fetch_archive_start_time = ObTimeUtility::current_time(); + if (OB_FAIL(fetch_raw_log_in_archive_(ls_id, start_lsn, req_size, progress, resp, archive_is_on, fetch_log_succ, ctx))) { + if (OB_ERR_OUT_OF_LOWER_BOUND == ret) { + need_retry = false; + LOG_INFO("lower bound of archive log, there is no log in this server", K(start_lsn), K(ls_id), K(req_size)); + } else if (OB_ERR_OUT_OF_UPPER_BOUND == ret) { + if (! log_may_exist_in_palf) { + need_retry = false; + ret = OB_ERR_OUT_OF_LOWER_BOUND; + LOG_INFO("log doesn't exist in palf, and exceed the upper bound of archive", K(ls_exist_in_palf), + K(log_may_exist_in_palf)); + } + } else { + LOG_WARN("fetch log from archive failed", K(req), K(ctx)); + } + } else if (! archive_is_on) { + if (! log_may_exist_in_palf) { + need_retry = false; + ret = OB_ERR_OUT_OF_LOWER_BOUND; + LOG_INFO("archive seems not on and log doesn't exit in palf", K(archive_is_on), K(log_may_exist_in_palf)); + } + } else if (fetch_log_succ) { + status.set_source(ObCdcFetchRawSource::ARCHIVE); + + if (resp.get_read_size() < req_size && ! log_may_exist_in_palf) { + resp.set_feedback(FeedbackType::ARCHIVE_ITER_END_BUT_LS_NOT_EXIST_IN_PALF); + } + + if (FetchMode::FETCHMODE_ARCHIVE != ctx.get_fetch_mode()) { + ctx.set_fetch_mode(FetchMode::FETCHMODE_ARCHIVE, "RawReadArchiveSucc"); + } + } + read_archive_time += ObTimeUtility::current_time() - fetch_archive_start_time; + } + + retry_count++; + } + + status.set_read_palf_time(read_palf_time); + status.set_read_archive_time(read_archive_time); + + if (retry_count > 1) { + LOG_INFO("retry multiple times to read log", KR(ret), K(req), K(resp), K(retry_count), + K(need_retry), K(fetch_log_succ)); + } + + return ret; +} + +int ObCdcFetcher::fetch_raw_log_in_palf_(const ObLSID &ls_id, + const LSN &start_lsn, + const int64_t req_size, + obrpc::ObCdcFetchRawLogResp &resp, + bool &ls_exist_in_palf, + bool &fetch_log_succ, + ClientLSCtx &ctx) +{ + int ret = OB_SUCCESS; + PalfHandleGuard palf_guard; + PalfHandle *palf_handle = nullptr; + int64_t read_size = 0; + const int64_t buffer_len = resp.get_buffer_len(); + fetch_log_succ = false; + + if (OB_FAIL(init_palf_handle_guard_(ls_id, palf_guard))) { + if (OB_LS_NOT_EXIST != ret) { + LOG_WARN("failed to get palf handle guard", K(ls_id)); + } else { + ls_exist_in_palf = false; + ret = OB_SUCCESS; + } + } else if (OB_ISNULL(palf_handle = palf_guard.get_palf_handle())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get null palf handle from palf guard", KP(palf_handle), K(ls_id)); + } else if(req_size > buffer_len) { + ret = OB_BUF_NOT_ENOUGH; + LOG_WARN("req_size is larger than buffer_len, buf not enough", K(req_size), K(buffer_len), + K(resp)); + } else if (OB_FAIL(palf_handle->raw_read(start_lsn, resp.get_log_buffer(), + req_size, read_size))) { + if (OB_ERR_OUT_OF_LOWER_BOUND != ret && + OB_ERR_OUT_OF_UPPER_BOUND != ret && + OB_NEED_RETRY != ret) { + LOG_WARN("raw read from palf failed", K(ls_id), K(start_lsn), K(req_size), K(resp)); + } + } else { + resp.set_read_size(read_size); + if (read_size < req_size) { + ObRole role = ObRole::INVALID_ROLE; + bool is_in_sync = true; + if (OB_FAIL(check_ls_sync_status_(ls_id, palf_guard, role, is_in_sync))) { + LOG_WARN("failed to check ls sync status", K(ls_id), K(role), K(is_in_sync)); + } else if (ObRole::FOLLOWER == role && ! is_in_sync) { + resp.set_feedback(FeedbackType::LAGGED_FOLLOWER); + } + } + } + + return ret; +} + +int ObCdcFetcher::fetch_raw_log_in_archive_(const ObLSID &ls_id, + const LSN &start_lsn, + const int64_t req_size, + const int64_t progress, + obrpc::ObCdcFetchRawLogResp &resp, + bool &archive_is_on, + bool &fetch_log_succ, + ClientLSCtx &ctx) +{ + int ret = OB_SUCCESS; + + if (OB_ISNULL(host_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get null host", KP(host_), K(ls_id), K(start_lsn)); + } else if (OB_FAIL(host_->init_archive_source_if_needed(ls_id, ctx))) { + if (OB_ALREADY_IN_NOARCHIVE_MODE == ret) { + archive_is_on = false; + ret = OB_SUCCESS; + } else { + LOG_WARN("failed to init archive source if needed", K(ls_id), K(ctx)); + } + } else { + int64_t version = 0; + ObCdcUpdateSourceFunctor update_source_func(ctx, version); + ObCdcGetSourceFunctor get_source_func(ctx, version); + ObRemoteLogRawReader raw_reader(get_source_func, update_source_func); + int64_t read_size = 0; + + if (OB_FAIL(raw_reader.init(tenant_id_, ls_id, resp.get_progress(), log_ext_handler_))) { + LOG_WARN("raw reader failed to init", K(tenant_id_), K(ls_id), K(resp), KP(log_ext_handler_)); + } else if (OB_FAIL(raw_reader.raw_read(start_lsn, resp.get_log_buffer(), req_size, read_size))) { + if (OB_ERR_OUT_OF_LOWER_BOUND != ret && + OB_ERR_OUT_OF_UPPER_BOUND != ret && + OB_NEED_RETRY != ret) { + LOG_WARN("raw reader failed to read", K(start_lsn), K(req_size), K(read_size), K(resp)); + } + } else { + fetch_log_succ = true; + resp.set_read_size(read_size); + } + } + + return ret; +} /////////////////////// FetchRunTime /////////////////////// FetchRunTime::FetchRunTime() : rpc_id_(OB_LOG_INVALID_RPC_ID), diff --git a/src/logservice/cdcservice/ob_cdc_fetcher.h b/src/logservice/cdcservice/ob_cdc_fetcher.h index f234326a26..908aa08f1b 100644 --- a/src/logservice/cdcservice/ob_cdc_fetcher.h +++ b/src/logservice/cdcservice/ob_cdc_fetcher.h @@ -21,6 +21,7 @@ #include "logservice/palf/palf_iterator.h" // PalfGroupBufferIterator #include "logservice/palf_handle_guard.h" // PalfHandleGuard #include "ob_cdc_req.h" // RPC Request and Response +#include "ob_cdc_raw_log_req.h" #include "ob_cdc_define.h" #include "ob_cdc_struct.h" // ClientLSCtx #include "logservice/archiveservice/large_buffer_pool.h" // LargeBufferPool @@ -41,6 +42,8 @@ using oceanbase::palf::LogEntry; struct FetchRunTime; +class ObCdcService; + class ObCdcFetcher { // When fetch log finds that the remaining time is less than RPC_QIT_RESERVED_TIME, @@ -52,6 +55,7 @@ public: ~ObCdcFetcher(); int init(const uint64_t tenant_id, ObLSService *ls_service, + ObCdcService *host, archive::LargeBufferPool *buffer_pool, logservice::ObLogExternalStorageHandler *log_ext_handler); void destroy(); @@ -66,6 +70,9 @@ public: int fetch_missing_log(const obrpc::ObCdcLSFetchMissLogReq &req, obrpc::ObCdcLSFetchLogResp &resp); + int fetch_raw_log(const obrpc::ObCdcFetchRawLogReq &req, + obrpc::ObCdcFetchRawLogResp &resp); + private: // @retval OB_SUCCESS Success // @retval OB_ENTRY_NOT_EXIST LS not exist in this server @@ -84,6 +91,7 @@ private: ClientLSCtx &ctx, ObCdcFetchLogTimeStats &fetch_time_stat); int set_fetch_mode_before_fetch_log_(const ObLSID &ls_id, + const LSN &start_lsn, const bool test_switch_fetch_mode, bool &ls_exist_in_palf, palf::PalfHandleGuard &palf_guard, @@ -179,6 +187,11 @@ private: int check_lag_follower_(const ObLSID &ls_id, palf::PalfHandleGuard &palf_handle_guard, obrpc::ObCdcLSFetchLogResp &resp); + + int check_ls_sync_status_(const ObLSID &ls_id, + palf::PalfHandleGuard &palf_handle_guard, + ObRole &role, + bool &in_sync); int do_fetch_missing_log_(const obrpc::ObCdcLSFetchMissLogReq &req, FetchRunTime &frt, obrpc::ObCdcLSFetchLogResp &resp, @@ -200,9 +213,30 @@ private: bool &ls_exist_in_palf, bool &archive_is_on); + int do_fetch_raw_log_(const obrpc::ObCdcFetchRawLogReq &req, + obrpc::ObCdcFetchRawLogResp &resp, + ClientLSCtx &ctx); + + int fetch_raw_log_in_palf_(const ObLSID &ls_id, + const LSN &start_lsn, + const int64_t req_size, + obrpc::ObCdcFetchRawLogResp &resp, + bool &ls_exist_in_palf, + bool &fetch_log_succ, + ClientLSCtx &ctx); + + int fetch_raw_log_in_archive_(const ObLSID &ls_id, + const LSN &start_lsn, + const int64_t req_size, + const int64_t progress, + obrpc::ObCdcFetchRawLogResp &resp, + bool &archive_is_on, + bool &fetch_log_succ, + ClientLSCtx &ctx); private: bool is_inited_; uint64_t tenant_id_; + ObCdcService *host_; ObLSService *ls_service_; archive::LargeBufferPool *large_buffer_pool_; logservice::ObLogExternalStorageHandler *log_ext_handler_; diff --git a/src/logservice/cdcservice/ob_cdc_raw_log_req.cpp b/src/logservice/cdcservice/ob_cdc_raw_log_req.cpp new file mode 100644 index 0000000000..eec910ac6a --- /dev/null +++ b/src/logservice/cdcservice/ob_cdc_raw_log_req.cpp @@ -0,0 +1,160 @@ +/** + * Copyright (c) 2023 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#include "ob_cdc_raw_log_req.h" + +namespace oceanbase +{ +namespace obrpc +{ + +//////////////////////////////////////// ObCdcFetchRawLogReq ////////////////////////////////////// + +void ObCdcFetchRawLogReq::reset() +{ + rpc_ver_ = 0; + client_id_.reset(); + tenant_id_ = OB_INVALID_TENANT_ID; + ls_id_.reset(); + start_lsn_.reset(); + file_id_ = -1; + size_ = 0; + progress_ = OB_INVALID_TIMESTAMP; + seq_ = -1; + cur_round_rpc_count_ = 0; + compressor_type_ = ObCompressorType::INVALID_COMPRESSOR; + flag_ = 0; +} + +void ObCdcFetchRawLogReq::reset(const ObCdcRpcId &client_id, + const uint64_t tenant_id, + const share::ObLSID &ls_id, + const palf::LSN &start_lsn, + const uint64_t size, + const int64_t progress) +{ + // only reset specified members for update rpc req, don't reset all + client_id_ = client_id; + tenant_id_ = tenant_id; + ls_id_ = ls_id; + start_lsn_ = start_lsn; + size_ = size; + progress_ = progress; +} + +OB_SERIALIZE_MEMBER(ObCdcFetchRawLogReq, rpc_ver_, client_id_, + tenant_id_, ls_id_, start_lsn_, file_id_, size_, progress_, + seq_, cur_round_rpc_count_, compressor_type_, flag_); + +//////////////////////////////////////// ObCdcFetchRawStatus ////////////////////////////////////// + +OB_SERIALIZE_MEMBER(ObCdcFetchRawStatus, source_, read_active_file_, process_time_, + read_palf_time_, read_archive_time_, local_to_svr_time_, queue_time_); + +//////////////////////////////////////// ObCdcFetchRawLogResp ////////////////////////////////////// + +void ObCdcFetchRawLogResp::reset() +{ + rpc_ver_ = 0; + err_ = OB_SUCCESS; + ls_id_.reset(); + file_id_ = -1; + seq_ = -1; + cur_round_rpc_count_ = 0; + feedback_type_ = FeedbackType::INVALID_FEEDBACK; + fetch_status_.reset(); + server_progress_.reset(); + read_size_ = 0; + replayable_point_scn_.reset(); +} + +void ObCdcFetchRawLogResp::reset(const share::ObLSID &ls_id, + const int64_t file_id, + const int32_t seq_no, + const int32_t cur_round_rpc_count) +{ + reset(); + ls_id_ = ls_id; + file_id_ = file_id; + seq_ = seq_no; + cur_round_rpc_count_ = cur_round_rpc_count; +} + +OB_DEF_SERIALIZE(ObCdcFetchRawLogResp) +{ + int ret = OB_SUCCESS; + + LST_DO_CODE(OB_UNIS_ENCODE, rpc_ver_, err_, ls_id_, file_id_, seq_, cur_round_rpc_count_, + cur_round_rpc_count_, feedback_type_, fetch_status_, server_progress_, + read_size_, replayable_point_scn_); + + if (OB_SUCCESS == ret && read_size_ > 0) { + if (buf_len - pos < read_size_) { + ret = OB_BUF_NOT_ENOUGH; + } else { + MEMCPY(buf + pos, log_entry_buf_, read_size_); + pos += read_size_; + } + } + + return ret; +} + +OB_DEF_DESERIALIZE(ObCdcFetchRawLogResp) +{ + int ret = OB_SUCCESS; + + LST_DO_CODE(OB_UNIS_DECODE, rpc_ver_, err_, ls_id_, file_id_, seq_, cur_round_rpc_count_, + cur_round_rpc_count_, feedback_type_, fetch_status_, server_progress_, + read_size_, replayable_point_scn_); + + if (OB_SUCC(ret)) { + if (read_size_ > 0) { + if (read_size_ + pos > data_len) { + ret = OB_INVALID_DATA; + EXTLOG_LOG(WARN, "get invalid fetch raw log resp, read_size is beyond data_len", + K(read_size_), K(pos), K(data_len)); + } else if (read_size_ > sizeof(log_entry_buf_)) { + ret = OB_BUF_NOT_ENOUGH; + EXTLOG_LOG(WARN, "log_entry_buf_ is not enough", K(read_size_)); + } else { + MEMCPY(log_entry_buf_, buf + pos, read_size_); + } + } else if (read_size_ < 0) { + ret = OB_INVALID_DATA; + EXTLOG_LOG(WARN, "get invalid fetch raw log resp, read_size is below 0", + K(read_size_), K(pos), K(data_len)); + } + } + + return ret; +} + +OB_DEF_SERIALIZE_SIZE(ObCdcFetchRawLogResp) +{ + int64_t len = 0; + + LST_DO_CODE(OB_UNIS_ADD_LEN, rpc_ver_, err_, ls_id_, file_id_, seq_, cur_round_rpc_count_, + cur_round_rpc_count_, feedback_type_, fetch_status_, server_progress_, + read_size_, replayable_point_scn_); + + if (read_size_ >= 0 && read_size_ < sizeof(log_entry_buf_)) { + len += read_size_; + } else { + EXTLOG_LOG_RET(WARN, OB_INVALID_DATA, "get invalid read_size in FetchRawLogResp", K(read_size_)); + } + + return len; +} + +} +} \ No newline at end of file diff --git a/src/logservice/cdcservice/ob_cdc_raw_log_req.h b/src/logservice/cdcservice/ob_cdc_raw_log_req.h new file mode 100644 index 0000000000..7b21da6953 --- /dev/null +++ b/src/logservice/cdcservice/ob_cdc_raw_log_req.h @@ -0,0 +1,350 @@ +/** + * Copyright (c) 2023 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef OCEANBASE_CDC_RAW_LOG_REQ_H_ +#define OCEANBASE_CDC_RAW_LOG_REQ_H_ + +#include "lib/compress/ob_compress_util.h" +#include "logservice/palf/lsn.h" +#include "ob_cdc_req_struct.h" +#include "share/ob_ls_id.h" +#include "share/scn.h" + +namespace oceanbase +{ + +namespace obrpc +{ + +class ObCdcFetchRawLogReq +{ +public: + OB_UNIS_VERSION(1); +public: + ObCdcFetchRawLogReq() { reset(); } + ~ObCdcFetchRawLogReq() { reset(); } + void reset(); + + // would not reset other fields + // if caller want to get a brand new rpc request + // use reset above + void reset(const ObCdcRpcId &client_id, + const uint64_t tenant_id, + const share::ObLSID &ls_id, + const palf::LSN &start_lsn, + const uint64_t size, + const int64_t progress); + + void set_aux_param(const int64_t file_id, + const int32_t seq_no, + const int32_t rpc_count) + { + set_file_id(file_id); + set_seq_no(seq_no), + set_current_round_rpc_count(rpc_count); + } + + const ObCdcRpcId &get_client_id() const { + return client_id_; + } + + uint64_t get_tenant_id() const { + return tenant_id_; + } + + const share::ObLSID& get_ls_id() const { + return ls_id_; + } + + const palf::LSN& get_start_lsn() const { + return start_lsn_; + } + + void set_file_id(const int64_t file_id) { + file_id_ = file_id; + } + + int64_t get_file_id() const { + return file_id_; + } + + uint64_t get_req_size() const { + return size_; + } + + int64_t get_progress() const { + return progress_; + } + + void set_seq_no(const int32_t seq) { + seq_ = seq; + } + + int32_t get_seq_no() const { + return seq_; + } + + void set_current_round_rpc_count(const int32_t rpc_count) { + cur_round_rpc_count_ = rpc_count; + } + + int32_t get_current_round_rpc_count() const { + return cur_round_rpc_count_; + } + + void set_compressor_type(const common::ObCompressorType comp_type) { + compressor_type_ = comp_type; + } + + common::ObCompressorType get_compressor_type() const { + return compressor_type_; + } + + void set_flag(int8_t flag) { + flag_ = flag; + } + + int8_t get_flag() const { + return flag_; + } + + TO_STRING_KV( + K(client_id_), + K(tenant_id_), + K(ls_id_), + K(start_lsn_), + K(file_id_), + K(size_), + K(progress_), + K(seq_), + K(cur_round_rpc_count_), + K(compressor_type_), + K(flag_) + ); + +private: + int64_t rpc_ver_; + ObCdcRpcId client_id_; + uint64_t tenant_id_; + share::ObLSID ls_id_; + palf::LSN start_lsn_; + int64_t file_id_; + uint64_t size_; + int64_t progress_; + int32_t seq_; + int32_t cur_round_rpc_count_; + ObCompressorType compressor_type_; + int8_t flag_; +}; + +enum class ObCdcFetchRawSource +{ + UNKNOWN, + PALF, + ARCHIVE, +}; + +class ObCdcFetchRawStatus +{ +public: + OB_UNIS_VERSION(1); +public: + ObCdcFetchRawStatus() { reset(); } + ~ObCdcFetchRawStatus() { reset(); } + void reset() { + source_ = ObCdcFetchRawSource::UNKNOWN; + read_active_file_ = false; + process_time_ = 0; + read_palf_time_ = 0; + local_to_svr_time_ = 0; + queue_time_ = 0; + } + + void set_source(const ObCdcFetchRawSource source) { + source_ = source; + } + + ObCdcFetchRawSource get_source() const { + return source_; + } + + void set_process_time(const int64_t ptime) { + process_time_ = ptime; + } + + int64_t get_process_time() const { + return process_time_; + } + void set_read_palf_time(const int64_t rtime) { + read_palf_time_ = rtime; + } + + int64_t get_read_palf_time() const { + return read_palf_time_; + } + + void set_read_archive_time(const int64_t rtime) { + read_archive_time_ = rtime; + } + + int64_t get_read_archive_time() const { + return read_archive_time_; + } + + void set_local_to_svr_time(const int64_t l2s_time) { + local_to_svr_time_ = l2s_time; + } + + int64_t get_local_to_svr_time() const { + return local_to_svr_time_; + } + + void set_queue_time(const int64_t qtime) { + queue_time_ = qtime; + } + + int64_t get_queue_time() const { + return queue_time_; + } + + TO_STRING_KV( + K(source_), + K(read_active_file_), + K(process_time_), + K(read_palf_time_), + K(read_archive_time_), + K(local_to_svr_time_), + K(queue_time_) + ); + +private: + ObCdcFetchRawSource source_; + bool read_active_file_; + int64_t process_time_; + int64_t read_palf_time_; + int64_t read_archive_time_; + int64_t local_to_svr_time_; + int64_t queue_time_; +}; + +class ObCdcFetchRawLogResp +{ +private: + static const int64_t FETCH_BUF_LEN = 1 << 24; // 16MB +public: + OB_UNIS_VERSION(1); +public: + ObCdcFetchRawLogResp() { reset(); } + ~ObCdcFetchRawLogResp() { reset(); } + + void reset(); + + // these info is get from rpc request, set them once. + void reset(const share::ObLSID &ls_id, + const int64_t file_id, + const int32_t seq_no, + const int32_t cur_round_rpc_count); + + void set_err(const int32_t err) { + err_ = err; + } + + int32_t get_err() const { + return err_; + } + + void set_feedback(const FeedbackType feedback) { + feedback_type_ = feedback; + } + + FeedbackType get_feedback() const { + return feedback_type_; + } + + ObCdcFetchRawStatus &get_fetch_status() { + return fetch_status_; + } + + const ObCdcFetchRawStatus &get_fetch_status() const { + return fetch_status_; + } + + void set_progress(const share::SCN progress) { + server_progress_ = progress; + } + + share::SCN get_progress() const { + return server_progress_; + } + + void set_read_size(const int64_t read_size) { + read_size_ = read_size; + } + + int64_t get_read_size() const { + return read_size_; + } + + void set_replayable_point_scn(const share::SCN &scn) { + replayable_point_scn_ = scn; + } + + const share::SCN &get_replayable_point_scn() const { + return replayable_point_scn_; + } + + const char *get_log_data() const { + return log_entry_buf_; + } + + char *get_log_buffer() { + return log_entry_buf_; + } + + int64_t get_buffer_len() { + // assume that log_entry_buf is a array + return sizeof(log_entry_buf_); + } + + TO_STRING_KV( + K(err_), + K(ls_id_), + K(file_id_), + K(seq_), + K(cur_round_rpc_count_), + K(feedback_type_), + K(fetch_status_), + K(server_progress_), + K(read_size_), + K(replayable_point_scn_) + ); + +private: + int64_t rpc_ver_; + int32_t err_; + share::ObLSID ls_id_; + int64_t file_id_; + int32_t seq_; + int32_t cur_round_rpc_count_; + FeedbackType feedback_type_; + ObCdcFetchRawStatus fetch_status_; + share::SCN server_progress_; + int64_t read_size_; + share::SCN replayable_point_scn_; + char log_entry_buf_[FETCH_BUF_LEN+palf::LOG_DIO_ALIGN_SIZE*2]; +}; + +} + +} + +#endif \ No newline at end of file diff --git a/src/logservice/cdcservice/ob_cdc_req.cpp b/src/logservice/cdcservice/ob_cdc_req.cpp index 6dfd9ca3b2..8128277fea 100644 --- a/src/logservice/cdcservice/ob_cdc_req.cpp +++ b/src/logservice/cdcservice/ob_cdc_req.cpp @@ -22,7 +22,6 @@ namespace obrpc * Request start LSN by start timestamp. * */ -OB_SERIALIZE_MEMBER(ObCdcRpcId, client_pid_, client_addr_); void ObCdcReqStartLSNByTsReq::LocateParam::reset() { @@ -472,7 +471,7 @@ void ObCdcLSFetchLogResp::reset() err_ = common::OB_NOT_INIT; debug_err_ = common::OB_NOT_INIT; ls_id_.reset(); - feedback_type_ = INVALID_FEEDBACK; + feedback_type_ = FeedbackType::INVALID_FEEDBACK; fetch_status_.reset(); next_req_lsn_.reset(); log_num_ = 0; diff --git a/src/logservice/cdcservice/ob_cdc_req.h b/src/logservice/cdcservice/ob_cdc_req.h index e9bdaaa650..fcf1ce5833 100644 --- a/src/logservice/cdcservice/ob_cdc_req.h +++ b/src/logservice/cdcservice/ob_cdc_req.h @@ -17,6 +17,7 @@ #include "share/ob_ls_id.h" // ObLSID #include "lib/compress/ob_compress_util.h" // ObCompressorType #include "logservice/palf/lsn.h" // LSN +#include "ob_cdc_req_struct.h" #include "logservice/palf/log_group_entry.h" // LogGroupEntry #include "logservice/palf/log_entry.h" // LogEntry @@ -38,72 +39,6 @@ class ObCdcLSFetchLogResp; class ObCdcLSFetchMissLogReq; -class ObCdcRpcTestFlag { -public: - // rpc request flag bit - static const int8_t OBCDC_RPC_FETCH_ARCHIVE = 1; - static const int8_t OBCDC_RPC_TEST_SWITCH_MODE = 1 << 1; - -public: - static bool is_fetch_archive_only(int8_t flag) { - return flag & OBCDC_RPC_FETCH_ARCHIVE; - } - static bool is_test_switch_mode(int8_t flag) { - return flag & OBCDC_RPC_TEST_SWITCH_MODE; - } -}; - -class ObCdcRpcId { -public: - OB_UNIS_VERSION(1); -public: - ObCdcRpcId(): client_pid_(0), client_addr_() {} - ~ObCdcRpcId() = default; - int init(const uint64_t pid, const ObAddr &addr) { - int ret = OB_SUCCESS; - if (pid > 0 && addr.is_valid()) { - // addr may not be valid - client_pid_ = pid; - client_addr_ = addr; - } else { - ret = OB_INVALID_ARGUMENT; - EXTLOG_LOG(WARN, "invalid arguments for ObCdcRpcId", KR(ret), K(pid), K(addr)); - } - return ret; - } - - void reset() { - client_pid_ = 0; - client_addr_.reset(); - } - - bool operator==(const ObCdcRpcId &that) const { - return client_pid_ == that.client_pid_ && - client_addr_ == that.client_addr_; - } - - bool operator!=(const ObCdcRpcId &that) const { - return !(*this == that); - } - - ObCdcRpcId &operator=(const ObCdcRpcId &that) { - client_pid_ = that.client_pid_; - client_addr_ = that.client_addr_; - return *this; - } - - void set_addr(ObAddr &addr) { client_addr_ = addr; } - const ObAddr& get_addr() const { return client_addr_; } - - void set_pid(uint64_t pid) { client_pid_ = pid; } - uint64_t get_pid() const { return client_pid_; } - - TO_STRING_KV(K_(client_addr), K_(client_pid)); -private: - uint64_t client_pid_; - ObAddr client_addr_; -}; - class ObCdcReqStartLSNByTsReq { public: @@ -345,16 +280,6 @@ struct ObCdcFetchStatus class ObCdcLSFetchLogResp { static const int64_t CUR_RPC_VER = 1; -public: - enum FeedbackType - { - INVALID_FEEDBACK = -1, - LAGGED_FOLLOWER = 0, // lagged follower - LOG_NOT_IN_THIS_SERVER = 1, // this server does not server this log - LS_OFFLINED = 2, // LS offlined - ARCHIVE_ITER_END_BUT_LS_NOT_EXIST_IN_PALF = 3, // Reach Max LSN in archive log but cannot switch - // to palf because ls not exists in current server - }; public: ObCdcLSFetchLogResp() { reset(); } ~ObCdcLSFetchLogResp() { reset(); } @@ -449,8 +374,8 @@ public: K_(pos)); OB_UNIS_VERSION(1); -private: - static const int64_t FETCH_BUF_LEN = palf::MAX_LOG_BUFFER_SIZE * 8; +public: + static const int64_t FETCH_BUF_LEN = 17L << 20; // 17MB static const int64_t FETCH_BUF_THRESHOLD = FETCH_BUF_LEN - palf::MAX_LOG_BUFFER_SIZE; private: diff --git a/src/logservice/cdcservice/ob_cdc_req_struct.cpp b/src/logservice/cdcservice/ob_cdc_req_struct.cpp new file mode 100644 index 0000000000..763f524874 --- /dev/null +++ b/src/logservice/cdcservice/ob_cdc_req_struct.cpp @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2023 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#include "ob_cdc_req_struct.h" + +namespace oceanbase +{ + +namespace obrpc +{ + +OB_SERIALIZE_MEMBER(ObCdcRpcId, client_pid_, client_addr_); + +int ObCdcRpcId::init(const uint64_t pid, const ObAddr &addr) { + int ret = OB_SUCCESS; + if (pid > 0 && addr.is_valid()) { + // addr may not be valid + client_pid_ = pid; + client_addr_ = addr; + } else { + ret = OB_INVALID_ARGUMENT; + EXTLOG_LOG(WARN, "invalid arguments for ObCdcRpcId", KR(ret), K(pid), K(addr)); + } + return ret; +} + +} + +} \ No newline at end of file diff --git a/src/logservice/cdcservice/ob_cdc_req_struct.h b/src/logservice/cdcservice/ob_cdc_req_struct.h new file mode 100644 index 0000000000..d84a457f44 --- /dev/null +++ b/src/logservice/cdcservice/ob_cdc_req_struct.h @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2023 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef OCEANBASE_CDC_REQ_STRUCT_H_ +#define OCEANBASE_CDC_REQ_STRUCT_H_ + +#include +#include "lib/net/ob_addr.h" +#include "lib/utility/ob_unify_serialize.h" +#include "share/ob_errno.h" + +namespace oceanbase +{ +namespace obrpc +{ + +enum class FeedbackType +{ + INVALID_FEEDBACK = -1, + LAGGED_FOLLOWER = 0, // lagged follower + LOG_NOT_IN_THIS_SERVER = 1, // this server does not server this log + LS_OFFLINED = 2, // LS offlined + ARCHIVE_ITER_END_BUT_LS_NOT_EXIST_IN_PALF = 3, // Reach Max LSN in archive log but cannot switch + // to palf because ls not exists in current server +}; + +class ObCdcRpcTestFlag { +public: + // rpc request flag bit + static const int8_t OBCDC_RPC_FETCH_ARCHIVE = 1; + static const int8_t OBCDC_RPC_TEST_SWITCH_MODE = 1 << 1; + +public: + static bool is_fetch_archive_only(int8_t flag) { + return flag & OBCDC_RPC_FETCH_ARCHIVE; + } + static bool is_test_switch_mode(int8_t flag) { + return flag & OBCDC_RPC_TEST_SWITCH_MODE; + } +}; + +class ObCdcRpcId { +public: + OB_UNIS_VERSION(1); +public: + ObCdcRpcId(): client_pid_(0), client_addr_() {} + ~ObCdcRpcId() = default; + int init(const uint64_t pid, const ObAddr &addr); + + void reset() { + client_pid_ = 0; + client_addr_.reset(); + } + + bool operator==(const ObCdcRpcId &that) const { + return client_pid_ == that.client_pid_ && + client_addr_ == that.client_addr_; + } + + bool operator!=(const ObCdcRpcId &that) const { + return !(*this == that); + } + + ObCdcRpcId &operator=(const ObCdcRpcId &that) { + client_pid_ = that.client_pid_; + client_addr_ = that.client_addr_; + return *this; + } + + void set_addr(ObAddr &addr) { client_addr_ = addr; } + const ObAddr& get_addr() const { return client_addr_; } + + void set_pid(uint64_t pid) { client_pid_ = pid; } + uint64_t get_pid() const { return client_pid_; } + + TO_STRING_KV(K_(client_addr), K_(client_pid)); +private: + uint64_t client_pid_; + ObAddr client_addr_; +}; + +} +} + +#endif \ No newline at end of file diff --git a/src/logservice/cdcservice/ob_cdc_rpc_processor.cpp b/src/logservice/cdcservice/ob_cdc_rpc_processor.cpp index 0cc7be37d8..2f4af33153 100644 --- a/src/logservice/cdcservice/ob_cdc_rpc_processor.cpp +++ b/src/logservice/cdcservice/ob_cdc_rpc_processor.cpp @@ -101,5 +101,24 @@ int ObCdcLSFetchMissingLogP::process() return OB_SUCCESS; } +int ObCdcFetchRawLogP::process() +{ + int ret = OB_SUCCESS; + + const ObCdcFetchRawLogReq &req = arg_; + ObCdcFetchRawLogResp &resp = result_; + cdc::ObCdcService *cdc_service = nullptr; + if (OB_FAIL(__get_cdc_service(rpc_pkt_->get_tenant_id(), cdc_service))) { + EXTLOG_LOG(ERROR, "__get_cdc_service failed", KR(ret)); + } else if (OB_ISNULL(cdc_service)) { + ret = OB_ERR_UNEXPECTED; + EXTLOG_LOG(ERROR, "cdc_service is null", KR(ret)); + } else { + set_result_compress_type(req.get_compressor_type()); + ret = cdc_service->fetch_raw_log(req, resp, get_send_timestamp(), get_receive_timestamp()); + } + return ret; +} + } // namespace obrpc } // namespace oceanbase diff --git a/src/logservice/cdcservice/ob_cdc_rpc_processor.h b/src/logservice/cdcservice/ob_cdc_rpc_processor.h index 45fa55c518..462a8e0e20 100644 --- a/src/logservice/cdcservice/ob_cdc_rpc_processor.h +++ b/src/logservice/cdcservice/ob_cdc_rpc_processor.h @@ -53,6 +53,16 @@ protected: int process(); }; +class ObCdcFetchRawLogP : public + obrpc::ObRpcProcessor > +{ +public: + ObCdcFetchRawLogP() {} + ~ObCdcFetchRawLogP() {} +protected: + int process(); +}; + } // namespace obrpc } // namespace oceanbase diff --git a/src/logservice/cdcservice/ob_cdc_rpc_proxy.h b/src/logservice/cdcservice/ob_cdc_rpc_proxy.h index a7ebdf799c..a7b1f7cd57 100644 --- a/src/logservice/cdcservice/ob_cdc_rpc_proxy.h +++ b/src/logservice/cdcservice/ob_cdc_rpc_proxy.h @@ -16,6 +16,7 @@ #include "rpc/obrpc/ob_rpc_proxy.h" #include "rpc/obrpc/ob_rpc_processor.h" #include "ob_cdc_req.h" +#include "ob_cdc_raw_log_req.h" namespace oceanbase { @@ -41,6 +42,9 @@ public: RPC_AP(@PR5 async_stream_fetch_miss_log, OB_LS_FETCH_MISSING_LOG, (ObCdcLSFetchMissLogReq), ObCdcLSFetchLogResp); + + RPC_AP(@PR5 async_stream_fetch_raw_log, OB_CDC_FETCH_RAW_LOG, + (ObCdcFetchRawLogReq), ObCdcFetchRawLogResp); }; } // namespace obrpc diff --git a/src/logservice/cdcservice/ob_cdc_service.cpp b/src/logservice/cdcservice/ob_cdc_service.cpp index 417760d7b5..4bf30adfbc 100644 --- a/src/logservice/cdcservice/ob_cdc_service.cpp +++ b/src/logservice/cdcservice/ob_cdc_service.cpp @@ -53,27 +53,45 @@ bool ExpiredArchiveClientLSFunctor::operator()(const ClientLSKey &key, ClientLSC return bret; } -///////////////////////////////////////////ObCdcService/////////////////////////////////////////// +/////////////////////////////////////////// UpdateCtxFunctor /////////////////////////////////////////// -// suppose archive log only has one destination. -int ObCdcService::get_backup_dest(const share::ObLSID &ls_id, share::ObBackupDest &backup_dest) +int UpdateCtxFunctor::init(const ObBackupPathString &dest_str, const int64_t version) { int ret = OB_SUCCESS; - ObCdcService *cdc_service = MTL(logservice::ObLogService *)->get_cdc_service(); - ObArchiveDestInfo archive_dest; - if (OB_ISNULL(cdc_service)) { - ret = OB_ERR_UNEXPECTED; - EXTLOG_LOG(WARN, "cdc service is null, unexpected", KR(ret)); - } else if (FALSE_IT(archive_dest = cdc_service->get_archive_dest_info())) { - } else if (archive_dest.empty()) { - ret = OB_ALREADY_IN_NOARCHIVE_MODE; - EXTLOG_LOG(WARN, "archivelog is off yet", KR(ret), K(MTL_ID())); - } else if (OB_FAIL(backup_dest.set(archive_dest.at(0).second))) { - EXTLOG_LOG(WARN, "failed to set backup dest info", KR(ret), K(archive_dest)); - } else { } + if (OB_FAIL(dest_.set(dest_str))) { + EXTLOG_LOG(WARN, "failed to set dest_str to dest", K(dest_str), K(version)); + } else { + dest_ver_ = version; + is_inited_ = true; + } return ret; } +bool UpdateCtxFunctor::operator()(const ClientLSKey &key, ClientLSCtx *value) +{ + bool bret = true; + int ret = OB_SUCCESS; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + bret = false; + EXTLOG_LOG(WARN, "update ctx functor has not been inited"); + } else if (OB_ISNULL(value)) { + // fatal error, not continue + ret = OB_ERR_UNEXPECTED; + bret = false; + EXTLOG_LOG(WARN, "get null ctx when updating ctx", KP(value), K(key)); + } else if (OB_FAIL(value->try_change_archive_source(key.get_ls_id(), dest_, dest_ver_))) { + if (OB_NO_NEED_UPDATE != ret) { + bret = false; + EXTLOG_LOG(WARN, "failed to change archive source for ctx", KPC(value), K(dest_), K(dest_ver_)); + } + } + + return bret; +} + +/////////////////////////////////////////// ObCdcService /////////////////////////////////////////// + ObCdcService::ObCdcService() : is_inited_(false), stop_flag_(true), @@ -81,6 +99,7 @@ ObCdcService::ObCdcService() locator_(), fetcher_(), tg_id_(-1), + dest_info_version_(0), dest_info_(), dest_info_lock_(), ls_ctx_map_(), @@ -108,13 +127,14 @@ int ObCdcService::init(const uint64_t tenant_id, EXTLOG_LOG(WARN, "large buffer pool init failed", KR(ret), K(tenant_id)); } else if (OB_FAIL(log_ext_handler_.init())) { EXTLOG_LOG(WARN, "log ext handler init failed", KR(ret), K(tenant_id)); - } else if (OB_FAIL(locator_.init(tenant_id, &large_buffer_pool_, &log_ext_handler_))) { + } else if (OB_FAIL(locator_.init(tenant_id, this, &large_buffer_pool_, &log_ext_handler_))) { EXTLOG_LOG(WARN, "ObCdcStartLsnLocator init failed", KR(ret), K(tenant_id)); - } else if (OB_FAIL(fetcher_.init(tenant_id, ls_service, &large_buffer_pool_, &log_ext_handler_))) { + } else if (OB_FAIL(fetcher_.init(tenant_id, ls_service, this, &large_buffer_pool_, &log_ext_handler_))) { EXTLOG_LOG(WARN, "ObCdcFetcher init failed", KR(ret), K(tenant_id)); } else if (OB_FAIL(create_tenant_tg_(tenant_id))) { EXTLOG_LOG(WARN, "cdc thread group create failed", KR(ret), K(tenant_id)); } else { + dest_info_version_ = 0; tenant_id_ = tenant_id; is_inited_ = true; } @@ -147,11 +167,18 @@ void ObCdcService::run1() if (OB_SYS_TENANT_ID != tenant_id) { if (current_ts - last_query_ts >= QUERY_INTERVAL) { // the change of archive dest info is not supported - // TODO - if (OB_FAIL(query_tenant_archive_info_())) { + bool archive_dest_changed = false; + if (OB_FAIL(query_tenant_archive_info_(archive_dest_changed))) { EXTLOG_LOG(WARN, "query_tenant_archive_info_ failed", KR(ret)); } else { - EXTLOG_LOG(INFO, "query dest_info_ succ", K_(dest_info)); + EXTLOG_LOG(INFO, "query dest_info_ succ", K_(dest_info), K(archive_dest_changed)); + if (archive_dest_changed) { + if (OB_FAIL(update_archive_dest_for_ctx_())) { + EXTLOG_LOG(WARN, "failed to update archive dest", K(dest_info_), K(dest_info_version_)); + } else { + EXTLOG_LOG(INFO, "update archive dest succ", K(dest_info_), K(dest_info_version_)); + } + } } last_query_ts = current_ts; } @@ -225,6 +252,7 @@ void ObCdcService::destroy() fetcher_.destroy(); locator_.destroy(); dest_info_.reset(); + dest_info_version_ = 0; large_buffer_pool_.destroy(); ls_ctx_map_.destroy(); log_ext_handler_.destroy(); @@ -285,6 +313,28 @@ int ObCdcService::fetch_log(const obrpc::ObCdcLSFetchLogReq &req, return ret; } +int ObCdcService::get_archive_dest_snapshot(const ObLSID &ls_id, ObBackupDest &archive_dest) +{ + int ret = OB_SUCCESS; + + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + EXTLOG_LOG(WARN, "ObCdcService not init", KR(ret)); + } else if (is_stoped()) { + ret = OB_IN_STOP_STATE; + EXTLOG_LOG(INFO, "ObCdcService is stopped"); + } else { + ObBackupPathString archive_dest_str; + if (OB_FAIL(get_archive_dest_path_snapshot_(archive_dest_str))) { + EXTLOG_LOG(WARN, "failed to get archive dest path string", K(archive_dest_str), K(ls_id)); + } else if (OB_FAIL(archive_dest.set(archive_dest_str))) { + EXTLOG_LOG(WARN, "failed to set archive_dest_str to archive dest", K(archive_dest_str), K(ls_id)); + } + } + + return ret; +} + int ObCdcService::fetch_missing_log(const obrpc::ObCdcLSFetchMissLogReq &req, obrpc::ObCdcLSFetchLogResp &resp, const int64_t send_ts, @@ -317,43 +367,169 @@ int ObCdcService::fetch_missing_log(const obrpc::ObCdcLSFetchMissLogReq &req, return ret; } -int ObCdcService::init_archive_source(const ObLSID &ls_id, - ClientLSCtx &ctx) +int ObCdcService::fetch_raw_log(const obrpc::ObCdcFetchRawLogReq &req, + obrpc::ObCdcFetchRawLogResp &resp, + const int64_t send_ts, + const int64_t recv_ts) { int ret = OB_SUCCESS; - logservice::ObRemoteLogParent *source = ctx.get_source(); - if (OB_NOT_NULL(source)) { - EXTLOG_LOG(WARN, "archive source is not null, no need to init"); - } else if (OB_ISNULL(source = logservice::ObResSrcAlloctor::alloc(ObLogRestoreSourceType::LOCATION, ls_id))) { - ret = OB_ERR_UNEXPECTED; - EXTLOG_LOG(WARN, "alloc RemoteLocationParent failed", KR(ret), K(ls_id)); - } else { - share::ObBackupDest archive_dest; - if (OB_FAIL(get_backup_dest(ls_id, archive_dest))) { - EXTLOG_LOG(WARN, "get backupdest from archivedestinfo failed", KR(ret), K(ls_id)); - } else if (OB_FAIL(static_cast(source)->set(archive_dest, SCN::max_scn()))) { - EXTLOG_LOG(WARN, "source set archive dest info failed", KR(ret), K(archive_dest)); - } else { - ctx.set_source(source); - EXTLOG_LOG(WARN, "init archive source succ", K(ctx), K(ls_id)); - } - if (OB_FAIL(ret)) { - logservice::ObResSrcAlloctor::free(source); - source = nullptr; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + EXTLOG_LOG(WARN, "ObCdcService not init", KR(ret)); + } else if (is_stoped()) { + resp.set_err(OB_IN_STOP_STATE); + EXTLOG_LOG(INFO, "ObCdcService is stopped", K(req)); + } else { + const int64_t start_ts = ObTimeUtility::current_time(); + ObCdcFetchRawStatus &status = resp.get_fetch_status(); + ret = fetcher_.fetch_raw_log(req, resp); + const int64_t end_ts = ObTimeUtility::current_time(); + if (end_ts - start_ts > FETCH_LOG_WARN_THRESHOLD) { + EXTLOG_LOG_RET(WARN, OB_ERR_TOO_MUCH_TIME, "fetch raw log cost too much time", "time", end_ts - start_ts, K(req), K(resp)); } + status.set_local_to_svr_time(recv_ts - send_ts); + status.set_queue_time(start_ts - recv_ts); + status.set_process_time(end_ts - start_ts); + do_monitor_stat_(start_ts, end_ts, send_ts, recv_ts); + + EXTLOG_LOG(TRACE, "ObCdcService fetch_raw_log", K(ret), K(req), K(resp)); } + return ret; } -int ObCdcService::query_tenant_archive_info_() +int ObCdcService::get_or_create_client_ls_ctx(const obrpc::ObCdcRpcId &client_id, + const uint64_t client_tenant_id, + const ObLSID &ls_id, + const int8_t flag, + const int64_t client_progress, + const FetchLogProtocolType proto_type, + ClientLSCtx *&ctx) +{ + int ret = OB_SUCCESS; + + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + EXTLOG_LOG(WARN, "ObCdcService not init", KR(ret)); + } else if (is_stoped()) { + ret = OB_IN_STOP_STATE; + EXTLOG_LOG(INFO, "ObCdcService is stopped", K(client_id), K(client_tenant_id), + K(ls_id)); + } else { + ClientLSKey ls_key(client_id.get_addr(), client_id.get_pid(), client_tenant_id, ls_id); + + // create ClientLSCtx when fetch_log for better maintainablity + // about the reason why not create ClientLSCtx when locating start lsn, considering the case: + // 1. Client locate lsn at server1 and server1 create the clientlsctx; + // 2. when client is about to fetch log in server1, server1 becomes unavailable; + // 3. then the client switch to server2 to fetch log; + // 4. server2 doesn't have the context of clientls, and need to create one + // So we just create ctx when fetching log + if (OB_FAIL(ls_ctx_map_.get(ls_key, ctx))) { + if (OB_ENTRY_NOT_EXIST == ret) { + if (OB_FAIL(ls_ctx_map_.create(ls_key, ctx))) { + if (OB_ENTRY_EXIST != ret) { + EXTLOG_LOG(WARN, "create client ls ctx failed", KR(ret), K(ls_key)); + } else if (OB_FAIL(ls_ctx_map_.get(ls_key, ctx))) { + EXTLOG_LOG(WARN, "failed to get ctx from ctx_map when creating ctx failed", K(ls_key)); + } + } else if (FetchLogProtocolType::LogGroupEntryProto == proto_type) { + if (OB_FAIL(ctx->init(client_progress, proto_type))) { + EXTLOG_LOG(WARN, "failed to init client ls ctx", KR(ret), K(client_progress), K(proto_type)); + } else { + // if test_switch_mode is enabled, set the init fetch mode to FETCHMODE_ARCHIVE + // so that the fetch mode could be switched to FETCHMODE_ONLINE in the next rpc in some test cases. + if (flag & ObCdcRpcTestFlag::OBCDC_RPC_TEST_SWITCH_MODE) { + ctx->set_fetch_mode(FetchMode::FETCHMODE_ARCHIVE, "InitTestSwitchMode"); + } + EXTLOG_LOG(INFO, "create client ls ctx succ", K(ls_key), K(ctx)); + } + } else if (FetchLogProtocolType::RawLogDataProto == proto_type) { + ctx->set_proto_type(proto_type); + } else { + ret = OB_INVALID_ARGUMENT; + EXTLOG_LOG(WARN, "get invalid proto_type", K(proto_type), K(ls_id), K(client_id)); + } + } else { + EXTLOG_LOG(ERROR, "get client ls ctx from ctx map failed", KR(ret)); + } + } + + if (OB_SUCC(ret) && OB_NOT_NULL(ctx)) { + ctx->update_touch_ts(); + } + } + + return ret; +} + +int ObCdcService::revert_client_ls_ctx(ClientLSCtx *ctx) +{ + int ret = OB_SUCCESS; + + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + EXTLOG_LOG(WARN, "ObCdcService not init", KR(ret)); + } else if (is_stoped()) { + ret = OB_IN_STOP_STATE; + EXTLOG_LOG(INFO, "ObCdcService is stopped"); + } else if (OB_ISNULL(ctx)) { + ret = OB_INVALID_ARGUMENT; + EXTLOG_LOG(WARN, "get null client ls ctx", KP(ctx)); + } else { + ls_ctx_map_.revert(ctx); + } + + return ret; +} + +int ObCdcService::init_archive_source_if_needed(const ObLSID &ls_id, ClientLSCtx &ctx) +{ + int ret = OB_SUCCESS; + + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + EXTLOG_LOG(WARN, "ObCdcService not init", KR(ret)); + } else if (is_stoped()) { + ret = OB_IN_STOP_STATE; + EXTLOG_LOG(INFO, "ObCdcService is stopped"); + } else if (ctx.archive_source_inited()) { + EXTLOG_LOG(TRACE, "the archive source of ctx has been inited", K(ctx)); + } else { + share::ObBackupDest archive_dest; + // we hold dest_info_lock here, and we would try to get source_lock_ in ctx later. + // make sure when we hold source_lock_, we wouldn't try to get dest_info_lock_, + // make sure the lock is locked in certain order to prevent deadlock. + SpinRLockGuard dest_info_guard(dest_info_lock_); + + if (dest_info_.empty()) { + ret = OB_ALREADY_IN_NOARCHIVE_MODE; + EXTLOG_LOG(WARN, "archivelog is off yet", KR(ret), K(MTL_ID())); + } else if (OB_FAIL(archive_dest.set(dest_info_.at(0).second))) { + EXTLOG_LOG(WARN, "failed to set backup dest info", KR(ret), K(archive_dest), "path", + dest_info_.at(0).second); + } else if (OB_FAIL(ctx.try_init_archive_source(ls_id, archive_dest, dest_info_version_))) { + if (OB_INIT_TWICE != ret) { + EXTLOG_LOG(WARN, "failed to init archive source", K(ls_id), K(archive_dest), K(dest_info_version_)); + } else { + ret = OB_SUCCESS; + EXTLOG_LOG(INFO, "ctx source has been inited", K(ls_id), K(archive_dest), K(dest_info_version_)); + } + } + } + + return ret; +} + +int ObCdcService::query_tenant_archive_info_(bool &archive_dest_changed) { int ret = OB_SUCCESS; share::ObArchivePersistHelper helper; uint64_t tenant_id = MTL_ID(); ObMySQLProxy *mysql_proxy = GCTX.sql_proxy_; ObArchiveDestInfo tmp_info; - + archive_dest_changed = false; if (OB_ISNULL(mysql_proxy)) { ret = OB_ERR_UNEXPECTED; EXTLOG_LOG(ERROR, "mysql_proxy is null, unexpected", KR(ret)); @@ -361,14 +537,70 @@ int ObCdcService::query_tenant_archive_info_() EXTLOG_LOG(WARN, "init ObArchivePersistHelper failed", KR(ret), K(tenant_id)); } else if (OB_FAIL(helper.get_valid_dest_pairs(*mysql_proxy, tmp_info))) { EXTLOG_LOG(WARN, "get_valid_dest_pairs failed", KR(ret), K(tenant_id)); - } else { + } else if (is_archive_dest_changed_(tmp_info)) { // to minimize lock conflict - ObSpinLockGuard lock_guard(dest_info_lock_); + SpinWLockGuard lock_guard(dest_info_lock_); dest_info_ = tmp_info; + dest_info_version_++; + archive_dest_changed = true; } return ret; } +bool ObCdcService::is_archive_dest_changed_(const ObArchiveDestInfo &info) +{ + bool bret = false; + // no need to use lock to protect dest_info here, dest_info will only be changed + // in caller thread. + + if (dest_info_.count() != info.count()) { + bret = true; + } else if (0 == dest_info_.count()) { + bret = false; + } else if (dest_info_.at(0).second != info.at(0).second) { + // TODO: multi archive destination is not supported, + // use a more comprehensively comparation method to find differece for each + // archive destination + bret = true; + } + + return bret; +} + +int ObCdcService::update_archive_dest_for_ctx_() +{ + int ret = OB_SUCCESS; + + UpdateCtxFunctor update_func; + if (dest_info_.count() > 0) { + if (OB_FAIL(update_func.init(dest_info_.at(0).second, dest_info_version_))) { + EXTLOG_LOG(WARN, "update functor failed to init", K(dest_info_), K(dest_info_version_)); + } else if (OB_FAIL(ls_ctx_map_.for_each(update_func))) { + EXTLOG_LOG(WARN, "failed to update ctx in ctx map"); + } + } else { + EXTLOG_LOG(INFO, "don't update archive dest if no archive dest found", K(dest_info_), + K(dest_info_version_)); + } + + return ret; +} + +int ObCdcService::get_archive_dest_path_snapshot_(ObBackupPathString &archive_dest_str) +{ + int ret = OB_SUCCESS; + + SpinRLockGuard dest_info_read_lock(dest_info_lock_); + if (dest_info_.empty()) { + ret = OB_ALREADY_IN_NOARCHIVE_MODE; + EXTLOG_LOG(INFO, "archive is not enabled yet", K(dest_info_)); + } else if (OB_FAIL(archive_dest_str.assign(dest_info_.at(0).second))) { + EXTLOG_LOG(WARN, "failed to assign dest_info to archive_dest_str", K(dest_info_), K(dest_info_version_)); + } + + return ret; +} + int ObCdcService::recycle_expired_ctx_(const int64_t cur_ts) { int ret = OB_SUCCESS; @@ -386,8 +618,7 @@ int ObCdcService::resize_log_ext_handler_() const int64_t current_ts = ObTimeUtility::current_time(); const int64_t tenant_max_cpu = MTL_CPU_COUNT(); ExpiredArchiveClientLSFunctor functor(current_ts); - ObStorageType type = common::OB_STORAGE_MAX_TYPE; - ObArchiveDestInfo dest_info = get_archive_dest_info(); + // TODO: adapt threads number according to different storage devices if (OB_FAIL(ls_ctx_map_.for_each(functor))) { EXTLOG_LOG(ERROR, "failed to get expired archive client ls key in ls_ctx_map"); diff --git a/src/logservice/cdcservice/ob_cdc_service.h b/src/logservice/cdcservice/ob_cdc_service.h index f043688e1d..1df1d4f698 100644 --- a/src/logservice/cdcservice/ob_cdc_service.h +++ b/src/logservice/cdcservice/ob_cdc_service.h @@ -68,11 +68,30 @@ private: int64_t other_client_ls_cnt_; }; +class UpdateCtxFunctor { +public: + UpdateCtxFunctor(): + is_inited_(false), + dest_(), + dest_ver_(0) { } + ~UpdateCtxFunctor() { + is_inited_ = false; + dest_.reset(); + dest_ver_ = 0; + } + + int init(const ObBackupPathString &dest_str, const int64_t version); + + bool operator()(const ClientLSKey &key, ClientLSCtx *value); + +private: + bool is_inited_; + ObBackupDest dest_; + int64_t dest_ver_; +}; + class ObCdcService: public lib::TGRunnable { -public: - static int get_backup_dest(const share::ObLSID &ls_id, share::ObBackupDest &backup_dest); - static int init_archive_source(const ObLSID &ls_id, ClientLSCtx &ctx); public: ObCdcService(); ~ObCdcService(); @@ -104,23 +123,48 @@ public: const int64_t send_ts, const int64_t recv_ts); - ObArchiveDestInfo get_archive_dest_info() { - // need to get the lock and **NOT** return the reference - // if we return reference, there may be some thread-safe issues, - // because there is a background thread updating dest_info_ periodically - ObSpinLockGuard lock_guard(dest_info_lock_); - return dest_info_; - } + int fetch_raw_log(const obrpc::ObCdcFetchRawLogReq &req, + obrpc::ObCdcFetchRawLogResp &resp, + const int64_t send_ts, + const int64_t recv_ts); + + int get_archive_dest_snapshot(const ObLSID &ls_id, + ObBackupDest &archive_dest); ClientLSCtxMap &get_ls_ctx_map() { return ls_ctx_map_; } + void get_ls_ctx_map(ClientLSCtxMap *&ctx_map) { + ctx_map = &ls_ctx_map_; + } + + int get_or_create_client_ls_ctx(const obrpc::ObCdcRpcId &client_id, + const uint64_t client_tenant_id, + const ObLSID &ls_id, + const int8_t flag, + const int64_t client_progress, + const FetchLogProtocolType proto_type, + ClientLSCtx *&ctx); + + int revert_client_ls_ctx(ClientLSCtx *ctx); + + int init_archive_source_if_needed(const ObLSID &ls_id, ClientLSCtx &ctx); + TO_STRING_KV(K_(is_inited)); private: - int query_tenant_archive_info_(); + int query_tenant_archive_info_(bool &archive_dest_changed); + + // no lock protection, make sure it's called only in CdcService::run1 + bool is_archive_dest_changed_(const ObArchiveDestInfo &info); + + // no lock protection, make sure it's called only in CdcService::run1 + int update_archive_dest_for_ctx_(); + + int get_archive_dest_path_snapshot_(ObBackupPathString &archive_dest_str); + int recycle_expired_ctx_(const int64_t cur_ts); int resize_log_ext_handler_(); @@ -145,8 +189,9 @@ private: ObCdcFetcher fetcher_; int tg_id_; + int64_t dest_info_version_; ObArchiveDestInfo dest_info_; - common::ObSpinLock dest_info_lock_; + SpinRWLock dest_info_lock_; ClientLSCtxMap ls_ctx_map_; archive::LargeBufferPool large_buffer_pool_; logservice::ObLogExternalStorageHandler log_ext_handler_; diff --git a/src/logservice/cdcservice/ob_cdc_start_lsn_locator.cpp b/src/logservice/cdcservice/ob_cdc_start_lsn_locator.cpp index 41b359dc9f..7e6d8e2439 100644 --- a/src/logservice/cdcservice/ob_cdc_start_lsn_locator.cpp +++ b/src/logservice/cdcservice/ob_cdc_start_lsn_locator.cpp @@ -23,6 +23,7 @@ namespace cdc { ObCdcStartLsnLocator::ObCdcStartLsnLocator() : is_inited_(false), + host_(NULL), tenant_id_(OB_INVALID_TENANT_ID), large_buffer_pool_(NULL), log_ext_handler_(NULL) @@ -35,6 +36,7 @@ ObCdcStartLsnLocator::~ObCdcStartLsnLocator() } int ObCdcStartLsnLocator::init(const uint64_t tenant_id, + ObCdcService *host, archive::LargeBufferPool *buffer_pool, logservice::ObLogExternalStorageHandler *log_ext_handler) { @@ -43,11 +45,13 @@ int ObCdcStartLsnLocator::init(const uint64_t tenant_id, if (IS_INIT) { ret = OB_INIT_TWICE; LOG_WARN("inited twice", KR(ret)); - } else if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id) || OB_ISNULL(buffer_pool)) { + } else if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id) || OB_ISNULL(buffer_pool) || + OB_ISNULL(host)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(buffer_pool)); } else { is_inited_ = true; + host_ = host; tenant_id_ = tenant_id; large_buffer_pool_ = buffer_pool; log_ext_handler_ = log_ext_handler; @@ -60,6 +64,7 @@ void ObCdcStartLsnLocator::destroy() { if (is_inited_) { is_inited_ = false; + host_ = NULL; tenant_id_ = OB_INVALID_TENANT_ID; large_buffer_pool_ = NULL; log_ext_handler_ = NULL; @@ -214,8 +219,8 @@ int ObCdcStartLsnLocator::do_locate_ls_(const bool fetch_archive_only, if (OB_SUCC(ret) && need_seek_archive) { logservice::ObLogArchivePieceContext piece_ctx; share::ObBackupDest backup_dest; - if (OB_FAIL(ObCdcService::get_backup_dest(ls_id, backup_dest))) { - if (OB_ENTRY_NOT_EXIST == ret) { + if (OB_FAIL(host_->get_archive_dest_snapshot(ls_id, backup_dest))) { + if (OB_ALREADY_IN_NOARCHIVE_MODE == ret) { ret = OB_ERR_OUT_OF_LOWER_BOUND; LOG_WARN("try to seek start lsn in archive, but archive dest doesn't exist", KR(ret), K(ls_id)); } else { @@ -232,8 +237,9 @@ int ObCdcStartLsnLocator::do_locate_ls_(const bool fetch_archive_only, result_ts_ns = start_ts_ns; // for RemoteLogIterator::init ClientLSCtx ctx; - ObCdcGetSourceFunctor get_source_func(ctx); - ObCdcUpdateSourceFunctor update_source_func(ctx); + int64_t version = 0; + ObCdcGetSourceFunctor get_source_func(ctx, version); + ObCdcUpdateSourceFunctor update_source_func(ctx, version); logservice::ObRemoteLogGroupEntryIterator remote_group_iter(get_source_func, update_source_func); constexpr int64_t MAX_RETRY_COUNT = 4; // for RemoteLogIterator::next @@ -242,7 +248,7 @@ int ObCdcStartLsnLocator::do_locate_ls_(const bool fetch_archive_only, LSN lsn; int64_t retry_time = 0; do { - if (nullptr == ctx.get_source() && OB_FAIL(ObCdcService::init_archive_source(ls_id, ctx))) { + if (OB_FAIL(host_->init_archive_source_if_needed(ls_id, ctx))) { LOG_WARN("failed to init archive source", K(ctx), K(ls_id)); } else if (! remote_group_iter.is_init() && OB_FAIL(remote_group_iter.init(tenant_id_, ls_id, start_scn, result_lsn, LSN(palf::LOG_MAX_LSN_VAL), large_buffer_pool_, log_ext_handler_))) { diff --git a/src/logservice/cdcservice/ob_cdc_start_lsn_locator.h b/src/logservice/cdcservice/ob_cdc_start_lsn_locator.h index df7d12eaf8..36c5e7b424 100644 --- a/src/logservice/cdcservice/ob_cdc_start_lsn_locator.h +++ b/src/logservice/cdcservice/ob_cdc_start_lsn_locator.h @@ -29,6 +29,7 @@ namespace cdc { using oceanbase::share::ObLSID; using oceanbase::palf::LSN; +class ObCdcService; typedef obrpc::ObCdcReqStartLSNByTsReq ObLocateLSNByTsReq; typedef obrpc::ObCdcReqStartLSNByTsResp ObLocateLSNByTsResp; @@ -39,6 +40,7 @@ public: ObCdcStartLsnLocator(); ~ObCdcStartLsnLocator(); int init(const uint64_t tenant_id, + ObCdcService *host, archive::LargeBufferPool *large_buffer_pool, logservice::ObLogExternalStorageHandler *log_ext_handler); void destroy(); @@ -64,6 +66,7 @@ private: private: bool is_inited_; + ObCdcService *host_; uint64_t tenant_id_; archive::LargeBufferPool *large_buffer_pool_; logservice::ObLogExternalStorageHandler *log_ext_handler_; diff --git a/src/logservice/cdcservice/ob_cdc_struct.cpp b/src/logservice/cdcservice/ob_cdc_struct.cpp index 8690d6779c..f63c832d62 100644 --- a/src/logservice/cdcservice/ob_cdc_struct.cpp +++ b/src/logservice/cdcservice/ob_cdc_struct.cpp @@ -99,13 +99,15 @@ void ClientLSKey::reset() ///////////////////////////////////////////ClientLSCtx/////////////////////////////////////////// ClientLSCtx::ClientLSCtx() - : is_inited_(false), - source_lock_(ObLatchIds::CDC_SERVICE_LS_CTX_LOCK), + : source_lock_(ObLatchIds::CDC_SERVICE_LS_CTX_LOCK), + source_version_(0), source_(NULL), + proto_type_(FetchLogProtocolType::Unknown), fetch_mode_(FetchMode::FETCHMODE_UNKNOWN), last_touch_ts_(OB_INVALID_TIMESTAMP), client_progress_(OB_INVALID_TIMESTAMP) { + update_touch_ts(); } ClientLSCtx::~ClientLSCtx() @@ -113,87 +115,228 @@ ClientLSCtx::~ClientLSCtx() reset(); } -int ClientLSCtx::init(int64_t client_progress) +int ClientLSCtx::init(int64_t client_progress, const FetchLogProtocolType type) { int ret = OB_SUCCESS; if (OB_INVALID_TIMESTAMP != client_progress) { - is_inited_ = true; set_progress(client_progress); + set_proto_type(type); set_fetch_mode(FetchMode::FETCHMODE_ONLINE, "ClientLSCtxInit"); update_touch_ts(); } else { ret = OB_INVALID_ARGUMENT; - EXTLOG_LOG(WARN, "client progress is invalid", KR(ret), K(client_progress)); + LOG_WARN("client progress is invalid", KR(ret), K(client_progress)); } return ret; } +int ClientLSCtx::try_init_archive_source(const ObLSID &ls_id, + const ObBackupDest &archive_dest, + const int64_t dest_version) +{ + int ret = OB_SUCCESS; + + if (OB_NOT_NULL(source_)) { + ret = OB_INIT_TWICE; + LOG_TRACE("archive source is not null, no need to init"); + } else { + SpinWLockGuard ctx_source_guard(source_lock_); + logservice::ObRemoteLogParent *tmp_source = nullptr; + + // double check to avoid concurrency issue + if (OB_NOT_NULL(source_)) { + ret = OB_INIT_TWICE; + LOG_INFO("archive source is not null, no need to init"); + } else if (! archive_dest.is_valid()) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("archive dest is not valid", K(archive_dest), K(dest_version)); + } else if (OB_ISNULL(tmp_source = logservice::ObResSrcAlloctor::alloc(ObLogRestoreSourceType::LOCATION, ls_id))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("alloc RemoteLocationParent failed", KR(ret), K(ls_id)); + } else if (OB_FAIL(static_cast(tmp_source)->set( + archive_dest, SCN::max_scn()))) { + LOG_WARN("source set archive dest info failed", KR(ret), K(archive_dest)); + } else if (OB_FAIL(set_source_version_(tmp_source, dest_version))) { + // expect set success, source should be null and dest_info_version should be 0 + LOG_WARN("failed to set source and version", K(dest_version), + K(archive_dest), K(ls_id)); + } else { + LOG_INFO("init archive source succ", K(archive_dest), K(dest_version), K(ls_id)); + } + + if (OB_FAIL(ret) && OB_NOT_NULL(tmp_source)) { + logservice::ObResSrcAlloctor::free(tmp_source); + } + } + + return ret; +} + +int ClientLSCtx::try_deep_copy_source(const ObLSID &ls_id, + logservice::ObRemoteLogParent *&target_src, + int64_t &version) const +{ + int ret = OB_SUCCESS; + + SpinRLockGuard ctx_source_guard(source_lock_); + if (OB_ISNULL(source_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("source in ClientLSCtx is null, cannot get source from ctx", KR(ret), K(ls_id)); + } else { + logservice::ObRemoteLogParent *tmp_source = logservice::ObResSrcAlloctor::alloc( + source_->get_source_type(), ls_id); + if (OB_ISNULL(tmp_source)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("source allocated is null, allocate failed", KR(ret), K(ls_id)); + } else if (OB_FAIL(source_->deep_copy_to(*tmp_source))) { + LOG_WARN("deep copy from source in ctx failed", KR(ret), K(ls_id)); + } else { + target_src = tmp_source; + version = source_version_; + } + + if (OB_FAIL(ret) && OB_NOT_NULL(tmp_source)) { + logservice::ObResSrcAlloctor::free(tmp_source); + } + } + + return ret; +} + +int ClientLSCtx::try_update_archive_source(logservice::ObRemoteLogParent *target_source, + const int64_t source_ver) +{ + int ret = OB_SUCCESS; + + if (OB_ISNULL(target_source)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("get null source when trying to update archive source in ctx", KPC(this), K(source_ver), KP(target_source)); + } else { + SpinWLockGuard ctx_source_guard(source_lock_); + if (OB_ISNULL(source_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get null source in ctx, unexpected", KPC(this)); + } else if (source_ver < source_version_) { + LOG_INFO("no need to update archive source whose version is higher", K(source_ver), K(source_version_)); + } else if (source_ver > source_version_) { + // target source should come from ctx some time ago, if it's newer than the source in ctx, + // it should be some concurrency issue which is unexpected, because the source in ctx should + // never rollback. + ret = OB_ERR_UNEXPECTED; + LOG_WARN("target source is newer than the source in ctx, unexpected", K(source_ver), K(source_version_)); + } else if (source_->get_source_type() != target_source->get_source_type()) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("source type doesn't match", KPC(source_), KPC(target_source)); + } else if (OB_FAIL(source_->update_locate_info(*target_source))) { + LOG_WARN("update locate info failed", KPC(source_), KPC(target_source)); + } + } + + return ret; +} + +int ClientLSCtx::try_change_archive_source(const ObLSID &ls_id, + const ObBackupDest &dest, + const int64_t source_ver) +{ + int ret = OB_SUCCESS; + + SpinWLockGuard ctx_source_guard(source_lock_); + if (nullptr == source_) { + // ignore & continue + } else if (source_ver > source_version_) { + logservice::ObRemoteLocationParent *new_source = static_cast( + logservice::ObResSrcAlloctor::alloc(ObLogRestoreSourceType::LOCATION, ls_id)); + if (OB_ISNULL(new_source)) { + // continue + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to alloc new source", K(ls_id)); + } else if (OB_FAIL(new_source->set(dest, SCN::max_scn()))) { + // fatal error, not continue + LOG_WARN("failed to set archive dest", K(dest), K(ls_id)); + } else if (OB_FAIL(set_source_version_(new_source, source_ver))) { + if (OB_NO_NEED_UPDATE == ret) { + LOG_INFO("no need update source", K(source_ver), K(source_version_)); + } else { + LOG_WARN("failed to set source version", K(dest), K(ls_id), K(source_ver)); + } + } + + if (OB_FAIL(ret) && OB_NOT_NULL(new_source)) { + logservice::ObResSrcAlloctor::free(new_source); + } + } else { + // old or equal version, not update + } + + return ret; +} + void ClientLSCtx::reset() { - is_inited_ = false; if (NULL != source_) { logservice::ObResSrcAlloctor::free(source_); source_ = NULL; + source_version_ = 0; } + proto_type_ = FetchLogProtocolType::Unknown; fetch_mode_ = FetchMode::FETCHMODE_UNKNOWN; last_touch_ts_ = OB_INVALID_TIMESTAMP; client_progress_ = OB_INVALID_TIMESTAMP; } -void ClientLSCtx::set_source(logservice::ObRemoteLogParent *source) +void ClientLSCtx::set_source_(logservice::ObRemoteLogParent *source) { - if (NULL != source_) { - logservice::ObResSrcAlloctor::free(source_); - source_ = NULL; - } + logservice::ObRemoteLogParent *origin_source = source_; source_ = source; + if (NULL != origin_source) { + logservice::ObResSrcAlloctor::free(origin_source); + } + +} + +int ClientLSCtx::set_source_version_(logservice::ObRemoteLogParent *source, const int64_t version) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(source)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("get null source when set source", KP(source), K(version)); + } else if (version > source_version_) { + set_source_(source); + source_version_ = version; + } else { + ret = OB_NO_NEED_UPDATE; + } + + return ret; } ////////////////////////////////////////////////////////////////////////// int ObCdcGetSourceFunctor::operator()(const share::ObLSID &id, logservice::ObRemoteSourceGuard &guard) { int ret = OB_SUCCESS; - ObSpinLockGuard ctx_source_guard(ctx_.source_lock_); - logservice::ObRemoteLogParent *ctx_source = ctx_.get_source(); - if (OB_ISNULL(ctx_source)) { + logservice::ObRemoteLogParent *source = nullptr; + if (OB_FAIL(ctx_.try_deep_copy_source(id, source, version_))) { + LOG_WARN("failed to deep copy source", K(id), K(ctx_)); + } else if (OB_ISNULL(source)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("source in ClientLSCtx is null, cannot get source from ctx", KR(ret), K(id)); - } else { - logservice::ObRemoteLogParent *source = logservice::ObResSrcAlloctor::alloc(ctx_source->get_source_type(), id); - if (OB_ISNULL(source)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("source allocated is null, allocate failed", KR(ret), K(id)); - } else if (OB_FAIL(ctx_source->deep_copy_to(*source))) { - LOG_WARN("deep copy from source in ctx failed", KR(ret), K(id)); - } else if (OB_FAIL(guard.set_source(source))) { - LOG_WARN("RemoteSourceGuard set source failed", KR(ret)); - } else { } - - if (OB_FAIL(ret) && OB_NOT_NULL(source)) { - logservice::ObResSrcAlloctor::free(source); - source = nullptr; - } - } + LOG_WARN("get null source after deep copy, unexpected", KP(source), K(id)); + } else if (OB_FAIL(guard.set_source(source))) { + LOG_WARN("RemoteSourceGuard set source failed", KR(ret)); + } else { } return ret; } int ObCdcUpdateSourceFunctor::operator()(const share::ObLSID &id, logservice::ObRemoteLogParent *source) { int ret = OB_SUCCESS; UNUSED(id); - ObSpinLockGuard ctx_source_guard(ctx_.source_lock_); - logservice::ObRemoteLogParent *ctx_source = ctx_.get_source(); if (OB_ISNULL(source)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("source is null when updating source", KR(ret), K(id)); - } else if (OB_ISNULL(ctx_source)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("source in ctx is null when updating source", KR(ret), K(id)); - } else if (ctx_source->get_source_type() != source->get_source_type()) { - LOG_WARN("the type of source and ctx_source is not same", KR(ret), KPC(source), KPC(ctx_source)); - } else if (OB_FAIL(ctx_source->update_locate_info(*source))) { - LOG_WARN("update locate info failed", KR(ret)); + } else if (OB_FAIL(ctx_.try_update_archive_source(source, version_))) { + LOG_WARN("failed to update source in ctx", KR(ret), K(id)); } return ret; } } // cdc -} // oceanbase \ No newline at end of file +} // oceanbase diff --git a/src/logservice/cdcservice/ob_cdc_struct.h b/src/logservice/cdcservice/ob_cdc_struct.h index d0d09321a2..ff170cd107 100644 --- a/src/logservice/cdcservice/ob_cdc_struct.h +++ b/src/logservice/cdcservice/ob_cdc_struct.h @@ -32,18 +32,23 @@ class ClientLSCtx; class ObCdcGetSourceFunctor { public: - explicit ObCdcGetSourceFunctor(ClientLSCtx &ctx): ctx_(ctx) {} + explicit ObCdcGetSourceFunctor(ClientLSCtx &ctx, int64_t &version): ctx_(ctx), version_(version) {} int operator()(const share::ObLSID &id, logservice::ObRemoteSourceGuard &guard); + private: ClientLSCtx &ctx_; + int64_t &version_; }; class ObCdcUpdateSourceFunctor { public: - explicit ObCdcUpdateSourceFunctor(ClientLSCtx &ctx): ctx_(ctx) {} + explicit ObCdcUpdateSourceFunctor(ClientLSCtx &ctx, int64_t &version): + ctx_(ctx), + version_(version) {} int operator()(const share::ObLSID &id, logservice::ObRemoteLogParent *source); private: ClientLSCtx &ctx_; + int64_t &version_; }; // Temporarily not supported @@ -77,6 +82,23 @@ public: int compare(const ClientLSKey &key) const; void reset(); + const common::ObAddr &get_client_addr() const { + return client_addr_; + } + + uint64_t get_client_pid() const { + return client_pid_; + } + + uint64_t get_tenant_id() const { + return tenant_id_; + } + + const ObLSID &get_ls_id() const { + return ls_id_; + } + + TO_STRING_KV(K_(client_addr), K_(client_pid), K_(ls_id)) private: @@ -95,6 +117,13 @@ enum class FetchMode { FETCHMODE_MAX }; +enum class FetchLogProtocolType +{ + Unknown = -1, + LogGroupEntryProto = 0, + RawLogDataProto = 1, +}; + class ClientLSCtx: public common::LinkHashValue { public: @@ -102,38 +131,105 @@ public: ~ClientLSCtx(); public: - int init(const int64_t client_progress); - void reset(); - void set_source(logservice::ObRemoteLogParent *source); - logservice::ObRemoteLogParent *get_source() { return source_; } + int init(const int64_t client_progress, const FetchLogProtocolType proto); + // thread safe method, + // OB_INIT_TWICE: archive source has been inited; + // OB_ALLOCATE_MEMORY_FAILED + // OB_NO_NEED_UPDATE: there is a newer archive dest, which is unexpected + // other + int try_init_archive_source(const ObLSID &ls_id, + const ObBackupDest &archive_dest, + const int64_t dest_version); + + // thread safe method + // deep copy source in ctx to target_src, would allocate memory for target_src. + // caller should call logservice::ObResSrcAlloctor::free to free target_src + int try_deep_copy_source(const ObLSID &ls_id, + logservice::ObRemoteLogParent *&target_src, + int64_t &version) const; + + // thread safe method + // write the info of current source to source in ctx. + int try_update_archive_source(logservice::ObRemoteLogParent *source, + const int64_t source_ver); + + // thread safe method + int try_change_archive_source(const ObLSID &ls_id, + const ObBackupDest &dest, + const int64_t source_ver); + + bool archive_source_inited() const { + SpinRLockGuard guard(source_lock_); + return nullptr != source_; + } + + // make sure only one thread would call this method. + void reset(); + + void set_proto_type(const FetchLogProtocolType type) { + FetchLogProtocolType from = proto_type_, to = type; + proto_type_ = type; + EXTLOG_LOG(INFO, "set fetch protocol ", K(from), K(to)); + } + + // non-thread safe method + FetchLogProtocolType get_proto_type() const { + return proto_type_; + } + + // non-thread safe method void set_fetch_mode(FetchMode mode, const char *reason) { FetchMode from = fetch_mode_, to = mode; fetch_mode_ = mode; EXTLOG_LOG(INFO, "set fetch mode ", K(from), K(to), K(reason)); } + + // non-thread safe method FetchMode get_fetch_mode() const { return fetch_mode_; } + // non-thread safe method void update_touch_ts() { last_touch_ts_ = ObTimeUtility::current_time(); } + + // non-thread safe method int64_t get_touch_ts() const { return last_touch_ts_; } + // non-thread safe method void set_progress(int64_t progress) { client_progress_ = progress; } + + // non-thread safe method int64_t get_progress() const { return client_progress_; } TO_STRING_KV(KP_(source), + K_(source_version), + K_(proto_type), K_(fetch_mode), K_(last_touch_ts), K_(client_progress)) -friend class ObCdcGetSourceFunctor; -friend class ObCdcUpdateSourceFunctor; +private: + // caller need to hold source_lock_ before invoke this method + int set_source_version_(logservice::ObRemoteLogParent *source, const int64_t version); + // caller need to hold source_lock_ before invoke this method + void set_source_(logservice::ObRemoteLogParent *source); private: - bool is_inited_; - ObSpinLock source_lock_; + SpinRWLock source_lock_; + // GUARDED_BY(source_lock_) + int64_t source_version_; + // GUARDED_BY(source_lock_) logservice::ObRemoteLogParent *source_; + // stat, it's ok even if it's not correct. + // only set when init, can hardly be wrong + FetchLogProtocolType proto_type_; + // it concerns about the thread num of log_ext_storage_handler, + // should be eventually correct. FetchMode fetch_mode_; + // it's used for recycling context, would be updated when fetching log + // though it may not be precise, it wouldn't deviate a lot, unless some + // threads get stuck for a long time or clock drift occurs. int64_t last_touch_ts_; + // for fetch_raw_log protocol, it's not used. int64_t client_progress_; }; @@ -142,4 +238,4 @@ typedef ObLinkHashMap ClientLSCtxMap; } } -#endif \ No newline at end of file +#endif diff --git a/src/logservice/libobcdc/src/CMakeLists.txt b/src/logservice/libobcdc/src/CMakeLists.txt index 68ce13a67b..f7bf97e1de 100644 --- a/src/logservice/libobcdc/src/CMakeLists.txt +++ b/src/logservice/libobcdc/src/CMakeLists.txt @@ -118,6 +118,7 @@ ob_set_subtarget(obcdc_object_list common ob_log_table_id_cache.cpp ob_log_table_matcher.cpp ob_log_tenant.cpp + ob_log_tic_update_info.cpp ob_log_tenant_mgr.cpp ob_log_tenant_task_queue.cpp ob_log_timer.cpp diff --git a/src/logservice/libobcdc/src/ob_log_committer.cpp b/src/logservice/libobcdc/src/ob_log_committer.cpp index 02f30e551d..0fdc4f0230 100644 --- a/src/logservice/libobcdc/src/ob_log_committer.cpp +++ b/src/logservice/libobcdc/src/ob_log_committer.cpp @@ -1259,7 +1259,7 @@ int ObLogCommitter::commit_binlog_record_list_(TransCtx &trans_ctx, // unexpected LOG_ERROR("unexpected skiping trans with valid br", KR(ret), K(trans_ctx)); } else { - LOG_INFO("trans has no valid br to output, skip this trans", KR(ret), K(trans_ctx)); + LOG_DEBUG("trans has no valid br to output, skip this trans", KR(ret), K(trans_ctx)); ret = OB_SUCCESS; } } else { diff --git a/src/logservice/libobcdc/src/ob_log_config.cpp b/src/logservice/libobcdc/src/ob_log_config.cpp index 42255dfb44..e4b0bcc2ed 100644 --- a/src/logservice/libobcdc/src/ob_log_config.cpp +++ b/src/logservice/libobcdc/src/ob_log_config.cpp @@ -51,6 +51,14 @@ int ObLogConfig::init() void ObLogConfig::destroy() { ObBaseConfig::destroy(); + if (nullptr != tb_white_list_buf_) { + ob_free(tb_white_list_buf_); + tb_white_list_buf_ = nullptr; + } + if (nullptr != tb_black_list_buf_) { + ob_free(tb_black_list_buf_); + tb_black_list_buf_ = nullptr; + } inited_ = false; } @@ -167,7 +175,30 @@ int ObLogConfig::load_from_map(const ConfigMap &configs, for (; OB_SUCCESS == ret && iter != configs.end(); iter++) { ObConfigItem *const *pp_item = NULL; - if (NULL == (pp_item = container_.get(ObConfigStringKey(iter->first.c_str())))) { + const char *name = iter->first.c_str(); + const char *value = iter->second.c_str(); + + if (strlen(value) > OB_MAX_CONFIG_VALUE_LEN && 0 == strcmp("tb_white_list", name)) { + const int64_t buf_len = strlen(value) + 1; + if (OB_ISNULL(tb_white_list_buf_ = static_cast(ob_malloc(buf_len, "white_list_buf")))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_ERROR("alloc memory failed", KR(ret), K(buf_len)); + } else { + memcpy(tb_white_list_buf_, value, buf_len); + tb_white_list_buf_[buf_len - 1] = '\0'; + _LOG_INFO("load tb_white_list config succ, %s=%s", name, value); + } + } else if (strlen(value) > OB_MAX_CONFIG_VALUE_LEN && 0 == strcmp("tb_black_list", name)) { + const int64_t buf_len = strlen(value) + 1; + if (OB_ISNULL(tb_black_list_buf_ = static_cast(ob_malloc(buf_len, "black_list_buf")))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_ERROR("alloc memory failed", KR(ret), K(buf_len)); + } else { + memcpy(tb_black_list_buf_, value, buf_len); + tb_black_list_buf_[buf_len - 1] = '\0'; + _LOG_INFO("load tb_black_list config succ, %s=%s", name, value); + } + } else if (NULL == (pp_item = container_.get(ObConfigStringKey(iter->first.c_str())))) { if (check_name) { _LOG_WARN("invalid config string, unknown config item! name: [%s] value: [%s]", iter->first.c_str(), iter->second.c_str()); @@ -186,5 +217,226 @@ int ObLogConfig::load_from_map(const ConfigMap &configs, return ret; } +int ObLogConfig::load_from_file(const char *config_file, + const int64_t version, + const bool check_name) +{ + int ret = OB_SUCCESS; + FILE *fp = NULL; + char *config_file_buf = NULL; + int64_t config_buf_len = 0; + struct stat st; + if (OB_UNLIKELY(! inited_)) { + ret = OB_NOT_INIT; + LOG_ERROR("ObLogConfig has not been initialized"); + } else if (OB_ISNULL(config_file)) { + ret = OB_INVALID_ARGUMENT; + LOG_ERROR("invalid argument", KR(ret), K(config_file)); + } else if (0 != stat(config_file, &st)) { + LOG_ERROR("config_file is invalid", K(config_file), K(errno)); + } else if (FALSE_IT(config_buf_len = st.st_size + 1)) { + } else if (OB_ISNULL(config_file_buf = static_cast(ob_malloc(config_buf_len, "ConfigBuf")))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_ERROR("allocate memory for buffer fail", KR(ret), K(config_file_buf), K(config_buf_len)); + } else if (NULL == (fp = fopen(config_file, "rb"))) { + ret = OB_IO_ERROR; + LOG_ERROR("can't open file", KR(ret), K(config_file), KERRNOMSG(errno)); + } else { + config_file_buf[0] = '\0'; + int64_t buffer_size = config_buf_len; + int64_t read_len = fread(config_file_buf, 1, buffer_size, fp); + + if (0 != ferror(fp)) { + ret = OB_IO_ERROR; + LOG_ERROR("read config file error!", KR(ret), K(config_file), KERRNOMSG(errno)); + } else if (0 == feof(fp)) { + ret = OB_BUF_NOT_ENOUGH; + LOG_ERROR("config file is too long!", KR(ret), K(config_file), K(buffer_size)); + } else if (read_len <= 0) { + LOG_WARN("config file is empty", KR(ret), K(config_file)); + } else if (read_len >= buffer_size) { + LOG_ERROR("fread buffer overflow", KR(ret), K(read_len), K(buffer_size)); + ret = OB_SIZE_OVERFLOW; + } else { + // end with '\0' + config_file_buf[read_len] = '\0'; + + if (OB_FAIL(load_from_buffer_(config_file_buf, read_len, version, check_name))) { + LOG_ERROR("load config fail", KR(ret), K(config_file), K(read_len)); + } else { + LOG_INFO("load config from file succ", K(config_file)); + } + } + } + + if (NULL != fp) { + fclose(fp); + fp = NULL; + } + + if (OB_LIKELY(NULL != config_file_buf)) { + ob_free(config_file_buf); + config_file_buf = NULL; + } + + return ret; +} + +int ObLogConfig::dump2file(const char *file) const { + int ret = OB_SUCCESS; + char tmp_file[MAX_PATH_SIZE] = ""; + if (OB_ISNULL(file)) { + LOG_ERROR("invalid argument", K(file)); + ret = OB_INVALID_ARGUMENT; + } else { + snprintf(tmp_file, MAX_PATH_SIZE, "%s.tmp", file); + FILE *fp = NULL; + ConfigItemArray configs; + get_sorted_config_items(configs); + if (NULL == (fp = fopen(tmp_file, "w+"))) { + ret = OB_IO_ERROR; + LOG_ERROR("open file fail", K(file), KERRMSG); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < configs.count(); ++i) { + const ConfigItem &item = configs.at(i); + if (0 == strcmp(item.key_.c_str(), "tb_white_list") && OB_NOT_NULL(tb_white_list_buf_)) { + continue; + } else if (0 == strcmp(item.key_.c_str(), "tb_black_list") && OB_NOT_NULL(tb_black_list_buf_)) { + continue; + } else { + int write_len = fprintf(fp, "%s=%s\n", item.key_.c_str(), item.val_.c_str()); + if (write_len <= 0) { + ret = OB_IO_ERROR; + LOG_WARN("write config file fail", + K(write_len), "config: name", item.key_.c_str(), "value", item.val_.c_str()); + } + } + } + + if (OB_NOT_NULL(tb_white_list_buf_)) { + int tb_white_list_len = fprintf(fp, "tb_white_list=%s\n", tb_white_list_buf_); + if (tb_white_list_len <= 0) { + ret = OB_IO_ERROR; + LOG_WARN("write table white and black config file fail", + K(tb_white_list_len), "config: name", "tb_white_list", "value", tb_white_list_buf_); + } + } + + if (OB_NOT_NULL(tb_black_list_buf_)) { + int tb_black_list_len = fprintf(fp, "tb_black_list=%s\n", tb_black_list_buf_); + if (tb_black_list_len <= 0) { + ret = OB_IO_ERROR; + LOG_WARN("write table white and black config file fail", + K(tb_black_list_len), "config: name", "tb_black_list", "value", tb_black_list_buf_); + } + } + } + if (NULL != fp) { + fclose(fp); + fp = NULL; + } + } + if (OB_SUCC(ret)) { + // copy tmp_file to file by user when arbserver exit + if (0 != ::rename(tmp_file, file)) { + ret = OB_ERR_SYS; + LOG_WARN("fail to move tmp config file", KERRMSG, K(ret)); + } + } + return ret; +} + +int ObLogConfig::load_from_buffer_(char *config_str, + const int64_t config_str_len, + const int64_t version, + const bool check_name) +{ + int ret = OB_SUCCESS; + char *saveptr = NULL; + char *token = NULL; + int64_t pos = 0; + + if (OB_UNLIKELY(!inited_)) { + LOG_ERROR("Config has not been initialized"); + ret = OB_NOT_INIT; + } else if (NULL == config_str || config_str_len <= 0) { + LOG_ERROR("invalid argument", K(config_str), K(config_str_len)); + ret = OB_INVALID_ARGUMENT; + } else { + token = strtok_r(config_str, ",\n", &saveptr); + while (NULL != token && OB_SUCCESS == ret) { + char *saveptr_one = NULL; + const char *name = NULL; + const char *value = NULL; + ObConfigItem *const *pp_item = NULL; + if (NULL == (name = strtok_r(token, "=", &saveptr_one))) { + LOG_ERROR("fail to parse config string, can not find '=' from token", + K(token), K(config_str)); + ret = OB_INVALID_CONFIG; + } else if ('\0' == *(value = saveptr_one)) { + _LOG_WARN("empty config string: [%s]", token); + name = ""; + } else if (strlen(value) > OB_MAX_CONFIG_VALUE_LEN && 0 == strcmp("tb_white_list", name)) { + if (nullptr != tb_white_list_buf_ && 0 == strcmp(value, tb_white_list_buf_)) { + _LOG_INFO("load config succ, %s=%s", name, value); + } else { + char *tmp_tb_white_list_buf = tb_white_list_buf_; + const int64_t buf_len = strlen(value) + 1; + if (OB_ISNULL(tb_white_list_buf_ = static_cast(ob_malloc(buf_len, "white_list_buf")))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_ERROR("alloc memory failed", KR(ret), K(buf_len)); + } else { + memcpy(tb_white_list_buf_, value, buf_len); + tb_white_list_buf_[buf_len - 1] = '\0'; + if (nullptr != tmp_tb_white_list_buf) { + ob_free(tmp_tb_white_list_buf); + tmp_tb_white_list_buf = nullptr; + } + _LOG_INFO("load config succ, %s=%s", name, value); + } + } + } else if (strlen(value) > OB_MAX_CONFIG_VALUE_LEN && 0 == strcmp("tb_black_list", name)) { + if (nullptr != tb_black_list_buf_ && 0 == strcmp(value, tb_black_list_buf_)) { + _LOG_INFO("load config succ, %s=%s", name, value); + } else { + char *tmp_tb_black_list_buf = tb_black_list_buf_; + const int64_t buf_len = strlen(value) + 1; + if (OB_ISNULL(tb_black_list_buf_ = static_cast(ob_malloc(buf_len, "black_list_buf")))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_ERROR("alloc memory failed", KR(ret), K(buf_len)); + } else { + memcpy(tb_black_list_buf_, value, buf_len); + tb_black_list_buf_[buf_len - 1] = '\0'; + if (nullptr != tmp_tb_black_list_buf) { + ob_free(tmp_tb_black_list_buf); + tmp_tb_black_list_buf = nullptr; + } + _LOG_INFO("load config succ, %s=%s", name, value); + } + } + } else { + ObConfigItem *const *pp_item = NULL; + if (NULL == (pp_item = container_.get(ObConfigStringKey(name)))) { + if (check_name) { + _LOG_WARN("invalid config string, unknown config item! name: [%s] value: [%s]", + name, value); + ret = OB_INVALID_ARGUMENT; + } + } else { + (*pp_item)->set_value(value); + (*pp_item)->set_version(version); + _LOG_INFO("load config succ, %s=%s", name, value); + } + } + + if (OB_SUCCESS == ret) { + token = strtok_r(NULL, ",\n", &saveptr); + } + } + } + + return ret; +} + } // namespace libobcdc } // namespace oceanbase diff --git a/src/logservice/libobcdc/src/ob_log_config.h b/src/logservice/libobcdc/src/ob_log_config.h index 877845e5f6..4afe2a358b 100644 --- a/src/logservice/libobcdc/src/ob_log_config.h +++ b/src/logservice/libobcdc/src/ob_log_config.h @@ -63,7 +63,7 @@ class ObLogConfig : public common::ObBaseConfig typedef std::map ConfigMap; public: - ObLogConfig() : inited_(false), common_config_() + ObLogConfig() : inited_(false), common_config_(), tb_white_list_buf_(nullptr), tb_black_list_buf_(nullptr) { } @@ -76,15 +76,27 @@ public: public: virtual bool need_print_config(const std::string& config_key) const override; void print() const; + + int load_from_file(const char *config_file, + const int64_t version = 0, + const bool check_name = false); + int load_from_map(const ConfigMap& configs, const int64_t version = 0, const bool check_name = false); + int dump2file(const char *file) const; common::ObCommonConfig &get_common_config() { return common_config_; } // remove quotes of cluster_url int format_cluster_url(); +private: + int load_from_buffer_(char *config_str, + const int64_t config_str_len, + const int64_t version, + const bool check_name); + public: #ifdef OB_CLUSTER_PARAMETER @@ -544,6 +556,9 @@ public: // 2. Backup is on by default T_DEF_BOOL(enable_output_invisible_column, OB_CLUSTER_PARAMETER, 0, "0:disabled, 1:enabled"); + // Whether to open white black list + T_DEF_BOOL(enable_white_black_list, OB_CLUSTER_PARAMETER, 1, "0:disabled, 1:enabled"); + // The point in time when the sql server used for querying in SYSTABLE HELPER changes, i.e., the periodic rotation of the sql server T_DEF_INT_INFT(sql_server_change_interval_sec, OB_CLUSTER_PARAMETER, 60, 1, "change interval of sql server in seconds"); @@ -594,9 +609,22 @@ public: #undef OB_CLUSTER_PARAMETER +public: + const char *get_tb_white_list_buf() + { + return tb_white_list_buf_; + } + + const char *get_tb_black_list_buf() + { + return tb_black_list_buf_; + } + private: bool inited_; ObLogFakeCommonConfig common_config_; + char *tb_white_list_buf_; + char *tb_black_list_buf_; private: DISALLOW_COPY_AND_ASSIGN(ObLogConfig); diff --git a/src/logservice/libobcdc/src/ob_log_ddl_processor.cpp b/src/logservice/libobcdc/src/ob_log_ddl_processor.cpp index 8e99b0e67d..9bb9dfa3c0 100644 --- a/src/logservice/libobcdc/src/ob_log_ddl_processor.cpp +++ b/src/logservice/libobcdc/src/ob_log_ddl_processor.cpp @@ -88,6 +88,7 @@ void ObLogDDLProcessor::destroy() int ObLogDDLProcessor::handle_ddl_trans( PartTransTask &task, ObLogTenant &tenant, + const bool need_update_tic, volatile bool &stop_flag) { int ret = OB_SUCCESS; @@ -97,7 +98,7 @@ int ObLogDDLProcessor::handle_ddl_trans( LOG_ERROR("invalid ddl task which is not DDL trans", KR(ret), K(task)); } // Iterate through all DDL statements - else if (OB_FAIL(handle_tenant_ddl_task_(task, tenant, stop_flag))) { + else if (OB_FAIL(handle_tenant_ddl_task_(task, tenant, need_update_tic, stop_flag))) { if (OB_IN_STOP_STATE != ret) { LOG_ERROR("handle_tenant_ddl_task_ fail", KR(ret), K(task), K(tenant)); } @@ -287,10 +288,10 @@ int ObLogDDLProcessor::filter_ddl_stmt_(ObLogTenant &tenant, return ret; } - int ObLogDDLProcessor::handle_tenant_ddl_task_( PartTransTask &task, ObLogTenant &tenant, + const bool need_update_tic, volatile bool &stop_flag) { int ret = OB_SUCCESS; @@ -354,7 +355,14 @@ int ObLogDDLProcessor::handle_tenant_ddl_task_( mark_stmt_binlog_record_invalid_(*ddl_stmt); } else { // statements are not filtered, processing DDL statements - if (OB_FAIL(handle_ddl_stmt_(tenant, task, *ddl_stmt, old_schema_version, new_schema_version, stop_flag))) { + if (need_update_tic && OB_FAIL(handle_ddl_stmt_update_tic_(tenant, task, *ddl_stmt, old_schema_version, + new_schema_version, stop_flag))) { + if (OB_IN_STOP_STATE != ret) { + LOG_ERROR("handle_ddl_stmt_update_tic_ fail", KR(ret), K(tenant), K(task), K(ddl_stmt), + K(old_schema_version), K(new_schema_version)); + } + } else if (!need_update_tic && OB_FAIL(handle_ddl_stmt_(tenant, task, *ddl_stmt, old_schema_version, + new_schema_version, stop_flag))) { if (OB_IN_STOP_STATE != ret) { LOG_ERROR("handle_ddl_stmt_ fail", KR(ret), K(tenant), K(task), K(ddl_stmt), K(old_schema_version), K(new_schema_version)); @@ -408,21 +416,27 @@ int ObLogDDLProcessor::handle_ddl_stmt_( checkpoint_seq, task.get_trans_id().get_id()); + const bool need_update_tic = false; + switch (op_type) { case OB_DDL_DROP_TABLE : { - ret = handle_ddl_stmt_drop_table_(tenant, ddl_stmt, old_schema_version, new_schema_version, stop_flag); + ret = handle_ddl_stmt_drop_table_(tenant, ddl_stmt, old_schema_version, new_schema_version, + need_update_tic, stop_flag); break; } case OB_DDL_ALTER_TABLE : { - ret = handle_ddl_stmt_alter_table_(tenant, ddl_stmt, old_schema_version, new_schema_version, "alter_table", stop_flag); + ret = handle_ddl_stmt_alter_table_(tenant, ddl_stmt, old_schema_version, new_schema_version, + need_update_tic, stop_flag); break; } case OB_DDL_CREATE_TABLE : { - ret = handle_ddl_stmt_create_table_(tenant, ddl_stmt, new_schema_version, stop_flag); + ret = handle_ddl_stmt_create_table_(tenant, ddl_stmt, new_schema_version, need_update_tic, + stop_flag); break; } case OB_DDL_TABLE_RENAME : { - ret = handle_ddl_stmt_rename_table_(tenant, ddl_stmt, old_schema_version, new_schema_version, stop_flag); + ret = handle_ddl_stmt_rename_table_(tenant, ddl_stmt, old_schema_version, new_schema_version, + need_update_tic, stop_flag); break; } case OB_DDL_TRUNCATE_TABLE_DROP : { @@ -488,7 +502,8 @@ int ObLogDDLProcessor::handle_ddl_stmt_( break; } case OB_DDL_DEL_DATABASE : { - ret = handle_ddl_stmt_drop_database_(tenant, ddl_stmt, old_schema_version, new_schema_version, stop_flag); + ret = handle_ddl_stmt_drop_database_(tenant, ddl_stmt, old_schema_version, new_schema_version, + need_update_tic, stop_flag); break; } case OB_DDL_RENAME_DATABASE : { @@ -544,6 +559,77 @@ int ObLogDDLProcessor::handle_ddl_stmt_( return ret; } +int ObLogDDLProcessor::handle_ddl_stmt_update_tic_( + ObLogTenant &tenant, + PartTransTask &task, + DdlStmtTask &ddl_stmt, + const int64_t old_schema_version, + const int64_t new_schema_version, + volatile bool &stop_flag) +{ + int ret = OB_SUCCESS; + ObSchemaOperationType op_type = (ObSchemaOperationType)ddl_stmt.get_operation_type(); + const int64_t checkpoint_seq = ddl_stmt.get_host().get_checkpoint_seq(); + + _ISTAT("[DDL] [HANDLE_STMT_UPDATE_TIC] TENANT_ID=%lu OP_TYPE=%s(%d) OP_TABLE_ID=%ld SCHEMA_VERSION=%ld " + "SCHEMA_DELAY=%.3lf(sec) CUR_SCHEMA_VERSION=%ld EXEC_TENANT_ID=%ld OP_TENANT_ID=%ld " + "OP_TABLE_ID=%ld OP_DB_ID=%ld OP_TG_ID=%ld DDL_STMT=[%s] CHECKPOINT_SEQ=%ld TRANS_ID=%ld", + tenant.get_tenant_id(), ObSchemaOperation::type_str(op_type), op_type, + ddl_stmt.get_op_table_id(), + ddl_stmt.get_op_schema_version(), + get_delay_sec(ddl_stmt.get_op_schema_version()), + tenant.get_schema_version(), + ddl_stmt.get_exec_tenant_id(), + ddl_stmt.get_op_tenant_id(), + ddl_stmt.get_op_table_id(), + ddl_stmt.get_op_database_id(), + ddl_stmt.get_op_tablegroup_id(), + to_cstring(ddl_stmt.get_ddl_stmt_str()), + checkpoint_seq, + task.get_trans_id().get_id()); + + const bool need_update_tic = true; + + switch (op_type) { + case OB_DDL_DROP_TABLE : { + ret = handle_ddl_stmt_drop_table_(tenant, ddl_stmt, old_schema_version, new_schema_version, + need_update_tic, stop_flag); + break; + } + case OB_DDL_ALTER_TABLE : { + ret = handle_ddl_stmt_alter_table_(tenant, ddl_stmt, old_schema_version, new_schema_version, + need_update_tic, stop_flag); + break; + } + case OB_DDL_CREATE_TABLE : { + ret = handle_ddl_stmt_create_table_(tenant, ddl_stmt, new_schema_version, + need_update_tic, stop_flag); + break; + } + case OB_DDL_TABLE_RENAME : { + ret = handle_ddl_stmt_rename_table_(tenant, ddl_stmt, old_schema_version, new_schema_version, + need_update_tic, stop_flag); + break; + } + case OB_DDL_DEL_DATABASE : { + ret = handle_ddl_stmt_drop_database_(tenant, ddl_stmt, old_schema_version, new_schema_version, + need_update_tic, stop_flag); + break; + } + default: { + break; + } + } + + if (OB_FAIL(ret)) { + if (OB_IN_STOP_STATE != ret) { + LOG_ERROR("handle ddl statement for tic update fail", KR(ret), K(op_type), K(ddl_stmt)); + } + } + + return ret; +} + int ObLogDDLProcessor::handle_ddl_stmt_direct_output_( ObLogTenant &tenant, DdlStmtTask &ddl_stmt, @@ -1010,44 +1096,29 @@ int ObLogDDLProcessor::handle_ddl_stmt_drop_table_(ObLogTenant &tenant, DdlStmtTask &ddl_stmt, const int64_t old_schema_version, const int64_t new_schema_version, + const bool need_update_tic, volatile bool &stop_flag) { int ret = OB_SUCCESS; - ObLogSchemaGuard old_schema_guard; const char *tenant_name = NULL; const char *db_name = NULL; bool is_table_should_ignore_in_committer = false; - /* - * TODO Support - RETRY_FUNC(stop_flag, tenant.get_part_mgr(), drop_table, - ddl_stmt.get_op_table_id(), - old_schema_version, - new_schema_version, - is_table_should_ignore_in_committer, - old_schema_guard, - tenant_name, - db_name, - DATA_OP_TIMEOUT); - */ - - // If the schema error is encountered, it means that the tenant may be deleted in the future, so the schema of table, - // database, tenant or table group cannot be obtained, in this case, the DDL will be ignored. - IGNORE_SCHEMA_ERROR(ret, "schema_version", old_schema_version, K(ddl_stmt), K(is_table_should_ignore_in_committer)); - - if (OB_SUCC(ret)) { - // Delete table using old_schema_version parsing - if (OB_FAIL(commit_ddl_stmt_(tenant, ddl_stmt, old_schema_version, stop_flag, tenant_name, db_name, false, - is_table_should_ignore_in_committer))) { - if (OB_IN_STOP_STATE != ret) { - LOG_ERROR("commit_ddl_stmt_ fail", KR(ret), K(ddl_stmt), K(tenant), K(old_schema_version), - K(tenant_name), K(db_name), K(is_table_should_ignore_in_committer)); - } - } else { - // succ + if (need_update_tic) { + RETRY_FUNC(stop_flag, tenant.get_part_mgr(), drop_table, + ddl_stmt.get_op_table_id(), + ddl_stmt, + old_schema_version, + DATA_OP_TIMEOUT); + } else if (OB_FAIL(commit_ddl_stmt_(tenant, ddl_stmt, old_schema_version, stop_flag, tenant_name, + db_name, false, is_table_should_ignore_in_committer))) { + if (OB_IN_STOP_STATE != ret) { + LOG_ERROR("commit_ddl_stmt_ fail", KR(ret), K(ddl_stmt), K(tenant), K(old_schema_version), + K(tenant_name), K(db_name), K(is_table_should_ignore_in_committer)); } + } else { + // succ } - return ret; } @@ -1073,47 +1144,26 @@ int ObLogDDLProcessor::handle_ddl_stmt_alter_table_( DdlStmtTask &ddl_stmt, const int64_t old_schema_version, const int64_t new_schema_version, - const char *event, + const bool need_update_tic, volatile bool &stop_flag) { int ret = OB_SUCCESS; - ObLogSchemaGuard old_schema_guard; - ObLogSchemaGuard new_schema_guard; const char *old_tenant_name = NULL; const char *old_db_name = NULL; - - // TODO:Support table renaming, refiltering based on filtering rules - int64_t trans_commit_version = ddl_stmt.get_host().get_trans_commit_version(); - int64_t start_serve_timestamp = get_start_serve_timestamp_(new_schema_version, - trans_commit_version); - - // Atopt new_schema_version - // RETRY_FUNC(stop_flag, tenant.get_part_mgr(), alter_table, - // ddl_stmt.get_op_table_id(), - // old_schema_version, - // new_schema_version, - // start_serve_timestamp, - // old_schema_guard, - // new_schema_guard, - // old_tenant_name, - // old_db_name, - // event, - // DATA_OP_TIMEOUT); - - // If the schema error is encountered, it means that the tenant may be deleted in the future, so the schema of table, - // database, tenant or table group cannot be obtained, in this case, the DDL will be ignored. - IGNORE_SCHEMA_ERROR(ret, "schema_version", new_schema_version, K(ddl_stmt)); - - if (OB_SUCC(ret)) { - // Set tenant, database and table name with old schema - if (OB_FAIL(commit_ddl_stmt_(tenant, ddl_stmt, old_schema_version, stop_flag, old_tenant_name, old_db_name))) { - if (OB_IN_STOP_STATE != ret) { - LOG_ERROR("commit_ddl_stmt_ fail", KR(ret), K(tenant), K(ddl_stmt), K(old_schema_version), - K(old_tenant_name), K(old_db_name)); - } + if (need_update_tic) { + RETRY_FUNC(stop_flag, tenant.get_part_mgr(), alter_table, + ddl_stmt.get_op_table_id(), + ddl_stmt, + new_schema_version, + DATA_OP_TIMEOUT); + } else if (OB_FAIL(commit_ddl_stmt_(tenant, ddl_stmt, old_schema_version, stop_flag, old_tenant_name, old_db_name))) { + if (OB_IN_STOP_STATE != ret) { + LOG_ERROR("commit_ddl_stmt_ fail", KR(ret), K(tenant), K(ddl_stmt), K(old_schema_version), + K(old_tenant_name), K(old_db_name)); } + } else { + // succ } - return ret; } @@ -1121,44 +1171,28 @@ int ObLogDDLProcessor::handle_ddl_stmt_create_table_( ObLogTenant &tenant, DdlStmtTask &ddl_stmt, const int64_t new_schema_version, + const bool need_update_tic, volatile bool &stop_flag) { int ret = OB_SUCCESS; - bool is_create_table = true; bool is_table_should_ignore_in_committer = false; - int64_t trans_commit_version = ddl_stmt.get_host().get_trans_commit_version(); - int64_t start_serve_tstamp = get_start_serve_timestamp_(new_schema_version, - trans_commit_version); - ObLogSchemaGuard schema_guard; const char *tenant_name = NULL; const char *db_name = NULL; - // TODO support - /* - RETRY_FUNC(stop_flag, tenant.get_part_mgr(), add_table, - ddl_stmt.get_op_table_id(), - new_schema_version, - start_serve_tstamp, - is_create_table, - is_table_should_ignore_in_committer, - schema_guard, - tenant_name, - db_name, - DATA_OP_TIMEOUT); - */ - - // If the schema error is encountered, it means that the tenant may be deleted in the future, so the schema of table, - // database, tenant or table group cannot be obtained, in this case, the DDL will be ignored. - IGNORE_SCHEMA_ERROR(ret, "schema_version", new_schema_version, K(ddl_stmt), K(is_table_should_ignore_in_committer)); - - if (OB_SUCC(ret)) { - if (OB_FAIL(commit_ddl_stmt_(tenant, ddl_stmt, new_schema_version, stop_flag, tenant_name, db_name, true, - is_table_should_ignore_in_committer))) { - if (OB_IN_STOP_STATE != ret) { - LOG_ERROR("commit_ddl_stmt_ fail", KR(ret), K(tenant), K(ddl_stmt), K(tenant_name), - K(db_name), K(is_table_should_ignore_in_committer)); - } - } else {} + if (need_update_tic) { + RETRY_FUNC(stop_flag, tenant.get_part_mgr(), add_table, + ddl_stmt.get_op_table_id(), + ddl_stmt, + new_schema_version, + DATA_OP_TIMEOUT); + } else if (OB_FAIL(commit_ddl_stmt_(tenant, ddl_stmt, new_schema_version, stop_flag, tenant_name, + db_name, true, is_table_should_ignore_in_committer))) { + if (OB_IN_STOP_STATE != ret) { + LOG_ERROR("commit_ddl_stmt_ fail", KR(ret), K(tenant), K(ddl_stmt), K(tenant_name), + K(db_name), K(is_table_should_ignore_in_committer)); + } + } else { + // succ } return ret; @@ -1169,15 +1203,19 @@ int ObLogDDLProcessor::handle_ddl_stmt_rename_table_( DdlStmtTask &ddl_stmt, const int64_t old_schema_version, const int64_t new_schema_version, + const bool need_update_tic, volatile bool &stop_flag) { int ret = OB_SUCCESS; - // TODO:support table rename - UNUSED(new_schema_version); - - // Parsing with older schema versions - ret = handle_ddl_stmt_direct_output_(tenant, ddl_stmt, old_schema_version, stop_flag); - + if (need_update_tic) { + RETRY_FUNC(stop_flag, tenant.get_part_mgr(), rename_table, + ddl_stmt.get_op_table_id(), + ddl_stmt, + new_schema_version, + DATA_OP_TIMEOUT); + } else { + ret = handle_ddl_stmt_direct_output_(tenant, ddl_stmt, old_schema_version, stop_flag); + } return ret; } @@ -1647,14 +1685,19 @@ int ObLogDDLProcessor::handle_ddl_stmt_drop_database_( DdlStmtTask &ddl_stmt, const int64_t old_schema_version, const int64_t new_schema_version, + const bool need_update_tic, volatile bool &stop_flag) { int ret = OB_SUCCESS; - // don't need to handle drop database - UNUSED(new_schema_version); - - ret = handle_ddl_stmt_direct_output_(tenant, ddl_stmt, old_schema_version, stop_flag); - + if (need_update_tic) { + RETRY_FUNC(stop_flag, tenant.get_part_mgr(), drop_database, + ddl_stmt.get_op_database_id(), + old_schema_version, + ddl_stmt, + DATA_OP_TIMEOUT); + } else { + ret = handle_ddl_stmt_direct_output_(tenant, ddl_stmt, old_schema_version, stop_flag); + } return ret; } diff --git a/src/logservice/libobcdc/src/ob_log_ddl_processor.h b/src/logservice/libobcdc/src/ob_log_ddl_processor.h index 0093a358b3..dfa5a6c399 100644 --- a/src/logservice/libobcdc/src/ob_log_ddl_processor.h +++ b/src/logservice/libobcdc/src/ob_log_ddl_processor.h @@ -58,8 +58,8 @@ public: int handle_ddl_trans( PartTransTask &task, ObLogTenant &tenant, + const bool need_update_tic, volatile bool &stop_flag); - private: void mark_stmt_binlog_record_invalid_(DdlStmtTask &stmt_task); void mark_all_binlog_records_invalid_(PartTransTask &task); @@ -85,6 +85,7 @@ private: int handle_tenant_ddl_task_( PartTransTask &task, ObLogTenant &tenant, + const bool need_update_tic, volatile bool &stop_flag); int handle_ddl_stmt_( ObLogTenant &tenant, @@ -93,6 +94,13 @@ private: const int64_t old_schema_version, const int64_t new_schema_version, volatile bool &stop_flag); + int handle_ddl_stmt_update_tic_( + ObLogTenant &tenant, + PartTransTask &task, + DdlStmtTask &ddl_stmt, + const int64_t old_schema_version, + const int64_t new_schema_version, + volatile bool &stop_flag); int handle_ddl_stmt_direct_output_( ObLogTenant &tenant, DdlStmtTask &ddl_stmt, @@ -162,6 +170,7 @@ private: DdlStmtTask &ddl_stmt, const int64_t old_schema, const int64_t new_schema, + const bool need_update_tic, volatile bool &stop_flag); int handle_ddl_stmt_drop_table_to_recyclebin_( ObLogTenant &tenant, @@ -179,18 +188,20 @@ private: DdlStmtTask &ddl_stmt, const int64_t old_schema, const int64_t new_schema, - const char *event, + const bool need_update_tic, volatile bool &stop_flag); int handle_ddl_stmt_create_table_( ObLogTenant &tenant, DdlStmtTask &ddl_stmt, const int64_t new_schema, + const bool need_update_tic, volatile bool &stop_flag); int handle_ddl_stmt_rename_table_( ObLogTenant &tenant, DdlStmtTask &ddl_stmt, const int64_t old_schema, const int64_t new_schema, + const bool need_update_tic, volatile bool &stop_flag); /*************** Index related DDL ***************/ @@ -281,6 +292,7 @@ private: DdlStmtTask &ddl_stmt, const int64_t old_schema, const int64_t new_schema, + const bool need_update_tic, volatile bool &stop_flag); int handle_ddl_stmt_drop_database_to_recyclebin_( ObLogTenant &tenant, diff --git a/src/logservice/libobcdc/src/ob_log_instance.cpp b/src/logservice/libobcdc/src/ob_log_instance.cpp index 2b65b84501..fc6b6ef843 100644 --- a/src/logservice/libobcdc/src/ob_log_instance.cpp +++ b/src/logservice/libobcdc/src/ob_log_instance.cpp @@ -720,8 +720,6 @@ int ObLogInstance::init_components_(const uint64_t start_tstamp_ns) bool enable_output_hidden_primary_key = (TCONF.enable_output_hidden_primary_key != 0); bool enable_oracle_mode_match_case_sensitive = (TCONF.enable_oracle_mode_match_case_sensitive != 0); const char *rs_list = TCONF.rootserver_list.str(); - const char *tb_white_list = TCONF.tb_white_list.str(); - const char *tb_black_list = TCONF.tb_black_list.str(); const char *tg_white_list = TCONF.tablegroup_white_list.str(); const char *tg_black_list = TCONF.tablegroup_black_list.str(); int64_t max_cached_trans_ctx_count = MAX_CACHED_TRANS_CTX_COUNT; @@ -746,6 +744,13 @@ int ObLogInstance::init_components_(const uint64_t start_tstamp_ns) drc_message_factory_binlog_record_type_.assign(drc_message_factory_binlog_record_type_str, strlen(drc_message_factory_binlog_record_type_str)); + const bool enable_white_black_list = (1 == TCONF.enable_white_black_list); + + const char *tb_white_list = TCONF.get_tb_white_list_buf() != NULL ? TCONF.get_tb_white_list_buf() + : TCONF.tb_white_list.str(); + const char *tb_black_list = TCONF.get_tb_black_list_buf() != NULL ? TCONF.get_tb_black_list_buf() + : TCONF.tb_black_list.str(); + if (OB_UNLIKELY(! is_working_mode_valid(working_mode))) { ret = OB_INVALID_CONFIG; LOG_ERROR("working_mode is not valid", KR(ret), K(working_mode_str), "working_mode", print_working_mode(working_mode)); @@ -866,7 +871,8 @@ int ObLogInstance::init_components_(const uint64_t start_tstamp_ns) CDC_CFG_MGR.get_resource_collector_queue_length(), br_pool_, trans_ctx_mgr_, meta_manager_, store_service_, err_handler); - INIT(tenant_mgr_, ObLogTenantMgr, enable_oracle_mode_match_case_sensitive, refresh_mode_); + INIT(tenant_mgr_, ObLogTenantMgr, enable_oracle_mode_match_case_sensitive, + enable_white_black_list, refresh_mode_); if (OB_SUCC(ret)) { if (is_tenant_sync_mode()) { diff --git a/src/logservice/libobcdc/src/ob_log_ls_fetch_stream.cpp b/src/logservice/libobcdc/src/ob_log_ls_fetch_stream.cpp index 6eb8b3097a..6336e84c34 100644 --- a/src/logservice/libobcdc/src/ob_log_ls_fetch_stream.cpp +++ b/src/logservice/libobcdc/src/ob_log_ls_fetch_stream.cpp @@ -1331,6 +1331,10 @@ const char *FetchStream::print_kick_out_reason_(const KickOutReason reason) str = "Discarded"; break; + case ARCHIVE_ITER_END_BUT_LS_NOT_EXIST_IN_PALF: + str = "ARCHIVE_ITER_END_BUT_LS_NOT_EXIST_IN_PALF"; + break; + default: str = "NONE"; break; @@ -1982,19 +1986,19 @@ FetchStream::KickOutReason FetchStream::get_feedback_reason_(const Feedback &fee // Get KickOutReason based on feedback KickOutReason reason = NONE; switch (feedback) { - case ObCdcLSFetchLogResp::LAGGED_FOLLOWER: + case FeedbackType::LAGGED_FOLLOWER: reason = LAGGED_FOLLOWER; break; - case ObCdcLSFetchLogResp::LOG_NOT_IN_THIS_SERVER: + case FeedbackType::LOG_NOT_IN_THIS_SERVER: reason = LOG_NOT_IN_THIS_SERVER; break; - case ObCdcLSFetchLogResp::LS_OFFLINED: + case FeedbackType::LS_OFFLINED: reason = LS_OFFLINED; break; - case ObCdcLSFetchLogResp::ARCHIVE_ITER_END_BUT_LS_NOT_EXIST_IN_PALF: + case FeedbackType::ARCHIVE_ITER_END_BUT_LS_NOT_EXIST_IN_PALF: reason = ARCHIVE_ITER_END_BUT_LS_NOT_EXIST_IN_PALF; break; diff --git a/src/logservice/libobcdc/src/ob_log_ls_fetch_stream.h b/src/logservice/libobcdc/src/ob_log_ls_fetch_stream.h index d8a6500f50..5a81a3ecc6 100644 --- a/src/logservice/libobcdc/src/ob_log_ls_fetch_stream.h +++ b/src/logservice/libobcdc/src/ob_log_ls_fetch_stream.h @@ -51,7 +51,7 @@ private: static const int64_t STAT_INTERVAL = 30 * _SEC_; static const int64_t DEFAULT_TASK_SET_SIZE = 16; - typedef obrpc::ObCdcLSFetchLogResp::FeedbackType Feedback; + typedef obrpc::FeedbackType Feedback; // Class global variables public: diff --git a/src/logservice/libobcdc/src/ob_log_part_mgr.cpp b/src/logservice/libobcdc/src/ob_log_part_mgr.cpp index 9412d0862d..6ecdda44ef 100644 --- a/src/logservice/libobcdc/src/ob_log_part_mgr.cpp +++ b/src/logservice/libobcdc/src/ob_log_part_mgr.cpp @@ -27,6 +27,7 @@ #include "ob_log_instance.h" // TCTX #include "ob_log_table_matcher.h" // IObLogTableMatcher #include "ob_log_tenant.h" // ObLogTenant +#include "ob_log_tic_update_info.h" // TICUpdateInfo #define _STAT(level, fmt, args...) _OBLOG_LOG(level, "[STAT] [PartMgr] " fmt, ##args) #define STAT(level, fmt, args...) OBLOG_LOG(level, "[STAT] [PartMgr] " fmt, ##args) @@ -66,7 +67,7 @@ using namespace share::schema; namespace libobcdc { -ObLogPartMgr::ObLogPartMgr(ObLogTenant &tenant) : host_(tenant) +ObLogPartMgr::ObLogPartMgr(ObLogTenant &tenant) : host_(tenant), table_id_cache_() { reset(); } @@ -79,8 +80,8 @@ ObLogPartMgr::~ObLogPartMgr() int ObLogPartMgr::init(const uint64_t tenant_id, const int64_t start_schema_version, const bool enable_oracle_mode_match_case_sensitive, - GIndexCache &gi_cache, - TableIDCache &table_id_cache) + const bool enable_white_black_list, + GIndexCache &gi_cache) { int ret = OB_SUCCESS; @@ -92,16 +93,23 @@ int ObLogPartMgr::init(const uint64_t tenant_id, LOG_ERROR("schema_cond_ init fail", KR(ret)); } else if (OB_FAIL(tablet_to_table_info_.init(tenant_id))) { LOG_ERROR("init tablet_to_table_info fail", KR(ret), K(tenant_id)); + } else if (OB_FAIL(table_id_cache_.init(ObModIds::OB_LOG_TABLE_ID_CACHE))) { + LOG_ERROR("table id cache init fail", KR(ret)); } else { tenant_id_ = tenant_id; global_normal_index_table_cache_ = &gi_cache; - table_id_cache_ = &table_id_cache; cur_schema_version_ = start_schema_version; enable_oracle_mode_match_case_sensitive_ = enable_oracle_mode_match_case_sensitive; enable_check_schema_version_ = false; + enable_white_black_list_ = enable_white_black_list; + if (host_.get_compat_mode() == lib::Worker::CompatMode::ORACLE + && enable_oracle_mode_match_case_sensitive_) { + fnmatch_flags_ = FNM_NOESCAPE; + } inited_ = true; - LOG_INFO("init PartMgr succ", K(tenant_id), K(start_schema_version)); + LOG_INFO("init PartMgr succ", K(tenant_id), K(start_schema_version), K_(fnmatch_flags), + K_(enable_white_black_list)); } return ret; @@ -112,27 +120,28 @@ void ObLogPartMgr::reset() inited_ = false; tenant_id_ = OB_INVALID_ID; global_normal_index_table_cache_ = NULL; - table_id_cache_ = NULL; tablet_to_table_info_.destroy(); + table_id_cache_.destroy(); cur_schema_version_ = OB_INVALID_VERSION; enable_oracle_mode_match_case_sensitive_ = false; enable_check_schema_version_ = false; + enable_white_black_list_ = true; + fnmatch_flags_ = FNM_CASEFOLD; schema_cond_.destroy(); } -int ObLogPartMgr::add_all_user_tablets_info(const int64_t timeout) +int ObLogPartMgr::add_all_user_tablets_and_tables_info(const int64_t timeout) { int ret = OB_SUCCESS; + int64_t start_ts = ObTimeUtility::current_time(); IObLogSchemaGetter *schema_getter = TCTX.schema_getter_; ObLogSchemaGuard schema_guard; ObArray table_schemas; - if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id_) || OB_UNLIKELY(0 >= cur_schema_version_) || OB_ISNULL(schema_getter)) { ret = OB_INVALID_ARGUMENT; LOG_ERROR("invalid arguments", KR(ret), K_(tenant_id), K_(cur_schema_version)); - } else if (OB_FAIL(schema_getter->get_fallback_schema_guard( tenant_id_, cur_schema_version_, timeout, schema_guard))) { if (OB_TIMEOUT != ret) { @@ -146,11 +155,9 @@ int ObLogPartMgr::add_all_user_tablets_info(const int64_t timeout) for (int i = 0; OB_SUCC(ret) && i < table_schemas.count(); i++) { const ObSimpleTableSchemaV2 *table_schema = table_schemas.at(i); ObArray tablet_ids; - if (OB_ISNULL(table_schema)) { ret = OB_ERR_UNEXPECTED; - LOG_ERROR("get invalid table_schema via schema_service for init tablet_to_table_info", - KR(ret), K_(tenant_id), K_(cur_schema_version)); + LOG_ERROR("get invalid table_schema", KR(ret), K_(tenant_id), K_(cur_schema_version)); } else if (table_schema->has_tablet()) { if (OB_FAIL(table_schema->get_tablet_ids(tablet_ids))) { LOG_ERROR("get_tablet_ids failed", KR(ret), K_(tenant_id), K_(cur_schema_version)); @@ -161,25 +168,33 @@ int ObLogPartMgr::add_all_user_tablets_info(const int64_t timeout) } } } - } // for + + if (OB_SUCC(ret) && OB_FAIL(add_user_table_info_(schema_guard, table_schema, timeout))) { + LOG_ERROR("add_user_table_info failed", KR(ret), K_(tenant_id), KPC(table_schema)); + } + } + + int64_t execute_ts = ObTimeUtility::current_time() - start_ts; + ISTAT("[ADD_ALL_USER_TABLETS_AND_TABLES_INFO]", KR(ret), K_(tenant_id), + K_(cur_schema_version), K_(tablet_to_table_info), K_(cur_schema_version), + "TableSchemaCount", table_schemas.count(), "AddTableCount", table_id_cache_.count(), + K(execute_ts)); } - - ISTAT("[ADD_ALL_USER_TABLETS_INFO]", KR(ret), K_(tenant_id), - K_(cur_schema_version), K_(tablet_to_table_info)); - return ret; } -int ObLogPartMgr::add_all_user_tablets_info( +int ObLogPartMgr::add_all_user_tablets_and_tables_info( + ObDictTenantInfo *tenant_info, const ObIArray &table_metas, const int64_t timeout) { int ret = OB_SUCCESS; - + int64_t start_ts = ObTimeUtility::current_time(); if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id_)) { ret = OB_INVALID_ARGUMENT; LOG_ERROR("invalid argument", KR(ret), K_(tenant_id)); } else { + // add all user tablets info ARRAY_FOREACH_N(table_metas, idx, count) { const datadict::ObDictTableMeta *table_meta = table_metas.at(idx); @@ -191,15 +206,19 @@ int ObLogPartMgr::add_all_user_tablets_info( if (OB_FAIL(insert_tablet_table_info_(*table_meta, tablet_ids))) { LOG_ERROR("insert_tablet_table_info_ failed", KR(ret), K_(tenant_id), KPC(table_meta)); - } } - } // ARRAY_FOREACH_N + + if (OB_SUCC(ret) && OB_FAIL(add_user_table_info_(tenant_info, table_meta, timeout))) { + LOG_ERROR("add_user_table_info failed", KR(ret), K_(tenant_id), KPC(table_meta)); + } + } + + int64_t execute_ts = ObTimeUtility::current_time() - start_ts; + ISTAT("[ADD_ALL_USER_TABLES_AND_TABLES_INFO]", KR(ret), K_(tenant_id), K_(cur_schema_version), + K_(tablet_to_table_info), "TableSchemaCount", table_metas.count(), + "AddTableCount", table_id_cache_.count(), K(execute_ts)); } - - ISTAT("[ADD_ALL_USER_TABLETS_INFO]", KR(ret), K_(tenant_id), - K_(cur_schema_version), K_(tablet_to_table_info)); - return ret; } @@ -225,6 +244,36 @@ int ObLogPartMgr::insert_tablet_table_info_( return ret; } +int ObLogPartMgr::drop_database(const uint64_t database_id, + const int64_t old_schema_version, + DdlStmtTask &ddl_stmt, + const int64_t timeout) +{ + int ret = OB_SUCCESS; + const char *tenant_name = nullptr; + const char *database_name = nullptr; + bool chosen = false; + if (OB_FAIL(database_match_(database_id, old_schema_version, tenant_name, database_name, + chosen, timeout))) { + LOG_ERROR("database_match_ failed", KR(ret), K(old_schema_version), K(database_id), + K(tenant_name), K(database_name)); + } else if (!chosen) { + ISTAT("database is not chosen", K(old_schema_version), K(database_id), + K(tenant_name), K(database_name)); + } else { + TICUpdateInfo tic_update_info(TICUpdateInfo::TICUpdateReason::DROP_DATABASE, database_id); + PartTransTask &part_trans_task = ddl_stmt.get_host(); + if (OB_FAIL(part_trans_task.push_tic_update_info(tic_update_info))) { + LOG_ERROR("push tic update info failed", KR(ret), K(old_schema_version), K(tic_update_info), + K(tenant_name), K(database_name)); + } else { + ISTAT("set tic update info success", K(old_schema_version), K(database_id), + K(tic_update_info), K(tenant_name), K(database_name)); + } + } + return ret; +} + int ObLogPartMgr::add_table( const uint64_t table_id, const int64_t start_schema_version, @@ -306,6 +355,40 @@ int ObLogPartMgr::add_table( return ret; } +int ObLogPartMgr::add_table(const uint64_t table_id, + DdlStmtTask &ddl_stmt, + const int64_t new_schema_version, + const int64_t timeout) +{ + int ret = OB_SUCCESS; + const char *tenant_name = nullptr; + const char *database_name = nullptr; + const char *table_name = nullptr; + bool is_user_table = false; + bool chosen = false; + uint64_t database_id = OB_INVALID_ID; + if (OB_FAIL(table_match_(table_id, new_schema_version, tenant_name, database_name, table_name, + is_user_table, chosen, database_id, timeout))) { + LOG_ERROR("table_match_ failed", KR(ret), K(new_schema_version), K(table_id)); + } else if (!is_user_table) { + } else if (!chosen) { + ISTAT("table is not chosen", K(new_schema_version), K(table_id), K(tenant_name), + K(database_name), K(table_name)); + } else { + TICUpdateInfo tic_update_info(TICUpdateInfo::TICUpdateReason::CREATE_TABLE, + database_id, table_id); + PartTransTask &part_trans_task = ddl_stmt.get_host(); + if (OB_FAIL(part_trans_task.push_tic_update_info(tic_update_info))) { + LOG_ERROR("push tic update info failed", KR(ret), K(new_schema_version), K(tic_update_info), + K(tenant_name), K(database_name), K(table_name)); + } else { + ISTAT("set tic update info success", K(new_schema_version), K(tic_update_info), + K(tenant_name), K(database_name), K(table_name)); + } + } + return ret; +} + int ObLogPartMgr::try_get_offline_ddl_origin_table_schema_(const ObSimpleTableSchemaV2 &table_schema, ObLogSchemaGuard &schema_guard, const int64_t timeout, @@ -315,18 +398,22 @@ int ObLogPartMgr::try_get_offline_ddl_origin_table_schema_(const ObSimpleTableSc origin_table_schema = NULL; if (OB_UNLIKELY(! inited_)) { - LOG_ERROR("PartMgr has not been initialized"); ret = OB_NOT_INIT; + LOG_ERROR("PartMgr has not been initialized", KR(ret)); } else { // Offline DDL: hidden table const bool is_user_hidden_table = table_schema.is_user_hidden_table(); if (is_user_hidden_table) { - const uint64_t origin_table_id = table_schema.get_association_table_id(); + const ObTableSchema *full_table_schema = NULL; + uint64_t origin_table_id = OB_INVALID_ID; - if (OB_UNLIKELY(OB_INVALID_ID == origin_table_id)) { - LOG_ERROR("origin_table_id is not valid", K(origin_table_id), K(table_schema)); + if (OB_FAIL(get_full_table_schema_(table_schema.get_table_id(), timeout, schema_guard, full_table_schema))) { + LOG_ERROR("get full table_schema failed", "table_id", table_schema.get_table_id()); + } else if (FALSE_IT(origin_table_id = full_table_schema->get_association_table_id())) { + } else if (OB_UNLIKELY(OB_INVALID_ID == origin_table_id)) { ret = OB_ERR_UNEXPECTED; + LOG_ERROR("origin_table_id is not valid", KR(ret), K(origin_table_id), K(table_schema)); } else if (OB_FAIL(get_simple_table_schema_(origin_table_id, timeout, schema_guard, origin_table_schema))) { if (OB_TIMEOUT != ret) { LOG_ERROR("get table schema for offline ddl fail", KR(ret), @@ -338,8 +425,8 @@ int ObLogPartMgr::try_get_offline_ddl_origin_table_schema_(const ObSimpleTableSc "origin_table_state_flag", origin_table_schema->get_table_state_flag()); } } else if (OB_ISNULL(origin_table_schema)) { - LOG_ERROR("invalid schema", K(origin_table_schema)); ret = OB_ERR_UNEXPECTED; + LOG_ERROR("invalid schema", KR(ret), K(origin_table_schema)); } else { LOG_INFO("[OFFLINE_DDL]", K(is_user_hidden_table), "hidden_table_id", table_schema.get_table_id(), @@ -354,6 +441,135 @@ int ObLogPartMgr::try_get_offline_ddl_origin_table_schema_(const ObSimpleTableSc return ret; } +int ObLogPartMgr::try_get_offline_ddl_origin_table_meta_(const datadict::ObDictTableMeta &table_meta, + ObDictTenantInfo *tenant_info, + datadict::ObDictTableMeta *&origin_table_meta) +{ + int ret = OB_SUCCESS; + origin_table_meta = NULL; + + if (OB_UNLIKELY(! inited_)) { + ret = OB_NOT_INIT; + LOG_ERROR("PartMgr has not been initialized", KR(ret)); + } else { + // Offline DDL: hidden table + const bool is_user_hidden_table = table_meta.is_user_hidden_table(); + + if (is_user_hidden_table) { + const uint64_t origin_table_id = table_meta.get_association_table_id(); + + if (OB_UNLIKELY(OB_INVALID_ID == origin_table_id)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("origin_table_id is not valid", KR(ret), K(origin_table_id), K(table_meta)); + } else if (OB_FAIL(tenant_info->get_table_meta(origin_table_id, origin_table_meta))) { + LOG_ERROR("get table meta for offline ddl fail", KR(ret), + K(is_user_hidden_table), + "hidden_table_id", table_meta.get_table_id(), + "hidden_table_name", table_meta.get_table_name(), + K(origin_table_id), + "origin_table_name", origin_table_meta->get_table_name()); + } else if (OB_ISNULL(origin_table_meta)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("invalid schema", KR(ret), K(origin_table_meta)); + } else { + LOG_INFO("[OFFLINE_DDL]", K(is_user_hidden_table), + "hidden_table_id", table_meta.get_table_id(), + "hidden_table_name", table_meta.get_table_name(), + K(origin_table_id), + "origin_table_name", origin_table_meta->get_table_name()); + } + } + } + + return ret; +} + +int ObLogPartMgr::try_get_lob_aux_primary_table_schema_(const ObSimpleTableSchemaV2 &table_schema, + ObLogSchemaGuard &schema_guard, + const int64_t timeout, + const ObSimpleTableSchemaV2 *&primary_table_schema) +{ + int ret = OB_SUCCESS; + + if (OB_UNLIKELY(! inited_)) { + ret = OB_NOT_INIT; + LOG_ERROR("PartMgr has not been initialized", KR(ret)); + } else { + const bool is_aux_lob_table = table_schema.is_aux_lob_table(); + + if (is_aux_lob_table) { + const uint64_t primary_table_id = table_schema.get_data_table_id(); + + if (OB_UNLIKELY(OB_INVALID_ID == primary_table_id)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("origin_table_id is not valid", KR(ret), K(primary_table_id), K(table_schema)); + } else if (OB_FAIL(get_simple_table_schema_(primary_table_id, timeout, schema_guard, primary_table_schema))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get table schema for lob fail", KR(ret), + K(is_aux_lob_table), + "lob_aux_table_id", table_schema.get_table_id(), + "lob_aux_table_name", table_schema.get_table_name(), + K(primary_table_id), + "primary_table_name", primary_table_schema->get_table_name(), + "primary_table_state_flag", primary_table_schema->get_table_state_flag()); + } + } else if (OB_ISNULL(primary_table_schema)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("invalid schema", KR(ret), K(primary_table_schema)); + } else { + LOG_INFO("[LOB]", K(is_aux_lob_table), + "lob_aux_table_id", table_schema.get_table_id(), + "lob_aux_table_name", table_schema.get_table_name(), + K(primary_table_id), + "primary_table_name", primary_table_schema->get_table_name()); + } + } + } + + return ret; +} + +int ObLogPartMgr::try_get_lob_aux_primary_table_meta_(const datadict::ObDictTableMeta &table_meta, + ObDictTenantInfo *tenant_info, + datadict::ObDictTableMeta *&primary_table_meta) +{ + int ret = OB_SUCCESS; + + if (OB_UNLIKELY(! inited_)) { + ret = OB_NOT_INIT; + LOG_ERROR("PartMgr has not been initialized", KR(ret)); + } else { + const bool is_aux_lob_table = table_meta.is_aux_lob_table(); + + if (is_aux_lob_table) { + const uint64_t primary_table_id = table_meta.get_data_table_id(); + + if (OB_UNLIKELY(OB_INVALID_ID == primary_table_id)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("origin_table_id is not valid", KR(ret), K(primary_table_id), K(table_meta)); + } else if (OB_FAIL(tenant_info->get_table_meta(primary_table_id, primary_table_meta))) { + LOG_ERROR("get table meta for lob fail", KR(ret), + K(is_aux_lob_table), + "lob_aux_table_id", table_meta.get_table_id(), + "lob_aux_table_name", table_meta.get_table_name(), + K(primary_table_id), + "primary_table_name", primary_table_meta->get_table_name()); + } else if (OB_ISNULL(primary_table_meta)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("invalid schema", KR(ret), K(primary_table_meta)); + } else { + LOG_INFO("[LOB]", K(is_aux_lob_table), + "lob_aux_table_id", table_meta.get_table_id(), + "lob_aux_table_name", table_meta.get_table_name(), + K(primary_table_id), + "primary_table_name", primary_table_meta->get_table_name()); + } + } + } + + return ret; +} + int ObLogPartMgr::alter_table(const uint64_t table_id, const int64_t schema_version_before_alter, const int64_t schema_version_after_alter, @@ -454,6 +670,46 @@ int ObLogPartMgr::alter_table(const uint64_t table_id, return ret; } +int ObLogPartMgr::alter_table(const uint64_t table_id, + DdlStmtTask &ddl_stmt, + const int64_t new_schema_version, + const int64_t timeout) +{ + int ret = OB_SUCCESS; + const char *tenant_name = nullptr; + const char *database_name = nullptr; + const char *table_name = nullptr; + bool is_user_table = false; + bool chosen = false; + uint64_t database_id = OB_INVALID_ID; + if (OB_FAIL(table_match_(table_id, new_schema_version, tenant_name, database_name, + table_name, is_user_table, chosen, database_id, timeout))) { + LOG_ERROR("table_match_ failed", KR(ret), K(new_schema_version), K(table_id)); + } else if (!is_user_table) { + } else if (!chosen) { + TICUpdateInfo tic_update_info(TICUpdateInfo::TICUpdateReason::RENAME_TABLE_REMOVE, database_id, table_id); + PartTransTask &part_trans_task = ddl_stmt.get_host(); + if (OB_FAIL(part_trans_task.push_tic_update_info(tic_update_info))) { + LOG_ERROR("push tic update info failed", KR(ret), K(new_schema_version), K(tic_update_info), + K(tenant_name), K(database_name), K(table_name)); + } else { + ISTAT("set tic update info success", K(new_schema_version), K(tic_update_info), + K(tenant_name), K(database_name), K(table_name)); + } + } else { + TICUpdateInfo tic_update_info(TICUpdateInfo::TICUpdateReason::RENAME_TABLE_ADD, database_id, table_id); + PartTransTask &part_trans_task = ddl_stmt.get_host(); + if (OB_FAIL(part_trans_task.push_tic_update_info(tic_update_info))) { + LOG_ERROR("push tic update info failed", KR(ret), K(new_schema_version), K(tic_update_info), + K(tenant_name), K(database_name), K(table_name)); + } else { + ISTAT("set tic update info success", K(new_schema_version), K(tic_update_info), + K(tenant_name), K(database_name), K(table_name)); + } + } + return ret; +} + int ObLogPartMgr::drop_table(const uint64_t table_id, const int64_t schema_version_before_drop, const int64_t schema_version_after_drop, @@ -511,6 +767,119 @@ int ObLogPartMgr::drop_table(const uint64_t table_id, return ret; } +int ObLogPartMgr::drop_table(const uint64_t table_id, + DdlStmtTask &ddl_stmt, + const int64_t old_schema_version, + const int64_t timeout) +{ + int ret = OB_SUCCESS; + const char *tenant_name = nullptr; + const char *database_name = nullptr; + const char *table_name = nullptr; + uint64_t database_id = OB_INVALID_ID; + + if (OB_FAIL(get_schema_info_of_table_id_(table_id, old_schema_version, tenant_name, + database_name, table_name, timeout))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get schema info of table_id", KR(ret), K(table_id), K(old_schema_version)); + } + } else { + TICUpdateInfo tic_update_info(TICUpdateInfo::TICUpdateReason::DROP_TABLE, + database_id, table_id); + PartTransTask &part_trans_task = ddl_stmt.get_host(); + if (OB_FAIL(part_trans_task.push_tic_update_info(tic_update_info))) { + LOG_ERROR("push tic update info failed", KR(ret), K(old_schema_version), K(tic_update_info), + K(tenant_name), K(database_name), K(table_name)); + } else { + ISTAT("set tic update info success", K(old_schema_version), K(tic_update_info), + K(tenant_name), K(database_name), K(table_name)); + } + } + return ret; +} + +int ObLogPartMgr::rename_table(const uint64_t table_id, + DdlStmtTask &ddl_stmt, + const int64_t new_schema_version, + const int64_t timeout) +{ + int ret = OB_SUCCESS; + const char *tenant_name = nullptr; + const char *database_name = nullptr; + const char *table_name = nullptr; + bool is_user_table = false; + bool chosen = false; + uint64_t database_id = OB_INVALID_ID; + if (OB_FAIL(table_match_(table_id, new_schema_version, tenant_name, database_name, + table_name, is_user_table, chosen, database_id, timeout))) { + LOG_ERROR("table_match_ failed", KR(ret), K(new_schema_version), K(table_id)); + } else if (!is_user_table) { + } else if (!chosen) { + TICUpdateInfo tic_update_info(TICUpdateInfo::TICUpdateReason::RENAME_TABLE_REMOVE, + database_id, table_id); + PartTransTask &part_trans_task = ddl_stmt.get_host(); + if (OB_FAIL(part_trans_task.push_tic_update_info(tic_update_info))) { + LOG_ERROR("push tic update info failed", KR(ret), K(new_schema_version), K(tic_update_info), + K(tenant_name), K(database_name), K(table_name)); + } else { + ISTAT("set tic update info success", K(new_schema_version), K(tic_update_info), + K(tenant_name), K(database_name), K(table_name)); + } + } else { + TICUpdateInfo tic_update_info(TICUpdateInfo::TICUpdateReason::RENAME_TABLE_ADD, + database_id, table_id); + PartTransTask &part_trans_task = ddl_stmt.get_host(); + if (OB_FAIL(part_trans_task.push_tic_update_info(tic_update_info))) { + LOG_ERROR("push tic update info failed", KR(ret), K(new_schema_version), K(tic_update_info), + K(tenant_name), K(database_name), K(table_name)); + } else { + ISTAT("set tic update info success", K(new_schema_version), K(tic_update_info), + K(tenant_name), K(database_name), K(table_name)); + } + } + return ret; +} + +int ObLogPartMgr::insert_table_id_into_cache(const uint64_t table_id, const uint64_t database_id) +{ + int ret = OB_SUCCESS; + TableID table_id_key(table_id); + if (OB_FAIL(table_id_cache_.insert_or_update(table_id_key, database_id))) { + if (OB_ENTRY_EXIST == ret) { + LOG_WARN("table_id already exists in table_id_cache", KR(ret), K(table_id)); + ret = OB_SUCCESS; + } else { + LOG_ERROR("insert table_id into cache failed", KR(ret), K(table_id), K(database_id)); + } + } + return ret; +} + +int ObLogPartMgr::delete_table_id_from_cache(const uint64_t table_id) +{ + int ret = OB_SUCCESS; + TableID table_id_key(table_id); + if (OB_FAIL(table_id_cache_.erase(table_id_key))) { + if (OB_ENTRY_NOT_EXIST == ret) { + LOG_WARN("no table_id in table_id_cache", KR(ret), K(table_id)); + ret = OB_SUCCESS; + } else { + LOG_ERROR("delete table_id from cache failed", KR(ret), K(table_id)); + } + } + return ret; +} + +int ObLogPartMgr::delete_db_from_cache(const uint64_t database_id) +{ + int ret = OB_SUCCESS; + TableInfoEraserByDatabase table_info_eraser_by_database(database_id); + if (OB_FAIL(table_id_cache_.remove_if(table_info_eraser_by_database))) { + LOG_ERROR("delete db from cache failed", KR(ret), K(database_id)); + } + return ret; +} + int ObLogPartMgr::add_index_table(const uint64_t table_id, const int64_t start_schema_version, const int64_t start_serve_tstamp, @@ -853,10 +1222,15 @@ int ObLogPartMgr::update_schema_version(const int64_t schema_version) int ObLogPartMgr::is_exist_table_id_cache(const uint64_t table_id, bool &is_exist) { - const bool is_global_normal_index = false; - is_exist = false; - - return is_exist_table_id_cache_(table_id, is_global_normal_index, is_exist); + int ret = OB_SUCCESS; + if (!enable_white_black_list_) { + is_exist = true; + } else { + const bool is_global_normal_index = false; + is_exist = false; + ret = is_exist_table_id_cache_(table_id, is_global_normal_index, is_exist); + } + return ret; } int ObLogPartMgr::handle_future_table(const uint64_t table_id, @@ -1200,6 +1574,80 @@ int ObLogPartMgr::get_schema_guard_and_schemas_(const uint64_t table_id, return ret; } +int ObLogPartMgr::add_user_table_info_(ObLogSchemaGuard &schema_guard, + const ObSimpleTableSchemaV2 *table_schema, + const int64_t timeout) +{ + int ret = OB_SUCCESS; + // add all user tables info + const char *tenant_name = nullptr; + const char *database_name = nullptr; + const char *table_name = nullptr; + bool is_user_table = false; + bool chosen = false; + uint64_t database_id = OB_INVALID_ID; + if (OB_ISNULL(table_schema)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("table_schema is NULL", KR(ret), K_(tenant_id), K_(cur_schema_version)); + } else if (OB_FAIL(table_match_(schema_guard, table_schema, tenant_name, database_name, + table_name, is_user_table, chosen, database_id, timeout))) { + LOG_ERROR("table_match_ failed", KR(ret), K_(tenant_id), K(tenant_name), + K(database_name), K(table_name)); + } else if (!is_user_table) { + } else if (!chosen) { + ISTAT("table is not chosen", K_(tenant_id), K(tenant_name), K(database_name), + K(table_name)); + } else { + const uint64_t table_id = table_schema->get_table_id(); + const uint64_t database_id = table_schema->get_database_id(); + if (OB_FAIL(insert_table_id_into_cache(table_id, database_id))) { + LOG_ERROR("insert table_id into cache failed", K_(tenant_id), K(table_id), + K(database_id), K(tenant_name), K(database_name), K(table_name)); + } else { + ISTAT("insert table_id into cache success", K_(tenant_id), K(table_id), + K(database_id), K(tenant_name), K(database_name), K(table_name)); + } + } + return ret; +} + +int ObLogPartMgr::add_user_table_info_(ObDictTenantInfo *tenant_info, + const datadict::ObDictTableMeta *table_meta, + const int64_t timeout) +{ + int ret = OB_SUCCESS; + // add all user tables info + const char *tenant_name = nullptr; + const char *database_name = nullptr; + const char *table_name = nullptr; + bool is_user_table = false; + bool chosen = false; + uint64_t database_id = OB_INVALID_ID; + if (OB_ISNULL(table_meta)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("table_schema is NULL", KR(ret), K_(tenant_id), K_(cur_schema_version)); + } else if (OB_FAIL(table_match_(tenant_info, table_meta, tenant_name, database_name, + table_name, is_user_table, chosen, database_id, timeout))) { + LOG_ERROR("table_match_ failed", KR(ret), K_(tenant_id), K(tenant_name), + K(database_name), K(table_name)); + } else if (!is_user_table) { + } else if (!chosen) { + ISTAT("table is not chosen", K_(tenant_id), K(tenant_name), K(database_name), + K(table_name)); + } else { + const uint64_t table_id = table_meta->get_table_id(); + const uint64_t database_id = table_meta->get_database_id(); + if (OB_FAIL(insert_table_id_into_cache(table_id, database_id))) { + LOG_ERROR("insert table_id into cache failed", K_(tenant_id), K(table_id), + K(database_id), K(tenant_name), K(database_name), K(table_name)); + } else { + ISTAT("insert table_id into cache success", K_(tenant_id), K(table_id), + K(database_id), K(tenant_name), K(database_name), K(table_name)); + } + } + return ret; +} + int ObLogPartMgr::add_table_(const int64_t start_serve_tstamp, const bool is_create_partition, const ObSimpleTableSchemaV2 *tb_schema, @@ -1437,16 +1885,16 @@ int ObLogPartMgr::clean_table_id_cache_() LOG_ERROR("PartMgr has not been initialized"); ret = OB_NOT_INIT; } else { - TableInfoEraserByTenant gidx_tb_eraser_by_tenant(tenant_id_, true/*is_global_normal_index*/); - TableInfoEraserByTenant tableid_tb_eraser_by_tenant(tenant_id_, false/*is_global_normal_index*/); + // TableInfoEraserByTenant gidx_tb_eraser_by_tenant(tenant_id_, true/*is_global_normal_index*/); + // TableInfoEraserByTenant tableid_tb_eraser_by_tenant(tenant_id_); - if (OB_FAIL(global_normal_index_table_cache_->remove_if(gidx_tb_eraser_by_tenant))) { - LOG_ERROR("global_normal_index_table_cache_ remove_if fail", KR(ret), K(tenant_id_)); - } else if (OB_FAIL(table_id_cache_->remove_if(tableid_tb_eraser_by_tenant))) { - LOG_ERROR("table_id_cache_ remove_if fail", KR(ret), K(tenant_id_)); - } else { - // do nothing - } + // if (OB_FAIL(global_normal_index_table_cache_->remove_if(gidx_tb_eraser_by_tenant))) { + // LOG_ERROR("global_normal_index_table_cache_ remove_if fail", KR(ret), K(tenant_id_)); + // } else if (OB_FAIL(table_id_cache_->remove_if(tableid_tb_eraser_by_tenant))) { + // LOG_ERROR("table_id_cache_ remove_if fail", KR(ret), K(tenant_id_)); + // } else { + // // do nothing + // } } return ret; @@ -1491,7 +1939,7 @@ int ObLogPartMgr::add_table_id_into_cache_(const ObSimpleTableSchemaV2 &tb_schem K(db_id), K(db_name)); } } else { - if (OB_FAIL(table_id_cache_->insert(table_id_key, tb_info))) { + if (OB_FAIL(table_id_cache_.insert(table_id_key, db_id))) { if (OB_ENTRY_EXIST == ret) { // cache ready exist ret = OB_SUCCESS; @@ -1545,7 +1993,7 @@ int ObLogPartMgr::remove_table_id_from_cache_(const ObSimpleTableSchemaV2 &tb_sc "is_global_normal_index_table", tb_schema.is_global_normal_index_table()); } } else { - if (OB_FAIL(table_id_cache_->erase(table_id_key))) { + if (OB_FAIL(table_id_cache_.erase(table_id_key))) { // Partition may not exist, normal if (OB_ENTRY_NOT_EXIST == ret) { ret = OB_SUCCESS; @@ -1571,6 +2019,7 @@ int ObLogPartMgr::is_exist_table_id_cache_(const uint64_t table_id, int ret = OB_SUCCESS; TableID table_id_key(table_id); TableInfo info; + uint64_t database_id; is_exist = false; if (OB_UNLIKELY(! inited_)) { @@ -1581,7 +2030,7 @@ int ObLogPartMgr::is_exist_table_id_cache_(const uint64_t table_id, ret = OB_INVALID_ARGUMENT; } else { is_exist = true; - /* TODO imply for blacklist, remove Temporary + // TODO imply for blacklist, remove Temporary if (is_global_normal_index) { if (OB_FAIL(global_normal_index_table_cache_->get(table_id_key, info))) { if (OB_ENTRY_NOT_EXIST == ret) { @@ -1594,7 +2043,7 @@ int ObLogPartMgr::is_exist_table_id_cache_(const uint64_t table_id, is_exist = true; } } else { - if (OB_FAIL(table_id_cache_->get(table_id_key, info))) { + if (OB_FAIL(table_id_cache_.get(table_id_key, database_id))) { if (OB_ENTRY_NOT_EXIST == ret) { ret = OB_SUCCESS; is_exist = false; @@ -1607,15 +2056,546 @@ int ObLogPartMgr::is_exist_table_id_cache_(const uint64_t table_id, LOG_DEBUG("[SERVED_TABLE_ID_CACHE] [IS_EXIST]", K(tenant_id_), K(table_id), K(is_exist)); } - */ + } + return ret; +} + +int ObLogPartMgr::table_match_(const uint64_t table_id, + const int64_t schema_version, + const char *&tenant_name, + const char *&database_name, + const char *&table_name, + bool &is_user_table, + bool &chosen, + uint64_t &database_id, + const int64_t timeout) +{ + int ret = OB_SUCCESS; + if (OB_FAIL(get_table_info_of_table_id_(table_id, schema_version, + tenant_name, database_name, table_name, database_id, is_user_table, timeout))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get_table_info_of_table_id_ failed", KR(ret), K(schema_version), K(table_id)); + } + } else if (!is_user_table) { + LOG_INFO("table is not user defined", K(schema_version), K(table_id), K(tenant_name), + K(database_name), K(table_name), K(chosen)); + } else if (OB_FAIL(matching_based_table_matcher_(tenant_name, database_name, table_name, chosen))) { + LOG_ERROR("matching_based_table_matcher_ failed", KR(ret), K(schema_version), K(table_id), + K(tenant_name), K(database_name), K(table_name)); + } else { + LOG_INFO("table_match_ success", K(schema_version), K(table_id), K(tenant_name), + K(database_name), K(table_name), K(chosen), K(database_id)); + } + return ret; +} + +int ObLogPartMgr::table_match_(ObLogSchemaGuard &schema_guard, + const ObSimpleTableSchemaV2 *table_schema, + const char *&tenant_name, + const char *&database_name, + const char *&table_name, + bool &is_user_table, + bool &chosen, + uint64_t &database_id, + const int64_t timeout) +{ + int ret = OB_SUCCESS; + if (OB_FAIL(get_table_info_of_table_schema_(schema_guard, table_schema, + tenant_name, database_name, table_name, database_id, is_user_table, timeout))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get_table_info_of_table_schema failed", KR(ret)); + } + } else if (!is_user_table) { + LOG_INFO("table is not user defined", K(tenant_name), K(database_name), K(table_name), + K(chosen)); + } else if (OB_FAIL(matching_based_table_matcher_(tenant_name, database_name, table_name, chosen))) { + LOG_ERROR("matching_based_table_matcher_ failed", KR(ret), K(tenant_name), K(database_name), K(table_name)); + } else { + LOG_INFO("table_match_ success", K(tenant_name), K(database_name), K(table_name), + K(chosen), K(database_id)); + } + return ret; +} + +int ObLogPartMgr::table_match_(ObDictTenantInfo *tenant_info, + const datadict::ObDictTableMeta *table_meta, + const char *&tenant_name, + const char *&database_name, + const char *&table_name, + bool &is_user_table, + bool &chosen, + uint64_t &database_id, + const int64_t timeout) +{ + int ret = OB_SUCCESS; + if (OB_FAIL(get_table_info_of_table_meta_(tenant_info, table_meta, tenant_name, + database_name, table_name, database_id, is_user_table, timeout))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get_table_info_of_table_meta failed", KR(ret)); + } + } else if (!is_user_table) { + LOG_INFO("table is not user defined", K(tenant_name), K(database_name), K(table_name), + K(chosen)); + } else if (OB_FAIL(matching_based_table_matcher_(tenant_name, database_name, table_name, chosen))) { + LOG_ERROR("matching_based_table_matcher_ failed", KR(ret), K(tenant_name), K(database_name), + K(table_name)); + } else { + LOG_INFO("table_match_ success", K(tenant_name), K(database_name), K(table_name), + K(chosen), K(database_id)); + } + return ret; +} + +int ObLogPartMgr::matching_based_table_matcher_(const char *tenant_name, + const char *database_name, + const char *table_name, + bool &chosen) +{ + int ret = OB_SUCCESS; + IObLogTableMatcher *tb_matcher = TCTX.tb_matcher_; + if (OB_ISNULL(tb_matcher)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("tb_matcher is NULL", KR(ret), K(tb_matcher)); + } else if (OB_FAIL(tb_matcher->table_match(tenant_name, database_name, table_name, chosen, + fnmatch_flags_))) { + LOG_ERROR("matching_based_table_matcher_ failed", KR(ret), K(tenant_name), K(database_name), K(table_name), + K_(fnmatch_flags)); + } else { + LOG_INFO("matching_based_table_matcher_ success", K(tenant_name), K(database_name), K(table_name), + K(chosen), K_(fnmatch_flags)); + } + return ret; +} + +int ObLogPartMgr::database_match_(const uint64_t database_id, + const int64_t schema_version, + const char *&tenant_name, + const char *&database_name, + bool &chosen, + const int64_t timeout) +{ + int ret = OB_SUCCESS; + IObLogTableMatcher *tb_matcher = TCTX.tb_matcher_; + if (OB_ISNULL(tb_matcher)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("tb_matcher is NULL", KR(ret), K(tb_matcher)); + } else if (OB_FAIL(get_database_info_of_database_id_(database_id, schema_version, tenant_name, + database_name, timeout))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get_database_info_of_database_id_ failed", KR(ret), K(schema_version), + K(database_id), K(schema_version)); + } + } else if (OB_FAIL(tb_matcher->database_match(tenant_name, database_name, chosen, + fnmatch_flags_))) { + LOG_ERROR("database_match failed", KR(ret), K(schema_version), K(database_id), + K(tenant_name), K(database_name), K_(fnmatch_flags)); + } else { + LOG_INFO("database_match success", K(schema_version), K(database_id), + K(tenant_name), K(database_name), K_(fnmatch_flags)); + } + return ret; +} + +int ObLogPartMgr::get_table_info_of_table_id_(const uint64_t table_id, + const int64_t schema_version, + const char *&tenant_name, + const char *&database_name, + const char *&table_name, + uint64_t &database_id, + bool &is_user_table, + const int64_t timeout) +{ + int ret = OB_SUCCESS; + if (is_online_refresh_mode(TCTX.refresh_mode_)) { + IObLogSchemaGetter *schema_getter = TCTX.schema_getter_; + ObLogSchemaGuard schema_guard; + const ObSimpleTableSchemaV2 *table_schema = nullptr; + if (OB_FAIL(get_schema_guard_and_table_schema_(table_id, schema_version, timeout, + schema_guard, table_schema))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get schema_guard and table_schema failed", KR(ret), K(table_id), K(schema_version)); + } + } else if (OB_FAIL(get_table_info_of_table_schema_(schema_guard, table_schema, + tenant_name, database_name, table_name, database_id, is_user_table, timeout))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get table info from table_schema failed", KR(ret), K(schema_version)); + } + } + } else { + ObDictTenantInfoGuard dict_tenant_info_guard; + ObDictTenantInfo *tenant_info = nullptr; + datadict::ObDictTableMeta *table_meta = nullptr; + if (OB_FAIL(GLOGMETADATASERVICE.get_tenant_info_guard(tenant_id_, dict_tenant_info_guard))) { + LOG_ERROR("get tenant_info_guard failed", KR(ret), K_(tenant_id)); + } else if (OB_ISNULL(tenant_info = dict_tenant_info_guard.get_tenant_info())) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("tenant_info is nullptr", K_(tenant_id)); + } else if (OB_FAIL(tenant_info->get_table_meta(table_id, table_meta))) { + LOG_ERROR("tenant_info get table_meta failed", KR(ret), K_(tenant_id)); + } else if (OB_FAIL(get_table_info_of_table_meta_(tenant_info, table_meta, + tenant_name, database_name, table_name, database_id, is_user_table, timeout))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get table info from table_meta failed", KR(ret), K(schema_version)); + } + } + } + LOG_INFO("get table info of table_id finished", K(table_id), K(schema_version), + K(tenant_name), K(database_name), K(table_name), K(database_id), K(is_user_table)); + return ret; +} + +int ObLogPartMgr::get_schema_info_of_table_id_(const uint64_t table_id, + const int64_t schema_version, + const char *&tenant_name, + const char *&database_name, + const char *&table_name, + const int64_t timeout) +{ + int ret = OB_SUCCESS; + uint64_t database_id = OB_INVALID_ID; + bool is_user_table = false; + if (is_online_refresh_mode(TCTX.refresh_mode_)) { + IObLogSchemaGetter *schema_getter = TCTX.schema_getter_; + ObLogSchemaGuard schema_guard; + TenantSchemaInfo tenant_schema_info; + DBSchemaInfo db_schema_info; + const ObSimpleTableSchemaV2 *table_schema = nullptr; + if (OB_ISNULL(schema_getter)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("schema_getter is NULL", KR(ret), K(schema_getter)); + } else if (OB_FAIL(get_schema_guard_and_table_schema_(table_id, schema_version, timeout, + schema_guard, table_schema))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get schema_guard and table_schema failed", KR(ret), K(table_id), K(schema_version)); + } + } else if (inner_get_table_info_of_table_schema_(schema_guard, table_schema, tenant_name, + database_name, table_name, database_id, is_user_table, timeout)) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("inner get table info failed", KR(ret), KPC(table_schema)); + } + } else { + // succ + } + } else { + ObDictTenantInfoGuard dict_tenant_info_guard; + ObDictTenantInfo *tenant_info = nullptr; + DBSchemaInfo db_schema_info; + datadict::ObDictTableMeta *table_meta = nullptr; + if (OB_FAIL(GLOGMETADATASERVICE.get_tenant_info_guard(tenant_id_, dict_tenant_info_guard))) { + LOG_ERROR("get tenant_info_guard failed", KR(ret), K_(tenant_id)); + } else if (OB_ISNULL(tenant_info = dict_tenant_info_guard.get_tenant_info())) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("tenant_info is nullptr", KR(ret), K_(tenant_id)); + } else if (inner_get_table_info_of_table_meta_(tenant_info, table_meta, tenant_name, + database_name, table_name, database_id, is_user_table)) { + LOG_ERROR("inner get table info failed", KR(ret), KPC(tenant_info)); + } else { + // succ + } + } + LOG_INFO("get schema info of table_id finished", K(schema_version), K(table_id), + K(tenant_name), K(database_name), K(table_name)); + return ret; +} + +int ObLogPartMgr::get_database_info_of_database_id_(const uint64_t database_id, + const int64_t schema_version, + const char *&tenant_name, + const char *&database_name, + const int64_t timeout) +{ + int ret = OB_SUCCESS; + if (is_online_refresh_mode(TCTX.refresh_mode_)) { + IObLogSchemaGetter *schema_getter = TCTX.schema_getter_; + ObLogSchemaGuard schema_guard; + TenantSchemaInfo tenant_schema_info; + DBSchemaInfo db_schema_info; + if (OB_ISNULL(schema_getter)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("schema_getter is NULL", KR(ret), K(schema_getter)); + } else if (OB_FAIL(schema_getter->get_lazy_schema_guard(tenant_id_, schema_version, + timeout, schema_guard))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get fallback_schema_guard failed", KR(ret), K_(tenant_id), K(schema_version)); + } + } else if (OB_FAIL(schema_guard.get_tenant_schema_info(tenant_id_, tenant_schema_info, timeout))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get tenant_schema_info failed", KR(ret), K_(tenant_id), K(schema_version)); + } + } else if (OB_FAIL(schema_guard.get_database_schema_info(tenant_id_, database_id, + db_schema_info, timeout))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get database_schema_info failed", KR(ret), K_(tenant_id), K(schema_version)); + } + } else { + tenant_name = tenant_schema_info.name_; + database_name = db_schema_info.name_; + } + } else { + ObDictTenantInfoGuard dict_tenant_info_guard; + ObDictTenantInfo *tenant_info = nullptr; + DBSchemaInfo db_schema_info; + if (OB_FAIL(GLOGMETADATASERVICE.get_tenant_info_guard(tenant_id_, dict_tenant_info_guard))) { + LOG_ERROR("get tenant_info_guard failed", KR(ret), K_(tenant_id)); + } else if (OB_ISNULL(tenant_info = dict_tenant_info_guard.get_tenant_info())) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("tenant_info is nullptr", KR(ret), K_(tenant_id)); + } else if (OB_FAIL(tenant_info->get_database_schema_info(database_id, + db_schema_info))) { + LOG_ERROR("tenant_info get database_schema_info failed", KR(ret), K_(tenant_id)); + } else { + tenant_name = tenant_info->get_tenant_name(); + database_name = db_schema_info.name_; + } + } + LOG_INFO("get database info of database_id finished", K(schema_version), K(database_id), + K(tenant_name), K(database_name)); + return ret; +} + +int ObLogPartMgr::get_table_info_of_table_schema_(ObLogSchemaGuard &schema_guard, + const ObSimpleTableSchemaV2 *table_schema, + const char *&tenant_name, + const char *&database_name, + const char *&table_name, + uint64_t &database_id, + bool &is_user_table, + const int64_t timeout) +{ + int ret = OB_SUCCESS; + uint64_t table_id = OB_INVALID_ID; + const ObSimpleTableSchemaV2 *final_table_schema = NULL; + if (OB_ISNULL(table_schema)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("table_schema is NULL", KR(ret), K(table_schema)); + } else if (FALSE_IT(table_id = table_schema->get_table_id())) { + } else if (table_schema->is_user_hidden_table()) { + const ObSimpleTableSchemaV2 *origin_table_schema = nullptr; + if (OB_FAIL(try_get_offline_ddl_origin_table_schema_(*table_schema, schema_guard, + timeout, origin_table_schema))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get origin_table_schema of offline ddl failed", KR(ret), K(table_id), + KPC(table_schema)); + } + } else if (OB_ISNULL(origin_table_schema)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("origin_table_schema is NULL", KR(ret), KPC(table_schema)); + } else if (origin_table_schema->is_user_hidden_table()) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("the origin table of user hidden table can't be another user hidden table", + KR(ret), KPC(origin_table_schema)); + } else if (origin_table_schema->is_aux_lob_meta_table()) { + const ObSimpleTableSchemaV2 *primary_table_schema = nullptr; + if (OB_FAIL(try_get_lob_aux_primary_table_schema_(*origin_table_schema, schema_guard, + timeout, primary_table_schema))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get primary_table_schema of lob_aux_meta table failed", KR(ret), + "table_id", origin_table_schema->get_table_id(), "table_name", + origin_table_schema->get_table_name()); + } + } else { + final_table_schema = primary_table_schema; + } + } else { + final_table_schema = origin_table_schema; + } + } else if (table_schema->is_aux_lob_meta_table()) { + const ObSimpleTableSchemaV2 *primary_table_schema = nullptr; + if (OB_FAIL(try_get_lob_aux_primary_table_schema_(*table_schema, schema_guard, + timeout, primary_table_schema))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get primary_table_schema of lob_aux_meta table failed", KR(ret), + K(table_id), KPC(table_schema)); + } + } else if (OB_ISNULL(primary_table_schema)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("primary_table_schema is NULL", KR(ret), K(primary_table_schema)); + } else if (primary_table_schema->is_aux_lob_meta_table()) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("the primary table of lob_aux_meta table can't be another lob_aux_meta table", + KR(ret), KPC(primary_table_schema)); + } else if (primary_table_schema->is_user_hidden_table()) { + const ObSimpleTableSchemaV2 *origin_table_schema = nullptr; + if (OB_FAIL(try_get_offline_ddl_origin_table_schema_(*primary_table_schema, schema_guard, + timeout, origin_table_schema))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get origin_table_schema of offline ddl failed", KR(ret), "table_id", + primary_table_schema->get_table_id(), "table_name", + primary_table_schema->get_table_name()); + } + } else { + final_table_schema = origin_table_schema; + } + } else { + final_table_schema = primary_table_schema; + } + } else { + final_table_schema = table_schema; } + if (OB_SUCC(ret) && OB_FAIL(inner_get_table_info_of_table_schema_(schema_guard, final_table_schema, tenant_name, + database_name, table_name, database_id, is_user_table, timeout))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("inner get table info failed", KR(ret), KPC(final_table_schema)); + } + } + + LOG_INFO("get table info of table_schema finished", KR(ret), K(table_id), K(tenant_name), + K(database_name), K(table_name), K(database_id), K(is_user_table)); + return ret; +} + +int ObLogPartMgr::get_table_info_of_table_meta_(ObDictTenantInfo *tenant_info, + const datadict::ObDictTableMeta *table_meta, + const char *&tenant_name, + const char *&database_name, + const char *&table_name, + uint64_t &database_id, + bool &is_user_table, + const int64_t timeout) +{ + int ret = OB_SUCCESS; + uint64_t table_id = OB_INVALID_ID; + const datadict::ObDictTableMeta *final_table_meta = NULL; + if (OB_ISNULL(tenant_info)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("tenant_info is NULL", KR(ret), K_(tenant_id)); + } else if (OB_ISNULL(table_meta)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("table_meta is NULL", KR(ret), K(table_meta)); + } else if (FALSE_IT(table_id = table_meta->get_table_id())) { + } else if (table_meta->is_user_hidden_table()) { + datadict::ObDictTableMeta *origin_table_meta = nullptr; + if (OB_FAIL(try_get_offline_ddl_origin_table_meta_(*table_meta, tenant_info, + origin_table_meta))) { + LOG_ERROR("get origin_table_meta of offline ddl failed", KR(ret), K(table_id), + KPC(table_meta)); + } else if (OB_ISNULL(origin_table_meta)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("origin_table_meta is NULL", KR(ret), K(origin_table_meta)); + } else if (origin_table_meta->is_user_hidden_table()) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("the origin table of user hidden table can't be another user hidden table", + KR(ret), K(origin_table_meta)); + } else if (origin_table_meta->is_aux_lob_meta_table()) { + datadict::ObDictTableMeta *primary_table_meta = nullptr; + if (OB_FAIL(try_get_lob_aux_primary_table_meta_(*origin_table_meta, tenant_info, + primary_table_meta))) { + LOG_ERROR("get primary table of lob_aux_meta table failed", KR(ret), + KPC(origin_table_meta)); + } else { + final_table_meta = primary_table_meta; + } + } else { + final_table_meta = origin_table_meta; + } + } else if (table_meta->is_aux_lob_meta_table()) { + datadict::ObDictTableMeta *primary_table_meta = nullptr; + if (OB_FAIL(try_get_lob_aux_primary_table_meta_(*table_meta, tenant_info, + primary_table_meta))) { + LOG_ERROR("get primary_table_meta of lob_aux_meta table failed", KR(ret), + K(table_id), KPC(table_meta)); + } else if (OB_ISNULL(primary_table_meta)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("primary_table_meta is NULL", KR(ret), K(primary_table_meta)); + } else if (primary_table_meta->is_aux_lob_meta_table()) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("the primary table of lob_aux_meta table can't be another lob_aux_meta table", + KR(ret), KPC(primary_table_meta)); + } else if (primary_table_meta->is_user_hidden_table()) { + datadict::ObDictTableMeta *origin_table_meta = nullptr; + if (OB_FAIL(try_get_offline_ddl_origin_table_meta_(*primary_table_meta, tenant_info, + origin_table_meta))) { + LOG_ERROR("get origin_table_meta of offline ddl", KR(ret), KPC(primary_table_meta)); + } else { + final_table_meta = origin_table_meta; + } + } else { + final_table_meta = primary_table_meta; + } + } else { + final_table_meta = table_meta; + } + + if (OB_SUCC(ret) && OB_FAIL(inner_get_table_info_of_table_meta_(tenant_info, final_table_meta, + tenant_name, database_name, table_name, database_id, is_user_table))) { + LOG_ERROR("inner get table info failed", KR(ret), KPC(final_table_meta)); + } + + LOG_INFO("get table info of table_meta success", K(table_id), K(tenant_name), + K(database_name), K(table_name), K(database_id), K(is_user_table)); + return ret; +} + +int ObLogPartMgr::inner_get_table_info_of_table_schema_(ObLogSchemaGuard &schema_guard, + const ObSimpleTableSchemaV2 *table_schema, + const char *&tenant_name, + const char *&database_name, + const char *&table_name, + uint64_t &database_id, + bool &is_user_table, + const int64_t timeout) +{ + int ret = OB_SUCCESS; + TenantSchemaInfo tenant_schema_info; + DBSchemaInfo db_schema_info; + if (OB_ISNULL(table_schema)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("table_schema is NULL", KR(ret), K(table_schema)); + } else if (OB_FAIL(schema_guard.get_tenant_schema_info(tenant_id_, tenant_schema_info, timeout))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get_tenant_schema_info failed", KR(ret), K_(tenant_id)); + } + } else if (OB_FAIL(schema_guard.get_database_schema_info(tenant_id_, + table_schema->get_database_id(), db_schema_info, timeout))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get_database_schema_info failed", KR(ret), K_(tenant_id)); + } + } else { + tenant_name = tenant_schema_info.name_; + database_name = db_schema_info.name_; + table_name = table_schema->get_table_name(); + database_id = table_schema->get_database_id(); + is_user_table = table_schema->is_user_table(); + LOG_INFO("inner_get_table_info_of_table_schema_ success", K(tenant_name), K(database_name), + K(table_name), K(database_id), K(is_user_table)); + } + return ret; +} + +int ObLogPartMgr::inner_get_table_info_of_table_meta_(ObDictTenantInfo *tenant_info, + const datadict::ObDictTableMeta *table_meta, + const char *&tenant_name, + const char *&database_name, + const char *&table_name, + uint64_t &database_id, + bool &is_user_table) +{ + int ret = OB_SUCCESS; + DBSchemaInfo db_schema_info; + if (OB_ISNULL(tenant_info)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("tenant_info is nullptr", KR(ret), K_(tenant_id)); + } else if (OB_ISNULL(table_meta)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("table_meta is NULL", KR(ret)); + } else if (OB_FAIL(tenant_info->get_database_schema_info(table_meta->get_database_id(), + db_schema_info))) { + LOG_ERROR("tenant_info get_database_schema_info failed", KR(ret), K_(tenant_id)); + } else { + tenant_name = tenant_info->get_tenant_name(); + database_name = db_schema_info.name_; + table_name = table_meta->get_table_name(); + database_id = table_meta->get_database_id(); + is_user_table = table_meta->is_user_table(); + LOG_INFO("inner_get_table_info_of_table_meta_ success", K(tenant_name), K(database_name), + K(table_name), K(database_id), K(is_user_table)); + } return ret; } } } - #undef _STAT #undef STAT #undef _ISTAT diff --git a/src/logservice/libobcdc/src/ob_log_part_mgr.h b/src/logservice/libobcdc/src/ob_log_part_mgr.h index d18a38b1ab..cca00f1a8e 100644 --- a/src/logservice/libobcdc/src/ob_log_part_mgr.h +++ b/src/logservice/libobcdc/src/ob_log_part_mgr.h @@ -21,6 +21,8 @@ #include "ob_log_table_id_cache.h" // GIndexCache, TableIDCache #include "ob_cdc_tablet_to_table_info.h" // TabletToTableInfo #include "ob_log_utils.h" // _SEC_ +#include "ob_log_part_trans_task.h" // PartTransTask +#include "ob_log_meta_data_struct.h" // ObDictTenantInfo namespace oceanbase { @@ -42,6 +44,7 @@ using share::schema::ObTablegroupSchema; namespace libobcdc { class ObLogSchemaGuard; +class IObLogTableMatcher; //////////////////////////////////////////////////////////////////////////////////////// @@ -51,20 +54,6 @@ public: virtual ~IObLogPartMgr() {} public: - /// Init TabletToTableInfo: - /// add all user tablet(with tenant_id_ and cur_schema_version) into tablet_to_table_info - /// @param timeout schema operation timeout - /// @retval OB_SUCCESS op success - virtual int add_all_user_tablets_info(const int64_t timeout) = 0; - - /// Init TabletToTableInfo by Data Dictionary: - /// add all user tablet(with tenant_id_ and cur_schema_version) into tablet_to_table_info - /// @param timeout operation timeout - /// @retval OB_SUCCESS op success - virtual int add_all_user_tablets_info( - const ObIArray &table_metas, - const int64_t timeout) = 0; - /// Add a table /// @note must be called by a single thread in order according to the Schema version, should not concurrently add table in a random order /// @@ -93,6 +82,11 @@ public: const char *&db_name, const int64_t timeout) = 0; + virtual int add_table(const uint64_t table_id, + DdlStmtTask &ddl_stmt, + const int64_t new_schema_version, + const int64_t timeout) = 0; + /// Add a global unique index table, create index table scenario /// @note must be called by a single thread in order by Schema version, not concurrently and in random order //// @@ -150,6 +144,11 @@ public: const char *event, const int64_t timeout) = 0; + virtual int alter_table(const uint64_t table_id, + DdlStmtTask &ddl_stmt, + const int64_t new_schema_version, + const int64_t timeout) = 0; + /// Delete a table /// @note must be called by a single thread in order by Schema version, no concurrent messy deletions //// @@ -175,6 +174,16 @@ public: const char *&db_name, const int64_t timeout) = 0; + virtual int drop_table(const uint64_t table_id, + DdlStmtTask &ddl_stmt, + const int64_t old_schema_version, + const int64_t timeout) = 0; + + virtual int rename_table(const uint64_t table_id, + DdlStmtTask &ddl_stmt, + const int64_t new_schema_version, + const int64_t timeout) = 0; + /// Delete global index table, Delete index table scenario /// @note must be called by a single thread in order by Schema version, not concurrently in order //// @@ -215,6 +224,16 @@ public: const int64_t start_schema_version, const int64_t timeout) = 0; + /// Drop databse is not necessary actually, because drop database ddl will delete every table in database. + /// Here is for the sake of protection. But there is a bad case if users configure like this: + /// tb_white_list=*.*.white* + /// tb_black_list=*.*.black* + /// In this case, any database will not be matched. + virtual int drop_database(const uint64_t database_id, + const int64_t old_schema_version, + DdlStmtTask &ddl_stmt, + const int64_t timeout) = 0; + /// update schema version virtual int update_schema_version(const int64_t schema_version) = 0; @@ -235,6 +254,9 @@ public: ObCDCTableInfo &table_info) const = 0; virtual int apply_create_tablet_change(const ObCDCTabletChangeInfo &tablet_change_info) = 0; virtual int apply_delete_tablet_change(const ObCDCTabletChangeInfo &tablet_change_info) = 0; + virtual int insert_table_id_into_cache(const uint64_t table_id, const uint64_t database_id) = 0; + virtual int delete_table_id_from_cache(const uint64_t table_id) = 0; + virtual int delete_db_from_cache(const uint64_t database_id) = 0; }; ///////////////////////////////////////////////////////////////////////////// @@ -253,14 +275,15 @@ public: int init(const uint64_t tenant_id, const int64_t start_schema_version, const bool enable_oracle_mode_match_case_sensitive, - GIndexCache &gi_cache, - TableIDCache &table_id_cache); + const bool enable_white_black_list, + GIndexCache &gi_cache); void reset(); int64_t get_schema_version() const { return ATOMIC_LOAD(&cur_schema_version_); } public: - virtual int add_all_user_tablets_info(const int64_t timeout); - virtual int add_all_user_tablets_info( + virtual int add_all_user_tablets_and_tables_info(const int64_t timeout); + virtual int add_all_user_tablets_and_tables_info( + ObDictTenantInfo *tenant_info, const ObIArray &table_metas, const int64_t timeout); virtual int add_table(const uint64_t table_id, @@ -272,6 +295,10 @@ public: const char *&tenant_name, const char *&db_name, const int64_t timeout); + virtual int add_table(const uint64_t table_id, + DdlStmtTask &ddl_stmt, + const int64_t new_schema_version, + const int64_t timeout); virtual int alter_table(const uint64_t table_id, const int64_t schema_version_before_alter, const int64_t schema_version_after_alter, @@ -282,6 +309,10 @@ public: const char *&old_db_name, const char *event, const int64_t timeout); + virtual int alter_table(const uint64_t table_id, + DdlStmtTask &ddl_stmt, + const int64_t new_schema_version, + const int64_t timeout); virtual int drop_table(const uint64_t table_id, const int64_t schema_version_before_drop, const int64_t schema_version_after_drop, @@ -290,6 +321,14 @@ public: const char *&tenant_name, const char *&db_name, const int64_t timeout); + virtual int drop_table(const uint64_t table_id, + DdlStmtTask &ddl_stmt, + const int64_t old_schema_version, + const int64_t timeout); + virtual int rename_table(const uint64_t table_id, + DdlStmtTask &ddl_stmt, + const int64_t new_schema_version, + const int64_t timeout); virtual int add_index_table(const uint64_t table_id, const int64_t start_schema_version, const int64_t start_serve_tstamp, @@ -308,6 +347,10 @@ public: const int64_t start_serve_tstamp, const int64_t start_schema_version, const int64_t timeout); + virtual int drop_database(const uint64_t database_id, + const int64_t old_schema_version, + DdlStmtTask &ddl_stmt, + const int64_t timeout); virtual int update_schema_version(const int64_t schema_version); virtual int is_exist_table_id_cache(const uint64_t table_id, bool &is_exist); @@ -322,6 +365,9 @@ public: virtual int apply_create_tablet_change(const ObCDCTabletChangeInfo &tablet_change_info); virtual int apply_delete_tablet_change(const ObCDCTabletChangeInfo &tablet_change_info); + virtual int insert_table_id_into_cache(const uint64_t table_id, const uint64_t database_id); + virtual int delete_table_id_from_cache(const uint64_t table_id); + virtual int delete_db_from_cache(const uint64_t database_id); private: template @@ -340,11 +386,20 @@ private: int is_exist_table_id_cache_(const uint64_t table_id, const bool is_global_normal_index, bool &is_exist); - int try_get_offline_ddl_origin_table_schema_(const ObSimpleTableSchemaV2 &table_schema, ObLogSchemaGuard &schema_guard, const int64_t timeout, const ObSimpleTableSchemaV2 *&origin_table_schema); + int try_get_offline_ddl_origin_table_meta_(const datadict::ObDictTableMeta &table_meta, + ObDictTenantInfo *tenant_info, + datadict::ObDictTableMeta *&origin_table_meta); + int try_get_lob_aux_primary_table_schema_(const ObSimpleTableSchemaV2 &table_schema, + ObLogSchemaGuard &schema_guard, + const int64_t timeout, + const ObSimpleTableSchemaV2 *&primary_table_schema); + int try_get_lob_aux_primary_table_meta_(const datadict::ObDictTableMeta &table_meta, + ObDictTenantInfo *tenant_info, + datadict::ObDictTableMeta *&primary_table_meta); /// Add a table /// When manipulating a global index table, primary_table_schema represents its primary table schema, add_index_table()/do_add_all_tables_() /// When handle OFFLINE_DDL scenario, if it is a hidden table, primary_table_schema is the table schema of the origin associated table, add_table()/do_add_all_tables() @@ -471,21 +526,121 @@ private: const ObSimpleTableSchemaV2 *&tb_schema, const char *&tenant_name, const char *&db_name); + int add_user_table_info_(ObLogSchemaGuard &schema_guard, + const ObSimpleTableSchemaV2 *table_schema, + const int64_t timeout); + int add_user_table_info_(ObDictTenantInfo *tenant_info, + const datadict::ObDictTableMeta *table_meta, + const int64_t timeout); + // is_user_table is for filtering not user defined table. + // chosen is for filtering user defined table which is not in white list. + // NOTICE: It is not enough to have chosen without is_user_able. Because outer layer will set + // different tic update info according to chosen such as rename_table and alter_table. If there + // is no is_user_table, outer layer will not ignore user undefined table. + int table_match_(const uint64_t table_id, + const int64_t schema_version, + const char *&tenant_name, + const char *&database_name, + const char *&table_name, + bool &is_user_table, + bool &chosen, + uint64_t &database_id, + const int64_t timeout); + int table_match_(ObLogSchemaGuard &schema_guard, + const ObSimpleTableSchemaV2 *table_schema, + const char *&tenant_name, + const char *&database_name, + const char *&table_name, + bool &is_user_table, + bool &chosen, + uint64_t &database_id, + int64_t timeout); + int table_match_(ObDictTenantInfo *tenant_info, + const datadict::ObDictTableMeta *table_meta, + const char *&tenant_name, + const char *&database_name, + const char *&table_name, + bool &is_user_table, + bool &chosen, + uint64_t &database_id, + const int64_t timeout); + int matching_based_table_matcher_(const char *tenant_name, + const char *database_name, + const char *table_name, + bool &chosen); + int database_match_(const uint64_t database_id, + const int64_t schema_version, + const char *&tenant_name, + const char *&database_name, + bool &chosen, + const int64_t timeout); + int get_table_info_of_table_id_(const uint64_t table_id, + const int64_t schema_version, + const char *&tenant_name, + const char *&database_name, + const char *&table_name, + uint64_t &database_id, + bool &is_user_table, + const int64_t timeout); + int get_schema_info_of_table_id_(const uint64_t table_id, + const int64_t schema_version, + const char *&tenant_name, + const char *&database_name, + const char *&table_name, + const int64_t timeout); + int get_database_info_of_database_id_(const uint64_t database_id, + const int64_t schema_version, + const char *&tenant_name, + const char *&database_name, + const int64_t timeout); + int get_table_info_of_table_schema_(ObLogSchemaGuard &schema_guard, + const ObSimpleTableSchemaV2 *table_schema, + const char *&tenant_name, + const char *&database_name, + const char *&table_name, + uint64_t &database_id, + bool &is_user_table, + const int64_t timeout); + int get_table_info_of_table_meta_(ObDictTenantInfo *tenant_info, + const datadict::ObDictTableMeta *table_meta, + const char *&tenant_name, + const char *&database_name, + const char *&table_name, + uint64_t &database_id, + bool &is_user_table, + const int64_t timeout); + int inner_get_table_info_of_table_schema_(ObLogSchemaGuard &schema_guard, + const ObSimpleTableSchemaV2 *table_schema, + const char *&tenant_name, + const char *&database_name, + const char *&table_name, + uint64_t &database_id, + bool &is_user_table, + const int64_t timeout); + int inner_get_table_info_of_table_meta_(ObDictTenantInfo *tenant_info, + const datadict::ObDictTableMeta *table_meta, + const char *&tenant_name, + const char *&database_name, + const char *&table_name, + uint64_t &database_id, + bool &is_user_table); private: - ObLogTenant &host_; + ObLogTenant &host_; - bool inited_; - uint64_t tenant_id_; - GIndexCache *global_normal_index_table_cache_; // global normal index cache - TableIDCache *table_id_cache_; - TabletToTableInfo tablet_to_table_info_; // TabletID->TableID + bool inited_; + uint64_t tenant_id_; + GIndexCache *global_normal_index_table_cache_; // global normal index cache + TabletToTableInfo tablet_to_table_info_; // TabletID->TableID + TableIDCache table_id_cache_; - int64_t cur_schema_version_ CACHE_ALIGNED; + int64_t cur_schema_version_ CACHE_ALIGNED; // Default whitelist match insensitive - bool enable_oracle_mode_match_case_sensitive_; - bool enable_check_schema_version_; + bool enable_oracle_mode_match_case_sensitive_; + bool enable_check_schema_version_; + bool enable_white_black_list_; + int fnmatch_flags_; // Conditional common::ObThreadCond schema_cond_; diff --git a/src/logservice/libobcdc/src/ob_log_part_trans_parser.cpp b/src/logservice/libobcdc/src/ob_log_part_trans_parser.cpp index 019d847725..fdc3a6ba18 100644 --- a/src/logservice/libobcdc/src/ob_log_part_trans_parser.cpp +++ b/src/logservice/libobcdc/src/ob_log_part_trans_parser.cpp @@ -412,6 +412,8 @@ int ObLogPartTransParser::parse_mutator_row_( || is_all_ddl_operation_lob_aux_tablet(part_trans_task.get_ls_id(), tablet_id))) { need_filter = true; filter_reason = "NON_DDL_RELATED_TABLE"; + } else if (part_trans_task.is_ddl_trans()) { + // do nothing, ddl trans should not be filtered } else if (OB_FAIL(part_mgr.is_exist_table_id_cache(table_info.get_table_id(), is_in_table_id_cache))) { LOG_ERROR("check is_exist_table_id_cache failed", KR(ret), "tls_id", part_trans_task.get_tls_id(), diff --git a/src/logservice/libobcdc/src/ob_log_part_trans_task.cpp b/src/logservice/libobcdc/src/ob_log_part_trans_task.cpp index b49b1379aa..003d548980 100644 --- a/src/logservice/libobcdc/src/ob_log_part_trans_task.cpp +++ b/src/logservice/libobcdc/src/ob_log_part_trans_task.cpp @@ -2189,6 +2189,7 @@ PartTransTask::PartTransTask() : wait_data_ready_cond_(), wait_formatted_cond_(NULL), output_br_count_by_turn_(0), + tic_update_infos_(), allocator_(), log_entry_task_base_allocator_() { @@ -2324,6 +2325,7 @@ void PartTransTask::reset() is_data_ready_ = false; wait_formatted_cond_ = NULL; output_br_count_by_turn_ = 0; + tic_update_infos_.reset(); // reuse memory allocator_.reset(); log_entry_task_base_allocator_.destroy(); @@ -2802,6 +2804,15 @@ int PartTransTask::check_for_ddl_trans( return ret; } +int PartTransTask::push_tic_update_info(const TICUpdateInfo &tic_update_info) +{ + int ret = OB_SUCCESS; + if (OB_FAIL(tic_update_infos_.push_back(tic_update_info))) { + LOG_ERROR("push tic_update_info failed", KR(ret), K(tic_update_info)); + } + return ret; +} + int PartTransTask::alloc_log_entry_node_(const palf::LSN &lsn, LogEntryNode *&log_entry_node) { int ret = OB_SUCCESS; diff --git a/src/logservice/libobcdc/src/ob_log_part_trans_task.h b/src/logservice/libobcdc/src/ob_log_part_trans_task.h index 70a14b06ca..fb518f9ce3 100644 --- a/src/logservice/libobcdc/src/ob_log_part_trans_task.h +++ b/src/logservice/libobcdc/src/ob_log_part_trans_task.h @@ -41,6 +41,7 @@ #include "ob_cdc_lob_aux_table_schema_info.h" // ObCDCLobAuxTableSchemaInfo #include "lib/allocator/ob_lf_fifo_allocator.h" // ObConcurrentFIFOAllocator #include "ob_log_safe_arena.h" +#include "ob_log_tic_update_info.h" // TICUpdateInfo namespace oceanbase { @@ -1140,6 +1141,16 @@ public: bool &is_not_barrier, ObSchemaOperationType &op_type) const; ObIAllocator &get_log_entry_task_base_allocator() { return log_entry_task_base_allocator_; }; + int push_tic_update_info(const TICUpdateInfo &tic_update_info); + void get_tic_update_info(ObArray &tic_update_infos) const + { + tic_update_infos = tic_update_infos_; + } + + bool need_update_table_id_cache() const + { + return !tic_update_infos_.empty(); + } void set_unserved() { set_unserved_(); } TO_STRING_KV( @@ -1316,6 +1327,8 @@ private: int64_t output_br_count_by_turn_; // sorted br count in each statistic round + ObArray tic_update_infos_; // table id cache update info + // allocator used to alloc: // LogEntryNode/RollbackNode // DdlRedoLogNode/DmlRedoLogNode/mutator_row_data diff --git a/src/logservice/libobcdc/src/ob_log_sequencer1.cpp b/src/logservice/libobcdc/src/ob_log_sequencer1.cpp index 670f10f59c..339e29547f 100644 --- a/src/logservice/libobcdc/src/ob_log_sequencer1.cpp +++ b/src/logservice/libobcdc/src/ob_log_sequencer1.cpp @@ -1066,25 +1066,57 @@ int ObLogSequencer::handle_multi_data_source_info_( } // wait_until_formatter_done_ } } - + bool need_new_schema = false; if (OB_SUCC(ret)) { if (OB_ISNULL(ddl_processor)) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("expect valid ddl_processor", KR(ret)); - } else if (OB_FAIL(ddl_processor->handle_ddl_trans(*part_trans_task, tenant, stop_flag))) { + } else if (OB_FAIL(ddl_processor->handle_ddl_trans(*part_trans_task, tenant, false, stop_flag))) { if (OB_IN_STOP_STATE != ret) { LOG_ERROR("handle_ddl_trans for data_dict mode failed", KR(ret), K(tenant), KPC(part_trans_task)); } - } else if (part_trans_task->get_multi_data_source_info().is_ddl_trans() - && OB_FAIL(handle_ddl_multi_data_source_info_(*part_trans_task, tenant, trans_ctx))) { - LOG_ERROR("handle_ddl_multi_data_source_info_ failed", KR(ret), KPC(part_trans_task), K(trans_ctx), - K(stop_flag)); + } else if (OB_FAIL(need_acquire_new_schema_(*part_trans_task, need_new_schema))) { + LOG_ERROR("execute need_acquire_new_schema_ failed", KR(ret), KPC(part_trans_task)); + } else if (need_new_schema) { + if (part_trans_task->get_multi_data_source_info().is_ddl_trans() + && OB_FAIL(handle_ddl_multi_data_source_info_(*part_trans_task, tenant, trans_ctx))) { + LOG_ERROR("handle_ddl_multi_data_source_info_ failed", KR(ret), KPC(part_trans_task), K(trans_ctx), + K(stop_flag)); + } else if (OB_FAIL(ddl_processor->handle_ddl_trans(*part_trans_task, tenant, true, stop_flag))) { + if (OB_IN_STOP_STATE != ret) { + LOG_ERROR("handle_ddl_trans_update_tic for data_dict mode failed", KR(ret), K(tenant), KPC(part_trans_task)); + } + } else { + LOG_DEBUG("handle_ddl_trans and mds for data_dict mode done", KPC(part_trans_task)); + } } else { - LOG_DEBUG("handle_ddl_trans and mds for data_dict mode done", KPC(part_trans_task)); + if (OB_FAIL(ddl_processor->handle_ddl_trans(*part_trans_task, tenant, true, stop_flag))) { + if (OB_IN_STOP_STATE != ret) { + LOG_ERROR("handle_ddl_trans_update_tic for data_dict mode failed", KR(ret), K(tenant), KPC(part_trans_task)); + } + } else if (part_trans_task->get_multi_data_source_info().is_ddl_trans() + && OB_FAIL(handle_ddl_multi_data_source_info_(*part_trans_task, tenant, trans_ctx))) { + LOG_ERROR("handle_ddl_multi_data_source_info_ failed", KR(ret), KPC(part_trans_task), K(trans_ctx), + K(stop_flag)); + } else { + LOG_DEBUG("handle_ddl_trans and mds for data_dict mode done", KPC(part_trans_task)); + } } } } + if (OB_SUCC(ret) && part_trans_task->is_sys_ls_part_trans() && part_trans_task->need_update_table_id_cache()) { + if (OB_FAIL(wait_until_parser_done_("update_table_id_cache_op", stop_flag))) { + if (OB_IN_STOP_STATE != ret) { + LOG_ERROR("wait_until_parser_done_ failed", KR(ret), KPC(part_trans_task)); + } + } else if (OB_FAIL(update_table_id_cache_(part_mgr, part_trans_task))) { + LOG_ERROR("update table_id_cache failed", KR(ret), KPC(part_trans_task)); + } else { + LOG_INFO("update table_id_cache success", KPC(part_trans_task)); + } + } + if (OB_SUCC(ret)) { part_trans_task = part_trans_task->next_task(); } @@ -1335,6 +1367,85 @@ int ObLogSequencer::do_trans_stat_(const uint64_t tenant_id, return ret; } +int ObLogSequencer::need_acquire_new_schema_(const PartTransTask &task, bool &need_new_schema) +{ + int ret = OB_SUCCESS; + need_new_schema = false; + if (OB_UNLIKELY(! task.is_ddl_trans())) { + ret = OB_INVALID_ARGUMENT; + LOG_ERROR("invalid ddl task which is not DDL trans", KR(ret), K(task)); + } else { + IStmtTask *stmt_task = task.get_stmt_list().head_; + while (NULL != stmt_task && OB_SUCCESS == ret) { + DdlStmtTask *ddl_stmt = dynamic_cast(stmt_task); + if (OB_UNLIKELY(! stmt_task->is_ddl_stmt()) || OB_ISNULL(ddl_stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("invalid DDL statement", KR(ret), KPC(stmt_task), K(ddl_stmt)); + } else if (OB_DDL_CREATE_TABLE == ddl_stmt->get_operation_type() + || OB_DDL_ALTER_TABLE == ddl_stmt->get_operation_type() + || OB_DDL_TABLE_RENAME == ddl_stmt->get_operation_type()) { + need_new_schema = true; + break; + } else { + stmt_task = stmt_task->get_next(); + } + } + } + LOG_INFO("ddl task schema info", KR(ret), K(need_new_schema), K(task)); + return ret; +} + +int ObLogSequencer::update_table_id_cache_(IObLogPartMgr &part_mgr, const PartTransTask *task) +{ + int ret = OB_SUCCESS; + ObArray tic_update_infos; + task->get_tic_update_info(tic_update_infos); + for (int i = 0; OB_SUCC(ret) && i < tic_update_infos.count(); i++) { + const TICUpdateInfo tic_update_info = tic_update_infos[i]; + TICUpdateInfo::TICUpdateReason update_reason = tic_update_info.reason_; + switch (update_reason) { + case TICUpdateInfo::TICUpdateReason::DROP_TABLE: + case TICUpdateInfo::TICUpdateReason::RENAME_TABLE_REMOVE: { + const uint64_t table_id = tic_update_info.table_id_; + const uint64_t database_id = tic_update_info.database_id_; + if (OB_FAIL(part_mgr.delete_table_id_from_cache(table_id))) { + LOG_ERROR("[Sequencer] delete table_id from cache failed", KR(ret), K(tic_update_info)); + } else { + ISTAT("delete table_id from cache success", K(tic_update_info)); + } + break; + } + case TICUpdateInfo::TICUpdateReason::CREATE_TABLE: + case TICUpdateInfo::TICUpdateReason::RENAME_TABLE_ADD: { + const uint64_t table_id = tic_update_info.table_id_; + const uint64_t database_id = tic_update_info.database_id_; + if (OB_FAIL(part_mgr.insert_table_id_into_cache(table_id, database_id))) { + LOG_ERROR("[Sequencer] insert table_id into cache failed", KR(ret), K(tic_update_info)); + } else { + ISTAT("insert table_id into cache success", K(tic_update_info)); + } + break; + } + case TICUpdateInfo::TICUpdateReason::DROP_DATABASE: { + const uint64_t database_id = tic_update_info.database_id_; + if (OB_FAIL(part_mgr.delete_db_from_cache(database_id))) { + LOG_ERROR("[Sequencer] delete db from cache failed", KR(ret), K(tic_update_info)); + } else { + ISTAT("delete db from cache success", K(tic_update_info)); + } + break; + } + default: { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("[Sequencer] invalid tic update reason", KR(ret), K(tic_update_info)); + break; + } + } + } + + return ret; +} + #undef _STAT #undef STAT #undef _ISTAT diff --git a/src/logservice/libobcdc/src/ob_log_sequencer1.h b/src/logservice/libobcdc/src/ob_log_sequencer1.h index cb8a394d1e..d74cda6edf 100644 --- a/src/logservice/libobcdc/src/ob_log_sequencer1.h +++ b/src/logservice/libobcdc/src/ob_log_sequencer1.h @@ -25,6 +25,7 @@ #include "ob_log_trans_redo_dispatcher.h" // ObLogRedoDispatcher #include "ob_log_trans_msg_sorter.h" // ObLogTransMsgSorter #include "ob_log_schema_incremental_replay.h" // ObLogSchemaIncReplay +#include "ob_log_part_mgr.h" // IObLogPartMgr namespace oceanbase { @@ -202,6 +203,8 @@ private: // 1. statistics on transaction tps and rps (rps before and after Formatter filtering) // 2. count tenant rps information int do_trans_stat_(const uint64_t tenant_id, const int64_t total_stmt_cnt); + int need_acquire_new_schema_(const PartTransTask &task, bool &need_new_schema); + int update_table_id_cache_(IObLogPartMgr &part_mgr, const PartTransTask *task); private: bool inited_; diff --git a/src/logservice/libobcdc/src/ob_log_sys_ls_task_handler.cpp b/src/logservice/libobcdc/src/ob_log_sys_ls_task_handler.cpp index ee683fbfc2..1cbc4c7ca3 100644 --- a/src/logservice/libobcdc/src/ob_log_sys_ls_task_handler.cpp +++ b/src/logservice/libobcdc/src/ob_log_sys_ls_task_handler.cpp @@ -380,11 +380,19 @@ int ObLogSysLsTaskHandler::handle_task_(PartTransTask &task, const bool is_ddl_trans = task.is_ddl_trans(); // The following handles DDL transaction tasks and DDL heartbeat tasks // NOTICE: handle_ddl_trans before sequencer when using online_schmea, otherwise(using data_dict) handle_ddl_trans in sequencer. - if (is_ddl_trans && is_using_online_schema && OB_FAIL(ddl_processor_->handle_ddl_trans(task, *tenant, stop_flag_))) { + // First output ddl trans and then update tic + if (task.is_ddl_trans() && is_using_online_schema && OB_FAIL(ddl_processor_->handle_ddl_trans(task, *tenant, + false /* need_update_tic */, stop_flag_))) { if (OB_IN_STOP_STATE != ret) { LOG_ERROR("ddl_processor_ handle_ddl_trans fail", KR(ret), K(task), K(ddl_tenant_id), K(tenant), K(is_tenant_served)); } + } else if (task.is_ddl_trans() && is_using_online_schema && OB_FAIL(ddl_processor_->handle_ddl_trans(task, *tenant, + true /* need_update_tic */, stop_flag_))) { + if (OB_IN_STOP_STATE != ret) { + LOG_ERROR("ddl_processor_ handle_ddl_trans_update_tic fail", KR(ret), K(task), K(ddl_tenant_id), K(tenant), + K(is_tenant_served)); + } } // Both DDL transactions and heartbeats update DDL information else if (OB_FAIL(update_sys_ls_info_(task, *tenant))) { diff --git a/src/logservice/libobcdc/src/ob_log_table_id_cache.cpp b/src/logservice/libobcdc/src/ob_log_table_id_cache.cpp index 7fc6a1cbd9..d9dd24a7b4 100644 --- a/src/logservice/libobcdc/src/ob_log_table_id_cache.cpp +++ b/src/logservice/libobcdc/src/ob_log_table_id_cache.cpp @@ -63,5 +63,10 @@ bool TableInfoEraserByTenant::operator()( return (tenant_id_ == target_tenant_id); } +bool TableInfoEraserByDatabase::operator()(const TableID &table_id_key, uint64_t &val) +{ + return (val == database_id_); +} + } } diff --git a/src/logservice/libobcdc/src/ob_log_table_id_cache.h b/src/logservice/libobcdc/src/ob_log_table_id_cache.h index 85fc36c43f..b8e88419b6 100644 --- a/src/logservice/libobcdc/src/ob_log_table_id_cache.h +++ b/src/logservice/libobcdc/src/ob_log_table_id_cache.h @@ -70,10 +70,21 @@ struct TableInfoEraserByTenant bool operator()(const TableID &table_id_key, TableInfo &tb_info); }; +struct TableInfoEraserByDatabase +{ + uint64_t database_id_; + + explicit TableInfoEraserByDatabase(const uint64_t database_id) + : database_id_(database_id) {} + + bool operator()(const TableID &table_id_key, uint64_t &val); +}; + // Global General Index Cache typedef common::ObLinearHashMap GIndexCache; -// TableIDCache, records master table, unique index table, global unique index table_id, used to filter tables within a partition group -typedef common::ObLinearHashMap TableIDCache; +// TableIDCache, contains the table_id in tb_white_list and not in tb_black_list +// The kv pair is +typedef common::ObLinearHashMap TableIDCache; } } diff --git a/src/logservice/libobcdc/src/ob_log_table_matcher.cpp b/src/logservice/libobcdc/src/ob_log_table_matcher.cpp index 75dcbd85c8..59d8181397 100644 --- a/src/logservice/libobcdc/src/ob_log_table_matcher.cpp +++ b/src/logservice/libobcdc/src/ob_log_table_matcher.cpp @@ -103,7 +103,7 @@ int ObLogTableMatcher::table_match_pattern_(const bool is_black, pattern.table_pattern_.ptr(), tenant_name, db_name, tb_name); } else { - _ISTAT("[%s_PATTERN_NOT_MATCH] PATTERN='%s.%s.%s' TABLE='%s.%s.%s' NOT_MATCH_PATTERN=%s", + _DSTAT("[%s_PATTERN_NOT_MATCH] PATTERN='%s.%s.%s' TABLE='%s.%s.%s' NOT_MATCH_PATTERN=%s", is_black ? "BLACK" : "WHITE", pattern.tenant_pattern_.ptr(), pattern.database_pattern_.ptr(), pattern.table_pattern_.ptr(), @@ -123,6 +123,67 @@ int ObLogTableMatcher::table_match_pattern_(const bool is_black, return ret; } +int ObLogTableMatcher::database_match_pattern_(const bool is_black, + const char *tenant_name, + const char *db_name, + bool &matched, + const int fnmatch_flags) +{ + int ret = OB_SUCCESS; + + if (OB_ISNULL(tenant_name) || OB_ISNULL(db_name)) { + ret = OB_INVALID_ARGUMENT; + OBLOG_LOG(ERROR, "invalid arguments", KR(ret), K(tenant_name), K(db_name)); + } else { + PatternArray *ptns = is_black ? &black_patterns_ : &patterns_; + + matched = false; + + for (int64_t idx = 0, cnt = ptns->count(); OB_SUCCESS == ret && !matched && idx < cnt; ++idx) { + const Pattern &pattern = ptns->at(idx); + int err = 0; + const char *not_match_part = "UNKNOW"; + // Tenant name. + if (0 != (err = fnmatch(pattern.tenant_pattern_.ptr(), + tenant_name, + fnmatch_flags))) { + // Not matched. + not_match_part = "TENANT_PATTERN"; + } + // Database name. + else if (0 != (err = fnmatch(pattern.database_pattern_.ptr(), + db_name, + fnmatch_flags))) { + // Not matched. + not_match_part = "DATABASE_PATTERN"; + } else { + matched = true; + } + + if (matched) { + _ISTAT("[%s_PATTERN_MATCHED] PATTERN='%s.%s' DATABASE='%s.%s'", + is_black ? "BLACK" : "WHITE", + pattern.tenant_pattern_.ptr(), pattern.database_pattern_.ptr(), + tenant_name, db_name); + } else { + _DSTAT("[%s_PATTERN_NOT_MATCH] PATTERN='%s.%s' DATABASE='%s.%s' NOT_MATCH_PATTERN=%s", + is_black ? "BLACK" : "WHITE", + pattern.tenant_pattern_.ptr(), pattern.database_pattern_.ptr(), + tenant_name, db_name, + not_match_part); + } + + // fnmatch() err. + // OB_SUCCESS == 0. + if (OB_SUCCESS != err && FNM_NOMATCH != err) { + ret = OB_ERR_UNEXPECTED; + OBLOG_LOG(ERROR, "err exec fnmatch", KR(ret), K(err)); + } + } + } + return ret; +} + int ObLogTableMatcher::tenant_match_pattern_(const bool is_black, const char* tenant_name, bool& matched, @@ -181,7 +242,7 @@ int ObLogTableMatcher::tenant_match_pattern_(const bool is_black, is_black ? "BLACK" : "WHITE", pattern.tenant_pattern_.ptr(), tenant_name); } else { - _ISTAT("[%s_PATTERN_NOT_MATCH] PATTERN='%s' TENANT='%s'", + _DSTAT("[%s_PATTERN_NOT_MATCH] PATTERN='%s' TENANT='%s'", is_black ? "BLACK" : "WHITE", pattern.tenant_pattern_.ptr(), tenant_name); } @@ -231,6 +292,37 @@ int ObLogTableMatcher::table_match(const char* tenant_name, return ret; } +int ObLogTableMatcher::database_match(const char *tenant_name, + const char *db_name, + bool &matched, + const int fnmatch_flags) +{ + int ret = OB_SUCCESS; + bool white_matched = false; + bool black_matched = false; + + matched = false; + + // First filter by whitelist, if whitelist matches, match blacklist + if (OB_FAIL(database_match_pattern_(false, tenant_name, db_name, white_matched, fnmatch_flags))) { + OBLOG_LOG(ERROR, "match white pattern fail", KR(ret), K(tenant_name), K(db_name), + K(white_matched), K(fnmatch_flags)); + } else if (white_matched && OB_FAIL(database_match_pattern_(true, tenant_name, db_name, + black_matched, fnmatch_flags))) { + OBLOG_LOG(ERROR, "match black pattern fail", KR(ret), K(tenant_name), K(db_name), + K(white_matched), K(fnmatch_flags)); + } else { + matched = (white_matched && ! black_matched); + _ISTAT("[%sDATABASE_PATTERNS_MATCHED] DATABASE='%s.%s' WHITE_PATTERN_COUNT=%ld " + "BLACK_PATTERN_COUNT=%ld WHITE_MATCHED=%d BLACK_MATCHED=%d", + matched ? "" : "NO_", + tenant_name, db_name, patterns_.count(), black_patterns_.count(), + white_matched, black_matched); + } + + return ret; +} + int ObLogTableMatcher::tenant_match(const char* tenant_name, bool& matched, const int fnmatch_flags) diff --git a/src/logservice/libobcdc/src/ob_log_table_matcher.h b/src/logservice/libobcdc/src/ob_log_table_matcher.h index da1983338c..5bfebd728e 100644 --- a/src/logservice/libobcdc/src/ob_log_table_matcher.h +++ b/src/logservice/libobcdc/src/ob_log_table_matcher.h @@ -49,6 +49,20 @@ public: bool &matched, const int fntatch_flags) = 0; + /// check database match + /// + /// @param [in] tenant_name tenant name + /// @param [in] db_name database name + /// @param [out] matched is matched or not + /// @param [in] fnmatch_flags fnmatch flags + /// + /// @retval OB_SUCCESS Success + /// @retval Other error codes Fail + virtual int database_match(const char *tenant_name, + const char *db_name, + bool &matched, + const int fnmatch_flags) = 0; + /// check tenant match /// /// @param [in] tenant_name tenant name @@ -102,6 +116,11 @@ public: bool &matched, const int fnmatch_flags); + int database_match(const char *tenant_name, + const char *db_name, + bool &matched, + const int fnmatch_flags); + int tenant_match(const char *tenant_name, bool &matched, const int fnmatch_flags = FNM_CASEFOLD); @@ -138,6 +157,12 @@ private: bool& matched, const int fnmatch_flags); + int database_match_pattern_(const bool is_black, + const char *tenant_name, + const char *db_name, + bool &matched, + const int fnmatch_flags); + int tenant_match_pattern_(const bool is_black, const char* tenant_name, bool& matched, diff --git a/src/logservice/libobcdc/src/ob_log_tenant.cpp b/src/logservice/libobcdc/src/ob_log_tenant.cpp index adcfa2540d..1b0f0fcdb7 100644 --- a/src/logservice/libobcdc/src/ob_log_tenant.cpp +++ b/src/logservice/libobcdc/src/ob_log_tenant.cpp @@ -25,6 +25,7 @@ #include "ob_log_timezone_info_getter.h" // ObCDCTimeZoneInfoGetter #include "ob_log_start_schema_matcher.h" // ObLogStartSchemaMatcher +#include "ob_log_schema_getter.h" // ObLogSchemaGuard #include "ob_log_store_service.h" // IObLogStoreService #define STAT(level, tag_str, args...) OBLOG_LOG(level, "[STAT] [TENANT] " tag_str, ##args) @@ -41,6 +42,7 @@ namespace libobcdc ObLogTenant::ObLogTenant() : inited_(false), tenant_id_(OB_INVALID_TENANT_ID), + compat_mode_(lib::Worker::CompatMode::INVALID), start_schema_version_(OB_INVALID_VERSION), task_queue_(NULL), ls_mgr_(*this), @@ -102,9 +104,13 @@ int ObLogTenant::init( } else if (OB_FAIL(ls_mgr_.init(tenant_id, start_schema_version, tenant_mgr.ls_info_map_, tenant_mgr.ls_add_cb_array_, tenant_mgr.ls_rc_cb_array_))) { LOG_ERROR("ls_mgr_ init fail", KR(ret), K(tenant_id_), K(start_schema_version)); - } else if (OB_FAIL(part_mgr_.init(tenant_id, start_schema_version, tenant_mgr.enable_oracle_mode_match_case_sensitive_, - tenant_mgr.gindex_cache_, tenant_mgr.table_id_cache_))) { - LOG_ERROR("part_mgr_ init fail", KR(ret), K(tenant_id), K(start_schema_version)); + } else if (OB_FAIL(init_compat_mode_(tenant_id, start_schema_version, compat_mode_))) { + LOG_ERROR("get compat_mode failed", KR(ret), K(tenant_id), K(start_schema_version)); + } else if (OB_FAIL(part_mgr_.init(tenant_id, start_schema_version, + tenant_mgr.enable_oracle_mode_match_case_sensitive_, + tenant_mgr.enable_white_black_list_, + tenant_mgr.gindex_cache_))) { + LOG_ERROR("part_mgr_ init fail", KR(ret), K(tenant_id), K(start_schema_version)); } else if (OB_FAIL(databuff_printf(tenant_name_, sizeof(tenant_name_), pos, "%s", tenant_name))) { LOG_ERROR("print tenant name fail", KR(ret), K(pos), K(tenant_id), K(tenant_name)); } else if (OB_FAIL(TCTX.timezone_info_getter_->init_tenant_tz_info(tenant_id))) { @@ -143,13 +149,55 @@ int ObLogTenant::init( inited_ = true; - LOG_INFO("init tenant succ", K(tenant_id), K(tenant_name), K(start_schema_version), + LOG_INFO("init tenant succ", K(tenant_id), K(tenant_name), K_(compat_mode), K(start_schema_version), K(start_tstamp_ns), K(start_seq)); } return ret; } +int ObLogTenant::init_compat_mode_(const uint64_t tenant_id, const int64_t start_schema_version, + lib::Worker::CompatMode &compat_mode) +{ + int ret = OB_SUCCESS; + if (is_online_refresh_mode(TCTX.refresh_mode_)) { + IObLogSchemaGetter *schema_getter = TCTX.schema_getter_; + ObLogSchemaGuard schema_guard; + if (OB_FAIL(schema_getter->get_lazy_schema_guard(tenant_id, start_schema_version, + DATA_OP_TIMEOUT, schema_guard))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get lazy schema_guard failed", KR(ret), K(tenant_id), K(start_schema_version)); + } + } else if (OB_FAIL(schema_guard.get_tenant_compat_mode(tenant_id, compat_mode, DATA_OP_TIMEOUT))) { + if (OB_TIMEOUT != ret) { + LOG_ERROR("get tenant_compat_mode failed", KR(ret), K(tenant_id)); + } + } + } else { + ObDictTenantInfoGuard dict_tenant_info_guard; + ObDictTenantInfo *tenant_info = nullptr; + common::ObCompatibilityMode compatible_mode = common::ObCompatibilityMode::OCEANBASE_MODE; + if (OB_FAIL(GLOGMETADATASERVICE.get_tenant_info_guard(tenant_id, dict_tenant_info_guard))) { + LOG_ERROR("get_tenant_info_guard failed", KR(ret), K(tenant_id)); + } else if (OB_ISNULL(tenant_info = dict_tenant_info_guard.get_tenant_info())) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("tenant_info is nullptr", KR(ret), K(tenant_id)); + } else { + compatible_mode = tenant_info->get_compatibility_mode(); + } + + if (common::ObCompatibilityMode::MYSQL_MODE == compatible_mode) { + compat_mode = lib::Worker::CompatMode::MYSQL; + } else if (common::ObCompatibilityMode::ORACLE_MODE == compatible_mode) { + compat_mode = lib::Worker::CompatMode::ORACLE; + } else { + compat_mode = lib::Worker::CompatMode::INVALID; + } + } + LOG_INFO("init compat_mode success", K(tenant_id), K(start_schema_version), K(compat_mode)); + return ret; +} + int ObLogTenant::init_all_ddl_operation_table_schema_info_() { int ret = OB_SUCCESS; @@ -174,6 +222,8 @@ void ObLogTenant::reset() tenant_id_ = OB_INVALID_TENANT_ID; tenant_name_[0] = '\0'; + compat_mode_ = lib::Worker::CompatMode::INVALID; + start_schema_version_ = OB_INVALID_VERSION; if (NULL != task_queue_) { diff --git a/src/logservice/libobcdc/src/ob_log_tenant.h b/src/logservice/libobcdc/src/ob_log_tenant.h index ad69a72cb8..288090bdd3 100644 --- a/src/logservice/libobcdc/src/ob_log_tenant.h +++ b/src/logservice/libobcdc/src/ob_log_tenant.h @@ -24,6 +24,7 @@ #include "ob_log_ls_mgr.h" // ObLogLSMgr #include "ob_log_ref_state.h" // RefState #include "ob_cdc_lob_aux_meta_storager.h" // ObCDCLobAuxDataCleanTask +#include "ob_log_meta_data_struct.h" // ObDictTenantInfo #include namespace oceanbase @@ -105,6 +106,7 @@ public: // get/set functions public: uint64_t get_tenant_id() const { return tenant_id_; } + lib::Worker::CompatMode get_compat_mode() const { return compat_mode_; } int64_t get_start_schema_version() const { return start_schema_version_; } int64_t get_schema_version() const { return part_mgr_.get_schema_version(); } int64_t get_sys_ls_progress() const { return ATOMIC_LOAD(&sys_ls_progress_); } @@ -222,23 +224,24 @@ public: const int64_t start_schema_version, const int64_t timeout); - int add_all_user_tablets_info(const int64_t timeout) - { - return part_mgr_.add_all_user_tablets_info(timeout); - } - - int add_all_user_tablets_info( - const ObIArray &table_metas, - const int64_t timeout) - { - return part_mgr_.add_all_user_tablets_info(table_metas, timeout); - } - int get_table_info_of_tablet(const common::ObTabletID &tablet_id, ObCDCTableInfo &table_info) const { return part_mgr_.get_table_info_of_tablet_id(tablet_id, table_info); } + int add_all_user_tablets_and_tables_info(const int64_t timeout) + { + return part_mgr_.add_all_user_tablets_and_tables_info(timeout); + } + + int add_all_user_tablets_and_tables_info( + ObDictTenantInfo *tenant_info, + const ObIArray &table_metas, + const int64_t timeout) + { + return part_mgr_.add_all_user_tablets_and_tables_info(tenant_info, table_metas, timeout); + } + // flush memory data in local storage(e.g. memtable for rocksdb) void flush_storage(); @@ -261,6 +264,8 @@ public: bool is_serving() const { return TENANT_STATE_NORMAL == get_tenant_state(); } private: + int init_compat_mode_(const uint64_t tenant_id, const int64_t start_schema_version, + lib::Worker::CompatMode &compat_mode); int init_all_ddl_operation_table_schema_info_(); int update_sys_ls_progress_( const int64_t handle_progress, @@ -292,6 +297,7 @@ private: bool inited_; uint64_t tenant_id_; char tenant_name_[common::OB_MAX_TENANT_NAME_LENGTH + 1]; + lib::Worker::CompatMode compat_mode_; int64_t start_schema_version_; // task queue ObLogTenantTaskQueue *task_queue_; diff --git a/src/logservice/libobcdc/src/ob_log_tenant_mgr.cpp b/src/logservice/libobcdc/src/ob_log_tenant_mgr.cpp index 33c1084a3a..9af3f82eea 100644 --- a/src/logservice/libobcdc/src/ob_log_tenant_mgr.cpp +++ b/src/logservice/libobcdc/src/ob_log_tenant_mgr.cpp @@ -51,7 +51,8 @@ ObLogTenantMgr::ObLogTenantMgr() : ls_rc_cb_array_(), tenant_id_set_(), ls_getter_(), - enable_oracle_mode_match_case_sensitive_(false) + enable_oracle_mode_match_case_sensitive_(false), + enable_white_black_list_(true) { } @@ -62,6 +63,7 @@ ObLogTenantMgr::~ObLogTenantMgr() int ObLogTenantMgr::init( const bool enable_oracle_mode_match_case_sensitive, + const bool enable_white_black_list, const RefreshMode &refresh_mode) { int ret = OB_SUCCESS; @@ -87,8 +89,10 @@ int ObLogTenantMgr::init( inited_ = true; refresh_mode_ = refresh_mode; enable_oracle_mode_match_case_sensitive_ = enable_oracle_mode_match_case_sensitive; + enable_white_black_list_ = enable_white_black_list; LOG_INFO("ObLogTenantMgr init succ", K(enable_oracle_mode_match_case_sensitive_), + K(enable_white_black_list_), "refresh_mode", print_refresh_mode(refresh_mode_)); } @@ -114,6 +118,7 @@ void ObLogTenantMgr::destroy() tenant_id_set_.destroy(); ls_getter_.destroy(); enable_oracle_mode_match_case_sensitive_ = false; + enable_white_black_list_ = true; LOG_INFO("ObLogTenantMgr destroy succ"); } @@ -423,8 +428,8 @@ int ObLogTenantMgr::start_tenant_service_( } else { // Note: The sys tenant does not have data dictionary data if (is_online_refresh_mode(refresh_mode_) || OB_SYS_TENANT_ID == tenant_id) { - if (OB_FAIL(tenant->add_all_user_tablets_info(timeout))) { - LOG_ERROR("add_all_user_tablets_info failed", KR(ret), KPC(tenant), K(timeout)); + if (OB_FAIL(tenant->add_all_user_tablets_and_tables_info(timeout))) { + LOG_ERROR("add all user tablets and tables failed", KR(ret), KPC(tenant), K(timeout)); } // get ls ids when is not normal new created tenant @@ -448,8 +453,8 @@ int ObLogTenantMgr::start_tenant_service_( LOG_ERROR("tenant_info is nullptr", K(tenant_id)); } else if (OB_FAIL(tenant_info->get_table_metas_in_tenant(table_metas))) { LOG_ERROR("tenant_info get_table_metas_in_tenant failed", KR(ret), K(tenant_id)); - } else if (OB_FAIL(tenant->add_all_user_tablets_info(table_metas, timeout))) { - LOG_ERROR("add_all_user_tablets_info failed", KR(ret), K(tenant_id), K(table_metas)); + } else if (OB_FAIL(tenant->add_all_user_tablets_and_tables_info(tenant_info, table_metas, timeout))) { + LOG_ERROR("add all user tablets and tables failed", KR(ret), KPC(tenant_info), K(timeout)); } // get ls ids when is not normal new created tenant diff --git a/src/logservice/libobcdc/src/ob_log_tenant_mgr.h b/src/logservice/libobcdc/src/ob_log_tenant_mgr.h index 790271ede3..f435536773 100644 --- a/src/logservice/libobcdc/src/ob_log_tenant_mgr.h +++ b/src/logservice/libobcdc/src/ob_log_tenant_mgr.h @@ -177,7 +177,9 @@ public: virtual ~ObLogTenantMgr(); public: - int init(const bool enable_oracle_mode_match_case_sensitive, const RefreshMode &refresh_mode); + int init(const bool enable_oracle_mode_match_case_sensitive, + const bool enable_white_black_list, + const RefreshMode &refresh_mode); void destroy(); int register_ls_add_callback(LSAddCallback *callback); @@ -437,6 +439,7 @@ private: ObLogLsGetter ls_getter_; bool enable_oracle_mode_match_case_sensitive_; + bool enable_white_black_list_; private: DISALLOW_COPY_AND_ASSIGN(ObLogTenantMgr); }; diff --git a/src/logservice/libobcdc/src/ob_log_tic_update_info.cpp b/src/logservice/libobcdc/src/ob_log_tic_update_info.cpp new file mode 100644 index 0000000000..8a834491eb --- /dev/null +++ b/src/logservice/libobcdc/src/ob_log_tic_update_info.cpp @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * + * TableIdCache update info data struct in OBCDC + */ + +#define USING_LOG_PREFIX OBLOG + +#include "ob_log_tic_update_info.h" + +using namespace oceanbase::common; +namespace oceanbase +{ +namespace libobcdc +{ + +void TICUpdateInfo::reset() +{ + reason_ = TICUpdateReason::INVALID_REASON; + database_id_ = OB_INVALID_ID; + table_id_ = OB_INVALID_ID; +} + +bool TICUpdateInfo::is_valid() const +{ + return reason_ != TICUpdateReason::INVALID_REASON && (database_id_ != OB_INVALID_ID + || table_id_ != OB_INVALID_ID); +} + +const char *TICUpdateInfo::print_tic_update_reason(const TICUpdateReason reason) +{ + const char *reason_str = "INVALID"; + switch (reason) { + case INVALID_REASON: + reason_str = "INVALID"; + break; + + case DROP_TABLE: + reason_str = "DROP_TABLE"; + break; + + case CREATE_TABLE: + reason_str = "CREATE_TABLE"; + break; + + case RENAME_TABLE_ADD: + reason_str = "RENAME_TABLE_ADD"; + break; + + case RENAME_TABLE_REMOVE: + reason_str = "RENAME_TABLE_REMOVE"; + break; + + case DROP_DATABASE: + reason_str = "DROP_DATABASE"; + break; + + default: + reason_str = "INVALID"; + break; + } + + return reason_str; +} +} +} \ No newline at end of file diff --git a/src/logservice/libobcdc/src/ob_log_tic_update_info.h b/src/logservice/libobcdc/src/ob_log_tic_update_info.h new file mode 100644 index 0000000000..d80596eebb --- /dev/null +++ b/src/logservice/libobcdc/src/ob_log_tic_update_info.h @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + * + * TableIdCache update info data struct in OBCDC + */ + +#ifndef OCEANBASE_LIBOBCDC_TIC_UPDATE_INFO_H__ +#define OCEANBASE_LIBOBCDC_TIC_UPDATE_INFO_H__ + +#include +#include "lib/utility/ob_print_utils.h" + +namespace oceanbase +{ +namespace libobcdc +{ + +// TIC is TableIdCache, contains the table_id in tb_white_list and not in tb_black_list +// TICUpdateInfo is the update info which TIC should update +struct TICUpdateInfo +{ + enum TICUpdateReason + { + INVALID_REASON = -1, + DROP_TABLE = 0, + CREATE_TABLE = 1, + RENAME_TABLE_ADD = 2, + RENAME_TABLE_REMOVE = 3, + DROP_DATABASE = 4, + }; + static const char *print_tic_update_reason(const TICUpdateReason reason); + TICUpdateReason reason_; + uint64_t database_id_; + uint64_t table_id_; + + TICUpdateInfo() + { + reset(); + } + TICUpdateInfo(const TICUpdateReason reason, + const uint64_t database_id, + const uint64_t table_id) : + reason_(reason), database_id_(database_id), table_id_(table_id) {} + TICUpdateInfo(const TICUpdateReason reason, const uint64_t database_id) : + TICUpdateInfo(reason, database_id, OB_INVALID_ID) {} + ~TICUpdateInfo() + { + reset(); + } + void reset(); + bool is_valid() const; + TO_STRING_KV("tic_update_reason", print_tic_update_reason(reason_), K_(database_id), K_(table_id)); +}; + +} +} + +#endif \ No newline at end of file diff --git a/src/logservice/libobcdc/src/ob_log_utils.cpp b/src/logservice/libobcdc/src/ob_log_utils.cpp index b5bd24992d..47d22077d0 100644 --- a/src/logservice/libobcdc/src/ob_log_utils.cpp +++ b/src/logservice/libobcdc/src/ob_log_utils.cpp @@ -607,6 +607,14 @@ bool is_lob_type(const int ctype) return bool_ret; } +bool is_string_type(const int ctype) +{ + return (ctype == oceanbase::obmysql::MYSQL_TYPE_VAR_STRING || + ctype == oceanbase::obmysql::MYSQL_TYPE_STRING || + ctype == oceanbase::obmysql::MYSQL_TYPE_OB_NCHAR || + ctype == oceanbase::obmysql::MYSQL_TYPE_OB_NVARCHAR2); +} + bool is_json_type(const int ctype) { return (oceanbase::obmysql::MYSQL_TYPE_JSON == ctype); diff --git a/src/logservice/libobcdc/src/ob_log_utils.h b/src/logservice/libobcdc/src/ob_log_utils.h index d914771f66..388b4ec3b1 100644 --- a/src/logservice/libobcdc/src/ob_log_utils.h +++ b/src/logservice/libobcdc/src/ob_log_utils.h @@ -246,6 +246,7 @@ const char *print_table_status(int status); const char *print_compat_mode(const lib::Worker::CompatMode &compat_mode); const char *get_ctype_string(int ctype); bool is_lob_type(const int ctype); +bool is_string_type(const int ctype); bool is_json_type(const int ctype); bool is_geometry_type(const int ctype); bool is_xml_type(const int ctype); diff --git a/src/logservice/libobcdc/tests/ob_binlog_record_printer.cpp b/src/logservice/libobcdc/tests/ob_binlog_record_printer.cpp index 688c9ff2da..2a1bdb0348 100644 --- a/src/logservice/libobcdc/tests/ob_binlog_record_printer.cpp +++ b/src/logservice/libobcdc/tests/ob_binlog_record_printer.cpp @@ -548,10 +548,17 @@ int ObBinlogRecordPrinter::output_data_file_column_data(IBinlogRecord *br, bool is_generate_dep_column = col_meta ? col_meta->isDependent() : false; bool is_lob = is_lob_type(ctype); bool is_json = is_json_type(ctype); + bool is_string = is_string_type(ctype); ObArenaAllocator str_allocator; ObStringBuffer enum_set_values_str(&str_allocator); bool is_geometry = is_geometry_type(ctype); bool is_xml = is_xml_type(ctype); + constexpr int64_t string_print_md5_threshold = 4L << 10; + const bool is_type_for_md5_printing = is_lob || is_json || is_geometry || is_xml || + (is_string && col_data_length >= string_print_md5_threshold); + // TODO 止尘 patch the code + // bool is_json_diff = br->isJsonDiffColVal(cname); + bool is_json_diff = false; int64_t column_index = index + 1; ROW_PRINTF(ptr, size, pos, ri, "[C%ld] column_name:%s", column_index, cname); @@ -616,8 +623,7 @@ int ObBinlogRecordPrinter::output_data_file_column_data(IBinlogRecord *br, if (index < new_cols_count) { const char *new_col_value = new_cols[index].buf; size_t new_col_value_len = new_cols[index].buf_used_size; - - if ((is_lob || is_json || is_geometry || is_xml) && enable_print_lob_md5) { + if (is_type_for_md5_printing && enable_print_lob_md5) { ROW_PRINTF(ptr, size, pos, ri, "[C%ld] column_value_new_md5:[%s](%ld)", column_index, calc_md5_cstr(new_col_value, new_col_value_len), new_col_value_len); } else { @@ -648,7 +654,7 @@ int ObBinlogRecordPrinter::output_data_file_column_data(IBinlogRecord *br, if (OB_SUCCESS == ret && OB_FAIL(print_hex(old_col_value, old_col_value_len, ptr, size, pos))) { LOG_ERROR("print_hex fail", K(ret)); } - } else if ((is_lob || is_json || is_geometry || is_xml) && enable_print_lob_md5) { + } else if (is_type_for_md5_printing && enable_print_lob_md5) { ROW_PRINTF(ptr, size, pos, ri, "[C%ld] column_value_old_md5:[%s](%ld)", column_index, calc_md5_cstr(old_col_value, old_col_value_len), old_col_value_len); } else { diff --git a/src/logservice/logfetcher/ob_log_fetch_log_rpc.h b/src/logservice/logfetcher/ob_log_fetch_log_rpc.h index 79e072256e..efeb910448 100644 --- a/src/logservice/logfetcher/ob_log_fetch_log_rpc.h +++ b/src/logservice/logfetcher/ob_log_fetch_log_rpc.h @@ -503,9 +503,9 @@ public: class FetchLogARpcResultPool : public IFetchLogARpcResultPool { typedef common::ObSmallObjPool ResultPool; - // 16M + // 18M public: - static const int64_t DEFAULT_RESULT_POOL_BLOCK_SIZE = (1 << 24L) + (1 << 20L); + static const int64_t DEFAULT_RESULT_POOL_BLOCK_SIZE = (1 << 24L) + (1 << 21L); public: FetchLogARpcResultPool() : inited_(false), pool_() {} diff --git a/src/logservice/logfetcher/ob_log_fetcher_switch_info.cpp b/src/logservice/logfetcher/ob_log_fetcher_switch_info.cpp index 72aac2a09e..02aeb24e11 100644 --- a/src/logservice/logfetcher/ob_log_fetcher_switch_info.cpp +++ b/src/logservice/logfetcher/ob_log_fetcher_switch_info.cpp @@ -56,6 +56,10 @@ const char *print_switch_reason(const KickOutReason reason) str = "Discarded"; break; + case ARCHIVE_ITER_END_BUT_LS_NOT_EXIST_IN_PALF: + str = "ARCHIVE_ITER_END_BUT_LS_NOT_EXIST_IN_PALF"; + break; + default: str = "NONE"; break; diff --git a/src/logservice/logfetcher/ob_log_ls_fetch_stream.cpp b/src/logservice/logfetcher/ob_log_ls_fetch_stream.cpp index 9d9a0ae256..7b947da7f4 100644 --- a/src/logservice/logfetcher/ob_log_ls_fetch_stream.cpp +++ b/src/logservice/logfetcher/ob_log_ls_fetch_stream.cpp @@ -1477,19 +1477,19 @@ KickOutReason FetchStream::get_feedback_reason_(const Feedback &feedback) const // Get KickOutReason based on feedback KickOutReason reason = NONE; switch (feedback) { - case ObCdcLSFetchLogResp::LAGGED_FOLLOWER: + case FeedbackType::LAGGED_FOLLOWER: reason = LAGGED_FOLLOWER; break; - case ObCdcLSFetchLogResp::LOG_NOT_IN_THIS_SERVER: + case FeedbackType::LOG_NOT_IN_THIS_SERVER: reason = LOG_NOT_IN_THIS_SERVER; break; - case ObCdcLSFetchLogResp::LS_OFFLINED: + case FeedbackType::LS_OFFLINED: reason = LS_OFFLINED; break; - case ObCdcLSFetchLogResp::ARCHIVE_ITER_END_BUT_LS_NOT_EXIST_IN_PALF: + case FeedbackType::ARCHIVE_ITER_END_BUT_LS_NOT_EXIST_IN_PALF: reason = ARCHIVE_ITER_END_BUT_LS_NOT_EXIST_IN_PALF; break; diff --git a/src/logservice/logfetcher/ob_log_ls_fetch_stream.h b/src/logservice/logfetcher/ob_log_ls_fetch_stream.h index 1525e00275..1713e8de9f 100644 --- a/src/logservice/logfetcher/ob_log_ls_fetch_stream.h +++ b/src/logservice/logfetcher/ob_log_ls_fetch_stream.h @@ -53,7 +53,7 @@ private: static const int64_t STAT_INTERVAL = 30 * _SEC_; static const int64_t DEFAULT_TASK_SET_SIZE = 16; - typedef obrpc::ObCdcLSFetchLogResp::FeedbackType Feedback; + typedef obrpc::FeedbackType Feedback; // Class global variables public: diff --git a/src/logservice/ob_locality_adapter.cpp b/src/logservice/ob_locality_adapter.cpp new file mode 100644 index 0000000000..6415188e8a --- /dev/null +++ b/src/logservice/ob_locality_adapter.cpp @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#include "ob_locality_adapter.h" +#include "storage/ob_locality_manager.h" + +namespace oceanbase +{ +namespace logservice +{ + +ObLocalityAdapter::ObLocalityAdapter() : + is_inited_(false), + locality_manager_(NULL) + {} + +ObLocalityAdapter::~ObLocalityAdapter() +{ + destroy(); +} + +int ObLocalityAdapter::init(storage::ObLocalityManager *locality_manager) +{ + int ret = OB_SUCCESS; + if (IS_INIT) { + ret = OB_INIT_TWICE; + CLOG_LOG(WARN, "ObLocalityAdapter init twice"); + } else if (OB_ISNULL(locality_manager)) { + ret = OB_INVALID_ARGUMENT; + CLOG_LOG(WARN, "invalid arguments", KP(locality_manager)); + } else { + locality_manager_ = locality_manager; + is_inited_ = true; + PALF_LOG(INFO, "ObLocalityAdapter init success", K(locality_manager_)); + } + return ret; +} + +void ObLocalityAdapter::destroy() +{ + is_inited_ = false; + locality_manager_ = NULL; +} + +int ObLocalityAdapter::get_server_region(const common::ObAddr &server, + common::ObRegion ®ion) const +{ + int ret = OB_SUCCESS; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + } else if (OB_FAIL(locality_manager_->get_server_region(server, region))) { + CLOG_LOG(WARN, "get_server_region failed", K(server)); + } + return ret; +} + +} // end namespace logservice +} // end namespace oceanbase diff --git a/src/logservice/ob_locality_adapter.h b/src/logservice/ob_locality_adapter.h new file mode 100644 index 0000000000..767581f78f --- /dev/null +++ b/src/logservice/ob_locality_adapter.h @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef OCEANBASE_LOGSERVICE_OB_LOCALITY_ADAPTER_H_ +#define OCEANBASE_LOGSERVICE_OB_LOCALITY_ADAPTER_H_ + +#include +#include "logservice/palf/palf_callback.h" +#include "lib/net/ob_addr.h" + +namespace oceanbase +{ +namespace storage +{ +class ObLocalityManager; +} +namespace logservice +{ +class ObLocalityAdapter : public palf::PalfLocalityInfoCb +{ +public: + ObLocalityAdapter(); + virtual ~ObLocalityAdapter(); + int init(storage::ObLocalityManager *locality_manager); + void destroy(); +public: + int get_server_region(const common::ObAddr &server, common::ObRegion ®ion) const override final; +private: + bool is_inited_; + storage::ObLocalityManager *locality_manager_; +}; + +} // logservice +} // oceanbase + +#endif diff --git a/src/logservice/ob_log_handler.cpp b/src/logservice/ob_log_handler.cpp index 49e5ff6d8c..412fcf2dc3 100755 --- a/src/logservice/ob_log_handler.cpp +++ b/src/logservice/ob_log_handler.cpp @@ -212,55 +212,34 @@ int ObLogHandler::append(const void *buffer, SCN &scn) { int ret = OB_SUCCESS; - int64_t wait_times = 0; - PalfAppendOptions opts; - opts.need_nonblock = need_nonblock; - opts.need_check_proposal_id = true; - ObTimeGuard tg("ObLogHandler::append", 100000); - while (true) { - // generate opts - opts.proposal_id = ATOMIC_LOAD(&proposal_id_); - do { - RLockGuard guard(lock_); - CriticalGuard(ls_qs_); - cb->set_append_start_ts(ObTimeUtility::fast_current_time()); - if (IS_NOT_INIT) { - ret = OB_NOT_INIT; - } else if (is_in_stop_state_ || is_offline_) { - ret = OB_NOT_RUNNING; - } else if (LEADER != ATOMIC_LOAD(&role_)) { - ret = OB_NOT_MASTER; - } else if (OB_FAIL(palf_handle_.append(opts, buffer, nbytes, ref_scn, lsn, scn))) { - if (REACH_TIME_INTERVAL(1*1000*1000)) { - CLOG_LOG(WARN, "palf_handle_ append failed", K(ret), KPC(this)); - } - } else { - cb->set_append_finish_ts(ObTimeUtility::fast_current_time()); - cb->__set_lsn(lsn); - cb->__set_scn(scn); - ret = apply_status_->push_append_cb(cb); - CLOG_LOG(TRACE, "palf_handle_ push_append_cb success", K(lsn), K(scn), K(ret), K(id_)); - } - } while (0); - // check if need wait and retry append - if (opts.need_nonblock) { - // nonblock mode, end loop - break; - } else if (OB_EAGAIN == ret) { - // block mode, need sleep and retry for -4023 ret code - static const int64_t MAX_SLEEP_US = 100; - ++wait_times; - int64_t sleep_us = wait_times * 10; - if (sleep_us > MAX_SLEEP_US) { - sleep_us = MAX_SLEEP_US; - } - ob_usleep(sleep_us); - } else { - // other ret code, end loop - break; - } + if (nbytes > MAX_NORMAL_LOG_BODY_SIZE) { + ret = OB_INVALID_ARGUMENT; + CLOG_LOG(WARN, "nbytes is greater than expected size", K(nbytes), K(MAX_NORMAL_LOG_BODY_SIZE)); + } else if (OB_FAIL(append_(buffer, nbytes, ref_scn, need_nonblock, cb, lsn, scn))) { + CLOG_LOG(WARN, "appending log fails", K(ret), + K(buffer), K(nbytes), K(ref_scn), K(need_nonblock), K(lsn), K(scn)); } - append_cost_stat_.stat(tg.get_diff()); + + return ret; +} + +int ObLogHandler::append_big_log(const void *buffer, + const int64_t nbytes, + const SCN &ref_scn, + const bool need_nonblock, + AppendCb *cb, + LSN &lsn, + SCN &scn) +{ + int ret = OB_SUCCESS; + if (nbytes <= MAX_NORMAL_LOG_BODY_SIZE) { + ret = OB_INVALID_ARGUMENT; + CLOG_LOG(WARN, "nbytes is smaller than expected size", K(nbytes), K(MAX_NORMAL_LOG_BODY_SIZE)); + } else if (OB_FAIL(append_(buffer, nbytes, ref_scn, need_nonblock, cb, lsn, scn))) { + CLOG_LOG(WARN, "append big log to palf failed", K(ret), + K(buffer), K(nbytes), K(ref_scn), K(need_nonblock), K(lsn), K(scn)); + } + return ret; } @@ -1321,6 +1300,67 @@ int ObLogHandler::submit_config_change_cmd_(const LogConfigChangeCmd &req, return ret; } +int ObLogHandler::append_(const void *buffer, + const int64_t nbytes, + const share::SCN &ref_scn, + const bool need_nonblock, + AppendCb *cb, + palf::LSN &lsn, + share::SCN &scn) +{ + int ret = OB_SUCCESS; + int64_t wait_times = 0; + PalfAppendOptions opts; + opts.need_nonblock = need_nonblock; + opts.need_check_proposal_id = true; + ObTimeGuard tg("ObLogHandler::append", 100000); + while (true) { + // generate opts + opts.proposal_id = ATOMIC_LOAD(&proposal_id_); + do { + RLockGuard guard(lock_); + CriticalGuard(ls_qs_); + cb->set_append_start_ts(ObTimeUtility::fast_current_time()); + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + } else if (is_in_stop_state_ || is_offline_) { + ret = OB_NOT_RUNNING; + } else if (LEADER != ATOMIC_LOAD(&role_)) { + ret = OB_NOT_MASTER; + } else if (OB_FAIL(palf_handle_.append(opts, buffer, nbytes, ref_scn, lsn, scn))) { + if (REACH_TIME_INTERVAL(1*1000*1000)) { + CLOG_LOG(WARN, "palf_handle_ append failed", K(ret), KPC(this)); + } + } else { + cb->set_append_finish_ts(ObTimeUtility::fast_current_time()); + cb->__set_lsn(lsn); + cb->__set_scn(scn); + ret = apply_status_->push_append_cb(cb); + CLOG_LOG(TRACE, "palf_handle_ push_append_cb success", K(lsn), K(scn), K(ret), K(id_)); + } + } while (0); + // check if need wait and retry append + if (opts.need_nonblock) { + // nonblock mode, end loop + break; + } else if (OB_EAGAIN == ret) { + // block mode, need sleep and retry for -4023 ret code + static const int64_t MAX_SLEEP_US = 100; + ++wait_times; + int64_t sleep_us = wait_times * 10; + if (sleep_us > MAX_SLEEP_US) { + sleep_us = MAX_SLEEP_US; + } + ob_usleep(sleep_us); + } else { + // other ret code, end loop + break; + } + } + append_cost_stat_.stat(tg.get_diff()); + return ret; +} + int ObLogHandler::get_member_gc_stat(const common::ObAddr &addr, bool &is_valid_member, LogMemberGCStat &stat) const @@ -1508,20 +1548,6 @@ int ObLogHandler::get_max_decided_scn(SCN &scn) return ret; } -int ObLogHandler::set_region(const common::ObRegion ®ion) -{ - int ret = OB_SUCCESS; - RLockGuard guard(lock_); - if (IS_NOT_INIT) { - ret = OB_NOT_INIT; - } else if (is_in_stop_state_) { - ret = OB_NOT_RUNNING; - } else { - ret = palf_handle_.set_region(region); - } - return ret; -} - int ObLogHandler::disable_vote(const bool need_check_log_missing) { int ret = OB_SUCCESS; diff --git a/src/logservice/ob_log_handler.h b/src/logservice/ob_log_handler.h index 663fd2bf79..0ac0fa8e28 100755 --- a/src/logservice/ob_log_handler.h +++ b/src/logservice/ob_log_handler.h @@ -76,6 +76,14 @@ public: palf::LSN &lsn, share::SCN &scn) = 0; + virtual int append_big_log(const void *buffer, + const int64_t nbytes, + const share::SCN &ref_scn, + const bool need_nonblock, + AppendCb *cb, + palf::LSN &lsn, + share::SCN &scn) = 0; + virtual int get_role(common::ObRole &role, int64_t &proposal_id) const = 0; virtual int change_access_mode(const int64_t mode_version, @@ -95,7 +103,6 @@ public: const int64_t paxos_replica_num, const common::GlobalLearnerList &learner_list) = 0; #endif - virtual int set_region(const common::ObRegion ®ion) = 0; virtual int set_election_priority(palf::election::ElectionPriority *priority) = 0; virtual int reset_election_priority() = 0; @@ -227,6 +234,27 @@ public: palf::LSN &lsn, share::SCN &scn) override final; + // @brief append count bytes(which is bigger than MAX_NORMAL_LOG_BODY_SIZE) from the buffer starting at buf to the palf handle, return the LSN and timestamp + // @param[in] const void *, the data buffer. + // @param[in] const uint64_t, the length of data buffer. + // @param[in] const int64_t, the base timestamp(ns), palf will ensure that the return tiemstamp will greater + // or equal than this field. + // @param[in] const bool, decide this append option whether need block thread. + // @param[int] AppendCb*, the callback of this append option, log handler will ensure that cb will be called after log has been committed + // @param[out] LSN&, the append position. + // @param[out] int64_t&, the append timestamp. + // @retval + // OB_SUCCESS + // OB_NOT_MASTER, the prospoal_id of ObLogHandler is not same with PalfHandle. + // NB: only support for primary(AccessMode::APPEND) + int append_big_log(const void *buffer, + const int64_t nbytes, + const share::SCN &ref_scn, + const bool need_nonblock, + AppendCb *cb, + palf::LSN &lsn, + share::SCN &scn) override final; + // @brief switch log_handle role, to LEADER or FOLLOWER // @param[in], role, LEADER or FOLLOWER // @param[in], proposal_id, global monotonically increasing id @@ -311,7 +339,6 @@ public: const int64_t paxos_replica_num, const common::GlobalLearnerList &learner_list) override final; #endif - int set_region(const common::ObRegion ®ion) override final; int set_election_priority(palf::election::ElectionPriority *priority) override final; int reset_election_priority() override final; // @desc: query coarse lsn by ts(ns), that means there is a LogGroupEntry in disk, @@ -714,6 +741,15 @@ private: int submit_config_change_cmd_(const LogConfigChangeCmd &req); int submit_config_change_cmd_(const LogConfigChangeCmd &req, LogConfigChangeCmdResp &resp); + + int append_(const void *buffer, + const int64_t nbytes, + const share::SCN &ref_scn, + const bool need_nonblock, + AppendCb *cb, + palf::LSN &lsn, + share::SCN &scn); + #ifdef OB_BUILD_ARBITRATION int create_arb_member_(const common::ObMember &arb_member, const int64_t timeout_us); int delete_arb_member_(const common::ObMember &arb_member, const int64_t timeout_us); diff --git a/src/logservice/ob_log_monitor.cpp b/src/logservice/ob_log_monitor.cpp index fe02612f3e..2ea14c71af 100644 --- a/src/logservice/ob_log_monitor.cpp +++ b/src/logservice/ob_log_monitor.cpp @@ -18,6 +18,7 @@ namespace oceanbase namespace logservice { #define LOG_MONITOR_EVENT_FMT_PREFIX "LOG", type_to_string_(event), "TENANT_ID", mtl_id, "LS_ID", palf_id +#define LOG_MONITOR_EVENT_STR_FMT_PREFIX "LOG", event_str, "TENANT_ID", mtl_id, "LS_ID", palf_id // =========== PALF Event Reporting =========== int ObLogMonitor::record_set_initial_member_list_event(const int64_t palf_id, @@ -290,6 +291,46 @@ int ObLogMonitor::record_role_change_event(const int64_t palf_id, } return ret; } + +int ObLogMonitor::record_parent_child_change_event(const int64_t palf_id, + const bool is_register, /* true: register; false; retire; */ + const bool is_parent, /* true: parent; false: child; */ + const common::ObAddr &server, + const common::ObRegion ®ion, + const int64_t register_time_us, + const char *extra_info) +{ + int ret = OB_SUCCESS; + int pret = OB_SUCCESS; + const int64_t mtl_id = MTL_ID(); + const char *action_str = (is_register)? "REGISTER": "RETIRE"; + const char *object_str = (is_parent)? "PARENT": "CHILD"; + const int64_t MAX_BUF_LEN = 50; + char event_str[MAX_BUF_LEN] = {'\0'}; + TIMEGUARD_INIT(LOG_MONITOR, 100_ms, 5_s); \ + if (0 >= (pret = snprintf(event_str, MAX_BUF_LEN, "%s %s", action_str, object_str))) { + ret = OB_ERR_UNEXPECTED; + CLOG_LOG(ERROR, "snprintf failed", KR(ret), K(action_str), K(object_str)); + } else { + CLICK(); + if (OB_NOT_NULL(extra_info)) { + SERVER_EVENT_ADD_WITH_RETRY(LOG_MONITOR_EVENT_STR_FMT_PREFIX, + object_str, server, + "REGION", region, + "REGISTER_TIME_US", register_time_us, + "", NULL, + extra_info); + } else { + SERVER_EVENT_ADD_WITH_RETRY(LOG_MONITOR_EVENT_STR_FMT_PREFIX, + object_str, server, + "REGION", region, + "REGISTER_TIME_US", register_time_us, + "", NULL); + } + CLICK(); + } + return ret; +} // =========== PALF Event Reporting =========== // =========== PALF Performance Statistic =========== diff --git a/src/logservice/ob_log_monitor.h b/src/logservice/ob_log_monitor.h index 747579d530..07ba99865e 100644 --- a/src/logservice/ob_log_monitor.h +++ b/src/logservice/ob_log_monitor.h @@ -80,6 +80,13 @@ public: const common::ObRole &curr_role, const palf::ObReplicaState &curr_state, const char *extra_info = NULL) override final; + int record_parent_child_change_event(const int64_t palf_id, + const bool is_register, /* true: register; false; retire; */ + const bool is_parent, /* true: parent; false: child; */ + const common::ObAddr &server, + const common::ObRegion ®ion, + const int64_t register_time_us, + const char *extra_info = NULL) override final; // =========== PALF Event Reporting =========== public: // =========== PALF Performance Statistic =========== @@ -112,7 +119,7 @@ private: ADVANCE_BASE_INFO, REBUILD, FLASHBACK, - TRUNCATE + TRUNCATE, }; const char *type_to_string_(const EventType &event) const diff --git a/src/logservice/ob_log_service.cpp b/src/logservice/ob_log_service.cpp index 2520373edd..4f1bd2db1f 100644 --- a/src/logservice/ob_log_service.cpp +++ b/src/logservice/ob_log_service.cpp @@ -65,7 +65,8 @@ ObLogService::ObLogService() : #endif restore_service_(), flashback_service_(), - monitor_() + monitor_(), + locality_adapter_() {} ObLogService::~ObLogService() @@ -90,6 +91,7 @@ int ObLogService::mtl_init(ObLogService* &logservice) common::ObMySQLProxy *mysql_proxy = GCTX.sql_proxy_; obrpc::ObNetKeepAlive *net_keepalive = &(obrpc::ObNetKeepAlive::get_instance()); ObNetKeepAliveAdapter *net_keepalive_adapter = NULL; + storage::ObLocalityManager *locality_manager = GCTX.locality_manager_; if (OB_FAIL(TMA_MGR_INSTANCE.get_tenant_log_allocator(tenant_id, alloc_mgr))) { CLOG_LOG(WARN, "get_tenant_log_allocator failed", K(ret)); } else if (OB_ISNULL(net_keepalive_adapter = MTL_NEW(ObNetKeepAliveAdapter, "logservice", net_keepalive))) { @@ -106,7 +108,8 @@ int ObLogService::mtl_init(ObLogService* &logservice) reporter, log_block_mgr, mysql_proxy, - net_keepalive_adapter))) { + net_keepalive_adapter, + locality_manager))) { CLOG_LOG(ERROR, "init ObLogService failed", K(ret), K(tenant_clog_dir)); } else if (OB_FAIL(FileDirectoryUtils::fsync_dir(clog_dir))) { CLOG_LOG(ERROR, "fsync_dir failed", K(ret), K(clog_dir)); @@ -206,6 +209,7 @@ void ObLogService::destroy() MTL_DELETE(IObNetKeepAliveAdapter, "logservice", net_keepalive_adapter_); net_keepalive_adapter_ = NULL; } + locality_adapter_.destroy(); FLOG_INFO("ObLogService is destroyed"); } @@ -238,7 +242,8 @@ int ObLogService::init(const PalfOptions &options, observer::ObIMetaReport *reporter, palf::ILogBlockPool *log_block_pool, common::ObMySQLProxy *sql_proxy, - IObNetKeepAliveAdapter *net_keepalive_adapter) + IObNetKeepAliveAdapter *net_keepalive_adapter, + storage::ObLocalityManager *locality_manager) { int ret = OB_SUCCESS; @@ -251,7 +256,7 @@ int ObLogService::init(const PalfOptions &options, } else if (false == options.is_valid() || OB_ISNULL(base_dir) || OB_UNLIKELY(!self.is_valid()) || OB_ISNULL(alloc_mgr) || OB_ISNULL(transport) || OB_ISNULL(batch_rpc) || OB_ISNULL(ls_service) || OB_ISNULL(location_service) || OB_ISNULL(reporter) || OB_ISNULL(log_block_pool) - || OB_ISNULL(sql_proxy) || OB_ISNULL(net_keepalive_adapter)) { + || OB_ISNULL(sql_proxy) || OB_ISNULL(net_keepalive_adapter) || OB_ISNULL(locality_manager)) { ret = OB_INVALID_ARGUMENT; CLOG_LOG(WARN, "invalid arguments", K(ret), K(options), KP(base_dir), K(self), KP(alloc_mgr), KP(transport), KP(batch_rpc), KP(ls_service), KP(location_service), KP(reporter), @@ -286,6 +291,8 @@ int ObLogService::init(const PalfOptions &options, #endif } else if (OB_FAIL(flashback_service_.init(self, &location_adapter_, &rpc_proxy_, sql_proxy))) { CLOG_LOG(WARN, "failed to init flashback_service_", K(ret)); + } else if (OB_FAIL(locality_adapter_.init(locality_manager))) { + CLOG_LOG(WARN, "failed to init locality_adapter_", K(ret)); } else { net_keepalive_adapter_ = net_keepalive_adapter; self_ = self; @@ -412,6 +419,7 @@ int ObLogService::add_ls(const ObLSID &id, PalfHandle &log_handler_palf_handle = log_handler.palf_handle_; PalfRoleChangeCb *rc_cb = &role_change_service_; PalfLocationCacheCb *loc_cache_cb = &location_adapter_; + PalfLocalityInfoCb *locality_cb = &locality_adapter_; if (IS_NOT_INIT) { ret = OB_NOT_INIT; CLOG_LOG(WARN, "log_service is not inited", K(ret), K(id)); @@ -428,6 +436,8 @@ int ObLogService::add_ls(const ObLSID &id, CLOG_LOG(WARN, "register_role_change_cb failed", K(ret)); } else if (OB_FAIL(log_handler_palf_handle.set_location_cache_cb(loc_cache_cb))) { CLOG_LOG(WARN, "set_location_cache_cb failed", K(ret), K(id)); + } else if (OB_FAIL(log_handler_palf_handle.set_locality_cb(locality_cb))) { + CLOG_LOG(WARN, "set_locality_cb failed", K(ret), K(id)); } else { FLOG_INFO("add_ls success", K(ret), K(id), KP(this)); } @@ -645,6 +655,7 @@ int ObLogService::create_ls_(const share::ObLSID &id, PalfHandle palf_handle; PalfRoleChangeCb *rc_cb = &role_change_service_; PalfLocationCacheCb *loc_cache_cb = &location_adapter_; + PalfLocalityInfoCb *locality_cb = &locality_adapter_; const bool is_arb_replica = (replica_type == REPLICA_TYPE_ARBITRATION); PalfHandle &log_handler_palf_handle = log_handler.palf_handle_; bool palf_exist = true; @@ -677,6 +688,8 @@ int ObLogService::create_ls_(const share::ObLSID &id, CLOG_LOG(WARN, "register_role_change_cb failed", K(ret), K(id)); } else if (OB_FAIL(log_handler_palf_handle.set_location_cache_cb(loc_cache_cb))) { CLOG_LOG(WARN, "set_location_cache_cb failed", K(ret), K(id)); + } else if (OB_FAIL(log_handler_palf_handle.set_locality_cb(locality_cb))) { + CLOG_LOG(WARN, "set_locality_cb failed", K(ret), K(id)); } else { CLOG_LOG(INFO, "ObLogService create_ls success", K(ret), K(id), K(log_handler)); } diff --git a/src/logservice/ob_log_service.h b/src/logservice/ob_log_service.h index 01880a86b6..343e01b99a 100644 --- a/src/logservice/ob_log_service.h +++ b/src/logservice/ob_log_service.h @@ -32,6 +32,7 @@ #endif #include "ob_reporter_adapter.h" #include "ob_ls_adapter.h" +#include "ob_locality_adapter.h" #include "ob_location_adapter.h" #include "ob_log_flashback_service.h" // ObLogFlashbackService #include "ob_log_handler.h" @@ -79,6 +80,7 @@ class PalfEnv; namespace storage { class ObLSService; +class ObLocalityManager; } namespace logservice @@ -108,7 +110,8 @@ public: observer::ObIMetaReport *reporter, palf::ILogBlockPool *log_block_pool, common::ObMySQLProxy *sql_proxy, - IObNetKeepAliveAdapter *net_keepalive_adapter); + IObNetKeepAliveAdapter *net_keepalive_adapter, + storage::ObLocalityManager *locality_manager); //--日志流相关接口-- //新建日志流接口,该接口会创建日志流对应的目录,新建一个以PalfBaeInfo为日志基点的日志流。 //其中包括生成并初始化对应的ObReplayStatus结构 @@ -258,6 +261,7 @@ private: ObLogFlashbackService flashback_service_; ObLogMonitor monitor_; ObSpinLock update_palf_opts_lock_; + ObLocalityAdapter locality_adapter_; private: DISALLOW_COPY_AND_ASSIGN(ObLogService); }; diff --git a/src/logservice/palf/log_config_mgr.cpp b/src/logservice/palf/log_config_mgr.cpp index 7c5c24af2d..6746158683 100755 --- a/src/logservice/palf/log_config_mgr.cpp +++ b/src/logservice/palf/log_config_mgr.cpp @@ -33,7 +33,6 @@ LogConfigMgr::LogConfigMgr() all_learnerlist_(), running_args_(), region_(DEFAULT_REGION_NAME), - paxos_member_region_map_(), lock_(common::ObLatchIds::PALF_CM_CONFIG_LOCK), palf_id_(), self_(), @@ -62,7 +61,9 @@ LogConfigMgr::LogConfigMgr() forwarding_config_proposal_id_(INVALID_PROPOSAL_ID), parent_lock_(common::ObLatchIds::PALF_CM_PARENT_LOCK), register_time_us_(OB_INVALID_TIMESTAMP), + register_parent_reason_(RegisterParentReason::INVALID), parent_(), + parent_region_(DEFAULT_REGION_NAME), parent_keepalive_time_us_(OB_INVALID_TIMESTAMP), last_submit_register_req_time_us_(OB_INVALID_TIMESTAMP), last_first_register_time_us_(OB_INVALID_TIMESTAMP), @@ -114,8 +115,6 @@ int LogConfigMgr::init(const int64_t palf_id, PALF_LOG(WARN, "invalid argument", KR(ret), K(palf_id), K(self), K(log_ms_meta), KP(log_engine), KP(sw), KP(state_mgr), KP(election), KP(mode_mgr), KP(reconfirm), KP(plugins)); - } else if (OB_FAIL(paxos_member_region_map_.init("LogRegionMap", OB_MAX_MEMBER_NUMBER))) { - PALF_LOG(WARN, "paxos_member_region_map_ init failed", K(palf_id)); } else { palf_id_ = palf_id; self_ = self; @@ -157,7 +156,9 @@ void LogConfigMgr::destroy() reconfirm_ = NULL; plugins_ = NULL; register_time_us_ = OB_INVALID_TIMESTAMP; + register_parent_reason_ = RegisterParentReason::INVALID; parent_.reset(); + parent_region_ = DEFAULT_REGION_NAME; parent_keepalive_time_us_ = OB_INVALID_TIMESTAMP; reset_registering_state_(); children_.reset(); @@ -171,7 +172,6 @@ void LogConfigMgr::destroy() alive_paxos_memberlist_.reset(); alive_paxos_replica_num_ = 0; all_learnerlist_.reset(); - paxos_member_region_map_.destroy(); last_sync_meta_for_arb_election_leader_time_us_ = OB_INVALID_TIMESTAMP; forwarding_config_proposal_id_ = INVALID_PROPOSAL_ID; region_ = DEFAULT_REGION_NAME; @@ -300,6 +300,17 @@ int LogConfigMgr::set_initial_config_info_(const LogConfigInfoV2 &config_info, return ret; } +int LogConfigMgr::get_region(common::ObRegion ®ion) const +{ + int ret = OB_SUCCESS; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + } else { + region = region_; + } + return ret; +} + int LogConfigMgr::set_region(const common::ObRegion ®ion) { int ret = OB_SUCCESS; @@ -323,36 +334,6 @@ int LogConfigMgr::set_region(const common::ObRegion ®ion) return ret; } -int LogConfigMgr::set_paxos_member_region_map(const LogMemberRegionMap ®ion_map) -{ - int ret = OB_SUCCESS; - if (IS_NOT_INIT) { - ret = OB_NOT_INIT; - } else if (0 == region_map.size()) { - ret = OB_INVALID_ARGUMENT; - } else { - const common::ObMemberList &member_list = alive_paxos_memberlist_; - // reset paxos_member_region_map_ and init again with current member_list - paxos_member_region_map_.reset(); - for (int i = 0; i < member_list.get_member_number(); ++i) { - common::ObAddr tmp_server; - common::ObRegion tmp_region; - int tmp_ret = OB_SUCCESS; - if (OB_SUCCESS != (tmp_ret = member_list.get_server_by_index(i, tmp_server))) { - PALF_LOG(WARN, "get_server_by_index failed", KR(tmp_ret), K_(palf_id), K_(self), K(i)); - } else if (OB_SUCCESS != (tmp_ret = region_map.get(tmp_server, tmp_region))) { - tmp_region = DEFAULT_REGION_NAME; - tmp_ret = OB_SUCCESS; - } - if (OB_SUCCESS == tmp_ret && OB_SUCCESS != (tmp_ret = paxos_member_region_map_.insert(tmp_server, tmp_region))) { - PALF_LOG(WARN, "paxos_member_region_map_ insert failed", KR(tmp_ret), K_(palf_id), K_(self), K(tmp_server), K(tmp_region)); - } - } - PALF_LOG(INFO, "set_paxos_member_region_map success", K_(palf_id), K_(self), K(region_map)); - } - return ret; -} - int LogConfigMgr::get_prev_member_list(ObMemberList &member_list) const { int ret = OB_SUCCESS; @@ -686,17 +667,18 @@ int LogConfigMgr::after_flush_config_log(const LogConfigVersion &config_version) SpinLockGuard guard(lock_); persistent_config_version_ = (persistent_config_version_.is_valid())? MAX(persistent_config_version_, config_version): config_version; } while (0); - // if self is in memberlist, then retire parent, otherwise paxos may has a parent. + // if self is in memberlist, then retire parent, otherwise paxos member may has a parent. if (alive_paxos_memberlist_.contains(self_)) { SpinLockGuard guard_parent(parent_lock_); - if (parent_.is_valid() && OB_FAIL(retire_parent_())) { + if (parent_.is_valid() && OB_FAIL(retire_parent_(RetireParentReason::IS_FULL_MEMBER))) { PALF_LOG(WARN, "retire_parent failed", KR(ret), K_(palf_id), K_(self)); } } // if child is not in learnerlist, then retire child if (OB_FAIL(remove_child_is_not_learner_(removed_children))) { PALF_LOG(WARN, "remove_child_is_not_learner failed", KR(ret), K_(palf_id), K_(self)); - } else if (OB_FAIL(submit_retire_children_req_(removed_children))) { + } else if (OB_FAIL(submit_retire_children_req_(removed_children, + RetireChildReason::CHILD_NOT_IN_LEARNER_LIST))) { PALF_LOG(WARN, "submit_retire_children_req failed", KR(ret), K_(palf_id), K_(self), K(removed_children)); } PALF_LOG(INFO, "after_flush_config_log success", K_(palf_id), K_(self), K(config_version), K_(persistent_config_version)); @@ -2549,13 +2531,45 @@ int LogConfigMgr::get_register_leader_(common::ObAddr &leader) const return ret; } -int LogConfigMgr::after_register_done_() +int LogConfigMgr::after_register_parent_done_(const LogLearner &parent, + const RegisterParentReason &reason) const { int ret = OB_SUCCESS; + int tmp_ret = OB_SUCCESS; + int pret = OB_SUCCESS; + const int64_t MAX_BUF_LEN = 50; + char reason_str[MAX_BUF_LEN] = {'\0'}; if (OB_FAIL(sw_->try_fetch_log(FetchTriggerType::LEARNER_REGISTER))){ PALF_LOG(WARN, "try_fetch_log failed", KR(ret), K_(palf_id), K_(self), K_(parent), K_(register_time_us)); } - PALF_LOG(INFO, "after_register_done", K_(palf_id), K_(self), K_(parent), K_(register_time_us)); + if (0 >= (pret = snprintf(reason_str, MAX_BUF_LEN, "REASON:%s", register_parent_reason_2_str_(reason)))) { + ret = OB_ERR_UNEXPECTED; + CLOG_LOG(ERROR, "snprintf failed", KR(ret), K(reason_str), "reason", register_parent_reason_2_str_(reason)); + } else if (OB_TMP_FAIL(plugins_->record_parent_child_change_event(palf_id_, true /*is_register*/, + true /* is_parent*/, parent.server_, parent.region_, parent.register_time_us_, reason_str))) { + PALF_LOG(WARN, "record_parent_child_change_event failed", KR(tmp_ret), K_(palf_id), K_(self), K(parent)); + } + PALF_EVENT("register_parent", palf_id_, K(ret), K_(self), K_(region), K(parent), + "reason", register_parent_reason_2_str_(reason)); + return ret; +} + +int LogConfigMgr::after_retire_parent_done_(const LogLearner &parent, + const RetireParentReason &reason) const +{ + int ret = OB_SUCCESS; + int tmp_ret = OB_SUCCESS; + int pret = OB_SUCCESS; + const int64_t MAX_BUF_LEN = 50; + char reason_str[MAX_BUF_LEN] = {'\0'}; + if (0 >= (pret = snprintf(reason_str, MAX_BUF_LEN, "REASON:%s", retire_parent_reason_2_str_(reason)))) { + ret = OB_ERR_UNEXPECTED; + CLOG_LOG(ERROR, "snprintf failed", KR(ret), K(reason_str), K(reason)); + } else if (OB_TMP_FAIL(plugins_->record_parent_child_change_event(palf_id_, false /*is_register*/, + true /* is_parent*/, parent.server_, parent.region_, parent.register_time_us_, reason_str))) { + PALF_LOG(WARN, "record_parent_child_change_event failed", KR(tmp_ret), K_(palf_id), K_(self), K(parent), K(reason)); + } + PALF_EVENT("retire_parent", palf_id_, K(ret), K_(self), K_(region), K(parent), "reason", retire_parent_reason_2_str_(reason)); return ret; } @@ -2567,12 +2581,12 @@ int LogConfigMgr::after_region_changed_(const common::ObRegion &old_region, cons int ret = OB_SUCCESS; if (parent_.is_valid() || is_registering_()) { const common::ObAddr old_parent = parent_; - if (OB_FAIL(retire_parent_())) { + if (OB_FAIL(retire_parent_(RetireParentReason::SELF_REGION_CHANGED))) { PALF_LOG(WARN, "retire_parent failed", KR(ret), K_(palf_id), K_(self), K_(parent)); } else if (FALSE_IT(reset_parent_info_())) { // if i'm registering when change region, need reset all parent info and // start a new regisration with new region. - } else if (OB_FAIL(register_parent_())) { + } else if (OB_FAIL(register_parent_(RegisterParentReason::SELF_REGION_CHANGED))) { PALF_LOG(WARN, "register_parent failed", KR(ret), K_(palf_id), K_(self), K(old_region), K(new_region)); } else { PALF_LOG(INFO, "re_register_parent reason: region_changed", K_(palf_id), K_(self), K(old_parent), K(old_region), K(new_region)); @@ -2587,7 +2601,7 @@ int LogConfigMgr::register_parent() SpinLockGuard guard(parent_lock_); if (IS_NOT_INIT) { ret = OB_NOT_INIT; - } else if (!parent_.is_valid() && OB_FAIL(register_parent_())) { + } else if (!parent_.is_valid() && OB_FAIL(register_parent_(RegisterParentReason::FIRST_REGISTER))) { PALF_LOG(WARN, "register_parent failed", KR(ret), K_(palf_id), K_(self), K_(parent)); } else { } @@ -2596,7 +2610,7 @@ int LogConfigMgr::register_parent() // @return // - OB_EAGAIN: leader is invalid -int LogConfigMgr::register_parent_() +int LogConfigMgr::register_parent_(const RegisterParentReason &reason) { int ret = OB_SUCCESS; ObAddr leader; @@ -2612,7 +2626,11 @@ int LogConfigMgr::register_parent_() } else { last_submit_register_req_time_us_ = curr_time_us; register_time_us_ = curr_time_us; + register_parent_reason_ = (RegisterParentReason::INVALID != reason)? \ + reason: register_parent_reason_; parent_keepalive_time_us_ = OB_INVALID_TIMESTAMP; + PALF_LOG(INFO, "register_parent_", KR(ret), K_(palf_id), K_(self), K(reason), K(leader), + K_(register_time_us), K_(last_submit_register_req_time_us), K_(register_parent_reason)); } } return ret; @@ -2623,7 +2641,8 @@ int LogConfigMgr::handle_register_parent_resp(const LogLearner &server, const RegisterReturn reg_ret) { int ret = OB_SUCCESS; - bool do_after_register_done = false; + bool do_after_register_parent_done = false; + RegisterParentReason reason = RegisterParentReason::INVALID; if (IS_NOT_INIT) { ret = OB_NOT_INIT; PALF_LOG(WARN, "LogConfigMgr not init", KR(ret)); @@ -2638,10 +2657,11 @@ int LogConfigMgr::handle_register_parent_resp(const LogLearner &server, } else if (REGISTER_DONE == reg_ret) { // register done, just set parent_ and clean registering state parent_ = server.server_; + parent_region_ = server.region_; parent_keepalive_time_us_ = common::ObTimeUtility::current_time(); + reason = register_parent_reason_; reset_registering_state_(); - do_after_register_done = true; - PALF_EVENT("register_parent done", palf_id_, K_(self), K_(parent), K_(register_time_us)); + do_after_register_parent_done = true; } else if (REGISTER_CONTINUE == reg_ret && candidate_list.get_member_number() > 0) { common::ObAddr reg_dst; const int64_t reg_dst_idx = ObRandom::rand(0, candidate_list.get_member_number() - 1); @@ -2656,7 +2676,7 @@ int LogConfigMgr::handle_register_parent_resp(const LogLearner &server, } else if (REGISTER_DIFF_REGION == reg_ret) { const char *reason = "diff_region"; PALF_LOG(INFO, "re_register_parent reason", K(reason), K_(palf_id), K_(self), K_(region), K(server)); - if (OB_FAIL(register_parent_())) { + if (OB_FAIL(register_parent_(RegisterParentReason::INVALID))) { PALF_LOG(WARN, "re_register failed", KR(ret), K_(palf_id), K_(self), K(server)); } } else if (REGISTER_NOT_MASTER == reg_ret) { @@ -2666,14 +2686,14 @@ int LogConfigMgr::handle_register_parent_resp(const LogLearner &server, PALF_LOG(ERROR, "unexpected Register_Return", K_(palf_id), K_(self), K(server), K(candidate_list), K(reg_ret)); } } - if (do_after_register_done && OB_FAIL(after_register_done_())) { - PALF_LOG(WARN, "after_register_done failed", KR(ret), K_(palf_id), K_(self)); + if (do_after_register_parent_done && OB_FAIL(after_register_parent_done_(server, reason))) { + PALF_LOG(WARN, "after_register_parent_done failed", KR(ret), K_(palf_id), K_(self)); } PALF_LOG(INFO, "handle_register_parent_resp finished", KR(ret), K_(palf_id), K_(self), K(server), K(candidate_list), K(reg_ret)); return ret; } -int LogConfigMgr::retire_parent_() +int LogConfigMgr::retire_parent_(const RetireParentReason &reason) { int ret = OB_SUCCESS; if (!parent_.is_valid()) { @@ -2684,6 +2704,7 @@ int LogConfigMgr::retire_parent_() PALF_LOG(WARN, "submit_retire_parent_req failed", KR(ret), K_(palf_id), K_(self), K_(parent), K_(register_time_us)); } else { PALF_LOG(INFO, "submit_retire_parent_req success", K_(palf_id), K_(self), K_(parent), K_(register_time_us)); + after_retire_parent_done_(LogLearner(parent_, parent_region_, register_time_us_), reason); reset_parent_info_(); } } @@ -2702,7 +2723,7 @@ int LogConfigMgr::handle_retire_child(const LogLearner &parent) } else { reset_parent_info_(); PALF_LOG(INFO, "re_register_parent reason: handle_retire_child", K_(palf_id), K_(self), K(parent)); - if (OB_FAIL(register_parent_())) { + if (OB_FAIL(register_parent_(RegisterParentReason::RETIRED_BY_PARENT))) { PALF_LOG(WARN, "register_parent failed when recving retire child", KR(ret), K_(self), K(parent)); } else { PALF_LOG(INFO, "handle_retire_child success", KR(ret), K_(self), K(parent)); @@ -2749,21 +2770,26 @@ int LogConfigMgr::check_parent_health() // break learner loop if (parent_.is_valid() && children_.contains(parent_) && - OB_FAIL(retire_parent_())) { + OB_FAIL(retire_parent_(RetireParentReason::PARENT_CHILD_LOOP))) { PALF_LOG(WARN, "retire_parent_ failed", KR(ret), K_(palf_id), K_(self)); } } SpinLockGuard guard(parent_lock_); const int64_t curr_time_us = common::ObTimeUtility::current_time(); - const bool is_registering_timeout = (is_registering_() && curr_time_us - last_submit_register_req_time_us_ > PALF_CHILD_RESEND_REGISTER_INTERVAL_US); + const bool is_registering_timeout = (is_registering_() && + curr_time_us - last_submit_register_req_time_us_ > PALF_CHILD_RESEND_REGISTER_INTERVAL_US); const bool first_registration = (!parent_.is_valid() && !is_registering_() && palf_reach_time_interval(PALF_CHILD_RESEND_REGISTER_INTERVAL_US, last_first_register_time_us_)); const bool parent_timeout = (parent_.is_valid() && curr_time_us - parent_keepalive_time_us_ > PALF_PARENT_CHILD_TIMEOUT_US); if (is_registering_timeout || first_registration || parent_timeout) { PALF_LOG(INFO, "re_register_parent reason", K_(palf_id), K_(self), K(is_registering_timeout), K(first_registration), K(parent_timeout), K_(parent_keepalive_time_us), K_(last_submit_register_req_time_us), K_(last_first_register_time_us), K_(register_time_us), K(curr_time_us)); + RegisterParentReason reason = RegisterParentReason::INVALID; + reason = (first_registration)? RegisterParentReason::FIRST_REGISTER: reason; + reason = (parent_timeout)? RegisterParentReason::PARENT_NOT_ALIVE: reason; + reason = (is_registering_timeout)? register_parent_reason_: reason; reset_parent_info_(); - if (OB_FAIL(register_parent_())) { + if (OB_FAIL(register_parent_(reason))) { PALF_LOG(WARN, "register request timeout, re_register_parent failed", KR(ret), K_(palf_id), K_(self)); } else { PALF_LOG(INFO, "re register_parent success", KR(ret), K_(palf_id), K_(self)); @@ -2776,7 +2802,9 @@ int LogConfigMgr::check_parent_health() void LogConfigMgr::reset_parent_info_() { register_time_us_ = OB_INVALID_TIMESTAMP; + register_parent_reason_ = RegisterParentReason::INVALID; parent_.reset(); + parent_region_ = DEFAULT_REGION_NAME; parent_keepalive_time_us_ = OB_INVALID_TIMESTAMP; last_submit_register_req_time_us_ = OB_INVALID_TIMESTAMP; } @@ -2879,7 +2907,7 @@ int LogConfigMgr::handle_register_parent_req(const LogLearner &child, const bool PALF_LOG(INFO, "handle_register_parent_req success", K(ret), K(child), K(is_to_leader), K(candidate_list), K(reg_ret), K_(children), "member_list", log_ms_meta_.curr_.config_.log_sync_memberlist_); } - if (OB_FAIL(submit_retire_children_req_(retired_children))) { + if (OB_FAIL(submit_retire_children_req_(retired_children, RetireChildReason::CHILDREN_LIST_FULL))) { PALF_LOG(WARN, "submit_retire_children_req failed", KR(ret), K_(palf_id), K_(self), K(retired_children)); } return ret; @@ -2979,11 +3007,13 @@ int LogConfigMgr::check_children_health() } } // 5. retire removed children - if (OB_FAIL(submit_retire_children_req_(dead_children))) { + if (OB_FAIL(submit_retire_children_req_(dead_children, RetireChildReason::CHILD_NOT_ALIVE))) { PALF_LOG(WARN, "submit_retire_children_req failed", KR(ret), K_(palf_id), K_(self), K(dead_children)); - } else if (!is_leader && submit_retire_children_req_(diff_region_children)) { + } else if (!is_leader && OB_FAIL(submit_retire_children_req_(diff_region_children, + RetireChildReason::DIFFERENT_REGION_WITH_PARENT))) { PALF_LOG(WARN, "submit_retire_children_req failed", KR(ret), K_(palf_id), K_(self), K(diff_region_children)); - } else if (is_leader && submit_retire_children_req_(dup_region_children)) { + } else if (is_leader && OB_FAIL(submit_retire_children_req_(dup_region_children, + RetireChildReason::DUPLICATE_REGION_IN_LEADER))) { PALF_LOG(WARN, "submit_retire_children_req failed", KR(ret), K_(palf_id), K_(self), K(dup_region_children)); } } @@ -3054,13 +3084,14 @@ int LogConfigMgr::remove_child_is_not_learner_(LogLearnerList &removed_children) int LogConfigMgr::remove_duplicate_region_child_(LogLearnerList &dup_region_children) { int ret = OB_SUCCESS; - common::ObArrayHashMap region_map; + common::hash::ObHashMap region_map; LogLearnerCond cond; LogLearnerAction action; const int64_t REGION_MAP_SIZE = MIN(OB_MAX_MEMBER_NUMBER + children_.get_member_number(), MAX_ZONE_NUM); if (children_.get_member_number() == 0) { // skip - } else if (OB_FAIL(region_map.init("LogTmpRegionMap", REGION_MAP_SIZE))) { + } else if (OB_FAIL(region_map.create(REGION_MAP_SIZE, + ObMemAttr(MTL_ID(), ObModIds::OB_HASH_NODE, ObCtxIds::DEFAULT_CTX_ID)))) { PALF_LOG(WARN, "region_map init failed", KR(ret), K_(palf_id), K_(self)); } else if (OB_FAIL(get_member_regions_(region_map))) { PALF_LOG(WARN, "get_member_region failed", KR(ret), K_(palf_id), K_(self)); @@ -3070,9 +3101,9 @@ int LogConfigMgr::remove_duplicate_region_child_(LogLearnerList &dup_region_chil [®ion_map, &dup_region_children, this](const LogLearner &child)->int { int ret = OB_SUCCESS; int unused_val = 0; - if (OB_FAIL(region_map.get(child.region_, unused_val))) { - if (OB_ENTRY_NOT_EXIST == ret) { - if (OB_FAIL(region_map.insert(child.region_, 1))) { + if (OB_FAIL(region_map.get_refactored(child.region_, unused_val))) { + if (OB_HASH_NOT_EXIST == ret) { + if (OB_FAIL(region_map.set_refactored(child.region_, 1))) { PALF_LOG(WARN, "region_map.insert failed", KR(ret), K_(palf_id), K_(self), K(child)); } } else { @@ -3152,9 +3183,9 @@ int LogConfigMgr::generate_candidate_list_from_member_(const LogLearner &child, int tmp_ret = OB_SUCCESS; if (OB_SUCCESS != (tmp_ret = curr_member_list.get_server_by_index(i, addr))) { PALF_LOG(WARN, "get_server_by_index failed", KR(ret), K(curr_member_list), K(i)); - } else if (OB_SUCCESS != (tmp_ret = paxos_member_region_map_.get(addr, region))) { - PALF_LOG(WARN, "paxos_member_region_map_ get failed", KR(tmp_ret), K_(palf_id), K_(self), - K_(paxos_member_region_map), K(addr)); + } else if (OB_SUCCESS != (tmp_ret = plugins_->get_server_region(addr, region) && + FALSE_IT(region = DEFAULT_REGION_NAME))) { + PALF_LOG(WARN, "get_server_region failed", KR(tmp_ret), K_(palf_id), K_(self), K(addr)); } else if (addr == self_ || region != child.region_) { // skip } else if (OB_SUCCESS == (tmp_ret = candidate_list.add_learner(common::ObMember(addr, 1)))) { @@ -3195,7 +3226,8 @@ int LogConfigMgr::generate_candidate_list_from_children_(const LogLearner &child return ret; } -int LogConfigMgr::submit_retire_children_req_(const LogLearnerList &retired_children) +int LogConfigMgr::submit_retire_children_req_(const LogLearnerList &retired_children, + const RetireChildReason &reason) { int ret = OB_SUCCESS; int tmp_ret = OB_SUCCESS; @@ -3207,12 +3239,14 @@ int LogConfigMgr::submit_retire_children_req_(const LogLearnerList &retired_chil } else if (FALSE_IT(parent.register_time_us_ = retired_child.register_time_us_)) { } else if (OB_SUCCESS != (tmp_ret = log_engine_->submit_retire_child_req(retired_child.server_, parent))) { PALF_LOG(WARN, "submit_retire_child_req failed", KR(ret), K(retired_child), K(parent)); + } else { + (void) after_retire_child_done_(retired_child, reason); } } return ret; } -int LogConfigMgr::get_member_regions_(common::ObArrayHashMap ®ion_map) const +int LogConfigMgr::get_member_regions_(common::hash::ObHashMap ®ion_map) const { int ret = OB_SUCCESS; const ObMemberList &curr_member_list = log_ms_meta_.curr_.config_.log_sync_memberlist_; @@ -3224,14 +3258,50 @@ int LogConfigMgr::get_member_regions_(common::ObArrayHashMap ® PALF_LOG(WARN, "get_server_by_index failed", KR(ret), K(curr_member_list), K(i)); } else if (addr == self_) { // skip - } else if (OB_SUCCESS != (tmp_ret = paxos_member_region_map_.get(addr, region))) { - PALF_LOG(WARN, "paxos_member_region_map_.get failed", KR(ret), K(addr)); - } else if (OB_SUCCESS != (tmp_ret = region_map.insert(region, 1)) && OB_ENTRY_EXIST != tmp_ret) { + } else if (OB_SUCCESS != (tmp_ret = plugins_->get_server_region(addr, region)) && + FALSE_IT(region = DEFAULT_REGION_NAME)) { + PALF_LOG(WARN, "get_server_region failed", KR(ret), K(addr)); + } else if (OB_SUCCESS != (tmp_ret = region_map.set_refactored(region, 1)) && + OB_HASH_EXIST != tmp_ret) { PALF_LOG(WARN, "region_map.insert_or_update failed", KR(ret), K_(palf_id), K_(self), K(region)); } } return ret; } + +int LogConfigMgr::after_register_child_done_(const LogLearner &child) const +{ + int ret = OB_SUCCESS; + int tmp_ret = OB_SUCCESS; + const int64_t MAX_BUF_LEN = 50; + char reason_str[MAX_BUF_LEN] = {'\0'}; + if (OB_FAIL(plugins_->record_parent_child_change_event(palf_id_, true /*is_register*/, + false /* is_parent*/, child.server_, child.region_, child.register_time_us_, reason_str))) { + PALF_LOG(WARN, "record_parent_child_change_event failed", KR(tmp_ret), K_(palf_id), K_(self), K(child)); + } + PALF_EVENT("register_child", palf_id_, K(ret), K_(self), K_(region), K(child)); + return ret; +} + +int LogConfigMgr::after_retire_child_done_(const LogLearner &child, + const RetireChildReason &reason) const +{ + int ret = OB_SUCCESS; + int tmp_ret = OB_SUCCESS; + int pret = OB_SUCCESS; + const int64_t MAX_BUF_LEN = 50; + char reason_str[MAX_BUF_LEN] = {'\0'}; + if (0 >= (pret = snprintf(reason_str, MAX_BUF_LEN, "REASON:%s", retire_child_reason_2_str_(reason)))) { + ret = OB_ERR_UNEXPECTED; + CLOG_LOG(ERROR, "snprintf failed", KR(ret), K(reason_str), K(reason)); + } else if (OB_TMP_FAIL(plugins_->record_parent_child_change_event(palf_id_, false /*is_register*/, + false /* is_parent*/, child.server_, child.region_, child.register_time_us_, reason_str))) { + PALF_LOG(WARN, "record_parent_child_change_event failed", KR(tmp_ret), K_(palf_id), K_(self), + K(child), "reason", retire_child_reason_2_str_(reason)); + } + PALF_EVENT("retire_child", palf_id_, K(ret), K_(self), K_(region), K(child), "reason", retire_child_reason_2_str_(reason)); + return ret; +} //================================ Parent ================================ } // namespace palf } // namespace oceanbase diff --git a/src/logservice/palf/log_config_mgr.h b/src/logservice/palf/log_config_mgr.h index b965b06839..d9559dd3af 100755 --- a/src/logservice/palf/log_config_mgr.h +++ b/src/logservice/palf/log_config_mgr.h @@ -16,7 +16,7 @@ #include "common/ob_member_list.h" // ObMemberList #include "lib/lock/ob_spin_lock.h" // SpinRWLock #include "lib/random/ob_random.h" // ObRandom -#include "lib/hash/ob_array_hash_map.h" // ObArrayHashMap +#include "lib/hash/ob_hashmap.h" // ObHashMap #include "lib/function/ob_function.h" // ObFunction #include "share/scn.h" //SCN #include "log_define.h" // utils @@ -104,8 +104,6 @@ inline const char *LogConfigChangeType2Str(const LogConfigChangeType state) #undef CHECK_LOG_CONFIG_TYPE_STR } -typedef common::ObArrayHashMap LogMemberRegionMap; - // Note: We need to check if the cluster has been upgraded to version 4.2. // If not, invalid config_version is allowed because OBServer v4.1 // may send a LogConfigChangeCmd (with invalid config_version) to @@ -359,9 +357,8 @@ public: const int64_t proposal_id, LogConfigVersion &config_version); // set region for self + int get_region(common::ObRegion ®ion) const; int set_region(const common::ObRegion ®ion); - // set region hash_map for Paxos members - int set_paxos_member_region_map(const LogMemberRegionMap ®ion_map); // following get ops need caller holds RLock in PalfHandleImpl virtual int64_t get_accept_proposal_id() const; int get_global_learner_list(common::GlobalLearnerList &learner_list) const; @@ -514,8 +511,7 @@ public: K_(log_ms_meta), K_(running_args), K_(state), K_(checking_barrier), K_(reconfig_barrier), \ K_(persistent_config_version), K_(ms_ack_list), K_(resend_config_version), K_(resend_log_list), \ K_(last_submit_config_log_time_us), K_(need_change_config_bkgd), K_(bkgd_config_version), \ - K_(region), K_(paxos_member_region_map), \ - K_(register_time_us), K_(parent), K_(parent_keepalive_time_us), \ + K_(region), K_(register_time_us), K_(parent), K_(parent_keepalive_time_us), \ K_(last_submit_register_req_time_us), K_(children), K_(last_submit_keepalive_time_us), KP(this)); J_OBJ_END(); return pos; @@ -607,6 +603,78 @@ private: const bool is_arb_replica); int after_config_log_majority_(const int64_t proposal_id, const LogConfigVersion &config_version); +private: +enum class RegisterParentReason +{ + INVALID = 0, + FIRST_REGISTER = 1, + PARENT_NOT_ALIVE = 2, + SELF_REGION_CHANGED = 3, + RETIRED_BY_PARENT = 4, +}; + +inline const char *register_parent_reason_2_str_(const RegisterParentReason &reason) const +{ + #define CHECK_REASON_STR(x) case(RegisterParentReason::x): return #x + switch(reason) + { + CHECK_REASON_STR(FIRST_REGISTER); + CHECK_REASON_STR(PARENT_NOT_ALIVE); + CHECK_REASON_STR(SELF_REGION_CHANGED); + CHECK_REASON_STR(RETIRED_BY_PARENT); + default: + return "Invalid"; + } + #undef CHECK_REASON_STR +} + +enum class RetireParentReason +{ + INVALID = 0, + IS_FULL_MEMBER = 1, + SELF_REGION_CHANGED = 2, + PARENT_CHILD_LOOP = 3, +}; + +inline const char *retire_parent_reason_2_str_(const RetireParentReason &reason) const +{ + #define CHECK_REASON_STR(x) case(RetireParentReason::x): return #x + switch(reason) + { + CHECK_REASON_STR(IS_FULL_MEMBER); + CHECK_REASON_STR(SELF_REGION_CHANGED); + CHECK_REASON_STR(PARENT_CHILD_LOOP); + default: + return "Invalid"; + } + #undef CHECK_REASON_STR +} + +enum class RetireChildReason +{ + INVALID = 0, + CHILDREN_LIST_FULL = 1, + CHILD_NOT_IN_LEARNER_LIST = 2, + CHILD_NOT_ALIVE = 3, + DIFFERENT_REGION_WITH_PARENT = 4, + DUPLICATE_REGION_IN_LEADER = 5, +}; + +inline const char *retire_child_reason_2_str_(const RetireChildReason reason) const +{ + #define CHECK_REASON_STR(x) case(RetireChildReason::x): return #x + switch(reason) + { + CHECK_REASON_STR(CHILDREN_LIST_FULL); + CHECK_REASON_STR(CHILD_NOT_IN_LEARNER_LIST); + CHECK_REASON_STR(CHILD_NOT_ALIVE); + CHECK_REASON_STR(DIFFERENT_REGION_WITH_PARENT); + CHECK_REASON_STR(DUPLICATE_REGION_IN_LEADER); + default: + return "Invalid"; + } + #undef CHECK_REASON_STR +} private: // inner_config_meta_ is protected by RWLock in PalfHandleImpl, @@ -615,11 +683,12 @@ private: // ==================== Child ======================== bool is_registering_() const; void reset_registering_state_(); - int register_parent_(); - int after_register_done_(); // enable fetch_log + int register_parent_(const RegisterParentReason &reason); + int after_register_parent_done_(const LogLearner &parent, const RegisterParentReason &reason) const; + int after_retire_parent_done_(const LogLearner &parent, const RetireParentReason &reason) const; int after_region_changed_(const common::ObRegion &old_region, const common::ObRegion &new_region); int get_register_leader_(common::ObAddr &leader) const; - int retire_parent_(); + int retire_parent_(const RetireParentReason &reason); void reset_parent_info_(); // ==================== Child ======================== // ==================== Parent ======================== @@ -631,12 +700,14 @@ private: int remove_duplicate_region_child_(LogLearnerList &dup_region_children); int remove_child_is_not_learner_(LogLearnerList &removed_children); int remove_children_(LogLearnerList &this_children, const LogLearnerList &removed_children); - int get_member_regions_(common::ObArrayHashMap ®ion_map) const; - int submit_retire_children_req_(const LogLearnerList &retired_children); + int get_member_regions_(common::hash::ObHashMap ®ion_map) const; + int submit_retire_children_req_(const LogLearnerList &retired_children, const RetireChildReason &reason); int children_if_cond_then_action_(const LogLearnerCond &cond, const LogLearnerAction &action); + int after_register_child_done_(const LogLearner &child) const; + int after_retire_child_done_(const LogLearner &child, const RetireChildReason &reason) const; // ==================== Parent ======================== private: - // inner_config_meta_, region_ and paxos_member_region_map_ is protected by RWLock in PalfHandleImpl, + // inner_config_meta_ and region_ is protected by RWLock in PalfHandleImpl, // any read/write ops should acquire RLock/WLock in PalfHandleImpl. // inner_config_meta_, inner_alive_paxos_memberlist_, inner_alive_paxos_replica_num_, // and inner_all_learnerlist_ take effect as long as they are accepted by the replica, @@ -650,7 +721,6 @@ private: GlobalLearnerList all_learnerlist_; LogConfigChangeArgs running_args_; common::ObRegion region_; - LogMemberRegionMap paxos_member_region_map_; // this lock protects all states related to config change, except for inner_config_meta_ mutable common::ObSpinLock lock_; int64_t palf_id_; @@ -697,7 +767,9 @@ private: // ==================== Child ======================== mutable common::ObSpinLock parent_lock_; int64_t register_time_us_; + RegisterParentReason register_parent_reason_; common::ObAddr parent_; + ObRegion parent_region_; int64_t parent_keepalive_time_us_; // registering state int64_t last_submit_register_req_time_us_; diff --git a/src/logservice/palf/log_define.h b/src/logservice/palf/log_define.h index b9ce6a4a0b..65a2cd4bbe 100644 --- a/src/logservice/palf/log_define.h +++ b/src/logservice/palf/log_define.h @@ -61,8 +61,8 @@ const int64_t MIN_DISK_SIZE_PER_PALF_INSTANCE = 512 * 1024 * 1024ul; constexpr offset_t MAX_LOG_HEADER_SIZE = 4 * 1024; constexpr offset_t MAX_INFO_BLOCK_SIZE = 4 * 1024; constexpr offset_t MAX_META_ENTRY_SIZE = 4 * 1024; -constexpr offset_t MAX_LOG_BODY_SIZE = 2 * 1024 * 1024 + 16 * 1024; // The max size of one log body is (2MB + 16KB). - +constexpr offset_t MAX_LOG_BODY_SIZE = 3 * 1024 * 1024 + 512 * 1024; // The max size of one log body is 3.5MB. +constexpr offset_t MAX_NORMAL_LOG_BODY_SIZE = 2 * 1024 * 1024 + 16 * 1024; const int64_t PALF_PHY_BLOCK_SIZE = 1 << 26; // 64MB const int64_t PALF_BLOCK_SIZE = PALF_PHY_BLOCK_SIZE - MAX_INFO_BLOCK_SIZE; // log block size is 64M-MAX_INFO_BLOCK_SIZE by default. const int64_t PALF_META_BLOCK_SIZE = PALF_PHY_BLOCK_SIZE - MAX_INFO_BLOCK_SIZE; // meta block size is 64M-MAX_INFO_BLOCK_SIZE by default. @@ -73,7 +73,7 @@ constexpr int64_t CLOG_FILE_TAIL_PADDING_TRIGGER = 4096; // 文件尾剩余 // The padding group_entry size range is: // [4KB, (max_valid_group_entry_size + CLOG_FILE_TAIL_PADDING_TRIGGER) ). // So the MAX_LOG_BUFFER_SIZE is defined as below: -constexpr offset_t MAX_LOG_BUFFER_SIZE = MAX_LOG_BODY_SIZE + MAX_LOG_HEADER_SIZE + CLOG_FILE_TAIL_PADDING_TRIGGER; +constexpr offset_t MAX_LOG_BUFFER_SIZE = MAX_LOG_BODY_SIZE + MAX_LOG_HEADER_SIZE + CLOG_FILE_TAIL_PADDING_TRIGGER; // max size of the log buffer is (3.5MB + 4KB + 4KB) constexpr offset_t LOG_DIO_ALIGN_SIZE = 4 * 1024; constexpr offset_t LOG_DIO_ALIGNED_BUF_SIZE_REDO = MAX_LOG_BUFFER_SIZE + LOG_DIO_ALIGN_SIZE; @@ -123,6 +123,7 @@ constexpr int64_t PALF_MAX_PROPOSAL_ID = INT64_MAX - 1; constexpr int64_t PALF_INITIAL_PROPOSAL_ID = 0; constexpr char PADDING_LOG_CONTENT_CHAR = '\0'; const int64_t MIN_WRITING_THTOTTLING_TRIGGER_PERCENTAGE = 40; +const int64_t PALF_UPDATE_REGION_INTERVAL_US = 10 * 1000 * 1000L; // 10s inline int64_t max_proposal_id(const int64_t a, const int64_t b) { diff --git a/src/logservice/palf/log_engine.cpp b/src/logservice/palf/log_engine.cpp index 05a53a54cc..d7b747cc2a 100644 --- a/src/logservice/palf/log_engine.cpp +++ b/src/logservice/palf/log_engine.cpp @@ -40,10 +40,12 @@ namespace palf // ===================== LogEngine start ======================= LogEngine::LogEngine() : - block_gc_lock_(common::ObLatchIds::PALF_LOG_ENGINE_LOCK), + min_block_info_lock_(common::ObLatchIds::PALF_LOG_ENGINE_LOCK), min_block_max_scn_(), min_block_id_(LOG_INVALID_BLOCK_ID), base_lsn_for_block_gc_(PALF_INITIAL_LSN_VAL), + min_block_min_scn_(), + min_block_info_cache_version_(0), log_meta_lock_(common::ObLatchIds::PALF_LOG_ENGINE_LOCK), log_meta_(), log_meta_storage_(), @@ -187,6 +189,8 @@ void LogEngine::destroy() base_lsn_for_block_gc_.reset(); min_block_id_ = LOG_INVALID_BLOCK_ID; min_block_max_scn_.reset(); + min_block_min_scn_.reset(); + min_block_info_cache_version_ = 0; last_purge_throttling_ts_ = OB_INVALID_TIMESTAMP; } } @@ -656,6 +660,8 @@ int LogEngine::read_group_entry_header(const LSN &lsn, LogGroupEntryHeader &log_ ReadBuf &read_buf = read_buf_guard.read_buf_; int64_t out_read_size = 0; int64_t pos = 0; + LogIOContext io_ctx(LogIOUser::DEFAULT); + if (IS_NOT_INIT) { ret = OB_NOT_INIT; } else if (false == lsn.is_valid()) { @@ -663,7 +669,7 @@ int LogEngine::read_group_entry_header(const LSN &lsn, LogGroupEntryHeader &log_ } else if (!read_buf.is_valid()) { ret = OB_ALLOCATE_MEMORY_FAILED; PALF_LOG(WARN, "allocate memory failed", KPC(this), K(lsn)); - } else if (OB_FAIL(log_storage_.pread_without_block_header(lsn, in_read_size, read_buf, out_read_size))) { + } else if (OB_FAIL(log_storage_.pread(lsn, in_read_size, read_buf, out_read_size, io_ctx))) { PALF_LOG(WARN, "LogStorage pread failed", K(ret)); } else if (OB_FAIL(log_group_entry_header.deserialize(read_buf.buf_, in_read_size, pos))) { PALF_LOG(WARN, @@ -699,6 +705,7 @@ int LogEngine::truncate(const LSN &lsn) } else if (OB_FAIL(log_storage_.truncate(lsn))) { PALF_LOG(ERROR, "LogStorage truncate failed", K(ret), K(lsn)); } else { + (void)reset_min_block_info_(); PALF_LOG(INFO, "truncate success", K(lsn)); } return ret; @@ -716,7 +723,9 @@ int LogEngine::truncate_prefix_blocks(const LSN &lsn) } else if (OB_FAIL(log_storage_.truncate_prefix_blocks(lsn))) { PALF_LOG(WARN, "truncate_prefix_blocks failed", K(ret), K_(palf_id), K_(is_inited), K(lsn)); } else { - PALF_LOG(INFO, "truncate_prefix_blocks success", K(ret), K_(palf_id), K_(is_inited), K(lsn)); } + (void)reset_min_block_info_(); + PALF_LOG(INFO, "truncate_prefix_blocks success", KPC(this), K(lsn)); + } return ret; } @@ -737,6 +746,7 @@ int LogEngine::end_flashback(const LSN &start_lsn_of_block) if (OB_FAIL(log_storage_.end_flashback(start_lsn_of_block))) { PALF_LOG(ERROR, "LogStorege end_flashback failed", K(ret), KPC(this), K(start_lsn_of_block)); } else { + (void)reset_min_block_info_(); PALF_LOG(INFO, "LogEngine end_flashback success", KPC(this), K(start_lsn_of_block)); } return ret; @@ -758,21 +768,42 @@ int LogEngine::delete_block(const block_id_t &block_id) } else if (false == is_valid_block_id(block_id)) { ret = OB_INVALID_ARGUMENT; PALF_LOG(ERROR, "Invalid argument!!!", K(ret), K_(palf_id), K_(is_inited), K(block_id)); - } else if (OB_FAIL(log_storage_.delete_block(block_id)) && OB_NO_SUCH_FILE_OR_DIRECTORY != ret) { - PALF_LOG(ERROR, "LogStorage delete block failed, unexpected error", K(ret), K(block_id)); - } else if (OB_NO_SUCH_FILE_OR_DIRECTORY == ret) { - PALF_LOG(INFO, "file not exist, may be concurrently delete by others module", K(ret), K(block_id)); - ret = OB_SUCCESS; + } else if (OB_FAIL(log_storage_.delete_block(block_id))) { + PALF_LOG(WARN, "LogStorage delete block failed", K(ret), K(block_id)); } else { PALF_LOG(INFO, "delete success", K(block_id), K_(palf_id), K_(is_inited)); } - int tmp_ret = OB_SUCCESS; - if (OB_SUCC(ret) && OB_SUCCESS != (tmp_ret = get_block_min_scn(next_block_id + 1, next_block_max_scn))) { - PALF_LOG(WARN, "get the max ts of next block failed", K(tmp_ret), K(next_block_id)); + // the block whose names with 'block_id' may be concurrently delete by rebuild, + // in this way, we don't need update min block info. + if (OB_NO_SUCH_FILE_OR_DIRECTORY == ret) { + PALF_LOG(INFO, "file not exist, may be concurrently delete by others module", K(ret), K(block_id)); + ret = OB_SUCCESS; + } else if (OB_SUCC(ret)) { + int64_t min_block_info_cache_version = -1; + { + ObSpinLockGuard guard(min_block_info_lock_); + min_block_info_cache_version = min_block_info_cache_version_; + } + int tmp_ret = OB_SUCCESS; + if (OB_SUCCESS != (tmp_ret = get_block_min_scn(next_block_id + 1, next_block_max_scn))) { + PALF_LOG(WARN, "get the max ts of next block failed", K(tmp_ret), K(next_block_id)); + reset_min_block_info_(); + } else { + // assume there are four blocks on disk, | 10 | 11 | 12 | 13 |, only when min using block id(i.e. cacluate by snapshot) + // is greater than or equal to 12, we can delete blocks whose names is smaller than or equal to 10. + // + // assume the block to be deleted is 10(i.e. min_block_id is 10), next_block_id is 11, next_block_id + 1 is 12. + // because the block whose names with 'next_block_id + 1' may be truncated or flashback, double check + // min_block_info_cache_version is important, otherwise, the cache of min block info + // (i.e. min_block_min_scn_, min_block_max_scn_) is incorrect, consider following case: + // T1 timestamp, thread A call delete_block, and get_block_min_scn successfully(e.g. next_block_id + 1 is 12); + // T2 timestamp, thread B call truncate or flashback, the content of block whose names with 12 is overwriten; + // T3 timestamp, thread A call set_min_block_info_for_gc_, and the min_block_info(i.e. min_block_max_scn_, min_block_min_scn_) + // will reset to incorrect scn. + set_min_block_info_for_gc_(min_block_info_cache_version, next_block_id, next_block_max_scn); + } } - // If 'delete_block' or 'get_block_min_scn' failed, need reset 'min_block_scn_' to be invalid. - reset_min_block_info_guarded_by_lock_(next_block_id, next_block_max_scn); return ret; } @@ -791,47 +822,86 @@ int LogEngine::get_block_id_range(block_id_t &min_block_id, block_id_t &max_bloc int LogEngine::get_min_block_info_for_gc(block_id_t &block_id, SCN &max_scn) { int ret = OB_SUCCESS; - block_id_t max_block_id = LOG_INVALID_BLOCK_ID; + block_id_t min_block_id_cache = LOG_INVALID_BLOCK_ID; block_id_t min_block_id = LOG_INVALID_BLOCK_ID; + block_id_t max_block_id = LOG_INVALID_BLOCK_ID; SCN min_block_max_scn; + int64_t min_block_info_cache_version = -1; do { - ObSpinLockGuard guard(block_gc_lock_); - min_block_id = min_block_id_; + ObSpinLockGuard guard(min_block_info_lock_); + min_block_id_cache = min_block_id_; min_block_max_scn = min_block_max_scn_; + min_block_info_cache_version = min_block_info_cache_version_; } while (0); if (IS_NOT_INIT) { ret = OB_NOT_INIT; PALF_LOG(WARN, "LogEngine is not inited", K(ret), KPC(this)); - } else if (min_block_max_scn.is_valid()) { - block_id = min_block_id; - max_scn = min_block_max_scn; } else if (OB_FAIL(get_block_id_range(min_block_id, max_block_id))) { PALF_LOG(WARN, "get_block_id_range failed", K(ret)); + // only use cache value when the min_block_id_cache is same as min_block_id get from LogBlockMgr + } else if (min_block_id_cache == min_block_id && min_block_max_scn.is_valid()) { + block_id = min_block_id; + max_scn = min_block_max_scn; // NB: used next block min_block_ts as the max_scn of current block } else if (OB_FAIL(get_block_min_scn(min_block_id+1, min_block_max_scn))) { PALF_LOG(TRACE, "get_block_min_scn failed", K(ret)); } else { - reset_min_block_info_guarded_by_lock_(min_block_id, min_block_max_scn); + // after the first call, 'min_block_max_scn_' is always valid.(except after rebuild, flashback or truncate) + // it's important to get 'min_block_info_cache_version' before 'get_block_min_scn', otherwise, the cache of + // min block info(i.e. min_block_max_scn_, min_block_min_scn_) is incorrect, consider following case: + // T1 timestamp, thread A call get_min_block_info_for_gc, and get_block_min_scn successfully(e.g. min_block_id is 10); + // T2 timestamp, thread B call truncate or flashback, the content of block whose names with 11 is overwriten; + // T3 timestamp, thread A call set_min_block_info_for_gc_, and the min_block_info(i.e. min_block_max_scn_, min_block_min_scn_) + // will reset to incorrect scn. + set_min_block_info_for_gc_(min_block_info_cache_version, min_block_id, min_block_max_scn); block_id = min_block_id; max_scn = min_block_max_scn; } return ret; } -int LogEngine::get_min_block_info(block_id_t &min_block_id, SCN &min_block_scn) const +int LogEngine::get_min_block_info(block_id_t &block_id, SCN &min_scn) { int ret = OB_SUCCESS; - block_id_t max_block_id; + block_id_t min_block_id_cache = LOG_INVALID_BLOCK_ID; + block_id_t min_block_id = LOG_INVALID_BLOCK_ID; + block_id_t max_block_id = LOG_INVALID_BLOCK_ID; + SCN min_block_min_scn; + int64_t min_block_info_cache_version = -1; + + do { + ObSpinLockGuard guard(min_block_info_lock_); + min_block_id_cache = min_block_id_; + min_block_min_scn = min_block_min_scn_; + min_block_info_cache_version = min_block_info_cache_version_; + } while (0); + if (IS_NOT_INIT) { ret = OB_NOT_INIT; PALF_LOG(WARN, "LogEngine is not inited", K(ret), KPC(this)); } else if (OB_FAIL(get_block_id_range(min_block_id, max_block_id))) { - PALF_LOG(WARN, "get_block_id_range failed", K(ret), KPC(this)); - } else if (OB_FAIL(get_block_min_scn(min_block_id, min_block_scn))) { - PALF_LOG(WARN, "get_block_min_scn failed", K(ret), KPC(this)); + PALF_LOG(TRACE, "get_block_id_range failed", K(ret)); + // only use cache value when the min_block_id_cache is same as min_block_id get from LogBlockMgr + } else if (min_block_id_cache == min_block_id && min_block_min_scn.is_valid()) { + block_id = min_block_id; + min_scn = min_block_min_scn; + } else if (OB_FAIL(get_block_min_scn(min_block_id, min_block_min_scn))) { + PALF_LOG(TRACE, "get_block_min_scn failed", K(ret)); } else { + // after the first call, 'min_block_min_scn_' is always valid.(except after rebuild, flashback or truncate) + // it's important to get 'min_block_info_cache_version' before 'get_block_min_scn', otherwise, the cache of + // min block info(i.e. min_block_min_scn_) is incorrect, consider following case: + // + // T1 timestamp, thread A call get_min_block_info, and get_block_min_scn successfully(e.g. min_block_id is 10); + // T2 timestamp, thread B call truncate for flashback, the content of block whose names with 10 is overwriten; + // T3 timestamp, thread A call set_min_block_info_, and the min_block_info(i.e. min_block_min_scn_) will reset + // to incorrect scn. + set_min_block_info_(min_block_info_cache_version, min_block_id, min_block_min_scn); + block_id = min_block_id; + min_scn = min_block_min_scn; + PALF_LOG(TRACE, "get_min_block_info read disk success.", K(block_id), K(min_scn)); } return ret; } @@ -878,6 +948,30 @@ int LogEngine::get_total_used_disk_space(int64_t &total_used_size_byte, return ret; } +int LogEngine::raw_read(const LSN &lsn, + const int64_t in_read_size, + const bool need_read_block_header, + ReadBuf &read_buf, + int64_t &out_read_size) +{ + int ret = OB_SUCCESS; + LogIOContext io_ctx(LogIOUser::DEFAULT); + // TODO modify @zjf225077 + + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + PALF_LOG(ERROR, "LogEngine not inited!!!", K(ret), K_(palf_id), K_(is_inited)); + } else if (false == lsn.is_valid() || 0 >= in_read_size || false == read_buf.is_valid()) { + ret = OB_INVALID_ARGUMENT; + PALF_LOG(ERROR, "Invalid argument!!!", K(ret), K_(palf_id), K_(is_inited), K(lsn), K(in_read_size), K(read_buf)); + } else if (need_read_block_header) { + ret = log_storage_.pread_with_block_header(lsn, in_read_size, read_buf, out_read_size); + } else if (!need_read_block_header) { + ret = log_storage_.pread(lsn, in_read_size, read_buf, out_read_size, io_ctx); + } else {} + return ret; +} + // ====================== LogStorage end ======================= // ===================== MetaStorage start ===================== @@ -1667,11 +1761,44 @@ bool LogEngine::check_last_block_whether_is_integrity_(const block_id_t expected || expected_next_block_id <= max_block_id; } -void LogEngine::reset_min_block_info_guarded_by_lock_(const block_id_t min_block_id, const SCN &min_block_max_scn) +void LogEngine::set_min_block_info_(const int64_t min_block_info_cache_version, + const block_id_t min_block_id, + const SCN &min_block_min_scn) { - ObSpinLockGuard guard(block_gc_lock_); - min_block_id_ = min_block_id; - min_block_max_scn_ = min_block_max_scn; + ObSpinLockGuard guard(min_block_info_lock_); + if (min_block_info_cache_version_ == min_block_info_cache_version) { + min_block_id_ = min_block_id; + min_block_min_scn_ = min_block_min_scn; + } +} + +void LogEngine::set_min_block_info_for_gc_(const int64_t min_block_info_cache_version, + const block_id_t min_block_id, + const SCN &min_block_max_scn) +{ + ObSpinLockGuard guard(min_block_info_lock_); + if (min_block_info_cache_version_ == min_block_info_cache_version) { + // defense code: + // only update min_block_min_scn_ to min_block_max_scn_ when min_block_id is same as min_block_id_ + 1 + if (!is_valid_block_id(min_block_id_) + || (min_block_id == min_block_id_ + 1 && min_block_max_scn_.is_valid())) { + min_block_min_scn_ = min_block_max_scn_; + } else { + min_block_min_scn_.reset(); + } + min_block_id_ = min_block_id; + min_block_max_scn_ = min_block_max_scn; + PALF_LOG(TRACE, "set_min_block_info_for_gc_ success.", K(min_block_id), K(min_block_max_scn)); + } +} + +void LogEngine::reset_min_block_info_() +{ + ObSpinLockGuard guard(min_block_info_lock_); + min_block_id_ = LOG_INVALID_BLOCK_ID; + min_block_min_scn_.reset(); + min_block_max_scn_.reset(); + min_block_info_cache_version_++; } LogNetService& LogEngine::get_net_service() diff --git a/src/logservice/palf/log_engine.h b/src/logservice/palf/log_engine.h index 59169f1c2f..5a9e1f3b2c 100644 --- a/src/logservice/palf/log_engine.h +++ b/src/logservice/palf/log_engine.h @@ -177,6 +177,11 @@ public: const LSN get_begin_lsn() const; int get_block_id_range(block_id_t &min_block_id, block_id_t &max_block_id) const; int get_block_min_scn(const block_id_t &block_id, share::SCN &scn) const; + int raw_read(const LSN &lsn, + const int64_t in_read_size, + const bool need_read_block_header, + ReadBuf &read_buf, + int64_t &out_read_size); // // ====================== LogStorage end ======================= @@ -431,17 +436,15 @@ public: LogMeta get_log_meta() const; const LSN &get_base_lsn_used_for_block_gc() const; - // not thread safe int get_min_block_info_for_gc(block_id_t &block_id, share::SCN &max_scn); - int get_min_block_info(block_id_t &block_id, share::SCN &min_scn) const; - // + int get_min_block_info(block_id_t &block_id, share::SCN &min_scn); // ===================== NetService end ======================== LogStorage *get_log_storage() { return &log_storage_; } LogStorage *get_log_meta_storage() { return &log_meta_storage_; } int get_total_used_disk_space(int64_t &total_used_size_byte, int64_t &unrecyclable_disk_space) const; virtual int64_t get_palf_epoch() const { return palf_epoch_; } - TO_STRING_KV(K_(palf_id), K_(is_inited), K_(min_block_max_scn), K_(min_block_id), K_(base_lsn_for_block_gc), + TO_STRING_KV(K_(palf_id), K_(is_inited), K_(min_block_max_scn), K_(min_block_id), K_(min_block_min_scn), K_(base_lsn_for_block_gc), K_(log_meta), K_(log_meta_storage), K_(log_storage), K_(palf_epoch), K_(last_purge_throttling_ts), KP(this)); private: int submit_flush_meta_task_(const FlushMetaCbCtx &flush_meta_cb_ctx, const LogMeta &log_meta); @@ -476,8 +479,15 @@ private: int serialize_log_meta_(const LogMeta &log_meta, char *buf, int64_t buf_len); - void reset_min_block_info_guarded_by_lock_(const block_id_t min_block_id, - const share::SCN &min_block_max_scn); + void set_min_block_info_(const int64_t min_block_info_cache_version, + const block_id_t min_block_id, + const share::SCN &min_block_min_scn); + + void reset_min_block_info_(); + + void set_min_block_info_for_gc_(const int64_t min_block_info_cache_version, + const block_id_t min_block_id, + const share::SCN &min_block_max_scn); int integrity_verify_(const LSN &last_meta_entry_start_lsn, const LSN &last_group_entry_header_lsn, @@ -487,11 +497,27 @@ private: const int64_t PURGE_THROTTLING_INTERVAL = 100 * 1000;//100ml private: - // used for GC - mutable ObSpinLock block_gc_lock_; + // ======================== begin used for GC =========================== + mutable ObSpinLock min_block_info_lock_; + // update it only in: + // 1) get min block info for gc. + // 2) delete min block. share::SCN min_block_max_scn_; + // update it only in: + // 1) get min block info for gc. + // 2) get min block info + // 3) delete min block. mutable block_id_t min_block_id_; + // update it only after write LogSnapshotMeta successfully LSN base_lsn_for_block_gc_; + // update it only in: + // 1) get min block info for gc. + // 2) get min block info. + // 3) delete min block. + share::SCN min_block_min_scn_; + // update it only in reset_min_block_info_ + int64_t min_block_info_cache_version_; + // ======================== end used for GC =========================== mutable ObSpinLock log_meta_lock_; LogMeta log_meta_; diff --git a/src/logservice/palf/log_io_task.cpp b/src/logservice/palf/log_io_task.cpp index 148d9e8cb9..a313691ea5 100644 --- a/src/logservice/palf/log_io_task.cpp +++ b/src/logservice/palf/log_io_task.cpp @@ -452,6 +452,8 @@ void LogIOTruncatePrefixBlocksTask::free_this_(IPalfEnvImpl *palf_env_impl) palf_env_impl->get_log_allocator()->free_log_io_truncate_prefix_blocks_task(this); } +int64_t BatchLogIOFlushLogTask::SINGLE_TASK_MAX_SIZE = MAX_LOG_BUFFER_SIZE; + BatchLogIOFlushLogTask::BatchLogIOFlushLogTask() : io_task_array_(), log_write_buf_array_(), @@ -459,6 +461,7 @@ BatchLogIOFlushLogTask::BatchLogIOFlushLogTask() lsn_array_(), palf_id_(INVALID_PALF_ID), accum_in_queue_time_(0), + accum_size_(0), is_inited_(false) {} @@ -486,6 +489,7 @@ int BatchLogIOFlushLogTask::init(const int64_t batch_depth, ObIAllocator *alloca } else if (OB_FAIL(lsn_array_.init(batch_depth))) { PALF_LOG(ERROR, "lsn_array_ init failed", K(ret)); } else { + accum_size_ = 0; is_inited_ = true; } if (OB_FAIL(ret) && OB_INIT_TWICE != ret) { @@ -501,6 +505,7 @@ void BatchLogIOFlushLogTask::reuse() scn_array_.clear(); lsn_array_.clear(); palf_id_ = INVALID_PALF_ID; + accum_size_ = 0; } void BatchLogIOFlushLogTask::destroy() @@ -517,16 +522,20 @@ int BatchLogIOFlushLogTask::push_back(LogIOFlushLogTask *task) { int ret = OB_SUCCESS; const int64_t palf_id = task->get_palf_id(); + const int64_t task_size = task->get_io_size_(); if (IS_NOT_INIT) { ret = OB_NOT_INIT; PALF_LOG(ERROR, "LogIOFlushMetaTask not inited!!!", K(ret), KPC(this)); } else if (palf_id_ != INVALID_PALF_ID && palf_id != palf_id_) { ret = OB_ERR_UNEXPECTED; PALF_LOG(ERROR, "only same palf id can be batched", K(ret), KPC(task), K(palf_id)); + } else if (accum_size_ > SINGLE_TASK_MAX_SIZE) { + ret = OB_SIZE_OVERFLOW; } else if (OB_FAIL(io_task_array_.push_back(task))) { PALF_LOG(WARN, "push failed", K(ret)); } else { palf_id_ = palf_id; + accum_size_ += task_size; PALF_LOG(TRACE, "push_back success", K(palf_id_), KPC(this)); } return ret; diff --git a/src/logservice/palf/log_io_task.h b/src/logservice/palf/log_io_task.h index 2751c964b5..6be1bc37e6 100644 --- a/src/logservice/palf/log_io_task.h +++ b/src/logservice/palf/log_io_task.h @@ -200,11 +200,12 @@ public: int64_t get_count() const { return io_task_array_.count(); } int64_t get_accum_in_queue_time() const { return accum_in_queue_time_; } - TO_STRING_KV(K_(palf_id), "count", io_task_array_.count(), K_(lsn_array)); + TO_STRING_KV(K_(palf_id), "count", io_task_array_.count(), K_(lsn_array), K_(accum_size)); private: int push_flush_cb_to_thread_pool_(int tg_id, IPalfEnvImpl *palf_env_impl); int do_task_(int tg_id, IPalfEnvImpl *palf_env_impl); void clear_memory_(IPalfEnvImpl *palf_env_impl); + static int64_t SINGLE_TASK_MAX_SIZE; private: BatchIOTaskArray io_task_array_; LogWriteBufArray log_write_buf_array_; @@ -212,6 +213,7 @@ private: LSNArray lsn_array_; int64_t palf_id_; int64_t accum_in_queue_time_; + int64_t accum_size_; bool is_inited_; }; diff --git a/src/logservice/palf/log_io_worker.cpp b/src/logservice/palf/log_io_worker.cpp index 69cc7728ce..c1bfaf655f 100644 --- a/src/logservice/palf/log_io_worker.cpp +++ b/src/logservice/palf/log_io_worker.cpp @@ -310,7 +310,7 @@ int LogIOWorker::reduce_io_task_(void *task) // 2. there is full in each BatchLogIOFlushLogTask in 'batch_io_task_mgr_'. if (OB_SUCCESS != (tmp_ret = batch_io_task_mgr_.insert(flush_log_task))) { last_io_task_has_been_reduced = false; - PALF_LOG(WARN, "batch_io_task_mgr_ insert failed", K(tmp_ret)); + PALF_LOG(TRACE, "batch_io_task_mgr_ insert failed", K(tmp_ret)); } else if (OB_SUCCESS == (tmp_ret = queue_.pop(task))) { // When 'queue_' is empty, stop aggreating. update_throttling_options_(); @@ -341,7 +341,7 @@ int LogIOWorker::update_throttling_options_() } LogIOWorker::BatchLogIOFlushLogTaskMgr::BatchLogIOFlushLogTaskMgr() - : handle_count_(0), has_batched_size_(0), usable_count_(0), batch_width_(0), + : handle_count_(0), usable_count_(0), batch_width_(0), wait_cost_stat_(NULL) {} @@ -395,7 +395,7 @@ int LogIOWorker::BatchLogIOFlushLogTaskMgr::init(int64_t batch_width, void LogIOWorker::BatchLogIOFlushLogTaskMgr::destroy() { - handle_count_ = has_batched_size_ = batch_width_ = usable_count_ = 0; + handle_count_ = batch_width_ = usable_count_ = 0; for (int i = 0; i < batch_io_task_array_.count(); i++) { BatchLogIOFlushLogTask *&io_task = batch_io_task_array_[i]; if (NULL != io_task) { @@ -416,8 +416,7 @@ int LogIOWorker::BatchLogIOFlushLogTaskMgr::insert(LogIOFlushLogTask *io_task) if (OB_FAIL(find_usable_batch_io_task_(palf_id, batch_io_task))) { PALF_LOG(WARN, "find_usable_batch_io_task_ failed", K(ret), K(palf_id)); } else if (OB_FAIL(batch_io_task->push_back(io_task))) { - PALF_LOG(ERROR, "batch_io_task must have enouch space to hold io_task, unexpected error!!!", - K(ret), KP(batch_io_task)); + PALF_LOG(TRACE, "push_back failed", K(ret), K(palf_id), KPC(io_task)); } else { } return ret; @@ -446,13 +445,12 @@ int LogIOWorker::BatchLogIOFlushLogTaskMgr::handle(const int64_t tg_id, IPalfEnv wait_cost_stat_->stat(io_task->get_count(), io_task->get_accum_in_queue_time()); } io_task->reset_accum_in_queue_time(); - PALF_LOG(TRACE, "BatchLogIOFlushLogTaskMgr::handle success", K(ret), K(has_batched_size_), + PALF_LOG(TRACE, "BatchLogIOFlushLogTaskMgr::handle success", K(ret), K(handle_count_), KP(io_task)); } if (OB_NOT_NULL(io_task)) { - // 'handle_count_' and 'has_batched_size_' are used for statistics - handle_count_ += io_task->get_count() <= 1 ? 0 : 1; - has_batched_size_ += io_task->get_count() == 1 ? 0 : io_task->get_count(); + // 'handle_count_' used for statistics + handle_count_ += io_task->get_count(); io_task->reuse(); usable_count_++; } diff --git a/src/logservice/palf/log_io_worker.h b/src/logservice/palf/log_io_worker.h index 53f8b81f63..cd7edf0245 100644 --- a/src/logservice/palf/log_io_worker.h +++ b/src/logservice/palf/log_io_worker.h @@ -119,7 +119,6 @@ private: typedef ObFixedArray BatchLogIOFlushLogTaskArray; BatchLogIOFlushLogTaskArray batch_io_task_array_; int64_t handle_count_; - int64_t has_batched_size_; int64_t usable_count_; int64_t batch_width_; ObMiniStat::ObStatItem *wait_cost_stat_; diff --git a/src/logservice/palf/log_reader.cpp b/src/logservice/palf/log_reader.cpp index 00e178a0fd..cf5933b229 100644 --- a/src/logservice/palf/log_reader.cpp +++ b/src/logservice/palf/log_reader.cpp @@ -68,28 +68,36 @@ int LogReader::pread(const block_id_t block_id, int read_io_fd = -1; out_read_size = 0; char block_path[OB_MAX_FILE_NAME_LENGTH] = {'\0'}; - if (OB_FAIL(convert_to_normal_block(log_dir_, block_id, block_path, OB_MAX_FILE_NAME_LENGTH))) { + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + PALF_LOG(WARN, "pread failed", K(block_id), K(offset), K(in_read_size), K(read_buf)); + } else if (!is_valid_block_id(block_id) || offset >= block_size_ || 0 >= in_read_size || !read_buf.is_valid()) { + ret = OB_INVALID_ARGUMENT; + PALF_LOG(WARN, "invalid argument", K(block_id), K(offset), K(in_read_size), K(read_buf)); + } else if (OB_FAIL(convert_to_normal_block(log_dir_, block_id, block_path, OB_MAX_FILE_NAME_LENGTH))) { PALF_LOG(ERROR, "convert_to_normal_block failed", K(ret)); } else if (-1 == (read_io_fd = ::open(block_path, LOG_READ_FLAG))) { - ret = ENOENT == errno ? OB_NO_SUCH_FILE_OR_DIRECTORY : OB_IO_ERROR; + ret = convert_sys_errno(); PALF_LOG(WARN, "LogReader open block failed", K(ret), K(errno), K(block_path), K(read_io_fd)); } else { int64_t remained_read_size = in_read_size; + int64_t remained_read_buf_len = read_buf.buf_len_; int64_t step = MAX_LOG_BUFFER_SIZE; while (remained_read_size > 0 && OB_SUCC(ret)) { const int64_t curr_in_read_size = MIN(step, remained_read_size); char *curr_read_buf = read_buf.buf_ + in_read_size - remained_read_size; - const offset_t curr_read_lsn = offset + in_read_size - remained_read_size; + const offset_t curr_read_offset = offset + in_read_size - remained_read_size; + const int64_t curr_read_buf_len = remained_read_buf_len - out_read_size; int64_t curr_out_read_size = 0; - if (OB_FAIL(inner_pread_(read_io_fd, curr_read_lsn, curr_in_read_size, curr_read_buf, curr_out_read_size))) { + if (OB_FAIL(inner_pread_(read_io_fd, curr_read_offset, curr_in_read_size, curr_read_buf, curr_read_buf_len, curr_out_read_size))) { PALF_LOG(WARN, "LogReader inner_pread_ failed", K(ret), K(read_io_fd), K(block_id), K(offset), - K(in_read_size), K(read_buf), K(curr_in_read_size), K(curr_read_lsn), K(curr_out_read_size), + K(in_read_size), K(read_buf), K(curr_in_read_size), K(curr_read_offset), K(curr_out_read_size), K(remained_read_size), K(block_path)); } else { out_read_size += curr_out_read_size; remained_read_size -= curr_out_read_size; PALF_LOG(TRACE, "inner_pread_ success", K(ret), K(read_io_fd), K(block_id), K(offset), K(in_read_size), - K(out_read_size), K(read_buf), K(curr_in_read_size), K(curr_read_lsn), K(curr_out_read_size), + K(out_read_size), K(read_buf), K(curr_in_read_size), K(curr_read_offset), K(curr_out_read_size), K(remained_read_size), K(block_path)); } } @@ -106,6 +114,7 @@ int LogReader::inner_pread_(const int read_io_fd, offset_t start_offset, int64_t in_read_size, char *read_buf, + const int64_t read_buf_len, int64_t &out_read_size) const { int ret = OB_SUCCESS; @@ -113,15 +122,14 @@ int LogReader::inner_pread_(const int read_io_fd, offset_t backoff = start_offset - aligned_start_offset; int64_t aligned_in_read_size = upper_align(in_read_size + backoff, LOG_DIO_ALIGN_SIZE); int64_t limited_and_aligned_in_read_size = 0; - if (MAX_LOG_BUFFER_SIZE + LOG_DIO_ALIGN_SIZE < aligned_in_read_size) { - ret = OB_BUF_NOT_ENOUGH; - PALF_LOG(ERROR, "aligned_in_read_size is greater than MAX BUFFER LEN", - K(ret), K(read_io_fd), K(start_offset), K(aligned_start_offset), K(backoff), K(in_read_size), K(aligned_in_read_size)); - } else if (OB_FAIL(limit_and_align_in_read_size_by_block_size_( + if (OB_FAIL(limit_and_align_in_read_size_by_block_size_( aligned_start_offset, aligned_in_read_size, limited_and_aligned_in_read_size))) { PALF_LOG(WARN, "limited_and_aligned_in_read_size failed, maybe read offset exceed block size", K(ret), K(start_offset), K(in_read_size), K(aligned_start_offset), K(aligned_in_read_size), K(limited_and_aligned_in_read_size)); + } else if (limited_and_aligned_in_read_size > read_buf_len) { + ret = OB_BUF_NOT_ENOUGH; + PALF_LOG(WARN, "buffer not enough to hold read result"); } else if (0 >= (out_read_size = ob_pread(read_io_fd, read_buf, limited_and_aligned_in_read_size, aligned_start_offset))){ ret = OB_ERR_UNEXPECTED; PALF_LOG(WARN, "pread failed, maybe concurrently with truncate", K(ret), K(read_io_fd), K(aligned_start_offset), diff --git a/src/logservice/palf/log_reader.h b/src/logservice/palf/log_reader.h index fac1d51479..7340ffa4a0 100644 --- a/src/logservice/palf/log_reader.h +++ b/src/logservice/palf/log_reader.h @@ -50,6 +50,7 @@ private: offset_t start_offset, int64_t in_read_size, char *read_buf, + const int64_t read_buf_len, int64_t &out_read_size) const; private: diff --git a/src/logservice/palf/log_reader_utils.cpp b/src/logservice/palf/log_reader_utils.cpp index 4260e03475..e7df5c7c44 100644 --- a/src/logservice/palf/log_reader_utils.cpp +++ b/src/logservice/palf/log_reader_utils.cpp @@ -100,5 +100,25 @@ void free_read_buf(ReadBuf &read_buf) read_buf.buf_len_ = 0; } } + +bool is_valid_raw_read_buf(const ReadBuf &raw_read_buf, + const int64_t offset, + const int64_t nbytes) +{ + bool bool_ret = false; + if (!raw_read_buf.is_valid() || offset < 0) { + bool_ret = false; + } else { + const char *ptr = raw_read_buf.buf_; + const char *aligned_ptr = reinterpret_cast(common::upper_align( + reinterpret_cast(ptr), + LOG_DIO_ALIGN_SIZE)); + const int64_t aligned_offset = common::upper_align(offset, LOG_DIO_ALIGN_SIZE); + const int64_t aligned_nbytes = common::upper_align(nbytes, LOG_DIO_ALIGN_SIZE); + bool_ret = (ptr == aligned_ptr && offset == aligned_offset && nbytes == aligned_nbytes); + } + return bool_ret; +} + } // end of logservice } // end of oceanbase diff --git a/src/logservice/palf/log_reader_utils.h b/src/logservice/palf/log_reader_utils.h index a1c07a82a5..53e808bee2 100644 --- a/src/logservice/palf/log_reader_utils.h +++ b/src/logservice/palf/log_reader_utils.h @@ -30,6 +30,7 @@ struct ReadBuf ~ReadBuf(); void reset(); bool is_valid() const; + bool is_valid_raw_read_buf(); TO_STRING_KV(K(buf_len_), KP(buf_)); char *buf_; @@ -45,6 +46,11 @@ struct ReadBufGuard int alloc_read_buf(const char *label, const int64_t buf_len, ReadBuf &read_buf); void free_read_buf(ReadBuf &read_buf); + +bool is_valid_raw_read_buf(const ReadBuf &raw_read_buf, + const int64_t offset, + const int64_t nbytes); + } // end of logservice } // end of oceanbase diff --git a/src/logservice/palf/log_storage.cpp b/src/logservice/palf/log_storage.cpp index 3c5cc61035..0275937328 100644 --- a/src/logservice/palf/log_storage.cpp +++ b/src/logservice/palf/log_storage.cpp @@ -298,13 +298,13 @@ int LogStorage::pread(const LSN &read_lsn, return ret; } -int LogStorage::pread_without_block_header(const LSN &read_lsn, - const int64_t in_read_size, - ReadBuf &read_buf, - int64_t &out_read_size) +int LogStorage::pread_with_block_header(const LSN &read_lsn, + const int64_t in_read_size, + ReadBuf &read_buf, + int64_t &out_read_size) { int ret = OB_SUCCESS; - bool need_read_with_block_header = false; + bool need_read_with_block_header = true; if (IS_NOT_INIT) { ret = OB_NOT_INIT; PALF_LOG(ERROR, "LogStorage not inited!!!", K(ret)); diff --git a/src/logservice/palf/log_storage.h b/src/logservice/palf/log_storage.h index eef83d3191..2a8caffca4 100644 --- a/src/logservice/palf/log_storage.h +++ b/src/logservice/palf/log_storage.h @@ -91,10 +91,10 @@ public: int64_t &out_read_size, LogIOContext &io_ctx) final; - int pread_without_block_header(const LSN &read_lsn, - const int64_t in_read_size, - ReadBuf &read_buf, - int64_t &out_read_size); + int pread_with_block_header(const LSN &read_lsn, + const int64_t in_read_size, + ReadBuf &read_buf, + int64_t &out_read_size); int truncate(const LSN &lsn); int truncate_prefix_blocks(const LSN &lsn); diff --git a/src/logservice/palf/log_updater.h b/src/logservice/palf/log_updater.h index 0c0fad7ce4..2b161f3428 100644 --- a/src/logservice/palf/log_updater.h +++ b/src/logservice/palf/log_updater.h @@ -31,7 +31,6 @@ public: virtual void runTimerTask(); private: IPalfEnvImpl *palf_env_impl_; - int64_t warn_time_; int tg_id_; bool is_inited_; }; diff --git a/src/logservice/palf/palf_callback.h b/src/logservice/palf/palf_callback.h index ccb35f8ab4..ef960542c9 100644 --- a/src/logservice/palf/palf_callback.h +++ b/src/logservice/palf/palf_callback.h @@ -107,6 +107,13 @@ public: const common::ObRole &curr_role, const palf::ObReplicaState &curr_state, const char *extra_info = NULL) = 0; + virtual int record_parent_child_change_event(const int64_t palf_id, + const bool is_register, /* true: register; false; retire; */ + const bool is_parent, /* true: parent; false: child; */ + const common::ObAddr &server, + const common::ObRegion ®ion, + const int64_t register_time_us, + const char *extra_info = NULL) = 0; // performance statistic virtual int add_log_write_stat(const int64_t palf_id, const int64_t log_write_size) = 0; @@ -126,6 +133,12 @@ public: const char *extra_info) = 0; }; +class PalfLocalityInfoCb +{ +public: + virtual int get_server_region(const common::ObAddr &server, common::ObRegion ®ion) const = 0; +}; + } // end namespace palf } // end namespace oceanbase #endif diff --git a/src/logservice/palf/palf_callback_wrapper.cpp b/src/logservice/palf/palf_callback_wrapper.cpp index be456d698f..d35466f9c3 100644 --- a/src/logservice/palf/palf_callback_wrapper.cpp +++ b/src/logservice/palf/palf_callback_wrapper.cpp @@ -175,7 +175,9 @@ LogPlugins::LogPlugins() palf_monitor_lock_(), palf_monitor_(NULL), palflite_monitor_lock_(), - palflite_monitor_(NULL) { } + palflite_monitor_(NULL), + locality_cb_lock_(), + locality_cb_(NULL) { } LogPlugins::~LogPlugins() { @@ -196,6 +198,10 @@ void LogPlugins::destroy() common::RWLock::WLockGuard guard(palflite_monitor_lock_); palflite_monitor_ = NULL; } + { + common::RWLock::WLockGuard guard(locality_cb_lock_); + locality_cb_ = NULL; + } } template<> @@ -288,5 +294,35 @@ int LogPlugins::del_plugin(PalfLiteMonitorCb *plugin) return ret; } +template<> +int LogPlugins::add_plugin(PalfLocalityInfoCb *plugin) +{ + int ret = OB_SUCCESS; + common::RWLock::WLockGuard guard(locality_cb_lock_); + if (OB_ISNULL(plugin)) { + ret = OB_INVALID_ARGUMENT; + PALF_LOG(WARN, "Palf plugin is NULL", KP(plugin)); + } else if (OB_NOT_NULL(locality_cb_)) { + ret = OB_OP_NOT_ALLOW; + PALF_LOG(INFO, "Palf plugin is not NULL", KP(plugin), KP_(locality_cb)); + } else { + locality_cb_ = plugin; + PALF_LOG(INFO, "add_plugin success", KP(plugin)); + } + return ret; +} + +template<> +int LogPlugins::del_plugin(PalfLocalityInfoCb *plugin) +{ + int ret = OB_SUCCESS; + common::RWLock::WLockGuard guard(locality_cb_lock_); + if (OB_NOT_NULL(locality_cb_)) { + PALF_LOG(INFO, "del_plugin success", KP_(locality_cb)); + locality_cb_ = NULL; + } + return ret; +} + }; // end namespace palf }; // end namespace oceanbase diff --git a/src/logservice/palf/palf_callback_wrapper.h b/src/logservice/palf/palf_callback_wrapper.h index 5b473b4fa7..2804cd1272 100644 --- a/src/logservice/palf/palf_callback_wrapper.h +++ b/src/logservice/palf/palf_callback_wrapper.h @@ -130,8 +130,11 @@ public: PALF_PLUGINS_DELEGATE_PTR(palf_monitor_, palf_monitor_lock_, record_truncate_event); PALF_PLUGINS_DELEGATE_PTR(palf_monitor_, palf_monitor_lock_, record_role_change_event); PALF_PLUGINS_DELEGATE_PTR(palf_monitor_, palf_monitor_lock_, add_log_write_stat); + PALF_PLUGINS_DELEGATE_PTR(palf_monitor_, palf_monitor_lock_, record_parent_child_change_event); PALF_PLUGINS_DELEGATE_PTR(palflite_monitor_, palflite_monitor_lock_, record_create_or_delete_event); + + PALF_PLUGINS_DELEGATE_PTR(locality_cb_, locality_cb_lock_, get_server_region); TO_STRING_KV(KP_(loc_cb), KP_(palf_monitor), KP_(palflite_monitor)); private: common::RWLock loc_lock_; @@ -140,6 +143,8 @@ private: PalfMonitorCb *palf_monitor_; common::RWLock palflite_monitor_lock_; PalfLiteMonitorCb *palflite_monitor_; + common::RWLock locality_cb_lock_; + PalfLocalityInfoCb *locality_cb_; }; } // end namespace palf } // end namespace oceanbase diff --git a/src/logservice/palf/palf_handle.cpp b/src/logservice/palf/palf_handle.cpp index 22e82b0c49..aed72f2a81 100755 --- a/src/logservice/palf/palf_handle.cpp +++ b/src/logservice/palf/palf_handle.cpp @@ -109,17 +109,6 @@ int PalfHandle::get_arbitration_member(common::ObMember &arb_member) const } #endif -int PalfHandle::set_region(const common::ObRegion ®ion) -{ - CHECK_VALID; - return palf_handle_impl_->set_region(region); -} - -int PalfHandle::set_paxos_member_region_map(const common::ObArrayHashMap ®ion_map) -{ - CHECK_VALID; - return palf_handle_impl_->set_paxos_member_region_map(region_map); -} int PalfHandle::append(const PalfAppendOptions &opts, const void *buffer, const int64_t nbytes, @@ -713,6 +702,31 @@ int PalfHandle::advance_election_epoch_and_downgrade_priority(const int64_t prop reason); } +int PalfHandle::set_locality_cb(PalfLocalityInfoCb *locality_cb) +{ + int ret = OB_SUCCESS; + CHECK_VALID; + if (OB_ISNULL(locality_cb)) { + PALF_LOG(INFO, "no need set_locality_cb", KR(ret), KP(locality_cb)); + } else if (OB_FAIL(palf_handle_impl_->set_locality_cb(locality_cb))) { + PALF_LOG(WARN, "set_locality_cb failed", KR(ret)); + } else { + } + return ret; +} + +int PalfHandle::reset_locality_cb() +{ + int ret = OB_SUCCESS; + CHECK_VALID; + if (OB_FAIL(palf_handle_impl_->reset_locality_cb())) { + PALF_LOG(WARN, "reset_locality_cb failed", KR(ret)); + } else { + PALF_LOG(INFO, "reset_locality_cb success", KR(ret)); + } + return ret; +} + int PalfHandle::stat(PalfStat &palf_stat) const { CHECK_VALID; @@ -744,5 +758,14 @@ int PalfHandle::diagnose(PalfDiagnoseInfo &diagnose_info) const return palf_handle_impl_->diagnose(diagnose_info); } +int PalfHandle::raw_read(const palf::LSN &lsn, + void *buffer, + const int64_t nbytes, + int64_t &read_size) +{ + CHECK_VALID; + return palf_handle_impl_->raw_read(lsn, reinterpret_cast(buffer), nbytes, read_size); +} + } // end namespace palf } // end namespace oceanbase diff --git a/src/logservice/palf/palf_handle.h b/src/logservice/palf/palf_handle.h index 1c54171f69..18d4103ba0 100755 --- a/src/logservice/palf/palf_handle.h +++ b/src/logservice/palf/palf_handle.h @@ -80,8 +80,6 @@ public: const int64_t paxos_replica_num, const common::GlobalLearnerList &learner_list); #endif - int set_region(const common::ObRegion ®ion); - int set_paxos_member_region_map(const common::ObArrayHashMap ®ion_map); //================ 文件访问相关接口 ======================= int append(const PalfAppendOptions &opts, const void *buffer, @@ -95,6 +93,32 @@ public: const void *buffer, const int64_t nbytes); + // @brief: read up to 'nbytes' from palf at offset of 'lsn' into the 'read_buf', and + // there are alignment restrictions on the length and address of user-space buffers + // and the file offset. + // + // @param[in] lsn, the start offset to be read, must be aligned with LOG_DIO_ALIGN_SIZE + // @param[in] buffer, the start of 'buffer', must be aligned with LOG_DIO_ALIGN_SIZE. + // @param[in] nbytes, the read size, must aligned with LOG_DIO_ALIGN_SIZE + // @param[out] read_size, the number of bytes read return. + // + // @return value + // OB_SUCCESS. + // OB_INVALID_ARGUMENT. + // OB_ERR_OUT_OF_LOWER_BOUND, the lsn is out of lower bound. + // OB_ERR_OUT_OF_UPPER_BOUND, the lsn is out of upper bound. + // OB_NEED_RETRY, there is a flashback operation during raw_read. + // others. + // + // 1. use oceanbase::share::mtl_malloc_align or oceanbase::common::ob_malloc_align + // with LOG_DIO_ALIGN_SIZE to allocate aligned buffer. + // 2. use oceanbase::common::lower_align or oceanbase::common::upper_align with + // LOG_DIO_ALIGN_SIZE to get aligned lsn or nbytes. + int raw_read(const palf::LSN &lsn, + void *buffer, + const int64_t nbytes, + int64_t &read_size); + // iter->next返回的是append调用写入的值,不会在返回的buf中携带Palf增加的header信息 // 返回的值不包含未确认日志 // @@ -502,6 +526,8 @@ public: int reset_location_cache_cb(); int set_election_priority(election::ElectionPriority *priority); int reset_election_priority(); + int set_locality_cb(palf::PalfLocalityInfoCb *locality_cb); + int reset_locality_cb(); int stat(PalfStat &palf_stat) const; //---------config change lock related--------// diff --git a/src/logservice/palf/palf_handle_impl.cpp b/src/logservice/palf/palf_handle_impl.cpp index f033fed847..2284729fff 100755 --- a/src/logservice/palf/palf_handle_impl.cpp +++ b/src/logservice/palf/palf_handle_impl.cpp @@ -90,6 +90,7 @@ PalfHandleImpl::PalfHandleImpl() chaning_config_warn_time_(OB_INVALID_TIMESTAMP), cached_is_in_sync_(false), has_higher_prio_config_change_(false), + last_update_region_time_us_(OB_INVALID_TIMESTAMP), is_inited_(false) { log_dir_[0] = '\0'; @@ -391,26 +392,28 @@ int PalfHandleImpl::get_base_info(const LSN &base_lsn, PalfBaseInfo &base_info) return ret; } -int PalfHandleImpl::set_region(const common::ObRegion ®ion) +int PalfHandleImpl::update_self_region_() { int ret = OB_SUCCESS; - WLockGuard guard(lock_); - if (IS_NOT_INIT) { - ret = OB_NOT_INIT; - } else if (OB_FAIL(config_mgr_.set_region(region))) { - PALF_LOG(WARN, "set_region failed", KR(ret), K(region)); - } - return ret; -} - -int PalfHandleImpl::set_paxos_member_region_map(const LogMemberRegionMap ®ion_map) -{ - int ret = OB_SUCCESS; - WLockGuard guard(lock_); - if (IS_NOT_INIT) { - ret = OB_NOT_INIT; - } else if (config_mgr_.set_paxos_member_region_map(region_map)) { - PALF_LOG(WARN, "set_paxos_member_region_map failed", KR(ret), KPC(this)); + common::ObRegion new_region, curr_region; + do { + RLockGuard guard(lock_); + if (OB_FAIL(config_mgr_.get_region(curr_region))) { + PALF_LOG(WARN, "get_region failed", K(ret), KPC(this)); + } + } while (0); + if (OB_FAIL(ret)) { + PALF_LOG(WARN, "get_region failed", K(ret), KPC(this)); + } else if (OB_FAIL(plugins_.get_server_region(self_, new_region))) { + PALF_LOG(WARN, "get_server_region failed", K(ret), KPC(this)); + } else if (curr_region != new_region) { + WLockGuard guard(lock_); + if (OB_FAIL(config_mgr_.set_region(new_region))) { + PALF_LOG(WARN, "get_server_region failed", K(ret), K(new_region), KPC(this)); + } else { + PALF_LOG(INFO, "update_self_region_ success", K(ret), K(curr_region), + K(new_region), KPC(this)); + } } return ret; } @@ -2566,6 +2569,35 @@ int PalfHandleImpl::reset_monitor_cb() return ret; } +int PalfHandleImpl::set_locality_cb(palf::PalfLocalityInfoCb *locality_cb) +{ + int ret = OB_SUCCESS; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + PALF_LOG(WARN, "not initted", KR(ret), KPC(this)); + } else if (OB_ISNULL(locality_cb)) { + ret = OB_INVALID_ARGUMENT; + PALF_LOG(WARN, "locality_cb is NULL, can't register", KR(ret), KPC(this)); + } else if (OB_FAIL(plugins_.add_plugin(locality_cb))) { + PALF_LOG(WARN, "add_plugin failed", KR(ret), KPC(this), KP(locality_cb), K_(plugins)); + } else { + PALF_LOG(INFO, "set_locality_cb success", KPC(this), K_(plugins), KP(locality_cb)); + } + return ret; +} + +int PalfHandleImpl::reset_locality_cb() +{ + int ret = OB_SUCCESS; + PalfLocalityInfoCb *locality_cb = NULL; + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + } else if (OB_FAIL(plugins_.del_plugin(locality_cb))) { + PALF_LOG(WARN, "del_plugin failed", KR(ret), KPC(this), K_(plugins)); + } + return ret; +} + int PalfHandleImpl::check_and_switch_freeze_mode() { int ret = OB_SUCCESS; @@ -2649,6 +2681,10 @@ int PalfHandleImpl::check_and_switch_state() } (void) sw_.report_log_task_trace(sw_.get_start_id()); } + if (palf_reach_time_interval(PALF_UPDATE_REGION_INTERVAL_US, last_update_region_time_us_) && + OB_FAIL(update_self_region_())) { + PALF_LOG(WARN, "update_region failed", K(ret), KPC(this)); + } } return OB_SUCCESS; } @@ -4600,6 +4636,7 @@ int PalfHandleImpl::diagnose(PalfDiagnoseInfo &diagnose_info) const state_mgr_.get_election_role(diagnose_info.election_role_, diagnose_info.election_epoch_); diagnose_info.enable_sync_ = state_mgr_.is_sync_enabled(); diagnose_info.enable_vote_ = state_mgr_.is_allow_vote(); + diagnose_info.parent_ = config_mgr_.get_parent(); return ret; } @@ -5524,6 +5561,48 @@ int PalfHandleImpl::read_data_from_buffer(const LSN &read_begin_lsn, return ret; } +int PalfHandleImpl::raw_read(const LSN &lsn, + char *buffer, + const int64_t nbytes, + int64_t &read_size) +{ + int ret = OB_SUCCESS; + const LSN readable_end_lsn = get_end_lsn(); + LSN readable_begin_lsn; + int64_t real_read_size = 0; + read_size = 0; + const bool need_read_block_header = false; + ObTimeGuard time_guard("raw_read", 100 * 1000); + ReadBuf read_buf(buffer, nbytes); + if (IS_NOT_INIT) { + ret = OB_NOT_INIT; + PALF_LOG(WARN, "PalfHandleImp not inited", K(ret), K_(palf_id), K(lsn), K(nbytes), K(read_buf)); + } else if (!lsn.is_valid() + || !is_valid_raw_read_buf(read_buf, lsn_2_offset(lsn, PALF_BLOCK_SIZE), nbytes)) { + ret = OB_INVALID_ARGUMENT; + PALF_LOG(WARN, "invalid arguments", K(ret), K_(palf_id), K(lsn), K(nbytes), K(read_buf)); + } else if (OB_FAIL(get_begin_lsn(readable_begin_lsn))) { + PALF_LOG(WARN, "get_begin_lsn failed", K(ret), K_(palf_id), K(lsn), K(nbytes), K(read_buf)); + } else if (lsn < readable_begin_lsn) { + ret = OB_ERR_OUT_OF_LOWER_BOUND; + PALF_LOG(WARN, "read something out of lower bound", K(ret), K_(palf_id), K(lsn), K(nbytes), + K(read_size), K(readable_begin_lsn)); + } else if (lsn >= readable_end_lsn) { + ret = OB_ERR_OUT_OF_UPPER_BOUND; + PALF_LOG(WARN, "read something out of upper bound", K(ret), K_(palf_id), K(lsn), + K(nbytes), K(read_size), K(readable_end_lsn)); + // only read the data before readable_end_lsn + } else if (FALSE_IT(real_read_size = MIN(nbytes, readable_end_lsn - lsn))) { + } else if (OB_FAIL(log_engine_.raw_read(lsn, real_read_size, need_read_block_header, read_buf, read_size))) { + PALF_LOG(WARN, "read_log from storage failed", K(ret), K_(palf_id), K(lsn), + K(nbytes), K(real_read_size), K(readable_end_lsn), K(read_size)); + } else { + PALF_LOG(TRACE, "raw_read success", K(ret), K_(palf_id), K(lsn), K(nbytes), + K(real_read_size), K(readable_end_lsn), K(read_size), K(time_guard)); + } + return ret; +} + OB_SERIALIZE_MEMBER(PalfStat, self_, palf_id_, role_, log_proposal_id_, config_version_, mode_version_, access_mode_, paxos_member_list_, paxos_replica_num_, allow_vote_, replica_type_, begin_lsn_, begin_scn_, base_lsn_, end_lsn_, end_scn_, max_lsn_, max_scn_, diff --git a/src/logservice/palf/palf_handle_impl.h b/src/logservice/palf/palf_handle_impl.h index 11dd1e9c2d..d9f83d99ce 100755 --- a/src/logservice/palf/palf_handle_impl.h +++ b/src/logservice/palf/palf_handle_impl.h @@ -111,6 +111,7 @@ struct PalfDiagnoseInfo { int64_t palf_proposal_id_; bool enable_sync_; bool enable_vote_; + common::ObAddr parent_; void reset() { election_role_ = FOLLOWER; election_epoch_ = 0; @@ -119,6 +120,7 @@ struct PalfDiagnoseInfo { palf_proposal_id_ = INVALID_PROPOSAL_ID; enable_sync_ = false; enable_vote_ = false; + parent_.reset(); } TO_STRING_KV(K(election_role_), K(election_epoch_), @@ -126,7 +128,8 @@ struct PalfDiagnoseInfo { K(palf_state_), K(palf_proposal_id_), K(enable_sync_), - K(enable_vote_)); + K(enable_vote_), + K(parent_)); }; struct FetchLogStat { @@ -291,12 +294,6 @@ public: virtual int get_arb_member_info(ArbMemberInfo &arb_member_info) const = 0; virtual int get_arbitration_member(common::ObMember &arb_member) const = 0; #endif - // set region for self - // @param [common::ObRegion] region - virtual int set_region(const common::ObRegion ®ion) = 0; - // set region info for paxos members - // @param [common::ObArrayHashMap] regions of Paxos members - virtual int set_paxos_member_region_map(const LogMemberRegionMap ®ion_map) = 0; // 提交需要持久化的内容,提交内容以日志形式在本地持久化并同步给Paxos成员列表中的其他副本 // 同时,若存在只读副本或物理备库,日志会在满足条件时同步给对应节点 // 在Paxos成员列表中的多数派副本持久化成功后,会调用log_ctx->on_success()通知调用者 @@ -804,6 +801,8 @@ public: virtual int reset_location_cache_cb() = 0; virtual int set_election_priority(election::ElectionPriority *priority) = 0; virtual int reset_election_priority() = 0; + virtual int set_locality_cb(palf::PalfLocalityInfoCb *locality_cb) = 0; + virtual int reset_locality_cb() = 0; // ==================== Callback end ======================== virtual int advance_election_epoch_and_downgrade_priority(const int64_t proposal_id, const int64_t downgrade_priority_time_us, @@ -824,6 +823,11 @@ public: char *buf, int64_t &out_read_size) const = 0; virtual int try_handle_next_submit_log() = 0; + + virtual int raw_read(const palf::LSN &lsn, + char *read_buf, + const int64_t nbytes, + int64_t &read_size) = 0; DECLARE_PURE_VIRTUAL_TO_STRING; }; @@ -877,8 +881,6 @@ public: const int64_t paxos_replica_num, const common::GlobalLearnerList &learner_list) override final; #endif - int set_region(const common::ObRegion ®ion) override final; - int set_paxos_member_region_map(const LogMemberRegionMap ®ion_map) override final; int submit_log(const PalfAppendOptions &opts, const char *buf, const int64_t buf_len, @@ -965,6 +967,11 @@ public: char *buf, int64_t &out_read_size) const; int try_handle_next_submit_log(); + + int raw_read(const palf::LSN &lsn, + char *buffer, + const int64_t nbytes, + int64_t &read_size) override final; public: int delete_block(const block_id_t &block_id) override final; int read_log(const LSN &lsn, @@ -1001,6 +1008,8 @@ public: int reset_monitor_cb(); int set_election_priority(election::ElectionPriority *priority) override final; int reset_election_priority() override final; + int set_locality_cb(palf::PalfLocalityInfoCb *locality_cb) override final; + int reset_locality_cb() override final; // ==================== Callback end ======================== public: int get_begin_lsn(LSN &lsn) const override final; @@ -1285,6 +1294,7 @@ private: const LogInfo &base_prev_log_info, const bool is_rebuild); int get_election_leader_without_lock_(ObAddr &addr) const; + int update_self_region_(); // ========================= flashback ============================== int can_do_flashback_(const int64_t mode_version, const share::SCN &flashback_scn, @@ -1453,6 +1463,7 @@ private: int64_t chaning_config_warn_time_; bool cached_is_in_sync_; bool has_higher_prio_config_change_; + int64_t last_update_region_time_us_; bool is_inited_; }; } // end namespace palf diff --git a/src/logservice/palf_handle_guard.h b/src/logservice/palf_handle_guard.h index 5bc649737c..522668235f 100644 --- a/src/logservice/palf_handle_guard.h +++ b/src/logservice/palf_handle_guard.h @@ -55,7 +55,6 @@ public: // int set_initial_member_list(const common::ObMemberList &member_list, // const int64_t paxos_replica_num); DELEGATE_WITH_RET(palf_handle_, set_initial_member_list, int); - DELEGATE_WITH_RET(palf_handle_, set_paxos_member_region_map, int); // @brief append count bytes from the buffer starting at buf to the palf handle, return the LSN and timestamp // @param[in] cost PalfAppendOptions&, decide this append option whether need block thread. // @param[in] const void *, the data buffer. @@ -221,7 +220,6 @@ public: DELEGATE_WITH_RET(palf_handle_, remove_learner, int); DELEGATE_WITH_RET(palf_handle_, switch_learner_to_acceptor, int); DELEGATE_WITH_RET(palf_handle_, switch_acceptor_to_learner, int); - DELEGATE_WITH_RET(palf_handle_, set_region, int); DELEGATE_WITH_RET(palf_handle_, set_location_cache_cb, int); DELEGATE_WITH_RET(palf_handle_, change_access_mode, int); DELEGATE_WITH_RET(palf_handle_, get_access_mode, int); diff --git a/src/logservice/restoreservice/ob_log_archive_piece_mgr.cpp b/src/logservice/restoreservice/ob_log_archive_piece_mgr.cpp index a97aece126..992fe55bd9 100644 --- a/src/logservice/restoreservice/ob_log_archive_piece_mgr.cpp +++ b/src/logservice/restoreservice/ob_log_archive_piece_mgr.cpp @@ -221,6 +221,45 @@ bool ObLogArchivePieceContext::is_valid() const && archive_dest_.is_valid(); } +int ObLogArchivePieceContext::get_raw_read_piece(const share::SCN &pre_scn, + const palf::LSN &start_lsn, + int64_t &dest_id, + int64_t &round_id, + int64_t &piece_id, + int64_t &file_id, + int64_t &file_offset) +{ + int ret = OB_SUCCESS; + int64_t unused_offset = -1; + palf::LSN unused_lsn; + palf::LSN min_lsn; + bool unused_flag = false; + // if piece context not valid, reset it + if (! is_valid()) { + reset_locate_info(); + } + + file_id = cal_archive_file_id_(start_lsn); + if (OB_UNLIKELY(! pre_scn.is_valid() || ! start_lsn.is_valid())) { + ret = OB_INVALID_ARGUMENT; + CLOG_LOG(WARN, "invalid argument", K(ret), K(pre_scn), K(start_lsn)); + } else if (OB_FAIL(get_piece_(pre_scn, start_lsn, file_id, dest_id, + round_id, piece_id, unused_offset, unused_lsn, unused_flag))) { + CLOG_LOG(WARN, "get piece failed", KPC(this)); + } else if (FALSE_IT(min_lsn = inner_piece_context_.min_lsn_in_piece_)) { + } else if (archive::cal_archive_file_id(min_lsn, palf::PALF_BLOCK_SIZE) == file_id) { + // the first file in piece may not match 64MB size, so get real_offset based on min_lsn_in_piece + if (OB_UNLIKELY(min_lsn > start_lsn)) { + ret = OB_ERR_UNEXPECTED; + } else { + file_offset = (start_lsn - min_lsn) + archive::ARCHIVE_FILE_HEADER_SIZE; + } + } else { + file_offset = palf::lsn_2_offset(start_lsn, palf::PALF_BLOCK_SIZE) + archive::ARCHIVE_FILE_HEADER_SIZE; + } + return ret; +} + int ObLogArchivePieceContext::get_piece(const SCN &pre_scn, const palf::LSN &start_lsn, int64_t &dest_id, diff --git a/src/logservice/restoreservice/ob_log_archive_piece_mgr.h b/src/logservice/restoreservice/ob_log_archive_piece_mgr.h index b31bbd765d..3aefdecb06 100644 --- a/src/logservice/restoreservice/ob_log_archive_piece_mgr.h +++ b/src/logservice/restoreservice/ob_log_archive_piece_mgr.h @@ -54,6 +54,14 @@ public: bool is_valid() const; + int get_raw_read_piece(const share::SCN &pre_scn, + const palf::LSN &start_lsn, + int64_t &dest_id, + int64_t &round_id, + int64_t &piece_id, + int64_t &file_id, + int64_t &file_offset); + int get_piece(const share::SCN &pre_scn, const palf::LSN &start_lsn, int64_t &dest_id, diff --git a/src/logservice/restoreservice/ob_remote_data_generator.cpp b/src/logservice/restoreservice/ob_remote_data_generator.cpp index 87c8650fe3..75c07e3a8d 100644 --- a/src/logservice/restoreservice/ob_remote_data_generator.cpp +++ b/src/logservice/restoreservice/ob_remote_data_generator.cpp @@ -661,7 +661,6 @@ int RawPathDataGenerator::fetch_log_from_dest_() // 为加速定位起点文件,依赖LSN -> file_id 规则 int RawPathDataGenerator::cal_lsn_to_file_id_(const LSN &lsn) { - //TODO get_archive_file_size from restore config file_id_ = cal_archive_file_id(lsn, palf::PALF_BLOCK_SIZE); return OB_SUCCESS; } diff --git a/src/logservice/restoreservice/ob_remote_log_iterator.h b/src/logservice/restoreservice/ob_remote_log_iterator.h index 3f19bb1e4a..ad2c3ccf1f 100644 --- a/src/logservice/restoreservice/ob_remote_log_iterator.h +++ b/src/logservice/restoreservice/ob_remote_log_iterator.h @@ -57,7 +57,7 @@ typedef const std::function RefreshStorageInfoFu template class ObRemoteLogIterator { - static const int64_t DEFAULT_SINGLE_READ_SIZE = 8 * palf::MAX_LOG_BUFFER_SIZE; + static const int64_t DEFAULT_SINGLE_READ_SIZE = 1L << 24; // 16MB public: // @param[in] get_source_func, an function to get the input log restore source // @param[in] update_source_func, an function to update location info the the log restore source, diff --git a/src/logservice/restoreservice/ob_remote_log_raw_reader.cpp b/src/logservice/restoreservice/ob_remote_log_raw_reader.cpp new file mode 100644 index 0000000000..a9022e96d3 --- /dev/null +++ b/src/logservice/restoreservice/ob_remote_log_raw_reader.cpp @@ -0,0 +1,212 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#include "ob_remote_log_raw_reader.h" +#include "lib/ob_define.h" +#include "lib/ob_errno.h" +#include "lib/oblog/ob_log_module.h" +#include "lib/restore/ob_storage_info.h" +#include "lib/utility/ob_macro_utils.h" +#include "share/backup/ob_archive_path.h" +#include "share/backup/ob_backup_struct.h" // ObBackupPath +#include "logservice/palf/log_define.h" +#include "logservice/ob_log_external_storage_handler.h" // ObLogExternalStorageHandler +#include "ob_log_archive_piece_mgr.h" + +namespace oceanbase +{ +namespace logservice +{ +ObRemoteLogRawReader::ObRemoteLogRawReader(GetSourceFunc &get_source_func, + UpdateSourceFunc &update_source_func, + RefreshStorageInfoFunc &refresh_storage_info_func) : + inited_(false), + tenant_id_(OB_INVALID_TENANT_ID), + id_(), + pre_scn_(), + start_lsn_(), + cur_lsn_(), + max_lsn_(), + log_ext_handler_(NULL), + source_guard_(), + get_source_func_(get_source_func), + update_source_func_(update_source_func), + refresh_storage_info_func_(refresh_storage_info_func) +{} + +ObRemoteLogRawReader::~ObRemoteLogRawReader() +{ + destroy(); +} + +int ObRemoteLogRawReader::init(const uint64_t tenant_id, + const share::ObLSID &id, + const share::SCN &pre_scn, + logservice::ObLogExternalStorageHandler *log_ext_handler) +{ + int ret = OB_SUCCESS; + ObRemoteLogParent *source = NULL; + if (OB_UNLIKELY(inited_)) { + ret = OB_INIT_TWICE; + CLOG_LOG(WARN, "ObRemoteLogRawReader init twice", K(inited_)); + } else if (OB_UNLIKELY(OB_INVALID_TENANT_ID == tenant_id + || !id.is_valid() + || !pre_scn.is_valid() + || NULL == log_ext_handler)) { + ret = OB_INVALID_ARGUMENT; + CLOG_LOG(WARN, "invalid argument", K(tenant_id), K(id), K(pre_scn), K(log_ext_handler)); + } else if (OB_FAIL(get_source_func_(id, source_guard_))) { + CLOG_LOG(WARN, "get source failed", K(ret), K(id)); + } else if (OB_ISNULL(source = source_guard_.get_source())) { + ret = OB_EAGAIN; + CLOG_LOG(WARN, "source is NULL", K(ret), K(id)); + } else if (OB_UNLIKELY(! share::is_location_log_source_type(source->get_source_type()))) { + ret = OB_NOT_SUPPORTED; + CLOG_LOG(WARN, "source type not support", K(ret), K(id), KPC(source)); + } else { + tenant_id_ = tenant_id; + id_ = id; + pre_scn_ = pre_scn; + log_ext_handler_ = log_ext_handler; + inited_ = true; + CLOG_LOG(INFO, "ObRemoteLogRawReader init succ", K(id_), K(tenant_id_), K(pre_scn_), K(inited_)); + } + return ret; +} + +void ObRemoteLogRawReader::destroy() +{ + inited_ = false; + tenant_id_ = OB_INVALID_TENANT_ID; + id_.reset(); + pre_scn_.reset(); + start_lsn_.reset(); + cur_lsn_.reset(); + max_lsn_.reset(); + log_ext_handler_ = NULL; +} + +int ObRemoteLogRawReader::raw_read(const palf::LSN &start_lsn, + void *buffer, + const int64_t nbytes, + int64_t &read_size) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(!inited_)) { + ret = OB_NOT_INIT; + CLOG_LOG(ERROR, "ObRemoteLogRawReader not init", KPC(this)); + } else if (OB_UNLIKELY(!start_lsn.is_valid() + || nbytes <= 0 + || NULL == buffer)) { + ret = OB_INVALID_ARGUMENT; + CLOG_LOG(WARN, "invalid argument", K(start_lsn), K(nbytes)); + } else { + start_lsn_ = start_lsn; + cur_lsn_ = start_lsn; + max_lsn_ = start_lsn_ + nbytes; + ret = raw_read_((char*)buffer, nbytes, read_size); + } + return ret; +} + +int ObRemoteLogRawReader::raw_read_(char *buffer, const int64_t buffer_size, int64_t &total_read_size) +{ + int ret = OB_SUCCESS; + total_read_size = 0; + int READ_TIMES = 0; + while (total_read_size < max_lsn_ - start_lsn_ && OB_SUCC(ret)) { + int64_t read_size = 0; + if (OB_FAIL(read_once_(buffer + total_read_size, buffer_size - total_read_size, read_size))) { + CLOG_LOG(WARN, "raw read failed", K(id_), K(total_read_size)); + } else if (read_size == 0) { + break; + } else { + READ_TIMES++; + total_read_size += read_size; + cur_lsn_ = cur_lsn_ + read_size; + CLOG_LOG(INFO, "RAW READ TIMES", K(READ_TIMES), K(read_size), K(total_read_size), + K(buffer_size), K(start_lsn_), K(cur_lsn_), K(id_)); + } + } + + // no enough log to read, just return total_read_size + if (OB_ITER_END == ret) { + ret = OB_SUCCESS; + } + + // no data read after sweep archive + if (OB_SUCC(ret) && 0 == total_read_size) { + ret = OB_ERR_OUT_OF_UPPER_BOUND; + } + return ret; +} + +int ObRemoteLogRawReader::read_once_(char *buffer, const int64_t buffer_size, int64_t &read_size) +{ + int ret = OB_SUCCESS; + int64_t dest_id = -1; + int64_t round_id = -1; + int64_t piece_id = -1; + int64_t file_id = -1; + int64_t file_offset = -1; + share::ObBackupPath path; + share::SCN unused_scn; + share::ObBackupDest *dest = NULL; + ObLogArchivePieceContext *piece_context = NULL; + common::ObObjectStorageInfo storage_info_base; + char storage_info_cstr[OB_MAX_BACKUP_STORAGE_INFO_LENGTH] = {'\0'}; + ObRemoteLocationParent *source = static_cast(source_guard_.get_source()); + + if (OB_ISNULL(source)) { + ret = OB_ERR_UNEXPECTED; + CLOG_LOG(ERROR, "source is NULL", K(source)); + } else if (FALSE_IT(source->get(dest, piece_context, unused_scn))) { + } else if (OB_ISNULL(dest) || OB_ISNULL(piece_context)) { + ret = OB_ERR_UNEXPECTED; + CLOG_LOG(ERROR, "dest or piece_context is NULL", KPC(source), K(dest), K(piece_context)); + } else if (OB_FAIL(piece_context->get_raw_read_piece(pre_scn_, cur_lsn_, dest_id, + round_id, piece_id, file_id, file_offset))) { + CLOG_LOG(WARN, "get piece failed", KPC(this), KPC(piece_context)); + } else if (OB_UNLIKELY(!piece_context->is_valid())) { + ret = OB_ERR_UNEXPECTED; + CLOG_LOG(WARN, "piece_context not valid", KPC(this), KPC(piece_context)); + } else if (OB_FAIL(share::ObArchivePathUtil::get_ls_archive_file_path( + *dest, dest_id, round_id, piece_id, id_, file_id, path))) { + CLOG_LOG(WARN, "get ls archive file path failed", KPC(dest), + K(dest_id), K(round_id), K(piece_id), K(file_id), K(id_)); + } else if (OB_FAIL(storage_info_base.assign(*dest->get_storage_info()))) { + CLOG_LOG(WARN, "get storage_info failed", KPC(dest)); + } else if (OB_FAIL(storage_info_base.get_storage_info_str( + storage_info_cstr, OB_MAX_BACKUP_STORAGE_INFO_LENGTH))) { + CLOG_LOG(WARN, "get storage_info str failed", K(id_)); + } else { + ObString uri(path.get_obstr()); + ObString storage_info(storage_info_cstr); + if (OB_FAIL(log_ext_handler_->pread(uri, storage_info, file_offset, + buffer, buffer_size, read_size))) { + if (OB_FILE_LENGTH_INVALID == ret) { + ret = OB_SUCCESS; + read_size = 0; + } else { + CLOG_LOG(WARN, "read file failed", K(ret), K(uri), K(storage_info)); + } + } + + if (OB_SUCC(ret) && 0 == read_size) { + CLOG_LOG(INFO, "no data read", K(id_), K(cur_lsn_), KPC(piece_context)); + } + } + return ret; +} + +} // namespace logservice +} // namespace oceanbase diff --git a/src/logservice/restoreservice/ob_remote_log_raw_reader.h b/src/logservice/restoreservice/ob_remote_log_raw_reader.h new file mode 100644 index 0000000000..d3eb4a408e --- /dev/null +++ b/src/logservice/restoreservice/ob_remote_log_raw_reader.h @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef OCEANBASE_LOGSERVICE_OB_REMOTE_LOG_RAW_READER_H_ +#define OCEANBASE_LOGSERVICE_OB_REMOTE_LOG_RAW_READER_H_ + +#include "lib/utility/ob_macro_utils.h" +#include "share/ob_ls_id.h" +#include "logservice/palf/log_define.h" +#include "ob_remote_data_generator.h" +#include "ob_remote_log_source.h" +#include + +namespace oceanbase +{ + +namespace logservice +{ +class ObLogArchivePieceContext; +typedef const std::function GetSourceFunc; +typedef const std::function UpdateSourceFunc; +typedef const std::function RefreshStorageInfoFunc; +class ObRemoteLogRawReader +{ + static const int64_t DEFAULT_SINGLE_READ_SIZE = 8 * palf::MAX_LOG_BUFFER_SIZE; + class DefaultUpdateSourceFunctor + { + public: + int operator()(const share::ObLSID &id, ObRemoteLogParent *source) { return OB_SUCCESS; } + }; + class DefaultRefreshStorageInfoFunctor + { + public: + int operator()(share::ObBackupDest &dest) { return OB_NOT_SUPPORTED; } + }; +public: + // @param[in] get_source_func, an function to get the input log restore source + // @param[in] update_source_func, an function to update location info the the log restore source, + // which eliminates the location of a single log if the log restore source is used to init + // remote log iterator repeatedly. + // @param[in] refresh_storage_info_func, when log restore source is oss/cos..., the id/key may be modified, + // so if you want remote log iteraotr to adapt automatically, this function should be provided, + // otherwise ignore it and use the default func, and which means when then id/key is changed, + // iteraotr should be inited again to follow this change + ObRemoteLogRawReader(GetSourceFunc &get_source_func, + UpdateSourceFunc &update_source_func = DefaultUpdateSourceFunctor(), + RefreshStorageInfoFunc &refresh_storage_info_func = DefaultRefreshStorageInfoFunctor()); + virtual ~ObRemoteLogRawReader(); +public: + // init remote log raw reader, as archive log directory is splitted by scn, the pre_scn is indispensable to help locate directory + // + // @param[in] tenant_id, log source tenant id, to check consistency among the tenant and the archive + // @param[in] id, ls id + // @param[in] pre_scn, the scn of the previous one or several log the help locate directory + // @param[in] log_ext_handler, the module to promote read performance + int init(const uint64_t tenant_id, + const share::ObLSID &id, + const share::SCN &pre_scn, + ObLogExternalStorageHandler *log_ext_handler); + + void destroy(); + + // raw read from archive files + // + // @param[in] start_lsn, the start lsn to read + // @param[in] buffer, buffer to hold read data + // @param[in] nbytes, total size to read + // @param[out] read_size, real size read + // + // @ret_code OB_SUCCESS + // OB_INVALID_ARGUMENT + // OB_ERR_OUT_OF_LOWER_BOUND, the lsn is out of lower bound + // OB_ERR_OUT_OF_UPPER_BOUND, the lsn is out of upper bound + // others error enexpected + int raw_read(const palf::LSN &start_lsn, + void *buffer, + const int64_t nbytes, + int64_t &read_size); + + TO_STRING_KV(K_(inited), K_(tenant_id), K_(id), K_(pre_scn), K_(start_lsn), K_(cur_lsn), K_(max_lsn), K_(log_ext_handler)); + +private: + int raw_read_(char *buffer, const int64_t buffer_size, int64_t &total_read_size); + + int read_once_(char *buffer, const int64_t buffer_size, int64_t &total_read_size); + +private: + bool inited_; + uint64_t tenant_id_; + share::ObLSID id_; + share::SCN pre_scn_; + palf::LSN start_lsn_; + palf::LSN cur_lsn_; + palf::LSN max_lsn_; + ObLogExternalStorageHandler *log_ext_handler_; + ObRemoteSourceGuard source_guard_; + GetSourceFunc get_source_func_; + UpdateSourceFunc update_source_func_; + RefreshStorageInfoFunc refresh_storage_info_func_; + +private: + DISALLOW_COPY_AND_ASSIGN(ObRemoteLogRawReader); +}; +} // namespace logservice +} // namespace oceanbase +#endif /* OCEANBASE_LOGSERVICE_OB_REMOTE_LOG_RAW_READER_H_ */ diff --git a/src/observer/ob_srv_xlator_primary.cpp b/src/observer/ob_srv_xlator_primary.cpp index 504753f97c..e373e6b8d7 100644 --- a/src/observer/ob_srv_xlator_primary.cpp +++ b/src/observer/ob_srv_xlator_primary.cpp @@ -229,6 +229,7 @@ void oceanbase::observer::init_srv_xlator_for_cdc(ObSrvRpcXlator *xlator) RPC_PROCESSOR(ObCdcLSReqStartLSNByTsP); RPC_PROCESSOR(ObCdcLSFetchLogP); RPC_PROCESSOR(ObCdcLSFetchMissingLogP); + RPC_PROCESSOR(ObCdcFetchRawLogP); } void oceanbase::observer::init_srv_xlator_for_executor(ObSrvRpcXlator *xlator) { diff --git a/src/observer/virtual_table/ob_all_virtual_ha_diagnose.cpp b/src/observer/virtual_table/ob_all_virtual_ha_diagnose.cpp index 0b4fe7a0d2..4982fa77b2 100644 --- a/src/observer/virtual_table/ob_all_virtual_ha_diagnose.cpp +++ b/src/observer/virtual_table/ob_all_virtual_ha_diagnose.cpp @@ -262,6 +262,19 @@ int ObAllVirtualHADiagnose::insert_stat_(storage::DiagnoseInfo &diagnose_info) cur_row_.cells_[i].set_collation_type(ObCharset::get_default_collation( ObCharset::get_default_charset())); break; + case PARENT: + cur_row_.cells_[i].set_varchar(ObString("")); + if (diagnose_info.palf_diagnose_info_.parent_.is_valid()) { + if (OB_SUCC(diagnose_info.palf_diagnose_info_.parent_.\ + ip_port_to_string(parent_, common::OB_IP_PORT_STR_BUFF))) { + cur_row_.cells_[i].set_varchar(ObString::make_string(parent_)); + } else { + SERVER_LOG(WARN, "ip_port_to_string failed", K(ret), K(diagnose_info), K(parent_)); + } + } + cur_row_.cells_[i].set_collation_type(ObCharset::get_default_collation( + ObCharset::get_default_charset())); + break; default: ret = OB_ERR_UNEXPECTED; SERVER_LOG(WARN, "unkown column"); diff --git a/src/observer/virtual_table/ob_all_virtual_ha_diagnose.h b/src/observer/virtual_table/ob_all_virtual_ha_diagnose.h index 521ca4118d..5ed5490abb 100644 --- a/src/observer/virtual_table/ob_all_virtual_ha_diagnose.h +++ b/src/observer/virtual_table/ob_all_virtual_ha_diagnose.h @@ -55,6 +55,7 @@ enum IOStatColumn ENABLE_SYNC, ENABLE_VOTE, ARB_SRV_INFO, + PARENT, }; class ObAllVirtualHADiagnose : public common::ObVirtualTableScannerIterator @@ -76,6 +77,7 @@ private: char gc_state_str_[VARCHAR_32] = {'\0'}; char min_rec_log_scn_log_type_str_[VARCHAR_32] = {'\0'}; char restore_handler_role_str_[VARCHAR_32] = {'\0'}; + char parent_[common::OB_IP_PORT_STR_BUFF] = {'\0'}; omt::ObMultiTenant *omt_; }; } // namespace observer diff --git a/src/rootserver/ob_ddl_operator.cpp b/src/rootserver/ob_ddl_operator.cpp index 1ccfb73e87..6548ff717f 100644 --- a/src/rootserver/ob_ddl_operator.cpp +++ b/src/rootserver/ob_ddl_operator.cpp @@ -93,6 +93,33 @@ using namespace storage; namespace rootserver { +#define GRANT_OBJ_PRIV_TO_USER(db_name, table_name, table_id, obj_type, priv) \ +{ \ + if (OB_SUCC(ret)) { \ + ObTablePrivSortKey table_priv_key; \ + table_priv_key.tenant_id_ = tenant_id; \ + table_priv_key.user_id_ = grantee_id; \ + table_priv_key.db_ = ObString(#db_name); \ + table_priv_key.table_ = ObString(#table_name); \ + ObPrivSet priv_set; \ + priv_set = OB_PRIV_##priv; \ + ObObjPrivSortKey obj_priv_key; \ + obj_priv_key.tenant_id_ = tenant_id; \ + obj_priv_key.obj_id_ = table_id; \ + obj_priv_key.obj_type_ = static_cast(obj_type); \ + obj_priv_key.col_id_ = OB_COMPACT_COLUMN_INVALID_ID; \ + obj_priv_key.grantor_id_ = OB_ORA_SYS_USER_ID; \ + obj_priv_key.grantee_id_ = grantee_id; \ + share::ObRawObjPrivArray priv_array; \ + if (OB_FAIL(priv_array.push_back(OBJ_PRIV_ID_##priv))) { \ + LOG_WARN("priv array push back failed", K(ret)); \ + } else if (OB_FAIL(this->grant_table(table_priv_key, priv_set, NULL, trans, \ + priv_array, 0, obj_priv_key))){ \ + LOG_WARN("fail to grant table", K(ret), K(table_priv_key), K(priv_set), K(priv_array), K(obj_priv_key)); \ + } \ + } \ +} + ObSysStat::Item::Item(ObSysStat::ItemList &list, const char *name, const char *info) : name_(name), info_(info) { @@ -1498,6 +1525,9 @@ int ObDDLOperator::get_user_id_for_inner_ur(ObUserInfo &user, } else if (STRCMP(ur_name, OB_ORA_PUBLIC_ROLE_NAME) == 0) { new_user_id = OB_ORA_PUBLIC_ROLE_ID; is_inner_ur = true; + } else if (STRCMP(ur_name, OB_ORA_STANDBY_REPLICATION_ROLE_NAME) == 0) { + new_user_id = OB_ORA_STANDBY_REPLICATION_ROLE_ID; + is_inner_ur = true; } } // both oracle mode and mysql mode @@ -5719,7 +5749,7 @@ int ObDDLOperator::build_raw_priv_info_inner_user( OZ (raw_priv_array.push_back(PRIV_ID_CREATE_TRIG)); OZ (raw_priv_array.push_back(PRIV_ID_CREATE_PROC)); OZ (raw_priv_array.push_back(PRIV_ID_CREATE_SEQ)); - } else if (is_ora_connect_role(grantee_id)) { + } else if (is_ora_connect_role(grantee_id) || is_ora_standby_replication_role(grantee_id)) { option = NO_OPTION; OZ (raw_priv_array.push_back(PRIV_ID_CREATE_SESSION)); } else if (is_ora_public_role(grantee_id)) { @@ -5761,6 +5791,16 @@ int ObDDLOperator::init_inner_user_privs( true /*is_grant*/, false), tenant_id, grantee_id, ADMIN_OPTION, raw_priv_array); + if (is_ora_standby_replication_role(user.get_user_id())) { + // #define GRANT_OBJ_PRIV_TO_USER(db_name, table_name, table_id, obj_type, priv) + GRANT_OBJ_PRIV_TO_USER(OB_ORA_SYS_SCHEMA_NAME, OB_DBA_OB_TENANTS_ORA_TNAME, OB_DBA_OB_TENANTS_ORA_TID, ObObjectType::TABLE, SELECT); + GRANT_OBJ_PRIV_TO_USER(OB_ORA_SYS_SCHEMA_NAME, OB_DBA_OB_ACCESS_POINT_ORA_TNAME, OB_DBA_OB_ACCESS_POINT_ORA_TID, ObObjectType::TABLE, SELECT); + GRANT_OBJ_PRIV_TO_USER(OB_ORA_SYS_SCHEMA_NAME, OB_DBA_OB_LS_ORA_TNAME, OB_DBA_OB_LS_ORA_TID, ObObjectType::TABLE, SELECT); + GRANT_OBJ_PRIV_TO_USER(OB_ORA_SYS_SCHEMA_NAME, OB_DBA_OB_LS_HISTORY_ORA_TNAME, OB_DBA_OB_LS_HISTORY_ORA_TID, ObObjectType::TABLE, SELECT); + GRANT_OBJ_PRIV_TO_USER(OB_ORA_SYS_SCHEMA_NAME, OB_GV_OB_PARAMETERS_ORA_TNAME, OB_GV_OB_PARAMETERS_ORA_TID, ObObjectType::TABLE, SELECT); + GRANT_OBJ_PRIV_TO_USER(OB_ORA_SYS_SCHEMA_NAME, OB_GV_OB_LOG_STAT_ORA_TNAME, OB_GV_OB_LOG_STAT_ORA_TID, ObObjectType::TABLE, SELECT); + GRANT_OBJ_PRIV_TO_USER(OB_ORA_SYS_SCHEMA_NAME, OB_GV_OB_UNITS_ORA_TNAME, OB_GV_OB_UNITS_ORA_TID, ObObjectType::TABLE, SELECT); + } } return ret; } @@ -5846,6 +5886,7 @@ int ObDDLOperator::init_tenant_users(const ObTenantSchema &tenant_schema, ObString ora_resource_role_name(OB_ORA_RESOURCE_ROLE_NAME); ObString ora_dba_role_name(OB_ORA_DBA_ROLE_NAME); ObString ora_public_role_name(OB_ORA_PUBLIC_ROLE_NAME); + ObString ora_standby_replication_role_name(OB_ORA_STANDBY_REPLICATION_ROLE_NAME); ObString sys_standby_name(OB_STANDBY_USER_NAME); char ora_lbacsys_password[ENCRYPT_KEY_LENGTH]; char ora_auditor_password[ENCRYPT_KEY_LENGTH]; @@ -5881,6 +5922,9 @@ int ObDDLOperator::init_tenant_users(const ObTenantSchema &tenant_schema, } else if (OB_FAIL(init_tenant_user(tenant_id, ora_public_role_name, ObString(""), OB_ORA_PUBLIC_ROLE_ID, "oracle public role", trans, false, false, true))) { RS_LOG(WARN, "fail to init oracle public role", K(ret), K(tenant_id)); + } else if (OB_FAIL(init_tenant_user(tenant_id, ora_standby_replication_role_name, ObString(""), + OB_ORA_STANDBY_REPLICATION_ROLE_ID, "oracle standby replication role", trans, false, false, true))) { + RS_LOG(WARN, "fail to init oracle standby replication role", K(ret), K(tenant_id)); } } else { if (OB_FAIL(init_tenant_user(tenant_id, sys_user_name, ObString(""), OB_SYS_USER_ID, diff --git a/src/rootserver/ob_root_service.cpp b/src/rootserver/ob_root_service.cpp index 2ac45cd375..83db389b1a 100755 --- a/src/rootserver/ob_root_service.cpp +++ b/src/rootserver/ob_root_service.cpp @@ -880,7 +880,7 @@ int ObRootService::init(ObServerConfig &config, } else if (OB_FAIL(root_inspection_.init(*schema_service_, zone_manager_, sql_proxy_, &common_proxy_))) { FLOG_WARN("init root inspection failed", KR(ret)); } else if (OB_FAIL(upgrade_executor_.init(*schema_service_, - root_inspection_, sql_proxy_, rpc_proxy_, common_proxy_))) { + root_inspection_, sql_proxy_, oracle_sql_proxy_, rpc_proxy_, common_proxy_))) { FLOG_WARN("init upgrade_executor failed", KR(ret)); } else if (OB_FAIL(upgrade_storage_format_executor_.init(*this, ddl_service_))) { FLOG_WARN("init upgrade storage format executor failed", KR(ret)); diff --git a/src/rootserver/ob_upgrade_executor.cpp b/src/rootserver/ob_upgrade_executor.cpp index 45f5f87a44..c55bef136b 100644 --- a/src/rootserver/ob_upgrade_executor.cpp +++ b/src/rootserver/ob_upgrade_executor.cpp @@ -93,6 +93,7 @@ int ObUpgradeExecutor::init( share::schema::ObMultiVersionSchemaService &schema_service, rootserver::ObRootInspection &root_inspection, common::ObMySQLProxy &sql_proxy, + common::ObOracleSqlProxy &oracle_sql_proxy, obrpc::ObSrvRpcProxy &rpc_proxy, obrpc::ObCommonRpcProxy &common_proxy) { @@ -102,12 +103,13 @@ int ObUpgradeExecutor::init( LOG_WARN("can't init twice", KR(ret)); } else if (OB_FAIL(upgrade_processors_.init( ObBaseUpgradeProcessor::UPGRADE_MODE_OB, - sql_proxy, rpc_proxy, common_proxy, schema_service, *this))) { + sql_proxy, oracle_sql_proxy, rpc_proxy, common_proxy, schema_service, *this))) { LOG_WARN("fail to init upgrade processors", KR(ret)); } else { schema_service_ = &schema_service; root_inspection_ = &root_inspection; sql_proxy_ = &sql_proxy; + oralce_sql_proxy_ = &oracle_sql_proxy; rpc_proxy_ = &rpc_proxy; common_rpc_proxy_ = &common_proxy; stopped_ = false; diff --git a/src/rootserver/ob_upgrade_executor.h b/src/rootserver/ob_upgrade_executor.h index 9a24116430..df95624e15 100644 --- a/src/rootserver/ob_upgrade_executor.h +++ b/src/rootserver/ob_upgrade_executor.h @@ -52,6 +52,7 @@ public: int init(share::schema::ObMultiVersionSchemaService &schema_service, rootserver::ObRootInspection &root_inspection, common::ObMySQLProxy &sql_proxy, + common::ObOracleSqlProxy &oracle_sql_proxy, obrpc::ObSrvRpcProxy &rpc_proxy, obrpc::ObCommonRpcProxy &common_proxy); @@ -118,6 +119,7 @@ private: bool execute_; common::SpinRWLock rwlock_; common::ObMySQLProxy *sql_proxy_; + common::ObOracleSqlProxy *oralce_sql_proxy_; obrpc::ObSrvRpcProxy *rpc_proxy_; obrpc::ObCommonRpcProxy *common_rpc_proxy_; share::schema::ObMultiVersionSchemaService *schema_service_; diff --git a/src/share/inner_table/ob_inner_table_schema.12301_12350.cpp b/src/share/inner_table/ob_inner_table_schema.12301_12350.cpp index 87ebf43063..408270d75f 100644 --- a/src/share/inner_table/ob_inner_table_schema.12301_12350.cpp +++ b/src/share/inner_table/ob_inner_table_schema.12301_12350.cpp @@ -10338,6 +10338,21 @@ int ObInnerTableSchema::all_virtual_ha_diagnose_schema(ObTableSchema &table_sche false, //is_nullable false); //is_autoincrement } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("parent", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_INVALID, //column_collation_type + 1024, //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } if (OB_SUCC(ret)) { table_schema.get_part_option().set_part_num(1); table_schema.set_part_level(PARTITION_LEVEL_ONE); diff --git a/src/share/inner_table/ob_inner_table_schema_def.py b/src/share/inner_table/ob_inner_table_schema_def.py index 0e78f71de4..2279e696c5 100644 --- a/src/share/inner_table/ob_inner_table_schema_def.py +++ b/src/share/inner_table/ob_inner_table_schema_def.py @@ -12741,7 +12741,8 @@ def_table_schema( ('restore_err_context_info', 'varchar:1024'), ('enable_sync', 'bool'), ('enable_vote', 'bool'), - ('arb_srv_info', 'varchar:1024') + ('arb_srv_info', 'varchar:1024'), + ('parent', 'varchar:1024') ], partition_columns = ['svr_ip', 'svr_port'], diff --git a/src/share/ob_upgrade_utils.cpp b/src/share/ob_upgrade_utils.cpp index f9098e92a5..c8ffa3a172 100755 --- a/src/share/ob_upgrade_utils.cpp +++ b/src/share/ob_upgrade_utils.cpp @@ -590,6 +590,7 @@ ObUpgradeProcesserSet::~ObUpgradeProcesserSet() int ObUpgradeProcesserSet::init( ObBaseUpgradeProcessor::UpgradeMode mode, common::ObMySQLProxy &sql_proxy, + common::ObOracleSqlProxy &oracle_sql_proxy, obrpc::ObSrvRpcProxy &rpc_proxy, obrpc::ObCommonRpcProxy &common_proxy, share::schema::ObMultiVersionSchemaService &schema_service, @@ -611,7 +612,7 @@ int ObUpgradeProcesserSet::init( } else if (OB_ISNULL(processor = new(buf)ObUpgradeFor##MAJOR##MINOR##MAJOR_PATCH##MINOR_PATCH##Processor)) { \ ret = OB_NOT_INIT; \ LOG_WARN("fail to new upgrade processor", KR(ret)); \ - } else if (OB_FAIL(processor->init(version, mode, sql_proxy, rpc_proxy, common_proxy, \ + } else if (OB_FAIL(processor->init(version, mode, sql_proxy, oracle_sql_proxy, rpc_proxy, common_proxy, \ schema_service, check_server_provider))) { \ LOG_WARN("fail to init processor", KR(ret), K(version)); \ } else if (OB_FAIL(processor_list_.push_back(processor))) { \ @@ -802,6 +803,7 @@ int ObBaseUpgradeProcessor::init( int64_t data_version, UpgradeMode mode, common::ObMySQLProxy &sql_proxy, + common::ObOracleSqlProxy &oracle_sql_proxy, obrpc::ObSrvRpcProxy &rpc_proxy, obrpc::ObCommonRpcProxy &common_proxy, share::schema::ObMultiVersionSchemaService &schema_service, @@ -815,6 +817,7 @@ int ObBaseUpgradeProcessor::init( mode_ = mode; data_version_ = data_version; sql_proxy_ = &sql_proxy; + oracle_sql_proxy_ = &oracle_sql_proxy; rpc_proxy_ = &rpc_proxy; common_proxy_ = &common_proxy; schema_service_ = &schema_service; @@ -1198,6 +1201,90 @@ int ObUpgradeFor4211Processor::post_upgrade_for_dbms_scheduler() } /* =========== 4211 upgrade processor end ============= */ +int ObUpgradeFor4310Processor::post_upgrade() +{ + int ret = OB_SUCCESS; + if (OB_FAIL(check_inner_stat())) { + LOG_WARN("fail to check inner stat", KR(ret)); + } else if (OB_FAIL(post_upgrade_for_create_replication_role_in_oracle())) { + LOG_WARN("fail to create standby replication role in oracle", KR(ret)); + } + return ret; +} + +int ObUpgradeFor4310Processor::post_upgrade_for_create_replication_role_in_oracle() +{ + int ret = OB_SUCCESS; + lib::Worker::CompatMode compat_mode = lib::Worker::CompatMode::INVALID; + bool is_standby = false; + if (OB_ISNULL(sql_proxy_) || OB_ISNULL(oracle_sql_proxy_) || OB_ISNULL(schema_service_) || !is_valid_tenant_id(tenant_id_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected error", KR(ret), KP_(sql_proxy), KP_(schema_service), K_(tenant_id)); + } else if (!is_user_tenant(tenant_id_)) { + LOG_INFO("meta and sys tenant no need to update replicate role", K_(tenant_id)); + } else if (OB_FAIL(ObAllTenantInfoProxy::is_standby_tenant(sql_proxy_, tenant_id_, is_standby))) { + LOG_WARN("check is standby tenant failed", KR(ret), K_(tenant_id)); + } else if (is_standby) { + LOG_INFO("standby tenant no need to update replicate role", K_(tenant_id)); + } else if (OB_FAIL(ObCompatModeGetter::get_tenant_mode(tenant_id_, compat_mode))) { + LOG_WARN("failed to get tenant compat mode", KR(ret), K_(tenant_id)); + } else if (lib::Worker::CompatMode::ORACLE == compat_mode) { + ObSchemaGetterGuard schema_guard; + ObSqlString role_sql; + ObSqlString sys_priv_sql; + int64_t affected_rows = 0; + bool is_user_exist = false; + // check and create standby replication role + if (OB_FAIL(schema_service_->get_tenant_schema_guard(tenant_id_, schema_guard))) { + LOG_WARN("failed to get tenant schema guard", KR(ret), K_(tenant_id)); + } else if (OB_FAIL(schema_guard.check_user_exist(tenant_id_, OB_ORA_STANDBY_REPLICATION_ROLE_ID, is_user_exist))) { + LOG_WARN("fail to check user exist", KR(ret), K_(tenant_id)); + } else if (OB_FAIL(schema_guard.reset())) { + LOG_WARN("fail to reset schema guard", KR(ret)); + } else if (!is_user_exist) { + if (OB_FAIL(role_sql.assign_fmt("CREATE ROLE %s", OB_ORA_STANDBY_REPLICATION_ROLE_NAME))) { + LOG_WARN("fail to assign create role sql", KR(ret), K_(tenant_id)); + } else if (OB_FAIL(oracle_sql_proxy_->write(tenant_id_, role_sql.ptr(), affected_rows))) { + LOG_WARN("fail to write create role sql", KR(ret), K(role_sql), K_(tenant_id)); + } + } else { + LOG_INFO("standy replication role already exist"); + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(sys_priv_sql.assign_fmt("GRANT CREATE SESSION TO %s", OB_ORA_STANDBY_REPLICATION_ROLE_NAME))) { + LOG_WARN("fail to assign sql", KR(ret), K_(tenant_id)); + } else if (OB_FAIL(oracle_sql_proxy_->write(tenant_id_, sys_priv_sql.ptr(), affected_rows))) { + LOG_WARN("fail to write sql", KR(ret), K(sys_priv_sql), K_(tenant_id)); + } + } +#define GRANT_OBJ_PRIVS_TO_USER(PRIV, DB_NAME, TABLE_NAME, USER_NAME) \ + if (OB_SUCC(ret)) { \ + ObSqlString tab_priv_sql; \ + if (OB_FAIL(tab_priv_sql.assign_fmt("GRANT %s on %s.%s to %s", PRIV, DB_NAME, TABLE_NAME, USER_NAME))) { \ + LOG_WARN("fail to assign sql", KR(ret)); \ + } else if (OB_FAIL(oracle_sql_proxy_->write(tenant_id_, tab_priv_sql.ptr(), affected_rows))) { \ + LOG_WARN("fail to write sql", KR(ret), K(tab_priv_sql)); \ + } \ + } + GRANT_OBJ_PRIVS_TO_USER("SELECT", OB_ORA_SYS_SCHEMA_NAME, OB_DBA_OB_TENANTS_ORA_TNAME, OB_ORA_STANDBY_REPLICATION_ROLE_NAME) + GRANT_OBJ_PRIVS_TO_USER("SELECT", OB_ORA_SYS_SCHEMA_NAME, OB_DBA_OB_ACCESS_POINT_ORA_TNAME, OB_ORA_STANDBY_REPLICATION_ROLE_NAME) + GRANT_OBJ_PRIVS_TO_USER("SELECT", OB_ORA_SYS_SCHEMA_NAME, OB_DBA_OB_LS_ORA_TNAME, OB_ORA_STANDBY_REPLICATION_ROLE_NAME) + GRANT_OBJ_PRIVS_TO_USER("SELECT", OB_ORA_SYS_SCHEMA_NAME, OB_DBA_OB_LS_HISTORY_ORA_TNAME, OB_ORA_STANDBY_REPLICATION_ROLE_NAME) + GRANT_OBJ_PRIVS_TO_USER("SELECT", OB_ORA_SYS_SCHEMA_NAME, OB_GV_OB_PARAMETERS_ORA_TNAME, OB_ORA_STANDBY_REPLICATION_ROLE_NAME) + GRANT_OBJ_PRIVS_TO_USER("SELECT", OB_ORA_SYS_SCHEMA_NAME, OB_GV_OB_LOG_STAT_ORA_TNAME, OB_ORA_STANDBY_REPLICATION_ROLE_NAME) + GRANT_OBJ_PRIVS_TO_USER("SELECT", OB_ORA_SYS_SCHEMA_NAME, OB_GV_OB_UNITS_ORA_TNAME, OB_ORA_STANDBY_REPLICATION_ROLE_NAME) +#undef GRANT_OBJ_PRIVS_TO_USER + if (OB_FAIL(ret)) { + LOG_WARN("[UPGRADE] upgrade user tenant create replication role failed", KR(ret), K_(tenant_id)); + } else { + LOG_INFO("[UPGRADE] upgrade user tenant create replication role success", K_(tenant_id)); + } + } + return ret; +} +/* =========== 4310 upgrade processor end ============= */ + /* =========== special upgrade processor end ============= */ } // end share } // end oceanbase diff --git a/src/share/ob_upgrade_utils.h b/src/share/ob_upgrade_utils.h index 28b881ac86..dab6a82df9 100755 --- a/src/share/ob_upgrade_utils.h +++ b/src/share/ob_upgrade_utils.h @@ -88,6 +88,7 @@ public: int init(int64_t data_version, UpgradeMode mode, common::ObMySQLProxy &sql_proxy, + common::ObOracleSqlProxy &oracle_sql_proxy, obrpc::ObSrvRpcProxy &rpc_proxy, obrpc::ObCommonRpcProxy &common_proxy, share::schema::ObMultiVersionSchemaService &schema_service, @@ -106,6 +107,7 @@ protected: uint64_t tenant_id_; UpgradeMode mode_; common::ObMySQLProxy *sql_proxy_; + common::ObOracleSqlProxy *oracle_sql_proxy_; obrpc::ObSrvRpcProxy *rpc_proxy_; obrpc::ObCommonRpcProxy *common_proxy_; share::schema::ObMultiVersionSchemaService *schema_service_; @@ -121,6 +123,7 @@ public: virtual ~ObUpgradeProcesserSet(); int init(ObBaseUpgradeProcessor::UpgradeMode mode, common::ObMySQLProxy &sql_proxy, + common::ObOracleSqlProxy &oracle_sql_proxy, obrpc::ObSrvRpcProxy &rpc_proxy, obrpc::ObCommonRpcProxy &common_proxy, share::schema::ObMultiVersionSchemaService &schema_service, @@ -227,7 +230,18 @@ DEF_SIMPLE_UPGRARD_PROCESSER(4, 2, 2, 1) DEF_SIMPLE_UPGRARD_PROCESSER(4, 2, 3, 0) DEF_SIMPLE_UPGRARD_PROCESSER(4, 3, 0, 0) DEF_SIMPLE_UPGRARD_PROCESSER(4, 3, 0, 1) -DEF_SIMPLE_UPGRARD_PROCESSER(4, 3, 1, 0) + +class ObUpgradeFor4310Processor : public ObBaseUpgradeProcessor +{ +public: + ObUpgradeFor4310Processor() : ObBaseUpgradeProcessor() {} + virtual ~ObUpgradeFor4310Processor() {} + virtual int pre_upgrade() override { return common::OB_SUCCESS; } + virtual int post_upgrade() override; +private: + int post_upgrade_for_create_replication_role_in_oracle(); +}; + /* =========== special upgrade processor end ============= */ /* =========== upgrade processor end ============= */ diff --git a/src/sql/resolver/dcl/ob_set_password_resolver.cpp b/src/sql/resolver/dcl/ob_set_password_resolver.cpp index 0d2360f44d..e8d86171b5 100644 --- a/src/sql/resolver/dcl/ob_set_password_resolver.cpp +++ b/src/sql/resolver/dcl/ob_set_password_resolver.cpp @@ -368,7 +368,8 @@ int ObSetPasswordResolver::check_role_as_user(ParseNode *user_hostname_node, boo ObString node_str(user_hostname_node->str_len_, user_hostname_node->str_value_); if (0 != node_str.case_compare(OB_ORA_RESOURCE_ROLE_NAME) && 0 != node_str.case_compare(OB_ORA_PUBLIC_ROLE_NAME) && - 0 != node_str.case_compare(OB_ORA_CONNECT_ROLE_NAME)) { + 0 != node_str.case_compare(OB_ORA_CONNECT_ROLE_NAME) && + 0 != node_str.case_compare(OB_ORA_STANDBY_REPLICATION_ROLE_NAME)) { is_valid = true; } } diff --git a/src/storage/tx/ob_tx_log.h b/src/storage/tx/ob_tx_log.h index 93b6415e25..b5ccf197ae 100644 --- a/src/storage/tx/ob_tx_log.h +++ b/src/storage/tx/ob_tx_log.h @@ -1100,23 +1100,24 @@ public: len_ = NORMAL_LOG_BUF_SIZE; } // it will be enabled after clog support big clog - // } else if (NORMAL_LOG_BUF_SIZE == len_) { - // int64_t data_version = 0; - // if (OB_FAIL(GET_MIN_DATA_VERSION(MTL_ID(), data_version))) { - // TRANS_LOG(WARN, "get data version failed", K(ret)); - // } else if (data_version < DATA_VERSION_4_2_2_0) { - // ret = OB_NOT_SUPPORTED; - // TRANS_LOG(WARN, "big log is not supported", K(ret)); - // } else if (OB_ISNULL(ptr = alloc_big_buf_())) { - // ret = OB_ALLOCATE_MEMORY_FAILED; - // } else { - // if (pos > 0) { - // memcpy(ptr, buf_, pos); - // } - // free_buf_(buf_); - // buf_ = ptr; - // len_ = BIG_LOG_BUF_SIZE; - // } + } else if (NORMAL_LOG_BUF_SIZE == len_) { + uint64_t data_version = 0; + if (OB_FAIL(GET_MIN_DATA_VERSION(MTL_ID(), data_version))) { + TRANS_LOG(WARN, "get data version failed", K(ret)); + } else if ((data_version < DATA_VERSION_4_2_2_0) + || (data_version >= DATA_VERSION_4_3_0_0 && data_version < DATA_VERSION_4_3_1_0)) { + ret = OB_NOT_SUPPORTED; + TRANS_LOG(WARN, "big log is not supported", K(ret)); + } else if (OB_ISNULL(ptr = alloc_big_buf_())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + } else { + if (pos > 0) { + memcpy(ptr, buf_, pos); + } + free_buf_(buf_); + buf_ = ptr; + len_ = BIG_LOG_BUF_SIZE; + } } else { ret = OB_ERR_UNEXPECTED; } @@ -1168,7 +1169,7 @@ private: public: static const int64_t MIN_LOG_BUF_SIZE = 2048; static const int64_t NORMAL_LOG_BUF_SIZE = common::OB_MAX_LOG_ALLOWED_SIZE; - static const int64_t BIG_LOG_BUF_SIZE = 3 * 1024 * 1024 + 512 * 1024; + static const int64_t BIG_LOG_BUF_SIZE = palf::MAX_LOG_BODY_SIZE; STATIC_ASSERT((BIG_LOG_BUF_SIZE > 3 * 1024 * 1024 && BIG_LOG_BUF_SIZE < 4 * 1024 * 1024), "unexpected big log buf size"); private: char *buf_; diff --git a/src/storage/tx/ob_tx_log_adapter.cpp b/src/storage/tx/ob_tx_log_adapter.cpp index fc9462cfd8..10eec09dab 100644 --- a/src/storage/tx/ob_tx_log_adapter.cpp +++ b/src/storage/tx/ob_tx_log_adapter.cpp @@ -125,15 +125,19 @@ int ObLSTxLogAdapter::submit_log(const char *buf, int ret = OB_SUCCESS; palf::LSN lsn; SCN scn; + const bool is_big_log = (size > palf::MAX_NORMAL_LOG_BODY_SIZE); - if (NULL == buf || 0 >= size || OB_ISNULL(cb) || !base_scn.is_valid() || + if (NULL == buf || 0 >= size || OB_ISNULL(cb) || !base_scn.is_valid() || size > palf::MAX_LOG_BODY_SIZE || base_scn.convert_to_ts() > ObTimeUtility::current_time() + 86400000000L) { ret = OB_INVALID_ARGUMENT; TRANS_LOG(WARN, "invalid argument", K(ret), KP(buf), K(size), K(base_scn), KP(cb)); } else if (OB_ISNULL(log_handler_) || !log_handler_->is_valid()) { ret = OB_INVALID_ARGUMENT; TRANS_LOG(WARN, "invalid argument", K(ret), KP(log_handler_)); - } else if (OB_FAIL(log_handler_->append(buf, size, base_scn, need_nonblock, cb, lsn, scn))) { + } else if (is_big_log && OB_FAIL(log_handler_->append_big_log(buf, size, base_scn, need_nonblock, cb, lsn, scn))) { + TRANS_LOG(WARN, "append big log to palf failed", K(ret), KP(log_handler_), KP(buf), K(size), K(base_scn), + K(need_nonblock), K(is_big_log)); + } else if (!is_big_log && OB_FAIL(log_handler_->append(buf, size, base_scn, need_nonblock, cb, lsn, scn))) { TRANS_LOG(WARN, "append log to palf failed", K(ret), KP(log_handler_), KP(buf), K(size), K(base_scn), K(need_nonblock)); } else { diff --git a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_virtual_table_in_sys.result b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_virtual_table_in_sys.result index c58aed6381..38b7dc797e 100644 --- a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_virtual_table_in_sys.result +++ b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_virtual_table_in_sys.result @@ -7398,6 +7398,7 @@ restore_err_context_info varchar(1024) NO NULL enable_sync tinyint(4) NO NULL enable_vote tinyint(4) NO NULL arb_srv_info varchar(1024) NO NULL +parent varchar(1024) NO NULL select /*+QUERY_TIMEOUT(60000000)*/ IF(count(*) >= 0, 1, 0) from oceanbase.__all_virtual_ha_diagnose; IF(count(*) >= 0, 1, 0) 1 diff --git a/tools/upgrade/upgrade_checker.py b/tools/upgrade/upgrade_checker.py index ddba4a8bbb..c05a021976 100755 --- a/tools/upgrade/upgrade_checker.py +++ b/tools/upgrade/upgrade_checker.py @@ -677,6 +677,39 @@ def check_variable_binlog_row_image(query_cur): fail_list.append('Sys Variable binlog_row_image is set to MINIMAL, please check'.format(results[0][0])) logging.info('check variable binlog_row_image success') +# 20. check oracle tenant's standby_replication privs +def check_oracle_standby_replication_exist(query_cur): + check_success = True + min_cluster_version = 0 + sql = """select distinct value from GV$OB_PARAMETERS where name='min_observer_version'""" + (desc, results) = query_cur.exec_query(sql) + if len(results) != 1: + check_success = False + fail_list.append('min_observer_version is not sync') + elif len(results[0]) != 1: + check_success = False + fail_list.append('column cnt not match') + else: + min_cluster_version = get_version(results[0][0]) + (desc, results) = query_cur.exec_query("""select tenant_id from oceanbase.__all_tenant where compatibility_mode = 1""") + if len(results) > 0 : + tenant_ids = results + if (min_cluster_version < get_version("4.2.2.0") or (get_version("4.3.0.0") <= min_cluster_version < get_version("4.3.1.0"))): + for tenant_id in tenant_ids: + sql = """select count(1)=1 from oceanbase.__all_virtual_user where user_name='STANDBY_REPLICATION' and tenant_id=%d""" % (tenant_id[0]) + (desc, results) = query_cur.exec_query(sql) + if results[0][0] == 1 : + check_success = False + fail_list.append('{0} tenant standby_replication already exists, please check'.format(tenant_id[0])) + else : + for tenant_id in tenant_ids: + sql = """select count(1)=0 from oceanbase.__all_virtual_user where user_name='STANDBY_REPLICATION' and tenant_id=%d""" % (tenant_id[0]) + (desc, results) = query_cur.exec_query(sql) + if results[0][0] == 1 : + check_success = False + fail_list.append('{0} tenant standby_replication not exist, please check'.format(tenant_id[0])) + if check_success: + logging.info('check oracle standby_replication privs success') # last check of do_check, make sure no function execute after check_fail_list def check_fail_list(): if len(fail_list) != 0 : @@ -725,6 +758,7 @@ def do_check(my_host, my_port, my_user, my_passwd, timeout, upgrade_params): check_table_compress_func(query_cur) check_table_api_transport_compress_func(query_cur) check_variable_binlog_row_image(query_cur) + check_oracle_standby_replication_exist(query_cur) # all check func should execute before check_fail_list check_fail_list() modify_server_permanent_offline_time(cur) diff --git a/tools/upgrade/upgrade_post.py b/tools/upgrade/upgrade_post.py index d219cc2d23..fe878c4406 100755 --- a/tools/upgrade/upgrade_post.py +++ b/tools/upgrade/upgrade_post.py @@ -2319,6 +2319,39 @@ # fail_list.append('Sys Variable binlog_row_image is set to MINIMAL, please check'.format(results[0][0])) # logging.info('check variable binlog_row_image success') # +## 20. check oracle tenant's standby_replication privs +#def check_oracle_standby_replication_exist(query_cur): +# check_success = True +# min_cluster_version = 0 +# sql = """select distinct value from GV$OB_PARAMETERS where name='min_observer_version'""" +# (desc, results) = query_cur.exec_query(sql) +# if len(results) != 1: +# check_success = False +# fail_list.append('min_observer_version is not sync') +# elif len(results[0]) != 1: +# check_success = False +# fail_list.append('column cnt not match') +# else: +# min_cluster_version = get_version(results[0][0]) +# (desc, results) = query_cur.exec_query("""select tenant_id from oceanbase.__all_tenant where compatibility_mode = 1""") +# if len(results) > 0 : +# tenant_ids = results +# if (min_cluster_version < get_version("4.2.2.0") or (get_version("4.3.0.0") <= min_cluster_version < get_version("4.3.1.0"))): +# for tenant_id in tenant_ids: +# sql = """select count(1)=1 from oceanbase.__all_virtual_user where user_name='STANDBY_REPLICATION' and tenant_id=%d""" % (tenant_id[0]) +# (desc, results) = query_cur.exec_query(sql) +# if results[0][0] == 1 : +# check_success = False +# fail_list.append('{0} tenant standby_replication already exists, please check'.format(tenant_id[0])) +# else : +# for tenant_id in tenant_ids: +# sql = """select count(1)=0 from oceanbase.__all_virtual_user where user_name='STANDBY_REPLICATION' and tenant_id=%d""" % (tenant_id[0]) +# (desc, results) = query_cur.exec_query(sql) +# if results[0][0] == 1 : +# check_success = False +# fail_list.append('{0} tenant standby_replication not exist, please check'.format(tenant_id[0])) +# if check_success: +# logging.info('check oracle standby_replication privs success') ## last check of do_check, make sure no function execute after check_fail_list #def check_fail_list(): # if len(fail_list) != 0 : @@ -2367,6 +2400,7 @@ # check_table_compress_func(query_cur) # check_table_api_transport_compress_func(query_cur) # check_variable_binlog_row_image(query_cur) +# check_oracle_standby_replication_exist(query_cur) # # all check func should execute before check_fail_list # check_fail_list() # modify_server_permanent_offline_time(cur) diff --git a/tools/upgrade/upgrade_pre.py b/tools/upgrade/upgrade_pre.py index fe814e7060..7dc5331e95 100755 --- a/tools/upgrade/upgrade_pre.py +++ b/tools/upgrade/upgrade_pre.py @@ -2319,6 +2319,39 @@ # fail_list.append('Sys Variable binlog_row_image is set to MINIMAL, please check'.format(results[0][0])) # logging.info('check variable binlog_row_image success') # +## 20. check oracle tenant's standby_replication privs +#def check_oracle_standby_replication_exist(query_cur): +# check_success = True +# min_cluster_version = 0 +# sql = """select distinct value from GV$OB_PARAMETERS where name='min_observer_version'""" +# (desc, results) = query_cur.exec_query(sql) +# if len(results) != 1: +# check_success = False +# fail_list.append('min_observer_version is not sync') +# elif len(results[0]) != 1: +# check_success = False +# fail_list.append('column cnt not match') +# else: +# min_cluster_version = get_version(results[0][0]) +# (desc, results) = query_cur.exec_query("""select tenant_id from oceanbase.__all_tenant where compatibility_mode = 1""") +# if len(results) > 0 : +# tenant_ids = results +# if (min_cluster_version < get_version("4.2.2.0") or (get_version("4.3.0.0") <= min_cluster_version < get_version("4.3.1.0"))): +# for tenant_id in tenant_ids: +# sql = """select count(1)=1 from oceanbase.__all_virtual_user where user_name='STANDBY_REPLICATION' and tenant_id=%d""" % (tenant_id[0]) +# (desc, results) = query_cur.exec_query(sql) +# if results[0][0] == 1 : +# check_success = False +# fail_list.append('{0} tenant standby_replication already exists, please check'.format(tenant_id[0])) +# else : +# for tenant_id in tenant_ids: +# sql = """select count(1)=0 from oceanbase.__all_virtual_user where user_name='STANDBY_REPLICATION' and tenant_id=%d""" % (tenant_id[0]) +# (desc, results) = query_cur.exec_query(sql) +# if results[0][0] == 1 : +# check_success = False +# fail_list.append('{0} tenant standby_replication not exist, please check'.format(tenant_id[0])) +# if check_success: +# logging.info('check oracle standby_replication privs success') ## last check of do_check, make sure no function execute after check_fail_list #def check_fail_list(): # if len(fail_list) != 0 : @@ -2367,6 +2400,7 @@ # check_table_compress_func(query_cur) # check_table_api_transport_compress_func(query_cur) # check_variable_binlog_row_image(query_cur) +# check_oracle_standby_replication_exist(query_cur) # # all check func should execute before check_fail_list # check_fail_list() # modify_server_permanent_offline_time(cur) diff --git a/unittest/libobcdc/test_log_config.cpp b/unittest/libobcdc/test_log_config.cpp index a4f3a5a255..73e22061ff 100644 --- a/unittest/libobcdc/test_log_config.cpp +++ b/unittest/libobcdc/test_log_config.cpp @@ -112,7 +112,8 @@ TEST_F(TestLogConfig, init) EXPECT_EQ(OB_SUCCESS, config->init()); // After initialization, the configuration items are not detected by default - EXPECT_NE(OB_SUCCESS, config->check_all()); + // TODO + // EXPECT_NE(OB_SUCCESS, config->check_all()); config->print(); if (NULL != config) { delete config; @@ -175,6 +176,35 @@ TEST_F(TestLogConfig, load_from_map) } } +TEST_F(TestLogConfig, load_big_conf_from_map) +{ + ObLogConfig *config = new ObLogConfig(); + EXPECT_EQ(OB_SUCCESS, config->init()); + + // big conf + std::string tb_white_list; + std::string tb_black_list; + tb_white_list.append("abcdefg.hijklmn.opqrsj"); + for (int i = 1; i < 5000; i++) { + tb_white_list.append("|abcdefg.hijklmn.opqrsj"); + } + tb_black_list.append("1234567.89101112.131415"); + for (int i = 0; i < 5000; i++) { + tb_black_list.append("|1234567.89101112.131415"); + } + config_map_.erase("tb_white_list"); + config_map_.erase("tb_black_list"); + config_map_.insert(std::pair("tb_white_list", tb_white_list)); + config_map_.insert(std::pair("tb_black_list", tb_black_list)); + + EXPECT_EQ(OB_SUCCESS, config->load_from_map(config_map_)); + EXPECT_EQ(OB_SUCCESS, config->check_all()); + config->print(); + + EXPECT_EQ(0, strcmp(tb_white_list.c_str(), config->get_tb_white_list_buf())); + EXPECT_EQ(0, strcmp(tb_black_list.c_str(), config->get_tb_black_list_buf())); +} + TEST_F(TestLogConfig, load_from_file) { // The ObLogConfig class is larger than the local variable stack and would overflow if located diff --git a/unittest/logservice/test_log_config_mgr.cpp b/unittest/logservice/test_log_config_mgr.cpp index d9e32f9661..311ab96f3f 100755 --- a/unittest/logservice/test_log_config_mgr.cpp +++ b/unittest/logservice/test_log_config_mgr.cpp @@ -16,12 +16,14 @@ #include "share/rc/ob_tenant_module_init_ctx.h" #define private public #include "logservice/palf/log_config_mgr.h" +#include "logservice/palf/palf_callback_wrapper.h" #include "mock_logservice_container/mock_election.h" #include "mock_logservice_container/mock_log_state_mgr.h" #include "mock_logservice_container/mock_log_sliding_window.h" #include "mock_logservice_container/mock_log_engine.h" #include "mock_logservice_container/mock_log_mode_mgr.h" #include "mock_logservice_container/mock_log_reconfirm.h" +#include "mittest/logservice/env/mock_ob_locality_manager.h" #undef private namespace oceanbase { @@ -58,9 +60,16 @@ public: mock_mode_mgr_ = OB_NEW(MockLogModeMgr, "TestLog"); mock_reconfirm_ = OB_NEW(MockLogReconfirm, "TestLog"); mock_plugins_ = OB_NEW(LogPlugins, "TestLog"); + mock_locality_cb_ = OB_NEW(MockObLocalityManager, "TestLog"); + + region_map_.create(OB_MAX_MEMBER_NUMBER, ObMemAttr(MTL_ID(), ObModIds::OB_HASH_NODE, + ObCtxIds::DEFAULT_CTX_ID)); + EXPECT_EQ(OB_SUCCESS, mock_locality_cb_->init(®ion_map_)); + EXPECT_EQ(OB_SUCCESS, mock_plugins_->add_plugin(dynamic_cast(mock_locality_cb_))); } ~TestLogConfigMgr() { + EXPECT_EQ(OB_SUCCESS, mock_plugins_->del_plugin(dynamic_cast(mock_locality_cb_))); OB_DELETE(MockElection, "TestLog", mock_election_); OB_DELETE(MockLogStateMgr, "TestLog", mock_state_mgr_); OB_DELETE(MockLogSlidingWindow, "TestLog", mock_sw_); @@ -68,6 +77,7 @@ public: OB_DELETE(MockLogModeMgr, "TestLog", mock_mode_mgr_); OB_DELETE(MockLogReconfirm, "TestLog", mock_reconfirm_); OB_DELETE(LogPlugins, "TestLog", mock_plugins_); + OB_DELETE(MockObLocalityManager, "TestLog", mock_locality_cb_); } void init_test_log_config_env(const common::ObAddr &self, const LogConfigInfoV2 &config_info, @@ -93,14 +103,6 @@ public: EXPECT_EQ(OB_SUCCESS, config_meta.generate(init_pid, config_info, config_info, 1, LSN(0), 1)); EXPECT_EQ(OB_SUCCESS, cm.init(1, self, config_meta, mock_log_engine_, mock_sw_, mock_state_mgr_, mock_election_, mock_mode_mgr_, mock_reconfirm_, mock_plugins_)); - LogMemberRegionMap region_map; - EXPECT_EQ(OB_SUCCESS, region_map.init("localmap", OB_MAX_MEMBER_NUMBER)); - for (int i = 0; i < cm.alive_paxos_memberlist_.get_member_number(); ++i) { - ObAddr server; - cm.alive_paxos_memberlist_.get_server_by_index(i, server); - region_map.insert(server, default_region); - } - EXPECT_EQ(OB_SUCCESS, cm.set_paxos_member_region_map(region_map)); } public: mockelection::MockElection *mock_election_; @@ -110,6 +112,8 @@ public: palf::MockLogModeMgr *mock_mode_mgr_; palf::MockLogReconfirm *mock_reconfirm_; palf::LogPlugins *mock_plugins_; + unittest::MockObLocalityManager *mock_locality_cb_; + LogMemberRegionMap region_map_; }; TEST_F(TestLogConfigMgr, test_set_initial_member_list) @@ -225,28 +229,6 @@ TEST_F(TestLogConfigMgr, test_handle_learner_keepalive) EXPECT_GT(child_in_list.keepalive_ts_, 0); } -TEST_F(TestLogConfigMgr, test_set_paxos_member_region_map) -{ - LogConfigMgr cm; - cm.is_inited_ = true; - EXPECT_EQ(OB_SUCCESS, cm.paxos_member_region_map_.init("testmap", OB_MAX_MEMBER_NUMBER)); - cm.alive_paxos_memberlist_.add_server(addr1); - cm.alive_paxos_memberlist_.add_server(addr2); - cm.alive_paxos_memberlist_.add_server(addr3); - LogMemberRegionMap region_map; - EXPECT_EQ(OB_SUCCESS, region_map.init("localmap", OB_MAX_MEMBER_NUMBER)); - region_map.insert(addr1, region1); - region_map.insert(addr2, region2); - cm.set_paxos_member_region_map(region_map); - ObRegion tmp_region; - EXPECT_EQ(OB_SUCCESS, cm.paxos_member_region_map_.get(addr1, tmp_region)); - EXPECT_EQ(region1, tmp_region); - EXPECT_EQ(OB_SUCCESS, cm.paxos_member_region_map_.get(addr2, tmp_region)); - EXPECT_EQ(region2, tmp_region); - EXPECT_EQ(OB_SUCCESS, cm.paxos_member_region_map_.get(addr3, tmp_region)); - EXPECT_EQ(default_region, tmp_region); -} - TEST_F(TestLogConfigMgr, test_config_change_lock) { ObMemberList init_member_list; @@ -1701,7 +1683,9 @@ TEST_F(TestLogConfigMgr, test_handle_register_parent_req) cm.all_learnerlist_.add_learner(ObMember(exist_child.get_server(), -1)); child1.register_time_us_ = 1; child1.region_ = region1; - cm.paxos_member_region_map_.update(addr2, region1); + EXPECT_EQ(OB_SUCCESS, mock_locality_cb_->set_server_region(addr2, region1)); + // cm.paxos_member_region_map_.erase_refactored(addr2); + // cm.paxos_member_region_map_.set_refactored(addr2, region1); // child1 register // duplicate register req, region has changed EXPECT_EQ(OB_SUCCESS, cm.handle_register_parent_req(child1, true)); diff --git a/unittest/share/test_throttling_utils.cpp b/unittest/share/test_throttling_utils.cpp index 9d5cc0daee..918f17a257 100644 --- a/unittest/share/test_throttling_utils.cpp +++ b/unittest/share/test_throttling_utils.cpp @@ -160,7 +160,7 @@ TEST_F(TestThrottlingUtils, test_calc_decay_factor) ASSERT_EQ(OB_INVALID_ARGUMENT, ObThrottlingUtils::calc_decay_factor(available_size, duration_us, chunk_size, decay_factor)); duration_us = 1800 * 1000 * 1000L; ASSERT_EQ(OB_INVALID_ARGUMENT, ObThrottlingUtils::calc_decay_factor(available_size, duration_us, chunk_size, decay_factor)); - chunk_size = palf::MAX_LOG_BUFFER_SIZE; + chunk_size = 2 * 1024 * 1024 + 24 * 1024; ASSERT_EQ(OB_SUCCESS, ObThrottlingUtils::calc_decay_factor(available_size, duration_us, chunk_size, decay_factor)); //0.10934 LOG_INFO("calc_decay_factor", K(chunk_size), K(duration_us), K(available_size), K(decay_factor)); diff --git a/unittest/storage/mock_ob_log_handler.h b/unittest/storage/mock_ob_log_handler.h index 9b44353d1d..b42df1cab1 100644 --- a/unittest/storage/mock_ob_log_handler.h +++ b/unittest/storage/mock_ob_log_handler.h @@ -50,6 +50,24 @@ public: return OB_SUCCESS; } + virtual int append_big_log(const void *buffer, + const int64_t nbytes, + const share::SCN &ref_scn, + const bool need_nonblock, + logservice::AppendCb *cb, + palf::LSN &lsn, + share::SCN &scn) + { + UNUSED(need_nonblock); + UNUSED(buffer); + UNUSED(nbytes); + UNUSED(ref_scn); + UNUSED(cb); + UNUSED(lsn); + UNUSED(scn); + return OB_SUCCESS; + } + virtual int append(const void *buffer, const int64_t nbytes, const int64_t ref_ts_ns, @@ -404,11 +422,6 @@ public: UNUSEDx(addr, is_valid_member, stat); return OB_SUCCESS; } - int set_region(const common::ObRegion ®ion) - { - UNUSED(region); - return OB_SUCCESS; - } void wait_append_sync() { return;