435 lines
9.9 KiB
C++
435 lines
9.9 KiB
C++
/***************************************************************************************
|
||
*
|
||
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||
*
|
||
* By downloading, copying, installing or using the software you agree to this license.
|
||
* If you do not agree to this license, do not download, install,
|
||
* copy or use the software.
|
||
*
|
||
* Copyright (C) 2014-2022, Happytimesoft Corporation, all rights reserved.
|
||
*
|
||
* Redistribution and use in binary forms, with or without modification, are permitted.
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software distributed
|
||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
|
||
* language governing permissions and limitations under the License.
|
||
*
|
||
****************************************************************************************/
|
||
|
||
#include "sys_inc.h"
|
||
#include "sys_log.h"
|
||
#include "ihash.h"
|
||
|
||
/****************************************************************\
|
||
HASH操作功能函数: 初始化数组,Call-Id索引值计算,添加/删除
|
||
\****************************************************************/
|
||
HT_API IHASHCTX * ihash_init(uint32 hash_num, uint32 link_num)
|
||
{
|
||
IHASHCTX * p_ctx = (IHASHCTX *)malloc(sizeof(IHASHCTX));
|
||
if (p_ctx == NULL)
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
memset(p_ctx, 0, sizeof(IHASHCTX));
|
||
|
||
p_ctx->hash_num = hash_num;
|
||
p_ctx->link_num = link_num;
|
||
|
||
p_ctx->hash_array = (IHASHNODE *)malloc(sizeof(IHASHNODE) * hash_num);
|
||
if (p_ctx->hash_array == NULL)
|
||
{
|
||
free(p_ctx);
|
||
return NULL;
|
||
}
|
||
memset(p_ctx->hash_array, 0, sizeof(IHASHNODE) * hash_num);
|
||
|
||
p_ctx->link_array = (IHASHNODE *)malloc(sizeof(IHASHNODE) * link_num);
|
||
if (p_ctx->link_array == NULL)
|
||
{
|
||
free(p_ctx->hash_array);
|
||
free(p_ctx);
|
||
return NULL;
|
||
}
|
||
memset(p_ctx->link_array, 0, sizeof(IHASHNODE) * link_num);
|
||
|
||
p_ctx->hash_semMutex = sys_os_create_mutex();
|
||
p_ctx->link_semMutex = sys_os_create_mutex();
|
||
|
||
uint32 i;
|
||
for (i=1; i<p_ctx->link_num; i++)
|
||
{
|
||
p_ctx->link_array[i].next_index = i+1;
|
||
if (i == (p_ctx->link_num - 1))
|
||
{
|
||
p_ctx->link_array[i].next_index = 0;
|
||
}
|
||
}
|
||
|
||
p_ctx->link_index = 1; // 第一个单元0不用
|
||
|
||
return p_ctx;
|
||
}
|
||
|
||
HT_API void ihash_uninit(IHASHCTX * p_ctx)
|
||
{
|
||
if (NULL == p_ctx)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (p_ctx->hash_array)
|
||
{
|
||
free(p_ctx->hash_array);
|
||
p_ctx->hash_array = NULL;
|
||
}
|
||
|
||
if (p_ctx->link_array)
|
||
{
|
||
free(p_ctx->link_array);
|
||
p_ctx->link_array = NULL;
|
||
}
|
||
|
||
if (p_ctx->hash_semMutex)
|
||
{
|
||
sys_os_destroy_sig_mutex(p_ctx->hash_semMutex);
|
||
p_ctx->hash_semMutex = NULL;
|
||
}
|
||
|
||
if (p_ctx->link_semMutex)
|
||
{
|
||
sys_os_destroy_sig_mutex(p_ctx->link_semMutex);
|
||
p_ctx->link_semMutex = NULL;
|
||
}
|
||
|
||
free(p_ctx);
|
||
}
|
||
|
||
HT_API uint32 ihash_link_pop(IHASHCTX * p_ctx)
|
||
{
|
||
sys_os_mutex_enter(p_ctx->link_semMutex);
|
||
|
||
uint32 ret_index = p_ctx->link_index;
|
||
p_ctx->link_index = p_ctx->link_array[ret_index].next_index;
|
||
|
||
p_ctx->link_array[ret_index].bFreeList = 0;
|
||
|
||
sys_os_mutex_leave(p_ctx->link_semMutex);
|
||
|
||
return ret_index;
|
||
}
|
||
|
||
HT_API void ihash_link_push(IHASHCTX * p_ctx, uint32 push_index)
|
||
{
|
||
if (push_index == 0)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, push_index == 0!!!\r\n", __FUNCTION__);
|
||
return;
|
||
}
|
||
|
||
if (push_index >= p_ctx->link_num)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, push_index[%u] >= MAX_NUM[%u]!!!\r\n", __FUNCTION__, push_index, p_ctx->link_num);
|
||
return;
|
||
}
|
||
|
||
if (p_ctx->link_array[push_index].bFreeList == 1)
|
||
{
|
||
log_print(HT_LOG_ERR, "%s, push_index[%u] bFreeList == 1!!!\r\n", __FUNCTION__, push_index);
|
||
return;
|
||
}
|
||
|
||
sys_os_mutex_enter(p_ctx->link_semMutex);
|
||
|
||
memset(&p_ctx->link_array[push_index],0,sizeof(IHASHNODE));
|
||
p_ctx->link_array[push_index].bFreeList = 1;
|
||
|
||
p_ctx->link_array[push_index].next_index = p_ctx->link_index;
|
||
p_ctx->link_index = push_index;
|
||
|
||
sys_os_mutex_leave(p_ctx->link_semMutex);
|
||
}
|
||
|
||
HT_API uint32 ihash_index(IHASHCTX * p_ctx, const char * key_str)
|
||
{
|
||
int i, len = strlen(key_str);
|
||
|
||
uint32 nr = 1, nr2 = 4;
|
||
uint8 ctmp;
|
||
|
||
for (i=0; i<len; i++)
|
||
{
|
||
ctmp = key_str[i];
|
||
nr^= (((nr & 63)+nr2)*((uint32)ctmp))+ (nr << 8);
|
||
nr2+=3;
|
||
}
|
||
|
||
return(nr & (p_ctx->hash_num -1));
|
||
}
|
||
|
||
HT_API BOOL ihash_add(IHASHCTX * p_ctx, const char * key_str, uint64 index, int type)
|
||
{
|
||
if (p_ctx == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
uint32 hash_key = ihash_index(p_ctx,key_str);
|
||
|
||
sys_os_mutex_enter(p_ctx->hash_semMutex);
|
||
|
||
if (p_ctx->hash_array[hash_key].bNodeValidate == 0)
|
||
{
|
||
strncpy(p_ctx->hash_array[hash_key].key_str, key_str, IHASH_KEY_MAX_LEN);
|
||
p_ctx->hash_array[hash_key].index = index;
|
||
p_ctx->hash_array[hash_key].next_index = 0;
|
||
p_ctx->hash_array[hash_key].bLinkValidate = 0;
|
||
p_ctx->hash_array[hash_key].bNodeValidate = 1;
|
||
}
|
||
else
|
||
{
|
||
IHASHNODE * p_node = &p_ctx->hash_array[hash_key];
|
||
|
||
if (type == 0)
|
||
{
|
||
while ((p_node->bLinkValidate == 1) && (strcmp(key_str,p_node->key_str) != 0))
|
||
{
|
||
p_node = &p_ctx->link_array[p_node->next_index];
|
||
if ((p_node - p_ctx->link_array) > (int)p_ctx->link_num)
|
||
{
|
||
sys_os_mutex_leave(p_ctx->hash_semMutex);
|
||
log_print(HT_LOG_ERR, "%s, link node address = 0x%x\r\n", __FUNCTION__, p_node);
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
if (strcmp(key_str,p_node->key_str) == 0)
|
||
{
|
||
if (p_node->index == index)
|
||
{
|
||
// 完全相同的重复添加
|
||
}
|
||
else
|
||
{
|
||
p_node->index = index;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
uint32 link_index = ihash_link_pop(p_ctx);
|
||
if (link_index == 0)
|
||
{
|
||
sys_os_mutex_leave(p_ctx->hash_semMutex);
|
||
log_print(HT_LOG_ERR, "%s, no free node!!!\r\n", __FUNCTION__);
|
||
return FALSE;
|
||
}
|
||
|
||
strncpy(p_ctx->link_array[link_index].key_str, key_str, IHASH_KEY_MAX_LEN);
|
||
p_ctx->link_array[link_index].index = index;
|
||
p_ctx->link_array[link_index].next_index = 0;
|
||
p_ctx->link_array[link_index].bLinkValidate = 0;
|
||
p_ctx->link_array[link_index].bNodeValidate = 1;
|
||
|
||
p_node->next_index = link_index;
|
||
p_node->bLinkValidate = 1;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
while ((p_node->bLinkValidate == 1) && ((strcmp(key_str,p_node->key_str) != 0) || p_node->index != index))
|
||
{
|
||
p_node = &p_ctx->link_array[p_node->next_index];
|
||
if ((p_node - p_ctx->link_array) > (int)p_ctx->link_num)
|
||
{
|
||
sys_os_mutex_leave(p_ctx->hash_semMutex);
|
||
log_print(HT_LOG_ERR, "%s, link node address = 0x%x\r\n", __FUNCTION__, p_node);
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
if ((strcmp(key_str,p_node->key_str) == 0) && p_node->index == index)
|
||
{
|
||
// 完全相同的重复添加
|
||
}
|
||
else
|
||
{
|
||
uint32 link_index = ihash_link_pop(p_ctx);
|
||
if (link_index == 0)
|
||
{
|
||
sys_os_mutex_leave(p_ctx->hash_semMutex);
|
||
log_print(HT_LOG_ERR, "%s, no free node!!!\r\n", __FUNCTION__);
|
||
return FALSE;
|
||
}
|
||
|
||
strncpy(p_ctx->link_array[link_index].key_str, key_str, IHASH_KEY_MAX_LEN);
|
||
p_ctx->link_array[link_index].index = index;
|
||
p_ctx->link_array[link_index].next_index = 0;
|
||
p_ctx->link_array[link_index].bLinkValidate = 0;
|
||
p_ctx->link_array[link_index].bNodeValidate = 1;
|
||
|
||
p_node->next_index = link_index;
|
||
p_node->bLinkValidate = 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
sys_os_mutex_leave(p_ctx->hash_semMutex);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
HT_API BOOL ihash_del(IHASHCTX * p_ctx, const char * key_str, uint64 index)
|
||
{
|
||
if (p_ctx == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
uint32 hash_key = ihash_index(p_ctx,key_str);
|
||
|
||
sys_os_mutex_enter(p_ctx->hash_semMutex);
|
||
|
||
if (p_ctx->hash_array[hash_key].bNodeValidate == 0)
|
||
{
|
||
sys_os_mutex_leave(p_ctx->hash_semMutex);
|
||
return FALSE;
|
||
}
|
||
|
||
IHASHNODE * p_node = &p_ctx->hash_array[hash_key];
|
||
|
||
if ((strcmp(key_str,p_node->key_str) == 0) && (p_node->index == index))
|
||
{
|
||
p_ctx->hash_array[hash_key].bNodeValidate = 0;
|
||
|
||
if (p_ctx->hash_array[hash_key].bLinkValidate == 1)
|
||
{
|
||
uint32 del_link_index = p_ctx->hash_array[hash_key].next_index;
|
||
IHASHNODE * p_del_node = &p_ctx->link_array[del_link_index];
|
||
|
||
memcpy(p_node,p_del_node,sizeof(IHASHNODE));
|
||
|
||
ihash_link_push(p_ctx,del_link_index);
|
||
}
|
||
|
||
sys_os_mutex_leave(p_ctx->hash_semMutex);
|
||
return TRUE;
|
||
}
|
||
else
|
||
{
|
||
IHASHNODE * p_node_prev = p_node;
|
||
|
||
while (p_node_prev->bLinkValidate == 1)
|
||
{
|
||
p_node = &p_ctx->link_array[p_node_prev->next_index];
|
||
|
||
if ((p_node - p_ctx->link_array) > (int)p_ctx->link_num)
|
||
{
|
||
sys_os_mutex_leave(p_ctx->hash_semMutex);
|
||
log_print(HT_LOG_ERR, "%s, link node address = 0x%x\r\n", __FUNCTION__, p_node);
|
||
return FALSE;
|
||
}
|
||
|
||
if ((strcmp(key_str,p_node->key_str) == 0) && (p_node->index == index))
|
||
{
|
||
p_node->bNodeValidate = 0;
|
||
|
||
p_node_prev->next_index = p_node->next_index;
|
||
p_node_prev->bLinkValidate = p_node->bLinkValidate;
|
||
|
||
uint32 del_link_index = p_node - p_ctx->link_array;
|
||
ihash_link_push(p_ctx,del_link_index);
|
||
|
||
break;
|
||
}
|
||
|
||
p_node_prev = p_node;
|
||
}
|
||
}
|
||
|
||
sys_os_mutex_leave(p_ctx->hash_semMutex);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
HT_API uint64 ihash_find_index_from_keystr(IHASHCTX * p_ctx, const char * key_str)
|
||
{
|
||
if (p_ctx == NULL)
|
||
{
|
||
return (uint64)-1;
|
||
}
|
||
|
||
uint32 hash_key = ihash_index(p_ctx,key_str);
|
||
IHASHNODE * p_node = &p_ctx->hash_array[hash_key];
|
||
|
||
sys_os_mutex_enter(p_ctx->hash_semMutex);
|
||
|
||
while (p_node->bNodeValidate == 1)
|
||
{
|
||
if (strcmp(key_str,p_node->key_str) == 0)
|
||
{
|
||
sys_os_mutex_leave(p_ctx->hash_semMutex);
|
||
return p_node->index;
|
||
}
|
||
|
||
if (p_node->bLinkValidate == 1)
|
||
{
|
||
if (p_node->next_index < p_ctx->link_num)
|
||
{
|
||
p_node = &p_ctx->link_array[p_node->next_index];
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
|
||
sys_os_mutex_leave(p_ctx->hash_semMutex);
|
||
|
||
return (uint64)-1;
|
||
}
|
||
|
||
HT_API void ihash_lock(IHASHCTX * p_ctx)
|
||
{
|
||
if (p_ctx != NULL)
|
||
{
|
||
sys_os_mutex_enter(p_ctx->hash_semMutex);
|
||
}
|
||
}
|
||
|
||
HT_API void ihash_unlock(IHASHCTX * p_ctx)
|
||
{
|
||
if (p_ctx != NULL)
|
||
{
|
||
sys_os_mutex_leave(p_ctx->hash_semMutex);
|
||
}
|
||
}
|
||
|
||
HT_API void * ihash_save_var(IHASHCTX * p_ctx)
|
||
{
|
||
if (p_ctx == NULL)
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
return p_ctx->p_node;
|
||
}
|
||
|
||
HT_API void ihash_restore_var(IHASHCTX * p_ctx, void * p_node)
|
||
{
|
||
if (p_ctx == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
p_ctx->p_node = (IHASHNODE *)p_node; // 此处应该检查指针是否在有效范围内并对齐到数组
|
||
}
|
||
|
||
|
||
|