Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
慢慢CG
TDengine
提交
c6aef80a
T
TDengine
项目概览
慢慢CG
/
TDengine
与 Fork 源项目一致
Fork自
taosdata / TDengine
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
TDengine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
c6aef80a
编写于
5月 13, 2020
作者:
H
hjLiao
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[td-225] refactor hash function
上级
5f0a0516
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
247 addition
and
235 deletion
+247
-235
src/util/inc/hash.h
src/util/inc/hash.h
+3
-3
src/util/src/hash.c
src/util/src/hash.c
+244
-232
未找到文件。
src/util/inc/hash.h
浏览文件 @
c6aef80a
...
...
@@ -94,7 +94,7 @@ size_t taosHashGetSize(const SHashObj *pHashObj);
* @param size
* @return
*/
int32_t
taosHashPut
(
SHashObj
*
pHashObj
,
const
char
*
key
,
size_t
keyLen
,
void
*
data
,
size_t
size
);
int32_t
taosHashPut
(
SHashObj
*
pHashObj
,
const
void
*
key
,
size_t
keyLen
,
void
*
data
,
size_t
size
);
/**
* return the payload data with the specified key
...
...
@@ -104,7 +104,7 @@ int32_t taosHashPut(SHashObj *pHashObj, const char *key, size_t keyLen, void *da
* @param keyLen
* @return
*/
void
*
taosHashGet
(
SHashObj
*
pHashObj
,
const
char
*
key
,
size_t
keyLen
);
void
*
taosHashGet
(
SHashObj
*
pHashObj
,
const
void
*
key
,
size_t
keyLen
);
/**
* remove item with the specified key
...
...
@@ -112,7 +112,7 @@ void *taosHashGet(SHashObj *pHashObj, const char *key, size_t keyLen);
* @param key
* @param keyLen
*/
void
taosHashRemove
(
SHashObj
*
pHashObj
,
const
char
*
key
,
size_t
keyLen
);
void
taosHashRemove
(
SHashObj
*
pHashObj
,
const
void
*
key
,
size_t
keyLen
);
/**
* clean up hash table
...
...
src/util/src/hash.c
浏览文件 @
c6aef80a
...
...
@@ -17,7 +17,6 @@
#include "hash.h"
#include "tulog.h"
#include "ttime.h"
#include "tutil.h"
static
FORCE_INLINE
void
__wr_lock
(
void
*
lock
)
{
...
...
@@ -90,154 +89,65 @@ static FORCE_INLINE int32_t taosHashCapacity(int32_t length) {
/**
* inplace update node in hash table
* @param pHashObj
hash table object
* @param pNode data node
* @param pHashObj hash table object
* @param pNode
hash
data node
*/
static
void
doUpdateHashTable
(
SHashObj
*
pHashObj
,
SHashNode
*
pNode
)
{
if
(
pNode
->
prev1
)
{
pNode
->
prev1
->
next
=
pNode
;
}
if
(
pNode
->
next
)
{
(
pNode
->
next
)
->
prev
=
pNode
;
}
}
static
void
doUpdateHashTable
(
SHashObj
*
pHashObj
,
SHashNode
*
pNode
);
/**
*
g
et SHashNode from hashlist, nodes from trash are not included.
*
G
et SHashNode from hashlist, nodes from trash are not included.
* @param pHashObj Cache objection
* @param key key for hash
* @param keyLen key length
* @param hashVal hash value by hash function
* @return
*/
static
SHashNode
*
doGetNodeFromHashTable
(
SHashObj
*
pHashObj
,
const
char
*
key
,
uint32_t
keyLen
,
uint32_t
*
hashVal
)
{
uint32_t
hash
=
(
*
pHashObj
->
hashFp
)(
key
,
keyLen
);
int32_t
slot
=
HASH_INDEX
(
hash
,
pHashObj
->
capacity
);
SHashEntry
*
pEntry
=
pHashObj
->
hashList
[
slot
];
SHashNode
*
pNode
=
pEntry
->
next
;
while
(
pNode
)
{
if
((
pNode
->
keyLen
==
keyLen
)
&&
(
memcmp
(
pNode
->
key
,
key
,
keyLen
)
==
0
))
{
break
;
}
pNode
=
pNode
->
next
;
}
if
(
pNode
)
{
assert
(
HASH_INDEX
(
pNode
->
hashVal
,
pHashObj
->
capacity
)
==
slot
);
}
// return the calculated hash value, to avoid calculating it again in other functions
if
(
hashVal
!=
NULL
)
{
*
hashVal
=
hash
;
}
return
pNode
;
}
static
SHashNode
*
doGetNodeFromHashTable
(
SHashObj
*
pHashObj
,
const
void
*
key
,
uint32_t
keyLen
,
uint32_t
*
hashVal
);
/**
*
r
esize the hash list if the threshold is reached
*
R
esize the hash list if the threshold is reached
*
* @param pHashObj
*/
static
void
taosHashTableResize
(
SHashObj
*
pHashObj
)
{
if
(
pHashObj
->
size
<
pHashObj
->
capacity
*
HASH_DEFAULT_LOAD_FACTOR
)
{
return
;
}
// double the original capacity
SHashNode
*
pNode
=
NULL
;
SHashNode
*
pNext
=
NULL
;
static
void
taosHashTableResize
(
SHashObj
*
pHashObj
);
int32_t
newSize
=
pHashObj
->
capacity
<<
1u
;
if
(
newSize
>
HASH_MAX_CAPACITY
)
{
// uTrace("current capacity:%d, maximum capacity:%d, no resize applied due to limitation is reached",
// pHashObj->capacity, HASH_MAX_CAPACITY);
return
;
}
// int64_t st = taosGetTimestampUs();
SHashEntry
**
pNewEntry
=
realloc
(
pHashObj
->
hashList
,
sizeof
(
SHashEntry
*
)
*
newSize
);
if
(
pNewEntry
==
NULL
)
{
// uTrace("cache resize failed due to out of memory, capacity remain:%d", pHashObj->capacity);
return
;
}
pHashObj
->
hashList
=
pNewEntry
;
for
(
int32_t
i
=
pHashObj
->
capacity
;
i
<
newSize
;
++
i
)
{
pHashObj
->
hashList
[
i
]
=
calloc
(
1
,
sizeof
(
SHashEntry
));
}
pHashObj
->
capacity
=
newSize
;
for
(
int32_t
i
=
0
;
i
<
pHashObj
->
capacity
;
++
i
)
{
SHashEntry
*
pEntry
=
pHashObj
->
hashList
[
i
];
pNode
=
pEntry
->
next
;
if
(
pNode
!=
NULL
)
{
assert
(
pNode
->
prev1
==
pEntry
&&
pEntry
->
num
>
0
);
}
while
(
pNode
)
{
int32_t
j
=
HASH_INDEX
(
pNode
->
hashVal
,
pHashObj
->
capacity
);
if
(
j
==
i
)
{
// this key resides in the same slot, no need to relocate it
pNode
=
pNode
->
next
;
}
else
{
pNext
=
pNode
->
next
;
// remove from current slot
assert
(
pNode
->
prev1
!=
NULL
);
if
(
pNode
->
prev1
==
pEntry
)
{
// first node of the overflow linked list
pEntry
->
next
=
pNode
->
next
;
}
else
{
pNode
->
prev
->
next
=
pNode
->
next
;
}
pEntry
->
num
--
;
assert
(
pEntry
->
num
>=
0
);
if
(
pNode
->
next
!=
NULL
)
{
(
pNode
->
next
)
->
prev
=
pNode
->
prev
;
}
// added into new slot
pNode
->
next
=
NULL
;
pNode
->
prev1
=
NULL
;
SHashEntry
*
pNewIndexEntry
=
pHashObj
->
hashList
[
j
];
if
(
pNewIndexEntry
->
next
!=
NULL
)
{
assert
(
pNewIndexEntry
->
next
->
prev1
==
pNewIndexEntry
);
pNewIndexEntry
->
next
->
prev
=
pNode
;
}
pNode
->
next
=
pNewIndexEntry
->
next
;
pNode
->
prev1
=
pNewIndexEntry
;
pNewIndexEntry
->
next
=
pNode
;
pNewIndexEntry
->
num
++
;
/**
* @param key key of object for hash, usually a null-terminated string
* @param keyLen length of key
* @param pData actually data. Requires a consecutive memory block, no pointer is allowed in pData.
* Pointer copy causes memory access error.
* @param dsize size of data
* @return SHashNode
*/
static
SHashNode
*
doCreateHashNode
(
const
void
*
key
,
size_t
keyLen
,
const
void
*
pData
,
size_t
dsize
,
uint32_t
hashVal
);
// continue
pNode
=
pNext
;
}
}
}
/**
* Update the hash node
*
* @param pNode hash node
* @param key key for generate hash value
* @param keyLen key length
* @param pData actual data
* @param dsize size of actual data
* @return hash node
*/
static
SHashNode
*
doUpdateHashNode
(
SHashNode
*
pNode
,
const
void
*
key
,
size_t
keyLen
,
const
void
*
pData
,
size_t
dsize
);
// int64_t et = taosGetTimestampUs();
// uTrace("hash table resize completed, new capacity:%d, load factor:%f, elapsed time:%fms", pHashObj->capacity,
// ((double)pHashObj->size) / pHashObj->capacity, (et - st) / 1000.0);
}
/**
* insert the hash node at the front of the linked list
*
* @param pHashObj
* @param pNode
*/
static
void
doAddToHashTable
(
SHashObj
*
pHashObj
,
SHashNode
*
pNode
);
/**
*
@param capacity maximum slots available for hash elements
* @param
fn hash function
*
Get the next element in hash table for iterator
* @param
pIter
* @return
*/
static
SHashNode
*
getNextHashNode
(
SHashMutableIterator
*
pIter
);
SHashObj
*
taosHashInit
(
size_t
capacity
,
_hash_fn_t
fn
,
bool
threadsafe
)
{
if
(
capacity
==
0
||
fn
==
NULL
)
{
return
NULL
;
...
...
@@ -285,79 +195,6 @@ SHashObj *taosHashInit(size_t capacity, _hash_fn_t fn, bool threadsafe) {
return
pHashObj
;
}
/**
* @param key key of object for hash, usually a null-terminated string
* @param keyLen length of key
* @param pData actually data. required a consecutive memory block, no pointer is allowed
* in pData. Pointer copy causes memory access error.
* @param size size of block
* @return SHashNode
*/
static
SHashNode
*
doCreateHashNode
(
const
char
*
key
,
size_t
keyLen
,
const
char
*
pData
,
size_t
dataSize
,
uint32_t
hashVal
)
{
size_t
totalSize
=
dataSize
+
sizeof
(
SHashNode
)
+
keyLen
+
1
;
// one extra byte for null
SHashNode
*
pNewNode
=
calloc
(
1
,
totalSize
);
if
(
pNewNode
==
NULL
)
{
uError
(
"failed to allocate memory, reason:%s"
,
strerror
(
errno
));
return
NULL
;
}
memcpy
(
pNewNode
->
data
,
pData
,
dataSize
);
pNewNode
->
key
=
pNewNode
->
data
+
dataSize
;
memcpy
(
pNewNode
->
key
,
key
,
keyLen
);
pNewNode
->
keyLen
=
keyLen
;
pNewNode
->
hashVal
=
hashVal
;
return
pNewNode
;
}
static
SHashNode
*
doUpdateHashNode
(
SHashNode
*
pNode
,
const
char
*
key
,
size_t
keyLen
,
const
char
*
pData
,
size_t
dataSize
)
{
size_t
size
=
dataSize
+
sizeof
(
SHashNode
)
+
keyLen
;
SHashNode
*
pNewNode
=
(
SHashNode
*
)
realloc
(
pNode
,
size
);
if
(
pNewNode
==
NULL
)
{
return
NULL
;
}
memcpy
(
pNewNode
->
data
,
pData
,
dataSize
);
pNewNode
->
key
=
pNewNode
->
data
+
dataSize
;
assert
(
memcmp
(
pNewNode
->
key
,
key
,
keyLen
)
==
0
&&
keyLen
==
pNewNode
->
keyLen
);
memcpy
(
pNewNode
->
key
,
key
,
keyLen
);
return
pNewNode
;
}
/**
* insert the hash node at the front of the linked list
*
* @param pHashObj
* @param pNode
*/
static
void
doAddToHashTable
(
SHashObj
*
pHashObj
,
SHashNode
*
pNode
)
{
assert
(
pNode
!=
NULL
);
int32_t
index
=
HASH_INDEX
(
pNode
->
hashVal
,
pHashObj
->
capacity
);
SHashEntry
*
pEntry
=
pHashObj
->
hashList
[
index
];
pNode
->
next
=
pEntry
->
next
;
if
(
pEntry
->
next
)
{
pEntry
->
next
->
prev
=
pNode
;
}
pEntry
->
next
=
pNode
;
pNode
->
prev1
=
pEntry
;
pEntry
->
num
++
;
pHashObj
->
size
++
;
}
size_t
taosHashGetSize
(
const
SHashObj
*
pHashObj
)
{
if
(
pHashObj
==
NULL
)
{
return
0
;
...
...
@@ -366,12 +203,7 @@ size_t taosHashGetSize(const SHashObj *pHashObj) {
return
pHashObj
->
size
;
}
/**
* add data node into hash table
* @param pHashObj hash object
* @param pNode hash node
*/
int32_t
taosHashPut
(
SHashObj
*
pHashObj
,
const
char
*
key
,
size_t
keyLen
,
void
*
data
,
size_t
size
)
{
int32_t
taosHashPut
(
SHashObj
*
pHashObj
,
const
void
*
key
,
size_t
keyLen
,
void
*
data
,
size_t
size
)
{
__wr_lock
(
pHashObj
->
lock
);
uint32_t
hashVal
=
0
;
...
...
@@ -402,7 +234,7 @@ int32_t taosHashPut(SHashObj *pHashObj, const char *key, size_t keyLen, void *da
return
0
;
}
void
*
taosHashGet
(
SHashObj
*
pHashObj
,
const
char
*
key
,
size_t
keyLen
)
{
void
*
taosHashGet
(
SHashObj
*
pHashObj
,
const
void
*
key
,
size_t
keyLen
)
{
__rd_lock
(
pHashObj
->
lock
);
uint32_t
hashVal
=
0
;
...
...
@@ -419,12 +251,7 @@ void *taosHashGet(SHashObj *pHashObj, const char *key, size_t keyLen) {
}
}
/**
* remove node in hash list
* @param pHashObj
* @param pNode
*/
void
taosHashRemove
(
SHashObj
*
pHashObj
,
const
char
*
key
,
size_t
keyLen
)
{
void
taosHashRemove
(
SHashObj
*
pHashObj
,
const
void
*
key
,
size_t
keyLen
)
{
__wr_lock
(
pHashObj
->
lock
);
uint32_t
val
=
0
;
...
...
@@ -518,23 +345,6 @@ SHashMutableIterator *taosHashCreateIter(SHashObj *pHashObj) {
return
pIter
;
}
static
SHashNode
*
getNextHashNode
(
SHashMutableIterator
*
pIter
)
{
assert
(
pIter
!=
NULL
);
pIter
->
entryIndex
++
;
while
(
pIter
->
entryIndex
<
pIter
->
pHashObj
->
capacity
)
{
SHashEntry
*
pEntry
=
pIter
->
pHashObj
->
hashList
[
pIter
->
entryIndex
];
if
(
pEntry
->
next
==
NULL
)
{
pIter
->
entryIndex
++
;
continue
;
}
return
pEntry
->
next
;
}
return
NULL
;
}
bool
taosHashIterNext
(
SHashMutableIterator
*
pIter
)
{
if
(
pIter
==
NULL
)
{
return
false
;
...
...
@@ -617,3 +427,205 @@ int32_t taosHashGetMaxOverflowLinkLength(const SHashObj *pHashObj) {
return
num
;
}
void
doUpdateHashTable
(
SHashObj
*
pHashObj
,
SHashNode
*
pNode
)
{
if
(
pNode
->
prev1
)
{
pNode
->
prev1
->
next
=
pNode
;
}
if
(
pNode
->
next
)
{
(
pNode
->
next
)
->
prev
=
pNode
;
}
}
SHashNode
*
doGetNodeFromHashTable
(
SHashObj
*
pHashObj
,
const
void
*
key
,
uint32_t
keyLen
,
uint32_t
*
hashVal
)
{
uint32_t
hash
=
(
*
pHashObj
->
hashFp
)(
key
,
keyLen
);
int32_t
slot
=
HASH_INDEX
(
hash
,
pHashObj
->
capacity
);
SHashEntry
*
pEntry
=
pHashObj
->
hashList
[
slot
];
SHashNode
*
pNode
=
pEntry
->
next
;
while
(
pNode
)
{
if
((
pNode
->
keyLen
==
keyLen
)
&&
(
memcmp
(
pNode
->
key
,
key
,
keyLen
)
==
0
))
{
break
;
}
pNode
=
pNode
->
next
;
}
if
(
pNode
)
{
assert
(
HASH_INDEX
(
pNode
->
hashVal
,
pHashObj
->
capacity
)
==
slot
);
}
// return the calculated hash value, to avoid calculating it again in other functions
if
(
hashVal
!=
NULL
)
{
*
hashVal
=
hash
;
}
return
pNode
;
}
void
taosHashTableResize
(
SHashObj
*
pHashObj
)
{
if
(
pHashObj
->
size
<
pHashObj
->
capacity
*
HASH_DEFAULT_LOAD_FACTOR
)
{
return
;
}
// double the original capacity
SHashNode
*
pNode
=
NULL
;
SHashNode
*
pNext
=
NULL
;
int32_t
newSize
=
pHashObj
->
capacity
<<
1u
;
if
(
newSize
>
HASH_MAX_CAPACITY
)
{
// uTrace("current capacity:%d, maximum capacity:%d, no resize applied due to limitation is reached",
// pHashObj->capacity, HASH_MAX_CAPACITY);
return
;
}
// int64_t st = taosGetTimestampUs();
SHashEntry
**
pNewEntry
=
realloc
(
pHashObj
->
hashList
,
sizeof
(
SHashEntry
*
)
*
newSize
);
if
(
pNewEntry
==
NULL
)
{
// uTrace("cache resize failed due to out of memory, capacity remain:%d", pHashObj->capacity);
return
;
}
pHashObj
->
hashList
=
pNewEntry
;
for
(
int32_t
i
=
pHashObj
->
capacity
;
i
<
newSize
;
++
i
)
{
pHashObj
->
hashList
[
i
]
=
calloc
(
1
,
sizeof
(
SHashEntry
));
}
pHashObj
->
capacity
=
newSize
;
for
(
int32_t
i
=
0
;
i
<
pHashObj
->
capacity
;
++
i
)
{
SHashEntry
*
pEntry
=
pHashObj
->
hashList
[
i
];
pNode
=
pEntry
->
next
;
if
(
pNode
!=
NULL
)
{
assert
(
pNode
->
prev1
==
pEntry
&&
pEntry
->
num
>
0
);
}
while
(
pNode
)
{
int32_t
j
=
HASH_INDEX
(
pNode
->
hashVal
,
pHashObj
->
capacity
);
if
(
j
==
i
)
{
// this key resides in the same slot, no need to relocate it
pNode
=
pNode
->
next
;
}
else
{
pNext
=
pNode
->
next
;
// remove from current slot
assert
(
pNode
->
prev1
!=
NULL
);
if
(
pNode
->
prev1
==
pEntry
)
{
// first node of the overflow linked list
pEntry
->
next
=
pNode
->
next
;
}
else
{
pNode
->
prev
->
next
=
pNode
->
next
;
}
pEntry
->
num
--
;
assert
(
pEntry
->
num
>=
0
);
if
(
pNode
->
next
!=
NULL
)
{
(
pNode
->
next
)
->
prev
=
pNode
->
prev
;
}
// added into new slot
pNode
->
next
=
NULL
;
pNode
->
prev1
=
NULL
;
SHashEntry
*
pNewIndexEntry
=
pHashObj
->
hashList
[
j
];
if
(
pNewIndexEntry
->
next
!=
NULL
)
{
assert
(
pNewIndexEntry
->
next
->
prev1
==
pNewIndexEntry
);
pNewIndexEntry
->
next
->
prev
=
pNode
;
}
pNode
->
next
=
pNewIndexEntry
->
next
;
pNode
->
prev1
=
pNewIndexEntry
;
pNewIndexEntry
->
next
=
pNode
;
pNewIndexEntry
->
num
++
;
// continue
pNode
=
pNext
;
}
}
}
// int64_t et = taosGetTimestampUs();
// uTrace("hash table resize completed, new capacity:%d, load factor:%f, elapsed time:%fms", pHashObj->capacity,
// ((double)pHashObj->size) / pHashObj->capacity, (et - st) / 1000.0);
}
SHashNode
*
doCreateHashNode
(
const
void
*
key
,
size_t
keyLen
,
const
void
*
pData
,
size_t
dsize
,
uint32_t
hashVal
)
{
size_t
totalSize
=
dsize
+
sizeof
(
SHashNode
)
+
keyLen
+
1
;
// one extra byte for null
SHashNode
*
pNewNode
=
calloc
(
1
,
totalSize
);
if
(
pNewNode
==
NULL
)
{
uError
(
"failed to allocate memory, reason:%s"
,
strerror
(
errno
));
return
NULL
;
}
memcpy
(
pNewNode
->
data
,
pData
,
dsize
);
pNewNode
->
key
=
pNewNode
->
data
+
dsize
;
memcpy
(
pNewNode
->
key
,
key
,
keyLen
);
pNewNode
->
keyLen
=
keyLen
;
pNewNode
->
hashVal
=
hashVal
;
return
pNewNode
;
}
SHashNode
*
doUpdateHashNode
(
SHashNode
*
pNode
,
const
void
*
key
,
size_t
keyLen
,
const
void
*
pData
,
size_t
dsize
)
{
size_t
size
=
dsize
+
sizeof
(
SHashNode
)
+
keyLen
;
SHashNode
*
pNewNode
=
(
SHashNode
*
)
realloc
(
pNode
,
size
);
if
(
pNewNode
==
NULL
)
{
return
NULL
;
}
memcpy
(
pNewNode
->
data
,
pData
,
dsize
);
pNewNode
->
key
=
pNewNode
->
data
+
dsize
;
assert
(
memcmp
(
pNewNode
->
key
,
key
,
keyLen
)
==
0
&&
keyLen
==
pNewNode
->
keyLen
);
memcpy
(
pNewNode
->
key
,
key
,
keyLen
);
return
pNewNode
;
}
void
doAddToHashTable
(
SHashObj
*
pHashObj
,
SHashNode
*
pNode
)
{
assert
(
pNode
!=
NULL
);
int32_t
index
=
HASH_INDEX
(
pNode
->
hashVal
,
pHashObj
->
capacity
);
SHashEntry
*
pEntry
=
pHashObj
->
hashList
[
index
];
pNode
->
next
=
pEntry
->
next
;
if
(
pEntry
->
next
)
{
pEntry
->
next
->
prev
=
pNode
;
}
pEntry
->
next
=
pNode
;
pNode
->
prev1
=
pEntry
;
pEntry
->
num
++
;
pHashObj
->
size
++
;
}
SHashNode
*
getNextHashNode
(
SHashMutableIterator
*
pIter
)
{
assert
(
pIter
!=
NULL
);
pIter
->
entryIndex
++
;
while
(
pIter
->
entryIndex
<
pIter
->
pHashObj
->
capacity
)
{
SHashEntry
*
pEntry
=
pIter
->
pHashObj
->
hashList
[
pIter
->
entryIndex
];
if
(
pEntry
->
next
==
NULL
)
{
pIter
->
entryIndex
++
;
continue
;
}
return
pEntry
->
next
;
}
return
NULL
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录