提交 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) ...@@ -30,6 +30,12 @@ inline int32_t faa_if_positive(int32_t* addr, int32_t x)
return ov; return ov;
} }
inline static ObQSync &get_global_link_hashmap_qsync()
{
static ObQSync qsync;
return qsync;
}
// DO NOT use me // DO NOT use me
class BaseRefHandle { class BaseRefHandle {
public: public:
...@@ -65,42 +71,6 @@ protected: ...@@ -65,42 +71,6 @@ protected:
uint64_t qc_slot_; 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. // balanced read/del performance, realtime reclaim Value, batch/delay reclaim Node.
class RefHandle final : public BaseRefHandle { class RefHandle final : public BaseRefHandle {
public: public:
...@@ -125,45 +95,6 @@ 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, template <typename Key, typename Value, typename AllocHandle = AllocHandle<Key, Value>, typename RefHandle = RefHandle,
int64_t SHRINK_THRESHOLD = 8> int64_t SHRINK_THRESHOLD = 8>
class ObLinkHashMap { class ObLinkHashMap {
...@@ -264,8 +195,12 @@ public: ...@@ -264,8 +195,12 @@ public:
void purge() void purge()
{ {
HazardList reclaim_list; 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 int64_t count() const
{ {
...@@ -344,6 +279,7 @@ public: ...@@ -344,6 +279,7 @@ public:
HazardList reclaim_list; HazardList reclaim_list;
HashNode* node = CONTAINER_OF(hash_link, HashNode, hash_link_); HashNode* node = CONTAINER_OF(hash_link, HashNode, hash_link_);
end_uref(node); end_uref(node);
CriticalGuard(get_global_link_hashmap_qsync());
ref_handle_.retire(node, reclaim_list); ref_handle_.retire(node, reclaim_list);
reclaim_nodes(reclaim_list); reclaim_nodes(reclaim_list);
count_handle_.add(-1); count_handle_.add(-1);
......
...@@ -66,12 +66,21 @@ static uint64_t node_free CACHE_ALIGNED; ...@@ -66,12 +66,21 @@ static uint64_t node_free CACHE_ALIGNED;
ObMemAttr attr(1001, ObNewModIds::OB_MEMSTORE); ObMemAttr attr(1001, ObNewModIds::OB_MEMSTORE);
static int64_t STEP = 0;
class TestAllocHandle { class TestAllocHandle {
typedef LinkHashNode<HashKey> Node; typedef LinkHashNode<HashKey> Node;
public: 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); ATOMIC_INC(&value_alloc);
HashValue* value = (HashValue*)ob_malloc(sizeof(HashValue), attr); HashValue* value = (HashValue*)ob_malloc(sizeof(HashValue), attr);
new (value) HashValue(); new (value) HashValue();
...@@ -79,12 +88,14 @@ public: ...@@ -79,12 +88,14 @@ public:
} }
void free_value(HashValue* val) void free_value(HashValue* val)
{ {
abort_unless(ATOMIC_LOAD(&is_inited_) == true);
ATOMIC_INC(&value_free); ATOMIC_INC(&value_free);
val->~HashValue(); val->~HashValue();
ob_free(val); ob_free(val);
} }
Node* alloc_node(HashValue* val) Node* alloc_node(HashValue* val)
{ {
abort_unless(ATOMIC_LOAD(&is_inited_) == true);
UNUSED(val); UNUSED(val);
ATOMIC_INC(&node_alloc); ATOMIC_INC(&node_alloc);
Node* node = (Node*)ob_malloc(sizeof(Node), attr); Node* node = (Node*)ob_malloc(sizeof(Node), attr);
...@@ -93,10 +104,18 @@ public: ...@@ -93,10 +104,18 @@ public:
} }
void free_node(Node* node) 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); ATOMIC_INC(&node_free);
node->~Node(); node->~Node();
ob_free(node); ob_free(node);
} }
private:
bool is_inited_;
}; };
class AtomicGetFunctor { class AtomicGetFunctor {
...@@ -118,9 +137,7 @@ static bool print(HashKey& key, HashValue* value) ...@@ -118,9 +137,7 @@ static bool print(HashKey& key, HashValue* value)
return true; return true;
} }
// typedef ObLinkHashMap<HashKey, HashValue, TestAllocHandle> Hashmap; typedef ObLinkHashMap<HashKey, HashValue, TestAllocHandle> Hashmap;
typedef ObLinkHashMap<HashKey, HashValue, TestAllocHandle, TCRefHandle> Hashmap;
// typedef ObLinkHashMapWithHazardValue<HashKey, HashValue, TestAllocHandle> Hashmap;
TEST(TestObHashMap, Feature) TEST(TestObHashMap, Feature)
{ {
...@@ -326,7 +343,37 @@ TEST(TestObHashMap, Stress) ...@@ -326,7 +343,37 @@ TEST(TestObHashMap, Stress)
EXPECT_EQ(node_free, node_alloc); 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); testing::InitGoogleTest(&argc, argv);
oceanbase::common::ObLogger::get_logger().set_file_name("test_link_hashmap.log", true); 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.
先完成此消息的编辑!
想要评论请 注册