[td-225] refactor hash function
This commit is contained in:
parent
5f0a05163d
commit
c6aef80a39
|
@ -94,7 +94,7 @@ size_t taosHashGetSize(const SHashObj *pHashObj);
|
||||||
* @param size
|
* @param size
|
||||||
* @return
|
* @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
|
* 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
|
* @param keyLen
|
||||||
* @return
|
* @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
|
* remove item with the specified key
|
||||||
|
@ -112,7 +112,7 @@ void *taosHashGet(SHashObj *pHashObj, const char *key, size_t keyLen);
|
||||||
* @param key
|
* @param key
|
||||||
* @param keyLen
|
* @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
|
* clean up hash table
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "tulog.h"
|
#include "tulog.h"
|
||||||
#include "ttime.h"
|
|
||||||
#include "tutil.h"
|
#include "tutil.h"
|
||||||
|
|
||||||
static FORCE_INLINE void __wr_lock(void *lock) {
|
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
|
* inplace update node in hash table
|
||||||
* @param pHashObj hash table object
|
* @param pHashObj hash table object
|
||||||
* @param pNode data node
|
* @param pNode hash data node
|
||||||
*/
|
*/
|
||||||
static void doUpdateHashTable(SHashObj *pHashObj, SHashNode *pNode) {
|
static void doUpdateHashTable(SHashObj *pHashObj, SHashNode *pNode);
|
||||||
if (pNode->prev1) {
|
|
||||||
pNode->prev1->next = pNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pNode->next) {
|
|
||||||
(pNode->next)->prev = pNode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get SHashNode from hashlist, nodes from trash are not included.
|
* Get SHashNode from hashlist, nodes from trash are not included.
|
||||||
* @param pHashObj Cache objection
|
* @param pHashObj Cache objection
|
||||||
* @param key key for hash
|
* @param key key for hash
|
||||||
* @param keyLen key length
|
* @param keyLen key length
|
||||||
|
* @param hashVal hash value by hash function
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
static SHashNode *doGetNodeFromHashTable(SHashObj *pHashObj, const char *key, uint32_t keyLen, uint32_t *hashVal) {
|
static 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* resize the hash list if the threshold is reached
|
* Resize the hash list if the threshold is reached
|
||||||
*
|
*
|
||||||
* @param pHashObj
|
* @param pHashObj
|
||||||
*/
|
*/
|
||||||
static void taosHashTableResize(SHashObj *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;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param capacity maximum slots available for hash elements
|
* @param key key of object for hash, usually a null-terminated string
|
||||||
* @param fn hash function
|
* @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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* insert the hash node at the front of the linked list
|
||||||
|
*
|
||||||
|
* @param pHashObj
|
||||||
|
* @param pNode
|
||||||
|
*/
|
||||||
|
static void doAddToHashTable(SHashObj *pHashObj, SHashNode *pNode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the next element in hash table for iterator
|
||||||
|
* @param pIter
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
static SHashNode *getNextHashNode(SHashMutableIterator *pIter);
|
||||||
|
|
||||||
SHashObj *taosHashInit(size_t capacity, _hash_fn_t fn, bool threadsafe) {
|
SHashObj *taosHashInit(size_t capacity, _hash_fn_t fn, bool threadsafe) {
|
||||||
if (capacity == 0 || fn == NULL) {
|
if (capacity == 0 || fn == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -285,79 +195,6 @@ SHashObj *taosHashInit(size_t capacity, _hash_fn_t fn, bool threadsafe) {
|
||||||
return pHashObj;
|
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) {
|
size_t taosHashGetSize(const SHashObj *pHashObj) {
|
||||||
if (pHashObj == NULL) {
|
if (pHashObj == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -366,12 +203,7 @@ size_t taosHashGetSize(const SHashObj *pHashObj) {
|
||||||
return pHashObj->size;
|
return pHashObj->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
int32_t taosHashPut(SHashObj *pHashObj, const void *key, size_t keyLen, void *data, size_t 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) {
|
|
||||||
__wr_lock(pHashObj->lock);
|
__wr_lock(pHashObj->lock);
|
||||||
|
|
||||||
uint32_t hashVal = 0;
|
uint32_t hashVal = 0;
|
||||||
|
@ -402,7 +234,7 @@ int32_t taosHashPut(SHashObj *pHashObj, const char *key, size_t keyLen, void *da
|
||||||
return 0;
|
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);
|
__rd_lock(pHashObj->lock);
|
||||||
|
|
||||||
uint32_t hashVal = 0;
|
uint32_t hashVal = 0;
|
||||||
|
@ -419,12 +251,7 @@ void *taosHashGet(SHashObj *pHashObj, const char *key, size_t keyLen) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void taosHashRemove(SHashObj *pHashObj, const void *key, size_t keyLen) {
|
||||||
* remove node in hash list
|
|
||||||
* @param pHashObj
|
|
||||||
* @param pNode
|
|
||||||
*/
|
|
||||||
void taosHashRemove(SHashObj *pHashObj, const char *key, size_t keyLen) {
|
|
||||||
__wr_lock(pHashObj->lock);
|
__wr_lock(pHashObj->lock);
|
||||||
|
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
|
@ -518,23 +345,6 @@ SHashMutableIterator *taosHashCreateIter(SHashObj *pHashObj) {
|
||||||
return pIter;
|
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) {
|
bool taosHashIterNext(SHashMutableIterator *pIter) {
|
||||||
if (pIter == NULL) {
|
if (pIter == NULL) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -617,3 +427,205 @@ int32_t taosHashGetMaxOverflowLinkLength(const SHashObj *pHashObj) {
|
||||||
|
|
||||||
return num;
|
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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue