提交 50933732 编写于 作者: N nroskill 提交者: wangzelin.wzl

[CP] [CP] [CP] [CP] fix link hashmap core

上级 392f40cc
......@@ -30,6 +30,12 @@ inline int32_t faa_if_positive(int32_t* addr, int32_t x)
return ov;
}
inline static ObQSync &get_global_link_hashmap_qsync()
{
static ObQSync qsync;
return qsync;
}
// DO NOT use me
class BaseRefHandle {
public:
......@@ -65,42 +71,6 @@ protected:
uint64_t qc_slot_;
};
// fast read, slow del, delay reclaim Value/Node
class TCRefHandle final : public BaseRefHandle {
public:
typedef RefNode Node;
explicit TCRefHandle(RetireStation& retire_station) : BaseRefHandle(retire_station)
{}
void born(Node* node)
{
UNUSED(get_tcref().born(&node->uref_));
}
int32_t end(Node* node)
{
UNUSED(get_tcref().end(&node->uref_));
return get_tcref().sync(&node->uref_);
}
bool inc(Node* node)
{
int32_t ref = 0;
if (TCRef::REF_LIMIT == (ref = get_tcref().inc_ref(&node->uref_))) {
ref = ATOMIC_LOAD(&node->uref_);
}
return ref > TCRef::REF_LIMIT / 2;
}
int32_t dec(Node* node)
{
return get_tcref().dec_ref(&node->uref_);
}
private:
static TCRef& get_tcref()
{
static TCRef tcref;
return tcref;
}
};
// balanced read/del performance, realtime reclaim Value, batch/delay reclaim Node.
class RefHandle final : public BaseRefHandle {
public:
......@@ -125,45 +95,6 @@ public:
}
};
class DummyRefHandle final : public BaseRefHandle {
public:
typedef RefNode Node;
enum { BORN_REF = 1 };
explicit DummyRefHandle(RetireStation& retire_station) : BaseRefHandle(retire_station)
{}
void enter_critical() override
{}
void leave_critical() override
{}
void retire(Node* node, HazardList& reclaim_list) override
{
reclaim_list.push(&node->retire_link_);
}
void purge(HazardList& reclaim_list) override
{
UNUSED(reclaim_list);
}
void born(Node* node)
{
UNUSED(node);
}
int32_t end(Node* node)
{
UNUSED(node);
return 0;
}
bool inc(Node* node)
{
UNUSED(node);
return true;
}
int32_t dec(Node* node)
{
UNUSED(node);
return 1;
}
};
template <typename Key, typename Value, typename AllocHandle = AllocHandle<Key, Value>, typename RefHandle = RefHandle,
int64_t SHRINK_THRESHOLD = 8>
class ObLinkHashMap {
......@@ -264,8 +195,12 @@ public:
void purge()
{
HazardList reclaim_list;
get_retire_station().purge(reclaim_list);
reclaim_nodes(reclaim_list);
{
CriticalGuard(get_global_link_hashmap_qsync());
get_retire_station().purge(reclaim_list);
reclaim_nodes(reclaim_list);
}
WaitQuiescent(get_global_link_hashmap_qsync());
}
int64_t count() const
{
......@@ -344,6 +279,7 @@ public:
HazardList reclaim_list;
HashNode* node = CONTAINER_OF(hash_link, HashNode, hash_link_);
end_uref(node);
CriticalGuard(get_global_link_hashmap_qsync());
ref_handle_.retire(node, reclaim_list);
reclaim_nodes(reclaim_list);
count_handle_.add(-1);
......
......@@ -66,12 +66,21 @@ static uint64_t node_free CACHE_ALIGNED;
ObMemAttr attr(1001, ObNewModIds::OB_MEMSTORE);
static int64_t STEP = 0;
class TestAllocHandle {
typedef LinkHashNode<HashKey> Node;
public:
HashValue* alloc_value()
TestAllocHandle() : is_inited_(true)
{}
~TestAllocHandle()
{
ATOMIC_STORE(&is_inited_, false);
}
HashValue *alloc_value()
{
abort_unless(ATOMIC_LOAD(&is_inited_) == true);
ATOMIC_INC(&value_alloc);
HashValue* value = (HashValue*)ob_malloc(sizeof(HashValue), attr);
new (value) HashValue();
......@@ -79,12 +88,14 @@ public:
}
void free_value(HashValue* val)
{
abort_unless(ATOMIC_LOAD(&is_inited_) == true);
ATOMIC_INC(&value_free);
val->~HashValue();
ob_free(val);
}
Node* alloc_node(HashValue* val)
{
abort_unless(ATOMIC_LOAD(&is_inited_) == true);
UNUSED(val);
ATOMIC_INC(&node_alloc);
Node* node = (Node*)ob_malloc(sizeof(Node), attr);
......@@ -93,10 +104,18 @@ public:
}
void free_node(Node* node)
{
if (ATOMIC_LOAD(&STEP) == 1) {
IGNORE_RETURN ATOMIC_BCAS(&STEP, 1, 2);
usleep(1 * 1000 * 1000);
}
abort_unless(ATOMIC_LOAD(&is_inited_) == true);
ATOMIC_INC(&node_free);
node->~Node();
ob_free(node);
}
private:
bool is_inited_;
};
class AtomicGetFunctor {
......@@ -118,9 +137,7 @@ static bool print(HashKey& key, HashValue* value)
return true;
}
// typedef ObLinkHashMap<HashKey, HashValue, TestAllocHandle> Hashmap;
typedef ObLinkHashMap<HashKey, HashValue, TestAllocHandle, TCRefHandle> Hashmap;
// typedef ObLinkHashMapWithHazardValue<HashKey, HashValue, TestAllocHandle> Hashmap;
typedef ObLinkHashMap<HashKey, HashValue, TestAllocHandle> Hashmap;
TEST(TestObHashMap, Feature)
{
......@@ -326,7 +343,37 @@ TEST(TestObHashMap, Stress)
EXPECT_EQ(node_free, node_alloc);
}
int main(int argc, char** argv)
TEST(TestObHashMap, Retire)
{
std::thread *t;
{
Hashmap A;
HashKey key;
HashValue *val_ptr = nullptr;
EXPECT_EQ(OB_SUCCESS, A.init());
key.v_ = 1;
EXPECT_EQ(OB_SUCCESS, A.create(key, val_ptr));
A.revert(val_ptr);
EXPECT_EQ(OB_SUCCESS, A.del(key));
ATOMIC_INC(&STEP);
t = new std::thread([&]() {
usleep(10 * 1000);
Hashmap B;
HashKey key;
EXPECT_EQ(OB_SUCCESS, B.init());
key.v_ = 1;
EXPECT_EQ(OB_SUCCESS, B.create(key, val_ptr));
B.revert(val_ptr);
});
while (ATOMIC_LOAD(&STEP) != 2)
;
// ~A()
}
t->join();
delete t;
}
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
oceanbase::common::ObLogger::get_logger().set_file_name("test_link_hashmap.log", true);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册