322 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			322 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /**
 | |
|  * 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 "lib/ob_define.h"
 | |
| #include "lib/ob_errno.h"
 | |
| #include <cstdio>
 | |
| #include <gtest/gtest.h>
 | |
| #include <signal.h>
 | |
| #include <stdexcept>
 | |
| #define private public
 | |
| #include "env/ob_simple_log_cluster_env.h"
 | |
| #undef private
 | |
| #include "logservice/palf/log_reader_utils.h"
 | |
| #include "logservice/palf/log_define.h"
 | |
| #include "logservice/palf/log_group_entry_header.h"
 | |
| #include "logservice/palf/log_io_worker.h"
 | |
| #include "logservice/palf/lsn.h"
 | |
| 
 | |
| const std::string TEST_NAME = "single_replica";
 | |
| 
 | |
| using namespace oceanbase::common;
 | |
| using namespace oceanbase;
 | |
| namespace oceanbase
 | |
| {
 | |
| using namespace logservice;
 | |
| namespace unittest
 | |
| {
 | |
| class TestObSimpleLogClusterSingleReplica : public ObSimpleLogClusterTestEnv
 | |
| {
 | |
| public:
 | |
|   TestObSimpleLogClusterSingleReplica() : ObSimpleLogClusterTestEnv()
 | |
|   {
 | |
|     int ret = init();
 | |
|     if (OB_SUCCESS != ret) {
 | |
|       throw std::runtime_error("TestObSimpleLogClusterLogEngine init failed");
 | |
|     }
 | |
|   }
 | |
|   ~TestObSimpleLogClusterSingleReplica()
 | |
|   {
 | |
|     destroy();
 | |
|   }
 | |
|   int init()
 | |
|   {
 | |
|     return OB_SUCCESS;
 | |
|   }
 | |
|   void destroy()
 | |
|   {}
 | |
|   int64_t id_;
 | |
|   PalfHandleGuard leader_;
 | |
| };
 | |
| 
 | |
| int64_t ObSimpleLogClusterTestBase::member_cnt_ = 1;
 | |
| int64_t ObSimpleLogClusterTestBase::node_cnt_ = 1;
 | |
| std::string ObSimpleLogClusterTestBase::test_name_ = TEST_NAME;
 | |
| 
 | |
| TEST_F(TestObSimpleLogClusterSingleReplica, update_disk_options)
 | |
| {
 | |
|   SET_CASE_LOG_FILE(TEST_NAME, "update_disk_options");
 | |
|   OB_LOGGER.set_log_level("TRACE");
 | |
|   const int64_t id = ATOMIC_FAA(&palf_id_, 1);
 | |
|   PALF_LOG(INFO, "start update_disk_options", K(id));
 | |
|   int64_t leader_idx = 0;
 | |
|   PalfHandleGuard leader;
 | |
|   PalfEnv *palf_env = NULL;
 | |
|   EXPECT_EQ(OB_SUCCESS, create_paxos_group(id, leader_idx, leader));
 | |
|   EXPECT_EQ(OB_SUCCESS, get_palf_env(leader_idx, palf_env));
 | |
|   PalfDiskOptions disk_opts;
 | |
|   EXPECT_EQ(OB_SUCCESS, palf_env->get_disk_options(disk_opts));
 | |
|   EXPECT_EQ(OB_SUCCESS, submit_log(leader, 4 * 32 + 10, id, MAX_LOG_BODY_SIZE));
 | |
|   while (leader.palf_handle_.palf_handle_impl_->log_engine_.log_storage_.log_tail_
 | |
|          < LSN(4 * 32 * MAX_LOG_BODY_SIZE)) {
 | |
|     sleep(1);
 | |
|   }
 | |
|   block_id_t min_block_id, max_block_id;
 | |
|   EXPECT_EQ(OB_SUCCESS,
 | |
|             leader.palf_handle_.palf_handle_impl_->log_engine_.get_block_id_range(
 | |
|                 min_block_id, max_block_id));
 | |
|   EXPECT_EQ(4, max_block_id);
 | |
|   disk_opts.log_disk_usage_limit_size_ = 8 * PALF_PHY_BLOCK_SIZE;
 | |
|   EXPECT_EQ(OB_SUCCESS, palf_env->update_disk_options(disk_opts));
 | |
|   sleep(1);
 | |
|   disk_opts.log_disk_utilization_limit_threshold_ = 50;
 | |
|   disk_opts.log_disk_utilization_threshold_ = 40;
 | |
|   EXPECT_EQ(OB_SUCCESS, palf_env->update_disk_options(disk_opts));
 | |
| 
 | |
|   disk_opts.log_disk_usage_limit_size_ = 4 * PALF_PHY_BLOCK_SIZE;
 | |
|   EXPECT_EQ(OB_STATE_NOT_MATCH, palf_env->update_disk_options(disk_opts));
 | |
| 
 | |
|   palf_env->palf_env_impl_.disk_options_wrapper_.disk_opts_for_recycling_blocks_ = palf_env->palf_env_impl_.disk_options_wrapper_.disk_opts_for_stopping_writing_;
 | |
|   palf_env->palf_env_impl_.disk_options_wrapper_.status_ = PalfDiskOptionsWrapper::Status::NORMAL_STATUS;
 | |
| 
 | |
|   disk_opts.log_disk_utilization_limit_threshold_ = 95;
 | |
|   disk_opts.log_disk_utilization_threshold_ = 80;
 | |
|   EXPECT_EQ(OB_SUCCESS, palf_env->update_disk_options(disk_opts));
 | |
|   EXPECT_EQ(OB_STATE_NOT_MATCH, palf_env->update_disk_options(disk_opts));
 | |
|   sleep(1);
 | |
|   EXPECT_EQ(PalfDiskOptionsWrapper::Status::SHRINKING_STATUS,
 | |
|             palf_env->palf_env_impl_.disk_options_wrapper_.status_);
 | |
|   EXPECT_GT(palf_env->palf_env_impl_.disk_options_wrapper_.disk_opts_for_stopping_writing_.log_disk_usage_limit_size_,
 | |
|             palf_env->palf_env_impl_.disk_options_wrapper_.disk_opts_for_recycling_blocks_.log_disk_usage_limit_size_);
 | |
|   EXPECT_EQ(OB_SUCCESS, leader.advance_base_lsn(LSN(4 * PALF_BLOCK_SIZE)));
 | |
|   EXPECT_EQ(OB_SUCCESS, leader.advance_base_lsn(LSN(2 * PALF_BLOCK_SIZE)));
 | |
|   EXPECT_EQ(LSN(4*PALF_BLOCK_SIZE), leader.palf_handle_.palf_handle_impl_->log_engine_.get_log_meta().get_log_snapshot_meta().base_lsn_);
 | |
|   while (leader.palf_handle_.palf_handle_impl_->log_engine_.base_lsn_for_block_gc_
 | |
|          != LSN(4 * PALF_BLOCK_SIZE)) {
 | |
|     sleep(1);
 | |
|   }
 | |
|   // wait blocks to be recycled
 | |
|   while (leader.palf_handle_.palf_handle_impl_->log_engine_.get_base_lsn_used_for_block_gc() != LSN(4*PALF_BLOCK_SIZE)) {
 | |
|     sleep(1);
 | |
|   }
 | |
|   sleep(1);
 | |
|   EXPECT_EQ(PalfDiskOptionsWrapper::Status::NORMAL_STATUS,
 | |
|             palf_env->palf_env_impl_.disk_options_wrapper_.status_);
 | |
|   EXPECT_EQ(
 | |
|       disk_opts,
 | |
|       palf_env->palf_env_impl_.disk_options_wrapper_.disk_opts_for_recycling_blocks_);
 | |
|   EXPECT_EQ(
 | |
|       disk_opts,
 | |
|       palf_env->palf_env_impl_.disk_options_wrapper_.disk_opts_for_stopping_writing_);
 | |
|   PALF_LOG(INFO, "runlin trace", K(disk_opts),
 | |
|            "holders:", palf_env->palf_env_impl_.disk_options_wrapper_);
 | |
|   // test expand
 | |
|   disk_opts.log_disk_usage_limit_size_ = 5 * 1024 * 1024 * 1024ul;
 | |
|   EXPECT_EQ(OB_SUCCESS, palf_env->update_disk_options(disk_opts));
 | |
|   disk_opts.log_disk_usage_limit_size_ = 6 * 1024 * 1024 * 1024ul;
 | |
|   EXPECT_EQ(OB_SUCCESS, palf_env->update_disk_options(disk_opts));
 | |
|   EXPECT_EQ(
 | |
|       disk_opts,
 | |
|       palf_env->palf_env_impl_.disk_options_wrapper_.disk_opts_for_recycling_blocks_);
 | |
|   EXPECT_EQ(
 | |
|       disk_opts,
 | |
|       palf_env->palf_env_impl_.disk_options_wrapper_.disk_opts_for_stopping_writing_);
 | |
| }
 | |
| 
 | |
| TEST_F(TestObSimpleLogClusterSingleReplica, delete_paxos_group)
 | |
| {
 | |
|   SET_CASE_LOG_FILE(TEST_NAME, "delete_paxos_group");
 | |
|   const int64_t id = ATOMIC_FAA(&palf_id_, 1);
 | |
|   PALF_LOG(INFO, "start test delete_paxos_group", K(id));
 | |
|   int64_t leader_idx = 0;
 | |
|   {
 | |
|     palf::PalfHandleGuard leader;
 | |
|     EXPECT_EQ(OB_SUCCESS, create_paxos_group(id, leader_idx, leader));
 | |
|     EXPECT_EQ(OB_SUCCESS, submit_log(leader, 100, leader_idx));
 | |
|   }
 | |
|   sleep(1);
 | |
|   // EXPECT_EQ(OB_SUCCESS, delete_paxos_group(id));
 | |
|   // TODO by yunlong: check log sync
 | |
|   PALF_LOG(INFO, "end test delete_paxos_group", K(id));
 | |
| }
 | |
| 
 | |
| TEST_F(TestObSimpleLogClusterSingleReplica, advance_base_lsn)
 | |
| {
 | |
|   SET_CASE_LOG_FILE(TEST_NAME, "advance_base_lsn");
 | |
|   OB_LOGGER.set_log_level("INFO");
 | |
|   const int64_t id = ATOMIC_FAA(&palf_id_, 1);
 | |
|   PALF_LOG(INFO, "start advance_base_lsn", K(id));
 | |
|   int64_t leader_idx = 0;
 | |
|   int64_t log_ts = 1;
 | |
|   {
 | |
|     PalfHandleGuard leader;
 | |
|     EXPECT_EQ(OB_SUCCESS, create_paxos_group(id, leader_idx, leader));
 | |
|     EXPECT_EQ(OB_SUCCESS, submit_log(leader, 100, id));
 | |
|     sleep(2);
 | |
|     LSN log_tail =
 | |
|         leader.palf_handle_.palf_handle_impl_->log_engine_.log_meta_storage_.log_tail_;
 | |
|     for (int64_t i = 0; i < 4096; i++) {
 | |
|       EXPECT_EQ(OB_SUCCESS, leader.palf_handle_.enable_vote());
 | |
|     }
 | |
|     sleep(3);
 | |
|     EXPECT_EQ(
 | |
|         LSN(4096 * 4096 + log_tail.val_),
 | |
|         leader.palf_handle_.palf_handle_impl_->log_engine_.log_meta_storage_.log_tail_);
 | |
|   }
 | |
|   EXPECT_EQ(OB_SUCCESS, restart_paxos_groups());
 | |
|   {
 | |
|     PalfHandleGuard leader;
 | |
|     EXPECT_EQ(OB_SUCCESS, get_leader(id, leader, leader_idx));
 | |
|     EXPECT_EQ(OB_SUCCESS, leader.palf_handle_.advance_base_lsn(LSN(0)));
 | |
|   }
 | |
| }
 | |
| 
 | |
| TEST_F(TestObSimpleLogClusterSingleReplica, test_truncate_failed)
 | |
| {
 | |
|   SET_CASE_LOG_FILE(TEST_NAME, "test_truncate_failed");
 | |
|   int64_t id = ATOMIC_AAF(&palf_id_, 1);
 | |
|   int64_t leader_idx = 0;
 | |
|   char block_path[OB_MAX_FILE_NAME_LENGTH] = {'\0'};
 | |
|   int64_t file_size = 0;
 | |
|   {
 | |
|     PalfHandleGuard leader;
 | |
|     EXPECT_EQ(OB_SUCCESS, create_paxos_group(id, leader_idx, leader));
 | |
|     EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10, id, 1000));
 | |
|     wait_lsn_until_flushed(leader.palf_handle_.palf_handle_impl_->get_max_lsn(), leader);
 | |
|     LSN max_lsn = leader.palf_handle_.palf_handle_impl_->log_engine_.log_storage_.log_tail_;
 | |
|     EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10, id, 1000));
 | |
|     wait_lsn_until_flushed(leader.palf_handle_.palf_handle_impl_->get_max_lsn(), leader);
 | |
|     int64_t fd = leader.palf_handle_.palf_handle_impl_->log_engine_.log_storage_.block_mgr_.curr_writable_handler_.io_fd_;
 | |
|     block_id_t block_id = leader.palf_handle_.palf_handle_impl_->log_engine_.log_storage_.block_mgr_.curr_writable_block_id_;
 | |
|     char *log_dir = leader.palf_handle_.palf_handle_impl_->log_engine_.log_storage_.block_mgr_.log_dir_;
 | |
|     convert_to_normal_block(log_dir, block_id, block_path, OB_MAX_FILE_NAME_LENGTH);
 | |
|     EXPECT_EQ(OB_ITER_END, read_log(leader));
 | |
|     PALF_LOG(ERROR, "truncate pos", K(max_lsn));
 | |
|     EXPECT_EQ(0, ftruncate(fd, max_lsn.val_));
 | |
|     FileDirectoryUtils::get_file_size(block_path, file_size);
 | |
|     EXPECT_EQ(file_size, max_lsn.val_);
 | |
|   }
 | |
|   PalfHandleGuard leader;
 | |
|   EXPECT_EQ(OB_SUCCESS, restart_paxos_groups());;
 | |
|   FileDirectoryUtils::get_file_size(block_path, file_size);
 | |
|   EXPECT_EQ(file_size, PALF_PHY_BLOCK_SIZE);
 | |
|   get_leader(id, leader, leader_idx);
 | |
|   EXPECT_EQ(OB_SUCCESS, submit_log(leader, 10, id, 1000));
 | |
|   EXPECT_EQ(OB_ITER_END, read_log(leader));
 | |
| }
 | |
| 
 | |
| TEST_F(TestObSimpleLogClusterSingleReplica, test_meta)
 | |
| {
 | |
|   SET_CASE_LOG_FILE(TEST_NAME, "test_meta");
 | |
|   int64_t id = ATOMIC_AAF(&palf_id_, 1);
 | |
|   int64_t leader_idx = 0;
 | |
|   LSN upper_aligned_log_tail;
 | |
|   {
 | |
|     PalfHandleGuard leader;
 | |
|     EXPECT_EQ(OB_SUCCESS, create_paxos_group(id, leader_idx, leader));
 | |
|     sleep(1);
 | |
|     // 测试meta文件刚好写满的重启场景
 | |
|     LogEngine *log_engine = &leader.palf_handle_.palf_handle_impl_->log_engine_;
 | |
|     LogStorage *log_meta_storage = &log_engine->log_meta_storage_;
 | |
|     LSN log_meta_tail = log_meta_storage->log_tail_;
 | |
|     upper_aligned_log_tail.val_ = (lsn_2_block(log_meta_tail, PALF_META_BLOCK_SIZE) + 1) * PALF_META_BLOCK_SIZE;
 | |
|     int64_t delta = upper_aligned_log_tail - log_meta_tail;
 | |
|     int64_t delta_cnt = delta / MAX_META_ENTRY_SIZE;
 | |
|     while (delta_cnt-- > 0) {
 | |
|       log_engine->append_log_meta_(log_engine->log_meta_);
 | |
|     }
 | |
|     EXPECT_EQ(upper_aligned_log_tail, log_meta_storage->log_tail_);
 | |
|     PALF_LOG(ERROR, "runlin trace before restart", K(upper_aligned_log_tail), KPC(log_meta_storage));
 | |
|   }
 | |
| 
 | |
|   EXPECT_EQ(OB_SUCCESS, restart_paxos_groups());
 | |
| 
 | |
|   {
 | |
|     PalfHandleGuard leader;
 | |
|     EXPECT_EQ(OB_SUCCESS, get_leader(id, leader, leader_idx));
 | |
|     LogEngine *log_engine = &leader.palf_handle_.palf_handle_impl_->log_engine_;
 | |
|     LogStorage *log_meta_storage = &log_engine->log_meta_storage_;
 | |
|     LSN log_meta_tail = log_meta_storage->log_tail_;
 | |
|     upper_aligned_log_tail.val_ = (lsn_2_block(log_meta_tail, PALF_META_BLOCK_SIZE) + 1) * PALF_META_BLOCK_SIZE;
 | |
|     int64_t delta = upper_aligned_log_tail - log_meta_tail;
 | |
|     int64_t delta_cnt = delta / MAX_META_ENTRY_SIZE;
 | |
|     while (delta_cnt-- > 0) {
 | |
|       log_engine->append_log_meta_(log_engine->log_meta_);
 | |
|     }
 | |
|     EXPECT_EQ(upper_aligned_log_tail, log_meta_storage->log_tail_);
 | |
|     EXPECT_EQ(OB_SUCCESS, submit_log(leader, 32, id, MAX_LOG_BODY_SIZE));
 | |
|     sleep(1);
 | |
|     wait_lsn_until_flushed(leader.palf_handle_.palf_handle_impl_->get_max_lsn(), leader);
 | |
|     block_id_t min_block_id, max_block_id;
 | |
|     EXPECT_EQ(OB_SUCCESS, log_meta_storage->get_block_id_range(min_block_id, max_block_id));
 | |
|     EXPECT_EQ(min_block_id, max_block_id);
 | |
|   }
 | |
| }
 | |
| 
 | |
| TEST_F(TestObSimpleLogClusterSingleReplica, test_gc_block)
 | |
| {
 | |
|   SET_CASE_LOG_FILE(TEST_NAME, "test_gc_block");
 | |
|   OB_LOGGER.set_log_level("TRACE");
 | |
|   int64_t id = ATOMIC_AAF(&palf_id_, 1);
 | |
|   int64_t leader_idx = 0;
 | |
|   LSN upper_aligned_log_tail;
 | |
|   PalfHandleGuard leader;
 | |
|   EXPECT_EQ(OB_SUCCESS, create_paxos_group(id, leader_idx, leader));
 | |
|   LogEngine *log_engine = &leader.palf_handle_.palf_handle_impl_->log_engine_;
 | |
|   LogStorage *log_meta_storage = &log_engine->log_meta_storage_;
 | |
|   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, wait_lsn_until_flushed(leader.palf_handle_.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, wait_lsn_until_flushed(leader.palf_handle_.palf_handle_impl_->get_max_lsn(), leader));
 | |
|   block_id_t expect_block_id = 1;
 | |
|   share::SCN expect_scn;
 | |
|   EXPECT_EQ(OB_SUCCESS, log_engine->get_min_block_info_for_gc(min_block_id, min_block_scn));
 | |
|   EXPECT_EQ(OB_SUCCESS, log_engine->get_block_min_scn(expect_block_id, expect_scn));
 | |
|   EXPECT_EQ(expect_scn, min_block_scn);
 | |
|   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, wait_lsn_until_flushed(leader.palf_handle_.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));
 | |
|   EXPECT_EQ(OB_SUCCESS, log_engine->get_block_min_scn(expect_block_id, expect_scn));
 | |
|   EXPECT_EQ(expect_scn, min_block_scn);
 | |
|   EXPECT_EQ(OB_SUCCESS, log_engine->delete_block(1));
 | |
|   expect_block_id = 3;
 | |
|   EXPECT_EQ(OB_SUCCESS, log_engine->get_min_block_info_for_gc(min_block_id, min_block_scn));
 | |
|   EXPECT_EQ(OB_SUCCESS, log_engine->get_block_min_scn(expect_block_id, expect_scn));
 | |
|   EXPECT_EQ(expect_scn, min_block_scn);
 | |
| }
 | |
| 
 | |
| } // namespace unittest
 | |
| } // namespace oceanbase
 | |
| 
 | |
| int main(int argc, char **argv)
 | |
| {
 | |
|   RUN_SIMPLE_LOG_CLUSTER_TEST(TEST_NAME);
 | |
| }
 | 
