Files
oceanbase/src/storage/blocksstable/ob_row_cache.cpp
2023-02-15 11:42:01 +00:00

273 lines
8.5 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_row_cache.h"
#include "lib/stat/ob_diagnose_info.h"
namespace oceanbase
{
using namespace common;
using namespace storage;
namespace blocksstable
{
/**
* -----------------------------------------------------ObRowCacheKey------------------------------------------------------
*/
ObRowCacheKey::ObRowCacheKey()
: rowkey_size_(0),
tenant_id_(0),
tablet_id_(),
data_version_(-1),
table_type_(ObITable::MAX_TABLE_TYPE),
rowkey_(),
datum_utils_(nullptr)
{
}
ObRowCacheKey::ObRowCacheKey(const uint64_t tenant_id,
const ObTabletID &tablet_id,
const ObDatumRowkey &rowkey,
const ObStorageDatumUtils &datum_utils,
const int64_t data_version,
const ObITable::TableType table_type)
{
tenant_id_ = tenant_id;
tablet_id_ = tablet_id;
data_version_ = data_version;
table_type_ = table_type;
rowkey_ = rowkey;
datum_utils_ = &datum_utils;
rowkey_size_ = rowkey.get_deep_copy_size();
}
ObRowCacheKey::~ObRowCacheKey()
{
}
int ObRowCacheKey::hash(uint64_t &hash_val) const
{
int ret = OB_SUCCESS;
hash_val = static_cast<uint64_t>(table_type_);
hash_val = common::murmurhash(&tenant_id_, sizeof(tenant_id_), hash_val);
hash_val = common::murmurhash(&tablet_id_, sizeof(tablet_id_), hash_val);
hash_val = common::murmurhash(&data_version_, sizeof(data_version_), hash_val);
if (rowkey_.is_valid()) {
if (OB_ISNULL(datum_utils_)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "Unexpected error for null datum utils", K(ret), K(*this));
} else if (OB_FAIL(rowkey_.hash(*datum_utils_, hash_val))) {
STORAGE_LOG(WARN, "Failed to calc hash value for datum rowkey", K(ret), K(rowkey_));
}
}
return ret;
}
int ObRowCacheKey::equal(const ObIKVCacheKey &other, bool &equal) const
{
int ret = OB_SUCCESS;
const ObRowCacheKey &other_key = reinterpret_cast<const ObRowCacheKey&>(other);
equal = (rowkey_size_ == other_key.rowkey_size_);
equal &= tenant_id_ == other_key.tenant_id_;
equal &= tablet_id_ == other_key.tablet_id_;
equal &= (data_version_ == other_key.data_version_);
equal &= (table_type_ == other_key.table_type_);
if (equal && rowkey_size_ > 0) {
const ObStorageDatumUtils *datum_utils = (nullptr != datum_utils_) ? datum_utils_ : other_key.datum_utils_;
if (OB_ISNULL(datum_utils)) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "Invalid argument to compare row cachekey", K(ret), K(*this), K(other_key));
} else if (OB_FAIL(rowkey_.equal(other_key.rowkey_, *datum_utils, equal))) {
STORAGE_LOG(WARN, "Failed to check rowkey cache key equal", K(ret), K(rowkey_), K(other_key));
}
}
return ret;
}
uint64_t ObRowCacheKey::get_tenant_id() const
{
return tenant_id_;
}
int64_t ObRowCacheKey::size() const
{
return sizeof(*this) + rowkey_size_;
}
int ObRowCacheKey::deep_copy(char *buf, const int64_t buf_len, ObIKVCacheKey *&key) const
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(NULL == buf || buf_len < size())) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "Invalid argument, ", K(buf), K(buf_len), K(ret));
} else if (OB_UNLIKELY(!is_valid())) {
ret = OB_INVALID_DATA;
STORAGE_LOG(WARN, "Invalid row cache key, ", K(*this), K(ret));
} else {
blocksstable::ObRowCacheKey *pkey = new (buf) ObRowCacheKey();
pkey->tenant_id_ = tenant_id_;
pkey->tablet_id_ = tablet_id_;
pkey->data_version_ = data_version_;
pkey->table_type_ = table_type_;
pkey->datum_utils_ = nullptr;
if (rowkey_.is_valid() && 0 < rowkey_size_) {
ObRawBufAllocatorWrapper temp_buf(buf + sizeof(*this), rowkey_size_);
if (OB_FAIL(rowkey_.deep_copy(pkey->rowkey_, temp_buf))) {
STORAGE_LOG(WARN, "Fail to deep copy rowkey, ", K(ret));
} else {
pkey->rowkey_size_ = rowkey_size_;
key = pkey;
}
}
if (OB_FAIL(ret)) {
pkey->~ObRowCacheKey();
}
}
return ret;
}
bool ObRowCacheKey::is_valid() const
{
return OB_LIKELY(0 != tenant_id_ && tablet_id_.is_valid() && rowkey_size_ > 0
&& data_version_ > -1 && (ObITable::is_minor_sstable(table_type_)
|| ObITable::is_major_sstable(table_type_)
|| ObITable::is_ddl_sstable(table_type_)
|| ObITable::is_meta_major_sstable(table_type_))
&& rowkey_.is_valid());
}
/**
* -----------------------------------------------------ObRowCacheValue------------------------------------------------------
*/
ObRowCacheValue::ObRowCacheValue()
: datums_(nullptr),
flag_(),
size_(0),
column_cnt_(0),
start_log_ts_(0),
block_id_()
{
}
ObRowCacheValue::~ObRowCacheValue()
{
}
int ObRowCacheValue::init(const int64_t start_log_ts,
const ObDatumRow &row)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!row.row_flag_.is_valid())) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "Unexpected row", K(ret), K(row));
} else {
datums_ = row.storage_datums_;
column_cnt_ = row.get_column_count();
start_log_ts_ = start_log_ts;
flag_ = row.row_flag_;
size_ = sizeof(ObStorageDatum) * column_cnt_;
for (int64_t i = 0; OB_SUCC(ret) && i < column_cnt_; i ++) {
size_ += datums_[i].get_deep_copy_size();
}
}
return ret;
}
int64_t ObRowCacheValue::size() const
{
return sizeof(*this) + size_;
}
int ObRowCacheValue::deep_copy(char *buf, const int64_t buf_len, ObIKVCacheValue *&value) const
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(NULL == buf || buf_len < size())) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "Invalid argument, ", K(buf), K(buf_len), K(ret));
} else if (OB_UNLIKELY(!is_valid())) {
ret = OB_INVALID_DATA;
STORAGE_LOG(WARN, "Invalid row cache value, ", K(*this), K(ret));
} else {
ObRowCacheValue *pvalue = new (buf) ObRowCacheValue();
if (NULL == datums_) {
pvalue->datums_ = NULL;
} else {
pvalue->size_ = size_;
pvalue->datums_ = new (buf + sizeof(*this)) ObStorageDatum [column_cnt_];
pvalue->column_cnt_ = column_cnt_;
pvalue->start_log_ts_ = start_log_ts_;
pvalue->flag_ = flag_;
pvalue->block_id_ = block_id_;
int64_t pos = sizeof(ObRowCacheValue) + sizeof(ObStorageDatum) * column_cnt_;
for (int64_t i = 0; OB_SUCC(ret) && i < column_cnt_; i ++) {
if (OB_FAIL(pvalue->datums_[i].deep_copy(datums_[i], buf, buf_len, pos))) {
STORAGE_LOG(WARN, "Failed to deepl copy datum", K(ret), K(i));
}
}
}
value = pvalue;
}
return ret;
}
/**
* -----------------------------------------------------ObRowCache------------------------------------------------------
*/
ObRowCache::ObRowCache()
{
}
ObRowCache::~ObRowCache()
{
}
int ObRowCache::get_row(const ObRowCacheKey &key, ObRowValueHandle &handle)
{
int ret = OB_SUCCESS;
const ObRowCacheValue *value = NULL;
if (OB_UNLIKELY(!key.is_valid())) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid row cache key.", K(key), K(ret));
} else if (OB_SUCCESS != (ret = get(key, value, handle.handle_))) {
if (OB_UNLIKELY(OB_ENTRY_NOT_EXIST != ret)) {
STORAGE_LOG(WARN, "Fail to get key from row cache, ", K(ret));
}
EVENT_INC(ObStatEventIds::ROW_CACHE_MISS);
} else {
EVENT_INC(ObStatEventIds::ROW_CACHE_HIT);
if (OB_ISNULL(value)) {
ret = OB_ERR_UNEXPECTED;
STORAGE_LOG(WARN, "Unexpected error, the value is NULL, ", K(ret));
} else {
handle.row_value_ = const_cast<ObRowCacheValue*>(value);
}
}
return ret;
}
int ObRowCache::put_row(const ObRowCacheKey &key, const ObRowCacheValue &value)
{
int ret = OB_SUCCESS;
bool overwrite = true;
if (OB_UNLIKELY(!key.is_valid() || !value.is_valid())) {
ret = OB_INVALID_ARGUMENT;
STORAGE_LOG(WARN, "invalid row cache input param.", K(key), K(value), K(ret));
} else if (OB_SUCCESS != (ret = put(key, value, overwrite))) {
STORAGE_LOG(WARN, "Fail to put row to row cache, ", K(ret));
}
return ret;
}
}//end namespace blocksstable
}//end namespace oceanbase