Files
oceanbase/src/storage/ob_handle_cache.h
chaser-ch 566e920620 Merge branch 'column_store'
Co-authored-by: wangt1xiuyi <13547954130@163.com>
Co-authored-by: yangqise7en <877793735@qq.com>
Co-authored-by: Zach41 <zach_41@163.com>
2023-10-31 15:39:22 +00:00

148 lines
3.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_STORAGE_OB_HANDLE_CACHE_H_
#define OCEANBASE_STORAGE_OB_HANDLE_CACHE_H_
#include "lib/list/ob_dlist.h"
#include "lib/hash/ob_hashtable.h"
namespace oceanbase
{
namespace storage
{
template<typename Key, typename Handle>
class ObHandleCacheNode : public common::ObDLinkBase<ObHandleCacheNode<Key, Handle>>
{
public:
ObHandleCacheNode() : bucket_idx_(-1) {}
virtual ~ObHandleCacheNode() { reset(); }
void reset()
{
ObDLinkBase<ObHandleCacheNode<Key, Handle>>::reset();
handle_.reset();
bucket_idx_ = -1;
}
Handle handle_;
Key key_;
int16_t bucket_idx_;
};
template<typename Key, typename Handle, int64_t N>
class ObHandleCache
{
typedef ObHandleCacheNode<Key, Handle> CacheNode;
typedef common::ObDList<CacheNode> LRUList;
public:
ObHandleCache()
{
STATIC_ASSERT(N <= 8192, "number of bucket is larger than 8192");
reset();
}
virtual ~ObHandleCache() {}
void reset()
{
lru_list_.reset();
for (int64_t i = 0; i < N; ++i) {
nodes_[i].reset();
}
MEMSET(buckets_, -1, sizeof(buckets_));
MEMSET(chain_, -1, sizeof(chain_));
hold_size_ = 0;
}
int get_handle(const Key &key, Handle &handle)
{
int ret = common::OB_SUCCESS;
int16_t idx = buckets_[key.hash() & MASK];
while (-1 < idx) {
if (nodes_[idx].key_ == key) {
handle = nodes_[idx].handle_;
break;
} else {
idx = chain_[idx];
}
}
if (-1 == idx) {
STORAGE_LOG(DEBUG, "get handle from handle cache failed", K(key));
ret = common::OB_ENTRY_NOT_EXIST;
} else {
STORAGE_LOG(DEBUG, "get handle from handle cache succeed", K(key));
lru_list_.remove(&nodes_[idx]);
lru_list_.add_first(&nodes_[idx]);
}
return ret;
}
int put_handle(const Key &key, Handle &handle)
{
int ret = common::OB_SUCCESS;
CacheNode *node = lru_list_.get_size() >= N ? lru_list_.remove_last() : nodes_ + lru_list_.get_size();
const int16_t node_idx = static_cast<int16_t>(node - nodes_);
int16_t *idx_ptr = NULL;
int16_t idx = 0;
if (-1 < node->bucket_idx_) {
idx_ptr = &buckets_[node->bucket_idx_];
idx = buckets_[node->bucket_idx_];
while (OB_LIKELY(-1 < idx) && (node_idx != idx)) {
idx_ptr = &chain_[idx];
idx = chain_[idx];
}
if (OB_UNLIKELY(-1 == idx)) {
ret = common::OB_ERR_UNEXPECTED;
lru_list_.add_last(node);
STORAGE_LOG(WARN, "idx can not be -1, the entry must exist", K(ret), K(key), K(node->bucket_idx_));
} else {
*idx_ptr = chain_[idx];
chain_[idx] = -1;
}
}
if (OB_SUCC(ret)) {
hold_size_ += handle.get_handle_size() - node->handle_.get_handle_size();
node->reset();
node->key_ = key;
node->handle_ = handle;
node->bucket_idx_ = key.hash() & MASK;
idx_ptr = &buckets_[node->bucket_idx_];
chain_[node_idx] = *idx_ptr;
*idx_ptr = node_idx;
lru_list_.add_first(node);
STORAGE_LOG(DEBUG, "put handle succeed", K(key));
}
return ret;
}
OB_INLINE int64_t hold() const { return hold_size_; }
private:
static const uint64_t BUCKET_SIZE = common::next_pow2(N * 2);
static const uint64_t MASK = BUCKET_SIZE - 1;
CacheNode nodes_[N];
int16_t buckets_[BUCKET_SIZE];
int16_t chain_[N];
LRUList lru_list_;
int64_t hold_size_;
};
}
}
#endif /* OCEANBASE_STORAGE_OB_HANDLE_CACHE_H_ */