Files
gb28181/GB28181Device/bm/ihash.cpp
2024-12-15 20:42:32 +08:00

435 lines
9.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/***************************************************************************************
*
* 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; // 此处应该检查指针是否在有效范围内并对齐到数组
}