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);
 | 
						|
}
 |