Files
oceanbase/src/clog/ob_external_stream.h
gm 4a92b6d7df reformat source code
according to code styles, 'AccessModifierOffset' should be -2.
2021-06-17 10:40:36 +08:00

317 lines
8.9 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.
*/
#ifndef OCEANBASE_CLOG_OB_EXTERNAL_STREAM_
#define OCEANBASE_CLOG_OB_EXTERNAL_STREAM_
#include "lib/allocator/ob_qsync.h"
#include "ob_log_define.h"
#include "ob_log_external_rpc.h"
namespace oceanbase {
namespace storage {
class ObPartitionService;
}
namespace logservice {
// get log status
// describe whether need to continue fetching logs
struct NeedFetchStatus {
// Whether need to continuing fetch logs is determined based on
// whether reach upper limit and reach max log id.
bool need_fetch_;
// whether reach upper limit
bool reach_upper_limit_;
// whether reach max log id
bool reach_max_log_id_;
// need fetch log by default
NeedFetchStatus()
{
reset();
}
void reset()
{
// need fetch log by default
need_fetch_ = true;
reach_upper_limit_ = false;
reach_max_log_id_ = false;
}
void reset(const bool need_fetch, const bool reach_upper_limit, const bool reach_max_log_id)
{
need_fetch_ = need_fetch;
reach_upper_limit_ = reach_upper_limit;
reach_max_log_id_ = reach_max_log_id;
}
TO_STRING_KV(K(need_fetch_), K(reach_upper_limit_), K(reach_max_log_id_));
};
typedef int64_t ObLogRpcIDType;
static const int64_t OB_LOG_INVALID_RPC_ID = 0;
// Information about a partition in Stream
struct ObStreamItem {
static const int64_t CACHED_CURSOR_COUNT = 128;
//************* member variables *************
common::ObPartitionKey pkey_;
uint64_t next_log_id_; // next log
int64_t fetch_progress_ts_; // get log progress timestamp, log update, or heartbeat update
uint64_t last_slide_log_id_; // record the maximum log id
// the most recent RPC of the partition fetch log, which means the last RPC update of the data of the partition
ObLogRpcIDType fetch_rpc_id_;
NeedFetchStatus need_fetch_status_; // get log status
// next_cursor_ and next_log_id_ one-to-one correspondence
int64_t next_cursor_;
int64_t cursor_array_size_;
clog::ObLogCursorExt cursor_array_[CACHED_CURSOR_COUNT];
ObStreamItem()
: pkey_(),
next_log_id_(common::OB_INVALID_ID),
fetch_progress_ts_(0),
last_slide_log_id_(common::OB_INVALID_ID),
fetch_rpc_id_(OB_LOG_INVALID_RPC_ID),
need_fetch_status_(),
next_cursor_(0),
cursor_array_size_(0)
{}
ObStreamItem(const common::ObPartitionKey& pkey, const uint64_t start_log_id)
: pkey_(pkey),
next_log_id_(start_log_id),
fetch_progress_ts_(0),
last_slide_log_id_(common::OB_INVALID_ID),
fetch_rpc_id_(OB_LOG_INVALID_RPC_ID),
need_fetch_status_(),
next_cursor_(0),
cursor_array_size_(0)
{}
bool is_valid() const
{
return pkey_.is_valid() && common::OB_INVALID_ID != next_log_id_;
}
inline int get_next_cursor(const clog::ObLogCursorExt*& cursor)
{
int ret = common::OB_SUCCESS;
if (OB_UNLIKELY(next_cursor_ >= cursor_array_size_)) {
ret = common::OB_CURSOR_NOT_EXIST;
} else {
cursor = cursor_array_ + next_cursor_;
}
return ret;
}
inline void prepare_get_cursor_result(clog::ObGetCursorResult& result)
{
result.csr_arr_ = cursor_array_;
result.arr_len_ = CACHED_CURSOR_COUNT;
result.ret_len_ = 0;
}
inline int update_cursor_array(const int64_t valid_array_size)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(valid_array_size > CACHED_CURSOR_COUNT) || OB_UNLIKELY(valid_array_size <= 0)) {
ret = OB_INVALID_ARGUMENT;
} else {
next_cursor_ = 0;
cursor_array_size_ = valid_array_size;
}
return ret;
}
// move to the next log
// ensure atomicity between multiple variables
inline int next_log_fetched(const int64_t log_submit_ts)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(next_cursor_ >= cursor_array_size_)) {
ret = OB_ERR_UNEXPECTED;
} else {
next_cursor_++;
next_log_id_++;
fetch_progress_ts_ = log_submit_ts;
}
return ret;
}
inline void update_progress_tstamp(const int64_t tstamp)
{
fetch_progress_ts_ = tstamp;
}
// Check whether need to continue fetching logs based on current status.
int check_need_fetch_status(const ObLogRpcIDType fetch_rpc_id, const int64_t upper_limit_ts,
storage::ObPartitionService& part_service, bool& status_changed, bool& need_fetch, bool& reach_upper_limit,
bool& reach_max_log_id);
TO_STRING_KV(K(pkey_), K(next_log_id_), K(fetch_progress_ts_), K(last_slide_log_id_), K(fetch_rpc_id_),
K(need_fetch_status_), K(next_cursor_), K(cursor_array_size_));
private:
uint64_t get_last_slide_log_id_(const ObPartitionKey& pkey, storage::ObPartitionService& part_service);
};
typedef common::ObSEArray<ObStreamItem*, 64> ObStreamItemArray;
class ObStream {
public:
ObStream()
: processing_(false),
liboblog_instance_id_(),
lifetime_(0),
deadline_ts_(0),
item_count_(0),
rr_pointer_(0),
upper_limit_ts_(common::OB_INVALID_TIMESTAMP)
{}
~ObStream()
{
destroy();
}
struct LiboblogInstanceId;
int init(const obrpc::ObLogOpenStreamReq::ParamArray& params, const int64_t lifetime,
const LiboblogInstanceId& liboblog_instance_id);
void destroy();
inline bool is_expired() const
{
return common::ObTimeUtility::current_time() > ATOMIC_LOAD(&deadline_ts_);
}
// mark expired
void mark_expired()
{
ATOMIC_STORE(&deadline_ts_, 0);
}
void keep_alive() // extend one cycle
{
ATOMIC_STORE(&deadline_ts_, common::ObTimeUtility::current_time() + lifetime_);
}
ObStreamItem* cur_item();
ObStreamItem* next_item();
// return whether the opening is successful
// true: preempt the stream successfully
// false: preempt failed
bool start_process(const int64_t upper_limit_ts)
{
bool succ = ATOMIC_BCAS(&processing_, false, true);
if (succ) {
// extend cycle
keep_alive();
update_upper_limit(upper_limit_ts);
}
return succ;
}
void finish_process()
{
(void)ATOMIC_STORE(&processing_, false);
}
// update upper limit
void update_upper_limit(const int64_t upper_limit)
{
ATOMIC_STORE(&upper_limit_ts_, upper_limit);
}
int64_t get_upper_limit() const
{
return ATOMIC_LOAD(&upper_limit_ts_);
}
// reset progress information of each partition
void clear_progress_ts();
// for monitor
int64_t get_item_count() const
{
return item_count_;
}
int64_t get_rr_pointer() const
{
return rr_pointer_;
}
const LiboblogInstanceId& get_liboblog_instance_id() const
{
return liboblog_instance_id_;
}
DECLARE_TO_STRING;
void print_basic_info(const int64_t stream_idx, const obrpc::ObStreamSeq& stream_seq) const;
public:
// maximum number of files to be cached
static const int64_t MAX_CACHED_FILE_COUNT = 10;
public:
struct LiboblogInstanceId {
common::ObAddr addr_;
uint64_t peer_pid_;
LiboblogInstanceId()
{
addr_.reset();
peer_pid_ = 0;
}
LiboblogInstanceId(const common::ObAddr& addr, const uint64_t his_pid) : addr_(addr), peer_pid_(his_pid)
{}
void reset()
{
addr_.reset();
peer_pid_ = 0;
}
TO_STRING_KV(K(addr_), K(peer_pid_));
};
private:
static const bool PRINT_STREAM_VERBOSE = false;
private:
// The Stream information maintained by the server does not allow concurrent modification. Use this mark to check.
bool processing_;
// LiboblogInstanceId is only used for debugging, since may be multiple liboblogs pulling the same cluster.
LiboblogInstanceId liboblog_instance_id_;
// Each time a stream is requested, the life of the stream will be extended to a life_time_
// (the interval between two accesses of the stream may be different, keep flexible).
int64_t lifetime_;
// If this stream is not used until deadline_ts_, it will be washed off by the scheduled task.
int64_t deadline_ts_;
// partition count in a stream
int64_t item_count_;
// rotate partition pointer
int64_t rr_pointer_;
// upper limit of current stream
int64_t upper_limit_ts_;
// must the last element, followed by the partition information
ObStreamItem items_[0];
};
// Protect the Stream object being used from being washed.
static inline common::ObQSync& get_stream_qs()
{
static common::ObQSync stream_qs;
return stream_qs;
}
struct SeqStreamPair {
obrpc::ObStreamSeq seq_;
ObStream* stream_;
TO_STRING_KV(K(seq_), KP(stream_));
};
typedef common::ObSEArray<SeqStreamPair, 16> RetiredStreamArray;
} // namespace logservice
} // namespace oceanbase
#endif