Bugfix: incorrect data was read from the temporary file in direct reading scenario.

This commit is contained in:
ND501
2024-02-18 08:55:00 +00:00
committed by ob-robot
parent bff9af6491
commit 6ebb015322
5 changed files with 84 additions and 17 deletions

View File

@ -147,11 +147,27 @@ int ObTmpPageCache::inner_read_io(const ObTmpBlockIOInfo &io_info,
} }
int ObTmpPageCache::direct_read(const ObTmpBlockIOInfo &info, int ObTmpPageCache::direct_read(const ObTmpBlockIOInfo &info,
ObMacroBlockHandle &mb_handle) ObMacroBlockHandle &mb_handle,
common::ObIAllocator &allocator)
{ {
int ret = OB_SUCCESS; int ret = OB_SUCCESS;
if (OB_FAIL(inner_read_io(info, nullptr, mb_handle))) { void *buf = nullptr;
STORAGE_LOG(WARN, "fail to inner read io", K(ret), K(mb_handle)); ObTmpDirectReadPageIOCallback *callback = nullptr;
if (OB_ISNULL(buf = allocator.alloc(sizeof(ObTmpDirectReadPageIOCallback)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
STORAGE_LOG(WARN, "allocate callback memory failed", K(ret));
} else {
// fill the callback
callback = new (buf) ObTmpDirectReadPageIOCallback;
callback->cache_ = this;
callback->offset_ = info.offset_;
callback->allocator_ = &allocator;
if (OB_FAIL(inner_read_io(info, callback, mb_handle))) {
STORAGE_LOG(WARN, "fail to inner read io", K(ret), K(mb_handle));
}
// There is no need to handle error cases (freeing the memory of the
// callback) because inner_read_io will handle error cases and free the
// memory of the callback.
} }
return ret; return ret;
} }
@ -182,6 +198,9 @@ int ObTmpPageCache::prefetch(
if (OB_FAIL(inner_read_io(info, callback, mb_handle))) { if (OB_FAIL(inner_read_io(info, callback, mb_handle))) {
STORAGE_LOG(WARN, "fail to inner read io", K(ret), K(mb_handle)); STORAGE_LOG(WARN, "fail to inner read io", K(ret), K(mb_handle));
} }
// There is no need to handle error cases (freeing the memory of the
// callback) because inner_read_io will handle error cases and free the
// memory of the callback.
} }
} }
return ret; return ret;
@ -213,6 +232,9 @@ int ObTmpPageCache::prefetch(
} else if (OB_FAIL(inner_read_io(info, callback, mb_handle))) { } else if (OB_FAIL(inner_read_io(info, callback, mb_handle))) {
STORAGE_LOG(WARN, "fail to inner read io", K(ret), K(mb_handle)); STORAGE_LOG(WARN, "fail to inner read io", K(ret), K(mb_handle));
} }
// There is no need to handle error cases (freeing the memory of the
// callback) because inner_read_io will handle error cases and free the
// memory of the callback.
} }
} }
return ret; return ret;
@ -381,6 +403,37 @@ const char *ObTmpPageCache::ObTmpMultiPageIOCallback::get_data()
return data_buf_; return data_buf_;
} }
int64_t ObTmpPageCache::ObTmpDirectReadPageIOCallback::size() const
{
return sizeof(*this);
}
const char * ObTmpPageCache::ObTmpDirectReadPageIOCallback::get_data()
{
return data_buf_;
}
int ObTmpPageCache::ObTmpDirectReadPageIOCallback::inner_process(const char *data_buffer, const int64_t size)
{
int ret = OB_SUCCESS;
ObTimeGuard time_guard("ObTmpDirectReadPageIOCallback", 100000); //100ms
if (OB_ISNULL(cache_) || OB_ISNULL(allocator_)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "Invalid tmp page cache callback allocator", KP_(cache), KP_(allocator), K(ret));
} else if (OB_UNLIKELY(size <= 0 || data_buffer == nullptr)) {
ret = OB_INVALID_DATA;
STORAGE_LOG(WARN, "invalid data buffer size", K(ret), K(size), KP(data_buffer));
} else if (OB_FAIL(alloc_data_buf(data_buffer, size))) {
STORAGE_LOG(WARN, "Fail to allocate memory, ", K(ret), K(size));
} else if (FALSE_IT(time_guard.click("alloc_data_buf"))) {
}
if (OB_FAIL(ret) && NULL != allocator_ && NULL != data_buf_) {
allocator_->free(data_buf_);
data_buf_ = NULL;
}
return ret;
}
int ObTmpPageCache::read_io(const ObTmpBlockIOInfo &io_info, ObITmpPageIOCallback *callback, int ObTmpPageCache::read_io(const ObTmpBlockIOInfo &io_info, ObITmpPageIOCallback *callback,
ObMacroBlockHandle &handle) ObMacroBlockHandle &handle)
{ {
@ -391,11 +444,7 @@ int ObTmpPageCache::read_io(const ObTmpBlockIOInfo &io_info, ObITmpPageIOCallbac
read_info.io_desc_ = io_info.io_desc_; read_info.io_desc_ = io_info.io_desc_;
read_info.macro_block_id_ = io_info.macro_block_id_; read_info.macro_block_id_ = io_info.macro_block_id_;
read_info.io_timeout_ms_ = io_info.io_timeout_ms_; read_info.io_timeout_ms_ = io_info.io_timeout_ms_;
if (callback == nullptr) { read_info.io_callback_ = callback;
read_info.buf_ = io_info.buf_;
} else {
read_info.io_callback_ = callback;
}
read_info.offset_ = io_info.offset_; read_info.offset_ = io_info.offset_;
read_info.size_ = io_info.size_; read_info.size_ = io_info.size_;
read_info.io_desc_.set_group_id(ObIOModule::TMP_PAGE_CACHE_IO); read_info.io_desc_.set_group_id(ObIOModule::TMP_PAGE_CACHE_IO);

View File

@ -104,7 +104,7 @@ public:
typedef common::ObKVCache<ObTmpPageCacheKey, ObTmpPageCacheValue> BasePageCache; typedef common::ObKVCache<ObTmpPageCacheKey, ObTmpPageCacheValue> BasePageCache;
static ObTmpPageCache &get_instance(); static ObTmpPageCache &get_instance();
int init(const char *cache_name, const int64_t priority); int init(const char *cache_name, const int64_t priority);
int direct_read(const ObTmpBlockIOInfo &info, ObMacroBlockHandle &mb_handle); int direct_read(const ObTmpBlockIOInfo &info, ObMacroBlockHandle &mb_handle, common::ObIAllocator &allocator);
int prefetch( int prefetch(
const ObTmpPageCacheKey &key, const ObTmpPageCacheKey &key,
const ObTmpBlockIOInfo &info, const ObTmpBlockIOInfo &info,
@ -167,6 +167,17 @@ public:
friend class ObTmpPageCache; friend class ObTmpPageCache;
common::ObArray<ObTmpPageIOInfo> page_io_infos_; common::ObArray<ObTmpPageIOInfo> page_io_infos_;
}; };
class ObTmpDirectReadPageIOCallback final : public ObITmpPageIOCallback
{
public:
ObTmpDirectReadPageIOCallback() {}
~ObTmpDirectReadPageIOCallback() override {}
int64_t size() const override;
int inner_process(const char *data_buffer, const int64_t size) override;
const char *get_data() override;
TO_STRING_KV("callback_type:", "ObTmpDirectReadPageIOCallback", KP_(data_buf));
DISALLOW_COPY_AND_ASSIGN(ObTmpDirectReadPageIOCallback);
};
private: private:
ObTmpPageCache(); ObTmpPageCache();
~ObTmpPageCache(); ~ObTmpPageCache();

View File

@ -1347,18 +1347,25 @@ int ObTmpTenantFileStore::read_page(ObTmpMacroBlock *block, ObTmpBlockIOInfo &io
} }
if (OB_SUCC(ret)) { if (OB_SUCC(ret)) {
if (!handle.is_disable_page_cache() && page_io_infos->count() > DEFAULT_PAGE_IO_MERGE_RATIO * page_nums) { if (page_io_infos->count() > DEFAULT_PAGE_IO_MERGE_RATIO * page_nums) {
// merge multi page io into one. // merge multi page io into one.
ObMacroBlockHandle mb_handle; ObMacroBlockHandle mb_handle;
ObTmpBlockIOInfo info(io_info); ObTmpBlockIOInfo info(io_info);
int64_t p_offset = common::lower_align(io_info.offset_, ObTmpMacroBlock::get_default_page_size()); const int64_t p_offset = common::lower_align(io_info.offset_, ObTmpMacroBlock::get_default_page_size());
// just skip header and padding. // just skip header and padding.
info.offset_ = p_offset + ObTmpMacroBlock::get_header_padding(); info.offset_ = p_offset + ObTmpMacroBlock::get_header_padding();
info.size_ = page_nums * ObTmpMacroBlock::get_default_page_size(); info.size_ = page_nums * ObTmpMacroBlock::get_default_page_size();
info.macro_block_id_ = block->get_macro_block_id(); info.macro_block_id_ = block->get_macro_block_id();
if (OB_FAIL(page_cache_->prefetch(info, *page_io_infos, mb_handle, io_allocator_))) { if (handle.is_disable_page_cache()) {
STORAGE_LOG(WARN, "fail to prefetch multi tmp page", K(ret)); if (OB_FAIL(page_cache_->direct_read(info, mb_handle, io_allocator_))) {
STORAGE_LOG(WARN, "fail to direct read multi page", K(ret));
}
} else { } else {
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));
}
}
if (OB_SUCC(ret)) {
ObTmpFileIOHandle::ObIOReadHandle read_handle(mb_handle, io_info.buf_, ObTmpFileIOHandle::ObIOReadHandle read_handle(mb_handle, io_info.buf_,
io_info.offset_ - p_offset, io_info.size_); io_info.offset_ - p_offset, io_info.size_);
if (OB_FAIL(handle.get_io_handles().push_back(read_handle))) { if (OB_FAIL(handle.get_io_handles().push_back(read_handle))) {
@ -1376,7 +1383,7 @@ int ObTmpTenantFileStore::read_page(ObTmpMacroBlock *block, ObTmpBlockIOInfo &io
info.size_ = ObTmpMacroBlock::get_default_page_size(); info.size_ = ObTmpMacroBlock::get_default_page_size();
info.macro_block_id_ = block->get_macro_block_id(); info.macro_block_id_ = block->get_macro_block_id();
if (handle.is_disable_page_cache()) { if (handle.is_disable_page_cache()) {
if (OB_FAIL(page_cache_->direct_read(info, mb_handle))) { if (OB_FAIL(page_cache_->direct_read(info, mb_handle, io_allocator_))) {
STORAGE_LOG(WARN, "fail to direct read tmp page", K(ret)); STORAGE_LOG(WARN, "fail to direct read tmp page", K(ret));
} }
} else { } else {

View File

@ -111,7 +111,7 @@ struct ObTmpBlockIOInfo final
public: public:
ObTmpBlockIOInfo() ObTmpBlockIOInfo()
: block_id_(0), offset_(0), size_(0), io_timeout_ms_(DEFAULT_IO_WAIT_TIME_MS), tenant_id_(0), : block_id_(0), offset_(0), size_(0), io_timeout_ms_(DEFAULT_IO_WAIT_TIME_MS), tenant_id_(0),
buf_(NULL), io_desc_(), macro_block_id_() {} buf_(NULL), io_desc_(), macro_block_id_() {}
ObTmpBlockIOInfo(const int64_t block_id, const int64_t offset, const int64_t size, ObTmpBlockIOInfo(const int64_t block_id, const int64_t offset, const int64_t size,
const uint64_t tenant_id, const MacroBlockId macro_block_id, char *buf, const uint64_t tenant_id, const MacroBlockId macro_block_id, char *buf,
const common::ObIOFlag io_desc) const common::ObIOFlag io_desc)

View File

@ -680,6 +680,7 @@ TEST_F(TestTmpFile, test_big_file)
write_time = ObTimeUtility::current_time() - write_time; write_time = ObTimeUtility::current_time() - write_time;
io_info.buf_ = read_buf; io_info.buf_ = read_buf;
// Flush all held block caches to ensure that subsequent read processes will go through I/O.
ObKVGlobalCache::get_instance().erase_cache(1, "tmp_block_cache"); ObKVGlobalCache::get_instance().erase_cache(1, "tmp_block_cache");
io_info.size_ = write_size; io_info.size_ = write_size;
@ -730,7 +731,6 @@ TEST_F(TestTmpFile, test_big_file)
ObTmpFileManager::get_instance().remove(fd); ObTmpFileManager::get_instance().remove(fd);
} }
/*
TEST_F(TestTmpFile, test_big_file_disable_page_cache) TEST_F(TestTmpFile, test_big_file_disable_page_cache)
{ {
int ret = OB_SUCCESS; int ret = OB_SUCCESS;
@ -762,6 +762,7 @@ TEST_F(TestTmpFile, test_big_file_disable_page_cache)
write_time = ObTimeUtility::current_time() - write_time; write_time = ObTimeUtility::current_time() - write_time;
io_info.buf_ = read_buf; io_info.buf_ = read_buf;
// Flush all held block caches to ensure that subsequent read processes will go through I/O.
ObKVGlobalCache::get_instance().erase_cache(1, "tmp_block_cache"); ObKVGlobalCache::get_instance().erase_cache(1, "tmp_block_cache");
io_info.size_ = write_size; io_info.size_ = write_size;
@ -811,7 +812,6 @@ TEST_F(TestTmpFile, test_big_file_disable_page_cache)
ObTmpFileManager::get_instance().remove(fd); ObTmpFileManager::get_instance().remove(fd);
} }
*/
TEST_F(TestTmpFile, test_multi_small_file_single_thread_read_write) TEST_F(TestTmpFile, test_multi_small_file_single_thread_read_write)
{ {