246 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			246 lines
		
	
	
		
			8.0 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 <gtest/gtest.h>
 | 
						|
#include "lib/utility/ob_test_util.h"
 | 
						|
#include "lib/restore/ob_storage.h"
 | 
						|
#include "lib/allocator/page_arena.h"
 | 
						|
#include "share/backup/ob_backup_io_adapter.h"
 | 
						|
#include "common/storage/ob_fd_simulator.h"
 | 
						|
#define private public
 | 
						|
#include "share/ob_device_manager.h"
 | 
						|
#undef private
 | 
						|
 | 
						|
using namespace oceanbase::common;
 | 
						|
 | 
						|
//test fd simulator
 | 
						|
class TestFdSimulator: public ::testing::Test
 | 
						|
{
 | 
						|
public:
 | 
						|
  TestFdSimulator() {}
 | 
						|
  virtual ~TestFdSimulator(){}
 | 
						|
  virtual void SetUp()
 | 
						|
  {
 | 
						|
  }
 | 
						|
  virtual void TearDown()
 | 
						|
  {
 | 
						|
  }
 | 
						|
  static void SetUpTestCase()
 | 
						|
  {
 | 
						|
  }
 | 
						|
  static void TearDownTestCase()
 | 
						|
  {
 | 
						|
  }
 | 
						|
private:
 | 
						|
  // disallow copy
 | 
						|
  DISALLOW_COPY_AND_ASSIGN(TestFdSimulator);
 | 
						|
};
 | 
						|
 | 
						|
TEST_F(TestFdSimulator, test_fd)
 | 
						|
{
 | 
						|
  ObFdSimulator fd_sim;
 | 
						|
  ASSERT_EQ(OB_SUCCESS, fd_sim.init());
 | 
						|
  int device_type = 0;
 | 
						|
  int device_flag = 0;
 | 
						|
  oceanbase::common::ObArenaAllocator allocator;
 | 
						|
  void* ctx = NULL;
 | 
						|
  int test_total_num = 200;
 | 
						|
  int test_1_num = 90; //<100
 | 
						|
  int test_2_num = 30; //90-110
 | 
						|
  int test_3_num = 80; //200
 | 
						|
  int used_fd_cnt = 0;
 | 
						|
  int free_fd_cnt = 0;
 | 
						|
  int expect_used_fd_cnt = 0;
 | 
						|
  int expect_free_fd_cnt = 0;
 | 
						|
 | 
						|
  int tmp_device_type = 0;
 | 
						|
  int tmp_device_flag = 0;
 | 
						|
  void* tmp_ctx = NULL;
 | 
						|
  //init fds
 | 
						|
  ObIOFd* fds = static_cast<ObIOFd*>(allocator.alloc(sizeof(ObIOFd)*test_total_num));
 | 
						|
 | 
						|
  for(int i =0; i<test_total_num;i++) {
 | 
						|
    new(fds+i)ObIOFd();
 | 
						|
  }
 | 
						|
  //get fd from simulator
 | 
						|
  ASSERT_TRUE(NULL != fds);
 | 
						|
  ctx = fds;
 | 
						|
  for (int i = 0; i < test_1_num + test_2_num; i++) {
 | 
						|
    device_type = i % 5; 
 | 
						|
    device_flag = i % 2;
 | 
						|
    ASSERT_EQ(OB_SUCCESS, fd_sim.get_fd(ctx, device_type, device_flag, fds[i]));
 | 
						|
    ObFdSimulator::get_fd_device_type(fds[i], tmp_device_type);
 | 
						|
    ObFdSimulator::get_fd_flag(fds[i], tmp_device_flag);
 | 
						|
    ASSERT_EQ(tmp_device_type, device_type);
 | 
						|
    ASSERT_EQ(tmp_device_flag, device_flag);
 | 
						|
    fd_sim.get_fd_stat(used_fd_cnt, free_fd_cnt);
 | 
						|
    ASSERT_EQ(i + 1, used_fd_cnt);
 | 
						|
    if (i < ObFdSimulator::DEFAULT_ARRAY_SIZE) {
 | 
						|
      ASSERT_EQ(free_fd_cnt, ObFdSimulator::DEFAULT_ARRAY_SIZE - used_fd_cnt);
 | 
						|
    } else {
 | 
						|
      ASSERT_EQ(free_fd_cnt, 2*ObFdSimulator::DEFAULT_ARRAY_SIZE - used_fd_cnt);
 | 
						|
    }
 | 
						|
    fd_sim.fd_to_ctx(fds[i], tmp_ctx);
 | 
						|
    ASSERT_EQ(tmp_ctx, ctx);
 | 
						|
  } 
 | 
						|
  //release some fd(relase the fd which fd_id %3 == 0)
 | 
						|
  for (int i = 0; i < test_1_num + test_2_num; i++) {
 | 
						|
    if (i % 3 == 0) {
 | 
						|
      ASSERT_EQ(OB_SUCCESS, fd_sim.release_fd(fds[i]));
 | 
						|
      ASSERT_EQ(OB_NOT_INIT, fd_sim.release_fd(fds[i]));
 | 
						|
    }
 | 
						|
  }
 | 
						|
  fd_sim.get_fd_stat(used_fd_cnt, free_fd_cnt);
 | 
						|
  expect_used_fd_cnt = (test_1_num + test_2_num)*2/3;
 | 
						|
  ASSERT_EQ(expect_used_fd_cnt, used_fd_cnt);
 | 
						|
  ASSERT_EQ(free_fd_cnt, 2*ObFdSimulator::DEFAULT_ARRAY_SIZE - expect_used_fd_cnt);
 | 
						|
 | 
						|
  //get fd, util fd num is 200, check the fd
 | 
						|
  for (int i = 0; i < test_1_num + test_2_num; i++) {
 | 
						|
    if (i % 3 == 0) {
 | 
						|
      ASSERT_EQ(OB_SUCCESS, fd_sim.get_fd(ctx, device_type, device_flag, fds[i]));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  for (int i = test_1_num + test_2_num; i < test_1_num + test_2_num + test_3_num; i++) {
 | 
						|
    ASSERT_EQ(OB_SUCCESS, fd_sim.get_fd(ctx, device_type, device_flag, fds[i]));
 | 
						|
  }
 | 
						|
  fd_sim.get_fd_stat(used_fd_cnt, free_fd_cnt);
 | 
						|
  ASSERT_EQ(used_fd_cnt, test_1_num + test_2_num + test_3_num);
 | 
						|
  ASSERT_EQ(free_fd_cnt, 0);
 | 
						|
 | 
						|
  //release all the fd
 | 
						|
  for (int i = 0; i < test_1_num + test_2_num + test_3_num; i++) {
 | 
						|
    ASSERT_EQ(OB_SUCCESS, fd_sim.release_fd(fds[i]));
 | 
						|
    ASSERT_EQ(OB_NOT_INIT, fd_sim.release_fd(fds[i]));
 | 
						|
  }
 | 
						|
  fd_sim.get_fd_stat(used_fd_cnt, free_fd_cnt);
 | 
						|
  ASSERT_EQ(free_fd_cnt, test_1_num + test_2_num + test_3_num);
 | 
						|
  ASSERT_EQ(used_fd_cnt, 0);
 | 
						|
}
 | 
						|
 | 
						|
//test fd simulator
 | 
						|
class TestDeviceManager: public ::testing::Test
 | 
						|
{
 | 
						|
public:
 | 
						|
  TestDeviceManager() {
 | 
						|
  }
 | 
						|
  virtual ~TestDeviceManager(){}
 | 
						|
  virtual void SetUp()
 | 
						|
  {
 | 
						|
  }
 | 
						|
  virtual void TearDown()
 | 
						|
  {
 | 
						|
  }
 | 
						|
  static void SetUpTestCase()
 | 
						|
  {
 | 
						|
  }
 | 
						|
  static void TearDownTestCase()
 | 
						|
  {
 | 
						|
  }
 | 
						|
protected:
 | 
						|
  // disallow copy
 | 
						|
private:
 | 
						|
  DISALLOW_COPY_AND_ASSIGN(TestDeviceManager);
 | 
						|
};
 | 
						|
 | 
						|
TEST_F(TestDeviceManager, test_device_manager)
 | 
						|
{
 | 
						|
  ObDeviceManager &manager = ObDeviceManager::get_instance();
 | 
						|
  int max_dev_num = 20;
 | 
						|
  ObIODevice* device_handle[2*max_dev_num];
 | 
						|
  char storage_info_buf[OB_MAX_URI_LENGTH];
 | 
						|
  ObString storage_info_local(OB_LOCAL_PREFIX);
 | 
						|
  manager.destroy();
 | 
						|
  
 | 
						|
  int32_t device_num = 0;
 | 
						|
  int32_t device_map_cnt = 0;
 | 
						|
  ObIODevice* tmp_dev_handle = NULL;
 | 
						|
  MEMSET(device_handle, 0 , sizeof(ObIODevice*)*2*max_dev_num);
 | 
						|
 | 
						|
  //all the device is same
 | 
						|
  for (int i = 0; i < max_dev_num; i++ ) {
 | 
						|
    ASSERT_EQ(OB_SUCCESS, manager.get_device(storage_info_local, storage_info_local, device_handle[i]));
 | 
						|
    if (0 != i) {
 | 
						|
      ASSERT_EQ(tmp_dev_handle, device_handle[i]);
 | 
						|
    } else {
 | 
						|
      tmp_dev_handle = device_handle[i];
 | 
						|
    }
 | 
						|
  }
 | 
						|
  device_num = manager.get_device_cnt();
 | 
						|
  ASSERT_EQ(1, device_num);
 | 
						|
  //release all the device
 | 
						|
  for (int i = 0; i < max_dev_num; i++) {
 | 
						|
    ASSERT_EQ(OB_SUCCESS, manager.release_device(device_handle[i]));
 | 
						|
  }
 | 
						|
  device_num = manager.get_device_cnt();
 | 
						|
  ASSERT_EQ(1, device_num); //since we do not release automatic
 | 
						|
 | 
						|
  //MAX_DEVICE_INSTANCE different deivce
 | 
						|
  for (int i = 0; i < max_dev_num; i++ ) {
 | 
						|
    ASSERT_EQ(OB_SUCCESS, databuff_printf(storage_info_buf, sizeof(storage_info_buf), 
 | 
						|
                  "%s_%d", OB_LOCAL_PREFIX, i));
 | 
						|
    ObString storage_info(storage_info_buf);
 | 
						|
    ASSERT_EQ(OB_SUCCESS, manager.get_device(storage_info, storage_info, device_handle[i]));
 | 
						|
    //all the device is not same 
 | 
						|
    if (NULL != tmp_dev_handle) {
 | 
						|
      ASSERT_TRUE(device_handle[i] != tmp_dev_handle);
 | 
						|
    }
 | 
						|
    tmp_dev_handle = device_handle[i];
 | 
						|
  }
 | 
						|
  device_num = manager.get_device_cnt();
 | 
						|
  ASSERT_EQ(max_dev_num, device_num);
 | 
						|
   
 | 
						|
  ObString storage_info_tmp("local://_x");
 | 
						|
  //exceed MAX_DEVICE_INSTANCE device, should fail
 | 
						|
  ASSERT_EQ(OB_OUT_OF_ELEMENT, manager.get_device(storage_info_tmp, storage_info_tmp, tmp_dev_handle));
 | 
						|
  //release some and get again, should suc(this device ref should be 0)
 | 
						|
  ASSERT_EQ(OB_SUCCESS, manager.release_device(device_handle[0]));
 | 
						|
  //get this device again
 | 
						|
  ASSERT_EQ(OB_SUCCESS, manager.get_device("local://_0", "local://_0", device_handle[0]));
 | 
						|
  //copy device handle, test double release scenario
 | 
						|
  tmp_dev_handle = device_handle[0];
 | 
						|
  ASSERT_EQ(OB_SUCCESS, manager.release_device(device_handle[0]));
 | 
						|
  //double release scenario, since the ref is 0, can not release again
 | 
						|
  ASSERT_EQ(OB_INVALID_ARGUMENT, manager.release_device(tmp_dev_handle));
 | 
						|
  //the device handle has been reset, so will be a null pointer error
 | 
						|
  ASSERT_EQ(OB_INVALID_ARGUMENT, manager.release_device(device_handle[0]));               
 | 
						|
  ASSERT_EQ(OB_SUCCESS, manager.get_device(storage_info_tmp, storage_info_tmp, device_handle[0]));
 | 
						|
  device_num = manager.get_device_cnt();
 | 
						|
  ASSERT_EQ(max_dev_num, device_num);
 | 
						|
  manager.destroy();
 | 
						|
  device_num = manager.get_device_cnt();
 | 
						|
  ASSERT_EQ(0, device_num);
 | 
						|
 | 
						|
  //get again
 | 
						|
  for (int i = 0; i < max_dev_num; i++ ) {
 | 
						|
    ObString storage_info("local://_x");
 | 
						|
    if ( i >= max_dev_num/2) {
 | 
						|
      ASSERT_EQ(OB_SUCCESS, databuff_printf(storage_info_buf, sizeof(storage_info_buf), 
 | 
						|
                  "%s_%d", OB_LOCAL_PREFIX, i));
 | 
						|
      storage_info.assign_ptr(storage_info_buf, strlen(storage_info_buf));
 | 
						|
    }
 | 
						|
    
 | 
						|
    ASSERT_EQ(OB_SUCCESS, manager.get_device(storage_info, storage_info, device_handle[i]));
 | 
						|
  }
 | 
						|
  device_num = manager.get_device_cnt();
 | 
						|
  ASSERT_EQ(max_dev_num/2 + 1, device_num);
 | 
						|
}
 | 
						|
 | 
						|
int main(int argc, char **argv)
 | 
						|
{
 | 
						|
  system("rm -f test_storage_device_manager.log");
 | 
						|
  OB_LOGGER.set_file_name("test_storage_device_manager.log");
 | 
						|
  OB_LOGGER.set_log_level("INFO");
 | 
						|
  ::testing::InitGoogleTest(&argc,argv);
 | 
						|
  return RUN_ALL_TESTS();
 | 
						|
} |