add defence in link_hashmap for leak of revert
This commit is contained in:
26
deps/oblib/src/lib/hash/ob_link_hashmap.h
vendored
26
deps/oblib/src/lib/hash/ob_link_hashmap.h
vendored
@ -22,11 +22,11 @@ namespace oceanbase
|
|||||||
{
|
{
|
||||||
namespace common
|
namespace common
|
||||||
{
|
{
|
||||||
inline int32_t faa_if_positive(int32_t* addr, int32_t x)
|
inline int32_t faa_if_ge(int32_t* addr, int32_t x, int32_t cmp)
|
||||||
{
|
{
|
||||||
int32_t ov = ATOMIC_LOAD(addr);
|
int32_t ov = ATOMIC_LOAD(addr);
|
||||||
int32_t nv = 0;
|
int32_t nv = 0;
|
||||||
while(ov > 0 && ov != (nv = ATOMIC_VCAS(addr, ov, ov + x))) {
|
while (ov >= cmp && ov != (nv = ATOMIC_VCAS(addr, ov, ov + x))) {
|
||||||
ov = nv;
|
ov = nv;
|
||||||
}
|
}
|
||||||
return ov;
|
return ov;
|
||||||
@ -43,7 +43,6 @@ class BaseRefHandle
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef RefNode Node;
|
typedef RefNode Node;
|
||||||
enum { BORN_REF = INT32_MAX/2 };
|
|
||||||
explicit BaseRefHandle(RetireStation& retire_station): qclock_(get_global_qclock()), retire_station_(retire_station), qc_slot_(UINT64_MAX) {}
|
explicit BaseRefHandle(RetireStation& retire_station): qclock_(get_global_qclock()), retire_station_(retire_station), qc_slot_(UINT64_MAX) {}
|
||||||
~BaseRefHandle() {}
|
~BaseRefHandle() {}
|
||||||
virtual void enter_critical() { qc_slot_ = qclock_.enter_critical(); }
|
virtual void enter_critical() { qc_slot_ = qclock_.enter_critical(); }
|
||||||
@ -68,11 +67,12 @@ protected:
|
|||||||
class ZeroRefHandle final : public BaseRefHandle
|
class ZeroRefHandle final : public BaseRefHandle
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum { BORN_REF = 1 };
|
||||||
typedef RefNode Node;
|
typedef RefNode Node;
|
||||||
explicit ZeroRefHandle(RetireStation& retire_station) : BaseRefHandle(retire_station) {}
|
explicit ZeroRefHandle(RetireStation& retire_station) : BaseRefHandle(retire_station) {}
|
||||||
void born(Node* node) { (void)ATOMIC_AAF(&node->uref_, 1); }
|
void born(Node* node) { (void)ATOMIC_AAF(&node->uref_, BORN_REF); }
|
||||||
int32_t end(Node* node) { return ATOMIC_AAF(&node->uref_, -1); }
|
int32_t end(Node* node) { return ATOMIC_AAF(&node->uref_, -BORN_REF); }
|
||||||
bool inc(Node* node) { return faa_if_positive(&node->uref_, 1) > 0; }
|
bool inc(Node* node) { return faa_if_ge(&node->uref_, 1, BORN_REF) >= BORN_REF; }
|
||||||
int32_t dec(Node* node) { return ATOMIC_AAF(&node->uref_, -1); }
|
int32_t dec(Node* node) { return ATOMIC_AAF(&node->uref_, -1); }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -80,11 +80,12 @@ public:
|
|||||||
class RefHandle final : public BaseRefHandle
|
class RefHandle final : public BaseRefHandle
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum { BORN_REF = INT32_MAX/2 };
|
||||||
typedef RefNode Node;
|
typedef RefNode Node;
|
||||||
explicit RefHandle(RetireStation& retire_station) : BaseRefHandle(retire_station) {}
|
explicit RefHandle(RetireStation& retire_station) : BaseRefHandle(retire_station) {}
|
||||||
void born(Node* node) { (void)ATOMIC_AAF(&node->uref_, BORN_REF); }
|
void born(Node* node) { (void)ATOMIC_AAF(&node->uref_, BORN_REF); }
|
||||||
int32_t end(Node* node) { return ATOMIC_AAF(&node->uref_, -BORN_REF); }
|
int32_t end(Node* node) { return ATOMIC_AAF(&node->uref_, -BORN_REF); }
|
||||||
bool inc(Node* node) { return faa_if_positive(&node->uref_, 1) > 0; }
|
bool inc(Node* node) { return faa_if_ge(&node->uref_, 1, BORN_REF) >= BORN_REF; }
|
||||||
int32_t dec(Node* node) { return ATOMIC_AAF(&node->uref_, -1); }
|
int32_t dec(Node* node) { return ATOMIC_AAF(&node->uref_, -1); }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -300,9 +301,17 @@ public:
|
|||||||
if (OB_LIKELY(0 == hash_ret)) {
|
if (OB_LIKELY(0 == hash_ret)) {
|
||||||
HashNode* node = CONTAINER_OF(hash_link, HashNode, hash_link_);
|
HashNode* node = CONTAINER_OF(hash_link, HashNode, hash_link_);
|
||||||
if (!try_inc_ref(node)) {
|
if (!try_inc_ref(node)) {
|
||||||
hash_ret = -ENOENT;
|
if (node->uref_ >= 0) {
|
||||||
|
hash_ret = -ENOENT; // get after del
|
||||||
|
} else {
|
||||||
|
hash_ret = -EPERM; // uref < 0, maybe revert too much time.
|
||||||
|
}
|
||||||
|
COMMON_LOG_RET(WARN, err_code_map(hash_ret), "inc ref error", K(node->uref_), K(lbt()));
|
||||||
} else {
|
} else {
|
||||||
value = (Value*)node->hash_val_;
|
value = (Value*)node->hash_val_;
|
||||||
|
if (node->uref_ - RefHandle::BORN_REF > 1000) {
|
||||||
|
COMMON_LOG_RET(WARN, OB_SUCCESS, "uref leak check", K(node->uref_), K(lbt()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err_code_map(hash_ret);
|
return err_code_map(hash_ret);
|
||||||
@ -388,6 +397,7 @@ private:
|
|||||||
case -EEXIST: ret = OB_ENTRY_EXIST; break;
|
case -EEXIST: ret = OB_ENTRY_EXIST; break;
|
||||||
case -ENOMEM: ret = OB_ALLOCATE_MEMORY_FAILED; break;
|
case -ENOMEM: ret = OB_ALLOCATE_MEMORY_FAILED; break;
|
||||||
case -EOVERFLOW: ret = OB_SIZE_OVERFLOW; break;
|
case -EOVERFLOW: ret = OB_SIZE_OVERFLOW; break;
|
||||||
|
case -EPERM: ret = OB_ERR_UNEXPECTED; break;
|
||||||
default: ret = OB_ERROR;
|
default: ret = OB_ERROR;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
Reference in New Issue
Block a user