550 lines
19 KiB
C++
550 lines
19 KiB
C++
/**
|
|
* Copyright (c) 2021 OceanBase
|
|
* OceanBase CE is licensed under Mulan PubL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
|
* You may obtain a copy of Mulan PubL v2 at:
|
|
* http://license.coscl.org.cn/MulanPubL-2.0
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
* See the Mulan PubL v2 for more details.
|
|
*/
|
|
|
|
#include "ob_ilog_per_file_cache.h"
|
|
#include "ob_raw_entry_iterator.h"
|
|
#include "ob_file_id_cache.h"
|
|
#include "ob_ilog_storage.h"
|
|
|
|
namespace oceanbase {
|
|
using namespace common;
|
|
namespace clog {
|
|
int ObIlogPerFileCache::init(const file_id_t file_id, const int64_t array_size, PageArena<>* pf_allocator)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (is_inited_) {
|
|
ret = OB_INIT_TWICE;
|
|
} else if (OB_UNLIKELY(OB_INVALID_FILE_ID == file_id) || OB_UNLIKELY(array_size <= 0) ||
|
|
OB_UNLIKELY(NULL == pf_allocator)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
CSR_LOG(ERROR, "ObIlogPerFileCache init error", K(ret), K(file_id), K(array_size), KP(pf_allocator));
|
|
} else {
|
|
pf_allocator_ = pf_allocator;
|
|
char* buf = reinterpret_cast<char*>(pf_allocator_->alloc(sizeof(ObLogCursorExt) * array_size));
|
|
if (OB_UNLIKELY(NULL == buf)) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
} else {
|
|
cursor_arr_ = reinterpret_cast<ObLogCursorExt*>(buf);
|
|
file_id_ = file_id;
|
|
arr_size_ = array_size;
|
|
tail_pos_ = 0;
|
|
is_inited_ = true;
|
|
}
|
|
}
|
|
if (OB_SUCCESS != ret && OB_INIT_TWICE != ret) {
|
|
destroy();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ObIlogPerFileCache::destroy()
|
|
{
|
|
if (is_inited_) {
|
|
is_inited_ = false;
|
|
file_id_ = OB_INVALID_FILE_ID;
|
|
pf_allocator_->free();
|
|
pf_allocator_ = NULL;
|
|
cursor_arr_ = NULL;
|
|
arr_size_ = 0;
|
|
tail_pos_ = 0;
|
|
}
|
|
}
|
|
|
|
int ObIlogPerFileCache::append_cursor(const ObLogCursorExt& cursor)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (IS_NOT_INIT) {
|
|
ret = OB_NOT_INIT;
|
|
} else if (OB_UNLIKELY(!cursor.is_valid())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
CSR_LOG(ERROR, "append cursor error, invalid cursor", K(ret), K(cursor));
|
|
} else if (OB_UNLIKELY(tail_pos_ >= arr_size_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
// inited arr_size_ error
|
|
CSR_LOG(ERROR, "append too many cursors", K(ret), K(tail_pos_), K(arr_size_));
|
|
} else {
|
|
cursor_arr_[tail_pos_] = cursor;
|
|
tail_pos_++;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObIlogPerFileCache::query_cursor(const ObPartitionKey& pkey, const uint64_t query_log_id, const uint64_t min_log_id,
|
|
const uint64_t max_log_id, const offset_t start_offset_index, ObGetCursorResult& result)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(!pkey.is_valid()) || OB_UNLIKELY(OB_INVALID_ID == query_log_id) ||
|
|
OB_UNLIKELY(OB_INVALID_ID == min_log_id) || OB_UNLIKELY(OB_INVALID_ID == max_log_id) ||
|
|
OB_UNLIKELY(min_log_id > query_log_id) || OB_UNLIKELY(max_log_id < query_log_id) ||
|
|
OB_UNLIKELY(start_offset_index < 0) || OB_UNLIKELY(start_offset_index >= tail_pos_) ||
|
|
OB_UNLIKELY(!result.is_valid())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
CSR_LOG(ERROR,
|
|
"invald argument",
|
|
K(ret),
|
|
K(pkey),
|
|
K(query_log_id),
|
|
K(min_log_id),
|
|
K(max_log_id),
|
|
K(start_offset_index),
|
|
K(tail_pos_));
|
|
} else {
|
|
const int64_t target_offset_index = static_cast<int64_t>(start_offset_index + (query_log_id - min_log_id));
|
|
const int64_t ret_len = std::min(static_cast<int64_t>(max_log_id - query_log_id + 1), result.arr_len_);
|
|
const ObLogCursorExt* start_cursor = cursor_arr_ + target_offset_index;
|
|
memcpy(result.csr_arr_, start_cursor, sizeof(ObLogCursorExt) * ret_len);
|
|
result.ret_len_ = ret_len;
|
|
CSR_LOG(DEBUG,
|
|
"[ILOG_PER_FILE_CACHE] query cursor success",
|
|
K_(file_id),
|
|
K(pkey),
|
|
K(query_log_id),
|
|
K(min_log_id),
|
|
K(max_log_id),
|
|
K(target_offset_index),
|
|
K(result));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// Return value
|
|
// 1. OB_SUCCESS SUCCESS target_log is the target log
|
|
// 2. other error code FAILURE target_log is invalid
|
|
int ObIlogPerFileCache::locate_by_timestamp(const common::ObPartitionKey& pkey, const int64_t start_ts,
|
|
const uint64_t min_log_id, const uint64_t max_log_id, const offset_t start_offset_index, uint64_t& target_log_id,
|
|
int64_t& target_log_timestamp)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!pkey.is_valid() || OB_INVALID_TIMESTAMP == start_ts || OB_INVALID_ID == min_log_id || min_log_id <= 0 ||
|
|
OB_INVALID_ID == max_log_id || max_log_id <= 0 || min_log_id > max_log_id || start_offset_index < 0 ||
|
|
start_offset_index >= tail_pos_) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
CSR_LOG(
|
|
ERROR, "invalid argument", K(ret), K(pkey), K(start_ts), K(min_log_id), K(max_log_id), K(start_offset_index));
|
|
} else {
|
|
const ObLogCursorExt* pkey_csr_arr = cursor_arr_ + start_offset_index;
|
|
const int64_t array_len = max_log_id - min_log_id + 1;
|
|
const ObLogCursorExt* target_csr = NULL;
|
|
|
|
// Binary search timestamp from array, the target_csr is the first log which log_ts
|
|
// is greater than start_ts
|
|
if (OB_FAIL(binary_search_timestamp_from_cursor_array_(pkey_csr_arr, array_len, start_ts, target_csr))) {
|
|
CSR_LOG(WARN,
|
|
"binary_search_timestamp_from_cursor_array_ fail",
|
|
K(ret),
|
|
K(pkey),
|
|
K(start_ts),
|
|
K(min_log_id),
|
|
K(max_log_id),
|
|
K(start_offset_index));
|
|
} else if (OB_ISNULL(target_csr)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
CSR_LOG(ERROR,
|
|
"binary_search_timestamp_from_cursor_array_ fail, target cursor is NULL",
|
|
K(ret),
|
|
K(pkey),
|
|
K(start_ts),
|
|
K(min_log_id),
|
|
K(max_log_id),
|
|
K(start_offset_index));
|
|
} else {
|
|
target_log_id = min_log_id + target_csr - pkey_csr_arr;
|
|
target_log_timestamp = target_csr->get_submit_timestamp();
|
|
}
|
|
|
|
CSR_LOG(INFO,
|
|
"[ILOG_PER_FILE_CACHE] locate_by_timestamp finish",
|
|
K(ret),
|
|
K(pkey),
|
|
K(start_ts),
|
|
K(min_log_id),
|
|
K(max_log_id),
|
|
K(start_offset_index),
|
|
K(target_log_id),
|
|
K(target_log_timestamp));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// Binary search a cursor which log_ts is greater than target_ts
|
|
int ObIlogPerFileCache::binary_search_timestamp_from_cursor_array_(const ObLogCursorExt* csr_arr,
|
|
const int64_t array_len, const int64_t start_ts, const ObLogCursorExt*& target_cursor)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(csr_arr) || OB_UNLIKELY(array_len <= 0) || OB_UNLIKELY(OB_INVALID_TIMESTAMP == start_ts)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
CSR_LOG(ERROR, "invalid argument", K(ret), K(csr_arr), K(array_len));
|
|
} else {
|
|
int64_t begin = 0;
|
|
int64_t end = array_len - 1;
|
|
|
|
while (begin <= end) {
|
|
int64_t middle = ((begin + end) / 2);
|
|
if (csr_arr[middle].get_submit_timestamp() >= start_ts) {
|
|
end = middle - 1;
|
|
} else {
|
|
begin = middle + 1;
|
|
}
|
|
}
|
|
|
|
if (end + 1 < array_len) {
|
|
target_cursor = csr_arr + end + 1;
|
|
} else {
|
|
ret = OB_ERR_OUT_OF_UPPER_BOUND;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObIlogPerFileCacheBuilder::init(ObIlogStorage* ilog_storage, ObFileIdCache* file_id_cache)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(NULL == ilog_storage) || OB_UNLIKELY(NULL == file_id_cache)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
CSR_LOG(ERROR, "init error", K(ret), KP(ilog_storage), KP(file_id_cache));
|
|
} else {
|
|
ilog_storage_ = ilog_storage;
|
|
file_id_cache_ = file_id_cache;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// NOTE: this operation is time-consumed
|
|
int ObIlogPerFileCacheBuilder::build_cache(
|
|
const file_id_t file_id, ObIlogPerFileCache* pf_cache, PageArena<>& pf_page_arena, ObIlogStorageQueryCost& csr_cost)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
CSR_LOG(TRACE, "[ILOG_PER_FILE_CACHE] start build", K(file_id), KP(pf_cache));
|
|
if (OB_ISNULL(ilog_storage_)) {
|
|
ret = OB_NOT_INIT;
|
|
} else if (OB_UNLIKELY(OB_INVALID_FILE_ID == file_id) || OB_UNLIKELY(NULL == pf_cache)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
CSR_LOG(ERROR, "build cache error", K(ret), K(file_id), KP(pf_cache));
|
|
} else {
|
|
ObIRawIndexIterator* raw_ilog_iter = NULL;
|
|
RawArray raw_array; // to buffer raw ilog entry from ilog file
|
|
ObArenaAllocator raw_entry_allocator(ObModIds::OB_INDEX_ITERATOR_ID); // tmp_allocator
|
|
const offset_t start_offset = 0;
|
|
if (OB_UNLIKELY(
|
|
NULL == (raw_ilog_iter = ilog_storage_->alloc_raw_index_iterator(file_id, file_id, start_offset)))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
CSR_LOG(ERROR, "alloc raw ilog iter", K(ret), K(file_id), KP(ilog_storage_), KP(raw_ilog_iter));
|
|
} else if (OB_FAIL(prepare_sorted_raw_array_(file_id, raw_ilog_iter, raw_entry_allocator, raw_array, csr_cost))) {
|
|
CSR_LOG(WARN, "prepare sorted raw_array error", K(ret), K(file_id), K(raw_array));
|
|
} else if (raw_array.count_ > 0) {
|
|
if (OB_FAIL(pf_cache->init(file_id, raw_array.count_, &pf_page_arena))) {
|
|
CSR_LOG(WARN, "init pf_cache error", K(ret), K(file_id), K(raw_array), KP(pf_cache));
|
|
} else if (OB_FAIL(build_pf_cache_(file_id, raw_array, pf_cache))) {
|
|
CSR_LOG(WARN, "build pf_cache error", K(ret), K(file_id), KP(pf_cache));
|
|
} else {
|
|
CSR_LOG(INFO, "[ILOG_PER_FILE_CACHE] build_cache success", K(ret), K(file_id), "entry_count", raw_array.count_);
|
|
}
|
|
} else {
|
|
CSR_LOG(ERROR, "[ILOG_PER_FILE_CACHE] build_cache ilog raw_array count is 0", K(file_id), K(raw_array));
|
|
}
|
|
if (OB_LIKELY(NULL != raw_ilog_iter)) {
|
|
ilog_storage_->revert_raw_index_iterator(raw_ilog_iter);
|
|
raw_ilog_iter = NULL;
|
|
}
|
|
raw_entry_allocator.clear();
|
|
}
|
|
CSR_LOG(TRACE, "[ILOG_PER_FILE_CACHE] build cache finish", K(ret), K(file_id), KP(pf_cache));
|
|
return ret;
|
|
}
|
|
|
|
// compare ret:
|
|
// e1 < e2 => -1
|
|
// e1 > e2 => 1
|
|
// e1 == e2 => 0
|
|
int ilog_entry_comparator(const void* e1, const void* e2)
|
|
{
|
|
int cmp_ret = 0;
|
|
if (OB_ISNULL(e1) || OB_ISNULL(e2)) {
|
|
int tmp_ret = common::OB_ERR_UNEXPECTED;
|
|
CSR_LOG(ERROR, "ilog_entry_comparator error, null element", K(tmp_ret), KP(e1), KP(e2));
|
|
} else {
|
|
const ObIndexEntry* i1 = reinterpret_cast<const ObIndexEntry*>(e1);
|
|
const ObIndexEntry* i2 = reinterpret_cast<const ObIndexEntry*>(e2);
|
|
if (i1->get_partition_key() != i2->get_partition_key()) {
|
|
if (i1->get_partition_key() < i2->get_partition_key()) {
|
|
cmp_ret = -1;
|
|
} else {
|
|
cmp_ret = 1;
|
|
}
|
|
} else if (i1->get_log_id() < i2->get_log_id()) {
|
|
cmp_ret = -1;
|
|
} else if (i1->get_log_id() > i2->get_log_id()) {
|
|
cmp_ret = 1;
|
|
} else {
|
|
cmp_ret = 0;
|
|
}
|
|
}
|
|
return cmp_ret;
|
|
}
|
|
|
|
int ObIlogPerFileCacheBuilder::prepare_sorted_raw_array_(const file_id_t file_id, ObIRawIndexIterator* raw_ilog_iter,
|
|
ObIAllocator& raw_entry_allocator, RawArray& raw_array, ObIlogStorageQueryCost& csr_cost)
|
|
{
|
|
// alloc -> fill -> sort
|
|
UNUSED(file_id);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(raw_ilog_iter)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
} else {
|
|
raw_array.arr_ =
|
|
reinterpret_cast<ObIndexEntry*>(raw_entry_allocator.alloc(sizeof(ObIndexEntry) * ILOG_ENTRY_COUNT_PER_FILE));
|
|
if (OB_UNLIKELY(NULL == raw_array.arr_)) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
CSR_LOG(ERROR, "alloc memory for raw_array error", K(ret), K(file_id));
|
|
} else {
|
|
ObIndexEntry ilog_entry;
|
|
int64_t count = 0;
|
|
ObReadParam param;
|
|
int64_t persist_len = 0;
|
|
while (OB_SUCC(ret) && OB_SUCC(raw_ilog_iter->next_entry(ilog_entry, param, persist_len)) &&
|
|
file_id == param.file_id_) {
|
|
ret = raw_array.arr_[count].shallow_copy(ilog_entry);
|
|
count++;
|
|
}
|
|
// always update csr_cost no matter success or not
|
|
csr_cost.read_ilog_disk_count_ += raw_ilog_iter->get_read_cost().read_disk_count_;
|
|
if (OB_ITER_END == ret) {
|
|
ret = OB_SUCCESS;
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
raw_array.count_ = count;
|
|
CSR_LOG(TRACE, "raw_array size", K(count), K(file_id));
|
|
} else {
|
|
CSR_LOG(WARN, "iterate ilog file error", K(ret), K(file_id), K(raw_array));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
qsort(raw_array.arr_, raw_array.count_, sizeof(ObIndexEntry), ilog_entry_comparator);
|
|
}
|
|
}
|
|
CSR_LOG(TRACE, "prepare_sorted_raw_array finish", K(ret), K(file_id), K(raw_array), K(csr_cost));
|
|
return ret;
|
|
}
|
|
|
|
ObLogCursorExt ObIlogPerFileCacheBuilder::trim_to_cursor_(const ObIndexEntry& entry)
|
|
{
|
|
ObLogCursorExt ret_cursor;
|
|
ret_cursor.reset(entry.get_file_id(),
|
|
entry.get_offset(),
|
|
entry.get_size(),
|
|
entry.get_accum_checksum(),
|
|
entry.get_submit_timestamp(),
|
|
entry.is_batch_committed());
|
|
return ret_cursor;
|
|
}
|
|
|
|
int ObIlogPerFileCacheBuilder::BackfillGenerator::init(const file_id_t file_id, ObFileIdCache* file_id_cache)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(OB_INVALID_FILE_ID == file_id) || OB_UNLIKELY(NULL == file_id_cache)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
CSR_LOG(ERROR, "DamGenerator init error", K(ret), K(file_id), KP(file_id_cache));
|
|
} else {
|
|
file_id_ = file_id;
|
|
file_id_cache_ = file_id_cache;
|
|
cur_offset_ = OB_INVALID_OFFSET;
|
|
|
|
cur_pkey_.reset();
|
|
cur_min_log_id_ = OB_INVALID_ID;
|
|
cur_max_log_id_ = OB_INVALID_ID;
|
|
cur_start_offset_index_ = OB_INVALID_OFFSET;
|
|
CSR_LOG(TRACE, "DamGenerator init success", K(file_id_), KP(file_id_cache_));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ObIlogPerFileCacheBuilder::BackfillGenerator::reset()
|
|
{
|
|
file_id_ = OB_INVALID_FILE_ID;
|
|
file_id_cache_ = NULL;
|
|
cur_offset_ = OB_INVALID_OFFSET;
|
|
|
|
cur_pkey_.reset();
|
|
cur_min_log_id_ = OB_INVALID_ID;
|
|
cur_max_log_id_ = OB_INVALID_ID;
|
|
cur_start_offset_index_ = OB_INVALID_OFFSET;
|
|
}
|
|
|
|
int ObIlogPerFileCacheBuilder::BackfillGenerator::end_cur_pkey_()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (OB_ISNULL(file_id_cache_)) {
|
|
ret = OB_NOT_INIT;
|
|
CSR_LOG(ERROR, "invalid file_id_cache", K(file_id_cache_));
|
|
} else if (OB_FAIL(file_id_cache_->backfill(cur_pkey_, cur_min_log_id_, file_id_, cur_start_offset_index_))) {
|
|
CSR_LOG(WARN,
|
|
"backfill file id cache fail",
|
|
K(ret),
|
|
K(cur_pkey_),
|
|
K(cur_min_log_id_),
|
|
K(file_id_),
|
|
K(cur_start_offset_index_));
|
|
} else {
|
|
CSR_LOG(TRACE,
|
|
"[ILOG_PER_FILE_CACHE] backfill success",
|
|
K(ret),
|
|
K(cur_pkey_),
|
|
K(cur_min_log_id_),
|
|
K(file_id_),
|
|
K(cur_start_offset_index_));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObIlogPerFileCacheBuilder::BackfillGenerator::do_track_(
|
|
const ObPartitionKey& pkey, const uint64_t log_id, const int32_t array_idx)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
// NOTE: travse sequentially
|
|
if (OB_UNLIKELY(OB_INVALID_OFFSET == cur_offset_ && 0 != array_idx) || OB_UNLIKELY(array_idx != (cur_offset_ + 1))) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
CSR_LOG(ERROR, "array index is not expected", K(ret), K(array_idx), K(cur_offset_));
|
|
} else if (OB_UNLIKELY(0 == array_idx)) {
|
|
cur_pkey_ = pkey;
|
|
cur_min_log_id_ = log_id;
|
|
cur_max_log_id_ = log_id;
|
|
cur_start_offset_index_ = array_idx;
|
|
} else {
|
|
const bool is_same_pkey = (cur_pkey_ == pkey);
|
|
const bool is_next_log = (cur_max_log_id_ + 1 == log_id);
|
|
|
|
if (is_same_pkey && is_next_log) {
|
|
cur_max_log_id_ = log_id;
|
|
// NOTE: logs in the same partition must be continous
|
|
} else if (is_same_pkey && !is_next_log) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
CLOG_LOG(ERROR,
|
|
"is_same_pkey, but not is_next_log",
|
|
K(ret),
|
|
K(pkey),
|
|
K(file_id_),
|
|
K(cur_min_log_id_),
|
|
K(cur_max_log_id_),
|
|
K(log_id));
|
|
} else if (OB_FAIL(end_cur_pkey_())) {
|
|
CSR_LOG(WARN,
|
|
"end_cur_pkey_ fail",
|
|
K(ret),
|
|
K(cur_pkey_),
|
|
K(pkey),
|
|
K(file_id_),
|
|
K(cur_min_log_id_),
|
|
K(cur_max_log_id_),
|
|
K(log_id));
|
|
} else {
|
|
cur_pkey_ = pkey;
|
|
cur_min_log_id_ = log_id;
|
|
cur_max_log_id_ = log_id;
|
|
cur_start_offset_index_ = array_idx;
|
|
}
|
|
}
|
|
|
|
if (OB_SUCCESS == ret) {
|
|
// update index
|
|
cur_offset_ = array_idx;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObIlogPerFileCacheBuilder::BackfillGenerator::track(const ObIndexEntry& ilog_entry, const int32_t array_idx)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const ObPartitionKey& pkey = ilog_entry.get_partition_key();
|
|
const uint64_t log_id = ilog_entry.get_log_id();
|
|
if (OB_UNLIKELY(!pkey.is_valid()) || OB_UNLIKELY(OB_INVALID_ID == log_id) || OB_UNLIKELY(array_idx < 0)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
CSR_LOG(WARN, "invalid ilog_entry", K(ret), K(pkey), K(log_id), K(ilog_entry), K(array_idx));
|
|
} else if (OB_FAIL(do_track_(pkey, log_id, array_idx))) {
|
|
CSR_LOG(WARN, "dam_generator do_track error", K(ret), K(pkey), K(log_id), K(array_idx));
|
|
} else {
|
|
// success, do nothing
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObIlogPerFileCacheBuilder::BackfillGenerator::close()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (cur_offset_ >= 0) {
|
|
if (OB_FAIL(end_cur_pkey_())) {
|
|
CSR_LOG(WARN,
|
|
"BackfillGenerator end_cur_pkey_ fail",
|
|
K(ret),
|
|
K(file_id_),
|
|
K(cur_offset_),
|
|
K(cur_pkey_),
|
|
K(cur_min_log_id_),
|
|
K(cur_max_log_id_),
|
|
K(cur_start_offset_index_));
|
|
} else {
|
|
CSR_LOG(TRACE,
|
|
"DamGenerator close success",
|
|
K(ret),
|
|
K(file_id_),
|
|
K(cur_offset_),
|
|
K(cur_pkey_),
|
|
K(cur_min_log_id_),
|
|
K(cur_max_log_id_),
|
|
K(cur_start_offset_index_));
|
|
|
|
reset();
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObIlogPerFileCacheBuilder::build_pf_cache_(
|
|
const file_id_t file_id, const RawArray& raw_array, ObIlogPerFileCache* pf_cache)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(pf_cache)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
} else if (OB_UNLIKELY(!raw_array.is_valid())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
CSR_LOG(ERROR, "invalid raw_array", K(ret), K(raw_array));
|
|
} else {
|
|
BackfillGenerator backfill_generator;
|
|
if (OB_FAIL(backfill_generator.init(file_id, file_id_cache_))) {
|
|
CSR_LOG(WARN, "backfill_generator init error", K(ret), K(file_id), K(pf_cache));
|
|
}
|
|
|
|
for (int32_t idx = 0; OB_SUCC(ret) && (idx < raw_array.count_); idx++) {
|
|
const ObIndexEntry& ilog_entry = raw_array.arr_[idx];
|
|
if (OB_FAIL(backfill_generator.track(ilog_entry, idx))) {
|
|
CSR_LOG(WARN, "backfill_generator track cur ilog_entry error", K(ret), K(ilog_entry), K(idx));
|
|
} else if (OB_FAIL(pf_cache->append_cursor(trim_to_cursor_(ilog_entry)))) {
|
|
CSR_LOG(WARN, "pf_cache append_cursor", K(ret), K(ilog_entry));
|
|
}
|
|
} // end for
|
|
|
|
// close the loop
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(backfill_generator.close())) {
|
|
CSR_LOG(WARN, "backfill_generator close error", K(ret), K(file_id), KP(pf_cache));
|
|
}
|
|
}
|
|
}
|
|
CSR_LOG(TRACE, "[ILOG_PER_FILE_CACHE] build_pf_cache finish", K(ret), K(file_id), "entry_count", raw_array.count_);
|
|
return ret;
|
|
}
|
|
} // namespace clog
|
|
} // namespace oceanbase
|