提交 44d430d9 编写于 作者: O obdev 提交者: wangzelin.wzl

delete unused code & sys parameters

上级 ae138ca6
......@@ -119,21 +119,6 @@ public:
size_ = 0;
}
int shrink_size(int64_t size)
{
LockGuard guard(lock_);
int ret = OB_SUCCESS;
if (size <= 0 || size > capacity_) {
ret = OB_INVALID_ARGUMENT;
COMMON_LOG(WARN, "invalid argument", K(size), K_(capacity));
} else if (size * 2 <= capacity_) {
capacity_ = size * 2;
} else {
capacity_ = size;
}
return ret;
}
void print() const
{
COMMON_LOG(INFO, "array_hash dump begin:", K(this));
......
/**
* 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_LIB_HASH_OB_EXT_ITER_HASHSET_H__
#define OCEANBASE_LIB_HASH_OB_EXT_ITER_HASHSET_H__
#include "lib/hash/ob_iteratable_hashset.h" // ObIteratableHashSet
#include "lib/utility/ob_print_utils.h"
namespace oceanbase
{
namespace common
{
namespace hash
{
template <class K, uint64_t N, class Allocator> class ObExtIterHashSet;
///////////////////////////////////// ObExtIterHashSet Iterator /////////////////////////////////////
template <class HashSet>
class ObExtIterHashSetConstIterator
{
public:
typedef typename HashSet::const_key_ref_t const_key_ref_t;
typedef ObExtIterHashSetConstIterator<HashSet> SelfType;
typedef typename HashSet::HashSetBucket BucketType;
typedef typename HashSet::InnerHashSetIter InnerIter;
public:
ObExtIterHashSetConstIterator(const HashSet *set, const BucketType *bucket, const InnerIter &iter)
: hash_set_(set), bucket_(bucket), iter_(iter)
{}
ObExtIterHashSetConstIterator(const SelfType &other)
: hash_set_(other.hash_set_), bucket_(other.bucket_), iter_(other.iter_)
{}
~ObExtIterHashSetConstIterator()
{}
public:
ObExtIterHashSetConstIterator &operator=(const SelfType &other)
{
if (this != &other) {
hash_set_ = other.hash_set_;
bucket_ = other.bucket_;
iter_ = other.iter_;
}
return *this;
}
ObExtIterHashSetConstIterator &operator=(SelfType &&other) = default;
bool operator==(const SelfType &other) const
{
return other.hash_set_ == hash_set_ && other.bucket_ == bucket_ && other.iter_ == iter_;
}
bool operator!=(const SelfType &other) const
{
return other.hash_set_ != hash_set_ || other.bucket_ != bucket_ || other.iter_ != iter_;
}
SelfType &operator++()
{
if (NULL == hash_set_ || NULL == bucket_) {
LIB_LOG(ERROR, "err hash set, iter or bucket", K(hash_set_), K(bucket_));
} else {
// if current bucket is not null, fetch next one.
if (iter_ != bucket_->hash_set_.end()) {
++iter_;
}
// if reach end of current bucket, step to the next bucket.
if (iter_ == bucket_->hash_set_.end() && NULL != bucket_->next_) {
bucket_ = bucket_->next_;
iter_ = bucket_->hash_set_.begin();
}
}
return *this;
}
const_key_ref_t operator*() const
{
if (NULL == hash_set_ || NULL == bucket_) {
LIB_LOG(ERROR, "err hash set, iter or bucket", K(hash_set_), K(bucket_));
}
return *iter_;
}
private:
const HashSet *hash_set_;
const BucketType *bucket_;
InnerIter iter_;
};
///////////////////////////////////// ObExtIterHashSet /////////////////////////////////////
template <class K, uint64_t N = 1031, class Allocator = ObIAllocator>
class ObExtIterHashSet
{
public:
typedef const K &const_key_ref_t;
typedef ObIteratableHashSet<K, N> BaseHashSet;
typedef ObExtIterHashSet<K, N, Allocator> SelfType;
typedef ObExtIterHashSetConstIterator<SelfType> const_iterator_t;
typedef typename BaseHashSet::const_iterator_t InnerHashSetIter;
struct HashSetBucket
{
BaseHashSet hash_set_;
HashSetBucket *next_;
HashSetBucket() : hash_set_(), next_(NULL) {}
~HashSetBucket() {}
void reset()
{
hash_set_.reset();
next_ = NULL;
}
};
public:
explicit ObExtIterHashSet(Allocator &allocator);
virtual ~ObExtIterHashSet();
public:
/**
* @retval OB_SUCCESS insert successfully
* @retval OB_HASH_EXIST key exists
* @retval other ret failed
*/
int set_refactored(const K &key);
/**
* @retval OB_HASH_EXIST key exists
* @retval OB_HASH_NOT_EXIST key not exists
*/
int exist_refactored(const K &key) const { return is_exist_(key) ? OB_HASH_EXIST : OB_HASH_NOT_EXIST; }
void reset();
void clear() { reset(); }
const_iterator_t begin() const
{
return const_iterator_t(this, &buckets_, buckets_.hash_set_.begin());
}
const_iterator_t end() const
{
return const_iterator_t(this, buckets_tail_, buckets_tail_->hash_set_.end());
}
int64_t count() const { return count_; }
public:
DECLARE_TO_STRING;
private:
bool is_exist_(const K &key) const;
bool is_full_() const { return count_ >= bucket_num_ * static_cast<int64_t>(N); }
int add_bucket_();
private:
int64_t count_; // count of object
int64_t bucket_num_; // count of bucket
Allocator &allocator_; // allocator
HashSetBucket buckets_; // bucket lists
HashSetBucket *buckets_tail_; // bucket lists tail
private:
template <class HashSet>
friend class ObExtIterHashSetConstIterator;
private:
DISALLOW_COPY_AND_ASSIGN(ObExtIterHashSet);
};
template <class K, uint64_t N, class Allocator>
ObExtIterHashSet<K, N, Allocator>::ObExtIterHashSet(Allocator &allocator) :
count_(0),
bucket_num_(1),
allocator_(allocator),
buckets_(),
buckets_tail_(&buckets_)
{}
template <class K, uint64_t N, class Allocator>
ObExtIterHashSet<K, N, Allocator>::~ObExtIterHashSet()
{
reset();
}
template <class K, uint64_t N, class Allocator>
int ObExtIterHashSet<K, N, Allocator>::set_refactored(const K &key)
{
int ret = OB_SUCCESS;
bool exist = is_exist_(key);
if (exist) {
ret = OB_HASH_EXIST;
} else if (is_full_() && OB_FAIL(add_bucket_())) {
LIB_LOG(WARN, "add_bucket_ fail", K(ret));
} else {
// keep inserting successful
if (NULL == buckets_tail_) {
ret = OB_ERR_UNEXPECTED;
LIB_LOG(WARN, "err bucket tail", K(ret));
} else if (OB_FAIL(buckets_tail_->hash_set_.set_refactored(key))) {
LIB_LOG(WARN, "set key into hash set fail", K(ret));
} else {
count_++;
}
}
return ret;
}
template <class K, uint64_t N, class Allocator>
bool ObExtIterHashSet<K, N, Allocator>::is_exist_(const K &key) const
{
bool exist = false;
const HashSetBucket *item = &buckets_;
while (! exist && NULL != item) {
if (OB_HASH_EXIST == item->hash_set_.exist_refactored(key)) {
exist = true;
break;
} else {
item = item->next_;
}
}
return exist;
}
template <class K, uint64_t N, class Allocator>
int ObExtIterHashSet<K, N, Allocator>::add_bucket_()
{
int ret = OB_SUCCESS;
HashSetBucket *bucket = (HashSetBucket *)allocator_.alloc(sizeof(HashSetBucket));
if (NULL == bucket) {
LIB_LOG(WARN, "allocate memory for bucket fail", "bucket_size", sizeof(HashSetBucket));
ret = OB_ALLOCATE_MEMORY_FAILED;
} else {
new(bucket) HashSetBucket();
bucket->next_ = NULL;
buckets_tail_->next_ = bucket;
buckets_tail_ = bucket;
bucket_num_++;
LIB_LOG(DEBUG, "add bucket", K(bucket_num_), K(count_), K(bucket));
}
return ret;
}
template <class K, uint64_t N, class Allocator>
void ObExtIterHashSet<K, N, Allocator>::reset()
{
HashSetBucket *bucket = buckets_.next_;
while (NULL != bucket) {
HashSetBucket *next = bucket->next_;
bucket->~HashSetBucket();
allocator_.free((void*)bucket);
bucket = next;
}
bucket = NULL;
buckets_.reset();
buckets_tail_ = &buckets_;
bucket_num_ = 1;
count_ = 0;
}
template <class K, uint64_t N, class Allocator>
int64_t ObExtIterHashSet<K, N, Allocator>::to_string(char *buf, const int64_t buf_len) const
{
int64_t pos = 0;
J_ARRAY_START();
const_iterator_t beg = begin();
for (const_iterator_t it = beg;
it != end();
++it) {
if (it != beg) {
J_COMMA();
}
BUF_PRINTO(*it);
}
J_ARRAY_END();
return pos;
}
} // namespace hash
} // namespace common
} // namespace oceanbase
#endif
/**
* 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_HASH_OB_FIXED_HASH_H_
#define OCEANBASE_HASH_OB_FIXED_HASH_H_
#include "lib/ob_define.h"
#include "lib/queue/ob_link.h"
#include "lib/hash/ob_hash.h"
namespace oceanbase
{
namespace common
{
template<typename key_t>
class FixedHash
{
public:
typedef ObLink Link;
struct node_t: public Link
{
node_t(): hash_(0), key_() {}
explicit node_t(key_t key): key_(key) {
hash_ = hash_map_calc_hash(key_);
}
~node_t() {}
static uint64_t hash_map_calc_hash(key_t key)
{
return calc_hash(key) | 1;
}
node_t* set(key_t key)
{
hash_ = hash_map_calc_hash(key);
key_ = key;
return this;
}
bool is_dummy_node() {
return 0 == (hash_ & 1);
}
int compare(node_t* that)
{
int ret = 0;
if (this->hash_ > that->hash_) {
ret = 1;
} else if (this->hash_ < that->hash_) {
ret = -1;
} else if (this->is_dummy_node()) {
ret = 0;
} else {
ret = common::compare(this->key_, that->key_);
}
return ret;
}
node_t* set_as_bucket(uint64_t idx)
{
hash_ = bitrev(idx);
return this;
}
uint64_t get_spk() { return bitrev(hash_); }
uint64_t hash_;
key_t key_;
};
FixedHash(void* buf, int64_t size):
nodes_((node_t*)buf), limit_(last2n(size/sizeof(node_t))) {
init_buckets(nodes_, limit_);
}
~FixedHash() {}
int insert(key_t key, node_t* node) {
node_t key_node(key);
return ol_insert(get_pre(&key_node), node->set(key));
}
int del(key_t key, node_t*& node) {
node_t key_node(key);
return ol_del(get_pre(&key_node), &key_node, node);
}
int get(key_t key, node_t*& node) {
node_t key_node(key);
return ol_get(get_pre(&key_node), &key_node, node);
}
node_t* next(node_t* node) {
while(NULL != (node = next_node(node))
&& node->is_dummy_node())
;
return node;
}
private:
node_t* next_node(node_t* node) {
node_t* next = NULL;
if (NULL == node) {
next = nodes_;
} else if (is_last_bit_set((uint64_t)(next = (node_t*)ATOMIC_LOAD(&node->next_)))) {
next = get_pre(node);
}
return next;
}
static uint64_t last2n(const uint64_t x)
{
return x == 0? 0 : (1UL << 63) >> (__builtin_clzll(x));
}
static uint64_t bitrev(uint64_t x)
{
x = (((x & 0xaaaaaaaaaaaaaaaaUL) >> 1) | ((x & 0x5555555555555555UL) << 1));
x = (((x & 0xccccccccccccccccUL) >> 2) | ((x & 0x3333333333333333UL) << 2));
x = (((x & 0xf0f0f0f0f0f0f0f0UL) >> 4) | ((x & 0x0f0f0f0f0f0f0f0fUL) << 4));
x = (((x & 0xff00ff00ff00ff00UL) >> 8) | ((x & 0x00ff00ff00ff00ffUL) << 8));
x = (((x & 0xffff0000ffff0000UL) >> 16) | ((x & 0x0000ffff0000ffff) << 16));
return((x >> 32) | (x << 32));
}
static uint64_t get_idx(uint64_t spk, uint64_t bcnt)
{
return bcnt == 0? 0 : (spk & (bcnt - 1));
}
node_t* get_pre(node_t* key_node)
{
return nodes_ + get_idx(key_node->get_spk(), limit_);
}
static uint64_t get_bucket_pre_idx(uint64_t idx) {
return idx & ~last2n(idx);
}
static int init_buckets(node_t* nodes, int64_t limit) {
int err = 0;
new(nodes)node_t[limit];
nodes[0].set_as_bucket(0);
for(int64_t i = 1; 0 == err && i < limit; i++) {
node_t* node = nodes + i;
node->set_as_bucket(i);
err = ol_insert(nodes + get_bucket_pre_idx(i), node);
}
return err;
}
private:
node_t* nodes_;
int64_t limit_;
};
}; // end namespace common
}; // end namespace oceanbase
#endif /* OCEANBASE_HASH_OB_FIXED_HASH_H_ */
/**
* 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 SRC_LIBRARY_SRC_LIB_HASH_OB_MEMLESS_LINK_HASHMAP_H_
#define SRC_LIBRARY_SRC_LIB_HASH_OB_MEMLESS_LINK_HASHMAP_H_
#include "lib/ob_define.h"
#include "lib/hash/ob_hashutils.h"
#include "lib/atomic/ob_atomic.h"
#include "lib/utility/ob_print_utils.h"
#include "lib/container/ob_array.h"
#include "lib/lock/ob_bucket_lock.h"
namespace oceanbase
{
namespace common
{
namespace hash
{
// ObMemLessLinkHashMap is convenient for reuse of node.
// there is a simple allocator in the map.
// memory of node should be pre-allocated.
// use of storage of table and meta block.
template <class KEY, class ITEM>
struct ObPreAllocLinkHashNode
{
explicit ObPreAllocLinkHashNode(ITEM &item): item_(item) {}
virtual ~ObPreAllocLinkHashNode() { }
virtual OB_INLINE bool equals(const ObPreAllocLinkHashNode &node) { return equals(node.get_key()); }
virtual OB_INLINE bool equals(const KEY &key) { return get_key() == key; }
//derived class should override static uint64_t hash(const uint64_t &key);
virtual const KEY &get_key() const = 0;
VIRTUAL_TO_STRING_KV(KP(this), K_(item));
ITEM &item_;
};
template <class KEY, class ITEM, class NODE, class ITEM_PROTECTOR>
class ObPreAllocLinkHashMap
{
public:
class ForeachFunctor
{
public:
virtual int operator()(ITEM &item, bool &is_full) = 0;
};
class EraseChecker
{
public:
virtual int operator()(ITEM &item) = 0;
};
class GetFunctor
{
public:
virtual int operator()(ITEM &item) = 0;
};
class Iterator
{
public:
explicit Iterator(ObPreAllocLinkHashMap &map)
: items_(),
item_idx_(0),
bucket_pos_(0),
map_(map)
{
}
virtual ~Iterator() { release_items(); }
int get_next(ITEM *&item)
{
int ret = OB_SUCCESS;
item = NULL;
while (OB_SUCC(ret)) {
if (item_idx_ < items_.count()) {
item = items_.at(item_idx_);
++item_idx_;
break;
} else if (bucket_pos_ >= map_.buckets_count_) {
ret = OB_ITER_END;
} else {
item_idx_ = 0;
release_items();
ObBucketRLockGuard guard(map_.buckets_lock_, bucket_pos_);
if (NULL != map_.buckets_[bucket_pos_]) {
NODE *node = map_.buckets_[bucket_pos_];
while (OB_SUCC(ret) && NULL != node) {
ITEM_PROTECTOR::hold(node->item_);
if (OB_FAIL(items_.push_back(&node->item_))) {
COMMON_LOG(WARN, "Failed to add item", K(ret));
ITEM_PROTECTOR::release(node->item_);
} else {
node = node->next_;
}
}
}
++bucket_pos_;
}
}
return ret;
}
private:
void release_items()
{
for (int64_t i = 0; i < items_.count(); ++i) {
ITEM_PROTECTOR::release(*items_.at(i));
}
items_.reuse();
}
common::ObArray<ITEM *> items_;
int64_t item_idx_;
int64_t bucket_pos_;
ObPreAllocLinkHashMap &map_;
DISALLOW_COPY_AND_ASSIGN(Iterator);
};
ObPreAllocLinkHashMap()
: is_inited_(false),
buckets_lock_(),
count_(),
buckets_(NULL),
buckets_count_(1),
allocator_()
{
}
virtual ~ObPreAllocLinkHashMap()
{
destroy();
}
void destroy()
{
for (uint64_t bucket_pos = 0; NULL != buckets_ && bucket_pos < buckets_count_; ++bucket_pos) {
ObBucketRLockGuard bucket_guard(buckets_lock_, bucket_pos);
NODE *cur = buckets_[bucket_pos];
NODE *next = NULL;
while (NULL != cur) {
next = cur->next_;
free_node(cur);
cur = next;
}
}
is_inited_ = false;
buckets_lock_.destroy();
count_ = 0;
ob_free(buckets_);
buckets_ = NULL;
buckets_count_ = 1;
}
int init(const int64_t buckets_count, const uint32_t latch_id, const lib::ObLabel &label)
{
int ret = OB_SUCCESS;
ObMemAttr mem_attr(OB_SERVER_TENANT_ID, label);
const int64_t real_buckets_count = hash::cal_next_prime(buckets_count);
if (is_inited_) {
ret = OB_INIT_TWICE;
COMMON_LOG(WARN, "cannot init twice", K(ret));
} else if (real_buckets_count <= 0 || buckets_count <= 0) {
ret = OB_INVALID_ARGUMENT;
COMMON_LOG(WARN, "invalid bucket count", K(ret), K(real_buckets_count), K(buckets_count));
} else if (OB_FAIL(buckets_lock_.init(real_buckets_count, latch_id, label))) {
COMMON_LOG(WARN, "failed to init buckets lock", K(ret));
} else if (OB_ISNULL(buckets_ = reinterpret_cast<NODE**>(
ob_malloc(sizeof(NODE*) * real_buckets_count, mem_attr)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
COMMON_LOG(WARN, "failed to alloc buckets", K(ret), K(real_buckets_count));
} else {
allocator_.set_label(label);
MEMSET(buckets_, 0, sizeof(NODE*) * real_buckets_count);
COMMON_LOG(INFO, "init hashmap", K(buckets_count), K(real_buckets_count),
"buf_size", sizeof(NODE*) * real_buckets_count, K(latch_id), K(label));
count_ = 0;
buckets_count_ = real_buckets_count;
is_inited_ = true;
}
return ret;
}
uint64_t get_count() const { return ATOMIC_LOAD(&count_); }
uint64_t get_buckets_count() const { return buckets_count_; }
NODE *alloc_node(ITEM &item)
{
return allocator_.alloc(item);
}
void free_node(NODE *&node)
{
allocator_.free(node);
node = NULL;
}
int put(NODE &node)
{
int ret = OB_SUCCESS;
if (!is_inited_) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "not inited", K(ret));
} else {
const uint64_t bucket_pos = NODE::hash(node.get_key()) % buckets_count_;
ObBucketWLockGuard bucket_guard(buckets_lock_, bucket_pos);
NODE *cur = buckets_[bucket_pos];
while (NULL != cur) {
if (cur->equals(node)) {
break;
} else {
cur = cur->next_;
}
}
if (NULL != cur) {
ret = OB_HASH_EXIST;
} else {
node.next_ = buckets_[bucket_pos];
buckets_[bucket_pos] = &node;
ATOMIC_INC(&count_);
}
}
return ret;
}
// delete node which has common key
int erase(const KEY &key, ITEM *&del_item, EraseChecker *checker = NULL)
{
int ret = OB_SUCCESS;
del_item = NULL;
if (!is_inited_) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "not inited", K(ret));
} else {
const uint64_t bucket_pos = NODE::hash(key) % buckets_count_;
ObBucketWLockGuard bucket_guard(buckets_lock_, bucket_pos);
NODE *cur = buckets_[bucket_pos];
NODE *prev = NULL;
while (NULL != cur) {
if (cur->equals(key)) {
break;
} else {
prev = cur;
cur = cur->next_;
}
}
if (NULL == cur) {
ret = OB_HASH_NOT_EXIST;
} else if (NULL != checker && OB_FAIL((*checker)(cur->item_))) {
// cannot erase now
} else {
if (NULL != prev) {
prev->next_ = cur->next_;
} else {
buckets_[bucket_pos] = cur->next_;
}
cur->next_ = NULL;
del_item = &cur->item_;
free_node(cur);
ATOMIC_DEC(&count_);
}
}
return ret;
}
// delete node which has common key
int erase(const KEY &key)
{
int ret = OB_SUCCESS;
ITEM *del_item = NULL;
if (OB_FAIL(erase(key, del_item))) {
COMMON_LOG(WARN, "failed to erase ndoe", K(ret), K(key));
}
return ret;
}
int exist(const KEY &key)
{
ITEM *item = NULL;
int ret = get(key, item);
if (OB_SUCCESS == ret) {
ret = OB_HASH_EXIST;
}
return ret;
}
int get(const KEY &key, GetFunctor &functor)
{
ITEM *item = NULL;
return get(key, item, &functor);
}
int get(const KEY &key, ITEM *&item, GetFunctor *functor = NULL)
{
int ret = OB_SUCCESS;
item = NULL;
if (!is_inited_) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "not inited", K(ret));
} else {
const uint64_t bucket_pos = NODE::hash(key) % buckets_count_;
ObBucketRLockGuard bucket_guard(buckets_lock_, bucket_pos);
NODE *cur = buckets_[bucket_pos];
while (NULL != cur) {
if (cur->equals(key)) {
break;
} else {
cur = cur->next_;
}
}
if (NULL == cur) {
ret = OB_HASH_NOT_EXIST;
} else if (NULL != functor && OB_FAIL((*functor)(cur->item_))) {
COMMON_LOG(WARN, "failed to do get functor", K(ret), K(*cur));
} else {
item = &cur->item_;
}
}
return ret;
}
int foreach(ForeachFunctor &functor)
{
int ret = OB_SUCCESS;
bool is_full = false;
if (!is_inited_) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "not inited", K(ret));
} else {
for (uint64_t bucket_pos = 0; OB_SUCC(ret) && !is_full && bucket_pos < buckets_count_; ++bucket_pos) {
ObBucketRLockGuard bucket_guard(buckets_lock_, bucket_pos);
NODE *cur = buckets_[bucket_pos];
while (OB_SUCC(ret) && NULL != cur && !is_full) {
if (OB_FAIL(functor(cur->item_, is_full))) {
COMMON_LOG(WARN, "failed to do foreach functor", K(ret));
} else {
cur = cur->next_;
}
}
}
}
return ret;
}
private:
bool is_inited_;
mutable common::ObBucketLock buckets_lock_;
uint64_t count_;
NODE **buckets_;
uint64_t buckets_count_;
SimpleAllocer<NODE> allocator_;
DISALLOW_COPY_AND_ASSIGN(ObPreAllocLinkHashMap);
};
} // hash
} // common
} // oceanbase
#endif /* SRC_LIBRARY_SRC_LIB_HASH_OB_MEMLESS_LINK_HASHMAP_H_ */
......@@ -47,7 +47,6 @@ oblib_addtest(hash/test_array_index_hash_set.cpp)
oblib_addtest(hash/test_build_in_hashmap.cpp)
oblib_addtest(hash/test_concurrent_hash_map.cpp)
oblib_addtest(hash/test_cuckoo_hashmap.cpp)
oblib_addtest(hash/test_ext_iter_hashset.cpp)
oblib_addtest(hash/test_hashmap.cpp)
oblib_addtest(hash/test_fnv_hash.cpp)
oblib_addtest(hash/test_hashset.cpp)
......@@ -57,7 +56,6 @@ oblib_addtest(hash/test_link_hashmap.cpp)
oblib_addtest(hash/test_linear_hash_map.cpp)
oblib_addtest(hash/test_placement_hashset.cpp)
oblib_addtest(hash/test_pointer_hashmap.cpp)
oblib_addtest(hash/test_pre_alloc_link_hashmap.cpp)
oblib_addtest(hash/test_simpleallocer.cpp)
oblib_addtest(json/test_json_print_utils.cpp)
oblib_addtest(json/test_yson.cpp)
......
/**
* 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 "lib/hash/ob_ext_iter_hashset.h"
#include "lib/allocator/ob_malloc.h"
#include <gtest/gtest.h>
using namespace oceanbase::common;
using namespace oceanbase::common::hash;
class ObExtIterHashSetTest: public ::testing::Test
{
public:
ObExtIterHashSetTest();
virtual ~ObExtIterHashSetTest();
virtual void SetUp();
virtual void TearDown();
public:
ObArenaAllocator allocator_;
private:
// disallow copy
ObExtIterHashSetTest(const ObExtIterHashSetTest &other);
ObExtIterHashSetTest& operator=(const ObExtIterHashSetTest &other);
protected:
// data members
};
ObExtIterHashSetTest::ObExtIterHashSetTest() : allocator_(ObModIds::TEST)
{
}
ObExtIterHashSetTest::~ObExtIterHashSetTest()
{
}
void ObExtIterHashSetTest::SetUp()
{
}
void ObExtIterHashSetTest::TearDown()
{
allocator_.reset();
}
TEST_F(ObExtIterHashSetTest, basic_test)
{
static const int64_t N = 256;
static const int64_t BUCKET_NUM = 8;
ObExtIterHashSet<int64_t, N> set(allocator_);
for (int round = 0; round < 5; ++round) {
ASSERT_EQ(0, set.count());
ASSERT_EQ(set.begin(), set.end());
ASSERT_EQ(++(set.begin()), set.end());
// insert data
for (int64_t index = 0; index < N * BUCKET_NUM; index++) {
int64_t value = index + 1;
ASSERT_EQ(OB_HASH_NOT_EXIST, set.exist_refactored(value));
ASSERT_EQ(OB_SUCCESS, set.set_refactored(value));
ASSERT_EQ(OB_HASH_EXIST, set.exist_refactored(value));
ASSERT_EQ(index + 1, set.count());
}
// verify data
ObExtIterHashSet<int64_t, N>::const_iterator_t it = set.begin();
for(int64_t value = 1; it != set.end(); ++it, value++) {
ASSERT_EQ(value, *it);
}
set.clear();
ASSERT_EQ(0, set.count());
}
}
TEST_F(ObExtIterHashSetTest, single_N)
{
ObExtIterHashSet<int64_t, 1> hashset(allocator_);
ObExtIterHashSet<int64_t, 1>::const_iterator_t iter = hashset.begin();
ASSERT_EQ(iter, hashset.end());
ASSERT_EQ(++iter, hashset.end());
ASSERT_EQ(0, hashset.count());
ASSERT_EQ(OB_SUCCESS, hashset.set_refactored(1));
ASSERT_EQ(OB_HASH_EXIST, hashset.set_refactored(1));
ASSERT_EQ(OB_HASH_EXIST, hashset.exist_refactored(1));
ASSERT_EQ(1, hashset.count());
ASSERT_EQ(OB_SUCCESS, hashset.set_refactored(2));
ASSERT_EQ(OB_HASH_EXIST, hashset.exist_refactored(2));
ASSERT_EQ(2, hashset.count());
iter = hashset.begin();
ASSERT_NE(iter, hashset.end());
ASSERT_EQ(1, *iter);
ASSERT_NE(++iter, hashset.end());
ASSERT_EQ(2, *iter);
ASSERT_EQ(++iter, hashset.end());
ASSERT_EQ(++iter, hashset.end());
}
TEST_F(ObExtIterHashSetTest, many_N_single_bucket)
{
const uint64_t N = 10345;
int64_t value = 0;
ObExtIterHashSet<int64_t, N> hashset(allocator_);
ObExtIterHashSet<int64_t, N>::const_iterator_t iter = hashset.begin();
ASSERT_EQ(iter, hashset.end());
ASSERT_EQ(++iter, hashset.end());
for (uint64_t i = 0; i < N; i++) {
ASSERT_EQ(OB_HASH_NOT_EXIST, hashset.exist_refactored(i));
}
for (uint64_t i = 0; i < N; i++) {
ASSERT_EQ(OB_SUCCESS, hashset.set_refactored(i));
}
ASSERT_EQ(OB_SUCCESS, hashset.set_refactored(N));
for (uint64_t i = 0; i < N; i++) {
ASSERT_EQ(OB_HASH_EXIST, hashset.exist_refactored(i));
}
for (uint64_t i = 0; i < N; i++) {
ASSERT_EQ(OB_HASH_EXIST, hashset.set_refactored(i));
}
ASSERT_EQ(OB_HASH_EXIST, hashset.set_refactored(N));
for (uint64_t i = 0; i < N; i++) {
ASSERT_EQ(OB_HASH_EXIST, hashset.exist_refactored(i));
}
ASSERT_EQ(N + 1, hashset.count());
for (value = 0, iter = hashset.begin(); iter != hashset.end(); ++iter, value++) {
ASSERT_EQ(value, *iter);
}
hashset.clear();
iter = hashset.begin();
ASSERT_EQ(iter, hashset.end());
ASSERT_EQ(++iter, hashset.end());
for (uint64_t i = 0; i < N; i++) {
ASSERT_EQ(OB_HASH_NOT_EXIST, hashset.exist_refactored(i));
}
for (uint64_t i = 0; i < N; i++) {
ASSERT_EQ(OB_SUCCESS, hashset.set_refactored(i));
}
ASSERT_EQ(OB_SUCCESS, hashset.set_refactored(N));
for (uint64_t i = 0; i < N; i++) {
ASSERT_EQ(OB_HASH_EXIST, hashset.exist_refactored(i));
}
for (uint64_t i = 0; i < N; i++) {
ASSERT_EQ(OB_HASH_EXIST, hashset.set_refactored(i));
}
ASSERT_EQ(OB_HASH_EXIST, hashset.set_refactored(N));
for (uint64_t i = 0; i < N; i++) {
ASSERT_EQ(OB_HASH_EXIST, hashset.exist_refactored(i));
}
ASSERT_EQ(N + 1, hashset.count());
for (value = 0, iter = hashset.begin(); iter != hashset.end(); ++iter, value++) {
ASSERT_EQ(value, *iter);
}
}
TEST_F(ObExtIterHashSetTest, many_N_single_buckets2)
{
const uint64_t N = 10345;
int64_t value = 0;
ObExtIterHashSet<int64_t, N> hashset(allocator_);
ObExtIterHashSet<int64_t, N>::const_iterator_t iter = hashset.begin();
ASSERT_EQ(iter, hashset.end());
ASSERT_EQ(++iter, hashset.end());
for (uint64_t i = N; i > 0; i--) {
ASSERT_EQ(OB_HASH_NOT_EXIST, hashset.exist_refactored(i));
}
for (uint64_t i = N; i > 0; i--) {
ASSERT_EQ(OB_SUCCESS, hashset.set_refactored(i));
}
ASSERT_EQ(OB_SUCCESS, hashset.set_refactored(0));
for (uint64_t i = N; i > 0; i--) {
ASSERT_EQ(OB_HASH_EXIST, hashset.exist_refactored(i));
}
for (uint64_t i = N; i > 0; i--) {
ASSERT_EQ(OB_HASH_EXIST, hashset.set_refactored(i));
}
ASSERT_EQ(OB_HASH_EXIST, hashset.set_refactored(0));
for (uint64_t i = N; i > 0; i--) {
ASSERT_EQ(OB_HASH_EXIST, hashset.exist_refactored(i));
}
ASSERT_EQ(N + 1, hashset.count());
for (value = N, iter = hashset.begin(); iter != hashset.end(); ++iter, value--) {
ASSERT_EQ(value, *iter);
}
hashset.clear();
iter = hashset.begin();
ASSERT_EQ(iter, hashset.end());
ASSERT_EQ(++iter, hashset.end());
for (uint64_t i = N; i > 0; i--) {
ASSERT_EQ(OB_HASH_NOT_EXIST, hashset.exist_refactored(i));
}
for (uint64_t i = N; i > 0; i--) {
ASSERT_EQ(OB_SUCCESS, hashset.set_refactored(i));
}
ASSERT_EQ(OB_SUCCESS, hashset.set_refactored(0));
for (uint64_t i = N; i > 0; i--) {
ASSERT_EQ(OB_HASH_EXIST, hashset.exist_refactored(i));
}
for (uint64_t i = N; i > 0; i--) {
ASSERT_EQ(OB_HASH_EXIST, hashset.set_refactored(i));
}
ASSERT_EQ(OB_HASH_EXIST, hashset.set_refactored(0));
for (uint64_t i = N; i > 0; i--) {
ASSERT_EQ(OB_HASH_EXIST, hashset.exist_refactored(i));
}
ASSERT_EQ(N + 1, hashset.count());
for (value = N, iter = hashset.begin(); iter != hashset.end(); ++iter, value--) {
ASSERT_EQ(value, *iter);
}
}
TEST_F(ObExtIterHashSetTest, many_N_many_buckets)
{
static const uint64_t N = 16;
static const uint64_t BUCKET_NUM = 100;
static const uint64_t ELEMENT_NUM = N * BUCKET_NUM;
int64_t value = 0;
ObExtIterHashSet<int64_t, N> hashset(allocator_);
ObExtIterHashSet<int64_t, N>::const_iterator_t iter = hashset.begin();
ASSERT_EQ(iter, hashset.end());
ASSERT_EQ(++iter, hashset.end());
for (uint64_t i = 0; i < ELEMENT_NUM; i++) {
ASSERT_EQ(OB_HASH_NOT_EXIST, hashset.exist_refactored(i));
}
for (uint64_t i = 0; i < ELEMENT_NUM; i++) {
ASSERT_EQ(OB_SUCCESS, hashset.set_refactored(i));
}
for (uint64_t i = 0; i < ELEMENT_NUM; i++) {
ASSERT_EQ(OB_HASH_EXIST, hashset.exist_refactored(i));
}
for (uint64_t i = 0; i < ELEMENT_NUM; i++) {
ASSERT_EQ(OB_HASH_EXIST, hashset.set_refactored(i));
}
for (uint64_t i = 0; i < ELEMENT_NUM; i++) {
ASSERT_EQ(OB_HASH_EXIST, hashset.exist_refactored(i));
}
ASSERT_EQ(ELEMENT_NUM, hashset.count());
for (value = 0, iter = hashset.begin(); iter != hashset.end(); ++iter, value++) {
ASSERT_EQ(value, *iter);
}
hashset.clear();
iter = hashset.begin();
ASSERT_EQ(iter, hashset.end());
ASSERT_EQ(++iter, hashset.end());
for (uint64_t i = 0; i < ELEMENT_NUM; i++) {
ASSERT_EQ(OB_HASH_NOT_EXIST, hashset.exist_refactored(i));
}
for (uint64_t i = 0; i < ELEMENT_NUM; i++) {
ASSERT_EQ(OB_SUCCESS, hashset.set_refactored(i));
}
for (uint64_t i = 0; i < ELEMENT_NUM; i++) {
ASSERT_EQ(OB_HASH_EXIST, hashset.exist_refactored(i));
}
for (uint64_t i = 0; i < ELEMENT_NUM; i++) {
ASSERT_EQ(OB_HASH_EXIST, hashset.set_refactored(i));
}
for (uint64_t i = 0; i < ELEMENT_NUM; i++) {
ASSERT_EQ(OB_HASH_EXIST, hashset.exist_refactored(i));
}
ASSERT_EQ(ELEMENT_NUM, hashset.count());
for (value = 0, iter = hashset.begin(); iter != hashset.end(); ++iter, value++) {
ASSERT_EQ(value, *iter);
}
}
TEST_F(ObExtIterHashSetTest, many_N_many_buckets2)
{
static const uint64_t N = 128;
static const uint64_t BUCKET_NUM = 10;
static const uint64_t ELEMENT_NUM = N * BUCKET_NUM;
int64_t value = 0;
ObExtIterHashSet<int64_t, N> hashset(allocator_);
ObExtIterHashSet<int64_t, N>::const_iterator_t iter = hashset.begin();
ASSERT_EQ(iter, hashset.end());
ASSERT_EQ(++iter, hashset.end());
for (uint64_t i = ELEMENT_NUM; i > 0; i--) {
ASSERT_EQ(OB_HASH_NOT_EXIST, hashset.exist_refactored(i));
}
for (uint64_t i = ELEMENT_NUM; i > 0; i--) {
ASSERT_EQ(OB_SUCCESS, hashset.set_refactored(i));
}
for (uint64_t i = ELEMENT_NUM; i > 0; i--) {
ASSERT_EQ(OB_HASH_EXIST, hashset.exist_refactored(i));
}
for (uint64_t i = ELEMENT_NUM; i > 0; i--) {
ASSERT_EQ(OB_HASH_EXIST, hashset.set_refactored(i));
}
for (uint64_t i = ELEMENT_NUM; i > 0; i--) {
ASSERT_EQ(OB_HASH_EXIST, hashset.exist_refactored(i));
}
ASSERT_EQ(ELEMENT_NUM, hashset.count());
for (value = ELEMENT_NUM, iter = hashset.begin(); iter != hashset.end(); ++iter, value--) {
ASSERT_EQ(value, *iter);
}
hashset.clear();
iter = hashset.begin();
ASSERT_EQ(iter, hashset.end());
ASSERT_EQ(++iter, hashset.end());
for (uint64_t i = ELEMENT_NUM; i > 0; i--) {
ASSERT_EQ(OB_HASH_NOT_EXIST, hashset.exist_refactored(i));
}
for (uint64_t i = ELEMENT_NUM; i > 0; i--) {
ASSERT_EQ(OB_SUCCESS, hashset.set_refactored(i));
}
for (uint64_t i = ELEMENT_NUM; i > 0; i--) {
ASSERT_EQ(OB_HASH_EXIST, hashset.exist_refactored(i));
}
for (uint64_t i = ELEMENT_NUM; i > 0; i--) {
ASSERT_EQ(OB_HASH_EXIST, hashset.set_refactored(i));
}
for (uint64_t i = ELEMENT_NUM; i > 0; i--) {
ASSERT_EQ(OB_HASH_EXIST, hashset.exist_refactored(i));
}
ASSERT_EQ(ELEMENT_NUM, hashset.count());
for (value = ELEMENT_NUM, iter = hashset.begin(); iter != hashset.end(); ++iter, value--) {
ASSERT_EQ(value, *iter);
}
}
int main(int argc, char **argv)
{
OB_LOGGER.set_log_level("INFO");
::testing::InitGoogleTest(&argc,argv);
return RUN_ALL_TESTS();
}
/**
* 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 <pthread.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include "lib/hash/ob_pre_alloc_link_hashmap.h"
#include "lib/allocator/ob_malloc.h"
#include "gtest/gtest.h"
using namespace oceanbase;
using namespace oceanbase::common;
using namespace oceanbase::common::hash;
struct Item
{
int64_t key_;
int64_t value_;
int64_t ref_;
Item(): key_(0), value_(0), ref_(0) {}
Item(const int64_t key, const int64_t value, const int64_t ref):
key_(key), value_(value), ref_(ref) {}
TO_STRING_KV(K_(key), K_(value));
};
struct Node: public ObPreAllocLinkHashNode<int64_t, Item>
{
explicit Node(Item &item): ObPreAllocLinkHashNode(item), next_(NULL) {}
virtual ~Node() { }
static uint64_t hash(int64_t key) { return key; }
virtual uint64_t hash() const { return hash(item_.key_); }
virtual const int64_t &get_key() const { return item_.key_; }
Node *next_;
};
class ItemProtector
{
public:
static void hold(Item &item)
{
++item.ref_;
}
static void release(Item &item)
{
--item.ref_;
}
};
typedef common::hash::ObPreAllocLinkHashMap<int64_t, Item, Node, ItemProtector> TestMap;
struct TestForeachFinder: public TestMap::ForeachFunctor
{
TestForeachFinder(): count_(0) {}
virtual ~TestForeachFinder() {}
virtual int operator()(Item &item, bool &is_full)
{
int ret = OB_SUCCESS;
if (count_ >= MAX_COUNT) {
is_full = true;
} else if (item.value_ == 0) {
items_[count_++] = &item;
} else if (item.value_ == 2) {
ret = OB_ERR_SYS;
}
return ret;
}
static const int64_t MAX_COUNT = 3;
Item *items_[MAX_COUNT];
int64_t count_;
};
struct TestForeachCheckRef: public TestMap::ForeachFunctor
{
TestForeachCheckRef(): count_(0) {}
virtual ~TestForeachCheckRef() {}
virtual int operator()(Item &item, bool &is_full)
{
int ret = OB_SUCCESS;
is_full = false;
++count_;
if (item.ref_ != 0) {
COMMON_LOG(ERROR, "ref not zero", K(item.ref_), K(item.key_));
ret = OB_ERR_SYS;
}
return ret;
}
int64_t count_;
};
class TestEraseChecker: public TestMap::EraseChecker
{
public:
virtual ~TestEraseChecker() {}
virtual int operator()(Item &item)
{
int ret = OB_SUCCESS;
if (item.value_ != 0) {
ret = OB_EAGAIN;
}
return ret;
}
};
class TestGetFunctor: public TestMap::GetFunctor
{
public:
TestGetFunctor(): item_(NULL) {}
virtual ~TestGetFunctor() {}
virtual int operator()(Item &item) override
{
int ret = OB_SUCCESS;
item_ = NULL;
if (item.value_ == 3) {
ret = OB_ERR_SYS;
} else {
item_ = &item;
}
return ret;
}
Item *item_;
private:
DISALLOW_COPY_AND_ASSIGN(TestGetFunctor);
};
TEST(TestObMemLessLinkHashMap, basic)
{
TestMap map;
int64_t buckets_count = 0;
uint32_t latch_id = 1;
const lib::ObLabel &label = "1";
Item item1 = {1,0,0};
Node *node1 = map.alloc_node(item1);
COMMON_LOG(INFO, "dump", K(item1), K(node1->item_), KP(&item1), KP(&node1->item_));
TestForeachFinder finder;
ASSERT_EQ(OB_NOT_INIT, map.put(*node1));
ASSERT_EQ(OB_INVALID_ARGUMENT, map.init(buckets_count, latch_id, label));
ASSERT_EQ(OB_INVALID_ARGUMENT, map.init(buckets_count, latch_id, label));
buckets_count = 100;
ASSERT_EQ(OB_SUCCESS, map.init(buckets_count, latch_id, label));
ASSERT_EQ(OB_INIT_TWICE, map.init(buckets_count, latch_id, label));
ASSERT_EQ(0, map.get_count());
ASSERT_EQ(OB_SUCCESS, map.put(*node1));
ASSERT_EQ(OB_HASH_EXIST, map.put(*node1));
ASSERT_EQ(1, map.get_count());
Item item2 = {1,0,0};
Node node2(item2);
ASSERT_EQ(OB_HASH_EXIST, map.put(node2));
ASSERT_EQ(1, map.get_count());
Item *get_item = NULL;
ASSERT_EQ(OB_SUCCESS, map.get(1, get_item));
ASSERT_EQ(&item1, get_item);
ASSERT_EQ(OB_SUCCESS, map.foreach(finder));
ASSERT_EQ(1, finder.count_);
COMMON_LOG(INFO, "dump", K(node1), K(finder.items_[0]));
ASSERT_EQ(&item1, finder.items_[0]);
Item *del_item = NULL;
ASSERT_EQ(OB_SUCCESS, map.erase(1, del_item));
ASSERT_EQ(&item1, del_item);
ASSERT_EQ(OB_HASH_NOT_EXIST, map.erase(1, del_item));
ASSERT_EQ(OB_HASH_NOT_EXIST, map.get(1, del_item));
}
TEST(TestObMemLessLinkHashMap, same_hash)
{
TestMap map;
int64_t buckets_count = 1;
uint32_t latch_id = 1;
const lib::ObLabel &label = "1";
Item item1 = {1,0,0};
ASSERT_EQ(OB_SUCCESS, map.init(buckets_count, latch_id, label));
buckets_count = map.get_buckets_count();
Node *node1 = map.alloc_node(item1);
Item item2 = {1 + buckets_count,0,0};
Node *node2 = map.alloc_node(item2);
ASSERT_EQ(OB_SUCCESS, map.put(*node1));
ASSERT_EQ(OB_SUCCESS, map.put(*node2));
ASSERT_EQ(2, map.get_count());
Item *got_item = NULL;
ASSERT_EQ(OB_SUCCESS, map.get(1, got_item));
ASSERT_EQ(&item1, got_item);
ASSERT_EQ(OB_SUCCESS, map.get(item2.key_, got_item));
ASSERT_EQ(&item2, got_item);
Item *del_item = NULL;
ASSERT_EQ(OB_SUCCESS, map.erase(item2.key_, del_item));
ASSERT_EQ(&item2, del_item);
ASSERT_EQ(OB_SUCCESS, map.erase(item1.key_, del_item));
ASSERT_EQ(&item1, del_item);
}
TEST(TestObMemLessLinkHashMap, erase)
{
TestMap map;
int64_t buckets_count = 100;
uint32_t latch_id = 1;
const lib::ObLabel &label = "1";
TestEraseChecker checker;
Item *del_item = NULL;
ASSERT_EQ(OB_SUCCESS, map.init(buckets_count, latch_id, label));
Item item1 = {1,0,0};
Node *node1 = map.alloc_node(item1);
Item item2 = {2,1, 0};
Node *node2 = map.alloc_node(item2);
ASSERT_EQ(OB_SUCCESS, map.put(*node1));
ASSERT_EQ(OB_SUCCESS, map.put(*node2));
ASSERT_EQ(OB_SUCCESS, map.erase(1, del_item, &checker));
ASSERT_EQ(del_item, &item1);
ASSERT_EQ(OB_EAGAIN, map.erase(2, del_item, &checker));
}
TEST(TestObMemLessLinkHashMap, get_functor)
{
TestMap map;
int64_t buckets_count = 100;
uint32_t latch_id = 1;
const lib::ObLabel &label = "1";
ASSERT_EQ(OB_SUCCESS, map.init(buckets_count, latch_id, label));
Item item1 = {1,0,0};
Node *node1 = map.alloc_node(item1);
Item item2 = {2,3, 0};
Node *node2 = map.alloc_node(item2);
TestGetFunctor get_functor;
Item *got_item = NULL;
ASSERT_EQ(OB_SUCCESS, map.put(*node1));
ASSERT_EQ(OB_SUCCESS, map.put(*node2));
ASSERT_EQ(OB_SUCCESS, map.get(1, got_item, &get_functor));
ASSERT_EQ(got_item, &item1);
ASSERT_EQ(OB_SUCCESS, map.get(1, get_functor));
ASSERT_EQ(get_functor.item_, &item1);
ASSERT_EQ(OB_ERR_SYS, map.get(2, got_item, &get_functor));
ASSERT_TRUE(got_item == NULL);
ASSERT_TRUE(get_functor.item_ == NULL);
ASSERT_EQ(OB_HASH_EXIST, map.exist(1));
ASSERT_EQ(OB_HASH_EXIST, map.exist(2));
ASSERT_EQ(OB_HASH_NOT_EXIST, map.exist(3));
}
TEST(TestObMemLessLinkHashMap, foreach)
{
TestMap map;
int64_t buckets_count = 100;
uint32_t latch_id = 1;
const lib::ObLabel &label = "1";
const int64_t count = 10000;
Item *items[count];
TestForeachFinder finder;
ASSERT_EQ(OB_SUCCESS, map.init(buckets_count, latch_id, label));
for (int64_t i = 0; i < count; ++i) {
Item *item = new Item();
item->key_ = i;
item->value_ = i % 2;
Node *node = map.alloc_node(*item);
items[i] = item;
ASSERT_EQ(OB_SUCCESS, map.put(*node));
}
for (int64_t i = 0; i < count; ++i) {
Item *got_item = NULL;
ASSERT_EQ(OB_SUCCESS, map.get(i, got_item));
ASSERT_EQ(items[i], got_item);
}
ASSERT_EQ(OB_SUCCESS, map.foreach(finder));
ASSERT_EQ(3, finder.count_);
for (int64_t i = 0; i < 3; ++i) {
COMMON_LOG(INFO, "dump", K(items[2 * i]), K(*finder.items_[i]));
}
for (int64_t i = 0; i < count; ++i) {
delete items[i];
}
}
TEST(TestObMemLessLinkHashMap, iterator)
{
TestMap map;
TestMap::Iterator iter(map);
int64_t buckets_count = 100000;
uint32_t latch_id = 1;
const lib::ObLabel &label = "1";
ASSERT_EQ(OB_SUCCESS, map.init(buckets_count, latch_id, label));
Item item1 = {1,0,0};
Node *node1 = map.alloc_node(item1);
Item item2 = {2,3, 0};
Node *node2 = map.alloc_node(item2);
TestGetFunctor get_functor;
Item *got_item = NULL;
ASSERT_EQ(OB_SUCCESS, map.put(*node1));
ASSERT_EQ(OB_SUCCESS, map.put(*node2));
ASSERT_EQ(OB_SUCCESS, iter.get_next(got_item));
ASSERT_EQ(&item1, got_item);
ASSERT_EQ(OB_SUCCESS, iter.get_next(got_item));
ASSERT_EQ(&item2, got_item);
ASSERT_EQ(OB_ITER_END, iter.get_next(got_item));
}
TEST(TestObMemLessLinkHashMap, iterator2)
{
int ret = OB_SUCCESS;
TestMap map;
int64_t buckets_count = 100;
uint32_t latch_id = 1;
const lib::ObLabel &label = "1";
ASSERT_EQ(OB_SUCCESS, map.init(buckets_count, latch_id, label));
const int64_t count = 8061;
for (int64_t i = 0; i < count; ++i) {
Item *item = new Item();
item->key_ = i;
item->value_ = i;
item->ref_ = 0;
Node *node = map.alloc_node(*item);
ASSERT_EQ(OB_SUCCESS, map.put(*node));
}
{
TestMap::Iterator iter(map);
Item *got_item = NULL;
int64_t num = 0;
while (OB_SUCC(ret)) {
if (OB_FAIL(iter.get_next(got_item))) {
COMMON_LOG(WARN, "rend", K(ret), K(num));
} else {
++num;
}
}
ASSERT_EQ(OB_ITER_END, ret);
}
TestForeachCheckRef checker;
ASSERT_EQ(OB_SUCCESS, map.foreach(checker));
ASSERT_EQ(count, checker.count_);
}
int main(int argc, char **argv)
{
OB_LOGGER.set_log_level("INFO");
testing::InitGoogleTest(&argc,argv);
return RUN_ALL_TESTS();
}
......@@ -17,7 +17,6 @@
#include "share/ob_define.h" // OB_*
#include "lib/allocator/ob_allocator.h" // ObIAllocator
#include "lib/hash/ob_ext_iter_hashset.h" // ObExtIterHashSet
#include "lib/container/ob_se_array.h" // ObSEArray
#include "lib/allocator/page_arena.h" // ObArenaAllocator
#include "lib/lock/ob_spin_lock.h" // ObSpinLock
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册