[SCN] adjust ObBatchCreateTabletArg
This commit is contained in:
1
deps/init/oceanbase.el7.aarch64.deps
vendored
1
deps/init/oceanbase.el7.aarch64.deps
vendored
@ -17,7 +17,6 @@ repo=http://yum.tbsite.net/taobao/7/aarch64/test/ob-deploy/
|
||||
devdeps-gtest-1.8.0-132022101316.el7.aarch64.rpm
|
||||
devdeps-isa-l-static-2.22.0-22022092915.el7.aarch64.rpm
|
||||
devdeps-libcurl-static-7.29.0-32022093010.el7.aarch64.rpm
|
||||
devdeps-libunwind-static-1.6.2-222022100410.el7.aarch64.rpm
|
||||
devdeps-mariadb-connector-c-3.1.12-12022100422.el7.aarch64.rpm
|
||||
devdeps-libaio-0.3.112-12022092915.el7.aarch64.rpm
|
||||
devdeps-rapidjson-1.1.0-12022100410.el7.aarch64.rpm
|
||||
|
||||
1
deps/init/oceanbase.el8.aarch64.deps
vendored
1
deps/init/oceanbase.el8.aarch64.deps
vendored
@ -12,7 +12,6 @@ repo=http://mirrors.aliyun.com/oceanbase/community/stable/el/8/aarch64/
|
||||
devdeps-gtest-1.8.0-132022101316.el8.aarch64.rpm
|
||||
devdeps-isa-l-static-2.22.0-22022092915.el8.aarch64.rpm
|
||||
devdeps-libcurl-static-7.29.0-32022093010.el8.aarch64.rpm
|
||||
devdeps-libunwind-static-1.6.2-222022100410.el8.aarch64.rpm
|
||||
devdeps-mariadb-connector-c-3.1.12-12022100422.el8.aarch64.rpm
|
||||
devdeps-libaio-0.3.112-12022092915.el8.aarch64.rpm
|
||||
devdeps-rapidjson-1.1.0-12022100410.el8.aarch64.rpm
|
||||
|
||||
2
deps/oblib/src/CMakeLists.txt
vendored
2
deps/oblib/src/CMakeLists.txt
vendored
@ -121,7 +121,7 @@ target_link_libraries(oblib_base_base_base
|
||||
${DEP_DIR}/lib/libssl.a
|
||||
${DEP_DIR}/lib/libcrypto.a
|
||||
${LGPL_DEPS}
|
||||
${DEP_DIR}/lib/libunwind.a
|
||||
$<$<STREQUAL:"${ARCHITECTURE}","x86_64">:${DEP_DIR}/lib/libunwind.a>
|
||||
${DEP_DIR}/lib/libz.a
|
||||
-L${DEP_DIR}/var/usr/lib64
|
||||
-L${DEP_DIR}/var/usr/lib
|
||||
|
||||
15
deps/oblib/src/lib/hash/ob_array_hash_map.h
vendored
15
deps/oblib/src/lib/hash/ob_array_hash_map.h
vendored
@ -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));
|
||||
|
||||
307
deps/oblib/src/lib/hash/ob_ext_iter_hashset.h
vendored
307
deps/oblib/src/lib/hash/ob_ext_iter_hashset.h
vendored
@ -1,307 +0,0 @@
|
||||
/**
|
||||
* 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
|
||||
164
deps/oblib/src/lib/hash/ob_fixed_hash.h
vendored
164
deps/oblib/src/lib/hash/ob_fixed_hash.h
vendored
@ -1,164 +0,0 @@
|
||||
/**
|
||||
* 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_ */
|
||||
379
deps/oblib/src/lib/hash/ob_pre_alloc_link_hashmap.h
vendored
379
deps/oblib/src/lib/hash/ob_pre_alloc_link_hashmap.h
vendored
@ -1,379 +0,0 @@
|
||||
/**
|
||||
* 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_ */
|
||||
2
deps/oblib/src/lib/signal/ob_libunwind.c
vendored
2
deps/oblib/src/lib/signal/ob_libunwind.c
vendored
@ -10,6 +10,7 @@
|
||||
* See the Mulan PubL v2 for more details.
|
||||
*/
|
||||
|
||||
#ifdef __x86_64__
|
||||
#include "lib/signal/ob_libunwind.h"
|
||||
#include "lib/signal/safe_snprintf.h"
|
||||
#define UNW_LOCAL_ONLY
|
||||
@ -106,3 +107,4 @@ int8_t get_frame_info(unw_cursor_t *cursor, uintptr_t *ip)
|
||||
*ip = uip - (r == 0);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -157,7 +157,9 @@ void coredump_cb(int sig, siginfo_t *si, void *context)
|
||||
// backtrace
|
||||
char bt[256];
|
||||
int64_t len = 0;
|
||||
#ifdef __x86_64__
|
||||
safe_backtrace(bt, sizeof(bt) - 1, &len);
|
||||
#endif
|
||||
bt[len++] = '\0';
|
||||
// extra
|
||||
const ObFatalErrExtraInfoGuard *extra_info = nullptr; // TODO: May deadlock, ObFatalErrExtraInfoGuard::get_thd_local_val_ptr();
|
||||
|
||||
@ -65,7 +65,9 @@ int ObSigBTOnlyProcessor::prepare()
|
||||
int64_t count = 0;
|
||||
count = safe_snprintf(buf_ + pos_, len - pos_, "tid: %ld, tname: %s, lbt: ", tid, tname);
|
||||
pos_ += count;
|
||||
#ifdef __x86_64__
|
||||
safe_backtrace(buf_ + pos_, len - pos_, &count);
|
||||
#endif
|
||||
pos_ += count;
|
||||
buf_[pos_++] = '\n';
|
||||
return ret;
|
||||
|
||||
@ -44,7 +44,9 @@ void crash_restore_handler(int sig, siginfo_t *s, void *p)
|
||||
if (SIGSEGV == sig || SIGABRT == sig ||
|
||||
SIGBUS == sig || SIGFPE == sig) {
|
||||
int64_t len = 0;
|
||||
#ifdef __x86_64__
|
||||
safe_backtrace(crash_restore_buffer, 255, &len);
|
||||
#endif
|
||||
crash_restore_buffer[len++] = '\0';
|
||||
siglongjmp(*g_jmp, 1);
|
||||
} else {
|
||||
|
||||
@ -33,6 +33,7 @@ bool g_inited = false;
|
||||
int send_request_and_wait(ObSigRequestCode code, int exclude_tid)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
#ifdef __x86_64__
|
||||
DTraceId trace_id = DTraceId::gen_trace_id();
|
||||
DTraceIdGuard trace_guard(trace_id);
|
||||
ObSigRequest req;
|
||||
@ -93,6 +94,7 @@ int send_request_and_wait(ObSigRequestCode code, int exclude_tid)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
2
deps/oblib/unittest/lib/CMakeLists.txt
vendored
2
deps/oblib/unittest/lib/CMakeLists.txt
vendored
@ -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)
|
||||
|
||||
@ -1,360 +0,0 @@
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
@ -1,373 +0,0 @@
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
Reference in New Issue
Block a user