302 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			302 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // 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 <gtest/gtest.h>
 | |
| #include <gmock/gmock.h>
 | |
| #include "lib/tbsys.h"
 | |
| #include <libaio.h>
 | |
| 
 | |
| 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<int64_t>(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();
 | |
| }
 | 
