275 lines
12 KiB
C++
275 lines
12 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_archive_block.h"
|
|
|
|
#include "common/ob_clock_generator.h"
|
|
#include "share/ob_define.h"
|
|
#include "lib/checksum/ob_crc64.h"
|
|
#include "lib/utility/utility.h"
|
|
#include "lib/utility/serialization.h"
|
|
|
|
namespace oceanbase {
|
|
|
|
using namespace common;
|
|
namespace archive {
|
|
ObArchiveBlockMeta::ObArchiveBlockMeta()
|
|
{
|
|
reset();
|
|
}
|
|
|
|
ObArchiveBlockMeta::~ObArchiveBlockMeta()
|
|
{
|
|
reset();
|
|
}
|
|
|
|
int ObArchiveBlockMeta::generate_block_(const char* buf, const int64_t data_len)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
int64_t meta_len = get_serialize_size();
|
|
int64_t total_len = data_len + meta_len;
|
|
|
|
magic_ = META_MAGIC;
|
|
version_ = ARCHIVE_BLOCK_VERSION;
|
|
total_len_ = total_len;
|
|
timestamp_ = ObClockGenerator::getClock();
|
|
data_checksum_ = calc_data_checksum_(buf, data_len);
|
|
meta_checksum_ = calc_meta_checksum_();
|
|
|
|
return ret;
|
|
}
|
|
|
|
void ObArchiveBlockMeta::reset()
|
|
{
|
|
magic_ = META_MAGIC;
|
|
version_ = ARCHIVE_BLOCK_VERSION;
|
|
total_len_ = 0;
|
|
timestamp_ = OB_INVALID_TIMESTAMP;
|
|
|
|
clog_epoch_id_ = OB_INVALID_TIMESTAMP;
|
|
accum_checksum_ = 0;
|
|
min_log_id_in_file_ = OB_INVALID_ID;
|
|
min_log_ts_in_file_ = OB_INVALID_TIMESTAMP;
|
|
max_log_id_ = OB_INVALID_ID;
|
|
max_checkpoint_ts_ = OB_INVALID_TIMESTAMP;
|
|
max_log_submit_ts_ = OB_INVALID_TIMESTAMP;
|
|
|
|
input_bytes_ = 0;
|
|
output_bytes_ = 0;
|
|
|
|
data_checksum_ = 0;
|
|
meta_checksum_ = 0;
|
|
}
|
|
|
|
bool ObArchiveBlockMeta::check_integrity(const char* data_buf, const int64_t data_len) const
|
|
{
|
|
bool bool_ret = true;
|
|
int16_t magic = META_MAGIC;
|
|
if (magic != magic_) {
|
|
bool_ret = false;
|
|
ARCHIVE_LOG(WARN, "magic is different", "magic", magic_, "expected", magic);
|
|
} else if (!check_meta_checksum()) {
|
|
bool_ret = false;
|
|
ARCHIVE_LOG(WARN, "check meta checksum fails", "meta", to_cstring(*this));
|
|
} else if (!check_data_checksum_(data_buf, data_len)) {
|
|
bool_ret = false;
|
|
ARCHIVE_LOG(WARN, "check data checksum fails");
|
|
} else {
|
|
// do nothing
|
|
}
|
|
return bool_ret;
|
|
}
|
|
|
|
bool ObArchiveBlockMeta::check_data_checksum_(const char* buf, const int64_t data_len) const
|
|
{
|
|
bool bool_ret = true;
|
|
int64_t ori_data_len = get_data_len();
|
|
|
|
// we do not allow null buf here
|
|
if (NULL == buf || data_len <= 0) {
|
|
bool_ret = false;
|
|
ARCHIVE_LOG(WARN, "buf is null", K(data_len), K(*this));
|
|
} else if (data_len == ori_data_len) {
|
|
int64_t crc_check_sum = ob_crc64(buf, data_len);
|
|
if (crc_check_sum == data_checksum_) {
|
|
// checksum pass
|
|
} else {
|
|
bool_ret = false;
|
|
ARCHIVE_LOG(ERROR, "checksum is not consistent", KP(buf), K(data_len), K(crc_check_sum), K(data_checksum_));
|
|
}
|
|
} else {
|
|
bool_ret = false;
|
|
ARCHIVE_LOG(ERROR, "data_len is not the same", KP(buf), K(data_len), K(ori_data_len), K(data_checksum_));
|
|
}
|
|
return bool_ret;
|
|
}
|
|
|
|
bool ObArchiveBlockMeta::check_meta_checksum() const
|
|
{
|
|
bool bool_ret = true;
|
|
int64_t calc_checksum = calc_meta_checksum_();
|
|
if (meta_checksum_ != calc_checksum) {
|
|
bool_ret = false;
|
|
ARCHIVE_LOG(WARN, "failed to checkmeta checksum ", K(calc_checksum), K(meta_checksum_));
|
|
}
|
|
return bool_ret;
|
|
}
|
|
|
|
int64_t ObArchiveBlockMeta::calc_data_checksum_(const char* buf, const int64_t data_len) const
|
|
{
|
|
int64_t checksum = 0;
|
|
if ((NULL == buf) && (data_len == 0)) {
|
|
// correct situation, checksum = 0 is expected
|
|
} else if ((NULL != buf) && (data_len > 0)) {
|
|
checksum = ob_crc64(buf, data_len);
|
|
} else {
|
|
// wrong situations, checksum = 0 is default
|
|
ARCHIVE_LOG(ERROR, "data checksum", "buf", buf, "data_len", data_len);
|
|
}
|
|
return checksum;
|
|
}
|
|
|
|
int64_t ObArchiveBlockMeta::calc_meta_checksum_() const
|
|
{
|
|
int64_t checksum = 0;
|
|
// excludes meta_checksum_, the calculation relies on the structure of the meta
|
|
int64_t calc_checksum_len = sizeof(*this) - sizeof(meta_checksum_);
|
|
checksum = ob_crc64(this, calc_checksum_len);
|
|
return checksum;
|
|
}
|
|
|
|
int ObArchiveBlockMeta::serialize(char* buf, const int64_t buf_len, int64_t& pos) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
int64_t new_pos = pos;
|
|
if ((NULL == buf) || (buf_len <= 0)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
ARCHIVE_LOG(WARN, "invalid argument", KR(ret), KP(buf), K(buf_len));
|
|
} else if (OB_FAIL(serialization::encode_i16(buf, buf_len, new_pos, magic_))) {
|
|
ARCHIVE_LOG(WARN, "failed to serialize magic_", KR(ret), K(pos), K(buf_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::encode_i16(buf, buf_len, new_pos, version_))) {
|
|
ARCHIVE_LOG(WARN, "failed to serialize version_", KR(ret), K(pos), K(buf_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::encode_i32(buf, buf_len, new_pos, total_len_))) {
|
|
ARCHIVE_LOG(WARN, "failed to serialize total_len_", KR(ret), K(pos), K(buf_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::encode_i64(buf, buf_len, new_pos, timestamp_))) {
|
|
ARCHIVE_LOG(WARN, "failed to serialize timestamp_", KR(ret), K(pos), K(buf_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::encode_i64(buf, buf_len, new_pos, clog_epoch_id_))) {
|
|
ARCHIVE_LOG(WARN, "failed to serialize clog_epoch_id_", KR(ret), K(pos), K(buf_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::encode_i64(buf, buf_len, new_pos, accum_checksum_))) {
|
|
ARCHIVE_LOG(WARN, "failed to serialize accum_checksum_", KR(ret), K(pos), K(buf_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::encode_i64(buf, buf_len, new_pos, min_log_id_in_file_))) {
|
|
ARCHIVE_LOG(WARN, "failed to serialize min_log_id_in_file_", KR(ret), K(pos), K(buf_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::encode_i64(buf, buf_len, new_pos, min_log_ts_in_file_))) {
|
|
ARCHIVE_LOG(WARN, "failed to serialize min_log_ts_in_file_", KR(ret), K(pos), K(buf_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::encode_i64(buf, buf_len, new_pos, max_log_id_))) {
|
|
ARCHIVE_LOG(WARN, "failed to serialize max_log_id_", KR(ret), K(pos), K(buf_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::encode_i64(buf, buf_len, new_pos, max_checkpoint_ts_))) {
|
|
ARCHIVE_LOG(WARN, "failed to serialize max_checkpoint_ts_", KR(ret), K(pos), K(buf_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::encode_i64(buf, buf_len, new_pos, max_log_submit_ts_))) {
|
|
ARCHIVE_LOG(WARN, "failed to serialize max_log_submit_ts_", KR(ret), K(pos), K(buf_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::encode_i64(buf, buf_len, new_pos, input_bytes_))) {
|
|
ARCHIVE_LOG(WARN, "failed to serialize input_bytes_", KR(ret), K(pos), K(buf_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::encode_i64(buf, buf_len, new_pos, output_bytes_))) {
|
|
ARCHIVE_LOG(WARN, "failed to serialize output_bytes_", KR(ret), K(pos), K(buf_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::encode_i64(buf, buf_len, new_pos, data_checksum_))) {
|
|
ARCHIVE_LOG(WARN, "failed to serialize data_checksum_", KR(ret), K(pos), K(buf_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::encode_i64(buf, buf_len, new_pos, meta_checksum_))) {
|
|
ARCHIVE_LOG(WARN, "failed to serialize meta_checksum_", KR(ret), K(pos), K(buf_len), K(new_pos));
|
|
} else {
|
|
pos = new_pos;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObArchiveBlockMeta::deserialize(const char* buf, const int64_t data_len, int64_t& pos)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
int64_t new_pos = pos;
|
|
if ((NULL == buf) || (data_len <= 0)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
ARCHIVE_LOG(TRACE, "invalid argument", KR(ret), KP(buf), K(data_len));
|
|
} else if (OB_FAIL(serialization::decode_i16(buf, data_len, new_pos, &magic_))) {
|
|
ARCHIVE_LOG(TRACE, "failed to deserialize magic_", KR(ret), K(pos), K(data_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::decode_i16(buf, data_len, new_pos, &version_))) {
|
|
ARCHIVE_LOG(TRACE, "failed to deserialize version_", KR(ret), K(pos), K(data_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::decode_i32(buf, data_len, new_pos, &total_len_))) {
|
|
ARCHIVE_LOG(TRACE, "failed to deserialize total_len_", KR(ret), K(pos), K(data_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::decode_i64(buf, data_len, new_pos, ×tamp_))) {
|
|
ARCHIVE_LOG(TRACE, "failed to deserialize timestamp_", KR(ret), K(pos), K(data_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::decode_i64(buf, data_len, new_pos, &clog_epoch_id_))) {
|
|
ARCHIVE_LOG(TRACE, "failed to deserialize clog_epoch_id_", KR(ret), K(pos), K(data_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::decode_i64(buf, data_len, new_pos, &accum_checksum_))) {
|
|
ARCHIVE_LOG(TRACE, "failed to deserialize accum_checksum_", KR(ret), K(pos), K(data_len), K(new_pos));
|
|
} else if (OB_FAIL(
|
|
serialization::decode_i64(buf, data_len, new_pos, reinterpret_cast<int64_t*>(&min_log_id_in_file_)))) {
|
|
ARCHIVE_LOG(WARN, "failed to deserialize min_log_id_in_file_", KR(ret), K(pos), K(data_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::decode_i64(buf, data_len, new_pos, &min_log_ts_in_file_))) {
|
|
ARCHIVE_LOG(WARN, "failed to deserialize min_log_ts_in_file_", KR(ret), K(pos), K(data_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::decode_i64(buf, data_len, new_pos, reinterpret_cast<int64_t*>(&max_log_id_)))) {
|
|
ARCHIVE_LOG(WARN, "failed to deserialize max_log_id_", KR(ret), K(pos), K(data_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::decode_i64(buf, data_len, new_pos, &max_checkpoint_ts_))) {
|
|
ARCHIVE_LOG(WARN, "failed to deserialize max_checkpoint_ts_", KR(ret), K(pos), K(data_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::decode_i64(buf, data_len, new_pos, &max_log_submit_ts_))) {
|
|
ARCHIVE_LOG(WARN, "failed to deserialize max_log_submit_ts_", KR(ret), K(pos), K(data_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::decode_i64(buf, data_len, new_pos, &input_bytes_))) {
|
|
ARCHIVE_LOG(TRACE, "failed to deserialize input_bytes_", KR(ret), K(pos), K(data_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::decode_i64(buf, data_len, new_pos, &output_bytes_))) {
|
|
ARCHIVE_LOG(TRACE, "failed to deserialize output_bytes_", KR(ret), K(pos), K(data_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::decode_i64(buf, data_len, new_pos, &data_checksum_))) {
|
|
ARCHIVE_LOG(TRACE, "failed to deserialize data_checksum_", KR(ret), K(pos), K(data_len), K(new_pos));
|
|
} else if (OB_FAIL(serialization::decode_i64(buf, data_len, new_pos, &meta_checksum_))) {
|
|
ARCHIVE_LOG(TRACE, "failed to deserialize meta_checksum_", KR(ret), K(pos), K(data_len), K(new_pos));
|
|
} else {
|
|
pos = new_pos;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int64_t ObArchiveBlockMeta::get_serialize_size(void) const
|
|
{
|
|
int64_t size = 0;
|
|
size += serialization::encoded_length_i16(magic_);
|
|
size += serialization::encoded_length_i16(version_);
|
|
size += serialization::encoded_length_i32(total_len_);
|
|
size += serialization::encoded_length_i64(timestamp_);
|
|
size += serialization::encoded_length_i64(clog_epoch_id_);
|
|
size += serialization::encoded_length_i64(accum_checksum_);
|
|
size += serialization::encoded_length_i64(min_log_id_in_file_);
|
|
size += serialization::encoded_length_i64(min_log_ts_in_file_);
|
|
size += serialization::encoded_length_i64(max_log_id_);
|
|
size += serialization::encoded_length_i64(max_checkpoint_ts_);
|
|
size += serialization::encoded_length_i64(max_log_submit_ts_);
|
|
size += serialization::encoded_length_i64(input_bytes_);
|
|
size += serialization::encoded_length_i64(output_bytes_);
|
|
size += serialization::encoded_length_i64(data_checksum_);
|
|
size += serialization::encoded_length_i64(meta_checksum_);
|
|
return size;
|
|
}
|
|
|
|
int ObArchiveBlockMeta::build_serialized_block(
|
|
char* buf, const int64_t buf_len, const char* data_buf, const int64_t data_len, int64_t& pos)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(buf) || (buf_len <= 0) || OB_ISNULL(data_buf) || (data_len <= 0)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
ARCHIVE_LOG(ERROR, "invalid argument", K(ret), KP(buf), K(buf_len), KP(data_buf), K(data_len));
|
|
} else if (OB_FAIL(generate_block_(data_buf, data_len))) {
|
|
ARCHIVE_LOG(ERROR, "generate block failed.", K(ret), KP(buf), K(data_len));
|
|
} else if (OB_FAIL(serialize(buf, buf_len, pos))) {
|
|
ARCHIVE_LOG(ERROR, "serialize block_meta_ failed.", K(ret), KP(buf), K(buf_len), K(pos));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
} // namespace archive
|
|
} // end namespace oceanbase
|