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