TEST(ObMultiVersionTabletImage, test_service)
{
  FileInfoCache fic;
  ObMultiVersionTabletImage image(fic);

  fic.init(100);
  CharArena allocator;
  ObRange r1,r2,r3;
  create_range(allocator, r1, 1, ObBorderFlag::INCLUSIVE_START|ObBorderFlag::INCLUSIVE_END, "aoo", "foo");
  create_range(allocator, r2, 1, ObBorderFlag::INCLUSIVE_END, "foo", "mj");
  create_range(allocator, r3, 1, ObBorderFlag::INCLUSIVE_END, "mj", "oi");

  int ret = 0;
  ObTablet* tablet = NULL;
  ObSSTableId id;
  id.sstable_file_id_ = 1;
  id.sstable_file_offset_ = 0;

  ret = image.alloc_tablet_object(r1, VERSION_1, tablet);
  ASSERT_EQ(0, ret);
  tablet->set_disk_no(1);
  ret = tablet->add_sstable_by_id(id);
  ASSERT_EQ(0, ret);
  ret = image.add_tablet(tablet, false);
  ASSERT_EQ(0, ret);

  //image.initialize_service_index();

  /*
  ret = image.alloc_tablet_object(r1, VERSION_2, tablet);
  ASSERT_EQ(0, ret);
  tablet->set_disk_no(1);
  ret = tablet->add_sstable_by_id(id);
  ASSERT_EQ(0, ret);
  ret = image.add_tablet(tablet, false);
  ASSERT_EQ(0, ret);

  ret = image.alloc_tablet_object(r2, VERSION_2, tablet);
  ASSERT_EQ(0, ret);
  id.sstable_file_id_ = 2;
  id.sstable_file_offset_ = 0;
  tablet->set_disk_no(2);
  tablet->add_sstable_by_id(id);
  ret = image.add_tablet(tablet, false);
  ASSERT_EQ(0, ret);

  ret = image.alloc_tablet_object(r3, VERSION_2, tablet);
  ASSERT_EQ(0, ret);
  id.sstable_file_id_ = 3;
  id.sstable_file_offset_ = 0;
  tablet->set_disk_no(3);
  tablet->add_sstable_by_id(id);
  ret = image.add_tablet(tablet, false);
  ASSERT_EQ(0, ret);

  ret = write_all(image);
  ASSERT_EQ(0, ret);
  */
  fic.destroy();
}
TEST(ObMultiVersionTabletImage, test_remove)
{
  FileInfoCache fic;
  ObMultiVersionTabletImage image(fic);
  fic.init(100);

  CharArena allocator;
  ObRange r1,r2,r3;
  create_range(allocator, r1, 1, ObBorderFlag::INCLUSIVE_START|ObBorderFlag::INCLUSIVE_END, "aoo", "foo");
  create_range(allocator, r2, 1, ObBorderFlag::INCLUSIVE_END, "foo", "mj");
  create_range(allocator, r3, 1, ObBorderFlag::INCLUSIVE_END, "mj", "oi");

  int ret = read_all(image);
  ASSERT_EQ(0, ret);

  int disk_no = 0;
  ObTablet *tablet= NULL;

  ret = image.remove_tablet(r1, VERSION_2, disk_no);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(1, disk_no);

  ret = image.acquire_tablet(r1, ObMultiVersionTabletImage::SCAN_FORWARD, VERSION_2, tablet);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(true, tablet->get_range().equal(r1));
  ASSERT_EQ(VERSION_1, tablet->get_data_version());
  ret = image.release_tablet(tablet);
  ASSERT_EQ(0, ret);

  fic.destroy();
}
TEST(ObMultiVersionTabletImage, test_write_null)
{
  FileInfoCache fic;
  ObMultiVersionTabletImage image(fic);

  fic.init(100);
  CharArena allocator;
  ObRange r1;

  ObBorderFlag flag; 
  flag.set_min_value();
  flag.set_max_value();

  create_range(allocator, r1, 1, flag.get_data(), "", "");

  int ret = 0;
  ObTablet* tablet = NULL;
  ObSSTableId id;
  id.sstable_file_id_ = 1;
  id.sstable_file_offset_ = 0;

  ret = image.alloc_tablet_object(r1, VERSION_1, tablet);
  ASSERT_EQ(0, ret);
  tablet->set_disk_no(1);
  ret = tablet->add_sstable_by_id(id);
  ASSERT_EQ(0, ret);
  ret = image.add_tablet(tablet, false);
  ASSERT_EQ(0, ret);

  image.write(VERSION_1, 1);

  fic.destroy();
}
Exemple #4
0
/// @brief 
bool fi_initialize()
{
	FileInfoCache* fi = Singleton<FileInfoCache>::GetInstancePointer();

	//
	//	cache 파일 경로는 `현재경로\ficache.db` 로 지정
	//
	std::wstringstream cache_path;
	cache_path << get_current_module_dirEx() << L"\\ficache.db";
	if (true != fi->initialize(cache_path.str().c_str(), 5000, false))
	{
		return false;
	}
	return true;
}
TEST(ObMultiVersionTabletImage, test_query_min_max)
{
  FileInfoCache fic;
  ObMultiVersionTabletImage image(fic);

  fic.init(100);
  CharArena allocator;
  ObRange r1,r2,r3;
  create_range(allocator, r1, 1, ObBorderFlag::INCLUSIVE_START|ObBorderFlag::INCLUSIVE_END, "aoo", "foo");
  create_range(allocator, r2, 1, ObBorderFlag::INCLUSIVE_END, "foo", "mj");
  create_range(allocator, r3, 1, ObBorderFlag::INCLUSIVE_END, "mj", "oi");

  ObRange rall;
  ObBorderFlag flag; 
  flag.set_min_value();
  flag.set_max_value();
  create_range(allocator, rall, 1, flag.get_data(), "aoo", "zoo");

  int ret = 0;
  ObTablet* tablet = NULL;
  ObSSTableId id;
  id.sstable_file_id_ = 1;
  id.sstable_file_offset_ = 0;

  ret = image.alloc_tablet_object(rall, VERSION_1, tablet);
  ASSERT_EQ(0, ret);
  tablet->set_disk_no(1);
  ret = tablet->add_sstable_by_id(id);
  ASSERT_EQ(0, ret);
  ret = image.add_tablet(tablet, false, true);
  ASSERT_EQ(0, ret);

  image.dump();

  ret = image.acquire_tablet(r1, ObMultiVersionTabletImage::SCAN_FORWARD, 0, tablet);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(VERSION_1, tablet->get_data_version());
  image.release_tablet(tablet);

  ret = image.acquire_tablet(rall, ObMultiVersionTabletImage::SCAN_FORWARD, 0, tablet);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(VERSION_1, tablet->get_data_version());
  tablet->get_range().hex_dump();
  image.release_tablet(tablet);

  fic.destroy();
}
  static void SetUpTestCase()
  {
    char cmd[512];
    ObSSTableId ob_sstable_id;

    ob_sstable_id.sstable_file_id_ = sstable_id1;
    get_sstable_path(ob_sstable_id, file_name, 256);
    remove(file_name);
    sprintf(cmd, "mkdir -p %s; rm -rf %s; cp %s %s", 
            file_name, file_name, file_name1, file_name);
    system(cmd);

    ob_sstable_id.sstable_file_id_ = sstable_id2;
    get_sstable_path(ob_sstable_id, file_name, 256);
    remove(file_name);
    sprintf(cmd, "mkdir -p %s; rm -rf %s; cp %s %s", 
            file_name, file_name, file_name2, file_name);
    system(cmd);

    fic.init(1024);
  }
int main(int argc, char **argv)
{
  TBSYS_LOGGER.setLogLevel("ERROR");
  TBSYS_LOGGER.setFileName("./log/thread_test.log");
  if (1 >= argc)
  {
    fprintf(stderr, "handle_type must be set\n");
    exit(-1);
  }

  if (0 == strcmp(argv[1], "prepare"))
  {
    prepare_file("./data");
  }
  else if (0 == strcmp(argv[1], "test"))
  {
    if (3 >= argc)
    {
      fprintf(stderr, "thread num and times per thread must be set\n");
      exit(-1);
    }
    ObBlockCacheConf conf;
    conf.block_cache_memsize_mb = 1024;
    conf.ficache_max_num = 1024;
    fic.init(conf.ficache_max_num);
    bc.init(conf);
    g_thread_num = atoi(argv[2]);
    g_times_per_thread = atoi(argv[3]);
    srand(static_cast<int32_t>(time(NULL)));
    thread_test();
    bc.destroy();
  }
  else
  {
    fprintf(stderr, "invalid handle_type must be [preapre | test]\n");
    exit(-1);
  }
}
    namespace chunkserver 
    {
      static const int64_t table_id = 100;
      static const int64_t sstable_file_id = 1001;
      static const int64_t sstable_file_offset = 0;
      static const int64_t DISK_NUM = 12;
      static const int64_t SSTABLE_NUM = DISK_NUM * 2;
      static const int64_t SSTABLE_ROW_NUM = 100;
      static const int64_t ROW_NUM = SSTABLE_NUM * SSTABLE_ROW_NUM;
      static const int64_t COL_NUM = 5;
      static const int64_t NON_EXISTENT_ROW_NUM = 100;
      static const ObString table_name(strlen("sstable") + 1, strlen("sstable") + 1, "sstable");
      static const int64_t OB_MAX_GET_COLUMN_NUMBER = 128;

      static char sstable_file_path[OB_MAX_FILE_NAME_LENGTH];
      static ObCellInfo** cell_infos;
      static char* row_key_strs[ROW_NUM + NON_EXISTENT_ROW_NUM][COL_NUM];
      static FileInfoCache fic;

      static ModulePageAllocator mod(0);
      static ModuleArena allocator(ModuleArena::DEFAULT_PAGE_SIZE, mod);
      static ObSSTableReader reader_(allocator, fic);

      class TestObBlockCacheReaderLoader: public ::testing::Test
      {
      public:
        TestObBlockCacheReaderLoader()
        : old_index_cache_(fic), old_block_cache_(fic), 
          new_index_cache_(fic), new_block_cache_(fic)
        {
        }

        ~TestObBlockCacheReaderLoader()
        {
        }

        void init_conf(ObBlockCacheConf &conf)
        {
          conf.block_cache_memsize_mb = 128;
          conf.ficache_max_num = 1024;
        }

        int init()
        {
          int ret = OB_SUCCESS;

          ObBlockCacheConf conf;
          init_conf(conf);
          EXPECT_EQ(OB_SUCCESS, ret);
        
          ret = old_block_cache_.init(conf);
          EXPECT_EQ(OB_SUCCESS, ret);
          ret = new_block_cache_.init(conf);
          EXPECT_EQ(OB_SUCCESS, ret);

          ObBlockIndexCacheConf bic_conf = {16 * 1024 * 1024};
          ret = old_index_cache_.init(bic_conf);
          EXPECT_EQ(OB_SUCCESS, ret);
          ret = new_index_cache_.init(bic_conf);
          EXPECT_EQ(OB_SUCCESS, ret);

          return ret;
        }

        static int init_sstable(ObSSTableReader& sstable, const ObCellInfo** cell_infos,
            const int64_t row_num, const int64_t col_num, const int64_t sst_id = 0L)
        {
          int err = OB_SUCCESS;
  
          ObSSTableSchema sstable_schema;
          ObSSTableSchemaColumnDef column_def;
  
          EXPECT_TRUE(NULL != cell_infos);
          EXPECT_TRUE(row_num > 0);
          EXPECT_TRUE(col_num > 0);

          uint64_t table_id = cell_infos[0][0].table_id_;
          ObString path;
          int64_t sstable_file_id = 0;
          ObString compress_name;
          char* path_str = sstable_file_path;
          int64_t path_len = OB_MAX_FILE_NAME_LENGTH;

          for (int64_t i = 0; i < col_num; ++i)
          {
            column_def.reserved_ = 0;
            if (i >=2)
            {
              column_def.column_group_id_= 2;
            }
            else
            {
              column_def.column_group_id_= 0;
            }
            column_def.column_name_id_ = cell_infos[0][i].column_id_;
            column_def.column_value_type_ = cell_infos[0][i].value_.get_type();
            column_def.table_id_ = table_id;
            sstable_schema.add_column_def(column_def);
          }
  
          if (0 == sst_id)
          {
            sstable_file_id = 100;
          }
          else
          {
            sstable_file_id = sst_id;
          }
  
          ObSSTableId sstable_id(sst_id);
          get_sstable_path(sstable_id, path_str, path_len);
          char cmd[256];
          sprintf(cmd, "mkdir -p %s", path_str);
          system(cmd);
          path.assign((char*)path_str, strlen(path_str));
          compress_name.assign("lzo_1.0", strlen("lzo_1.0"));
          remove(path.ptr());

          ObSSTableWriter writer;
          err = writer.create_sstable(sstable_schema, path, compress_name, 0);
          EXPECT_EQ(OB_SUCCESS, err);
  
          for (int64_t i = 0; i < row_num; ++i)
          {
            ObSSTableRow row;
            row.set_table_id(table_id);
            row.set_column_group_id(0);
            err = row.set_row_key(cell_infos[i][0].row_key_);
            EXPECT_EQ(OB_SUCCESS, err);
            for (int64_t j = 0; j < 2; ++j)
            {
              err = row.add_obj(cell_infos[i][j].value_);
              EXPECT_EQ(OB_SUCCESS, err);
            }
  
            int64_t space_usage = 0;
            err = writer.append_row(row, space_usage);
            EXPECT_EQ(OB_SUCCESS, err);
          }

          for (int64_t i = 0; i < row_num; ++i)
          {
            ObSSTableRow row;
            row.set_table_id(table_id);
            row.set_column_group_id(2);
            err = row.set_row_key(cell_infos[i][0].row_key_);
            EXPECT_EQ(OB_SUCCESS, err);
            for (int64_t j = 2; j < col_num; ++j)
            {
              err = row.add_obj(cell_infos[i][j].value_);
              EXPECT_EQ(OB_SUCCESS, err);
            }
  
            int64_t space_usage = 0;
            err = writer.append_row(row, space_usage);
            EXPECT_EQ(OB_SUCCESS, err);
          }
  
          int64_t offset = 0;
          err = writer.close_sstable(offset);
          EXPECT_EQ(OB_SUCCESS, err);
  
          err = fic.init(1024);
          EXPECT_EQ(OB_SUCCESS, err);

          err = reader_.open(sstable_id);
          EXPECT_EQ(OB_SUCCESS, err);
          EXPECT_TRUE(reader_.is_opened());
  
          return err;
        }
  
      public:
        static void SetUpTestCase()
        {
          int err = OB_SUCCESS;
      
          //malloc
          cell_infos = new ObCellInfo*[ROW_NUM + NON_EXISTENT_ROW_NUM];
          for (int64_t i = 0; i < ROW_NUM + NON_EXISTENT_ROW_NUM; ++i)
          {
            cell_infos[i] = new ObCellInfo[COL_NUM];
          }
      
          for (int64_t i = 0; i < ROW_NUM + NON_EXISTENT_ROW_NUM; ++i)
          {
            for (int64_t j = 0; j < COL_NUM; ++j)
            {
              row_key_strs[i][j] = new char[50];
            }
          }
      
          // init cell infos
          for (int64_t i = 0; i < ROW_NUM + NON_EXISTENT_ROW_NUM; ++i)
          {
            for (int64_t j = 0; j < COL_NUM; ++j)
            {
              cell_infos[i][j].table_id_ = table_id;
              sprintf(row_key_strs[i][j], "row_key_%08ld", i);
              cell_infos[i][j].row_key_.assign(row_key_strs[i][j], strlen(row_key_strs[i][j]));
              cell_infos[i][j].column_id_ = j + 2;
              cell_infos[i][j].value_.set_int(1000 + i * COL_NUM + j);
            }
          }
      
          //init sstable
          err = init_sstable(reader_, (const ObCellInfo**)cell_infos, 
                             ROW_NUM, COL_NUM, sstable_file_id);
          EXPECT_EQ(OB_SUCCESS, err);
        }
      
        static void TearDownTestCase()
        {
          for (int64_t i = 0; i < ROW_NUM + NON_EXISTENT_ROW_NUM; ++i)
          {
            for (int64_t j = 0; j < COL_NUM; ++j)
            {
              if (NULL != row_key_strs[i][j])
              {
                delete[] row_key_strs[i][j];
                row_key_strs[i][j] = NULL;
              }
            }
          }
      
          for (int64_t i = 0; i < ROW_NUM + NON_EXISTENT_ROW_NUM; ++i)
          {
            if (NULL != cell_infos[i])
            {
              delete[] cell_infos[i];
              cell_infos[i] = NULL;
            }
          }
          if (NULL != cell_infos)
          {
            delete[] cell_infos;
          }

          reader_.reset();
        }

      public:
        virtual void SetUp()
        {
          int ret;
  
          ret = init();
          ASSERT_EQ(OB_SUCCESS, ret);
        }
      
        virtual void TearDown()
        {
          int ret;

          ret = cache_utility_.destroy_cache(old_block_cache_, old_index_cache_);
          ASSERT_EQ(OB_SUCCESS, ret);
          ret = cache_utility_.destroy_cache(new_block_cache_,new_index_cache_);
          ASSERT_EQ(OB_SUCCESS, ret);
        }

      public:
        ObBlockIndexCache old_index_cache_;
        ObBlockCache old_block_cache_;
        ObBlockIndexCache new_index_cache_;
        ObBlockCache new_block_cache_;
        ObBlockCacheReader cache_reader_;
        ObBlockCacheLoader cache_loader_;
        ObSwitchCacheUtility cache_utility_;
      };

      TEST_F(TestObBlockCacheReaderLoader, test_block_cache_loader)
      {
        int ret;
        uint64_t table_id = 100;
        uint64_t column_group_id = 0;

        ObString start_key = cell_infos[0][0].row_key_;
        ObString end_key = cell_infos[ROW_NUM - 1][0].row_key_;

        ret = cache_loader_.load_block_into_cache(old_index_cache_, old_block_cache_, 
                                                  table_id, column_group_id, 
                                                  start_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret);
        ret = cache_loader_.load_block_into_cache(old_index_cache_, old_block_cache_, 
                                                  table_id, column_group_id, 
                                                  end_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret);

        ret = cache_reader_.get_start_key_of_next_block(old_block_cache_, table_id, 
                                                        column_group_id, start_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret);
        ret = cache_loader_.load_block_into_cache(new_index_cache_, new_block_cache_, 
                                                  table_id, column_group_id, 
                                                  start_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret);
        ret = cache_reader_.get_start_key_of_next_block(old_block_cache_, table_id, 
                                                        column_group_id, end_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret);
        ret = cache_loader_.load_block_into_cache(new_index_cache_, new_block_cache_, 
                                                  table_id, column_group_id, 
                                                  end_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret);
        ret = cache_reader_.get_start_key_of_next_block(old_block_cache_, table_id, 
                                                        column_group_id, end_key, &reader_);
        ASSERT_EQ(OB_ITER_END, ret);
      }

      TEST_F(TestObBlockCacheReaderLoader, test_block_cache_loader_twice)
      {
        int ret;
        uint64_t table_id = 100;
        uint64_t column_group_id = 0;

        ObString start_key = cell_infos[0][0].row_key_;

        ret = cache_loader_.load_block_into_cache(old_index_cache_, old_block_cache_, 
                                                  table_id, column_group_id, 
                                                  start_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret);
        ret = cache_loader_.load_block_into_cache(old_index_cache_, old_block_cache_, 
                                                  table_id, column_group_id, 
                                                  start_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret);

        ret = cache_reader_.get_start_key_of_next_block(old_block_cache_, table_id, 
                                                        column_group_id, start_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret);
        ret = cache_loader_.load_block_into_cache(new_index_cache_, new_block_cache_, 
                                                  table_id, column_group_id, 
                                                  start_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret);
        ret = cache_reader_.get_start_key_of_next_block(old_block_cache_, table_id, 
                                                        column_group_id, start_key, &reader_);
        ASSERT_EQ(OB_ITER_END, ret);
      }

      TEST_F(TestObBlockCacheReaderLoader, test_block_cache_switch)
      {
        int ret;
        uint64_t table_id = 100;
        uint64_t column_group_id = 0;

        ObString start_key = cell_infos[0][0].row_key_;
        ObString end_key = cell_infos[ROW_NUM - 1][0].row_key_;

        ret = cache_loader_.load_block_into_cache(old_index_cache_, old_block_cache_, 
                                                  table_id, column_group_id, 
                                                  start_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret);
        ret = cache_loader_.load_block_into_cache(old_index_cache_, old_block_cache_, 
                                                  table_id, column_group_id, 
                                                  end_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret);

        ret = cache_reader_.get_start_key_of_next_block(old_block_cache_, table_id, 
                                                        column_group_id, start_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret);
        ret = cache_loader_.load_block_into_cache(new_index_cache_, new_block_cache_, 
                                                  table_id, column_group_id, 
                                                  start_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret);
        ret = cache_reader_.get_start_key_of_next_block(old_block_cache_, table_id, 
                                                        column_group_id, end_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret);
        ret = cache_loader_.load_block_into_cache(new_index_cache_, new_block_cache_, 
                                                  table_id, column_group_id, 
                                                  end_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret); 
        ret = cache_reader_.get_start_key_of_next_block(old_block_cache_, table_id, 
                                                        column_group_id, end_key, &reader_);
        ASSERT_EQ(OB_ITER_END, ret);
        
        ret = cache_utility_.destroy_cache(old_block_cache_, old_index_cache_);
        ASSERT_EQ(OB_SUCCESS, ret); 
        ObBlockCacheConf conf;
        init_conf(conf);
        old_block_cache_.set_fileinfo_cache(fic);
        ret = old_block_cache_.init(conf);
        EXPECT_EQ(OB_SUCCESS, ret);  
        ObBlockIndexCacheConf bic_conf = {16 * 1024 * 1024};  
        old_index_cache_.set_fileinfo_cache(fic);    
        ret = old_index_cache_.init(bic_conf);
        EXPECT_EQ(OB_SUCCESS, ret);

        ret = cache_reader_.get_start_key_of_next_block(new_block_cache_, table_id, 
                                                        column_group_id, start_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret);
        ret = cache_loader_.load_block_into_cache(old_index_cache_, old_block_cache_, 
                                                  table_id, column_group_id, 
                                                  start_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret);
        ret = cache_reader_.get_start_key_of_next_block(new_block_cache_, table_id, 
                                                        column_group_id, end_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret);
        ret = cache_loader_.load_block_into_cache(old_index_cache_, old_block_cache_, 
                                                  table_id, column_group_id, 
                                                  end_key, &reader_);
        ASSERT_EQ(OB_SUCCESS, ret); 
        ret = cache_reader_.get_start_key_of_next_block(old_block_cache_, table_id, 
                                                        column_group_id, end_key, &reader_);
        ASSERT_EQ(OB_ITER_END, ret);
      }

      TEST_F(TestObBlockCacheReaderLoader, test_block_cache_load_one_file)
      {
        int ret;
        uint64_t table_id = 100;
        uint64_t column_group_id = 0;
        uint64_t column_group_id2 = 2;
        ObString row_key;

        for (int i = 0; i < ROW_NUM; i++)
        {
          row_key = cell_infos[i][0].row_key_;
          ret = cache_loader_.load_block_into_cache(old_index_cache_, old_block_cache_, 
                                                    table_id, column_group_id, 
                                                    row_key, &reader_);
          ASSERT_EQ(OB_SUCCESS, ret);
          ret = cache_loader_.load_block_into_cache(old_index_cache_, old_block_cache_, 
                                                    table_id, column_group_id2, 
                                                    row_key, &reader_);
          ASSERT_EQ(OB_SUCCESS, ret);
        }

        for (int i = 0; i < ROW_NUM; i++)
        {
          ret = cache_reader_.get_start_key_of_next_block(old_block_cache_, table_id, 
                                                          column_group_id, row_key, &reader_);
          if (OB_ITER_END == ret)
          {
            break;
          }
          else
          {
            ASSERT_EQ(OB_SUCCESS, ret);
          }
          ret = cache_loader_.load_block_into_cache(new_index_cache_, new_block_cache_, 
                                                    table_id, column_group_id, 
                                                    row_key, &reader_);
          ASSERT_EQ(OB_SUCCESS, ret);
        }
      }

    }//end namespace common
        static int init_sstable(ObSSTableReader& sstable, const ObCellInfo** cell_infos,
            const int64_t row_num, const int64_t col_num, const int64_t sst_id = 0L)
        {
          int err = OB_SUCCESS;
  
          ObSSTableSchema sstable_schema;
          ObSSTableSchemaColumnDef column_def;
  
          EXPECT_TRUE(NULL != cell_infos);
          EXPECT_TRUE(row_num > 0);
          EXPECT_TRUE(col_num > 0);

          uint64_t table_id = cell_infos[0][0].table_id_;
          ObString path;
          int64_t sstable_file_id = 0;
          ObString compress_name;
          char* path_str = sstable_file_path;
          int64_t path_len = OB_MAX_FILE_NAME_LENGTH;

          for (int64_t i = 0; i < col_num; ++i)
          {
            column_def.reserved_ = 0;
            if (i >=2)
            {
              column_def.column_group_id_= 2;
            }
            else
            {
              column_def.column_group_id_= 0;
            }
            column_def.column_name_id_ = cell_infos[0][i].column_id_;
            column_def.column_value_type_ = cell_infos[0][i].value_.get_type();
            column_def.table_id_ = table_id;
            sstable_schema.add_column_def(column_def);
          }
  
          if (0 == sst_id)
          {
            sstable_file_id = 100;
          }
          else
          {
            sstable_file_id = sst_id;
          }
  
          ObSSTableId sstable_id(sst_id);
          get_sstable_path(sstable_id, path_str, path_len);
          char cmd[256];
          sprintf(cmd, "mkdir -p %s", path_str);
          system(cmd);
          path.assign((char*)path_str, strlen(path_str));
          compress_name.assign("lzo_1.0", strlen("lzo_1.0"));
          remove(path.ptr());

          ObSSTableWriter writer;
          err = writer.create_sstable(sstable_schema, path, compress_name, 0);
          EXPECT_EQ(OB_SUCCESS, err);
  
          for (int64_t i = 0; i < row_num; ++i)
          {
            ObSSTableRow row;
            row.set_table_id(table_id);
            row.set_column_group_id(0);
            err = row.set_row_key(cell_infos[i][0].row_key_);
            EXPECT_EQ(OB_SUCCESS, err);
            for (int64_t j = 0; j < 2; ++j)
            {
              err = row.add_obj(cell_infos[i][j].value_);
              EXPECT_EQ(OB_SUCCESS, err);
            }
  
            int64_t space_usage = 0;
            err = writer.append_row(row, space_usage);
            EXPECT_EQ(OB_SUCCESS, err);
          }

          for (int64_t i = 0; i < row_num; ++i)
          {
            ObSSTableRow row;
            row.set_table_id(table_id);
            row.set_column_group_id(2);
            err = row.set_row_key(cell_infos[i][0].row_key_);
            EXPECT_EQ(OB_SUCCESS, err);
            for (int64_t j = 2; j < col_num; ++j)
            {
              err = row.add_obj(cell_infos[i][j].value_);
              EXPECT_EQ(OB_SUCCESS, err);
            }
  
            int64_t space_usage = 0;
            err = writer.append_row(row, space_usage);
            EXPECT_EQ(OB_SUCCESS, err);
          }
  
          int64_t offset = 0;
          err = writer.close_sstable(offset);
          EXPECT_EQ(OB_SUCCESS, err);
  
          err = fic.init(1024);
          EXPECT_EQ(OB_SUCCESS, err);

          err = reader_.open(sstable_id);
          EXPECT_EQ(OB_SUCCESS, err);
          EXPECT_TRUE(reader_.is_opened());
  
          return err;
        }
TEST(ObMultiVersionTabletImage, test_upgrade)
{
  FileInfoCache fic;
  ObMultiVersionTabletImage image(fic);
  fic.init(100);

  CharArena allocator;
  ObRange r1,r2,r3;
  create_range(allocator, r1, 1, ObBorderFlag::INCLUSIVE_START|ObBorderFlag::INCLUSIVE_END, "aoo", "foo");
  create_range(allocator, r2, 1, ObBorderFlag::INCLUSIVE_END, "foo", "mj");
  create_range(allocator, r3, 1, ObBorderFlag::INCLUSIVE_END, "mj", "oi");

  int ret = read_all(image);
  ASSERT_EQ(0, ret);

  int disk_no = 0;
  ObTablet *tablet= NULL;

  ret = image.remove_tablet(r1, VERSION_2, disk_no);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(1, disk_no);

  ret = image.acquire_tablet(r1, ObMultiVersionTabletImage::SCAN_FORWARD, VERSION_1, tablet);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(true, tablet->get_range().equal(r1));
  ASSERT_EQ(VERSION_1, tablet->get_data_version());
  ret = image.release_tablet(tablet);
  ASSERT_EQ(0, ret);

  // get tablet version1 r1 for merge
  int num = 2;
  ObTablet *tablets[num];
  ret = image.get_tablets_for_merge(VERSION_2, num, tablets);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(1, num);
  tablet = tablets[0];
  ASSERT_EQ(VERSION_1, tablet->get_data_version());
  ASSERT_EQ(true, tablet->get_range().equal(r1));
  ret = image.release_tablet(tablet);

  // upgrade r1 v1 to r1 v2
  ObTablet *new_tablet = NULL;
  ret = image.alloc_tablet_object(r1, VERSION_2, new_tablet);
  ASSERT_EQ(0, ret);
  new_tablet->set_disk_no(2);
  ObSSTableId id;
  id.sstable_file_id_ = 15 << 8 | 2;
  id.sstable_file_offset_ = 0;
  ret = new_tablet->add_sstable_by_id(id);
  ASSERT_EQ(0, ret);
  ret = image.upgrade_tablet(tablet, new_tablet, false);
  ASSERT_EQ(0, ret);

  ret = image.upgrade_service();
  ASSERT_EQ(0, ret);

  // query r1 v2
  ret = image.acquire_tablet(r1, ObMultiVersionTabletImage::SCAN_FORWARD, 0, tablet);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(true, tablet->get_range().equal(r1));
  ASSERT_EQ(VERSION_2, tablet->get_data_version());
  ret = image.release_tablet(tablet);
  ASSERT_EQ(0, ret);


  // query tablets for merge, should be null
  ret = image.get_tablets_for_merge(VERSION_2, num, tablets);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(0, num);


  // query tablets v2 for merge to v3
  num = 2;
  ret = image.get_tablets_for_merge(VERSION_3, num, tablets);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(2, num);
  tablet = tablets[0];
  ret = image.alloc_tablet_object(tablet->get_range(), VERSION_3, new_tablet);
  ASSERT_EQ(0, ret);
  new_tablet->set_disk_no(10);
  id.sstable_file_id_ = 15 << 8 | 10;
  id.sstable_file_offset_ = 0;
  ret = new_tablet->add_sstable_by_id(id);
  ASSERT_EQ(0, ret);
  ret = image.upgrade_tablet(tablet, new_tablet, false);
  ASSERT_EQ(0, ret);
  for (int i = 0; i < num; ++i)
  {
    image.release_tablet(tablets[i]);
  }

  ret = image.upgrade_service();
  // query v3 
  ret = image.acquire_tablet(r1, ObMultiVersionTabletImage::SCAN_FORWARD, 0, tablet);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(VERSION_3, tablet->get_data_version());
  image.release_tablet(tablet);

  fic.destroy();
}
TEST(ObMultiVersionTabletImage, test_query)
{
  FileInfoCache fic;
  ObMultiVersionTabletImage image(fic);
  fic.init(100);

  CharArena allocator;
  ObRange r1,r2,r3;
  create_range(allocator, r1, 1, ObBorderFlag::INCLUSIVE_START|ObBorderFlag::INCLUSIVE_END, "aoo", "foo");
  create_range(allocator, r2, 1, ObBorderFlag::INCLUSIVE_END, "foo", "mj");
  create_range(allocator, r3, 1, ObBorderFlag::INCLUSIVE_END, "mj", "oi");

  int ret = read_all(image);
  ASSERT_EQ(0, ret);
  image.dump();


  ObTablet *tablet = NULL;
  ret = image.acquire_tablet(r2, ObMultiVersionTabletImage::SCAN_FORWARD, 0, tablet);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(true, tablet->get_range().equal(r2));
  ret = image.release_tablet(tablet);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(VERSION_2, tablet->get_data_version());

  ret = image.acquire_tablet(r1, ObMultiVersionTabletImage::SCAN_FORWARD, 0, tablet);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(true, tablet->get_range().equal(r1));
  ret = image.release_tablet(tablet);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(VERSION_1, tablet->get_data_version());

  ret = image.acquire_tablet(r1, ObMultiVersionTabletImage::SCAN_FORWARD, VERSION_1, tablet);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(true, tablet->get_range().equal(r1));
  ret = image.release_tablet(tablet);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(VERSION_1, tablet->get_data_version());

  ObRange query_whole_range;
  query_whole_range.table_id_ = 1;
  query_whole_range.border_flag_.set_min_value();
  query_whole_range.border_flag_.set_max_value();
  ret = image.acquire_tablet(query_whole_range,  ObMultiVersionTabletImage::SCAN_FORWARD, VERSION_1, tablet);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(true, tablet->get_range().equal(r1));
  ret = image.release_tablet(tablet);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(VERSION_1, tablet->get_data_version());

  ret = image.acquire_tablet_all_version(query_whole_range, ObMultiVersionTabletImage::SCAN_BACKWARD, 
      ObMultiVersionTabletImage::FROM_NEWEST_INDEX, VERSION_2, tablet);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(true, tablet->get_range().equal(r3));
  ret = image.release_tablet(tablet);
  ASSERT_EQ(0, ret);

  ret = image.acquire_tablet(query_whole_range, ObMultiVersionTabletImage::SCAN_BACKWARD, VERSION_1, tablet);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(true, tablet->get_range().equal(r1));
  ret = image.release_tablet(tablet);
  ASSERT_EQ(0, ret);

  ObRange r4;
  create_range(allocator, r4, 1, ObBorderFlag::INCLUSIVE_START|ObBorderFlag::INCLUSIVE_END, "foo", "koo");
  ret = image.acquire_tablet_all_version(r4, ObMultiVersionTabletImage::SCAN_FORWARD, 
      ObMultiVersionTabletImage::FROM_NEWEST_INDEX, 0, tablet);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(true, tablet->get_range().equal(r1));
  ASSERT_EQ(VERSION_2, tablet->get_data_version());
  ret = image.release_tablet(tablet);
  ASSERT_EQ(0, ret);

  create_range(allocator, r4, 1, ObBorderFlag::INCLUSIVE_START|ObBorderFlag::INCLUSIVE_END, "foz", "noo");
  ret = image.acquire_tablet(r4,  ObMultiVersionTabletImage::SCAN_FORWARD,0, tablet);
  ASSERT_EQ(0, ret);
  ASSERT_EQ(true, tablet->get_range().equal(r2));
  ASSERT_EQ(VERSION_2, tablet->get_data_version());
  ret = image.release_tablet(tablet);
  ASSERT_EQ(0, ret);

  fic.destroy();
}
 static void TearDownTestCase()
 {
   fic.destroy();
 }