Files
oceanbase/mittest/mtlenv/storage/test_migration_tablet_param.cpp
2024-11-20 13:45:41 +00:00

408 lines
14 KiB
C++

// owner: jiahua.cjh
// owner group: storage
/**
* 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 <gtest/gtest.h>
#define private public
#define protected public
#include "lib/ob_errno.h"
#include "lib/allocator/page_arena.h"
#include "lib/oblog/ob_log.h"
#include "share/rc/ob_tenant_base.h"
#include "mtlenv/mock_tenant_module_env.h"
#include "mtlenv/storage/medium_info_helper.h"
#include "unittest/storage/test_tablet_helper.h"
#include "unittest/storage/test_dml_common.h"
#include "storage/tablet/ob_tablet.h"
#define USING_LOG_PREFIX STORAGE
using namespace oceanbase::common;
using namespace oceanbase::share;
using namespace oceanbase::storage;
namespace oceanbase
{
int ObClusterVersion::get_tenant_data_version(const uint64_t tenant_id, uint64_t &data_version)
{
data_version = DATA_VERSION_4_3_2_0;
return OB_SUCCESS;
}
namespace unittest
{
class TestMigrationTabletParam : public ::testing::Test
{
public:
TestMigrationTabletParam() = default;
virtual ~TestMigrationTabletParam() = default;
public:
static constexpr uint64_t TENANT_ID = 1001;
static const share::ObLSID LS_ID;
public:
static void SetUpTestCase();
static void TearDownTestCase();
public:
static int create_ls(const uint64_t tenant_id, const share::ObLSID &ls_id, ObLSHandle &ls_handle);
static int remove_ls(const share::ObLSID &ls_id);
int create_tablet(const common::ObTabletID &tablet_id, ObTabletHandle &tablet_handle);
static int insert_data_into_mds_data(ObArenaAllocator &allocator, mds::MdsDumpKV &kv);
static bool is_user_data_equal(const ObTabletCreateDeleteMdsUserData &left, const ObTabletCreateDeleteMdsUserData &right);
public:
ObArenaAllocator allocator_;
};
const share::ObLSID TestMigrationTabletParam::LS_ID(1234);
void TestMigrationTabletParam::SetUpTestCase()
{
int ret = OB_SUCCESS;
ret = MockTenantModuleEnv::get_instance().init();
ASSERT_EQ(OB_SUCCESS, ret);
ObServerStorageMetaService::get_instance().is_started_ = true;
// create ls
ObLSHandle ls_handle;
ret = create_ls(TENANT_ID, LS_ID, ls_handle);
ASSERT_EQ(OB_SUCCESS, ret);
}
void TestMigrationTabletParam::TearDownTestCase()
{
int ret = OB_SUCCESS;
// remove ls
ret = remove_ls(LS_ID);
ASSERT_EQ(OB_SUCCESS, ret);
MockTenantModuleEnv::get_instance().destroy();
}
int TestMigrationTabletParam::create_ls(const uint64_t tenant_id, const share::ObLSID &ls_id, ObLSHandle &ls_handle)
{
int ret = OB_SUCCESS;
ret = TestDmlCommon::create_ls(tenant_id, ls_id, ls_handle);
return ret;
}
int TestMigrationTabletParam::remove_ls(const share::ObLSID &ls_id)
{
int ret = OB_SUCCESS;
ret = MTL(ObLSService*)->remove_ls(ls_id);
return ret;
}
int TestMigrationTabletParam::create_tablet(const common::ObTabletID &tablet_id, ObTabletHandle &tablet_handle)
{
int ret = OB_SUCCESS;
const uint64_t table_id = 1234567;
share::schema::ObTableSchema table_schema;
ObLSHandle ls_handle;
ObLS *ls = nullptr;
if (OB_FAIL(MTL(ObLSService*)->get_ls(LS_ID, ls_handle, ObLSGetMod::STORAGE_MOD))) {
LOG_WARN("failed to get ls", K(ret));
} else if (OB_ISNULL(ls = ls_handle.get_ls())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("ls is null", K(ret), KP(ls));
} else if (OB_FAIL(build_test_schema(table_schema, table_id))) {
LOG_WARN("failed to build table schema");
} else if (OB_FAIL(TestTabletHelper::create_tablet(ls_handle, tablet_id, table_schema, allocator_,
ObTabletStatus::MAX, share::SCN::invalid_scn(), tablet_handle))) {
LOG_WARN("failed to create tablet", K(ret));
}
return ret;
}
int TestMigrationTabletParam::insert_data_into_mds_data(ObArenaAllocator &allocator, mds::MdsDumpKV &kv)
{
int ret = OB_SUCCESS;
ObTabletCreateDeleteMdsUserData user_data;
user_data.tablet_status_ = ObTabletStatus::NORMAL;
const int64_t serialize_size = user_data.get_serialize_size();
char *buffer = static_cast<char *>(allocator.alloc(serialize_size));
int64_t pos = 0;
if (OB_ISNULL(buffer)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fail to alloc memory", K(ret), K(serialize_size));
} else if (OB_FAIL(user_data.serialize(buffer, serialize_size, pos))) {
LOG_WARN("fail to serialize user data", K(ret));
} else {
kv.v_.user_data_.assign(buffer, serialize_size);
}
return ret;
}
bool TestMigrationTabletParam::is_user_data_equal(const ObTabletCreateDeleteMdsUserData &left, const ObTabletCreateDeleteMdsUserData &right)
{
const bool res = left.tablet_status_ == right.tablet_status_ && left.transfer_scn_ == right.transfer_scn_
&& left.transfer_ls_id_ == right.transfer_ls_id_ && left.data_type_ == right.data_type_
&& left.create_commit_scn_ == right.create_commit_scn_
&& left.create_commit_version_ == right.create_commit_version_
&& left.delete_commit_version_ == right.delete_commit_version_
&& left.start_transfer_commit_version_ == right.start_transfer_commit_version_;
return res;
}
TEST_F(TestMigrationTabletParam, migration)
{
int ret = OB_SUCCESS;
// create tablet
const common::ObTabletID tablet_id(ObTimeUtility::fast_current_time() % 10000000000000);
ObTabletHandle tablet_handle;
ObTabletStatus status(ObTabletStatus::MAX);
share::SCN create_commit_scn;
create_commit_scn = share::SCN::plus(share::SCN::min_scn(), 100);
ret = create_tablet(tablet_id, tablet_handle);
ASSERT_EQ(OB_SUCCESS, ret);
ObTablet *tablet = tablet_handle.get_obj();
ASSERT_NE(nullptr, tablet);
// write data to mds table
{
ObTabletCreateDeleteMdsUserData user_data;
user_data.tablet_status_ = ObTabletStatus::NORMAL;
user_data.data_type_ = ObTabletMdsUserDataType::CREATE_TABLET;
mds::MdsCtx ctx(mds::MdsWriter(transaction::ObTransID(123)));
ret = tablet->set_tablet_status(user_data, ctx);
ASSERT_EQ(OB_SUCCESS, ret);
share::SCN redo_scn = share::SCN::plus(share::SCN::min_scn(), 50);
ctx.on_redo(redo_scn);
ctx.on_commit(create_commit_scn, create_commit_scn);
}
// {
// // build migration param v2
// ObMigrationTabletParam param_v2;
// ret = tablet->build_migration_tablet_param(param_v2);
// ASSERT_EQ(OB_NOT_SUPPORTED, ret);
// // insert some data into migration param
// ret = insert_data_into_mds_data(allocator_, param_v2.mds_data_.tablet_status_committed_kv_);
// ASSERT_EQ(OB_SUCCESS, ret);
// param_v2.version_ = ObMigrationTabletParam::PARAM_VERSION_V2;
// int64_t serialize_size = param_v2.get_serialize_size();
// char *buffer = new char[serialize_size]();
// int64_t pos = 0;
// ret = param_v2.serialize(buffer, serialize_size, pos);
// ASSERT_EQ(OB_SUCCESS, ret);
// ASSERT_EQ(serialize_size, pos);
// // param v2 deserialize
// ObMigrationTabletParam param2;
// pos = 0;
// ret = param2.deserialize(buffer, serialize_size, pos);
// ASSERT_EQ(OB_SUCCESS, ret);
// ASSERT_EQ(pos, serialize_size);
// ASSERT_TRUE(param2.is_valid());
// delete [] buffer;
// }
{
// build migration param v3
ObMigrationTabletParam param_v3;
ret = tablet->build_migration_tablet_param(param_v3);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(true, param_v3.version_ == ObMigrationTabletParam::PARAM_VERSION_V3);
// insert some data into migration param
ret = insert_data_into_mds_data(allocator_, param_v3.mds_data_.tablet_status_committed_kv_);
ASSERT_EQ(OB_SUCCESS, ret);
int64_t serialize_size = param_v3.get_serialize_size();
char *buffer = new char[serialize_size]();
int64_t pos = 0;
ret = param_v3.serialize(buffer, serialize_size, pos);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(serialize_size, pos);
// param v3 deserialize
ObMigrationTabletParam param2;
pos = 0;
ret = param2.deserialize(buffer, serialize_size, pos);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(pos, serialize_size);
ASSERT_TRUE(param2.is_valid());
delete [] buffer;
}
}
TEST_F(TestMigrationTabletParam, transfer)
{
int ret = OB_SUCCESS;
// create tablet
const common::ObTabletID tablet_id(ObTimeUtility::fast_current_time() % 10000000000000);
ObTabletHandle tablet_handle;
ObTabletStatus status(ObTabletStatus::MAX);
ret = create_tablet(tablet_id, tablet_handle);
ASSERT_EQ(OB_SUCCESS, ret);
ObTablet *tablet = tablet_handle.get_obj();
ASSERT_NE(nullptr, tablet);
// write data to mds table
{
ObTabletCreateDeleteMdsUserData user_data;
user_data.tablet_status_ = ObTabletStatus::TRANSFER_OUT;
user_data.data_type_ = ObTabletMdsUserDataType::START_TRANSFER_OUT;
user_data.transfer_scn_ = share::SCN::plus(share::SCN::min_scn(), 60);
share::SCN transfer_commit_scn;
transfer_commit_scn = share::SCN::plus(share::SCN::min_scn(), 70);
mds::MdsCtx ctx(mds::MdsWriter(transaction::ObTransID(123)));
ret = tablet->set_tablet_status(user_data, ctx);
ASSERT_EQ(OB_SUCCESS, ret);
share::SCN redo_scn = user_data.transfer_scn_;
ctx.on_redo(redo_scn);
ctx.on_commit(transfer_commit_scn, transfer_commit_scn);
}
// write medium info
{
compaction::ObMediumCompactionInfoKey key(100);
compaction::ObMediumCompactionInfo info;
ret = MediumInfoHelper::build_medium_compaction_info(allocator_, info, 100);
ASSERT_EQ(OB_SUCCESS, ret);
mds::MdsCtx ctx(mds::MdsWriter(transaction::ObTransID(777)));
ret = tablet->set(key, info, ctx, 1_s/*lock_timeout_us*/);
ASSERT_EQ(OB_SUCCESS, ret);
share::SCN redo_scn = share::SCN::plus(share::SCN::min_scn(), 110);
ctx.on_redo(redo_scn);
share::SCN commit_scn = share::SCN::plus(share::SCN::min_scn(), 120);
ctx.on_commit(commit_scn, commit_scn);
}
{
// build transfer tablet param v3
ObMigrationTabletParam param_v3;
ASSERT_EQ(false, param_v3.is_valid());
share::ObLSID dst_ls_id(1001);
const int64_t data_version = DATA_VERSION_4_3_2_0;
ret = tablet->build_transfer_tablet_param(data_version, dst_ls_id, param_v3);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(true, param_v3.is_valid());
ASSERT_EQ(true, param_v3.version_ == ObMigrationTabletParam::PARAM_VERSION_V3);
ASSERT_EQ(param_v3.last_persisted_committed_tablet_status_.data_type_, ObTabletMdsUserDataType::START_TRANSFER_IN);
ASSERT_EQ(param_v3.last_persisted_committed_tablet_status_.tablet_status_, ObTabletStatus::TRANSFER_IN);
int64_t serialize_size = param_v3.get_serialize_size();
char *buffer = new char[serialize_size]();
int64_t pos = 0;
ret = param_v3.serialize(buffer, serialize_size, pos);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(serialize_size, pos);
// param v3 deserialize
ObMigrationTabletParam param2;
pos = 0;
ret = param2.deserialize(buffer, serialize_size, pos);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(pos, serialize_size);
ASSERT_TRUE(param2.is_valid());
ASSERT_EQ(true, is_user_data_equal(param_v3.last_persisted_committed_tablet_status_, param2.last_persisted_committed_tablet_status_));
ObMigrationTabletParam test_param;
test_param.assign(param_v3);
ASSERT_EQ(true, is_user_data_equal(param_v3.last_persisted_committed_tablet_status_, test_param.last_persisted_committed_tablet_status_));
delete [] buffer;
}
}
TEST_F(TestMigrationTabletParam, empty_shell_transfer)
{
int ret = OB_SUCCESS;
// create tablet
const common::ObTabletID tablet_id(ObTimeUtility::fast_current_time() % 10000000000000);
share::schema::ObTableSchema schema;
ObLSHandle ls_handle;
ObLS *ls = nullptr;
ObLSTabletService *ls_tablet_service = nullptr;
if (OB_FAIL(MTL(ObLSService*)->get_ls(LS_ID, ls_handle, ObLSGetMod::STORAGE_MOD))) {
LOG_WARN("failed to get ls", K(ret));
} else if (OB_ISNULL(ls = ls_handle.get_ls())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("ls is null", K(ret), KP(ls));
} else {
ls_tablet_service = ls->get_tablet_svr();
}
ASSERT_NE(nullptr, ls_tablet_service);
TestSchemaUtils::prepare_data_schema(schema);
ret = TestTabletHelper::create_tablet(ls_handle, tablet_id, schema, allocator_, ObTabletStatus::Status::DELETED);
ASSERT_EQ(OB_SUCCESS, ret);
ret = ls_tablet_service->update_tablet_to_empty_shell(tablet_id);
ASSERT_EQ(OB_SUCCESS, ret);
ObTabletHandle empty_shell_tablet_handle;
ret = ls_tablet_service->get_tablet(tablet_id, empty_shell_tablet_handle, 0, ObMDSGetTabletMode::READ_WITHOUT_CHECK);
ASSERT_EQ(OB_SUCCESS, ret);
ObTablet *empty_shell_tablet = empty_shell_tablet_handle.get_obj();
ASSERT_NE(nullptr, empty_shell_tablet);
{
// build transfer tablet param v3
ObMigrationTabletParam param_v3;
ASSERT_EQ(false, param_v3.is_valid());
share::ObLSID dst_ls_id(1001);
const int64_t data_version = DATA_VERSION_4_3_2_0;
ret = empty_shell_tablet->build_transfer_tablet_param(data_version, dst_ls_id, param_v3);
ASSERT_EQ(OB_ERR_UNEXPECTED, ret);
}
{
// build migration tablet param v3
ObMigrationTabletParam param_v3;
ASSERT_EQ(false, param_v3.is_valid());
ASSERT_EQ(false, param_v3.is_valid());
ret = empty_shell_tablet->build_migration_tablet_param(param_v3);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_EQ(true, param_v3.is_valid());
ASSERT_EQ(true, param_v3.version_ == ObMigrationTabletParam::PARAM_VERSION_V3);
ObMigrationTabletParam test_param;
test_param.assign(param_v3);
ASSERT_EQ(true, is_user_data_equal(param_v3.last_persisted_committed_tablet_status_, test_param.last_persisted_committed_tablet_status_));
}
}
} // namespace unittest
} // namespace oceanbase
int main(int argc, char **argv)
{
system("rm -rf test_migration_tablet_param.log*");
OB_LOGGER.set_file_name("test_migration_tablet_param.log", true);
OB_LOGGER.set_log_level("INFO");
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}