Optimize tmp file

This commit is contained in:
godchen0212
2023-07-14 04:42:06 +00:00
committed by ob-robot
parent 6734061113
commit 9b23516657
12 changed files with 1682 additions and 883 deletions

View File

@ -330,23 +330,101 @@ ObTmpFileArea *ObTmpFilePageBuddy::find_buddy(const int32_t page_nums, const int
return tmp;
}
ObTmpMacroBlock::ObTmpMacroBlock()
: is_inited_(false),
is_washing_(false),
is_disked_(false),
free_page_nums_(0),
buffer_(NULL),
ObTmpFileMacroBlockHeader::ObTmpFileMacroBlockHeader()
: version_(TMP_FILE_MACRO_BLOCK_HEADER_VERSION),
magic_(TMP_FILE_MACRO_BLOCK_HEADER_MAGIC),
block_id_(-1),
dir_id_(-1),
tenant_id_(0),
alloc_time_(0),
access_time_(0),
io_desc_(),
lock_(common::ObLatchIds::TMP_FILE_MACRO_LOCK),
macro_block_handle_(),
free_page_nums_(-1)
{
}
bool ObTmpFileMacroBlockHeader::is_valid() const
{
return TMP_FILE_MACRO_BLOCK_HEADER_VERSION == version_
&& TMP_FILE_MACRO_BLOCK_HEADER_MAGIC == magic_
&& block_id_ >= 0
&& dir_id_ >= 0
&& tenant_id_ > 0
&& free_page_nums_ >= 0;
}
int ObTmpFileMacroBlockHeader::serialize(char *buf, const int64_t buf_len, int64_t &pos) const
{
int ret = OB_SUCCESS;
if (OB_ISNULL(buf) || OB_UNLIKELY(buf_len < 0)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), KP(buf), K(buf_len));
} else if (OB_UNLIKELY(pos + get_serialize_size() > buf_len)) {
ret = OB_BUF_NOT_ENOUGH;
STORAGE_LOG(WARN, "data buffer is not enough", K(ret), K(pos), K(buf_len), K(*this));
} else if (OB_UNLIKELY(!is_valid())) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "tmp file macro block header is invalid", K(ret), K(*this));
} else {
ObTmpFileMacroBlockHeader *header = reinterpret_cast<ObTmpFileMacroBlockHeader *>(buf + pos);
header->version_ = version_;
header->magic_ = magic_;
header->block_id_ = block_id_;
header->dir_id_ = dir_id_;
header->tenant_id_ = tenant_id_;
header->free_page_nums_ = free_page_nums_;
pos += header->get_serialize_size();
}
return ret;
}
int ObTmpFileMacroBlockHeader::deserialize(const char *buf, const int64_t data_len, int64_t &pos)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(buf) || OB_UNLIKELY(data_len <= 0 || pos < 0)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid arguments", K(ret), KP(buf), K(data_len), K(pos));
} else if (OB_UNLIKELY(data_len - pos < get_serialize_size())) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "buffer not enough", K(ret), KP(buf), K(data_len), K(pos));
} else {
const ObTmpFileMacroBlockHeader *ptr = reinterpret_cast<const ObTmpFileMacroBlockHeader *>(buf + pos);
version_ = ptr->version_;
magic_ = ptr->magic_;
block_id_ = ptr->block_id_;
dir_id_ = ptr->dir_id_;
tenant_id_ = ptr->tenant_id_;
free_page_nums_ = ptr->free_page_nums_;
if (OB_UNLIKELY(!is_valid())) {
ret = OB_DESERIALIZE_ERROR;
STORAGE_LOG(ERROR, "deserialize error", K(ret), K(*this));
} else {
pos += get_serialize_size();
}
}
return ret;
}
void ObTmpFileMacroBlockHeader::reset()
{
version_ = TMP_FILE_MACRO_BLOCK_HEADER_VERSION;
magic_ = TMP_FILE_MACRO_BLOCK_HEADER_MAGIC;
block_id_ = -1;
dir_id_ = -1;
tenant_id_ = 0;
free_page_nums_ = 0;
}
ObTmpMacroBlock::ObTmpMacroBlock()
: buffer_(NULL),
handle_(),
page_buddy_(),
using_extents_() {}
using_extents_(),
macro_block_handle_(),
tmp_file_header_(),
io_desc_(),
block_status_(MAX),
is_inited_(false),
alloc_time_(0),
access_time_(0)
{
}
ObTmpMacroBlock::~ObTmpMacroBlock()
{
@ -363,12 +441,11 @@ int ObTmpMacroBlock::init(const int64_t block_id, const int64_t dir_id, const ui
} else if (OB_FAIL(page_buddy_.init(allocator))) {
STORAGE_LOG(WARN, "Fail to init the page buddy", K(ret));
} else {
block_id_ = block_id;
dir_id_ = dir_id;
tenant_id_ = tenant_id,
free_page_nums_ = ObTmpFilePageBuddy::MAX_PAGE_NUMS;
is_disked_ = false;
is_washing_ = false;
tmp_file_header_.block_id_ = block_id;
tmp_file_header_.dir_id_ = dir_id;
tmp_file_header_.tenant_id_ = tenant_id;
tmp_file_header_.free_page_nums_ = ObTmpFilePageBuddy::MAX_PAGE_NUMS;
ATOMIC_STORE(&block_status_, MEMORY);
is_inited_ = true;
alloc_time_ = 0;
ATOMIC_STORE(&access_time_, 0);
@ -384,29 +461,24 @@ void ObTmpMacroBlock::destroy()
using_extents_.reset();
page_buddy_.destroy();
macro_block_handle_.reset();
block_id_ = -1;
dir_id_ = -1;
tenant_id_ = 0;
free_page_nums_ = 0;
tmp_file_header_.reset();
buffer_ = NULL;
handle_.reset();
is_disked_ = false;
is_washing_ = false;
is_inited_ = false;
ATOMIC_STORE(&block_status_, MAX);
alloc_time_ = 0;
ATOMIC_STORE(&access_time_, 0);
}
int ObTmpMacroBlock::close(bool &is_all_close, uint8_t &free_page_nums)
int ObTmpMacroBlock::close(bool &is_all_close)
{
int ret = OB_SUCCESS;
is_all_close = true;
free_page_nums = 0;
if (IS_NOT_INIT) {
is_all_close = false;
STORAGE_LOG(WARN, "ObTmpMacroBlock has not been inited");
} else {
ObTmpFileExtent *tmp = NULL;
SpinWLockGuard guard(lock_);
for (int32_t i = 0; OB_SUCC(ret) && i < using_extents_.count() && is_all_close; i++) {
tmp = using_extents_.at(i);
if (NULL != tmp && !tmp->is_closed()) {
@ -422,12 +494,10 @@ int ObTmpMacroBlock::close(bool &is_all_close, uint8_t &free_page_nums)
} else if (OB_FAIL(free(start_id, page_nums))) {
STORAGE_LOG(WARN, "fail to free the extent", K(ret));
} else {
free_page_nums += page_nums;
}
if (OB_FAIL(ret)) {
tmp->unclose(page_nums);
is_all_close = false;
free_page_nums -= page_nums;
}
} else {
is_all_close = false;
@ -438,12 +508,31 @@ int ObTmpMacroBlock::close(bool &is_all_close, uint8_t &free_page_nums)
return ret;
}
int ObTmpMacroBlock::is_extents_closed(bool &is_extents_closed) {
int ret = OB_SUCCESS;
is_extents_closed = true;
if (IS_NOT_INIT) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObTmpMacroBlock has not been inited");
} else {
SpinRLockGuard guard(lock_);
for (int64_t i = 0; i< using_extents_.count(); ++i) {
if (!using_extents_.at(i)->is_closed()) {
STORAGE_LOG(DEBUG, "the tmp macro block's extents is not all closed", K(ret), K(tmp_file_header_.block_id_));
is_extents_closed = false;
break;
}
}
}
return ret;
}
int ObTmpMacroBlock::get_block_cache_handle(ObTmpBlockValueHandle &handle)
{
int ret = OB_SUCCESS;
ObTmpBlockCacheKey key(block_id_, tenant_id_);
ObTmpBlockCacheKey key(tmp_file_header_.block_id_, tmp_file_header_.tenant_id_);
SpinRLockGuard guard(lock_);
if (!is_disked_) {
if (!is_disked()) {
handle = handle_;
} else if (OB_FAIL(ObTmpBlockCache::get_instance().get_block(key, handle))) {
if (OB_UNLIKELY(OB_ENTRY_NOT_EXIST != ret)) {
@ -462,10 +551,10 @@ int ObTmpMacroBlock::get_wash_io_info(ObTmpBlockIOInfo &info)
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObTmpMacroBlock has not been inited", K(ret));
} else {
info.block_id_ = block_id_;
info.block_id_ = tmp_file_header_.block_id_;
info.offset_ = 0;
info.size_ = ObTmpMacroBlock::get_block_size();
info.tenant_id_ = tenant_id_;
info.size_ = ObTmpFileStore::get_block_size();
info.tenant_id_ = tmp_file_header_.tenant_id_;
info.macro_block_id_ = get_macro_block_id();
info.buf_ = buffer_;
info.io_desc_ = io_desc_;
@ -473,15 +562,13 @@ int ObTmpMacroBlock::get_wash_io_info(ObTmpBlockIOInfo &info)
return ret;
}
int ObTmpMacroBlock::give_back_buf_into_cache(bool is_wash)
int ObTmpMacroBlock::give_back_buf_into_cache()
{
int ret = OB_SUCCESS;
ObTmpBlockCacheKey key(block_id_, tenant_id_);
ObTmpBlockCacheKey key(tmp_file_header_.block_id_, tmp_file_header_.tenant_id_);
SpinWLockGuard guard(lock_);
if (OB_FAIL(ObTmpBlockCache::get_instance().put_block(key, handle_))) {
STORAGE_LOG(WARN, "fail to put block into block cache", K(ret), K(key));
} else if (is_wash) {
set_disked();
}
return ret;
}
@ -489,20 +576,26 @@ int ObTmpMacroBlock::give_back_buf_into_cache(bool is_wash)
int ObTmpMacroBlock::alloc_all_pages(ObTmpFileExtent &extent)
{
int ret = OB_SUCCESS;
SpinWLockGuard guard(lock_);
if (IS_NOT_INIT) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObTmpMacroBlock has not been inited", K(ret));
} else if (!is_memory()) {
ret = OB_STATE_NOT_MATCH;
STORAGE_LOG(WARN, "the block is not in memory", K(ret), K(ATOMIC_LOAD(&block_status_)));
} else if (OB_FAIL(page_buddy_.alloc_all_pages())) {
STORAGE_LOG(WARN, "Fail to allocate the tmp extent", K(ret), K_(block_id), K_(dir_id), K_(tenant_id),
K_(free_page_nums), K_(page_buddy));
STORAGE_LOG(WARN, "Fail to allocate the tmp extent", K(ret), K_(tmp_file_header), K_(page_buddy));
} else {
extent.set_block_id(get_block_id());
extent.set_start_page_id(0);
extent.set_page_nums(ObTmpFilePageBuddy::MAX_PAGE_NUMS);
extent.alloced();
free_page_nums_ -= extent.get_page_nums();
if (OB_FAIL(using_extents_.push_back(&extent))) {
STORAGE_LOG(WARN, "Fail to push back into using_extexts", K(ret));
page_buddy_.free(extent.get_start_page_id(), extent.get_page_nums());
extent.reset();
} else {
tmp_file_header_.free_page_nums_ -= extent.get_page_nums();
}
const int64_t cur_time = ObTimeUtility::fast_current_time();
alloc_time_ = cur_time;
@ -516,23 +609,26 @@ int ObTmpMacroBlock::alloc(const uint8_t page_nums, ObTmpFileExtent &extent)
int ret = OB_SUCCESS;
uint8_t start_page_id = extent.get_start_page_id();
uint8_t alloced_page_nums = 0;
SpinWLockGuard guard(lock_);
if (IS_NOT_INIT) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObTmpMacroBlock has not been inited", K(ret));
} else if (!is_memory()) {
ret = OB_STATE_NOT_MATCH;
STORAGE_LOG(WARN, "the block is not in memory", K(ret), K(ATOMIC_LOAD(&block_status_)));
} else if (OB_FAIL(page_buddy_.alloc(page_nums, start_page_id, alloced_page_nums))) {
STORAGE_LOG(WARN, "Fail to allocate the tmp extent", K(ret), K_(block_id), K_(dir_id), K_(tenant_id),
K_(free_page_nums), K_(page_buddy));
STORAGE_LOG(WARN, "Fail to allocate the tmp extent", K(ret), K_(tmp_file_header), K_(page_buddy));
} else {
extent.set_block_id(block_id_);
extent.set_block_id(tmp_file_header_.block_id_);
extent.set_page_nums(alloced_page_nums);
extent.set_start_page_id(start_page_id);
extent.alloced();
free_page_nums_ -= alloced_page_nums;
if (OB_FAIL(using_extents_.push_back(&extent))) {
STORAGE_LOG(WARN, "Fail to push back into using_extexts", K(ret));
page_buddy_.free(extent.get_start_page_id(), extent.get_page_nums());
free_page_nums_ += extent.get_page_nums();
extent.reset();
} else {
tmp_file_header_.free_page_nums_ -= alloced_page_nums;
}
const int64_t cur_time = ObTimeUtility::fast_current_time();
if (0 == alloc_time_) {
@ -555,15 +651,16 @@ int ObTmpMacroBlock::free(ObTmpFileExtent &extent)
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObTmpMacroBlock has not been inited", K(ret));
} else {
SpinWLockGuard guard(lock_);
page_buddy_.free(extent.get_start_page_id(), extent.get_page_nums());
free_page_nums_ += extent.get_page_nums();
for (int64_t i = using_extents_.count() - 1; i >= 0; --i) {
if (&extent == using_extents_.at(i)) {
using_extents_.remove(i);
break;
}
}
if (free_page_nums_ == get_mblk_page_nums()) {
tmp_file_header_.free_page_nums_ += extent.get_page_nums();
if (tmp_file_header_.free_page_nums_ == ObTmpFilePageBuddy::MAX_PAGE_NUMS) {
alloc_time_ = 0;
ATOMIC_STORE(&access_time_, 0);
}
@ -579,13 +676,14 @@ int ObTmpMacroBlock::free(const int32_t start_page_id, const int32_t page_nums)
STORAGE_LOG(WARN, "ObTmpMacroBlock has not been inited", K(ret));
} else {
page_buddy_.free(start_page_id, page_nums);
free_page_nums_ += page_nums;
tmp_file_header_.free_page_nums_ += page_nums;
}
return ret;
}
int64_t ObTmpMacroBlock::get_used_page_nums() const
{
SpinRLockGuard guard(lock_);
int64_t used_page_nums = 0;
for (int64_t i = using_extents_.count() - 1; i >= 0; --i) {
used_page_nums += std::ceil(using_extents_.at(i)->get_offset() / DEFAULT_PAGE_SIZE);
@ -598,11 +696,19 @@ void ObTmpMacroBlock::set_io_desc(const common::ObIOFlag &io_desc)
io_desc_ = io_desc;
}
int ObTmpMacroBlock::check_and_set_status(const BlockStatus old_block_status, const BlockStatus block_status)
{
int ret = OB_SUCCESS;
if (old_block_status != ATOMIC_VCAS(&block_status_, old_block_status, block_status)) {
ret = OB_STATE_NOT_MATCH;
}
return ret;
}
ObTmpTenantMacroBlockManager::ObTmpTenantMacroBlockManager()
: is_inited_(false),
next_blk_id_(0),
allocator_(),
blocks_()
: allocator_(),
blocks_(),
is_inited_(false)
{
}
@ -644,7 +750,7 @@ int ObTmpTenantMacroBlockManager::alloc_macro_block(const int64_t dir_id, const
} else if (OB_ISNULL(t_mblk = new (block_buf) ObTmpMacroBlock())) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "fail to new a ObTmpMacroBlock", K(ret));
} else if (OB_FAIL(t_mblk->init(get_next_blk_id(), dir_id, tenant_id, *allocator_))) {
} else if (OB_FAIL(t_mblk->init(OB_TMP_FILE_STORE.get_next_blk_id(), dir_id, tenant_id, *allocator_))) {
STORAGE_LOG(WARN, "fail to init tmp block", K(ret));
} else if (OB_FAIL(blocks_.set_refactored(t_mblk->get_block_id(), t_mblk))) {
STORAGE_LOG(WARN, "fail to set tmp macro block map", K(ret), K(t_mblk));
@ -692,6 +798,7 @@ int ObTmpTenantMacroBlockManager::free_macro_block(const int64_t block_id)
return ret;
}
int ObTmpTenantMacroBlockManager::get_disk_macro_block_list(
common::ObIArray<MacroBlockId> &macro_id_list)
{
@ -762,31 +869,16 @@ void ObTmpTenantMacroBlockManager::destroy()
is_inited_ = false;
}
int64_t ObTmpTenantMacroBlockManager::get_next_blk_id()
{
int64_t next_blk_id = -1;
int64_t old_val = ATOMIC_LOAD(&next_blk_id_);
int64_t new_val = 0;
bool finish = false;
while (!finish) {
new_val = (old_val + 1) % INT64_MAX;
next_blk_id = new_val;
finish = (old_val == (new_val = ATOMIC_VCAS(&next_blk_id_, old_val, new_val)));
old_val = new_val;
}
return next_blk_id;
}
ObTmpTenantFileStore::ObTmpTenantFileStore()
: is_inited_(false),
page_cache_num_(0),
block_cache_num_(0),
ref_cnt_(0),
page_cache_(NULL),
lock_(common::ObLatchIds::TMP_FILE_STORE_LOCK),
tmp_block_manager_(),
lock_(),
allocator_(),
io_allocator_(),
tmp_block_manager_(),
tmp_mem_block_manager_()
{
}
@ -851,6 +943,7 @@ int64_t ObTmpTenantFileStore::get_memory_limit(const uint64_t tenant_id) const {
} else {
memory_limit = tenant_memory_limit;
}
memory_limit = common::upper_align(memory_limit, ObTmpFileStore::get_block_size());
return memory_limit;
}
@ -875,7 +968,7 @@ int ObTmpTenantFileStore::alloc(const int64_t dir_id, const uint64_t tenant_id,
ObTmpFileExtent &extent)
{
int ret = OB_SUCCESS;
const int64_t block_size = tmp_block_manager_.get_block_size();
const int64_t block_size = ObTmpFileStore::get_block_size();
// In buddy allocation, if free space in one block isn't powers of 2, need upper align.
int64_t max_order = std::ceil(std::log(ObTmpFilePageBuddy::MAX_PAGE_NUMS) / std::log(2));
int64_t origin_max_cont_page_nums = std::pow(2, max_order - 1);
@ -886,38 +979,48 @@ int ObTmpTenantFileStore::alloc(const int64_t dir_id, const uint64_t tenant_id,
STORAGE_LOG(WARN, "ObTmpTenantFileStore has not been inited", K(ret));
} else if (alloc_size <= 0 || alloc_size > block_size) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(alloc_size));
STORAGE_LOG(WARN, "invalid argument", K(alloc_size), K(block_size));
} else {
SpinWLockGuard guard(lock_);
common::ObSEArray<ObTmpMacroBlock *, 1> free_blocks;
if (alloc_size > max_cont_size_per_block) {
if (OB_FAIL(tmp_mem_block_manager_.try_wash(free_blocks))) {
ret = OB_STATE_NOT_MATCH;
while (OB_STATE_NOT_MATCH == ret || OB_SIZE_OVERFLOW == ret) {
if (OB_FAIL(tmp_mem_block_manager_.cleanup())) {
STORAGE_LOG(WARN, "fail to try wash tmp macro block", K(ret), K(dir_id), K(tenant_id));
} else if (OB_FAIL(tmp_mem_block_manager_.free_empty_blocks(free_blocks))) {
STORAGE_LOG(WARN, "fail to free empty blocks", K(ret), K(dir_id), K(tenant_id));
} else if (OB_FAIL(alloc_macro_block(dir_id, tenant_id, t_mblk))) {
STORAGE_LOG(WARN, "cannot allocate a tmp macro block", K(ret), K(dir_id), K(tenant_id));
} else if (OB_FAIL(tmp_mem_block_manager_.alloc_block_all_pages(t_mblk, extent))) {
STORAGE_LOG(WARN, "Fail to allocate the tmp extent", K(ret), K(t_mblk->get_block_id()));
} else {
if (alloc_size < block_size) {
const int64_t nums = std::ceil(alloc_size * 1.0 / ObTmpMacroBlock::get_default_page_size());
if (OB_FAIL(free_extent(t_mblk->get_block_id(), nums,
ObTmpFilePageBuddy::MAX_PAGE_NUMS - nums))) {
STORAGE_LOG(WARN, "fail to free pages", K(ret), K(t_mblk->get_block_id()));
} else {
extent.set_page_nums(nums);
}
}
}
} else if (OB_FAIL(tmp_mem_block_manager_.alloc_extent(dir_id, tenant_id, alloc_size, extent, free_blocks))) {
if (OB_ITER_END == ret) {
if (OB_FAIL(tmp_mem_block_manager_.free_empty_blocks(free_blocks))) {
STORAGE_LOG(WARN, "fail to free empty blocks", K(ret), K(dir_id), K(tenant_id));
} else if (OB_FAIL(alloc_macro_block(dir_id, tenant_id, t_mblk))) {
STORAGE_LOG(WARN, "cannot allocate a tmp macro block", K(ret), K(dir_id), K(tenant_id));
} else if (OB_FAIL(tmp_mem_block_manager_.alloc_extent(dir_id, tenant_id, alloc_size, extent, free_blocks))) {
STORAGE_LOG(WARN, "fail to alloc tmp extent", K(ret));
SpinWLockGuard guard(lock_);
if (OB_SUCC(ret)) {
if (alloc_size > max_cont_size_per_block) {
if (OB_FAIL(alloc_macro_block(dir_id, tenant_id, t_mblk))) {
STORAGE_LOG(WARN, "cannot allocate a tmp macro block", K(ret), K(dir_id), K(tenant_id));
} else if (OB_ISNULL(t_mblk)) {
ret = OB_ERR_NULL_VALUE;
STORAGE_LOG(WARN, "block alloced is NULL", K(ret), K(dir_id), K(tenant_id));
} else if (OB_FAIL(t_mblk->alloc_all_pages(extent))) {
STORAGE_LOG(WARN, "Fail to allocate the tmp extent", K(ret), K(t_mblk->get_block_id()));
} else if (alloc_size < block_size) {
const int64_t nums = std::ceil(alloc_size * 1.0 / ObTmpMacroBlock::get_default_page_size());
if (OB_FAIL(free_extent(t_mblk->get_block_id(), nums,
ObTmpFilePageBuddy::MAX_PAGE_NUMS - nums))) {
STORAGE_LOG(WARN, "fail to free pages", K(ret), K(t_mblk->get_block_id()));
} else {
extent.set_page_nums(nums);
}
}
} else if (OB_FAIL(tmp_mem_block_manager_.alloc_extent(dir_id, tenant_id, alloc_size, extent))) {
if (OB_STATE_NOT_MATCH == ret) {
if (OB_FAIL(alloc_macro_block(dir_id, tenant_id, t_mblk))) {
STORAGE_LOG(WARN, "cannot allocate a tmp macro block", K(ret), K(dir_id), K(tenant_id));
} else if (OB_ISNULL(t_mblk)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "unexpected error, t_mblk is nullptr", K(ret), KP(t_mblk));
} else {
const int64_t page_nums = std::ceil(alloc_size * 1.0 / ObTmpMacroBlock::get_default_page_size());
if (OB_FAIL(t_mblk->alloc(page_nums, extent))){
STORAGE_LOG(WARN, "fail to alloc tmp extent", K(ret));
} else if (OB_FAIL(tmp_mem_block_manager_.refresh_dir_to_blk_map(dir_id, t_mblk))) {
STORAGE_LOG(WARN, "fail to refresh dir_to_blk_map", K(ret), K(*t_mblk));
}
}
}
}
}
}
@ -971,14 +1074,12 @@ int ObTmpTenantFileStore::free_extent(ObTmpFileExtent *extent)
STORAGE_LOG(WARN, "invalid argument", K(ret), K(*extent));
} else if (OB_FAIL(tmp_block_manager_.get_macro_block(extent->get_block_id(), t_mblk))) {
STORAGE_LOG(WARN, "fail to get tmp macro block", K(ret));
} else if (OB_ISNULL(t_mblk)) {
ret = OB_ERR_NULL_VALUE;
STORAGE_LOG(WARN, "block is null", K(ret));
} else if (OB_FAIL(t_mblk->free(*extent))) {
STORAGE_LOG(WARN, "fail to free extent", K(ret));
} else {
if (!t_mblk->is_disked()) {
if (OB_FAIL(tmp_mem_block_manager_.free_extent(extent->get_page_nums(), t_mblk))) {
STORAGE_LOG(WARN, "fail to free extent in block cache", K(ret));
}
}
extent->reset();
if (OB_SUCC(ret) && t_mblk->is_empty()) {
if (OB_FAIL(free_macro_block(t_mblk))) {
@ -1002,14 +1103,12 @@ int ObTmpTenantFileStore::free_extent(const int64_t block_id, const int32_t star
STORAGE_LOG(WARN, "invalid argument", K(ret), K(block_id), K(start_page_id), K(page_nums));
} else if (OB_FAIL(tmp_block_manager_.get_macro_block(block_id, t_mblk))) {
STORAGE_LOG(WARN, "fail to get tmp block", K(ret), K(block_id), K(start_page_id), K(page_nums));
} else if (OB_ISNULL(t_mblk)) {
ret = OB_ERR_NULL_VALUE;
STORAGE_LOG(WARN, "block is null", K(ret));
} else if (OB_FAIL(t_mblk->free(start_page_id, page_nums))) {
STORAGE_LOG(WARN, "fail to free extent", K(ret));
} else {
if (!t_mblk->is_disked()) {
if (OB_FAIL(tmp_mem_block_manager_.free_extent(page_nums, t_mblk))) {
STORAGE_LOG(WARN, "fail to free extent in block cache", K(ret));
}
}
if (OB_SUCC(ret) && t_mblk->is_empty()) {
if (OB_FAIL(free_macro_block(t_mblk))) {
STORAGE_LOG(WARN, "fail to free tmp macro block", K(ret));
@ -1028,37 +1127,21 @@ int ObTmpTenantFileStore::free_macro_block(ObTmpMacroBlock *&t_mblk)
} else if (OB_ISNULL(t_mblk)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret));
} else if (OB_FAIL(tmp_block_manager_.free_macro_block(t_mblk->get_block_id()))) {
STORAGE_LOG(WARN, "fail to free tmp macro block for block manager", K(ret));
} else if (t_mblk->is_memory() && OB_FAIL(tmp_mem_block_manager_.check_and_free_mem_block(t_mblk))) {
STORAGE_LOG(WARN, "fail to check and free mem block", K(ret));
}
if (OB_FAIL(ret)) {
} else if (t_mblk->is_washing() &&
OB_FAIL(tmp_mem_block_manager_.wait_write_finish(t_mblk->get_block_id(), ObTmpTenantMemBlockManager::get_default_timeout_ms()))) {
STORAGE_LOG(WARN, "fail to wait write io finish", K(ret), K(t_mblk));
} else {
if (!t_mblk->is_disked()) {
if (OB_FAIL(t_mblk->give_back_buf_into_cache())) {
STORAGE_LOG(WARN, "fail to put tmp block cache", K(ret), K(t_mblk));
} else {
dec_block_cache_num(1);
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(tmp_block_manager_.free_macro_block(t_mblk->get_block_id()))) {
STORAGE_LOG(WARN, "fail to free tmp macro block for block manager", K(ret));
} else if (!t_mblk->is_disked()) {
if (OB_FAIL(tmp_mem_block_manager_.free_macro_block(t_mblk->get_block_id()))) {
STORAGE_LOG(WARN, "fail to free tmp macro block for block cache", K(ret));
} else {
// in case of repeatedly put tmp block cache
t_mblk->set_disked();
}
} else if (!t_mblk->get_macro_block_handle().get_io_handle().is_empty() &&
OB_FAIL(tmp_mem_block_manager_.wait_write_io_finish())) { // in case of doing write io
STORAGE_LOG(WARN, "fail to wait write io finish", K(ret), K(t_mblk));
}
ObTaskController::get().allow_next_syslog();
STORAGE_LOG(INFO, "finish to free a block", K(ret),
"block_id", t_mblk->get_block_id(),
"macro_id", t_mblk->get_macro_block_id(),
"dir_id", t_mblk->get_dir_id(),
"free_page_nums", t_mblk->get_free_page_nums());
t_mblk->~ObTmpMacroBlock();
allocator_.free(t_mblk);
}
ObTaskController::get().allow_next_syslog();
STORAGE_LOG(INFO, "finish to free a block", K(ret), K(*t_mblk));
t_mblk->~ObTmpMacroBlock();
allocator_.free(t_mblk);
}
return ret;
}
@ -1071,9 +1154,15 @@ int ObTmpTenantFileStore::alloc_macro_block(const int64_t dir_id, const uint64_t
if (IS_NOT_INIT) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObTmpMacroBlockManager has not been inited", K(ret));
} else if (tmp_mem_block_manager_.check_block_full()) {
ret = OB_SIZE_OVERFLOW;
STORAGE_LOG(WARN, "mem block is full", K(ret), K(tenant_id), K(dir_id));
} else if (OB_FAIL(tmp_block_manager_.alloc_macro_block(dir_id, tenant_id, t_mblk))) {
STORAGE_LOG(WARN, "cannot allocate a tmp macro block", K(ret), K(dir_id),
K(tenant_id));
} else if (OB_ISNULL(t_mblk)) {
ret = OB_ERR_NULL_VALUE;
STORAGE_LOG(WARN, "block is null", K(ret));
} else {
ObTmpBlockCacheKey key(t_mblk->get_block_id(), tenant_id);
if (OB_FAIL(tmp_mem_block_manager_.alloc_buf(key, t_mblk->get_handle()))) {
@ -1190,51 +1279,46 @@ int ObTmpTenantFileStore::read_page(ObTmpMacroBlock *block, ObTmpBlockIOInfo &io
remain_size -= size;
size = std::min(ObTmpMacroBlock::get_default_page_size(), remain_size);
} while (OB_SUCC(ret) && size > 0);
}
if (OB_SUCC(ret)) {
// guarantee read io after the finished write.
if (OB_FAIL(wait_write_io_finish_if_need())) {
STORAGE_LOG(WARN, "fail to wait previous write io", K(ret));
if (OB_SUCC(ret)) {
if (page_io_infos->count() > DEFAULT_PAGE_IO_MERGE_RATIO * page_nums) {
// merge multi page io into one.
ObMacroBlockHandle mb_handle;
ObTmpBlockIOInfo info(io_info);
int64_t p_offset = common::lower_align(io_info.offset_, ObTmpMacroBlock::get_default_page_size());
// just skip header and padding.
info.offset_ = p_offset + ObTmpMacroBlock::get_header_padding();
info.size_ = page_nums * ObTmpMacroBlock::get_default_page_size();
info.macro_block_id_ = block->get_macro_block_id();
if (OB_FAIL(page_cache_->prefetch(info, *page_io_infos, mb_handle, io_allocator_))) {
STORAGE_LOG(WARN, "fail to prefetch multi tmp page", K(ret));
} else {
if (page_io_infos->count() > DEFAULT_PAGE_IO_MERGE_RATIO * page_nums) {
// merge multi page io into one.
ObMacroBlockHandle mb_handle;
ObTmpBlockIOInfo info(io_info);
int64_t p_offset = common::lower_align(io_info.offset_, ObTmpMacroBlock::get_default_page_size());
// just skip header and padding.
info.offset_ = p_offset + ObTmpMacroBlock::get_header_padding();
info.size_ = page_nums * ObTmpMacroBlock::get_default_page_size();
info.macro_block_id_ = block->get_macro_block_id();
if (OB_FAIL(page_cache_->prefetch(info, *page_io_infos, mb_handle, io_allocator_))) {
STORAGE_LOG(WARN, "fail to prefetch multi tmp page", K(ret));
} else {
ObTmpFileIOHandle::ObIOReadHandle read_handle(mb_handle, io_info.buf_,
io_info.offset_ - p_offset, io_info.size_);
if (OB_FAIL(handle.get_io_handles().push_back(read_handle))) {
STORAGE_LOG(WARN, "Fail to push back into read_handles", K(ret));
}
}
ObTmpFileIOHandle::ObIOReadHandle read_handle(mb_handle, io_info.buf_,
io_info.offset_ - p_offset, io_info.size_);
if (OB_FAIL(handle.get_io_handles().push_back(read_handle))) {
STORAGE_LOG(WARN, "Fail to push back into read_handles", K(ret));
}
}
} else {
// just do io, page by page.
for (int i = 0; OB_SUCC(ret) && i < page_io_infos->count(); i++) {
ObMacroBlockHandle mb_handle;
ObTmpBlockIOInfo info(io_info);
info.offset_ = page_io_infos->at(i).key_.get_page_id() * ObTmpMacroBlock::get_default_page_size();
// just skip header and padding.
info.offset_ += ObTmpMacroBlock::get_header_padding();
info.size_ = ObTmpMacroBlock::get_default_page_size();
info.macro_block_id_ = block->get_macro_block_id();
if (OB_FAIL(page_cache_->prefetch(page_io_infos->at(i).key_, info, mb_handle, io_allocator_))) {
STORAGE_LOG(WARN, "fail to prefetch tmp page", K(ret));
} else {
// just do io, page by page.
for (int i = 0; OB_SUCC(ret) && i < page_io_infos->count(); i++) {
ObMacroBlockHandle mb_handle;
ObTmpBlockIOInfo info(io_info);
info.offset_ = page_io_infos->at(i).key_.get_page_id() * ObTmpMacroBlock::get_default_page_size();
// just skip header and padding.
info.offset_ += ObTmpMacroBlock::get_header_padding();
info.size_ = ObTmpMacroBlock::get_default_page_size();
info.macro_block_id_ = block->get_macro_block_id();
if (OB_FAIL(page_cache_->prefetch(page_io_infos->at(i).key_, info, mb_handle, io_allocator_))) {
STORAGE_LOG(WARN, "fail to prefetch tmp page", K(ret));
} else {
char *buf = io_info.buf_ + ObTmpMacroBlock::calculate_offset(
page_io_infos->at(i).key_.get_page_id(), page_io_infos->at(i).offset_) - io_info.offset_;
ObTmpFileIOHandle::ObIOReadHandle read_handle(mb_handle, buf, page_io_infos->at(i).offset_,
page_io_infos->at(i).size_);
if (OB_FAIL(handle.get_io_handles().push_back(read_handle))) {
STORAGE_LOG(WARN, "Fail to push back into read_handles", K(ret));
}
}
char *buf = io_info.buf_ + ObTmpMacroBlock::calculate_offset(
page_io_infos->at(i).key_.get_page_id(), page_io_infos->at(i).offset_) - io_info.offset_;
ObTmpFileIOHandle::ObIOReadHandle read_handle(mb_handle, buf, page_io_infos->at(i).offset_,
page_io_infos->at(i).size_);
if (OB_FAIL(handle.get_io_handles().push_back(read_handle))) {
STORAGE_LOG(WARN, "Fail to push back into read_handles", K(ret));
}
}
}
@ -1247,19 +1331,6 @@ int ObTmpTenantFileStore::read_page(ObTmpMacroBlock *block, ObTmpBlockIOInfo &io
return ret;
}
int ObTmpTenantFileStore::wait_write_io_finish_if_need()
{
// guarantee read io after the finished write.
int ret = OB_SUCCESS;
SpinWLockGuard guard(lock_);
if (tmp_mem_block_manager_.check_need_wait_write()) {
if (OB_FAIL(tmp_mem_block_manager_.wait_write_io_finish())) {
STORAGE_LOG(WARN, "fail to wait previous write io", K(ret));
}
}
return ret;
}
int ObTmpTenantFileStore::write(const ObTmpBlockIOInfo &io_info)
{
int ret = OB_SUCCESS;
@ -1272,45 +1343,88 @@ int ObTmpTenantFileStore::write(const ObTmpBlockIOInfo &io_info)
} else if (OB_ISNULL(block)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "the block is NULL", K(ret), K_(io_info.block_id));
} else if (!block->is_disked()) {
} else if (block->is_memory()) {
block->set_io_desc(io_info.io_desc_);
MEMCPY(block->get_buffer() + io_info.offset_, io_info.buf_, io_info.size_);
// TODO: wash this block
if (0 == block->get_free_page_nums()) {
// NOTICE:
// 1. The extent info must be update before this. But, it doesn't support
// this at present. So, the free_page_nums is not up to date. If no modify,
// it could bring the program into a error status.
}
} else {
// Skip washing and disked status
// Won't change io_info for retry alloc block.
ret = OB_NOT_SUPPORTED;
STORAGE_LOG(WARN, "fail to write tmp block, because of not support update-in-place",
K(ret), K(io_info));
// TODO: 1. read io. 2. write io.
}
return ret;
}
int ObTmpTenantFileStore::sync(const int64_t block_id)
int ObTmpTenantFileStore::wash_block(const int64_t block_id,
ObTmpTenantMemBlockManager::ObIOWaitInfoHandle &handle)
{
int ret = OB_SUCCESS;
SpinWLockGuard guard(lock_);
ObTmpMacroBlock *block = NULL;
if (IS_NOT_INIT) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObTmpTenantFileStore has not been inited", K(ret), K(block_id));
} else if (OB_UNLIKELY(block_id <= 0)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), K(block_id));
} else if (OB_FAIL(tmp_mem_block_manager_.try_sync(block_id))) {
// OB_HASH_NOT_EXIST:
// if multiple file sync same block, the block may be not exist in hash map.
// OB_STATE_NOT_MATCH:
// the extents in block may be not all close and shouldn't sync it now.
if (OB_HASH_NOT_EXIST == ret || OB_STATE_NOT_MATCH == ret) {
ret = OB_SUCCESS;
} else {
STORAGE_LOG(WARN, "sync block failed", K(ret), K(block_id));
}
} else if (OB_FAIL(tmp_block_manager_.get_macro_block(block_id, block))) {
STORAGE_LOG(WARN, "fail to get block from tmp block manager", K(ret), K(block_id));
} else if (OB_ISNULL(block)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "the block is NULL", K(ret), K(block_id));
} else if (OB_FAIL(tmp_mem_block_manager_.wash_block(block_id, handle))) {
STORAGE_LOG(WARN, "wash block failed", K(ret), K(block_id));
}
return ret;
}
int ObTmpTenantFileStore::sync_block(const int64_t block_id,
ObTmpTenantMemBlockManager::ObIOWaitInfoHandle &handle)
{
int ret = OB_SUCCESS;
ObTmpMacroBlock *blk = NULL;
SpinRLockGuard guard(lock_);
bool is_closed = false;
if (IS_NOT_INIT) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObTmpTenantFileStore has not been inited", K(ret), K(block_id));
} else if (OB_UNLIKELY(block_id <= 0)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), K(block_id));
} else if (OB_FAIL(tmp_block_manager_.get_macro_block(block_id, blk))) {
STORAGE_LOG(WARN, "fail to get macro block", K(ret), K(block_id));
} else if (OB_FAIL(blk->is_extents_closed(is_closed))) {
STORAGE_LOG(WARN, "check block closed failed", K(ret), K(block_id));
} else if (!is_closed) {
//do nothing
} else if (OB_FAIL(tmp_mem_block_manager_.wash_block(block_id, handle))) {
STORAGE_LOG(WARN, "wash block failed", K(ret), K(block_id));
}
return ret;
}
int ObTmpTenantFileStore::wait_write_finish(const int64_t block_id, const int64_t timeout_ms)
{
int ret = OB_SUCCESS;
ObTmpMacroBlock *blk = NULL;
bool is_closed = false;
if (IS_NOT_INIT) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObTmpTenantFileStore has not been inited", K(ret), K(block_id));
} else if (OB_UNLIKELY(block_id <= 0)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid argument", K(ret), K(block_id));
} else if (OB_FAIL(tmp_block_manager_.get_macro_block(block_id, blk))) {
STORAGE_LOG(WARN, "fail to get macro block", K(ret), K(block_id));
} else if (OB_ISNULL(blk)) {
ret = OB_ERR_NULL_VALUE;
STORAGE_LOG(WARN, "macro block is NULL", K(ret), K(block_id));
} else if (!blk->is_washing()) {
// block has not been washed, nothing todo.
} else if (blk->is_washing() &&
OB_FAIL(tmp_mem_block_manager_.wait_write_finish(block_id, timeout_ms))){
STORAGE_LOG(WARN, "wait write finish failed", K(ret), K(block_id));
}
return ret;
}
@ -1328,6 +1442,19 @@ int ObTmpTenantFileStore::get_disk_macro_block_list(common::ObIArray<MacroBlockI
return ret;
}
int ObTmpTenantFileStore::get_macro_block(const int64_t block_id, ObTmpMacroBlock *&t_mblk)
{
int ret = OB_SUCCESS;
if (IS_NOT_INIT) {
ret = OB_NOT_INIT;
STORAGE_LOG(WARN, "ObTmpTenantFileStore has not been inited", K(ret));
} else if (OB_FAIL(tmp_block_manager_.get_macro_block(block_id, t_mblk))) {
STORAGE_LOG(WARN, "ObTmpTenantFileStore get macro block failed", K(ret));
}
return ret;
}
ObTmpTenantFileStoreHandle::ObTmpTenantFileStoreHandle()
: tenant_store_(), allocator_()
{
@ -1386,10 +1513,11 @@ ObTmpFileStore &ObTmpFileStore::get_instance()
}
ObTmpFileStore::ObTmpFileStore()
: is_inited_(false),
lock_(common::ObLatchIds::TMP_FILE_STORE_LOCK),
allocator_(),
tenant_file_stores_()
: next_blk_id_(0),
tenant_file_stores_(),
lock_(),
is_inited_(false),
allocator_()
{
}
@ -1465,6 +1593,44 @@ int ObTmpFileStore::write(const uint64_t tenant_id, const ObTmpBlockIOInfo &io_i
return ret;
}
int ObTmpFileStore::wash_block(const uint64_t tenant_id, const int64_t block_id,
ObTmpTenantMemBlockManager::ObIOWaitInfoHandle &handle)
{
int ret = OB_SUCCESS;
ObTmpTenantFileStoreHandle store_handle;
if (OB_FAIL(get_store(tenant_id, store_handle))) {
STORAGE_LOG(WARN, "fail to get tmp tenant file store", K(ret), K(tenant_id), K(block_id));
} else if (OB_FAIL(store_handle.get_tenant_store()->wash_block(block_id, handle))) {
STORAGE_LOG(WARN, "fail to write the extent", K(ret), K(tenant_id), K(block_id));
}
return ret;
}
int ObTmpFileStore::wait_write_finish(const uint64_t tenant_id, const int64_t block_id, const int64_t timeout_ms)
{
int ret = OB_SUCCESS;
ObTmpTenantFileStoreHandle store_handle;
if (OB_FAIL(get_store(tenant_id, store_handle))) {
STORAGE_LOG(WARN, "fail to get tmp tenant file store", K(ret), K(tenant_id));
} else if (OB_FAIL(store_handle.get_tenant_store()->wait_write_finish(block_id, timeout_ms))) {
STORAGE_LOG(WARN, "fail to write the extent", K(ret), K(tenant_id));
}
return ret;
}
int ObTmpFileStore::sync_block(const uint64_t tenant_id, const int64_t block_id,
ObTmpTenantMemBlockManager::ObIOWaitInfoHandle &handle)
{
int ret = OB_SUCCESS;
ObTmpTenantFileStoreHandle store_handle;
if (OB_FAIL(get_store(tenant_id, store_handle))) {
STORAGE_LOG(WARN, "fail to get tmp tenant file store", K(ret), K(tenant_id));
} else if (OB_FAIL(store_handle.get_tenant_store()->sync_block(block_id, handle))) {
STORAGE_LOG(WARN, "fail to write the extent", K(ret), K(tenant_id));
}
return ret;
}
int ObTmpFileStore::inc_block_cache_num(const uint64_t tenant_id, const int64_t num)
{
int ret = OB_SUCCESS;
@ -1513,18 +1679,6 @@ int ObTmpFileStore::dec_page_cache_num(const uint64_t tenant_id, const int64_t n
return ret;
}
int ObTmpFileStore::sync(const uint64_t tenant_id, const int64_t block_id)
{
int ret = OB_SUCCESS;
ObTmpTenantFileStoreHandle store_handle;
if (OB_FAIL(get_store(tenant_id, store_handle))) {
STORAGE_LOG(WARN, "fail to get tmp tenant file store", K(ret), K(tenant_id), K(block_id));
} else if (OB_FAIL(store_handle.get_tenant_store()->sync(block_id))) {
STORAGE_LOG(WARN, "fail to write the extent", K(ret), K(tenant_id), K(block_id));
}
return ret;
}
int ObTmpFileStore::free(const uint64_t tenant_id, ObTmpFileExtent *extent)
{
int ret = OB_SUCCESS;
@ -1564,6 +1718,18 @@ int ObTmpFileStore::free_tenant_file_store(const uint64_t tenant_id)
return ret;
}
int ObTmpFileStore::get_macro_block(const int64_t tenant_id, const int64_t block_id, ObTmpMacroBlock *&t_mblk)
{
int ret = OB_SUCCESS;
ObTmpTenantFileStoreHandle store_handle;
if (OB_FAIL(get_store(tenant_id, store_handle))) {
STORAGE_LOG(WARN, "fail to get tmp tenant file store", K(ret), K(tenant_id));
} else if (OB_FAIL(store_handle.get_tenant_store()->get_macro_block(block_id, t_mblk))) {
STORAGE_LOG(WARN, "fail to free", K(ret), K(tenant_id), K(block_id));
}
return ret;
}
int ObTmpFileStore::get_macro_block_list(common::ObIArray<MacroBlockId> &macro_id_list)
{
int ret = OB_SUCCESS;
@ -1694,12 +1860,27 @@ int ObTmpFileStore::get_store(const uint64_t tenant_id, ObTmpTenantFileStoreHand
return ret;
}
int64_t ObTmpFileStore::get_next_blk_id()
{
int64_t next_blk_id = -1;
int64_t old_val = ATOMIC_LOAD(&next_blk_id_);
int64_t new_val = 0;
bool finish = false;
while (!finish) {
new_val = (old_val + 1) % INT64_MAX;
next_blk_id = new_val;
finish = (old_val == (new_val = ATOMIC_VCAS(&next_blk_id_, old_val, new_val)));
old_val = new_val;
}
return next_blk_id;
}
void ObTmpFileStore::destroy()
{
ObTmpPageCache::get_instance().destroy();
tenant_file_stores_.destroy();
allocator_.destroy();
ObTmpBlockCache::get_instance().destory();
ObTmpBlockCache::get_instance().destroy();
is_inited_ = false;
}