* Copyright (c) 2022 Huawei Technologies Co.,Ltd.
*
* GR is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*
* gr_session.c
*
*
* IDENTIFICATION
* src/common/gr_session.c
*
* -------------------------------------------------------------------------
*/
#include "gr_session.h"
#include "cm_utils.h"
#include "gr_diskgroup.h"
#include "gr_malloc.h"
#include "gr_file.h"
#include "cm_system.h"
#include "gr_thv.h"
#include "gr_filesystem.h"
#include "gr_resource_mgr.h"
#include "gr_error_handler.h"
#ifdef __cplusplus
extern "C" {
#endif
status_t gr_session_fd_add(gr_session_t *session, int64 fd, uint64 ftid, const char *file_name)
{
gr_session_fd_entry_t *ent = GR_MALLOC_STRUCT(gr_session_fd_entry_t);
if (ent == NULL) {
GR_ERROR_RETURN(GR_ERR_CATEGORY_RESOURCE, ERR_GR_NO_SPACE, CM_ERROR,
"Failed to allocate memory for session FD entry");
}
ent->fd = fd;
ent->ftid = ftid;
ent->next = NULL;
if (file_name != NULL) {
errno_t err = strncpy_s(ent->file_name, sizeof(ent->file_name), file_name, sizeof(ent->file_name) - 1);
if (SECUREC_UNLIKELY(err != EOK)) {
cm_free(ent);
GR_ERROR_RETURN(GR_ERR_CATEGORY_SYSTEM, ERR_SYSTEM_CALL, CM_ERROR,
"Failed to copy file name, errno: %d", err);
}
} else {
ent->file_name[0] = '\0';
}
cm_spin_lock(&session->fd_lock, NULL);
ent->next = session->fd_list_head;
session->fd_list_head = ent;
session->fd_count++;
cm_spin_unlock(&session->fd_lock);
return CM_SUCCESS;
}
bool32 gr_session_fd_remove(gr_session_t *session, int64 fd)
{
cm_spin_lock(&session->fd_lock, NULL);
gr_session_fd_entry_t *prev = NULL;
gr_session_fd_entry_t *curr = session->fd_list_head;
while (curr != NULL) {
if (curr->fd == fd) {
if (prev == NULL) {
session->fd_list_head = curr->next;
} else {
prev->next = curr->next;
}
session->fd_count--;
curr->next = session->fd_free_list;
session->fd_free_list = curr;
session->fd_free_count++;
cm_spin_unlock(&session->fd_lock);
return CM_TRUE;
}
prev = curr;
curr = curr->next;
}
cm_spin_unlock(&session->fd_lock);
return CM_FALSE;
}
void gr_session_fd_close_all(gr_session_t *session)
{
if (session == NULL) {
GR_ERROR_HANDLE(GR_ERR_CATEGORY_SESSION, ERR_GR_SESSION_INVALID_ID,
"gr_session_fd_close_all: session is NULL");
return;
}
LOG_DEBUG_INF("[GR_SESSION]session %u starting to close all file descriptors", session->id);
cm_spin_lock(&session->fd_lock, NULL);
gr_session_fd_entry_t *curr = session->fd_list_head;
uint32_t fd_count = session->fd_count;
session->fd_list_head = NULL;
session->fd_count = 0;
cm_spin_unlock(&session->fd_lock);
LOG_DEBUG_INF("[GR_SESSION]session %u found %u file descriptors to close", session->id, fd_count);
uint32_t closed_count = 0;
while (curr != NULL) {
gr_session_fd_entry_t *next = curr->next;
LOG_DEBUG_INF("[GR_SESSION]session %u closing fd %lld (entry %u/%u)",
session->id, curr->fd, closed_count + 1, fd_count);
status_t close_status = gr_filesystem_close(curr->fd, CM_FALSE);
if (close_status != CM_SUCCESS) {
LOG_RUN_WAR("[GR_SESSION]session %u failed to close fd %lld, status: %d",
session->id, curr->fd, close_status);
} else {
closed_count++;
}
cm_spin_lock(&session->fd_lock, NULL);
curr->next = session->fd_free_list;
session->fd_free_list = curr;
session->fd_free_count++;
cm_spin_unlock(&session->fd_lock);
curr = next;
}
LOG_RUN_INF("[GR_SESSION]session %u completed closing file descriptors: %u/%u closed successfully",
session->id, closed_count, fd_count);
}
gr_session_ctrl_t g_gr_session_ctrl = {0};
status_t gr_extend_session(uint32_t extend_num)
{
uint32_t old_alloc_sessions = g_gr_session_ctrl.alloc_sessions;
uint32_t new_alloc_sessions = g_gr_session_ctrl.alloc_sessions + extend_num;
if (new_alloc_sessions > g_gr_session_ctrl.total) {
GR_ERROR_RETURN(GR_ERR_CATEGORY_SESSION, ERR_GR_SESSION_EXTEND, CM_ERROR,
"Failed to extend session, expect new alloc sessions %u, but max is %u",
new_alloc_sessions, g_gr_session_ctrl.total);
}
for (uint32_t i = old_alloc_sessions; i < new_alloc_sessions; i++) {
g_gr_session_ctrl.sessions[i] = (gr_session_t *)cm_malloc(sizeof(gr_session_t));
if (g_gr_session_ctrl.sessions[i] == NULL) {
GR_ERROR_RETURN(GR_ERR_CATEGORY_RESOURCE, ERR_GR_SESSION_EXTEND, CM_ERROR,
"Failed to alloc memory for session %u", i);
for (uint32_t j = old_alloc_sessions; j < i; j++) {
CM_FREE_PTR(g_gr_session_ctrl.sessions[j]);
g_gr_session_ctrl.sessions[j] = NULL;
}
g_gr_session_ctrl.alloc_sessions = old_alloc_sessions;
}
errno_t err = memset_s(g_gr_session_ctrl.sessions[i], sizeof(gr_session_t), 0, sizeof(gr_session_t));
if (err != EOK) {
GR_ERROR_RETURN(GR_ERR_CATEGORY_SYSTEM, ERR_GR_SESSION_EXTEND, CM_ERROR,
"Failed to initialize session %u memory, errno: %d", i, err);
CM_FREE_PTR(g_gr_session_ctrl.sessions[i]);
g_gr_session_ctrl.sessions[i] = NULL;
for (uint32_t j = old_alloc_sessions; j < i; j++) {
CM_FREE_PTR(g_gr_session_ctrl.sessions[j]);
g_gr_session_ctrl.sessions[j] = NULL;
}
g_gr_session_ctrl.alloc_sessions = old_alloc_sessions;
}
g_gr_session_ctrl.sessions[i]->id = i;
g_gr_session_ctrl.sessions[i]->is_used = CM_FALSE;
g_gr_session_ctrl.sessions[i]->is_closed = CM_TRUE;
g_gr_session_ctrl.sessions[i]->put_log = CM_FALSE;
g_gr_session_ctrl.sessions[i]->objectid = i;
g_gr_session_ctrl.sessions[i]->is_holding_hotpatch_latch = CM_FALSE;
g_gr_session_ctrl.alloc_sessions++;
LOG_DEBUG_INF("Allocated session %u successfully.", i);
}
LOG_RUN_INF("Succeed to extend sessions to %u.", g_gr_session_ctrl.alloc_sessions);
return CM_SUCCESS;
}
status_t gr_init_session_pool(uint32_t max_session_num)
{
uint32_t gr_session_size = (uint32_t)(max_session_num * sizeof(gr_session_t *));
g_gr_session_ctrl.sessions = cm_malloc(gr_session_size);
if (g_gr_session_ctrl.sessions == NULL) {
return ERR_GR_SESSION_CREATE;
}
errno_t errcode = memset_s(g_gr_session_ctrl.sessions, gr_session_size, 0, gr_session_size);
securec_check_ret(errcode);
g_gr_session_ctrl.alloc_sessions = 0;
uint32_t extend_num = max_session_num >= GR_SESSION_NUM_PER_GROUP ? GR_SESSION_NUM_PER_GROUP : max_session_num;
g_gr_session_ctrl.total = max_session_num;
status_t status = gr_extend_session(extend_num);
if (status != CM_SUCCESS) {
return status;
}
g_gr_session_ctrl.is_inited = CM_TRUE;
return CM_SUCCESS;
}
gr_session_ctrl_t *gr_get_session_ctrl(void)
{
return &g_gr_session_ctrl;
}
uint32_t gr_get_uwression_startid(void)
{
gr_config_t *inst_cfg = gr_get_inst_cfg();
uint32_t start_sid = (uint32_t)GR_BACKGROUND_TASK_NUM;
if (inst_cfg->params.nodes_list.inst_cnt > 1) {
start_sid = start_sid + inst_cfg->params.channel_num + inst_cfg->params.work_thread_cnt;
}
return start_sid;
}
uint32_t gr_get_max_total_session_cnt(void)
{
gr_config_t *inst_cfg = gr_get_inst_cfg();
return gr_get_uwression_startid() + inst_cfg->params.cfg_session_num;
}
uint32_t gr_get_recover_task_idx(void)
{
return (gr_get_uwression_startid() - (uint32_t)GR_BACKGROUND_TASK_NUM);
}
uint32_t gr_get_delay_clean_task_idx(void)
{
return (gr_get_uwression_startid() - (uint32_t)GR_BACKGROUND_TASK_NUM) + GR_DELAY_CLEAN_BACKGROUND_TASK;
}
uint32_t gr_get_alarm_check_task_idx(void)
{
return (gr_get_uwression_startid() - (uint32_t)GR_BACKGROUND_TASK_NUM) + GR_ALARM_CHECK_TASK;
}
static status_t gr_init_session(gr_session_t *session, const cs_pipe_t *pipe)
{
gr_latch_stack_t *latch_stack = &session->latch_stack;
errno_t errcode = memset_s(latch_stack, sizeof(gr_latch_stack_t), 0, sizeof(gr_latch_stack_t));
securec_check_ret(errcode);
session->is_direct = CM_TRUE;
session->connected = CM_FALSE;
if (pipe != NULL) {
session->pipe = *pipe;
session->connected = CM_TRUE;
}
session->is_closed = CM_FALSE;
session->proto_type = PROTO_TYPE_UNKNOWN;
session->status = GR_SESSION_STATUS_IDLE;
session->client_version = GR_PROTO_VERSION;
session->proto_version = GR_PROTO_VERSION;
session->is_holding_hotpatch_latch = CM_FALSE;
GR_RETURN_IF_ERROR(init_session_hash_mgr(session));
GS_INIT_SPIN_LOCK(session->fd_lock);
session->fd_list_head = NULL;
session->fd_free_list = NULL;
session->fd_count = 0;
session->fd_free_count = 0;
GS_INIT_SPIN_LOCK(session->dir_lock);
session->dir_list_head = NULL;
session->dir_count = 0;
return CM_SUCCESS;
}
gr_session_t *gr_get_reserv_session(uint32_t idx)
{
gr_session_ctrl_t *session_ctrl = gr_get_session_ctrl();
gr_session_t *session = session_ctrl->sessions[idx];
return session;
}
status_t gr_create_session(const cs_pipe_t *pipe, gr_session_t **session)
{
uint32_t i, id;
*session = NULL;
id = GR_INVALID_ID32;
cm_spin_lock(&g_gr_session_ctrl.lock, NULL);
uint32_t start_sid = gr_get_uwression_startid();
uint32_t end_sid = gr_get_max_total_session_cnt();
status_t status;
for (i = start_sid; i < end_sid; i++) {
if (i >= g_gr_session_ctrl.alloc_sessions) {
uint32_t extend_num =
g_gr_session_ctrl.total - g_gr_session_ctrl.alloc_sessions >= GR_SESSION_NUM_PER_GROUP ?
GR_SESSION_NUM_PER_GROUP :
g_gr_session_ctrl.total - g_gr_session_ctrl.alloc_sessions;
status = gr_extend_session(extend_num);
if (status != CM_SUCCESS) {
cm_spin_unlock(&g_gr_session_ctrl.lock);
return status;
}
}
if (g_gr_session_ctrl.sessions[i]->is_used == CM_FALSE) {
id = i;
break;
}
}
if (id == GR_INVALID_ID32) {
LOG_DEBUG_INF("No sessions are available.");
cm_spin_unlock(&g_gr_session_ctrl.lock);
return ERR_GR_SESSION_CREATE;
}
*session = g_gr_session_ctrl.sessions[i];
LOG_DEBUG_INF("Session[%u] is available.", id);
cm_spin_lock(&(*session)->lock, NULL);
g_gr_session_ctrl.used_count++;
(*session)->is_used = CM_TRUE;
cm_spin_unlock(&(*session)->lock);
cm_spin_unlock(&g_gr_session_ctrl.lock);
GR_RETURN_IF_ERROR(gr_init_session(*session, pipe));
return CM_SUCCESS;
}
void gr_destroy_session_inner(gr_session_t *session)
{
if (session->connected == CM_TRUE) {
cs_disconnect(&session->pipe);
session->connected = CM_FALSE;
}
g_gr_session_ctrl.used_count--;
session->is_closed = CM_TRUE;
session->is_used = CM_FALSE;
errno_t ret = memset_sp(&session->cli_info, sizeof(session->cli_info), 0, sizeof(session->cli_info));
securec_check_panic(ret);
session->client_version = GR_PROTO_VERSION;
session->proto_version = GR_PROTO_VERSION;
session->put_log = CM_FALSE;
session->is_holding_hotpatch_latch = CM_FALSE;
CM_FREE_PTR(session->hash_mgr.hash_items);
cm_spin_lock(&session->fd_lock, NULL);
gr_session_fd_entry_t *curr = session->fd_list_head;
session->fd_list_head = NULL;
session->fd_count = 0;
gr_session_fd_entry_t *free_curr = session->fd_free_list;
session->fd_free_list = NULL;
session->fd_free_count = 0;
cm_spin_unlock(&session->fd_lock);
while (curr != NULL) {
gr_session_fd_entry_t *next = curr->next;
CM_FREE_PTR(curr);
curr = next;
}
while (free_curr != NULL) {
gr_session_fd_entry_t *next = free_curr->next;
CM_FREE_PTR(free_curr);
free_curr = next;
}
cm_spin_lock(&session->dir_lock, NULL);
gr_session_dir_entry_t *dir_curr = session->dir_list_head;
session->dir_list_head = NULL;
session->dir_count = 0;
cm_spin_unlock(&session->dir_lock);
while (dir_curr != NULL) {
gr_session_dir_entry_t *next = dir_curr->next;
CM_FREE_PTR(dir_curr);
dir_curr = next;
}
}
status_t gr_session_dir_add(gr_session_t *session, uint64 handle)
{
gr_session_dir_entry_t *ent = GR_MALLOC_STRUCT(gr_session_dir_entry_t);
if (ent == NULL) {
GR_ERROR_RETURN(GR_ERR_CATEGORY_RESOURCE, ERR_GR_NO_SPACE, CM_ERROR,
"Failed to allocate memory for session DIR entry");
}
ent->handle = handle;
ent->next = NULL;
cm_spin_lock(&session->dir_lock, NULL);
ent->next = session->dir_list_head;
session->dir_list_head = ent;
session->dir_count++;
cm_spin_unlock(&session->dir_lock);
return CM_SUCCESS;
}
bool32 gr_session_dir_remove(gr_session_t *session, uint64 handle)
{
cm_spin_lock(&session->dir_lock, NULL);
gr_session_dir_entry_t *prev = NULL;
gr_session_dir_entry_t *curr = session->dir_list_head;
while (curr != NULL) {
if (curr->handle == handle) {
if (prev == NULL) {
session->dir_list_head = curr->next;
} else {
prev->next = curr->next;
}
session->dir_count--;
cm_spin_unlock(&session->dir_lock);
CM_FREE_PTR(curr);
return CM_TRUE;
}
prev = curr;
curr = curr->next;
}
cm_spin_unlock(&session->dir_lock);
return CM_FALSE;
}
void gr_session_dir_close_all(gr_session_t *session)
{
if (session == NULL) {
GR_ERROR_HANDLE(GR_ERR_CATEGORY_SESSION, ERR_GR_SESSION_INVALID_ID,
"gr_session_dir_close_all: session is NULL");
return;
}
LOG_DEBUG_INF("[GR_SESSION]session %u starting to close all directory handles", session->id);
cm_spin_lock(&session->dir_lock, NULL);
gr_session_dir_entry_t *curr = session->dir_list_head;
uint32_t dir_count = session->dir_count;
session->dir_list_head = NULL;
session->dir_count = 0;
cm_spin_unlock(&session->dir_lock);
LOG_DEBUG_INF("[GR_SESSION]session %u found %u directory handles to close", session->id, dir_count);
uint32_t closed_count = 0;
while (curr != NULL) {
gr_session_dir_entry_t *next = curr->next;
LOG_DEBUG_INF("[GR_SESSION]session %u closing dir handle %llu (entry %u/%u)",
session->id, (unsigned long long)curr->handle, closed_count + 1, dir_count);
status_t close_status = gr_filesystem_closedir(curr->handle);
if (close_status != CM_SUCCESS) {
LOG_RUN_WAR("[GR_SESSION]session %u failed to close dir handle %llu, status: %d",
session->id, (unsigned long long)curr->handle, close_status);
} else {
closed_count++;
}
CM_FREE_PTR(curr);
curr = next;
}
LOG_RUN_INF("[GR_SESSION]session %u completed closing directory handles: %u/%u closed successfully",
session->id, closed_count, dir_count);
}
void gr_destroy_session(gr_session_t *session)
{
cm_spin_lock(&g_gr_session_ctrl.lock, NULL);
cm_spin_lock(&session->shm_lock, NULL);
LOG_DEBUG_INF("Succeed to lock session %u shm lock", session->id);
gr_destroy_session_inner(session);
cm_spin_unlock(&session->shm_lock);
LOG_DEBUG_INF("Succeed to unlock session %u shm lock", session->id);
cm_spin_unlock(&g_gr_session_ctrl.lock);
}
gr_session_t *gr_get_session(uint32_t sid)
{
if (sid >= g_gr_session_ctrl.alloc_sessions || sid >= g_gr_session_ctrl.total) {
return NULL;
}
return g_gr_session_ctrl.sessions[sid];
}
bool32 gr_unlock_shm_meta_s_with_stack(gr_session_t *session, gr_shared_latch_t *shared_latch, bool32 is_try_lock)
{
CM_ASSERT(session != NULL);
CM_ASSERT(shared_latch->latch.stat != LATCH_STATUS_IDLE);
session->latch_stack.stack_top_bak = session->latch_stack.stack_top;
session->latch_stack.op = LATCH_SHARED_OP_UNLATCH;
spin_statis_t *stat_spin = NULL;
uint32_t sid = GR_SESSIONID_IN_LOCK(session->id);
if (!is_try_lock) {
cm_spin_lock_by_sid(sid, &shared_latch->latch.lock, stat_spin);
} else {
bool32 is_locked = cm_spin_try_lock(&shared_latch->latch.lock);
if (!is_locked) {
return CM_FALSE;
}
}
gr_set_latch_extent(&shared_latch->latch_extent, shared_latch->latch.stat, shared_latch->latch.shared_count);
session->latch_stack.op = LATCH_SHARED_OP_UNLATCH_BEG;
CM_ASSERT(shared_latch->latch.shared_count > 0);
shared_latch->latch.shared_count--;
if (shared_latch->latch.shared_count == 0) {
if (shared_latch->latch.stat == LATCH_STATUS_S) {
shared_latch->latch.stat = LATCH_STATUS_IDLE;
}
shared_latch->latch.sid = 0;
}
shared_latch->latch_extent.shared_sid_count -= sid;
cm_spin_unlock(&shared_latch->latch.lock);
CM_ASSERT(session->latch_stack.stack_top);
session->latch_stack.latch_offset_stack[session->latch_stack.stack_top - 1].type = GR_LATCH_OFFSET_INVALID;
session->latch_stack.stack_top--;
session->latch_stack.op = LATCH_SHARED_OP_UNLATCH_END;
return CM_TRUE;
}
static bool32 gr_need_clean_session_latch(gr_session_t *session, uint64 cli_pid, int64 start_time)
{
if (cli_pid == 0 || !session->is_used || !session->connected || cm_sys_process_alived(cli_pid, start_time)) {
return CM_FALSE;
}
return CM_TRUE;
}
void gr_clean_session_latch(gr_session_t *session, bool32 is_daemon)
{
if (!session->is_direct) {
LOG_DEBUG_INF("Clean sid:%u is not direct.", GR_SESSIONID_IN_LOCK(session->id));
return;
}
uint64 cli_pid = session->cli_info.cli_pid;
int64 start_time = session->cli_info.start_time;
if (is_daemon && !gr_need_clean_session_latch(session, cli_pid, start_time)) {
LOG_RUN_INF("[CLEAN_LATCH]session id %u, pid %llu, start_time %lld, process name:%s need check next time.",
session->id, cli_pid, start_time, session->cli_info.process_name);
return;
}
LOG_RUN_INF("[CLEAN_LATCH]session id %u, pid %llu, start_time %lld, process name:%s in lock.", session->id, cli_pid,
start_time, session->cli_info.process_name);
LOG_DEBUG_INF("Clean sid:%u latch_stack op:%u, stack_top:%hu completed (simplified).", GR_SESSIONID_IN_LOCK(session->id),
session->latch_stack.op, session->latch_stack.stack_top);
session->latch_stack.op = LATCH_SHARED_OP_NONE;
session->latch_stack.stack_top = GR_MAX_LATCH_STACK_BOTTON;
}
void gr_server_session_lock(gr_session_t *session)
{
cm_spin_lock(&session->lock, NULL);
while (!cm_spin_timed_lock(&session->shm_lock, GR_SERVER_SESS_TIMEOUT)) {
bool32 alived = cm_sys_process_alived(session->cli_info.cli_pid, session->cli_info.start_time);
if (!alived) {
LOG_DEBUG_INF("Process:%s is not alive, pid:%llu, start_time:%lld.", session->cli_info.process_name,
session->cli_info.cli_pid, session->cli_info.start_time);
cm_spin_unlock(&session->shm_lock);
LOG_DEBUG_INF("Succeed to unlock session %u shm lock", session->id);
continue;
}
LOG_DEBUG_INF("Process:%s is alive, pid:%llu, start_time:%lld.", session->cli_info.process_name,
session->cli_info.cli_pid, session->cli_info.start_time);
cm_sleep(CM_SLEEP_500_FIXED);
}
LOG_DEBUG_INF("Succeed to lock session %u shm lock", session->id);
}
void gr_server_session_unlock(gr_session_t *session)
{
cm_spin_unlock(&session->shm_lock);
LOG_DEBUG_INF("Succeed to unlock session %u shm lock", session->id);
cm_spin_unlock(&session->lock);
LOG_DEBUG_INF("Succeed to unlock session %u lock", session->id);
}
void cm_spin_lock_init(spinlock_t *lock)
{
CM_ASSERT(lock != NULL);
*lock = 0;
}
status_t init_session_hash_mgr(gr_session_t *session)
{
session_hash_mgr_t *mgr = &session->hash_mgr;
mgr->hash_count = 0;
mgr->hash_capacity = MAX_FILE_HASH_COUNT;
mgr->hash_items = (file_hash_info_t *)malloc(
sizeof(file_hash_info_t) * mgr->hash_capacity);
if (mgr->hash_items == NULL) {
return CM_ERROR;
}
cm_spin_lock_init(&mgr->lock);
return CM_SUCCESS;
}
status_t update_file_hash(gr_session_t *session, uint32_t file_handle, const uint8_t *new_hash)
{
session_hash_mgr_t *mgr = &session->hash_mgr;
errno_t err = 0;
if (new_hash == NULL) {
LOG_RUN_ERR("[hash]: invalid param, failed to update file hash.");
}
cm_spin_lock(&mgr->lock, NULL);
for (uint32_t i = 0; i < mgr->hash_count; i++) {
if (SECUREC_LIKELY(mgr->hash_items[i].file_handle == file_handle)) {
err = memcpy_s(mgr->hash_items[i].prev_hash, SHA256_DIGEST_LENGTH,
mgr->hash_items[i].curr_hash, SHA256_DIGEST_LENGTH);
if (err != EOK) {
LOG_RUN_ERR("[hash]: failed to update pre_hash, error code is %d.\n", err);
return CM_ERROR;
}
err = memcpy_s(mgr->hash_items[i].curr_hash, SHA256_DIGEST_LENGTH,
new_hash, SHA256_DIGEST_LENGTH);
if (err != EOK) {
LOG_RUN_ERR("[hash]: failed to update curr_hash, error code is %d.\n", err);
return CM_ERROR;
}
mgr->hash_items[i].last_update_time = cm_current_time();
cm_spin_unlock(&mgr->lock);
return CM_SUCCESS;
}
}
if (mgr->hash_count >= mgr->hash_capacity) {
cm_spin_unlock(&mgr->lock);
return CM_ERROR;
}
file_hash_info_t *new_item = &mgr->hash_items[mgr->hash_count];
new_item->file_handle = file_handle;
err = memcpy_s(new_item->curr_hash, SHA256_DIGEST_LENGTH,
new_hash, SHA256_DIGEST_LENGTH);
if (err != EOK) {
LOG_RUN_ERR("[hash]: failed to insert hash information, error code is %d.\n", err);
return CM_ERROR;
}
err = memset_s(new_item->prev_hash, SHA256_DIGEST_LENGTH, 0, SHA256_DIGEST_LENGTH);
if (err != EOK) {
CM_THROW_ERROR(ERR_SYSTEM_CALL, err);
return CM_ERROR;
}
new_item->last_update_time = cm_current_time();
mgr->hash_count++;
cm_spin_unlock(&mgr->lock);
return CM_SUCCESS;
}
status_t get_file_hash(gr_session_t *session, uint32_t file_handle, uint8_t *curr_hash, uint8_t *prev_hash)
{
session_hash_mgr_t *mgr = &session->hash_mgr;
status_t status = CM_ERROR;
errno_t err = 0;
if (curr_hash == NULL || prev_hash == NULL) {
LOG_RUN_ERR("[hash]: invalid param, failed to get hash");
return CM_ERROR;
}
cm_spin_lock(&mgr->lock, NULL);
for (uint32_t i = 0; i < mgr->hash_count; i++) {
if (mgr->hash_items[i].file_handle == file_handle) {
err = memcpy_s(curr_hash, SHA256_DIGEST_LENGTH,
mgr->hash_items[i].curr_hash, SHA256_DIGEST_LENGTH);
if (err != EOK) {
LOG_RUN_ERR("[hash]: failed to get curr_hash, error code is %d.\n", err);
return CM_ERROR;
}
err = memcpy_s(prev_hash, SHA256_DIGEST_LENGTH,
mgr->hash_items[i].prev_hash, SHA256_DIGEST_LENGTH);
if (err != EOK) {
LOG_RUN_ERR("[hash]: failed to get prev_hash, error code is %d.\n", err);
return CM_ERROR;
}
status = CM_SUCCESS;
break;
}
}
cm_spin_unlock(&mgr->lock);
return status;
}
status_t generate_random_sha256(unsigned char *hash)
{
if (hash == NULL) {
LOG_RUN_ERR("invalid param, hash is NULL");
return GR_ERROR;
}
if (RAND_bytes(hash, SHA256_DIGEST_LENGTH) != 1) {
LOG_RUN_ERR("failed to generate sha256");
return GR_ERROR;
}
return GR_SUCCESS;
}
#ifdef __cplusplus
}
#endif