// Copyright 2014 Alibaba Inc. All Rights Reserved. // Author: // qiaoli.xql@alibaba-inc.com // Owner: // lujun.wlj@alibaba-inc.com // // This file tests ObLogPartitionMetaReader. // //l1: Write the correct trailer information and read the correct PartitionMeta information //l2: Write the correct trailer information and read the incorrect PartitionMeta information //l3: Write the correct trailer information and can not read PartitionMeta information //14: not write trailer // #include "clog/ob_log_partition_meta_reader.h" #include "clog/ob_log_file_trailer.h" #include "clog/ob_log_direct_reader.h" #include "clog/ob_log_file_pool.h" #include "clog/ob_log_common.h" #include #include #include "lib/tbsys.h" #include using namespace oceanbase::common; namespace oceanbase { using namespace clog; namespace unittest { class MyMinUsingFileIDGetter: public ObIGetMinUsingFID { public: MyMinUsingFileIDGetter() {} virtual ~MyMinUsingFileIDGetter() {} int on_leader_revoke(const common::ObPartitionKey &partition_key) { UNUSED(partition_key); return OB_SUCCESS; } int on_leader_takeover(const common::ObPartitionKey &partition_key) { UNUSED(partition_key); return OB_SUCCESS; } int on_member_change_success( const common::ObPartitionKey &partition_key, const int64_t mc_timestamp, const common::ObMemberList &prev_member_list, const common::ObMemberList &curr_member_list) { UNUSED(partition_key); UNUSED(mc_timestamp); UNUSED(prev_member_list); UNUSED(curr_member_list); return OB_SUCCESS; } int64_t get_min_using_file_id() const { return 1; } }; class TestObLogPartitionMetaReader: public ::testing::Test { public: virtual void SetUp(); virtual void TearDown(); int write_data(const int fd, const char *buf, const int64_t buf_len, const int64_t offset); int submit_aio(struct iocb *p); int wait_event(struct iocb *p); int write_file(); static const int64_t data_size = 1 << 9; //512 static const int64_t align_size = 1 << 10; //1K static const char *label = "2"; static const char *label2 = "3"; io_context_t ctx_; ObAlignedBuffer buffer; ObAlignedBuffer buffer2; ObLogFileTrailer trailer; ObLogCache cache; const char *path; int64_t blk_len; char buf[align_size]; }; void TestObLogPartitionMetaReader::SetUp() { path = "readers"; EXPECT_LE(0, system("mkdir readers")); EXPECT_LE(0, system("rm readers/*")); memset(&ctx_, 0, sizeof(ctx_)); memset(buf, 0, sizeof(buf)); EXPECT_EQ(0, io_setup(1, &ctx_)); EXPECT_EQ(OB_SUCCESS, buffer.init(align_size, align_size, label)); EXPECT_EQ(OB_SUCCESS, buffer2.init(data_size, data_size, label2)); const int64_t bucket_num = 1024; const int64_t max_cache_size = 1024 * 1024 * 512; const int64_t block_size = common::OB_MALLOC_BIG_BLOCK_SIZE; ObKVGlobalCache::get_instance().init(bucket_num, max_cache_size, block_size); EXPECT_EQ(OB_SUCCESS, cache.init("TestObLogCache", 5)); } void TestObLogPartitionMetaReader::TearDown() { if (NULL != ctx_) { io_destroy(ctx_); } buffer.destroy(); cache.destroy(); ObKVGlobalCache::get_instance().destroy(); } int TestObLogPartitionMetaReader::write_data(const int fd, const char *buf, const int64_t buf_len, const int64_t offset) { int ret = OB_SUCCESS; struct iocb io; struct iocb *p = &io; memset(&io, 0x0, sizeof(io)); io_prep_pwrite(&io, fd, (void *)buf, buf_len, offset); EXPECT_EQ(1, io_submit(ctx_, 1, &p)); EXPECT_EQ(OB_SUCCESS, wait_event(p)); return ret; } int TestObLogPartitionMetaReader::wait_event(struct iocb *p) { int ret = OB_SUCCESS; struct io_event e; struct timespec timeout; OB_ASSERT(p->u.c.offset != -1); OB_ASSERT(static_cast(p->u.c.nbytes) >= 0); timeout.tv_sec = 100; timeout.tv_nsec = 0; //100s EXPECT_EQ(1, io_getevents(ctx_, 1, 1, &e, &timeout)); EXPECT_EQ(0U, e.res2); EXPECT_EQ(p->u.c.nbytes, e.res); EXPECT_EQ(p->data, e.data); return ret; } int TestObLogPartitionMetaReader::write_file() { int ret = OB_SUCCESS; int fd = -1; int64_t pos = 0; int64_t num = 2; int64_t file_size = 1 << 22; //4K int64_t percent = 100; file_id_t start_file_id = 11; //11-14 are test file ObLogBlockMetaV2::MetaContent block; ObLogWriteFilePool write_pool; MyMinUsingFileIDGetter min_getter; EXPECT_EQ(OB_SUCCESS, write_pool.init(path, file_size, percent, &min_getter)); EXPECT_EQ(OB_SUCCESS, block.generate_block(buf, data_size, OB_DATA_BLOCK)); CLOG_LOG(INFO, "block", "meta", to_cstring(block), "buf", buf, "data_size", (int64_t)data_size); EXPECT_EQ(OB_SUCCESS, block.serialize(buffer.get_align_buf(), align_size, pos)); memcpy((buffer.get_align_buf() + pos), buf, data_size); offset_t start_pos = -1; file_id_t next_file_id = 0; blk_len = block.get_total_len(); //--------------test case 1----------------------- //Write file which file id is 11, content is correct, write tow block EXPECT_EQ(OB_SUCCESS, write_pool.get_fd(start_file_id, fd)); for (int64_t i = 0; i < num; i++) { if (OB_SUCCESS != (ret = write_data(fd, buffer.get_align_buf(), blk_len, i * blk_len))) { CLOG_LOG(ERROR, "write_data fail", KERRMSG); } } pos = 0; start_pos = 1024; next_file_id = start_file_id + 1; //Write the trailer of file which file id is 11, include start address and next file id EXPECT_EQ(OB_SUCCESS, trailer.build_serialized_trailer(buffer2.get_align_buf(), data_size, start_pos, next_file_id, pos)); EXPECT_EQ(OB_SUCCESS, write_data(fd, buffer2.get_align_buf(), data_size, CLOG_TRAILER_OFFSET)); if (fd >= 0) { close(fd); } //--------------test case 2----------------------- // Write file whild file id is 13, write data failed, check block integrity fail start_file_id = next_file_id; EXPECT_EQ(OB_SUCCESS, write_pool.get_fd(start_file_id, fd)); buffer.get_align_buf()[512] = 'B'; for (int64_t i = 0; i < num; i++) { if (OB_SUCCESS != (ret = write_data(fd, buffer.get_align_buf(), blk_len, i * blk_len))) { CLOG_LOG(ERROR, "write_data fail", KERRMSG); } } pos = 0; start_pos = 0; next_file_id = start_file_id + 1; //Write the trailer of file which file id is 12, include start address and next file id EXPECT_EQ(OB_SUCCESS, trailer.build_serialized_trailer(buffer2.get_align_buf(), data_size, start_pos, next_file_id, pos)); EXPECT_EQ(OB_SUCCESS, write_data(fd, buffer2.get_align_buf(), data_size, CLOG_TRAILER_OFFSET)); if (fd >= 0) { close(fd); } //--------------test case 3----------------------- // Write file whild file id is 13, write one block, data correct, // check meat checksum fail start_file_id = next_file_id; EXPECT_EQ(OB_SUCCESS, write_pool.get_fd(start_file_id, fd)); EXPECT_EQ(OB_SUCCESS, write_data(fd, buffer.get_align_buf(), blk_len, 0)); pos = 0; start_pos = 512; next_file_id = start_file_id + 1; //Write the trailer of file which file id is 13, include start address and next file id EXPECT_EQ(OB_SUCCESS, trailer.build_serialized_trailer(buffer2.get_align_buf(), data_size, start_pos, next_file_id, pos)); EXPECT_EQ(OB_SUCCESS, write_data(fd, buffer2.get_align_buf(), data_size, CLOG_TRAILER_OFFSET)); if (fd >= 0) { close(fd); } //--------------test case 4----------------------- // Write file whild file id is 14, write one block, data correct start_file_id = next_file_id; EXPECT_EQ(OB_SUCCESS, write_pool.get_fd(start_file_id, fd)); EXPECT_EQ(OB_SUCCESS, write_data(fd, buffer.get_align_buf(), blk_len, 0)); if (fd >= 0) { close(fd); } return ret; } TEST_F(TestObLogPartitionMetaReader, test_read_partition_meta) { ObLogReadFilePool reader_pool; ObLogDirectReader dreader; ObLogPartitionMetaReader reader; ObReadParam param; ObReadRes res; file_id_t start_file_id = 11; param.timeout_ = 5000000; //5s param.read_len_ = OB_MAX_LOG_BUFFER_SIZE; param.file_id_ = start_file_id; EXPECT_EQ(OB_NOT_INIT, reader.read_partition_meta(param, res)); EXPECT_EQ(OB_INVALID_ARGUMENT, reader.init(NULL)); EXPECT_EQ(OB_NOT_INIT, reader.read_partition_meta(param, res)); //Test read CLOG_LOG(INFO, "begin unittest::test_ob_log_partition_meta_reader"); EXPECT_EQ(OB_SUCCESS, reader_pool.init(path)); EXPECT_EQ(OB_SUCCESS, dreader.init(&reader_pool, &cache)); EXPECT_EQ(OB_SUCCESS, reader.init(&dreader)); EXPECT_EQ(OB_INIT_TWICE, reader.init(&dreader)); EXPECT_EQ(OB_SUCCESS, write_file()); //Test read first block param.file_id_ = start_file_id; EXPECT_EQ(OB_SUCCESS, reader.read_partition_meta(param, res)); EXPECT_EQ((int64_t)data_size, res.data_len_); param.file_id_ = param.file_id_ + 1; EXPECT_EQ(OB_INVALID_DATA, reader.read_partition_meta(param, res)); param.file_id_ = param.file_id_ + 1; EXPECT_EQ(OB_INVALID_DATA, reader.read_partition_meta(param, res)); param.file_id_ = param.file_id_ + 1; EXPECT_EQ(OB_READ_NOTHING, reader.read_partition_meta(param, res)); //Test failure param.reset(); EXPECT_EQ(OB_INVALID_ARGUMENT, reader.read_partition_meta(param, res)); //Test deserialize failed param.file_id_ = start_file_id; param.read_len_ = 1; param.timeout_ = 5000000; //5s EXPECT_EQ(OB_DESERIALIZE_ERROR, reader.read_partition_meta(param, res)); //Test invalid argument param.file_id_ = start_file_id; param.read_len_ = 1; param.timeout_ = 0; res.reset(); EXPECT_EQ(OB_INVALID_ARGUMENT, reader.read_partition_meta(param, res)); } } // end namespace unittest } // end namespace oceanbase int main(int argc, char **argv) { OB_LOGGER.set_file_name("test_ob_log_partition_meta_reader.log", true); OB_LOGGER.set_log_level("INFO"); CLOG_LOG(INFO, "begin unittest::test_ob_log_partition_meta_reader"); testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }