diff --git a/mittest/logservice/env/ob_simple_arb_server.h b/mittest/logservice/env/ob_simple_arb_server.h index 130edf25b9..27e21e9645 100644 --- a/mittest/logservice/env/ob_simple_arb_server.h +++ b/mittest/logservice/env/ob_simple_arb_server.h @@ -171,6 +171,8 @@ public: } return ret; } + int update_server_log_disk(const int64_t log_disk_size) + {return OB_SUCCESS;} public: int simple_init(const std::string &cluster_name, const common::ObAddr &addr, diff --git a/mittest/logservice/env/ob_simple_log_cluster_env.cpp b/mittest/logservice/env/ob_simple_log_cluster_env.cpp index 9d516287ed..afb0b81e72 100755 --- a/mittest/logservice/env/ob_simple_log_cluster_env.cpp +++ b/mittest/logservice/env/ob_simple_log_cluster_env.cpp @@ -1480,5 +1480,15 @@ int ObSimpleLogClusterTestEnv::wait_until_disk_space_to(const int64_t server_id, return ret; } +int ObSimpleLogClusterTestEnv::update_server_log_disk(const int64_t log_disk_size) +{ + int ret = OB_SUCCESS; + auto cluster = get_cluster(); + for (auto srv : cluster) { + srv->update_server_log_disk(log_disk_size); + } + return ret; +} + } // end namespace unittest } // end namespace oceanbase diff --git a/mittest/logservice/env/ob_simple_log_cluster_env.h b/mittest/logservice/env/ob_simple_log_cluster_env.h index a5f31f5935..4bd3253ae0 100644 --- a/mittest/logservice/env/ob_simple_log_cluster_env.h +++ b/mittest/logservice/env/ob_simple_log_cluster_env.h @@ -249,6 +249,7 @@ public: bool is_degraded(const PalfHandleImplGuard &leader, const int64_t degraded_server_idx); bool is_upgraded(PalfHandleImplGuard &leader, const int64_t palf_id); int wait_until_disk_space_to(const int64_t server_id, const int64_t expect_log_disk_space); + int update_server_log_disk(const int64_t log_disk_size); public: static int64_t palf_id_; private: diff --git a/mittest/logservice/env/ob_simple_log_server.cpp b/mittest/logservice/env/ob_simple_log_server.cpp index 29cbc7948d..f7df7b9e64 100644 --- a/mittest/logservice/env/ob_simple_log_server.cpp +++ b/mittest/logservice/env/ob_simple_log_server.cpp @@ -163,44 +163,10 @@ int ObSimpleLogServer::simple_init( return ret; } -int ObSimpleLogServer::construct_allowed_new_log_disk_(const uint64_t tenant_id, - const int64_t expected_log_disk_size, - const int64_t old_log_disk_size, - int64_t &allowed_new_log_disk_size) -{ - int ret = OB_SUCCESS; - bool can_update_log_disk_size_with_expected_log_disk = true; - int64_t palf_log_disk_size = 0; - MAKE_TENANT_SWITCH_SCOPE_GUARD(guard); - if (OB_FAIL(guard.switch_to(tenant_id))) { - LOG_WARN("failed to switch tenant", K(ret), K(tenant_id)); - } else { - ObLogService *log_service = MTL(ObLogService*); - int64_t used_log_disk_size = 0; - if (OB_ISNULL(log_service)) { - ret = OB_ERR_UNEXPECTED; - LOG_ERROR("ObLogService is nullptr", K(ret), KP(log_service)); - } else if (OB_FAIL(log_service->get_palf_stable_disk_usage(used_log_disk_size, palf_log_disk_size))) { - LOG_WARN("failed to update_log_disk_size", K(ret), K(palf_log_disk_size), K(allowed_new_log_disk_size), K(expected_log_disk_size)); - } else if (FALSE_IT(can_update_log_disk_size_with_expected_log_disk = (expected_log_disk_size >= palf_log_disk_size))) { - // For shrinking log disk, we still update log disk size of 'new_unit' to 'old_log_disk_size'. - } else if (!can_update_log_disk_size_with_expected_log_disk - && FALSE_IT(allowed_new_log_disk_size = old_log_disk_size)) { - // For expanding log disk, we update log disk size of 'new_unit' to 'expected_log_disk_size'. - } else if (can_update_log_disk_size_with_expected_log_disk - && FALSE_IT(allowed_new_log_disk_size = expected_log_disk_size)) { - } else { - LOG_INFO("construct_new_log_disk success", K(ret), K(tenant_id), K(can_update_log_disk_size_with_expected_log_disk), - K(old_log_disk_size), K(allowed_new_log_disk_size), K(expected_log_disk_size)); - } - } - return ret; -} - int ObSimpleLogServer::update_tenant_log_disk_size_(const uint64_t tenant_id, - const int64_t expected_log_disk_size, const int64_t old_log_disk_size, - const int64_t allowed_new_log_disk_size) + const int64_t new_log_disk_size, + int64_t &allowed_new_log_disk_size) { int ret = OB_SUCCESS; MAKE_TENANT_SWITCH_SCOPE_GUARD(guard); @@ -208,15 +174,15 @@ int ObSimpleLogServer::update_tenant_log_disk_size_(const uint64_t tenant_id, ObLogService *log_service = MTL(ObLogService *); if (OB_ISNULL(log_service)) { ret = OB_ERR_UNEXPECTED; - } else if (OB_FAIL(log_service->update_log_disk_usage_limit_size(expected_log_disk_size))) { - LOG_WARN("failed to update_log_disk_usage_limit_size", K(ret), K(tenant_id), K(expected_log_disk_size), + } else if (OB_FAIL(log_service->update_log_disk_usage_limit_size(new_log_disk_size))) { + LOG_WARN("failed to update_log_disk_usage_limit_size", K(ret), K(tenant_id), K(new_log_disk_size), K(old_log_disk_size), K(allowed_new_log_disk_size)); - } else if (OB_FAIL(log_block_pool_.update_tenant(old_log_disk_size, allowed_new_log_disk_size))) { - LOG_WARN("failed to update teannt int ObServerLogBlockMGR", K(ret), K(tenant_id), K(expected_log_disk_size), + } else if (OB_FAIL(log_block_pool_.update_tenant(old_log_disk_size, new_log_disk_size, allowed_new_log_disk_size, log_service))) { + LOG_WARN("failed to update teannt int ObServerLogBlockMGR", K(ret), K(tenant_id), K(new_log_disk_size), K(old_log_disk_size), K(allowed_new_log_disk_size)); } else { disk_opts_.log_disk_usage_limit_size_ = allowed_new_log_disk_size; - LOG_INFO("update_log_disk_usage_limit_size success", K(ret), K(tenant_id), K(expected_log_disk_size), + LOG_INFO("update_log_disk_usage_limit_size success", K(ret), K(tenant_id), K(new_log_disk_size), K(old_log_disk_size), K(allowed_new_log_disk_size), K(disk_opts_)); } } @@ -226,26 +192,26 @@ int ObSimpleLogServer::update_tenant_log_disk_size_(const uint64_t tenant_id, int ObSimpleLogServer::update_disk_opts_no_lock_(const PalfDiskOptions &opts) { int ret = OB_SUCCESS; + CLOG_LOG(INFO, "begin update_disk_opts_no_lock_", K(opts), K(disk_opts_), K(inner_table_disk_opts_)); int64_t old_log_disk_size = disk_opts_.log_disk_usage_limit_size_; - int64_t expected_log_disk_size = opts.log_disk_usage_limit_size_; + int64_t new_log_disk_size = opts.log_disk_usage_limit_size_; int64_t allowed_new_log_disk_size = 0; // 内部表中的disk_opts立马生效 inner_table_disk_opts_ = opts; - // disk_opts_表示本地持久化最新的disk_opts,在construct_allowed_new_log_disk_中会修改disk_opts_的log_disk_usage_limit_size_ + // disk_opts_表示本地持久化最新的disk_opts,log_disk_percentage_延迟生效 disk_opts_ = opts; + disk_opts_.log_disk_usage_limit_size_ = old_log_disk_size; if (!opts.is_valid()) { ret = OB_INVALID_ARGUMENT; CLOG_LOG(WARN, "invalid argument", K(opts)); - } else if (OB_FAIL(construct_allowed_new_log_disk_(node_id_, expected_log_disk_size, - old_log_disk_size, allowed_new_log_disk_size))) { - CLOG_LOG(WARN, "construct_allowed_new_log_disk_ failed", K(expected_log_disk_size), K(old_log_disk_size), - K(allowed_new_log_disk_size)); - } else if (OB_FAIL(update_tenant_log_disk_size_(node_id_, expected_log_disk_size, - old_log_disk_size, allowed_new_log_disk_size))) { - CLOG_LOG(WARN, "update_tenant_log_disk_size_ failed", K(expected_log_disk_size), K(old_log_disk_size), + } else if (OB_FAIL(update_tenant_log_disk_size_(node_id_, + old_log_disk_size, + new_log_disk_size, + allowed_new_log_disk_size))) { + CLOG_LOG(WARN, "update_tenant_log_disk_size_ failed", K(new_log_disk_size), K(old_log_disk_size), K(allowed_new_log_disk_size)); } else { - CLOG_LOG(INFO, "update_disk_opts success", K(opts), K(disk_opts_), K(expected_log_disk_size), K(old_log_disk_size), + CLOG_LOG(INFO, "update_disk_opts success", K(opts), K(disk_opts_), K(new_log_disk_size), K(old_log_disk_size), K(allowed_new_log_disk_size)); } return ret; @@ -272,6 +238,12 @@ int ObSimpleLogServer::try_resize() return ret; } +int ObSimpleLogServer::update_server_log_disk(const int64_t log_disk_size) +{ + ObSpinLockGuard guard(log_disk_lock_); + return log_block_pool_.resize_(log_disk_size); +} + int ObSimpleLogServer::init_memory_dump_timer_() { int ret = OB_SUCCESS; @@ -349,7 +321,8 @@ int ObSimpleLogServer::init_io_(const std::string &cluster_name) storage_env.default_block_size_ = OB_DEFAULT_MACRO_BLOCK_SIZE; storage_env.data_disk_size_ = 1024 * 1024 * 1024; storage_env.data_disk_percentage_ = 0; - storage_env.log_disk_size_ = 10LL * 1024 * 1024 * 1024; + // 当disk_opts_有效时,使用disk_opts_中记录的log_disk_usage_limit_size_作为log_block_pool_的初始值,否则重启会失败 + storage_env.log_disk_size_ = disk_opts_.is_valid() ? disk_opts_.log_disk_usage_limit_size_ : 2LL * 1024 * 1024 * 1024; storage_env.log_disk_percentage_ = 0; storage_env.log_spec_.log_dir_ = slog_dir.c_str(); @@ -394,7 +367,7 @@ int ObSimpleLogServer::init_log_service_() if (disk_opts_.is_valid()) { opts.disk_options_ = disk_opts_; } else { - opts.disk_options_.log_disk_usage_limit_size_ = 10 * 1024 * 1024 * 1024ul; + opts.disk_options_.log_disk_usage_limit_size_ = 2 * 1024 * 1024 * 1024ul; opts.disk_options_.log_disk_utilization_threshold_ = 80; opts.disk_options_.log_disk_utilization_limit_threshold_ = 95; opts.disk_options_.log_disk_throttling_percentage_ = 100; diff --git a/mittest/logservice/env/ob_simple_log_server.h b/mittest/logservice/env/ob_simple_log_server.h index 49392d08dd..ce3b1d2620 100644 --- a/mittest/logservice/env/ob_simple_log_server.h +++ b/mittest/logservice/env/ob_simple_log_server.h @@ -251,6 +251,7 @@ public: virtual int create_mock_election(const int64_t palf_id, MockElection *&mock_election) = 0; 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; DECLARE_PURE_VIRTUAL_TO_STRING; }; @@ -287,6 +288,7 @@ public: virtual int update_disk_opts(const PalfDiskOptions &opts) override final; virtual int get_disk_opts(PalfDiskOptions &opts) override final { + ObSpinLockGuard guard(log_disk_lock_); opts = disk_opts_; return OB_SUCCESS; } @@ -368,6 +370,7 @@ public: } return ret; } + int update_server_log_disk(const int64_t log_disk_size); TO_STRING_KV(K_(node_id), K_(addr), KP(palf_env_)); protected: @@ -375,15 +378,10 @@ protected: int init_network_(const common::ObAddr &addr, const bool is_bootstrap); int init_log_service_(); int init_memory_dump_timer_(); - // 更新log_disk_size的逻辑保持和ObMultiTenant.cpp中维护同名函数一样 - int construct_allowed_new_log_disk_(const uint64_t tenant_id, - const int64_t expected_log_disk_size, - const int64_t old_log_disk_size, - int64_t &allowed_new_log_disk_size); int update_tenant_log_disk_size_(const uint64_t tenant_id, - const int64_t expected_log_disk_size, const int64_t old_log_disk_size, - const int64_t allowed_log_disk_size); + const int64_t new_log_disk_size, + int64_t &allowed_log_disk_size); int update_disk_opts_no_lock_(const PalfDiskOptions &opts); private: @@ -415,8 +413,11 @@ private: ObSrvRpcProxy srv_proxy_; logservice::coordinator::ObFailureDetector detector_; MockElectionMap mock_election_map_; + // ObTenantUnit以及__all_unit_configs ObSpinLock log_disk_lock_; + // 本地已生效日志盘规格 palf::PalfDiskOptions disk_opts_; + // 内部表中记录日志盘规格 palf::PalfDiskOptions inner_table_disk_opts_; ObLooper looper_; }; diff --git a/mittest/logservice/test_ob_simple_log_disk_mgr.cpp b/mittest/logservice/test_ob_simple_log_disk_mgr.cpp index b4cc3f8423..ae238c1479 100644 --- a/mittest/logservice/test_ob_simple_log_disk_mgr.cpp +++ b/mittest/logservice/test_ob_simple_log_disk_mgr.cpp @@ -37,27 +37,27 @@ using namespace logservice; namespace unittest { class TestObSimpleLogDiskMgr : public ObSimpleLogClusterTestEnv -{ -public: - TestObSimpleLogDiskMgr() : ObSimpleLogClusterTestEnv() { - int ret = init(); - if (OB_SUCCESS != ret) { - throw std::runtime_error("TestObSimpleLogDiskMgr init failed"); + public: + TestObSimpleLogDiskMgr() : ObSimpleLogClusterTestEnv() + { + int ret = init(); + if (OB_SUCCESS != ret) { + throw std::runtime_error("TestObSimpleLogDiskMgr init failed"); + } } - } - ~TestObSimpleLogDiskMgr() - { - destroy(); - } - int init() - { - return OB_SUCCESS; - } - void destroy() - {} - int64_t id_; -}; + ~TestObSimpleLogDiskMgr() + { + destroy(); + } + int init() + { + return OB_SUCCESS; + } + void destroy() + {} + int64_t id_; + }; int64_t ObSimpleLogClusterTestBase::member_cnt_ = 1; int64_t ObSimpleLogClusterTestBase::node_cnt_ = 1; @@ -66,6 +66,8 @@ bool ObSimpleLogClusterTestBase::need_add_arb_server_ = false; TEST_F(TestObSimpleLogDiskMgr, out_of_disk_space) { + 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, "out_of_disk_space"); int64_t id = ATOMIC_AAF(&palf_id_, 1); int server_idx = 0; @@ -117,7 +119,8 @@ TEST_F(TestObSimpleLogDiskMgr, update_disk_options_basic) palf_env->palf_env_impl_.disk_options_wrapper_.status_); EXPECT_EQ(palf_env->palf_env_impl_.disk_options_wrapper_.disk_opts_for_recycling_blocks_.log_disk_usage_limit_size_, 20*PALF_PHY_BLOCK_SIZE); - // 可以在上一次为缩容完成之前,可以继续缩容 + + // case1: 在上一次未缩容完成之前,可以继续缩容 EXPECT_EQ(OB_SUCCESS, update_disk_options(leader_idx, 10)); usleep(1000*1000+palf::BlockGCTimerTask::BLOCK_GC_TIMER_INTERVAL_MS); EXPECT_EQ(PalfDiskOptionsWrapper::Status::SHRINKING_STATUS, @@ -130,8 +133,7 @@ TEST_F(TestObSimpleLogDiskMgr, update_disk_options_basic) EXPECT_EQ(OB_SUCCESS, get_disk_options(leader_idx, opts)); EXPECT_EQ(opts.log_disk_usage_limit_size_, 10*1024*1024*1024ul); } - // 可以在上一次未缩容完成之前,可以继续扩容, 同时由于扩容后日志盘依旧小于第一次缩容 - // ,因此依旧处于缩容状态. + // case2: 在上一次未缩容完成之前,可以继续扩容, 同时由于扩容后日志盘依旧小于第一次缩容,因此依旧处于缩容状态. EXPECT_EQ(OB_SUCCESS, update_disk_options(leader_idx, 11)); usleep(1000*1000+palf::BlockGCTimerTask::BLOCK_GC_TIMER_INTERVAL_MS); EXPECT_EQ(PalfDiskOptionsWrapper::Status::SHRINKING_STATUS, @@ -171,6 +173,37 @@ TEST_F(TestObSimpleLogDiskMgr, update_disk_options_basic) } } +TEST_F(TestObSimpleLogDiskMgr, shrink_log_disk) +{ + SET_CASE_LOG_FILE(TEST_NAME, "shrink_log_disk"); + OB_LOGGER.set_log_level("INFO"); + // 验证缩容由于单日志流最少需要512MB日志盘失败 + // 保证能同时容纳两个日志流 + PalfEnv *palf_env = NULL; + int64_t leader_idx = 0; + PalfHandleImplGuard leader; + share::SCN create_scn = share::SCN::base_scn(); + int server_idx = 0; + EXPECT_EQ(OB_SUCCESS, get_palf_env(server_idx, palf_env)); + EXPECT_EQ(OB_SUCCESS, update_disk_options(16)); + EXPECT_EQ(PalfDiskOptionsWrapper::Status::NORMAL_STATUS, + palf_env->palf_env_impl_.disk_options_wrapper_.status_); + EXPECT_EQ(palf_env->palf_env_impl_.disk_options_wrapper_.disk_opts_for_stopping_writing_.log_disk_usage_limit_size_, + 16*PALF_PHY_BLOCK_SIZE); + int64_t tmp_id1 = ATOMIC_AAF(&palf_id_, 1); + { + PalfHandleImplGuard leader; + EXPECT_EQ(OB_SUCCESS, create_paxos_group(tmp_id1, leader_idx, leader)); + } + int64_t tmp_id2 = ATOMIC_AAF(&palf_id_, 1); + { + PalfHandleImplGuard leader; + EXPECT_EQ(OB_SUCCESS, create_paxos_group(tmp_id2, leader_idx, leader)); + } + EXPECT_EQ(OB_NOT_SUPPORTED, update_disk_options(9)); + EXPECT_EQ(OB_SUCCESS, delete_paxos_group(tmp_id1)); +} + TEST_F(TestObSimpleLogDiskMgr, update_disk_options_restart) { disable_hot_cache_ = true; diff --git a/mittest/logservice/test_ob_simple_log_engine.cpp b/mittest/logservice/test_ob_simple_log_engine.cpp index 9bf7ca5f0b..cb6230c93d 100644 --- a/mittest/logservice/test_ob_simple_log_engine.cpp +++ b/mittest/logservice/test_ob_simple_log_engine.cpp @@ -457,7 +457,8 @@ public: TEST_F(TestObSimpleLogClusterLogEngine, io_reducer_basic_func) { SET_CASE_LOG_FILE(TEST_NAME, "io_reducer_func"); - + update_server_log_disk(4*1024*1024*1024ul); + update_disk_options(4*1024*1024*1024ul/palf::PALF_PHY_BLOCK_SIZE); OB_LOGGER.set_log_level("TRACE"); PALF_LOG(INFO, "begin io_reducer_basic_func"); PalfHandleImplGuard leader_1; diff --git a/mittest/logservice/test_ob_simple_log_rebuild.cpp b/mittest/logservice/test_ob_simple_log_rebuild.cpp index f8b830afe2..343f0f9d16 100644 --- a/mittest/logservice/test_ob_simple_log_rebuild.cpp +++ b/mittest/logservice/test_ob_simple_log_rebuild.cpp @@ -182,14 +182,14 @@ TEST_F(TestObSimpleLogClusterRebuild, test_old_leader_rebuild) EXPECT_EQ(OB_SUCCESS, get_leader(id, new_leader, new_leader_idx)); PALF_LOG(INFO, "after get_leader", K(id), K(leader_idx), K(new_leader_idx)); // submit logs - EXPECT_EQ(OB_SUCCESS, submit_log(new_leader, 64 * 6, id, MB)); + EXPECT_EQ(OB_SUCCESS, submit_log(new_leader, 64 * 8, id, MB)); // update new_leader's disk option, only reserves 4 * 80% log blocks, // that means 2 blocks will be recycled PALF_LOG(INFO, "begin advance_base_lsn", K(id), K(leader_idx), K(new_leader_idx)); LSN recycle_lsn(2 * PALF_BLOCK_SIZE); EXPECT_EQ(OB_SUCCESS, new_leader.palf_handle_impl_->set_base_lsn(recycle_lsn)); - update_disk_options(new_leader_idx, 4); + update_disk_options(new_leader_idx, 8); // recycle 2 block sleep(5); block_id_t leader_min_block_id; @@ -254,7 +254,7 @@ TEST_F(TestObSimpleLogClusterRebuild, test_old_leader_rebuild) revert_cluster_palf_handle_guard(palf_list); EXPECT_EQ(OB_SUCCESS, new_leader.palf_handle_impl_->set_base_lsn(LSN(64*6*MB))); sleep(1); - EXPECT_EQ(OB_SUCCESS, update_disk_options(new_leader_idx, 40)); + EXPECT_EQ(OB_SUCCESS, update_disk_options(new_leader_idx, 30)); PALF_LOG(INFO, "end test old_leader_rebuild", K(id)); } @@ -283,11 +283,11 @@ TEST_F(TestObSimpleLogClusterRebuild, test_follower_rebuild) // the follower is empty block_net(leader_idx, follower_idx); EXPECT_EQ(OB_SUCCESS, submit_log(leader, 64, leader_idx, MB)); - EXPECT_EQ(OB_SUCCESS, submit_log(leader, 64 * 5, leader_idx, MB)); + EXPECT_EQ(OB_SUCCESS, submit_log(leader, 64 * 7, leader_idx, MB)); // recycle one block LSN recycle_lsn(2 * PALF_BLOCK_SIZE); EXPECT_EQ(OB_SUCCESS, leader.palf_handle_impl_->set_base_lsn(recycle_lsn)); - update_disk_options(leader_idx, 4); + update_disk_options(leader_idx, 8); sleep(1); block_id_t leader_min_block_id, follower_min_block_id; share::SCN min_scn; 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 05b1ce9c94..3593a325ad 100644 --- a/mittest/logservice/test_ob_simple_log_single_replica_func.cpp +++ b/mittest/logservice/test_ob_simple_log_single_replica_func.cpp @@ -97,6 +97,8 @@ void read_padding_entry(PalfHandleImplGuard &leader, SCN padding_scn, LSN paddin TEST_F(TestObSimpleLogClusterSingleReplica, delete_paxos_group) { + 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, "delete_paxos_group"); const int64_t id = ATOMIC_AAF(&palf_id_, 1); PALF_LOG(INFO, "start test delete_paxos_group", K(id)); diff --git a/src/logservice/ob_server_log_block_mgr.cpp b/src/logservice/ob_server_log_block_mgr.cpp index 6e1f3b5c28..6c4bff5e28 100644 --- a/src/logservice/ob_server_log_block_mgr.cpp +++ b/src/logservice/ob_server_log_block_mgr.cpp @@ -158,7 +158,7 @@ int ObServerLogBlockMgr::start(const int64_t new_size_byte) ret = OB_NOT_INIT; CLOG_LOG(WARN, "ObServerLogBlockMGR is not inited", K(ret), KPC(this)); } else if (!check_space_is_enough_(new_size_byte)) { - ret = OB_LOG_OUTOF_DISK_SPACE; + ret = OB_MACHINE_RESOURCE_NOT_ENOUGH; CLOG_LOG(WARN, "server log disk is too small to hold all tenants or the count of tenants" ", log disk space is not enough!!!", K(ret), KPC(this), K(min_log_disk_size_for_all_tenants_), K(new_size_byte)); @@ -189,27 +189,25 @@ int ObServerLogBlockMgr::resize_(const int64_t new_size_byte) ret = OB_NOT_INIT; CLOG_LOG(ERROR, "ObServerLogBlockMgr has not inited", K(ret), KPC(this), K(new_size_byte), K(aligned_new_size_byte)); - } else if (new_size_byte < share::ObUnitResource::UNIT_MIN_LOG_DISK_SIZE) { - ret = OB_NOT_SUPPORTED; - CLOG_LOG(ERROR, "The size of reserved disp space need greater than 1GB!!!", K(ret), - KPC(this), K(new_size_byte), K(aligned_new_size_byte)); } else if (curr_total_size == aligned_new_size_byte) { CLOG_LOG(TRACE, "no need do resize", K(ret), KPC(this), K(new_size_byte), K(aligned_new_size_byte)); } else if (FALSE_IT(new_log_pool_meta.status_ = (aligned_new_size_byte > curr_total_size ? EXPANDING_STATUS : SHRINKING_STATUS))) { - } else if (SHRINKING_STATUS == new_log_pool_meta.status_ - && free_size_byte < resize_block_cnt * BLOCK_SIZE) { + } else if (aligned_new_size_byte < min_log_disk_size_for_all_tenants_) { ret = OB_NOT_SUPPORTED; - CLOG_LOG(ERROR, "shrink_block_cnt is greater than free_block_cnt", K(ret), KPC(this), - K(resize_block_cnt), "free_block_cnt:", free_size_byte / BLOCK_SIZE); + LOG_DBA_ERROR(OB_NOT_SUPPORTED, + "possible reason", + "new log_disk_size is not enough to hold all tenants, please check the configuration about log disk", + "new log disk size(MB)", (new_size_byte+1024*1024-1)/1024/1024, + "min log disk size(MB)", (min_log_disk_size_for_all_tenants_+1024*1024-1)/1024/1024); } else if (OB_FAIL( do_resize_(old_log_pool_meta, resize_block_cnt, new_log_pool_meta))) { if (OB_ALLOCATE_DISK_SPACE_FAILED == ret) { LOG_DBA_ERROR(OB_ALLOCATE_DISK_SPACE_FAILED, "possible reason", "may be diskspace is not enough, please check the configuration about log disk", - "expected log disk size(MB)", (new_size_byte+1024*1024-1)/1024/1024); + "new log disk size(MB)", (new_size_byte+1024*1024-1)/1024/1024); } else { CLOG_LOG(ERROR, "do_resize_ failed", K(ret), KPC(this), K(old_log_pool_meta), K(new_log_pool_meta)); @@ -343,40 +341,113 @@ void ObServerLogBlockMgr::abort_create_tenant(const int64_t log_disk_size) } } -int ObServerLogBlockMgr::update_tenant(const int64_t old_log_disk_size, const int64_t new_log_disk_size) +int ObServerLogBlockMgr::update_tenant(const int64_t old_log_disk_size, + const int64_t new_log_disk_size, + int64_t &allowed_new_log_disk_size, + logservice::ObLogService *log_service) { int ret = OB_SUCCESS; + ObSpinLockGuard guard(resize_lock_); + int64_t used_log_disk_size = 0, palf_log_disk_size = 0; + bool can_update_log_disk_size_with_expected_log_disk = false; + int64_t tmp_log_disk_size = min_log_disk_size_for_all_tenants_; + tmp_log_disk_size -= old_log_disk_size; + // 'old_log_disk_size' is current log disk size in ObTenant. + // 'new_log_disk_size' is the latest log disk size record in __all_unit_config. + // 'allowed_new_log_disk_size' is current allowed log disk size when update log disk. + // + // To avoid overselling, we can not use 'new_log_disk_size' to update unit config which will save in slog. + // therefore, we need constuct a virtual log disk size which named with 'allowed_new_log_disk_size'. if (IS_NOT_INIT) { ret = OB_NOT_INIT; CLOG_LOG(WARN, "ObServerLogBlockMGR is not inited", K(old_log_disk_size), K(new_log_disk_size), KPC(this)); + } else if (old_log_disk_size <= 0 || new_log_disk_size <= 0 || OB_ISNULL(log_service)) { + ret = OB_INVALID_ARGUMENT; + CLOG_LOG(WARN, "invalid argument", K(old_log_disk_size), K(new_log_disk_size), KP(log_service), KPC(this)); + } else if (OB_FAIL(log_service->get_palf_stable_disk_usage(used_log_disk_size, palf_log_disk_size))) { + CLOG_LOG(WARN, "fail to get_palf_stable_disk_usage", K(old_log_disk_size), K(new_log_disk_size)); + // The standard for determing whether it's in shrinking or expanding status: + // 1. If 'palf_log_disk_size' is smaller than or equal to 'new_log_disk_size', it's in expanding status. + // 2. If 'palf_log_disk_size' is greater than 'new_log_disk_size', it's in shrinking status. + // + // For shrinking log disk, we don't update ObTenantConfig of ObTenant to new ObTenantConfig until shrinking successfully. + // + // NB: All fields of new ObTenantConfig except log_disk_size has been updated in case of shrinking log disk. + // + // For example: + // 1. before shrinkg log disk successfully, and then expand log disk. + // - At T1 timestamp, the original log disk is 100G, and update it to 50G, we will construct 'new_unit' with + // 100G, but update palf with 50G because original log disk size is greater than new log disk size. + // - At T2 timestamp, the log disk size in current ObTenantConfig is 100G, and we update it to 80G, there are + // two scenarios: + // 1. if 'palf_log_disk_size' which get from palf is 100G, we think palf is still in shrinking status. and we will + // construct 'new_unit' with 100G because 'palf_log_disk_size' is greater than new log disk size(80G). but udpate + // palf with 80G + // 2. if 'palf_log_disk_size' which get from palf is 50G, we think palf has been in normal status. and we will + // construct 'new_unit' with 80G because 'palf_log_disk_size' is smaller than new log disk size(80G), but udpate + // palf with 80G. + } else if (FALSE_IT(can_update_log_disk_size_with_expected_log_disk = (new_log_disk_size >= palf_log_disk_size))) { + // For expanding log disk, we can update 'allowed_new_log_disk_size' to 'new_log_disk_size' directlly. + } else if (can_update_log_disk_size_with_expected_log_disk && FALSE_IT(allowed_new_log_disk_size = new_log_disk_size)) { + // For shrinking log disk, we still update log disk size of 'new_unit' to 'old_log_disk_size'. + } else if (!can_update_log_disk_size_with_expected_log_disk && FALSE_IT(allowed_new_log_disk_size = old_log_disk_size)) { + } else if ((tmp_log_disk_size += allowed_new_log_disk_size) > get_total_size_guarded_by_lock_()) { + ret = OB_MACHINE_RESOURCE_NOT_ENOUGH; + CLOG_LOG(WARN, "ObServerLogBlockMGR can not hold any new tenants", KPC(this), K(old_log_disk_size), + K(new_log_disk_size), K(allowed_new_log_disk_size), K(tmp_log_disk_size)); + // case 1: for shrinking log disk, shrinking log disk from 100G to 50G. + // - At T1 timestamp, 'new_log_disk_size' is 50G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 100G. + // the log disk size record in slog is 100G, and we will update log disk size used for palf to 50G, but not update log + // disk which has assigned in ObServerLogBlockMGR. + // - At T2 timestamp, 'new_log_disk_size' is still 50G, 'old_log_disk_size' is still 100G, however, 'allowed_new_log_disk_size' + // is 50G because of shrinking log disk has been successfully, the log disk record in slog is 50G, and then we will update log disk + // size used for palf to 50G again but has no effect, log disk assigned in ObServerLogBlockMGR update to 50G(assume there is only one tenant). + // + // case 2: for expanding log disk, expanding log disk from 100G to 150G. + // - At T1 timestamp, 'new_log_disk_size' is 150G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 150G. + // the log disk size record in slog is 150G, and then, we will update log disk size used for palf to 150G, the log disk + // which has assigned in ObServerLogBlockMGR updaet to 150G(assume there is only one tenant). + // + // case 3: for shrinking log disk, shrinking log disk from 100G to 50G, and then shrinking log disk from 50G to 25G. + // - At T1 timestamp, 'new_log_disk_size' is 50G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 100G. + // the log disk size record in slog is 100G, and we will update log disk size used for palf to 50G, but not update log + // disk which has assigned in ObServerLogBlockMGR. + // - At T2 timestamp, 'new_log_disk_size' is 25G, 'old_log_disk_size' is still 100G, however, there are two possibility value for + // 'allowed_new_log_disk_size': + // 1. the value is 100G because of last shrinking log disk has not been successfully, the log disk record in slog is still 100G + // and then we will update log disk size used for palf to 25G, but not update log disk assigned in ObServerLogBlockMGR. + // At T3 timestamp, 'new_log_disk_size' is 25G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 25G, + // the log disk record in slog is 25G, the log disk assigned in ObServerLogBlockMGR is 25G. + // 2. the value is 50G because of last shrinking log disk has been successfully, the log disk record in slog is 50G + // and then we will update log disk size used for palf to 25G, update log disk assigned in ObServerLogBlockMGR to 50G(assume there is only one tenant). + // At T3 timestamp, 'new_log_disk_size' is 25G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 25G, + // the log disk record in slog is 25G, the log disk assigned in ObServerLogBlockMGR is 25G. + // + // case 4: for shrinking log disk, shrinking log disk from 100G to 50G, and then expanding log disk from 50G to 80G. + // - At T1 timestamp, 'new_log_disk_size' is 50G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 100G. + // the log disk size record in slog is 100G, and we will update log disk size used for palf to 50G, but not update log + // disk which has assigned in ObServerLogBlockMGR. + // - At T2 timestamp, 'new_log_disk_size' is 80G, 'old_log_disk_size' is still 100G, however, there are two possibility value for + // 'allowed_new_log_disk_size': + // 1. the value is 100G because of last shrinking log disk has not been successfully, the log disk record in slog is still 100G + // and then we will update log disk size used for palf to 80G, but not update log disk assigned in ObServerLogBlockMGR. + // At T3 timestamp, 'new_log_disk_size' is 80G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 80G, + // the log disk record in slog is 80G, the log disk assigned in ObServerLogBlockMGR is 80G. + // 2. the value is 80G because of last shrinking log disk has been successfully, the log disk record in slog is 80G + // and then we will update log disk size used for palf to 80G, update log disk assigned in ObServerLogBlockMGR to 80G(assume there is only one tenant). + // At T3 timestamp, 'new_log_disk_size' is 25G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 25G, + // the log disk record in slog is 25G, the log disk assigned in ObServerLogBlockMGR is 25G. + // + } else if (OB_FAIL(log_service->update_log_disk_usage_limit_size(new_log_disk_size))) { + CLOG_LOG(WARN, "failed to update_log_disk_usage_limit_size", K(new_log_disk_size), K(old_log_disk_size), + K(allowed_new_log_disk_size)); } else { - ObSpinLockGuard guard(resize_lock_); - int64_t tmp_log_disk_size = min_log_disk_size_for_all_tenants_; - tmp_log_disk_size -= old_log_disk_size; - if ((tmp_log_disk_size +=new_log_disk_size) > get_total_size_guarded_by_lock_()) { - ret = OB_MACHINE_RESOURCE_NOT_ENOUGH; - CLOG_LOG(ERROR, "ObServerLogBlockMGR can not hold any new tenants", - K(ret), KPC(this), K(old_log_disk_size), K(new_log_disk_size)); - } else { - min_log_disk_size_for_all_tenants_ = tmp_log_disk_size; - CLOG_LOG(INFO, "ObServerLogBlockMGR update_tenant success", KPC(this), K(old_log_disk_size), K(new_log_disk_size)); - } + min_log_disk_size_for_all_tenants_ = tmp_log_disk_size; + CLOG_LOG(INFO, "update_tenant success", KPC(this), K(new_log_disk_size), K(old_log_disk_size), + K(allowed_new_log_disk_size)); } - return ret; -} -void ObServerLogBlockMgr::abort_update_tenant(const int64_t old_log_disk_size, const int64_t new_log_disk_size) -{ - if (IS_NOT_INIT) { - CLOG_LOG_RET(WARN, OB_NOT_INIT, "ObServerLogBlockMGR is not inited", K(old_log_disk_size), K(new_log_disk_size), KPC(this)); - } else { - ObSpinLockGuard guard(resize_lock_); - min_log_disk_size_for_all_tenants_ -= old_log_disk_size; - min_log_disk_size_for_all_tenants_ += new_log_disk_size; - OB_ASSERT(min_log_disk_size_for_all_tenants_ >= 0 - && min_log_disk_size_for_all_tenants_ <= get_total_size_guarded_by_lock_()); - CLOG_LOG(INFO, "ObServerLogBlockMGR abort_update_tenant success", KPC(this), K(old_log_disk_size), K(new_log_disk_size)); - } + return ret; } int ObServerLogBlockMgr::remove_tenant(const int64_t log_disk_size) @@ -695,17 +766,13 @@ int ObServerLogBlockMgr::try_resize() ret = OB_NOT_RUNNING; CLOG_LOG(WARN, "ObServerLogBlockMgr not running, can not support resize", KPC(this)); } else if (OB_FAIL(observer::ObServerUtils::get_log_disk_info_in_config(log_disk_size, - log_disk_percentage))) { - if (OB_LOG_OUTOF_DISK_SPACE == ret) { - CLOG_LOG(ERROR, "log disk size is too large", K(ret), KPC(this), - K(log_disk_size), K(log_disk_percentage)); + log_disk_percentage))) { + if (OB_SERVER_OUTOF_DISK_SPACE == ret) { + ret = OB_MACHINE_RESOURCE_NOT_ENOUGH; + CLOG_LOG(ERROR, "try_resize failed, log disk space is not enough", K(log_disk_size), KPC(this)); } else { - CLOG_LOG(ERROR, "get_log_disk_info_in_config failed", K(ret), KPC(this), - K(log_disk_size), K(log_disk_percentage)); + CLOG_LOG(ERROR, "get_log_disk_info_in_config failed", K(log_disk_size), KPC(this)); } - } else if (log_disk_size == get_total_size_guarded_by_lock_()) { - } else if (false == check_space_is_enough_(log_disk_size)) { - CLOG_LOG(ERROR, "log disk size is not enough to hold all tenants", KPC(this), K(log_disk_size)); } else if (OB_FAIL(resize_(log_disk_size))) { CLOG_LOG(ERROR, "ObServerLogBlockMGR resize failed", K(ret), KPC(this)); } else { diff --git a/src/logservice/ob_server_log_block_mgr.h b/src/logservice/ob_server_log_block_mgr.h index 87d35f781a..ca4c8a6842 100644 --- a/src/logservice/ob_server_log_block_mgr.h +++ b/src/logservice/ob_server_log_block_mgr.h @@ -29,7 +29,7 @@ namespace oceanbase { namespace logservice { - +class ObLogService; class ObServerLogBlockMgr : public palf::ILogBlockPool { public: @@ -187,14 +187,14 @@ public: // @brief before 'update_tenant_log_disk_size' in ObMultiTenant, need update it. // @param[in] the log disk size used by tenant. // @param[in] the log disk size need by tenant. + // @param[in] the log disk size allowed by tenant + // @param[in] ObLogService* // OB_SUCCESS // OB_MACHINE_RESOURCE_NOT_ENOUGH - int update_tenant(const int64_t old_log_disk_size, const int64_t new_log_disk_size); - - // @brief after 'update_tenant_log_disk_size' in ObMultiTenant failed, need rollbakc it. - // @param[in] the log disk size need by tenant. - // @param[in] the log disk size used by tenant. - void abort_update_tenant(const int64_t old_log_disk_size, const int64_t new_log_disk_size); + int update_tenant(const int64_t old_log_disk_size, + const int64_t new_log_disk_size, + int64_t &allowed_log_disk_size, + ObLogService *log_service); // @brief after 'del_tenant' in ObMultiTenant success, need remove it from ObServerLogBlockMgr // NB: accurately, when tenant not exist in 'omt_', we can remove it from ObServerLogBlockMgr diff --git a/src/logservice/palf/palf_env_impl.cpp b/src/logservice/palf/palf_env_impl.cpp index 4240b08460..bef621624c 100644 --- a/src/logservice/palf/palf_env_impl.cpp +++ b/src/logservice/palf/palf_env_impl.cpp @@ -169,7 +169,6 @@ int PalfDiskOptionsWrapper::update_disk_options_not_guarded_by_lock_(const PalfD disk_opts_for_stopping_writing_.log_disk_throttling_percentage_ = new_trigger_percentage; disk_opts_for_recycling_blocks_.log_disk_throttling_maximum_duration_ = new_maximum_duration; disk_opts_for_stopping_writing_.log_disk_throttling_maximum_duration_ = new_maximum_duration; - sequence_++; } return ret; @@ -404,7 +403,7 @@ int PalfEnvImpl::create_palf_handle_impl_(const int64_t palf_id, PALF_LOG(WARN, "palf_handle has exist, ignore this request", K(ret), K(palf_id)); } else if (false == check_can_create_palf_handle_impl_()) { ret = OB_LOG_OUTOF_DISK_SPACE; - PALF_LOG(ERROR, "PalfEnv can not hold more instance", K(ret), KPC(this), K(palf_id)); + PALF_LOG(WARN, "PalfEnv can not hold more instance", K(ret), KPC(this), K(palf_id)); } else if (0 > (pret = snprintf(base_dir, MAX_PATH_SIZE, "%s/%ld", log_dir_, palf_id))) { ret = OB_ERR_UNEXPECTED; PALF_LOG(ERROR, "snprinf failed", K(pret), K(palf_id)); @@ -709,6 +708,11 @@ int PalfEnvImpl::try_recycle_blocks() const bool curr_diskspace_enough = usable_disk_limit_size_to_stop_writing > total_used_size_byte ? true : false; constexpr int64_t MB = 1024 * 1024LL; + const int64_t print_error_log_disk_size = + disk_opts_for_stopping_writing.log_disk_usage_limit_size_ + * disk_opts_for_stopping_writing.log_disk_utilization_threshold_; + const bool need_print_error_log = + print_error_log_disk_size > total_used_size_byte ? false : true; // step1. change SHRINKING_STATUS to normal // 1. when there is no possibility to stop writing, @@ -736,23 +740,27 @@ int PalfEnvImpl::try_recycle_blocks() if (diskspace_enough_ != curr_diskspace_enough) { ATOMIC_STORE(&diskspace_enough_, curr_diskspace_enough); } - if ((true == need_recycle && false == has_recycled && false == is_shrinking) || false == diskspace_enough_) { + + // NB: print error log when: + // 1. write-stop. + // 2. the used log disk space exceeded the log disk recycle threshold(stop-write PalfDiskOptions) and there is no recycable block. + if ((false == diskspace_enough_) || (true == need_print_error_log && false == has_recycled)) { constexpr int64_t INTERVAL = 1*1000*1000; if (palf_reach_time_interval(INTERVAL, disk_not_enough_print_interval_)) { - int tmp_ret = OB_LOG_OUTOF_DISK_SPACE; - LOG_DBA_ERROR(OB_LOG_OUTOF_DISK_SPACE, "msg", "log disk space is almost full", "ret", tmp_ret, - "total_size(MB)", disk_opts_for_recycling_blocks.log_disk_usage_limit_size_/MB, - "used_size(MB)", total_used_size_byte/MB, - "used_percent(%)", (total_used_size_byte* 100) / (disk_opts_for_stopping_writing.log_disk_usage_limit_size_ + 1), - "warn_size(MB)", (total_size_to_recycle_blocks*disk_opts_for_recycling_blocks.log_disk_utilization_threshold_)/100/MB, - "warn_percent(%)", disk_opts_for_recycling_blocks.log_disk_utilization_threshold_, - "limit_size(MB)", (total_size_to_recycle_blocks*disk_opts_for_recycling_blocks.log_disk_utilization_limit_threshold_)/100/MB, - "limit_percent(%)", disk_opts_for_recycling_blocks.log_disk_utilization_limit_threshold_, - "total_unrecyclable_size_byte(MB)", total_unrecyclable_size_byte/MB, - "maximum_used_size(MB)", maximum_used_size/MB, - "maximum_log_stream", palf_id, - "oldest_log_stream", oldest_palf_id, - "oldest_scn", oldest_scn); + int tmp_ret = OB_LOG_OUTOF_DISK_SPACE; + LOG_DBA_ERROR(OB_LOG_OUTOF_DISK_SPACE, "msg", "log disk space is almost full", "ret", tmp_ret, + "total_size(MB)", disk_opts_for_recycling_blocks.log_disk_usage_limit_size_/MB, + "used_size(MB)", total_used_size_byte/MB, + "used_percent(%)", (total_used_size_byte* 100) / (disk_opts_for_stopping_writing.log_disk_usage_limit_size_ + 1), + "warn_size(MB)", (total_size_to_recycle_blocks*disk_opts_for_recycling_blocks.log_disk_utilization_threshold_)/100/MB, + "warn_percent(%)", disk_opts_for_recycling_blocks.log_disk_utilization_threshold_, + "limit_size(MB)", (total_size_to_recycle_blocks*disk_opts_for_recycling_blocks.log_disk_utilization_limit_threshold_)/100/MB, + "limit_percent(%)", disk_opts_for_recycling_blocks.log_disk_utilization_limit_threshold_, + "total_unrecyclable_size_byte(MB)", total_unrecyclable_size_byte/MB, + "maximum_used_size(MB)", maximum_used_size/MB, + "maximum_log_stream", palf_id, + "oldest_log_stream", oldest_palf_id, + "oldest_scn", oldest_scn); } } else { if (REACH_TIME_INTERVAL(2 * 1000 * 1000L)) { @@ -886,13 +894,15 @@ int PalfEnvImpl::update_options(const PalfOptions &options) } else if (false == options.is_valid()) { ret = OB_INVALID_ARGUMENT; PALF_LOG(WARN, "invalid argument", K(options)); - } else if (OB_FAIL(disk_options_wrapper_.update_disk_options(options.disk_options_))) { - PALF_LOG(WARN, "update_disk_options failed", K(ret), K(options)); } else if (OB_FAIL(log_rpc_.update_transport_compress_options(options.compress_options_))) { PALF_LOG(WARN, "update_transport_compress_options failed", K(ret), K(options)); + } else if (FALSE_IT(rebuild_replica_log_lag_threshold_ = options.rebuild_replica_log_lag_threshold_)) { + } else if (OB_FAIL(check_can_update_log_disk_options_(options.disk_options_))) { + PALF_LOG(WARN, "check_can_update_log_disk_options_ failed", K(options)); + } else if (OB_FAIL(disk_options_wrapper_.update_disk_options(options.disk_options_))) { + PALF_LOG(WARN, "update_disk_options failed", K(ret), K(options)); } else { - rebuild_replica_log_lag_threshold_ = options.rebuild_replica_log_lag_threshold_; - PALF_LOG(INFO, "update_palf_options success", K(options)); + PALF_LOG(INFO, "update_options successs", K(options), KPC(this)); } return ret; } @@ -1315,5 +1325,18 @@ int PalfEnvImpl::init_log_io_worker_config_(const int log_writer_parallelism, return ret; } +int PalfEnvImpl::check_can_update_log_disk_options_(const PalfDiskOptions &disk_opts) +{ + int ret = OB_SUCCESS; + const int64_t curr_palf_instance_num = palf_handle_impl_map_.count(); + const int64_t curr_min_log_disk_size = curr_palf_instance_num * MIN_DISK_SIZE_PER_PALF_INSTANCE; + if (disk_opts.log_disk_usage_limit_size_ < curr_min_log_disk_size) { + ret = OB_NOT_SUPPORTED; + PALF_LOG(WARN, "can not hold current palf instance", K(curr_palf_instance_num), + K(curr_min_log_disk_size), K(disk_opts)); + } + return ret; +} + } // end namespace palf } // end namespace oceanbase diff --git a/src/logservice/palf/palf_env_impl.h b/src/logservice/palf/palf_env_impl.h index 90f5922285..ed4466b06f 100644 --- a/src/logservice/palf/palf_env_impl.h +++ b/src/logservice/palf/palf_env_impl.h @@ -346,6 +346,8 @@ private: const int64_t tenant_id, LogIOWorkerConfig &config); + int check_can_update_log_disk_options_(const PalfDiskOptions &disk_options); + private: typedef common::RWLock RWLock; typedef RWLock::RLockGuard RLockGuard; diff --git a/src/observer/ob_server_utils.cpp b/src/observer/ob_server_utils.cpp index a1c2104030..e8d2d9dab8 100644 --- a/src/observer/ob_server_utils.cpp +++ b/src/observer/ob_server_utils.cpp @@ -51,158 +51,102 @@ int ObServerUtils::get_server_ip(ObIAllocator *allocator, ObString &ipstr) int ObServerUtils::get_log_disk_info_in_config(int64_t& log_disk_size, int64_t& log_disk_percentage) { - int64_t data_disk_size = 0; - int64_t data_disk_percentage = 0; - - return observer::ObServerUtils::cal_all_part_disk_size(GCONF.datafile_size, - GCONF.log_disk_size, - GCONF.datafile_disk_percentage, - GCONF.log_disk_percentage, - data_disk_size, - log_disk_size, - data_disk_percentage, - log_disk_percentage); + int ret = OB_SUCCESS; + int64_t suggested_data_disk_size = GCONF.datafile_size; + int64_t suggested_data_disk_percentage = GCONF.datafile_disk_percentage; + int64_t suggested_clog_disk_size = GCONF.log_disk_size; + int64_t suggested_clog_disk_percentage = GCONF.log_disk_percentage; + int64_t data_default_disk_percentage = 0; + int64_t clog_default_disk_percentage = 0; + int64_t data_disk_total_size = 0; + int64_t clog_disk_total_size = 0; + bool shared_mode = false; + const char* data_dir = OB_FILE_SYSTEM_ROUTER.get_sstable_dir(); + const char* clog_dir = OB_FILE_SYSTEM_ROUTER.get_clog_dir(); + if (OB_FAIL(cal_all_part_disk_default_percentage(data_disk_total_size, + data_default_disk_percentage, + clog_disk_total_size, + clog_default_disk_percentage, + shared_mode))) { + LOG_ERROR("cal all part disk default percentage failed", + KR(ret), K(data_dir), K(suggested_data_disk_size), K(suggested_data_disk_percentage), + K(data_default_disk_percentage), K(shared_mode)); + } else if (OB_FAIL(decide_disk_size(clog_disk_total_size, + suggested_clog_disk_size, + suggested_clog_disk_percentage, + clog_default_disk_percentage, + log_disk_size, + log_disk_percentage))) { + LOG_ERROR("decide disk size failed", + KR(ret), K(data_dir), K(suggested_data_disk_size), K(suggested_data_disk_percentage), + K(data_default_disk_percentage), K(shared_mode)); + } else { + LOG_INFO("get_log_disk_info_in_config", K(suggested_data_disk_size), K(suggested_clog_disk_size), + K(suggested_data_disk_percentage), K(suggested_clog_disk_percentage), K(log_disk_size), + K(log_disk_percentage)); + } + return ret; } int ObServerUtils::get_data_disk_info_in_config(int64_t& data_disk_size, int64_t& data_disk_percentage) { - int64_t log_disk_size = 0; - int64_t log_disk_percentage = 0; - - return observer::ObServerUtils::cal_all_part_disk_size(GCONF.datafile_size, - GCONF.log_disk_size, - GCONF.datafile_disk_percentage, - GCONF.log_disk_percentage, - data_disk_size, - log_disk_size, - data_disk_percentage, - log_disk_percentage); + int ret = OB_SUCCESS; + int64_t suggested_data_disk_size = GCONF.datafile_size; + int64_t suggested_data_disk_percentage = GCONF.datafile_disk_percentage; + int64_t suggested_clog_disk_size = GCONF.log_disk_size; + int64_t suggested_clog_disk_percentage = GCONF.log_disk_percentage; + int64_t data_default_disk_percentage = 0; + int64_t clog_default_disk_percentage = 0; + int64_t data_disk_total_size = 0; + int64_t clog_disk_total_size = 0; + bool shared_mode = false; + const char* data_dir = OB_FILE_SYSTEM_ROUTER.get_sstable_dir(); + const char* clog_dir = OB_FILE_SYSTEM_ROUTER.get_clog_dir(); + if (OB_FAIL(cal_all_part_disk_default_percentage(data_disk_total_size, + data_default_disk_percentage, + clog_disk_total_size, + clog_default_disk_percentage, + shared_mode))) { + LOG_ERROR("cal all part disk default percentage failed", + KR(ret), K(data_dir), K(suggested_data_disk_size), K(suggested_data_disk_percentage), + K(data_default_disk_percentage), K(shared_mode)); + } else if (OB_FAIL(decide_disk_size(data_disk_total_size, + suggested_data_disk_size, + suggested_data_disk_percentage, + data_default_disk_percentage, + data_disk_size, + data_disk_percentage))) { + LOG_ERROR("decide data disk size failed", + KR(ret), K(data_dir), K(suggested_data_disk_size), K(suggested_data_disk_percentage), + K(data_default_disk_percentage), K(shared_mode)); + } else { + LOG_INFO("get_data_disk_info_in_config", K(suggested_data_disk_size), K(suggested_clog_disk_size), + K(suggested_data_disk_percentage), K(suggested_clog_disk_percentage), K(data_disk_size), + K(data_disk_percentage)); + } + return ret; } int ObServerUtils::cal_all_part_disk_size(const int64_t suggested_data_disk_size, - const int64_t suggested_log_disk_size, + const int64_t suggested_clog_disk_size, const int64_t suggested_data_disk_percentage, - const int64_t suggested_log_disk_percentage, + const int64_t suggested_clog_disk_percentage, int64_t& data_disk_size, int64_t& log_disk_size, int64_t& data_disk_percentage, int64_t& log_disk_percentage) { int ret = OB_SUCCESS; - -// background information about default disk percentage: -// If not in shared mode, disk will be used up to 90%. -// If in shared mode, data and clog disk usage will be up to 60% and 30% - const int64_t DEFAULT_DISK_PERCENTAGE_IN_SEPRATE_MODE = 90; - const int64_t DEFAULT_DATA_DISK_PERCENTAGE_IN_SHARED_MODE = 60; - const int64_t DEFAULT_CLOG_DISK_PERCENTAGE_IN_SHARED_MODE = 30; - - // We use sstable_dir as the data disk directory to identify whether the log and data are located - // on the same file system, and the storage module will ensure that sstable_dir and slog_dir are - // located on the same file system; - const char* data_dir = OB_FILE_SYSTEM_ROUTER.get_sstable_dir(); - const char* clog_dir = OB_FILE_SYSTEM_ROUTER.get_clog_dir(); - - struct statvfs data_statvfs; - struct statvfs clog_statvfs; - if (OB_SUCC(ret)) { - if (OB_UNLIKELY(0 != statvfs(data_dir, &data_statvfs))) { - LOG_ERROR("Failed to get data disk space ", KR(ret), K(data_dir), K(errno)); - ret = OB_ERR_UNEXPECTED; - } else if (OB_UNLIKELY(0 != statvfs(clog_dir, &clog_statvfs))) { - LOG_ERROR("Failed to get clog disk space ", KR(ret), K(clog_dir), K(errno)); - ret = OB_ERR_UNEXPECTED; - } - } - - bool shared_mode = true; - int64_t data_default_disk_percentage = 0; - int64_t clog_default_disk_percentage = 0; - - if (OB_SUCC(ret)) { - if (data_statvfs.f_fsid == clog_statvfs.f_fsid) { - shared_mode = true; - data_default_disk_percentage = DEFAULT_DATA_DISK_PERCENTAGE_IN_SHARED_MODE; - clog_default_disk_percentage = DEFAULT_CLOG_DISK_PERCENTAGE_IN_SHARED_MODE; - } else { - shared_mode = false; - data_default_disk_percentage = DEFAULT_DISK_PERCENTAGE_IN_SEPRATE_MODE; - clog_default_disk_percentage = DEFAULT_DISK_PERCENTAGE_IN_SEPRATE_MODE; - } - if (OB_FAIL(decide_disk_size(data_statvfs, - suggested_data_disk_size, - suggested_data_disk_percentage, - data_default_disk_percentage, - data_dir, - data_disk_size, - data_disk_percentage))) { - LOG_ERROR("decide data disk size failed", - KR(ret), K(data_dir), K(suggested_data_disk_size), K(suggested_data_disk_percentage), - K(data_default_disk_percentage), K(shared_mode)); - } else if (OB_FAIL(decide_disk_size(clog_statvfs, - suggested_log_disk_size, - suggested_log_disk_percentage, - clog_default_disk_percentage, - clog_dir, - log_disk_size, - log_disk_percentage))) { - LOG_ERROR("decide clog disk size failed", - KR(ret), K(clog_dir), K(suggested_data_disk_size), K(suggested_data_disk_percentage), - K(clog_default_disk_percentage), K(shared_mode)); - } - } - - if (OB_FAIL(ret)) { - LOG_ERROR("decide_all_disk_size failed", - KR(ret), K(data_dir), K(clog_dir), - K(suggested_data_disk_size), K(suggested_data_disk_percentage), - K(data_default_disk_percentage), K(clog_default_disk_percentage), - K(shared_mode), K(data_disk_size), K(log_disk_size)); + if (OB_FAIL(get_data_disk_info_in_config(data_disk_size, data_disk_percentage))) { + LOG_ERROR("get_data_disk_info_in_config failed", K(data_disk_size), K(data_disk_percentage)); + } else if (OB_FAIL(get_log_disk_info_in_config(log_disk_size, log_disk_percentage))) { + LOG_ERROR("get_log_disk_info_in_config failed", K(log_disk_size), K(log_disk_percentage)); } else { - LOG_INFO("decide_all_disk_size succ", - K(data_dir), K(clog_dir), - K(suggested_data_disk_size), K(suggested_data_disk_percentage), - K(data_default_disk_percentage), K(clog_default_disk_percentage), - K(shared_mode), K(data_disk_size), K(log_disk_size)); + LOG_INFO("cal_all_part_disk_size success", K(suggested_data_disk_size), K(suggested_clog_disk_size), + K(suggested_data_disk_percentage), K(suggested_clog_disk_percentage), K(data_disk_size), + K(log_disk_size), K(data_disk_percentage), K(log_disk_percentage)); } - - return ret; -} - -int ObServerUtils::decide_disk_size(const struct statvfs& svfs, - const int64_t suggested_disk_size, - const int64_t suggested_disk_percentage, - const int64_t default_disk_percentage, - const char* dir, - int64_t& disk_size, - int64_t& disk_percentage) -{ - int ret = OB_SUCCESS; - - int64_t total_space = (svfs.f_blocks + svfs.f_bavail - svfs.f_bfree) * svfs.f_bsize; - int64_t free_space = svfs.f_bavail * svfs.f_bsize; - - if (suggested_disk_size <= 0) { - int64_t disk_percentage = 0; - if (suggested_disk_percentage <= 0) { - disk_percentage = default_disk_percentage; - } else { - disk_percentage = suggested_disk_percentage; - } - disk_size = total_space * disk_percentage / 100; - } else { - disk_size = suggested_disk_size; - } - - if (disk_size > total_space) { - ret = OB_SERVER_OUTOF_DISK_SPACE; - } - LOG_INFO("decide disk size finished", - K(dir), - K(suggested_disk_size), K(suggested_disk_percentage), - K(default_disk_percentage), - K(total_space), K(free_space), K(disk_size)); return ret; } @@ -327,6 +271,91 @@ int ObServerUtils::calc_auto_extend_size(int64_t &actual_extend_size) return ret; } +int ObServerUtils::cal_all_part_disk_default_percentage(int64_t& data_disk_total_size, + int64_t& data_disk_default_percentage, + int64_t& clog_disk_total_size, + int64_t& clog_disk_default_percentage, + bool &shared_mode) +{ + int ret = OB_SUCCESS; + +// background information about default disk percentage: +// If not in shared mode, disk will be used up to 90%. +// If in shared mode, data and clog disk usage will be up to 60% and 30% + const int64_t DEFAULT_DISK_PERCENTAGE_IN_SEPRATE_MODE = 90; + const int64_t DEFAULT_DATA_DISK_PERCENTAGE_IN_SHARED_MODE = 60; + const int64_t DEFAULT_CLOG_DISK_PERCENTAGE_IN_SHARED_MODE = 30; + + // We use sstable_dir as the data disk directory to identify whether the log and data are located + // on the same file system, and the storage module will ensure that sstable_dir and slog_dir are + // located on the same file system; + const char* data_dir = OB_FILE_SYSTEM_ROUTER.get_sstable_dir(); + const char* clog_dir = OB_FILE_SYSTEM_ROUTER.get_clog_dir(); + + struct statvfs data_statvfs; + struct statvfs clog_statvfs; + if (OB_SUCC(ret)) { + if (OB_UNLIKELY(0 != statvfs(data_dir, &data_statvfs))) { + LOG_ERROR("Failed to get data disk space ", KR(ret), K(data_dir), K(errno)); + ret = OB_ERR_UNEXPECTED; + } else if (OB_UNLIKELY(0 != statvfs(clog_dir, &clog_statvfs))) { + LOG_ERROR("Failed to get clog disk space ", KR(ret), K(clog_dir), K(errno)); + ret = OB_ERR_UNEXPECTED; + } + } + + if (OB_SUCC(ret)) { + if (data_statvfs.f_fsid == clog_statvfs.f_fsid) { + shared_mode = true; + data_disk_default_percentage = DEFAULT_DATA_DISK_PERCENTAGE_IN_SHARED_MODE; + clog_disk_default_percentage = DEFAULT_CLOG_DISK_PERCENTAGE_IN_SHARED_MODE; + } else { + shared_mode = false; + data_disk_default_percentage = DEFAULT_DISK_PERCENTAGE_IN_SEPRATE_MODE; + clog_disk_default_percentage = DEFAULT_DISK_PERCENTAGE_IN_SEPRATE_MODE; + } + data_disk_total_size = (data_statvfs.f_blocks + data_statvfs.f_bavail - data_statvfs.f_bfree) * data_statvfs.f_bsize; + clog_disk_total_size = (clog_statvfs.f_blocks + clog_statvfs.f_bavail - clog_statvfs.f_bfree) * clog_statvfs.f_bsize; + LOG_INFO("cal_all_part_disk_default_percentage succ", + K(data_dir), K(clog_dir), + K(shared_mode), K(data_disk_total_size), K(data_disk_default_percentage), + K(clog_disk_total_size), K(clog_disk_default_percentage)); + } + + return ret; +} + +int ObServerUtils::decide_disk_size(const int64_t total_space, + const int64_t suggested_disk_size, + const int64_t suggested_disk_percentage, + const int64_t default_disk_percentage, + int64_t& disk_size, + int64_t& disk_percentage) +{ + int ret = OB_SUCCESS; + + if (suggested_disk_size <= 0) { + int64_t disk_percentage = 0; + if (suggested_disk_percentage <= 0) { + disk_percentage = default_disk_percentage; + } else { + disk_percentage = suggested_disk_percentage; + } + disk_size = total_space * disk_percentage / 100; + } else { + disk_size = suggested_disk_size; + } + + if (disk_size > total_space) { + ret = OB_SERVER_OUTOF_DISK_SPACE; + } + LOG_INFO("decide disk size finished", + K(suggested_disk_size), K(suggested_disk_percentage), + K(default_disk_percentage), + K(total_space), K(disk_size)); + return ret; +} + } // namespace observer } // namespace oceanbase diff --git a/src/observer/ob_server_utils.h b/src/observer/ob_server_utils.h index e911058090..05a66b4f2f 100644 --- a/src/observer/ob_server_utils.h +++ b/src/observer/ob_server_utils.h @@ -71,6 +71,17 @@ private: const char* dir, int64_t& disk_size, int64_t& disk_percentage); + static int decide_disk_size(const int64_t disk_total_size, + const int64_t suggested_disk_size, + const int64_t suggested_disk_percentage, + const int64_t default_disk_percentage, + int64_t& disk_size, + int64_t& disk_percentage); + static int cal_all_part_disk_default_percentage(int64_t &data_disk_total_size, + int64_t& data_disk_percentage, + int64_t &log_disk_total_size, + int64_t& log_disk_percentage, + bool &shared_mode); DISALLOW_COPY_AND_ASSIGN(ObServerUtils); }; } // namespace observer diff --git a/src/observer/omt/ob_multi_tenant.cpp b/src/observer/omt/ob_multi_tenant.cpp index 076fefda8b..397571e09b 100644 --- a/src/observer/omt/ob_multi_tenant.cpp +++ b/src/observer/omt/ob_multi_tenant.cpp @@ -1019,8 +1019,8 @@ int ObMultiTenant::update_tenant_unit_no_lock(const ObUnitInfoGetter::ObTenantCo } else if (OB_FAIL(update_tenant_memory(tenant_id, unit.config_.memory_size(), allowed_mem_limit))) { LOG_WARN("fail to update tenant memory", K(ret), K(tenant_id)); } else if (OB_FAIL(update_tenant_log_disk_size(tenant_id, - unit.config_.log_disk_size(), old_unit.config_.log_disk_size(), + unit.config_.log_disk_size(), allowed_new_log_disk_size))) { LOG_WARN("fail to update tenant log disk size", K(ret), K(tenant_id)); } else if (OB_FAIL(construct_allowed_unit_config(allowed_new_log_disk_size, @@ -1154,104 +1154,23 @@ int ObMultiTenant::update_tenant_memory(const uint64_t tenant_id, const int64_t } int ObMultiTenant::update_tenant_log_disk_size(const uint64_t tenant_id, - const int64_t expected_log_disk_size, const int64_t old_log_disk_size, + const int64_t new_log_disk_size, int64_t &allowed_new_log_disk_size) { int ret = OB_SUCCESS; - int64_t used_log_disk_size = 0, palf_log_disk_size = 0; - bool can_update_log_disk_size_with_expected_log_disk = false; - // 'expected_log_disk_size' is the latest log disk size record in __all_unit_config. - // 'old_log_disk_size' is current log disk size in ObTenant. - // 'allowed_new_log_disk_size' is current allowed log disk size when update log disk. - // - // To avoid overselling, we can not use 'expected_log_disk_size' to update unit config which will save in slog. - // therefore, we need constuct a virtual log disk size which named with 'allowed_new_log_disk_size'. MAKE_TENANT_SWITCH_SCOPE_GUARD(guard); if (OB_SUCC(guard.switch_to(tenant_id))) { ObLogService *log_service = MTL(ObLogService *); if (OB_ISNULL(log_service)) { ret = OB_ERR_UNEXPECTED; - } else if (OB_FAIL(log_service->get_palf_stable_disk_usage(used_log_disk_size, palf_log_disk_size))) { - LOG_WARN("fail to get_palf_stable_disk_usage", K(tenant_id), K(old_log_disk_size), K(expected_log_disk_size)); - // The standard for determing whether it's in shrinking or expanding status: - // 1. If 'palf_log_disk_size' is smaller than or equal to 'expected_log_disk_size', it's in expanding status. - // 2. If 'palf_log_disk_size' is greater than 'expected_log_disk_size', it's in shrinking status. - // - // For shrinking log disk, we don't update ObTenantConfig of ObTenant to new ObTenantConfig until shrinking successfully. - // - // NB: All fields of new ObTenantConfig except log_disk_size has been updated in case of shrinking log disk. - // - // For example: - // 1. before shrinkg log disk successfully, and then expand log disk. - // - At T1 timestamp, the original log disk is 100G, and update it to 50G, we will construct 'new_unit' with - // 100G, but update palf with 50G because original log disk size is greater than new log disk size. - // - At T2 timestamp, the log disk size in current ObTenantConfig is 100G, and we update it to 80G, there are - // two scenarios: - // 1. if 'palf_log_disk_size' which get from palf is 100G, we think palf is still in shrinking status. and we will - // construct 'new_unit' with 100G because 'palf_log_disk_size' is greater than new log disk size(80G). but udpate - // palf with 80G - // 2. if 'palf_log_disk_size' which get from palf is 50G, we think palf has been in normal status. and we will - // construct 'new_unit' with 80G because 'palf_log_disk_size' is smaller than new log disk size(80G), but udpate - // palf with 80G. - } else if (FALSE_IT(can_update_log_disk_size_with_expected_log_disk = (expected_log_disk_size >= palf_log_disk_size))) { - // For expanding log disk, we can update 'allowed_new_log_disk_size' to 'expected_log_disk_size' directlly. - } else if (can_update_log_disk_size_with_expected_log_disk && FALSE_IT(allowed_new_log_disk_size = expected_log_disk_size)) { - // For shrinking log disk, we still update log disk size of 'new_unit' to 'old_log_disk_size'. - } else if (!can_update_log_disk_size_with_expected_log_disk && FALSE_IT(allowed_new_log_disk_size = old_log_disk_size)) { - // case 1: for shrinking log disk, shrinking log disk from 100G to 50G. - // - At T1 timestamp, 'expected_log_disk_size' is 50G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 100G. - // the log disk size record in slog is 100G, and we will update log disk size used for palf to 50G, but not update log - // disk which has assigned in ObServerLogBlockMGR. - // - At T2 timestamp, 'expected_log_disk_size' is still 50G, 'old_log_disk_size' is still 100G, however, 'allowed_new_log_disk_size' - // is 50G because of shrinking log disk has been successfully, the log disk record in slog is 50G, and then we will update log disk - // size used for palf to 50G again but has no effect, log disk assigned in ObServerLogBlockMGR update to 50G(assume there is only one tenant). - // - // case 2: for expanding log disk, expanding log disk from 100G to 150G. - // - At T1 timestamp, 'expected_log_disk_size' is 150G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 150G. - // the log disk size record in slog is 150G, and then, we will update log disk size used for palf to 150G, the log disk - // which has assigned in ObServerLogBlockMGR updaet to 150G(assume there is only one tenant). - // - // case 3: for shrinking log disk, shrinking log disk from 100G to 50G, and then shrinking log disk from 50G to 25G. - // - At T1 timestamp, 'expected_log_disk_size' is 50G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 100G. - // the log disk size record in slog is 100G, and we will update log disk size used for palf to 50G, but not update log - // disk which has assigned in ObServerLogBlockMGR. - // - At T2 timestamp, 'expected_log_disk_size' is 25G, 'old_log_disk_size' is still 100G, however, there are two possibility value for - // 'allowed_new_log_disk_size': - // 1. the value is 100G because of last shrinking log disk has not been successfully, the log disk record in slog is still 100G - // and then we will update log disk size used for palf to 25G, but not update log disk assigned in ObServerLogBlockMGR. - // At T3 timestamp, 'expected_log_disk_size' is 25G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 25G, - // the log disk record in slog is 25G, the log disk assigned in ObServerLogBlockMGR is 25G. - // 2. the value is 50G because of last shrinking log disk has been successfully, the log disk record in slog is 50G - // and then we will update log disk size used for palf to 25G, update log disk assigned in ObServerLogBlockMGR to 50G(assume there is only one tenant). - // At T3 timestamp, 'expected_log_disk_size' is 25G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 25G, - // the log disk record in slog is 25G, the log disk assigned in ObServerLogBlockMGR is 25G. - // - // case 4: for shrinking log disk, shrinking log disk from 100G to 50G, and then expanding log disk from 50G to 80G. - // - At T1 timestamp, 'expected_log_disk_size' is 50G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 100G. - // the log disk size record in slog is 100G, and we will update log disk size used for palf to 50G, but not update log - // disk which has assigned in ObServerLogBlockMGR. - // - At T2 timestamp, 'expected_log_disk_size' is 80G, 'old_log_disk_size' is still 100G, however, there are two possibility value for - // 'allowed_new_log_disk_size': - // 1. the value is 100G because of last shrinking log disk has not been successfully, the log disk record in slog is still 100G - // and then we will update log disk size used for palf to 80G, but not update log disk assigned in ObServerLogBlockMGR. - // At T3 timestamp, 'expected_log_disk_size' is 80G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 80G, - // the log disk record in slog is 80G, the log disk assigned in ObServerLogBlockMGR is 80G. - // 2. the value is 80G because of last shrinking log disk has been successfully, the log disk record in slog is 80G - // and then we will update log disk size used for palf to 80G, update log disk assigned in ObServerLogBlockMGR to 80G(assume there is only one tenant). - // At T3 timestamp, 'expected_log_disk_size' is 25G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 25G, - // the log disk record in slog is 25G, the log disk assigned in ObServerLogBlockMGR is 25G. - // - } else if (OB_FAIL(GCTX.log_block_mgr_->update_tenant(old_log_disk_size, allowed_new_log_disk_size))) { - LOG_WARN("failed to update teannt int ObServerLogBlockMGR", K(ret), K(tenant_id), K(expected_log_disk_size), - K(old_log_disk_size), K(allowed_new_log_disk_size)); - } else if (OB_FAIL(log_service->update_log_disk_usage_limit_size(expected_log_disk_size))) { - LOG_WARN("failed to update_log_disk_usage_limit_size", K(ret), K(tenant_id), K(expected_log_disk_size), - K(old_log_disk_size), K(allowed_new_log_disk_size)); - GCTX.log_block_mgr_->abort_update_tenant(allowed_new_log_disk_size, old_log_disk_size); + } else if (OB_FAIL(GCTX.log_block_mgr_->update_tenant(old_log_disk_size, new_log_disk_size, + allowed_new_log_disk_size, log_service))) { + LOG_WARN("fail to update_tenant", K(tenant_id), K(old_log_disk_size), K(new_log_disk_size), + K(allowed_new_log_disk_size)); } else { - LOG_INFO("update_log_disk_usage_limit_size success", K(ret), K(tenant_id), K(expected_log_disk_size), - K(old_log_disk_size), K(allowed_new_log_disk_size)); + LOG_INFO("update_tenant_log_disk_size success", K(tenant_id), K(old_log_disk_size), + K(new_log_disk_size), K(allowed_new_log_disk_size)); } } return ret; diff --git a/src/observer/omt/ob_multi_tenant.h b/src/observer/omt/ob_multi_tenant.h index dfe0ca8b1f..6120e14c44 100644 --- a/src/observer/omt/ob_multi_tenant.h +++ b/src/observer/omt/ob_multi_tenant.h @@ -112,8 +112,8 @@ public: int update_tenant_memory(const uint64_t tenant_id, const int64_t mem_limit, int64_t &allowed_mem_limit); int update_tenant_memory(const share::ObUnitInfoGetter::ObTenantConfig &unit); int update_tenant_log_disk_size(const uint64_t tenant_id, - const int64_t expected_log_disk_size, const int64_t old_log_disk_size, + const int64_t new_log_disk_size, int64_t &allowed_log_disk_size); int modify_tenant_io(const uint64_t tenant_id, const share::ObUnitConfig &unit_config); int update_tenant_config(uint64_t tenant_id); diff --git a/src/observer/virtual_table/ob_all_virtual_unit.cpp b/src/observer/virtual_table/ob_all_virtual_unit.cpp index af912ad17a..eb88ff793e 100644 --- a/src/observer/virtual_table/ob_all_virtual_unit.cpp +++ b/src/observer/virtual_table/ob_all_virtual_unit.cpp @@ -16,12 +16,14 @@ #include "observer/omt/ob_multi_tenant.h" #include "observer/omt/ob_tenant.h" #include "share/ob_unit_getter.h" +#include "logservice/ob_log_service.h" using namespace oceanbase; using namespace oceanbase::common; using namespace oceanbase::storage; using namespace oceanbase::observer; using namespace oceanbase::omt; +using namespace logservice; ObAllVirtualUnit::ObAllVirtualUnit() : ObVirtualTableScannerIterator(), @@ -244,9 +246,9 @@ int ObAllVirtualUnit::inner_get_next_row(ObNewRow *&row) break; case LOG_DISK_IN_USE: { int64_t clog_disk_in_use = 0; - if (OB_FAIL(static_cast(GCTX.disk_reporter_) - ->get_clog_disk_used_size(tenant_meta.unit_.tenant_id_, clog_disk_in_use))) { - SERVER_LOG(WARN, "fail to get data disk in use", K(ret), K(tenant_meta)); + const uint64_t tenant_id = tenant_meta.unit_.tenant_id_; + if (OB_FAIL(get_clog_disk_used_size_(tenant_id, clog_disk_in_use))) { + SERVER_LOG(WARN, "fail to get clog disk in use", K(ret), K(tenant_meta)); } else { cur_row_.cells_[i].set_int(clog_disk_in_use); } @@ -284,5 +286,25 @@ int ObAllVirtualUnit::inner_get_next_row(ObNewRow *&row) return ret; } +int ObAllVirtualUnit::get_clog_disk_used_size_(const uint64_t tenant_id, + int64_t &log_used_size) +{ + int ret = OB_SUCCESS; + log_used_size = 0; + MAKE_TENANT_SWITCH_SCOPE_GUARD(guard); + if (OB_SUCC(guard.switch_to(tenant_id))) { + ObLogService *log_service = MTL(ObLogService*); + int64_t unused_log_disk_total_size = 0; + if (OB_ISNULL(log_service)) { + ret = OB_ERR_UNEXPECTED; + SERVER_LOG(WARN, "ObLogService is nullptr", KP(log_service), K(tenant_id)); + } else if (OB_FAIL(log_service->get_palf_stable_disk_usage(log_used_size, + unused_log_disk_total_size))) { + SERVER_LOG(WARN, "get_palf_stable_disk_usage failed", KP(log_service), K(tenant_id)); + } + } + // return OB_SUCCESS whatever. + return OB_SUCCESS; +} diff --git a/src/observer/virtual_table/ob_all_virtual_unit.h b/src/observer/virtual_table/ob_all_virtual_unit.h index e772d32a8a..0e2d6b589f 100644 --- a/src/observer/virtual_table/ob_all_virtual_unit.h +++ b/src/observer/virtual_table/ob_all_virtual_unit.h @@ -53,7 +53,8 @@ public: virtual int inner_open(); virtual void reset(); virtual int inner_get_next_row(common::ObNewRow *&row); - +private: + int get_clog_disk_used_size_(const uint64_t tenant_id, int64_t &log_used_size); private: char ip_buf_[common::OB_IP_STR_BUFF]; common::ObAddr addr_; diff --git a/unittest/logservice/test_server_log_block_mgr.cpp b/unittest/logservice/test_server_log_block_mgr.cpp index ce780c3017..aafa324930 100644 --- a/unittest/logservice/test_server_log_block_mgr.cpp +++ b/unittest/logservice/test_server_log_block_mgr.cpp @@ -153,10 +153,16 @@ public: ret = OB_ENTRY_NOT_EXIST; } else { int64_t old_size = map_[key]; - ret = this->log_block_mgr_.update_tenant(old_size, new_size); + int64_t tmp_min_log_disk_size_for_all_tenants = this->log_block_mgr_.min_log_disk_size_for_all_tenants_; + tmp_min_log_disk_size_for_all_tenants -= old_size; + tmp_min_log_disk_size_for_all_tenants += new_size; + if (tmp_min_log_disk_size_for_all_tenants > this->log_block_mgr_.get_total_size_guarded_by_lock_()) { + ret = OB_MACHINE_RESOURCE_NOT_ENOUGH; + } if (OB_SUCCESS != ret) { map_[key] = old_size; } else { + this->log_block_mgr_.min_log_disk_size_for_all_tenants_ = tmp_min_log_disk_size_for_all_tenants; map_[key] = new_size; } }