/** * 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_LOG_COMMON_ #define OCEANBASE_CLOG_OB_LOG_COMMON_ #include #include #include "share/ob_define.h" #include "share/ob_errno.h" #include "lib/utility/ob_print_utils.h" #include "lib/allocator/ob_qsync.h" #include "lib/oblog/ob_base_log_writer.h" #include "ob_log_define.h" namespace oceanbase { namespace clog { class ObICLogItem : public common::ObIBaseLogItem { public: ObICLogItem() {} virtual ~ObICLogItem() {} virtual bool is_valid() const = 0; virtual char* get_buf() = 0; virtual const char* get_buf() const = 0; virtual int64_t get_data_len() const = 0; virtual int after_flushed( const file_id_t file_id, const offset_t offset, const int error_code, const ObLogWritePoolType type) = 0; virtual int64_t to_string(char* buf, const int64_t buf_len) const = 0; }; // The new file will write ObNewLogFileBuf in the file header to avoid reading the old block when reusing log files class ObNewLogFileBuf { public: ObNewLogFileBuf() {} ~ObNewLogFileBuf() {} static char buf_[CLOG_DIO_ALIGN_SIZE] __attribute__((aligned(CLOG_DIO_ALIGN_SIZE))); private: DISALLOW_COPY_AND_ASSIGN(ObNewLogFileBuf); }; template struct TSI { public: TSI() : create_err_(0), key_() { create_err_ = pthread_key_create(&key_, release); } ~TSI() { if (0 == create_err_) { (void)pthread_key_delete(key_); } } T* get() { int err = 0; T* val = NULL; if (create_err_ != 0) { CLOG_LOG(WARN, "pthread_key create error before", K(create_err_)); } else if (NULL != (val = (T*)pthread_getspecific(key_))) { // good } else if (NULL == (val = new (std::nothrow) T())) { CLOG_LOG(WARN, "alloc value error", KP(val)); } else if (0 != (err = pthread_setspecific(key_, val))) { CLOG_LOG(WARN, "pthread set specific error", K(err), K(key_)); } if (0 != err) { release(val); val = NULL; } return val; } private: static void release(void* arg) { if (NULL != arg) { delete (T*)arg; } } int create_err_; pthread_key_t key_; }; inline common::ObQSync& get_log_file_qs() { // wait on log_file_qs before reuse static common::ObQSync log_file_qs; return log_file_qs; } int close_fd(const int fd); class ObLogMeta { public: ObLogMeta() : log_id_(common::OB_INVALID_ID), submit_timestamp_(common::OB_INVALID_TIMESTAMP), proposal_id_() {} ~ObLogMeta() {} void reset() { log_id_ = common::OB_INVALID_ID; submit_timestamp_ = common::OB_INVALID_TIMESTAMP; proposal_id_.reset(); } int set(const uint64_t log_id, const int64_t submit_timestamp, const common::ObProposalID& proposal_id) { int ret = common::OB_SUCCESS; if (common::OB_INVALID_ID == log_id || common::OB_INVALID_TIMESTAMP == submit_timestamp || !proposal_id.is_valid()) { ret = common::OB_INVALID_ARGUMENT; CLOG_LOG(WARN, "invalid arguments", K(ret), K(log_id), K(submit_timestamp), K(proposal_id)); } else { log_id_ = log_id; submit_timestamp_ = submit_timestamp; proposal_id_ = proposal_id; } return ret; } bool is_valid() const { return common::OB_INVALID_ID != log_id_ && common::OB_INVALID_TIMESTAMP != submit_timestamp_ && proposal_id_.is_valid(); } uint64_t get_log_id() const { return log_id_; } int64_t get_submit_timestamp() const { return submit_timestamp_; } const common::ObProposalID& get_proposal_id() const { return proposal_id_; } public: TO_STRING_KV(K(log_id_), K(submit_timestamp_), K(proposal_id_)); private: uint64_t log_id_; int64_t submit_timestamp_; common::ObProposalID proposal_id_; }; class ObLogInfo { OB_UNIS_VERSION(1); public: ObLogInfo() { reset(); } ~ObLogInfo() { reset(); } public: void reset() { buff_ = NULL; size_ = 0; log_id_ = common::OB_INVALID_ID; submit_timestamp_ = common::OB_INVALID_TIMESTAMP; proposal_id_.reset(); // true on purpose, if no need reset externally need_flushed_ = true; } int set(const char* buff, const int64_t size, const uint64_t log_id, const int64_t submit_timestamp, const common::ObProposalID& proposal_id, const bool need_flushed) { int ret = common::OB_SUCCESS; if (OB_ISNULL(buff) || size <= 0 || common::OB_INVALID_ID == log_id || common::OB_INVALID_TIMESTAMP == submit_timestamp || !proposal_id.is_valid()) { ret = common::OB_INVALID_ARGUMENT; CLOG_LOG(WARN, "invalid arguments", K(ret), KP(buff), K(size), K(log_id), K(submit_timestamp), K(proposal_id)); } else { buff_ = buff; size_ = size; log_id_ = log_id; submit_timestamp_ = submit_timestamp; proposal_id_ = proposal_id; need_flushed_ = need_flushed; } return ret; } int set(const char* buff, const int64_t size, const ObLogMeta& log_meta, const bool need_flushed) { return set( buff, size, log_meta.get_log_id(), log_meta.get_submit_timestamp(), log_meta.get_proposal_id(), need_flushed); } const char* get_buf() const { return buff_; } int64_t get_size() const { return size_; } uint64_t get_log_id() const { return log_id_; } int64_t get_submit_timestamp() const { return submit_timestamp_; } const common::ObProposalID& get_proposal_id() const { return proposal_id_; } bool is_valid() const { return NULL != buff_ && size_ > 0 && common::OB_INVALID_ID != log_id_ && common::OB_INVALID_TIMESTAMP != submit_timestamp_ && proposal_id_.is_valid(); } void reset_need_flushed() { need_flushed_ = false; } bool is_need_flushed() const { return need_flushed_; } TO_STRING_KV(K(size_), K(log_id_), K(submit_timestamp_), K(proposal_id_), K(need_flushed_)); private: const char* buff_; int64_t size_; uint64_t log_id_; int64_t submit_timestamp_; common::ObProposalID proposal_id_; bool need_flushed_; }; typedef common::ObSEArray ObLogInfoArray; typedef common::ObSEArray ObBatchAckArray; typedef common::ObSEArray ObLogPersistSizeArray; // used for one phase commit transactions's rpc arg #define DUMMY_PARTITION_ID common::ObPartitionKey(1000, 1000, 1000) int64_t aio_write(const int fd, void* buf, const int64_t count, const int64_t offset, const int64_t timeout, iocb& iocb, io_context_t& ctx, io_event& ioevent); } // namespace clog } // namespace oceanbase #endif // OCEANBASE_CLOG_OB_LOG_COMMON_