[Feature] Auto extend disk space
This commit is contained in:
		@ -805,6 +805,35 @@ int64_t ObLocalFileSystem::get_free_macro_block_count() const
 | 
			
		||||
  return store_file_.get_free_macro_block_count();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int64_t ObLocalFileSystem::get_total_macro_block_max_count() const
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  int64_t total_space = 0;
 | 
			
		||||
  int64_t free_space = 0;
 | 
			
		||||
  int64_t max_block_count = 0;
 | 
			
		||||
  int64_t max_block_size;
 | 
			
		||||
  int64_t datafile_size = GCONF.datafile_size;
 | 
			
		||||
  int64_t datafile_maxsize = GCONF.datafile_maxsize;
 | 
			
		||||
 | 
			
		||||
  if (OB_FAIL(FileDirectoryUtils::get_disk_space(sstable_dir_, total_space, free_space))) {
 | 
			
		||||
    STORAGE_LOG(WARN, "Failed to get disk space ", K(ret));
 | 
			
		||||
  } else if (datafile_size > 0 && data_file_size_ < datafile_maxsize ) {  
 | 
			
		||||
    // get total block count of ssblock file. Further more, if auto extend mode is on, 
 | 
			
		||||
    // and the disk is shared, the volume of disk will not fixed 
 | 
			
		||||
    int64_t actual_disk_max_size = data_file_size_ + free_space;
 | 
			
		||||
    actual_disk_max_size = actual_disk_max_size < datafile_maxsize ? 
 | 
			
		||||
      actual_disk_max_size : datafile_maxsize;
 | 
			
		||||
    max_block_size = lower_align(actual_disk_max_size, macro_block_size_);
 | 
			
		||||
  } else {
 | 
			
		||||
    max_block_size = lower_align(data_file_size_, macro_block_size_);   // cur total block cnt
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (OB_SUCC(ret)) {
 | 
			
		||||
    max_block_count = max_block_size / macro_block_size_;
 | 
			
		||||
  } 
 | 
			
		||||
  return max_block_count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObLocalFileSystem::get_marker_status(ObMacroBlockMarkerStatus& status)
 | 
			
		||||
{
 | 
			
		||||
  return store_file_.get_store_status(status);
 | 
			
		||||
@ -883,7 +912,8 @@ int ObLocalFileSystem::inner_get_super_block_version(const int64_t offset, int64
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObLocalFileSystem::resize_file(const int64_t new_data_file_size, const int64_t new_data_file_disk_percentage)
 | 
			
		||||
int ObLocalFileSystem::resize_file(
 | 
			
		||||
    const int64_t new_data_file_size, const int64_t new_data_file_disk_percentage, const int64_t extend_size)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  int64_t new_cal_data_file_size = new_data_file_size;
 | 
			
		||||
@ -891,9 +921,13 @@ int ObLocalFileSystem::resize_file(const int64_t new_data_file_size, const int64
 | 
			
		||||
  int64_t free_space = 0;
 | 
			
		||||
  if (OB_FAIL(FileDirectoryUtils::get_disk_space(sstable_dir_, total_space, free_space))) {
 | 
			
		||||
    STORAGE_LOG(WARN, "Failed to get disk space ", K(ret));
 | 
			
		||||
  } else if (extend_size > 0) { // auto extend disk size, extend_size default 0
 | 
			
		||||
    int64_t max_extend_size = free_space;
 | 
			
		||||
    max_extend_size = extend_size < max_extend_size ? extend_size : max_extend_size;
 | 
			
		||||
    new_cal_data_file_size = data_file_size_ + max_extend_size;
 | 
			
		||||
  } else if (new_cal_data_file_size <= 0) {
 | 
			
		||||
    new_cal_data_file_size = total_space * new_data_file_disk_percentage / 100;
 | 
			
		||||
  }
 | 
			
		||||
  } 
 | 
			
		||||
#ifdef ERRSIM
 | 
			
		||||
  if (OB_SUCC(ret)) {
 | 
			
		||||
    ret = E(EventTable::EN_RESIZE_PHYSICAL_FILE_FAILED) OB_SUCCESS;
 | 
			
		||||
@ -906,8 +940,11 @@ int ObLocalFileSystem::resize_file(const int64_t new_data_file_size, const int64
 | 
			
		||||
    const int64_t curr_aligned_file_size = lower_align(data_file_size_, macro_block_size_);
 | 
			
		||||
    const int64_t new_aligned_file_size = lower_align(new_cal_data_file_size, macro_block_size_);
 | 
			
		||||
    if (curr_aligned_file_size > new_aligned_file_size) {
 | 
			
		||||
      ret = OB_NOT_SUPPORTED;
 | 
			
		||||
      LOG_WARN("can not resize file to smaller", K(ret), K(curr_aligned_file_size), K(new_aligned_file_size));
 | 
			
		||||
      ret = OB_ERR_RESIZE_FILE_TO_SMALLER;
 | 
			
		||||
      LOG_WARN("can not resize file to smaller", 
 | 
			
		||||
        K(ret), 
 | 
			
		||||
        K(curr_aligned_file_size), 
 | 
			
		||||
        K(new_aligned_file_size));
 | 
			
		||||
    } else if (curr_aligned_file_size == new_aligned_file_size) {
 | 
			
		||||
      LOG_INFO("new file size is equal to current file size, do not need to resize file",
 | 
			
		||||
          K(curr_aligned_file_size),
 | 
			
		||||
@ -917,11 +954,16 @@ int ObLocalFileSystem::resize_file(const int64_t new_data_file_size, const int64
 | 
			
		||||
      const int64_t offset = curr_aligned_file_size;
 | 
			
		||||
      const int64_t delta_size = new_aligned_file_size - curr_aligned_file_size;
 | 
			
		||||
      if (0 != (sys_ret = ::fallocate(fd_.fd_, 0, offset, delta_size))) {
 | 
			
		||||
        LOG_WARN("fail to expand file size", K(ret), K(sys_ret), K(offset), K(delta_size), K(errno), KERRMSG);
 | 
			
		||||
        LOG_WARN("fail to expand file size", 
 | 
			
		||||
          K(ret), K(sys_ret), K(offset), K(delta_size), K(free_space), K(errno), KERRMSG);
 | 
			
		||||
      } else {
 | 
			
		||||
        data_file_size_ = new_cal_data_file_size;
 | 
			
		||||
        datafile_disk_percentage_ = new_data_file_disk_percentage;
 | 
			
		||||
        LOG_INFO("succeed to resize file", K(data_file_size_), K(datafile_disk_percentage_));
 | 
			
		||||
          data_file_size_ = new_cal_data_file_size;
 | 
			
		||||
          datafile_disk_percentage_ = new_data_file_disk_percentage;
 | 
			
		||||
          LOG_INFO("succeed to resize file", 
 | 
			
		||||
            K(extend_size), 
 | 
			
		||||
            K(delta_size),
 | 
			
		||||
            K(data_file_size_), 
 | 
			
		||||
            K(datafile_disk_percentage_));
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -111,7 +111,8 @@ public:
 | 
			
		||||
  virtual int get_marker_status(ObMacroBlockMarkerStatus& status) override;
 | 
			
		||||
  virtual int read_old_super_block(ObSuperBlockV2& super_block) override;
 | 
			
		||||
  virtual int get_super_block_version(int64_t& super_block_version) override;
 | 
			
		||||
  virtual int resize_file(const int64_t new_data_file_size, const int64_t new_data_file_disk_percentage) override;
 | 
			
		||||
  virtual int resize_file(const int64_t new_data_file_size, const int64_t new_data_file_disk_percentage, const int64_t extend_size = 0) override;
 | 
			
		||||
  virtual int64_t get_total_macro_block_max_count() const override;
 | 
			
		||||
 | 
			
		||||
  OB_INLINE int get_block_file_fd() const { return fd_.fd_; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -338,6 +338,23 @@ int ObMacroBlockHandleV1::set_macro_block_id(const MacroBlockId& macro_block_id)
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ---------------------------------------------------------ObStoreFileAutoExtendTask-----------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
ObStoreFileAutoExtendTask::ObStoreFileAutoExtendTask()
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
ObStoreFileAutoExtendTask::~ObStoreFileAutoExtendTask()
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
// TODO Before mini merge adjustment, create PG, which will be cored here
 | 
			
		||||
void ObStoreFileAutoExtendTask::runTimerTask()
 | 
			
		||||
{
 | 
			
		||||
   OB_STORE_FILE.ssblock_check_and_extend();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ---------------------------------------------------------ObStoreFileGCTask-----------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
@ -398,6 +415,7 @@ ObStoreFile::ObStoreFile()
 | 
			
		||||
      meta_array_lock_(),
 | 
			
		||||
      cur_meta_array_pos_(0),
 | 
			
		||||
      gc_task_(),
 | 
			
		||||
      ssblock_auto_extend_task_(),
 | 
			
		||||
      inspect_bad_block_task_(),
 | 
			
		||||
      print_buffer_(NULL),
 | 
			
		||||
      print_buffer_size_(ObLogger::MAX_LOG_SIZE - 100),
 | 
			
		||||
@ -408,9 +426,11 @@ ObStoreFile::ObStoreFile()
 | 
			
		||||
      store_file_system_(NULL),
 | 
			
		||||
      is_mark_sweep_enabled_(false),
 | 
			
		||||
      is_doing_mark_sweep_(false),
 | 
			
		||||
      is_doing_disk_extend_(false),
 | 
			
		||||
      cond_(),
 | 
			
		||||
      is_fs_support_punch_hole_(true),
 | 
			
		||||
      block_file_fd_(OB_INVALID_FD)
 | 
			
		||||
      block_file_fd_(OB_INVALID_FD),
 | 
			
		||||
      alloc_lock_()
 | 
			
		||||
{
 | 
			
		||||
  MEMSET(used_macro_cnt_, 0, sizeof(used_macro_cnt_));
 | 
			
		||||
}
 | 
			
		||||
@ -522,6 +542,10 @@ int ObStoreFile::open(const bool is_physical_flashback)
 | 
			
		||||
        STORAGE_LOG(WARN, "Fail to schedule gc task, ", K(ret));
 | 
			
		||||
      } else if (OB_FAIL(TG_SCHEDULE(lib::TGDefIDs::StoreFileGC, inspect_bad_block_task_, INSPECT_DELAY_US, true))) {
 | 
			
		||||
        STORAGE_LOG(WARN, "Fail to schedule bad_block_inspect task, ", K(ret));
 | 
			
		||||
      } else if (OB_FAIL(TG_START(lib::TGDefIDs::StoreFileAutoExtend))){
 | 
			
		||||
        STORAGE_LOG(WARN, "Fail to start StoreFileAutoExtend timer", K(ret));
 | 
			
		||||
      } else if (OB_FAIL(TG_SCHEDULE(lib::TGDefIDs::StoreFileAutoExtend, ssblock_auto_extend_task_, AUTOEXTEND_DELAY_US, true))) {
 | 
			
		||||
        STORAGE_LOG(WARN, "Fail to schedule StoreFileAutoExtend task", K(ret));
 | 
			
		||||
      } else {
 | 
			
		||||
        is_opened_ = true;
 | 
			
		||||
        if (is_replay_old) {
 | 
			
		||||
@ -555,6 +579,9 @@ void ObStoreFile::destroy()
 | 
			
		||||
  inspect_bad_block_task_.destroy();
 | 
			
		||||
  TG_STOP(lib::TGDefIDs::StoreFileGC);
 | 
			
		||||
  TG_WAIT(lib::TGDefIDs::StoreFileGC);
 | 
			
		||||
  TG_STOP(lib::TGDefIDs::StoreFileAutoExtend);
 | 
			
		||||
  TG_WAIT(lib::TGDefIDs::StoreFileAutoExtend);
 | 
			
		||||
 | 
			
		||||
  SLOGGER.destroy();
 | 
			
		||||
 | 
			
		||||
  lib::ObMutexGuard bad_block_guard(bad_block_lock_);
 | 
			
		||||
@ -584,6 +611,7 @@ void ObStoreFile::destroy()
 | 
			
		||||
  is_opened_ = false;
 | 
			
		||||
  is_mark_sweep_enabled_ = false;
 | 
			
		||||
  is_doing_mark_sweep_ = false;
 | 
			
		||||
  is_doing_disk_extend_ = false;
 | 
			
		||||
  cond_.destroy();
 | 
			
		||||
  is_fs_support_punch_hole_ = true;
 | 
			
		||||
  block_file_fd_ = OB_INVALID_FD;
 | 
			
		||||
@ -592,6 +620,7 @@ void ObStoreFile::destroy()
 | 
			
		||||
void ObStoreFile::stop()
 | 
			
		||||
{
 | 
			
		||||
  TG_STOP(lib::TGDefIDs::StoreFileGC);
 | 
			
		||||
  TG_STOP(lib::TGDefIDs::StoreFileAutoExtend);
 | 
			
		||||
  is_opened_ = false;
 | 
			
		||||
  STORAGE_LOG(INFO, "the store file gc task stopped");
 | 
			
		||||
}
 | 
			
		||||
@ -599,6 +628,7 @@ void ObStoreFile::stop()
 | 
			
		||||
void ObStoreFile::wait()
 | 
			
		||||
{
 | 
			
		||||
  TG_WAIT(lib::TGDefIDs::StoreFileGC);
 | 
			
		||||
  TG_WAIT(lib::TGDefIDs::StoreFileAutoExtend);
 | 
			
		||||
  STORAGE_LOG(INFO, "the store file finish wait");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -800,15 +830,33 @@ int ObStoreFile::check_disk_full(const int64_t required_size) const
 | 
			
		||||
    ret = OB_INVALID_ARGUMENT;
 | 
			
		||||
    STORAGE_LOG(WARN, "invalid args", K(ret), K(required_size));
 | 
			
		||||
  } else {
 | 
			
		||||
    int64_t calc_total_block_cnt = store_file_system_->get_total_macro_block_count();;
 | 
			
		||||
    int64_t calc_free_block_cnt = free_block_cnt_;
 | 
			
		||||
 | 
			
		||||
    // if auto disk extend is active, calc total block and free block cnt
 | 
			
		||||
    int64_t cur_total_data_file_size = store_file_system_->get_total_data_size();
 | 
			
		||||
    if (cur_total_data_file_size > 0 && 
 | 
			
		||||
        cur_total_data_file_size < GCONF.datafile_maxsize) { // if auto extend mode is on
 | 
			
		||||
      int64_t cur_total_block_cnt = store_file_system_->get_total_macro_block_count();
 | 
			
		||||
      calc_total_block_cnt = 
 | 
			
		||||
        store_file_system_->get_total_macro_block_max_count();
 | 
			
		||||
      calc_free_block_cnt = 
 | 
			
		||||
        calc_total_block_cnt - cur_total_block_cnt + free_block_cnt_;
 | 
			
		||||
    } 
 | 
			
		||||
    const int64_t required_count = required_size / store_file_system_->get_macro_block_size();
 | 
			
		||||
    const int64_t free_count = free_block_cnt_ - required_count;
 | 
			
		||||
    const int64_t used_percent = 100 - 100 * free_count / store_file_system_->get_total_macro_block_count();
 | 
			
		||||
    const int64_t free_count = calc_free_block_cnt - required_count;
 | 
			
		||||
    const int64_t used_percent = 100 - 100 * free_count / calc_total_block_cnt;
 | 
			
		||||
    if (GCONF.data_disk_usage_limit_percentage != NO_LIMIT_PERCENT &&
 | 
			
		||||
        used_percent >= GCONF.data_disk_usage_limit_percentage) {
 | 
			
		||||
      ret = OB_CS_OUTOF_DISK_SPACE;
 | 
			
		||||
      if (REACH_TIME_INTERVAL(24 * 3600LL * 1000 * 1000 /* 24h */)) {
 | 
			
		||||
        STORAGE_LOG(
 | 
			
		||||
            ERROR, "disk is almost full", K(ret), K(required_size), K(required_count), K(free_count), K(used_percent));
 | 
			
		||||
        STORAGE_LOG(ERROR, "disk is almost full", 
 | 
			
		||||
              K(ret), K(required_size), 
 | 
			
		||||
              K(required_count), 
 | 
			
		||||
              K(free_count), 
 | 
			
		||||
              K(used_percent),
 | 
			
		||||
              K(calc_free_block_cnt),
 | 
			
		||||
              K(calc_total_block_cnt));
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@ -950,6 +998,35 @@ int ObStoreFile::is_free_block(const int64_t block_index, bool& is_free)
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObStoreFile::auto_extend_file_size() 
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  if (OB_UNLIKELY(free_block_cnt_ > 0)) {
 | 
			
		||||
  } else if (OB_FAIL(extend_file_size_task())) {
 | 
			
		||||
    LOG_WARN("Fail to extend file size", K(ret));
 | 
			
		||||
  } else if (OB_FAIL(TG_SCHEDULE(lib::TGDefIDs::StoreFileGC, gc_task_, 0, false))) { 
 | 
			
		||||
    LOG_WARN("Fail to schedule gc task to mark and sweep", K(ret));
 | 
			
		||||
  } else {
 | 
			
		||||
    int64_t begin_time = ObTimeUtility::current_time();
 | 
			
		||||
    while (OB_SUCC(ret)) {
 | 
			
		||||
      // check free blocks after gc_task get started.
 | 
			
		||||
      // so if we cannot get free_block_cnt > 0 after extend_file_size_task,
 | 
			
		||||
      // we should do retry until free_block_cnt refresh already or timeout after 5s
 | 
			
		||||
      // to return failed. 
 | 
			
		||||
      if (free_block_cnt_ > 0) {
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      if (ObTimeUtility::current_time() - begin_time > MARK_BLOCK_INFO_TIMEOUT) {
 | 
			
		||||
        LOG_WARN("Timeout loop of waitting and getting free blocks", 
 | 
			
		||||
          K(free_block_cnt_));
 | 
			
		||||
        ret = OB_MARK_BLOCK_INFO_TIMEOUT;
 | 
			
		||||
      }
 | 
			
		||||
      usleep(50 * 1000); // 50ms
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObStoreFile::alloc_block(ObMacroBlockHandle& macro_handle)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
@ -957,16 +1034,21 @@ int ObStoreFile::alloc_block(ObMacroBlockHandle& macro_handle)
 | 
			
		||||
  macro_handle.reuse();
 | 
			
		||||
  const int64_t MAX_ALLOC_BLOCK_TRY_COUNT = 10;
 | 
			
		||||
 | 
			
		||||
  lib::ObMutexGuard guard(block_lock_);
 | 
			
		||||
  if (OB_UNLIKELY(free_block_cnt_ <= 0)) {
 | 
			
		||||
    ret = OB_CS_OUTOF_DISK_SPACE;
 | 
			
		||||
    STORAGE_LOG(ERROR,
 | 
			
		||||
        "Fail to alloc block, ",
 | 
			
		||||
  lib::ObMutexGuard guard(alloc_lock_); // lock free_block_cnt--
 | 
			
		||||
  if (OB_ISNULL(store_file_system_)) {
 | 
			
		||||
    ret = OB_INVALID_ARGUMENT;
 | 
			
		||||
    LOG_WARN("Fail to alloc block, null pointer", K(ret));
 | 
			
		||||
  } else if (OB_LIKELY(free_block_cnt_ > 0)) {
 | 
			
		||||
    // do nothing
 | 
			
		||||
  } else if (OB_FAIL(auto_extend_file_size())) {
 | 
			
		||||
    int64_t total_block_cnt = store_file_system_->get_total_macro_block_count();
 | 
			
		||||
    STORAGE_LOG(ERROR,"Fail to alloc block, ", 
 | 
			
		||||
        K(ret),
 | 
			
		||||
        K(free_block_cnt_),
 | 
			
		||||
        "total_count",
 | 
			
		||||
        store_file_system_->get_total_macro_block_count());
 | 
			
		||||
  } else {
 | 
			
		||||
        K(total_block_cnt));
 | 
			
		||||
  } 
 | 
			
		||||
  if (OB_SUCC(ret)) {
 | 
			
		||||
    lib::ObMutexGuard guard(block_lock_); // lock block
 | 
			
		||||
    bool is_alloc_succ = false;
 | 
			
		||||
    for (int64_t i = 0; OB_SUCC(ret) && !is_alloc_succ && i < MAX_ALLOC_BLOCK_TRY_COUNT && free_block_cnt_ > 0; ++i) {
 | 
			
		||||
      block_idx = free_block_array_[free_block_pop_pos_];
 | 
			
		||||
@ -983,21 +1065,10 @@ int ObStoreFile::alloc_block(ObMacroBlockHandle& macro_handle)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (OB_SUCC(ret)) {
 | 
			
		||||
      if (is_alloc_succ) {
 | 
			
		||||
      } else if (OB_UNLIKELY(free_block_cnt_ <= 0)) {
 | 
			
		||||
        ret = OB_CS_OUTOF_DISK_SPACE;
 | 
			
		||||
        STORAGE_LOG(ERROR,
 | 
			
		||||
            "Fail to alloc block, ",
 | 
			
		||||
            K(ret),
 | 
			
		||||
            K(free_block_cnt_),
 | 
			
		||||
            "total_count",
 | 
			
		||||
            store_file_system_->get_total_macro_block_count());
 | 
			
		||||
      } else {
 | 
			
		||||
        ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
        STORAGE_LOG(WARN, "Fail to alloc block", K(ret));
 | 
			
		||||
      }
 | 
			
		||||
    if (is_alloc_succ) {
 | 
			
		||||
    } else {
 | 
			
		||||
      ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
      STORAGE_LOG(WARN, "Fail to alloc block", K(ret));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
@ -1068,11 +1139,9 @@ int ObStoreFile::mark_macro_blocks()
 | 
			
		||||
  } else {
 | 
			
		||||
    // mark init
 | 
			
		||||
    MEMSET(macro_block_bitmap_, 0, (store_file_system_->get_total_macro_block_count() / 64 + 1) * sizeof(uint64_t));
 | 
			
		||||
 | 
			
		||||
    for (int64_t i = 0; i < ObStoreFileSystem::RESERVED_MACRO_BLOCK_INDEX && is_mark_sweep_enabled(); ++i) {
 | 
			
		||||
      bitmap_set(i);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // mark data block
 | 
			
		||||
    ObMacroBlockCommonHeader::MacroBlockType macro_type;
 | 
			
		||||
    used_macro_cnt_[ObMacroBlockCommonHeader::SSTableData] = 0;
 | 
			
		||||
@ -1097,7 +1166,6 @@ int ObStoreFile::mark_macro_blocks()
 | 
			
		||||
        STORAGE_LOG(ERROR, "Fail to iter data macro block ids, ", K(ret));
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // mark meta block
 | 
			
		||||
    if (OB_SUCC(ret)) {
 | 
			
		||||
      lib::ObMutexGuard guard(meta_array_lock_);
 | 
			
		||||
@ -1109,6 +1177,126 @@ int ObStoreFile::mark_macro_blocks()
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// should lock before using to protect free_block_cnt_ opt
 | 
			
		||||
int ObStoreFile::extend_file_size_task()
 | 
			
		||||
{
 | 
			
		||||
  lib::ObMutexGuard guard(block_lock_); // lock block info update opt 
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  if (OB_ISNULL(store_file_system_)) {
 | 
			
		||||
  } else {
 | 
			
		||||
    int64_t datafile_maxsize = GCONF.datafile_maxsize;
 | 
			
		||||
    int64_t datafile_size = GCONF.datafile_size;
 | 
			
		||||
    int64_t datafile_next = GCONF.datafile_next;
 | 
			
		||||
    if (OB_UNLIKELY(datafile_maxsize <= 0) ||
 | 
			
		||||
        OB_UNLIKELY(datafile_next <= 0) ||
 | 
			
		||||
        OB_UNLIKELY(datafile_size <= 0)) {
 | 
			
		||||
      LOG_DEBUG("Do not extend file size, datafile params not set", K(ret), 
 | 
			
		||||
        K(datafile_maxsize), 
 | 
			
		||||
        K(datafile_next), 
 | 
			
		||||
        K(datafile_size));
 | 
			
		||||
    } else if (datafile_maxsize <= datafile_size) {
 | 
			
		||||
      LOG_DEBUG("Do not extend file size, maxsize should bigger than datafile size", 
 | 
			
		||||
        K(ret), 
 | 
			
		||||
        K(datafile_maxsize), 
 | 
			
		||||
        K(datafile_size));
 | 
			
		||||
    } else {
 | 
			
		||||
      disable_mark_sweep(); // lock and wait mark_and_sweep block option done
 | 
			
		||||
      if (OB_FAIL(wait_mark_sweep_finish())) {
 | 
			
		||||
        LOG_WARN("fail to wait mark and sweep finish", K(ret));
 | 
			
		||||
      } else {
 | 
			
		||||
        bool is_extend_size = false;
 | 
			
		||||
        int64_t total_block_cnt = store_file_system_->get_total_macro_block_count();
 | 
			
		||||
        int64_t free_block_cnt_to_extend = 
 | 
			
		||||
          total_block_cnt - total_block_cnt * GCONF._datafile_usage_upper_bound_percentage / 100;
 | 
			
		||||
        // here we can see auto extend disk premise: 
 | 
			
		||||
        // 1. free_block_cnt ratio is less than one percentage (default 10%)
 | 
			
		||||
        // 2. free_block_cnt is less than one value (512 = 1G)
 | 
			
		||||
        if (free_block_cnt_to_extend < free_block_cnt_ && 
 | 
			
		||||
            (free_block_cnt_ > AUTO_EXTEND_LEAST_FREE_BLOCK_CNT)) {
 | 
			
		||||
          LOG_DEBUG("Do not extend file, not reach extend trigger.", 
 | 
			
		||||
            K(free_block_cnt_to_extend), 
 | 
			
		||||
            K(free_block_cnt_), 
 | 
			
		||||
            K(total_block_cnt));
 | 
			
		||||
        } else {
 | 
			
		||||
          is_extend_size = true;
 | 
			
		||||
          int64_t disk_in_use = total_block_cnt - free_block_cnt_;
 | 
			
		||||
          LOG_INFO("Auto extend, start to extend disk.", 
 | 
			
		||||
            K(free_block_cnt_to_extend), 
 | 
			
		||||
            K(free_block_cnt_), 
 | 
			
		||||
            K(total_block_cnt), 
 | 
			
		||||
            K(disk_in_use));
 | 
			
		||||
        }
 | 
			
		||||
        if (is_extend_size) {
 | 
			
		||||
          if (is_doing_disk_extend()) { // is_doing_disk_extend == true means there have not finish extend task yet, 
 | 
			
		||||
                                        // here DO NOT resize_file again!!!
 | 
			
		||||
            LOG_INFO("Do extend file, there has doing extend job, only need to mark free block.", 
 | 
			
		||||
              K(free_block_cnt_), 
 | 
			
		||||
              "total blocks,",
 | 
			
		||||
              store_file_system_->get_total_macro_block_count());
 | 
			
		||||
          } else {
 | 
			
		||||
            // calculate max extend size, max_extend_file maybe less than zero in the following situation:
 | 
			
		||||
            // 1. alter datafile_size as A, alter datafile_maxsize as B, and A < B
 | 
			
		||||
            // 2. auto extend to size to C ( A < C < B )
 | 
			
		||||
            // 3. alter datafile_maxsize as D ( A < D < C )
 | 
			
		||||
            int64_t cur_total_data_file_size = store_file_system_->get_total_data_size();
 | 
			
		||||
            int64_t max_extend_file = datafile_maxsize - cur_total_data_file_size; 
 | 
			
		||||
            // calc actual_extend_size, following the rules:
 | 
			
		||||
            // 1. if datafile_next less than 1G, actual_extend_size equal to min(1G, datafile_maxsize * 10%)
 | 
			
		||||
            // 2. if datafile_next large than 1G, actual_extend_size equal to min(datafile_next, max_extend_file)
 | 
			
		||||
            int64_t actual_extend_size;
 | 
			
		||||
            if (datafile_next < DATAFILE_NEXT_MIN) {
 | 
			
		||||
              int64_t min_extend_size = datafile_maxsize * 10 / 100;
 | 
			
		||||
              actual_extend_size = 
 | 
			
		||||
                min_extend_size < DATAFILE_NEXT_MIN ? min_extend_size : DATAFILE_NEXT_MIN;
 | 
			
		||||
              if (actual_extend_size > max_extend_file) { // take the smaller
 | 
			
		||||
                actual_extend_size = max_extend_file;
 | 
			
		||||
              }
 | 
			
		||||
            } else {
 | 
			
		||||
              actual_extend_size = 
 | 
			
		||||
                datafile_next < max_extend_file ? datafile_next : max_extend_file;
 | 
			
		||||
            }
 | 
			
		||||
            if (actual_extend_size <= 0) {
 | 
			
		||||
              ret = OB_CS_OUTOF_DISK_SPACE;
 | 
			
		||||
              LOG_DEBUG("No more disk space to extend, is full now", K(ret),
 | 
			
		||||
                K(datafile_maxsize),
 | 
			
		||||
                K(cur_total_data_file_size)); 
 | 
			
		||||
            } else if (OB_FAIL(store_file_system_->resize_file(0, 0, actual_extend_size))) {
 | 
			
		||||
              LOG_WARN("Extend file fail.", 
 | 
			
		||||
                K(actual_extend_size), 
 | 
			
		||||
                K(datafile_maxsize), 
 | 
			
		||||
                K(datafile_next));
 | 
			
		||||
            } else if (OB_FAIL(refresh_block_meta())){
 | 
			
		||||
              LOG_WARN("Extend file size fail, fresh block meta error", K(ret));
 | 
			
		||||
            } else {
 | 
			
		||||
              start_doing_disk_extend(); // set doing disk extend enable to skip auto extend check until mark_and_sweep done
 | 
			
		||||
              LOG_INFO("Extend file success.", 
 | 
			
		||||
                K(actual_extend_size), 
 | 
			
		||||
                K(store_file_system_->get_total_data_size()));
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      enable_mark_sweep(); // restart gc task 
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ObStoreFile::ssblock_check_and_extend()
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  if (OB_ISNULL(store_file_system_)) {
 | 
			
		||||
  } else if (is_doing_disk_extend()){ // avoid doing double extend task
 | 
			
		||||
    LOG_WARN("Extend file is doing now, skip this round.");
 | 
			
		||||
  } else {
 | 
			
		||||
    if (OB_FAIL(extend_file_size_task())) {
 | 
			
		||||
      LOG_WARN("Fail to extend file size", K(ret));
 | 
			
		||||
    } else {
 | 
			
		||||
      LOG_DEBUG("Success to extend file size");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ObStoreFile::mark_and_sweep()
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
@ -1168,11 +1356,19 @@ void ObStoreFile::mark_and_sweep()
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    // time 
 | 
			
		||||
    end_time = ObTimeUtility::current_time();
 | 
			
		||||
    sweep_cost_time_ = end_time - begin_time;
 | 
			
		||||
 | 
			
		||||
    // print buf
 | 
			
		||||
    hold_macro_cnt_ = hold_cnt;
 | 
			
		||||
    print_buffer_[print_pos] = '\0';
 | 
			
		||||
 | 
			
		||||
    // finish doing entire mark and sweep process
 | 
			
		||||
    // is_mark_sweep_enabled==true means mark and sweep process is not being broken yet
 | 
			
		||||
    if (is_mark_sweep_enabled()) { 
 | 
			
		||||
      finish_doing_disk_extend();
 | 
			
		||||
      STORAGE_LOG(INFO, "finish doing mark_and_sweep without suspend ");
 | 
			
		||||
    }
 | 
			
		||||
    STORAGE_LOG(INFO, "mark_and_sweep free blocks.", K(print_buffer_), K(free_cnt), K(hold_cnt));
 | 
			
		||||
    set_mark_sweep_done();
 | 
			
		||||
  }
 | 
			
		||||
@ -1278,97 +1474,121 @@ void ObStoreFile::set_mark_sweep_done()
 | 
			
		||||
  cond_.broadcast();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObStoreFile::resize_file(const int64_t new_data_file_size, const int64_t new_data_file_disk_percentage)
 | 
			
		||||
// should lock and then use
 | 
			
		||||
int ObStoreFile::refresh_block_meta() 
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  disable_mark_sweep();
 | 
			
		||||
  if (OB_ISNULL(store_file_system_)) {
 | 
			
		||||
    // do nothing
 | 
			
		||||
  } else if (OB_FAIL(wait_mark_sweep_finish())) {
 | 
			
		||||
    LOG_WARN("fail to wait mark and sweep finish", K(ret));
 | 
			
		||||
    LOG_DEBUG("Do resize file fail, store_file_system_ is null pointer");
 | 
			
		||||
  } else {
 | 
			
		||||
    lib::ObMutexGuard guard(block_lock_);
 | 
			
		||||
    if (OB_FAIL(store_file_system_->resize_file(new_data_file_size, new_data_file_disk_percentage))) {
 | 
			
		||||
      LOG_WARN("fail to resize file", K(ret));
 | 
			
		||||
    } else {
 | 
			
		||||
      const int64_t new_total_file_size =
 | 
			
		||||
          lower_align(store_file_system_->get_total_data_size(), store_file_system_->get_macro_block_size());
 | 
			
		||||
      const int64_t new_macro_block_cnt = new_total_file_size / store_file_system_->get_macro_block_size();
 | 
			
		||||
      const int64_t origin_macro_block_cnt = store_file_system_->get_total_macro_block_count();
 | 
			
		||||
      if (new_macro_block_cnt > origin_macro_block_cnt) {
 | 
			
		||||
        uint32_t* new_free_block_array = nullptr;
 | 
			
		||||
        uint64_t* new_macro_block_bitmap = nullptr;
 | 
			
		||||
        ObServerSuperBlock super_block = store_file_system_->get_server_super_block();
 | 
			
		||||
        super_block.content_.total_file_size_ = new_total_file_size;
 | 
			
		||||
        super_block.content_.total_macro_block_count_ = new_macro_block_cnt;
 | 
			
		||||
        super_block.content_.modify_timestamp_ = ObTimeUtility::current_time();
 | 
			
		||||
        ObStorageFile* file = OB_FILE_SYSTEM.get_server_root_handle().get_storage_file();
 | 
			
		||||
        if (OB_ISNULL(file)) {
 | 
			
		||||
          ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
          LOG_WARN("error unexpected, file must not be null", K(ret));
 | 
			
		||||
        } else if (OB_FAIL(alloc_memory(
 | 
			
		||||
                       new_macro_block_cnt, new_free_block_array, new_macro_block_bitmap, macro_block_info_))) {
 | 
			
		||||
          LOG_WARN("fail to alloc memory", K(ret), K(new_macro_block_cnt));
 | 
			
		||||
        } else if (OB_FAIL(file->write_super_block(super_block))) {
 | 
			
		||||
          LOG_WARN("fail to write super block", K(ret));
 | 
			
		||||
    const int64_t new_total_file_size =
 | 
			
		||||
      lower_align(store_file_system_->get_total_data_size(), store_file_system_->get_macro_block_size());
 | 
			
		||||
    const int64_t new_macro_block_cnt = new_total_file_size / store_file_system_->get_macro_block_size();
 | 
			
		||||
    const int64_t origin_macro_block_cnt = store_file_system_->get_total_macro_block_count();
 | 
			
		||||
    if (new_macro_block_cnt > origin_macro_block_cnt) {
 | 
			
		||||
      uint32_t* new_free_block_array = nullptr;
 | 
			
		||||
      uint64_t* new_macro_block_bitmap = nullptr;
 | 
			
		||||
      ObServerSuperBlock super_block = store_file_system_->get_server_super_block();
 | 
			
		||||
      super_block.content_.total_file_size_ = new_total_file_size;
 | 
			
		||||
      super_block.content_.total_macro_block_count_ = new_macro_block_cnt;
 | 
			
		||||
      super_block.content_.modify_timestamp_ = ObTimeUtility::current_time();
 | 
			
		||||
      ObStorageFile* file = OB_FILE_SYSTEM.get_server_root_handle().get_storage_file();
 | 
			
		||||
      if (OB_ISNULL(file)) {
 | 
			
		||||
        ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
        LOG_WARN("error unexpected, file must not be null", K(ret));
 | 
			
		||||
      } else if (OB_FAIL(alloc_memory(
 | 
			
		||||
                      new_macro_block_cnt, new_free_block_array, new_macro_block_bitmap, macro_block_info_))) {
 | 
			
		||||
        LOG_WARN("fail to alloc memory", K(ret), K(new_macro_block_cnt));
 | 
			
		||||
      } else if (OB_FAIL(file->write_super_block(super_block))) {
 | 
			
		||||
        LOG_WARN("fail to write super block", K(ret));
 | 
			
		||||
      } else {
 | 
			
		||||
        // copy free block info to new_free_block_array
 | 
			
		||||
        if (free_block_pop_pos_ > free_block_push_pos_) {
 | 
			
		||||
          MEMCPY(new_free_block_array,
 | 
			
		||||
              free_block_array_ + free_block_pop_pos_,
 | 
			
		||||
              (origin_macro_block_cnt - free_block_pop_pos_) * sizeof(uint32_t));
 | 
			
		||||
          MEMCPY(new_free_block_array + origin_macro_block_cnt - free_block_pop_pos_,
 | 
			
		||||
              free_block_array_,
 | 
			
		||||
              free_block_push_pos_ * sizeof(uint32_t));
 | 
			
		||||
        } else if (free_block_pop_pos_ < free_block_push_pos_) {
 | 
			
		||||
          MEMCPY(new_free_block_array,
 | 
			
		||||
              free_block_array_ + free_block_pop_pos_,
 | 
			
		||||
              (free_block_push_pos_ - free_block_pop_pos_) * sizeof(uint32_t));
 | 
			
		||||
        } else {
 | 
			
		||||
          // copy free block info to new_free_block_array
 | 
			
		||||
          if (free_block_pop_pos_ > free_block_push_pos_) {
 | 
			
		||||
            MEMCPY(new_free_block_array,
 | 
			
		||||
                free_block_array_ + free_block_pop_pos_,
 | 
			
		||||
                (origin_macro_block_cnt - free_block_pop_pos_) * sizeof(uint32_t));
 | 
			
		||||
            MEMCPY(new_free_block_array + origin_macro_block_cnt - free_block_pop_pos_,
 | 
			
		||||
                free_block_array_,
 | 
			
		||||
                free_block_push_pos_ * sizeof(uint32_t));
 | 
			
		||||
          } else if (free_block_pop_pos_ < free_block_push_pos_) {
 | 
			
		||||
            MEMCPY(new_free_block_array,
 | 
			
		||||
                free_block_array_ + free_block_pop_pos_,
 | 
			
		||||
                (free_block_push_pos_ - free_block_pop_pos_) * sizeof(uint32_t));
 | 
			
		||||
          } else {
 | 
			
		||||
            MEMCPY(new_free_block_array, free_block_array_, free_block_cnt_ * sizeof(uint32_t));
 | 
			
		||||
          }
 | 
			
		||||
          free_block_pop_pos_ = 0;
 | 
			
		||||
          free_block_push_pos_ = free_block_cnt_;
 | 
			
		||||
          MEMCPY(new_macro_block_bitmap,
 | 
			
		||||
              macro_block_bitmap_,
 | 
			
		||||
              get_macro_bitmap_array_cnt(origin_macro_block_cnt) * sizeof(uint64_t));
 | 
			
		||||
          allocator_.free(free_block_array_);
 | 
			
		||||
          allocator_.free(macro_block_bitmap_);
 | 
			
		||||
          free_block_array_ = new_free_block_array;
 | 
			
		||||
          macro_block_bitmap_ = new_macro_block_bitmap;
 | 
			
		||||
          LOG_INFO("succeed to resize file", K(new_data_file_size));
 | 
			
		||||
        }
 | 
			
		||||
        if (OB_FAIL(ret)) {
 | 
			
		||||
          allocator_.free(new_free_block_array);
 | 
			
		||||
          allocator_.free(new_macro_block_bitmap);
 | 
			
		||||
          MEMCPY(new_free_block_array, free_block_array_, free_block_cnt_ * sizeof(uint32_t));
 | 
			
		||||
        }
 | 
			
		||||
        free_block_pop_pos_ = 0;
 | 
			
		||||
        free_block_push_pos_ = free_block_cnt_;
 | 
			
		||||
        MEMCPY(new_macro_block_bitmap,
 | 
			
		||||
            macro_block_bitmap_,
 | 
			
		||||
            get_macro_bitmap_array_cnt(origin_macro_block_cnt) * sizeof(uint64_t));
 | 
			
		||||
        allocator_.free(free_block_array_);
 | 
			
		||||
        allocator_.free(macro_block_bitmap_);
 | 
			
		||||
        free_block_array_ = new_free_block_array;
 | 
			
		||||
        macro_block_bitmap_ = new_macro_block_bitmap;
 | 
			
		||||
      }
 | 
			
		||||
      if (OB_FAIL(ret)) {
 | 
			
		||||
        allocator_.free(new_free_block_array);
 | 
			
		||||
        allocator_.free(new_macro_block_bitmap);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  enable_mark_sweep();
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObStoreFile::validate_datafile_size(const char* config_data_file_size)
 | 
			
		||||
int ObStoreFile::resize_file(
 | 
			
		||||
    const int64_t new_data_file_size, const int64_t new_data_file_disk_percentage)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  if (OB_ISNULL(store_file_system_)) {
 | 
			
		||||
    LOG_DEBUG("Do resize file fail, store_file_system_ is null pointer");
 | 
			
		||||
  } else {
 | 
			
		||||
    lib::ObMutexGuard guard(block_lock_);
 | 
			
		||||
    disable_mark_sweep();
 | 
			
		||||
    if (OB_FAIL(wait_mark_sweep_finish())) {
 | 
			
		||||
      LOG_WARN("fail to wait mark and sweep finish", K(ret));
 | 
			
		||||
    } else {
 | 
			
		||||
      if (OB_FAIL(store_file_system_->resize_file(new_data_file_size, new_data_file_disk_percentage))) {
 | 
			
		||||
        LOG_WARN("fail to resize file", K(ret));
 | 
			
		||||
      } else if (OB_FAIL(refresh_block_meta())) {
 | 
			
		||||
        LOG_WARN("fail to refresh block meta", K(ret));
 | 
			
		||||
      } else {
 | 
			
		||||
        start_doing_disk_extend();
 | 
			
		||||
        LOG_INFO("succeed to resize file");
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    enable_mark_sweep();
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObStoreFile::validate_datafile_param(const ObString& name, const char* config_data_file_param)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  bool valid = false;
 | 
			
		||||
  if (OB_ISNULL(store_file_system_)) {
 | 
			
		||||
    ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
    LOG_WARN("The OB store file instance is not exist", K(ret));
 | 
			
		||||
  } else {
 | 
			
		||||
  } 
 | 
			
		||||
  if (OB_SUCC(ret)) {
 | 
			
		||||
    bool valid = false;
 | 
			
		||||
    int64_t new_data_file_size = ObConfigCapacityParser::get(config_data_file_size, valid);
 | 
			
		||||
    if(!valid){
 | 
			
		||||
      ret = OB_ERR_PARSE_SQL;
 | 
			
		||||
      LOG_USER_ERROR(OB_INVALID_CONFIG, "datafile_size can not be parsed");
 | 
			
		||||
    } else {
 | 
			
		||||
      const int64_t original_file_size = store_file_system_->get_total_data_size();
 | 
			
		||||
      if (new_data_file_size < original_file_size) {
 | 
			
		||||
        ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
        LOG_WARN("datafile_size is smaller than the original configuration", K(ret));
 | 
			
		||||
        LOG_USER_ERROR(OB_INVALID_CONFIG, "datafile_size can not be smaller than the original configuration");
 | 
			
		||||
    int64_t new_data_file_param;
 | 
			
		||||
    if (0 == name.case_compare("datafile_size")) {
 | 
			
		||||
      new_data_file_param = ObConfigCapacityParser::get(config_data_file_param, valid);
 | 
			
		||||
      if(!valid){
 | 
			
		||||
        ret = OB_ERR_PARSE_SQL;
 | 
			
		||||
        LOG_USER_ERROR(OB_INVALID_CONFIG, "datafile size can not be parsed");
 | 
			
		||||
      } else {
 | 
			
		||||
        const int64_t original_file_size = store_file_system_->get_total_data_size();
 | 
			
		||||
        if (new_data_file_param < original_file_size) {
 | 
			
		||||
          ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
          LOG_WARN("datafile_size is smaller than the original configuration", 
 | 
			
		||||
            K(ret), K(new_data_file_param), K(original_file_size));
 | 
			
		||||
          LOG_USER_ERROR(OB_INVALID_CONFIG, 
 | 
			
		||||
            "datafile_size can not be smaller than the original configuration");
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }  
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -209,6 +209,13 @@ private:
 | 
			
		||||
  common::ObIOHandle io_handle_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class ObStoreFileAutoExtendTask : public common::ObTimerTask {
 | 
			
		||||
public:
 | 
			
		||||
  ObStoreFileAutoExtendTask();
 | 
			
		||||
  virtual ~ObStoreFileAutoExtendTask();
 | 
			
		||||
  virtual void runTimerTask();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class ObStoreFileGCTask : public common::ObTimerTask {
 | 
			
		||||
public:
 | 
			
		||||
  ObStoreFileGCTask();
 | 
			
		||||
@ -348,61 +355,62 @@ public:
 | 
			
		||||
  int get_macro_block_info(const int64_t block_index, ObMacroBlockInfo& macro_block_info);
 | 
			
		||||
  int report_bad_block(const MacroBlockId& macro_block_id, const int64_t error_type, const char* error_msg);
 | 
			
		||||
  int get_bad_block_infos(common::ObArray<ObBadBlockInfo>& bad_block_infos);
 | 
			
		||||
  OB_INLINE const char* get_store_file_path()
 | 
			
		||||
  {
 | 
			
		||||
    return sstable_dir_;
 | 
			
		||||
  }
 | 
			
		||||
  OB_INLINE int64_t get_free_macro_block_count() const
 | 
			
		||||
  {
 | 
			
		||||
    return free_block_cnt_;
 | 
			
		||||
  }
 | 
			
		||||
  OB_INLINE const char* get_store_file_path() { return sstable_dir_; }
 | 
			
		||||
  OB_INLINE int64_t get_free_macro_block_count() const { return free_block_cnt_; }
 | 
			
		||||
  
 | 
			
		||||
  int add_disk(
 | 
			
		||||
      const common::ObString& diskgroup_name, const common::ObString& disk_path, const common::ObString& alias_name);
 | 
			
		||||
  int drop_disk(const common::ObString& diskgroup_name, const common::ObString& alias_name);
 | 
			
		||||
  int is_free_block(const int64_t block_index, bool& is_free);
 | 
			
		||||
  int resize_file(const int64_t new_data_file_size, const int64_t new_data_file_disk_percentage);
 | 
			
		||||
  int validate_datafile_size(const char* config_data_file_size);
 | 
			
		||||
  int validate_datafile_param(const ObString& name, const char* config_data_file_param);
 | 
			
		||||
  int refresh_block_meta();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  friend class ObStoreFileGCTask;
 | 
			
		||||
  friend class ObFileSystemInspectBadBlockTask;
 | 
			
		||||
  friend class ObAllMacroIdIterator;
 | 
			
		||||
  friend class ObStoreFileAutoExtendTask;
 | 
			
		||||
  ObStoreFile();
 | 
			
		||||
  virtual ~ObStoreFile();
 | 
			
		||||
  int alloc_block(ObMacroBlockHandle& macro_handle);
 | 
			
		||||
  int  alloc_block(ObMacroBlockHandle& macro_handle);
 | 
			
		||||
  int  mark_macro_blocks();
 | 
			
		||||
  int  extend_file_size_task();
 | 
			
		||||
  int  auto_extend_file_size();
 | 
			
		||||
  void free_block(const uint32_t block_idx, bool& is_freed);
 | 
			
		||||
  int mark_macro_blocks();
 | 
			
		||||
  void mark_and_sweep();
 | 
			
		||||
  void ssblock_check_and_extend();
 | 
			
		||||
  OB_INLINE bool is_valid(const MacroBlockId macro_id);
 | 
			
		||||
  OB_INLINE void bitmap_set(const int64_t block_idx);
 | 
			
		||||
  OB_INLINE bool bitmap_test(const int64_t block_idx);
 | 
			
		||||
  bool is_bad_block(const MacroBlockId& macro_block_id);
 | 
			
		||||
  int read_checkpoint_and_replay_log(bool& is_replay_old);
 | 
			
		||||
  void disable_mark_sweep()
 | 
			
		||||
  {
 | 
			
		||||
    ATOMIC_SET(&is_mark_sweep_enabled_, false);
 | 
			
		||||
  }
 | 
			
		||||
  void enable_mark_sweep()
 | 
			
		||||
  {
 | 
			
		||||
    ATOMIC_SET(&is_mark_sweep_enabled_, true);
 | 
			
		||||
  }
 | 
			
		||||
  bool is_mark_sweep_enabled()
 | 
			
		||||
  {
 | 
			
		||||
    return ATOMIC_LOAD(&is_mark_sweep_enabled_);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void disable_mark_sweep() { ATOMIC_SET(&is_mark_sweep_enabled_, false);}
 | 
			
		||||
  void enable_mark_sweep() { ATOMIC_SET(&is_mark_sweep_enabled_, true);}
 | 
			
		||||
  bool is_mark_sweep_enabled() { return ATOMIC_LOAD(&is_mark_sweep_enabled_);}
 | 
			
		||||
 | 
			
		||||
  void finish_doing_disk_extend() { ATOMIC_SET(&is_doing_disk_extend_, false);}
 | 
			
		||||
  void start_doing_disk_extend() { ATOMIC_SET(&is_doing_disk_extend_, true);}
 | 
			
		||||
  bool is_doing_disk_extend() { return ATOMIC_LOAD(&is_doing_disk_extend_);}
 | 
			
		||||
  int64_t get_macro_bitmap_array_cnt(const int64_t macro_block_cnt) { return macro_block_cnt / 64 + 1; }
 | 
			
		||||
 | 
			
		||||
  int wait_mark_sweep_finish();
 | 
			
		||||
  void set_mark_sweep_doing();
 | 
			
		||||
  void set_mark_sweep_done();
 | 
			
		||||
 | 
			
		||||
  int alloc_memory(const int64_t total_macro_block_cnt, uint32_t*& free_block_array, uint64_t*& macro_block_bitmap,
 | 
			
		||||
      ObSegmentArray<ObMacroBlockInfo>& macro_block_info_array);
 | 
			
		||||
  int64_t get_macro_bitmap_array_cnt(const int64_t macro_block_cnt)
 | 
			
		||||
  {
 | 
			
		||||
    return macro_block_cnt / 64 + 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  static const int64_t RECYCLE_DELAY_US = 5 * 1000 * 1000;  // 5s
 | 
			
		||||
  static const int64_t INSPECT_DELAY_US = 1 * 1000 * 1000;  // 1s
 | 
			
		||||
  static const int64_t RECYCLE_DELAY_US     = 5 * 1000 * 1000;  // 5s
 | 
			
		||||
  static const int64_t INSPECT_DELAY_US     = 1 * 1000 * 1000;  // 1s
 | 
			
		||||
  static const int64_t AUTOEXTEND_DELAY_US  = 1 * 1000 * 1000;  // 1s
 | 
			
		||||
  static const int64_t DATAFILE_NEXT_MIN    = 1 * 1024 * 1024 * 1024; // 1G
 | 
			
		||||
  static const int64_t FREE_BLOCK_LEFT_PERCENTAGE = 5;
 | 
			
		||||
  static const int64_t AUTO_EXTEND_LEAST_FREE_BLOCK_CNT = 512; // 1G 
 | 
			
		||||
  static const int64_t MARK_BLOCK_INFO_TIMEOUT = RECYCLE_DELAY_US;
 | 
			
		||||
 | 
			
		||||
  bool is_inited_;
 | 
			
		||||
  bool is_opened_;
 | 
			
		||||
  char sstable_dir_[common::OB_MAX_FILE_NAME_LENGTH];
 | 
			
		||||
@ -419,6 +427,7 @@ private:
 | 
			
		||||
  int64_t cur_meta_array_pos_;
 | 
			
		||||
  common::ObArray<MacroBlockId> meta_block_ids_[2];
 | 
			
		||||
  ObStoreFileGCTask gc_task_;
 | 
			
		||||
  ObStoreFileAutoExtendTask ssblock_auto_extend_task_;
 | 
			
		||||
  ObFileSystemInspectBadBlockTask inspect_bad_block_task_;
 | 
			
		||||
  char* print_buffer_;
 | 
			
		||||
  int64_t print_buffer_size_;
 | 
			
		||||
@ -431,9 +440,11 @@ private:
 | 
			
		||||
  ObStoreFileSystem* store_file_system_;
 | 
			
		||||
  bool is_mark_sweep_enabled_;
 | 
			
		||||
  bool is_doing_mark_sweep_;
 | 
			
		||||
  bool is_doing_disk_extend_;
 | 
			
		||||
  ObThreadCond cond_;  // for mark sweep
 | 
			
		||||
  bool is_fs_support_punch_hole_;
 | 
			
		||||
  int block_file_fd_;
 | 
			
		||||
  lib::ObMutex alloc_lock_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
OB_INLINE bool ObStoreFile::is_valid(const MacroBlockId macro_id)
 | 
			
		||||
 | 
			
		||||
@ -736,6 +736,11 @@ int64_t ObStoreFileSystem::get_total_macro_block_count() const
 | 
			
		||||
  return super_block_.get_total_macro_block_count();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int64_t ObStoreFileSystem::get_total_macro_block_max_count() const
 | 
			
		||||
{
 | 
			
		||||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int64_t ObStoreFileSystem::get_free_macro_block_count() const
 | 
			
		||||
{
 | 
			
		||||
  return -1;
 | 
			
		||||
@ -777,10 +782,11 @@ int ObStoreFileSystem::get_bad_block_infos(common::ObArray<ObBadBlockInfo>& bad_
 | 
			
		||||
  return OB_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObStoreFileSystem::resize_file(const int64_t new_data_file_size, const int64_t new_data_file_disk_percentage)
 | 
			
		||||
int ObStoreFileSystem::resize_file(
 | 
			
		||||
    const int64_t new_data_file_size, const int64_t new_data_file_disk_percentage, const int64_t extend_size)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_NOT_SUPPORTED;
 | 
			
		||||
  UNUSEDx(new_data_file_size, new_data_file_disk_percentage);
 | 
			
		||||
  UNUSEDx(new_data_file_size, new_data_file_disk_percentage, extend_size);
 | 
			
		||||
  LOG_WARN("resize file is not supported in current file system", K(ret));
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -399,7 +399,9 @@ public:
 | 
			
		||||
  {
 | 
			
		||||
    return super_block_;
 | 
			
		||||
  }
 | 
			
		||||
  virtual int resize_file(const int64_t new_data_file_size, const int64_t new_data_file_disk_percentage);
 | 
			
		||||
  virtual int resize_file(const int64_t new_data_file_size, const int64_t new_data_file_disk_percentage, const int64_t extend_size = 0);
 | 
			
		||||
 | 
			
		||||
  virtual int64_t get_total_macro_block_max_count() const;
 | 
			
		||||
 | 
			
		||||
  VIRTUAL_TO_STRING_KV("ObStoreFileSystem", "empty");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user