* This file is part of the oGRAC project.
* Copyright (c) 2024 Huawei Technologies Co.,Ltd.
*
* oGRAC 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.
* -------------------------------------------------------------------------
*
* cm_dbs_file.c
*
*
* IDENTIFICATION
* src/common/cm_dbs_file.c
*
* -------------------------------------------------------------------------
*/
#include <stdint.h>
#include <fcntl.h>
#include <semaphore.h>
#include "cm_dbs_module.h"
#include "cm_dbs_file.h"
#include "cm_spinlock.h"
#include "cm_log.h"
#include "cm_file.h"
#include "cm_error.h"
#include "cm_dbs_map.h"
#include "cm_dbs_ctrl.h"
#include "cm_dbs_intf.h"
#include "cm_dbs_defs.h"
#include "cm_dbstor.h"
#include "cm_dbs_file.h"
#define DBSTOR_MAX_FILE_SIZE (1024ULL * 1024 * 1024 * 1024)
#define DBSTOR_MAX_RWBUF_SIZE (1 * 1024 * 1024)
#define DBSTOR_MAX_RETRY_COUNT 3
#define DBSTOR_MIN_DIR_DEPTH 2
#define DBSTOR_ULOG_ARCHIVE_END 21
status_t cm_check_file_path(const char *file_path)
{
uint32 len = strlen(file_path);
if (len == 0 || len >= MAX_DBS_FS_FILE_PATH_LEN) {
OG_LOG_RUN_ERR("[CM_DEVICE] invalid file path %s, len %u", file_path, len);
return OG_ERROR;
}
if (cm_check_exist_special_char(file_path, strlen(file_path))) {
OG_LOG_RUN_ERR("[CM_DEVICE] invalid file path %s", file_path);
return OG_ERROR;
}
if (file_path[0] != '/') {
OG_LOG_RUN_ERR("[CM_DEVICE] invalid file path %s", file_path);
return OG_ERROR;
}
return OG_SUCCESS;
}
void cm_remove_extra_delim(char *file_path, const char delim)
{
uint32 length = strlen(file_path);
uint32 i = 0, j = 0;
for (; i < length; i++) {
if (i == 0 || file_path[i] != delim) {
file_path[j++] = file_path[i];
} else if (file_path[i-1] != delim) {
file_path[j++] = file_path[i];
}
}
file_path[j] = '\0';
if (j > 0 && file_path[j - 1] == delim) {
file_path[j - 1] = '\0';
}
return;
}
static char* cm_find_fix_delim(char *file_path, const char delim, uint32 fix_num)
{
uint32 length = strlen(file_path);
uint32 cur_num = 0;
for (uint32 i = 0; i < length; i++) {
if (file_path[i] == delim) {
cur_num++;
}
if (cur_num == fix_num) {
return file_path + i;
}
}
return NULL;
}
static status_t cm_get_fs_name(const char *file_path, const char *delim, char *fs_name)
{
char *context = NULL;
char *token = NULL;
char file[MAX_DBS_FS_FILE_PATH_LEN] = { 0 };
MEMS_RETURN_IFERR(strcpy_sp(file, MAX_DBS_FS_FILE_PATH_LEN, file_path));
token = strtok_s(file, delim, &context);
if (token == NULL) {
OG_LOG_RUN_ERR("[CM_DEVICE] get fs name failed, file_path %s", file);
return OG_ERROR;
}
if (strlen(token) >= MAX_DBS_FS_NAME_LEN) {
OG_LOG_RUN_ERR("[CM_DEVICE] invalid fs name %s, len %lu", token, strlen(token));
return OG_ERROR;
}
MEMS_RETURN_IFERR(strcpy_s(fs_name, MAX_DBS_FS_NAME_LEN, token));
return OG_SUCCESS;
}
static status_t cm_get_file_name_and_dir(const char *file_path, uint32 path_depth,
const char *delim, char *file_name, char *file_dir)
{
char *context = NULL;
char *token = NULL;
uint32 cur_depth = 0;
char file[MAX_DBS_FS_FILE_PATH_LEN] = { 0 };
MEMS_RETURN_IFERR(strcpy_sp(file, MAX_DBS_FS_FILE_PATH_LEN, file_path));
token = strtok_s(file, delim, &context);
while (token != NULL) {
if (cur_depth >= path_depth) {
OG_LOG_RUN_INF("[CM_DEVICE] get file name failed, cur depth %u, path depth %u",
cur_depth, path_depth);
return OG_ERROR;
}
if (cur_depth == path_depth - 1) {
MEMS_RETURN_IFERR(strcpy_s(file_name, MAX_DBS_FILE_NAME_LEN, token));
break;
} else {
MEMS_RETURN_IFERR(strcat_s(file_dir, MAX_DBS_FS_FILE_PATH_LEN, "/"));
MEMS_RETURN_IFERR(strcat_s(file_dir, MAX_DBS_FS_FILE_PATH_LEN, token));
}
cur_depth++;
token = strtok_s(NULL, delim, &context);
}
return OG_SUCCESS;
}
static status_t cm_dbs_open_root(char *fs_name, int32 *root_handle)
{
cm_dbs_map_item_s root_item = { 0 };
int ret = dbs_global_handle()->dbs_file_open_root(fs_name, &root_item.obj_id);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] open fs root failed, ret %d, fs name %s", ret, fs_name);
return OG_ERROR;
}
if (cm_dbs_map_set(fs_name, &root_item, root_handle, DEV_TYPE_DBSTOR_FILE) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] map set item to handle failed");
return OG_ERROR;
}
return OG_SUCCESS;
}
static status_t cm_dbs_open_file_handle(object_id_t* phandle, char* file_name, uint32 file_type, object_id_t* handle)
{
if (phandle == NULL || file_name == NULL || handle == NULL) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file handle failed, invalid param.");
return OG_ERROR;
}
int ret = dbs_global_handle()->dbs_file_open(phandle, file_name, file_type, handle);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] open dbs file failed, ret %d, file_name(%s) ", ret, file_name);
return OG_ERROR;
}
return OG_SUCCESS;
}
status_t cm_dbs_open_file_by_depth(object_id_t *root_handle, const char *path, uint32 total_depth,
uint32 file_type, object_id_t *file_handle)
{
char *token = NULL;
char *context = NULL;
char file_path[MAX_DBS_FS_FILE_PATH_LEN] = { 0 };
MEMS_RETURN_IFERR(strcpy_sp(file_path, MAX_DBS_FS_FILE_PATH_LEN, path));
int cur_depth = 0;
object_id_t phandle = *root_handle;
object_id_t chandle = { 0 };
token = strtok_s(file_path, "/", &context);
while (token != NULL) {
if (cur_depth == total_depth - 1) {
if (cm_dbs_open_file_handle(&phandle, token, file_type, file_handle) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] create file or dir failed, dir %s, type %u, file path %s",
token, file_type, path);
return OG_ERROR;
}
break;
} else {
if (cm_dbs_open_file_handle(&phandle, token, DIR_TYPE, &chandle) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] create file failed, dir %s, file path %s", token, path);
return OG_ERROR;
}
phandle = chandle;
}
token = strtok_s(NULL, "/", &context);
cur_depth++;
}
return OG_SUCCESS;
}
static status_t cm_dbs_open_file_common(const char *name, uint32 file_type, int32 *handle)
{
if (*handle != OG_INVALID_HANDLE) {
return OG_SUCCESS;
}
char file_path[MAX_DBS_FS_FILE_PATH_LEN] = { 0 };
MEMS_RETURN_IFERR(strcpy_sp(file_path, MAX_DBS_FS_FILE_PATH_LEN, name));
cm_remove_extra_delim(file_path, '/');
if (cm_check_file_path(file_path) != OG_SUCCESS) {
return OG_ERROR;
}
int path_depth = 0;
if (cm_get_file_path_depth(file_path, "/", &path_depth) != OG_SUCCESS || path_depth < 1) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file path %s depth failed", file_path);
return OG_ERROR;
}
char fs_name[MAX_DBS_FS_NAME_LEN] = { 0 };
if (cm_get_fs_name(file_path, "/", fs_name) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] get fs name failed, file path %s", file_path);
return OG_ERROR;
}
if (path_depth == 1) {
return cm_dbs_open_root(fs_name, handle);
}
object_id_t root_obj_id = { 0 };
int ret = dbs_global_handle()->dbs_file_open_root(fs_name, &root_obj_id);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] open fs root failed, ret %d, fs name %s", ret, fs_name);
return OG_ERROR;
}
char *fix_file_path = cm_find_fix_delim(file_path, '/', 2);
cm_dbs_map_item_s file_item = { 0 };
ret = dbs_global_handle()->dbs_file_open_by_path(&root_obj_id, fix_file_path + 1, file_type, &file_item.obj_id);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] open file failed, ret %d, file path %s", ret, file_path);
return OG_ERROR;
}
if (cm_dbs_map_set(file_path, &file_item, handle, DEV_TYPE_DBSTOR_FILE) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] map set item to handle failed");
return OG_ERROR;
}
OG_LOG_RUN_INF("[CM_DEVICE] open file path %s success, handle %d", file_path, *handle);
return OG_SUCCESS;
}
void cm_dbs_close_file(int32 handle)
{
int32 tmp_handle = handle;
if (handle == OG_INVALID_HANDLE) {
return;
}
cm_dbs_map_remove(handle);
OG_LOG_DEBUG_INF("[CM_DEVICE] close handle %d success", tmp_handle);
return;
}
static status_t cm_dbs_create_file_handle(object_id_t* phandle, char* file_name, uint32 file_type, object_id_t* handle)
{
if (phandle == NULL || file_name == NULL || handle == NULL) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file handle failed, invalid param.");
return OG_ERROR;
}
int ret = dbs_global_handle()->dbs_file_open(phandle, file_name, file_type, handle);
if (ret != 0) {
ret = dbs_global_handle()->dbs_file_create(phandle, file_name, file_type, handle);
}
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] create dbs file failed, ret %d, file_name(%s) ", ret, file_name);
return OG_ERROR;
}
return OG_SUCCESS;
}
status_t cm_dbs_create_file_by_depth(object_id_t *root_handle, const char *path, uint32 total_depth,
uint32 file_type, object_id_t *file_handle)
{
char *token = NULL;
char *context = NULL;
char file_path[MAX_DBS_FS_FILE_PATH_LEN] = { 0 };
MEMS_RETURN_IFERR(strcpy_sp(file_path, MAX_DBS_FS_FILE_PATH_LEN, path));
int cur_depth = 0;
object_id_t phandle = *root_handle;
object_id_t chandle = { 0 };
token = strtok_s(file_path, "/", &context);
while (token != NULL) {
if (cur_depth == total_depth - 1) {
if (cm_dbs_create_file_handle(&phandle, token, file_type, file_handle) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] create file or dir failed, dir %s, type %u, file path %s",
token, file_type, file_path);
return OG_ERROR;
}
break;
} else {
if (cm_dbs_create_file_handle(&phandle, token, DIR_TYPE, &chandle) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] create file failed, dir %s, file path %s", token, file_path);
return OG_ERROR;
}
phandle = chandle;
}
token = strtok_s(NULL, "/", &context);
cur_depth++;
}
return OG_SUCCESS;
}
static status_t cm_dbs_create_file_common(const char *name, uint32 file_type, int32 *handle)
{
if (cm_check_file_path(name) != OG_SUCCESS) {
return OG_ERROR;
}
char file_path[MAX_DBS_FS_FILE_PATH_LEN] = { 0 };
MEMS_RETURN_IFERR(strcpy_sp(file_path, MAX_DBS_FS_FILE_PATH_LEN, name));
cm_remove_extra_delim(file_path, '/');
int path_depth = 0;
if (cm_get_file_path_depth(file_path, "/", &path_depth) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file path %s depth failed", file_path);
return OG_ERROR;
}
if (path_depth < DBSTOR_MIN_DIR_DEPTH) {
OG_LOG_RUN_ERR("[CM_DEVICE] invalid path %s depth %u to create file", file_path, path_depth);
return OG_ERROR;
}
char fs_name[MAX_DBS_FS_NAME_LEN] = { 0 };
object_id_t root_obj_id = { 0 };
if (cm_get_fs_name(file_path, "/", fs_name) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] get fs name failed, file path %s", file_path);
return OG_ERROR;
}
int ret = dbs_global_handle()->dbs_file_open_root(fs_name, &root_obj_id);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] open fs root failed, ret %d, fs name %s", ret, fs_name);
return OG_ERROR;
}
char *fix_file_path = cm_find_fix_delim(file_path, '/', 2);
cm_dbs_map_item_s file_item = { 0 };
ret = dbs_global_handle()->dbs_file_create_by_path(&root_obj_id, fix_file_path + 1, file_type, &file_item.obj_id);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] create file failed, ret %d, file path %s", ret, file_path);
return OG_ERROR;
}
if (cm_dbs_map_set(file_path, &file_item, handle, DEV_TYPE_DBSTOR_FILE) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] map set item to handle failed");
return OG_ERROR;
}
OG_LOG_RUN_INF("[CM_DEVICE] create file path %s success, handle %u", file_path, *handle);
return OG_SUCCESS;
}
static status_t cm_dbs_get_dir_handle(char *file_dir, uint32 dir_path_depth, object_id_t *obj_id)
{
char fs_name[MAX_DBS_FS_NAME_LEN] = { 0 };
if (cm_get_fs_name(file_dir, "/", fs_name) != OG_SUCCESS) {
return OG_ERROR;
}
OG_LOG_RUN_INF("[CM_DEVICE] begin to open root, file dir %s, fs_name %s", file_dir, fs_name);
object_id_t root_obj_id = { 0 };
int ret = dbs_global_handle()->dbs_file_open_root(fs_name, &root_obj_id);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] open fs root failed, ret %d, fs name %s", ret, fs_name);
return OG_ERROR;
}
if (dir_path_depth == 1) {
*obj_id = root_obj_id;
return OG_SUCCESS;
}
char *fix_file_path = cm_find_fix_delim(file_dir, '/', 2);
ret = dbs_global_handle()->dbs_file_open_by_path(&root_obj_id, fix_file_path + 1, DIR_TYPE, obj_id);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] open file dir failed, ret %d, file dir %s", ret, file_dir);
return OG_ERROR;
}
return OG_SUCCESS;
}
status_t cm_dbs_remove_file(const char *name)
{
char file_path[MAX_DBS_FS_FILE_PATH_LEN] = { 0 };
MEMS_RETURN_IFERR(strcpy_sp(file_path, MAX_DBS_FS_FILE_PATH_LEN, name));
cm_remove_extra_delim(file_path, '/');
if (cm_check_file_path(file_path) != OG_SUCCESS) {
return OG_ERROR;
}
int path_depth = 0;
if (cm_get_file_path_depth(file_path, "/", &path_depth) != OG_SUCCESS || path_depth <= 1) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file path %s depth failed", file_path);
return OG_ERROR;
}
if (path_depth < DBSTOR_MIN_DIR_DEPTH) {
OG_LOG_RUN_INF("[CM_DEVICE] invalid file path %s", file_path);
return OG_ERROR;
}
char file_name[MAX_DBS_FILE_NAME_LEN] = { 0 };
char file_dir[MAX_DBS_FS_FILE_PATH_LEN] = { 0 };
if (cm_get_file_name_and_dir(file_path, path_depth, "/", file_name, file_dir) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file name and dir failed, file path %s", file_path);
return OG_ERROR;
}
object_id_t dir_obj_id = { 0 };
if (cm_dbs_get_dir_handle(file_dir, path_depth - 1, &dir_obj_id) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file dir handle failed, file dir %s", file_dir);
return OG_ERROR;
}
int ret = dbs_global_handle()->dbs_file_remove(&dir_obj_id, file_name);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] remove file failed, ret %d, file path %s", ret, file_path);
return OG_ERROR;
}
OG_LOG_RUN_INF("[CM_DEVICE] remove file success, file path %s", file_path);
return OG_SUCCESS;
}
status_t cm_dbs_remove_dir(const char *name)
{
return cm_dbs_remove_file(name);
}
status_t cm_dbs_remove_file_vstore_id(uint32 vstore_id, const char *name)
{
if (dbs_global_handle()->dbs_file_open_root_by_vstorid == NULL) {
OG_LOG_RUN_ERR("dbs_file_open_root_by_vstorid is not support\n");
return OG_ERROR;
}
char file_path[MAX_DBS_FS_FILE_PATH_LEN] = { 0 };
MEMS_RETURN_IFERR(strcpy_sp(file_path, MAX_DBS_FS_FILE_PATH_LEN, name));
cm_remove_extra_delim(file_path, '/');
if (cm_check_file_path(file_path) != OG_SUCCESS) {
return OG_ERROR;
}
int path_depth = 0;
if (cm_get_file_path_depth(file_path, "/", &path_depth) != OG_SUCCESS || path_depth < DBSTOR_MIN_DIR_DEPTH) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file path %s depth %d failed", file_path, path_depth);
return OG_ERROR;
}
char file_name[MAX_DBS_FILE_NAME_LEN] = { 0 };
char file_dir[MAX_DBS_FS_FILE_PATH_LEN] = { 0 };
if (cm_get_file_name_and_dir(file_path, path_depth, "/", file_name, file_dir) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file name and dir failed, file path %s", file_path);
return OG_ERROR;
}
object_id_t dir_obj_id = { 0 };
char fs_name[MAX_DBS_FS_NAME_LEN] = { 0 };
if (cm_get_fs_name(file_dir, "/", fs_name) != OG_SUCCESS) {
return OG_ERROR;
}
object_id_t root_obj_id = { 0 };
int32 ret = dbs_global_handle()->dbs_file_open_root_by_vstorid(fs_name, vstore_id, &root_obj_id);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] open fs root failed, ret %d, fs name %s", ret, fs_name);
return OG_ERROR;
}
if (path_depth == DBSTOR_MIN_DIR_DEPTH) {
dir_obj_id = root_obj_id;
} else {
char *fix_file_path = cm_find_fix_delim(file_dir, '/', 2);
ret = dbs_global_handle()->dbs_file_open_by_path(&root_obj_id, fix_file_path + 1, DIR_TYPE, &dir_obj_id);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] open file dir failed, ret %d, file dir %s", ret, file_dir);
return OG_ERROR;
}
}
ret = dbs_global_handle()->dbs_file_remove(&dir_obj_id, file_name);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] remove file failed, ret %d, file path %s", ret, file_path);
return OG_ERROR;
}
OG_LOG_RUN_INF("[CM_DEVICE] remove file success, file path %s", file_path);
return OG_SUCCESS;
}
status_t cm_dbs_open_fs(const char *name, int32 *root_handle)
{
if (cm_check_file_path(name) != OG_SUCCESS) {
return OG_ERROR;
}
if (strlen(name) >= MAX_DBS_FS_NAME_LEN) {
OG_LOG_RUN_ERR("[CM_DEVICE] invalid fs name %s, len %lu", name, strlen(name));
return OG_ERROR;
}
char fs_name[MAX_DBS_FS_NAME_LEN] = { 0 };
MEMS_RETURN_IFERR(strcpy_sp(fs_name, MAX_DBS_FS_NAME_LEN, name));
cm_remove_extra_delim(fs_name, '/');
int path_depth = 0;
if (cm_get_file_path_depth(fs_name, "/", &path_depth) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file path %s depth failed", fs_name);
return OG_ERROR;
}
if (path_depth != 1) {
OG_LOG_RUN_ERR("[CM_DEVICE] invalid fs name %s", fs_name);
return OG_ERROR;
}
if (cm_dbs_open_root(fs_name, root_handle) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] open fs %s failed", fs_name);
return OG_ERROR;
}
OG_LOG_RUN_INF("[CM_DEVICE] open fs %s success", fs_name);
return OG_SUCCESS;
}
status_t cm_dbs_create_file(const char *name, int32 *handle)
{
return cm_dbs_create_file_common(name, FILE_TYPE, handle);
}
status_t cm_dbs_create_dir(const char *name, int32 *handle)
{
return cm_dbs_create_file_common(name, DIR_TYPE, handle);
}
status_t cm_dbs_open_file(const char *name, int32 *handle)
{
return cm_dbs_open_file_common(name, FILE_TYPE, handle);
}
status_t cm_dbs_open_dir(const char *name, int32 *handle)
{
return cm_dbs_open_file_common(name, DIR_TYPE, handle);
}
static status_t cm_do_dbs_file_read(object_id_t *obj_id, uint64 offset, char *buf, uint32 size, uint32 *real_read_size)
{
int32 ret = 0;
for (uint32 i = 0; i < DBSTOR_MAX_RETRY_COUNT; i++) {
ret = dbs_global_handle()->dbs_file_read(obj_id, offset, buf, size, real_read_size);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] failed to read file, cnt %u info %llu/%u ret:%d.", i + 1, offset, size, ret);
continue;
}
return OG_SUCCESS;
}
return OG_ERROR;
}
status_t cm_dbs_read_file(int32 handle, int64 offset, const void *buf, int32 size, int32 *return_size)
{
if (offset + size > DBSTOR_MAX_FILE_SIZE) {
OG_LOG_RUN_ERR("[CM_DEVICE] invalid file offset %llu and size %d", offset, size);
return OG_ERROR;
}
int32 already_r_size = 0;
int32 read_size = 0;
int64 read_offset = offset;
char *read_buf = (char *)buf;
int32 total_size = size;
OG_LOG_DEBUG_INF("[CM_DEVICE] Begin to read file handle %d offset %lld size %d.", handle, offset, size);
cm_dbs_map_item_s obj = { 0 };
if (cm_dbs_map_get(handle, &obj) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] Failed to get dbstor file to read by handle(%d).", handle);
return OG_ERROR;
}
uint32 real_read_size = 0;
OG_LOG_DEBUG_INF("[CM_DEVICE] Success to get dbstor file to read by handle(%d).", handle);
while (total_size > 0) {
read_size = total_size > DBSTOR_MAX_RWBUF_SIZE ? DBSTOR_MAX_RWBUF_SIZE : total_size;
real_read_size = 0;
if (cm_do_dbs_file_read(&obj.obj_id, read_offset, read_buf, read_size, &real_read_size) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] Failed to read file total_size: %d already read size: %d.",
size, already_r_size);
return OG_ERROR;
}
if (real_read_size == 0) {
break;
}
read_offset += real_read_size;
read_buf += real_read_size;
already_r_size += real_read_size;
total_size -= real_read_size;
}
*return_size = already_r_size;
OG_LOG_DEBUG_INF("[CM_DEVICE] Success to read file total_size: %d already read size: %d.", size, *return_size);
return OG_SUCCESS;
}
static status_t cm_do_dbs_file_write(object_id_t *obj_id, uint64 offset, char *buf, uint32 size)
{
int32 ret = 0;
for (uint32 i = 0; i < DBSTOR_MAX_RETRY_COUNT; i++) {
ret = dbs_global_handle()->dbs_file_write(obj_id, offset, buf, size);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] Failed to write file, cnt %u info %llu/%u ret:%d.", i + 1, offset, size, ret);
continue;
}
return OG_SUCCESS;
}
return OG_ERROR;
}
status_t cm_dbs_write_file(int32 handle, int64 offset, const void *buf, int32 size)
{
if (offset + size > DBSTOR_MAX_FILE_SIZE) {
OG_LOG_RUN_ERR("[CM_DEVICE] invalid file offset %llu and size %d", offset, size);
return OG_ERROR;
}
int32 write_size = 0;
int64 off = offset;
int32 total_size = size;
char *w_buf = (char *)buf;
OG_LOG_DEBUG_INF("[CM_DEVICE] Begin to write file handle %d offset %lld size %d.", handle, offset, size);
cm_dbs_map_item_s obj = { 0 };
if (cm_dbs_map_get(handle, &obj) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] Failed to get dbstor file to write by handle(%d).", handle);
return OG_ERROR;
}
OG_LOG_DEBUG_INF("[CM_DEVICE] Success to get dbstor file to write by handle(%d).", handle);
while (total_size > 0) {
write_size = total_size > DBSTOR_MAX_RWBUF_SIZE ? DBSTOR_MAX_RWBUF_SIZE : total_size;
if (cm_do_dbs_file_write(&obj.obj_id, off, w_buf, write_size) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] Failed to write file total size: %d already write size: %d.",
size, size - total_size);
return OG_ERROR;
}
off += write_size;
w_buf += write_size;
total_size -= write_size;
}
OG_LOG_DEBUG_INF("[CM_DEVICE] Success to write file total_size %d offset %lld already write size %d.",
size, off, size - total_size);
return OG_SUCCESS;
}
status_t cm_dbs_rename_file(const char *src_name, const char *dst_name)
{
if (cm_check_file_path(src_name) != OG_SUCCESS || cm_check_file_path(dst_name) != OG_SUCCESS) {
return OG_ERROR;
}
char src_path[MAX_DBS_FS_FILE_PATH_LEN] = { 0 };
char dst_path[MAX_DBS_FS_FILE_PATH_LEN] = { 0 };
MEMS_RETURN_IFERR(strcpy_sp(src_path, MAX_DBS_FS_FILE_PATH_LEN, src_name));
cm_remove_extra_delim(src_path, '/');
MEMS_RETURN_IFERR(strcpy_sp(dst_path, MAX_DBS_FS_FILE_PATH_LEN, dst_name));
cm_remove_extra_delim(dst_path, '/');
int src_path_depth = 0;
int dst_path_depth = 0;
if (cm_get_file_path_depth(src_path, "/", &src_path_depth) != OG_SUCCESS || src_path_depth <= 1) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file path %s depth failed", src_path);
return OG_ERROR;
}
if (cm_get_file_path_depth(dst_path, "/", &dst_path_depth) != OG_SUCCESS || dst_path_depth <= 1) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file path %s depth failed", dst_path);
return OG_ERROR;
}
if (!cm_dbs_exist_file(src_path, DIR_TYPE) && !cm_dbs_exist_file(src_path, FILE_TYPE)) {
return OG_ERROR;
}
char src_file_name[MAX_DBS_FILE_NAME_LEN] = { 0 };
char src_file_dir[MAX_DBS_FS_FILE_PATH_LEN] = { 0 };
char dst_file_name[MAX_DBS_FILE_NAME_LEN] = { 0 };
char dst_file_dir[MAX_DBS_FS_FILE_PATH_LEN] = { 0 };
if (cm_get_file_name_and_dir(src_path, src_path_depth, "/", src_file_name, src_file_dir) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs src file name and dir failed, file path %s", src_path);
return OG_ERROR;
}
if (cm_get_file_name_and_dir(dst_path, dst_path_depth, "/", dst_file_name, dst_file_dir) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs dst file name and dir failed, file path %s", dst_path);
return OG_ERROR;
}
if (strcmp(dst_file_dir, src_file_dir) != 0 || strcmp(dst_file_name, src_file_name) == 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] invalid src file path %s and dst file path %s", src_path, dst_path);
return OG_ERROR;
}
object_id_t dir_obj_id = { 0 };
if (cm_dbs_get_dir_handle(dst_file_dir, dst_path_depth - 1, &dir_obj_id) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file dir handle failed, file dir %s", dst_file_dir);
return OG_ERROR;
}
int ret = dbs_global_handle()->dbs_file_rename(&dir_obj_id, src_file_name, dst_file_name);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] rename %s to %s failed, ret %d", src_path, dst_path, ret);
return OG_ERROR;
}
OG_LOG_RUN_INF("[CM_DEVICE] rename %s to %s success", src_path, dst_path);
return OG_SUCCESS;
}
bool32 cm_dbs_exist_file(const char *name, uint32 file_type)
{
if (cm_check_file_path(name) != OG_SUCCESS) {
return OG_FALSE;
}
char file_path[MAX_DBS_FS_FILE_PATH_LEN] = { 0 };
MEMS_RETURN_IFERR(strcpy_sp(file_path, MAX_DBS_FS_FILE_PATH_LEN, name));
cm_remove_extra_delim(file_path, '/');
int path_depth = 0;
if (cm_get_file_path_depth(file_path, "/", &path_depth) != OG_SUCCESS || path_depth < 1) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file path %s depth failed", file_path);
return OG_FALSE;
}
char fs_name[MAX_DBS_FS_NAME_LEN] = { 0 };
if (cm_get_fs_name(file_path, "/", fs_name) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] get fs name failed, file path %s", file_path);
return OG_FALSE;
}
object_id_t root_obj_id = { 0 };
int ret = dbs_global_handle()->dbs_file_open_root(fs_name, &root_obj_id);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] open fs root failed, ret %d, fs name %s", ret, fs_name);
return OG_FALSE;
}
if (path_depth == 1) {
return OG_TRUE;
}
char *fix_file_path = cm_find_fix_delim(file_path, '/', 2);
object_id_t file_obj_id = { 0 };
ret = dbs_global_handle()->dbs_file_open_by_path(&root_obj_id, fix_file_path + 1, file_type, &file_obj_id);
if (ret != 0) {
OG_LOG_RUN_INF("[CM_DEVICE] file probably does not exist, ret %d, file path %s", ret, file_path);
return OG_FALSE;
}
return OG_TRUE;
}
status_t cm_dbs_access_file(const char *name, int32 *handle)
{
return cm_dbs_open_file(name, handle);
}
status_t cm_dbs_query_file_num(const char *name, uint32 *file_num)
{
OG_LOG_RUN_INF("[CM_DEVICE] begin to get file num, file dir %s", name);
char file_dir[MAX_DBS_FILE_PATH_LEN] = { 0 };
MEMS_RETURN_IFERR(strcpy_sp(file_dir, MAX_DBS_FILE_PATH_LEN, name));
cm_remove_extra_delim(file_dir, '/');
if (cm_check_file_path(file_dir) != OG_SUCCESS) {
return OG_ERROR;
}
int path_depth = 0;
if (cm_get_file_path_depth(file_dir, "/", &path_depth) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file dir %s depth failed", file_dir);
return OG_ERROR;
}
object_id_t dir_obj_id = { 0 };
if (cm_dbs_get_dir_handle(file_dir, path_depth, &dir_obj_id) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file dir handle failed, file dir %s", file_dir);
return OG_ERROR;
}
int32 ret = dbs_global_handle()->dbs_file_get_num(&dir_obj_id, file_num);
if (ret != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] Failed to get file num, ret %d, file dir %s", ret, file_dir);
return OG_ERROR;
}
OG_LOG_RUN_INF("[CM_DEVICE] Success to get file_num %u, file dir %s", *file_num, file_dir);
return OG_SUCCESS;
}
status_t cm_dbs_query_file_num_by_vstore_id(const char *name, uint32 *file_num, uint32 vstore_id)
{
OG_LOG_RUN_INF("[CM_DEVICE] begin to get file num, file dir %s", name);
char file_dir[MAX_DBS_FILE_PATH_LEN] = { 0 };
MEMS_RETURN_IFERR(strcpy_sp(file_dir, MAX_DBS_FILE_PATH_LEN, name));
cm_remove_extra_delim(file_dir, '/');
if (cm_check_file_path(file_dir) != OG_SUCCESS) {
return OG_ERROR;
}
int path_depth = 0;
if (cm_get_file_path_depth(file_dir, "/", &path_depth) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file dir %s depth failed", file_dir);
return OG_ERROR;
}
object_id_t dir_obj_id = { 0 };
char fs_name[MAX_DBS_FS_NAME_LEN] = { 0 };
if (cm_get_fs_name(file_dir, "/", fs_name) != OG_SUCCESS) {
return OG_ERROR;
}
OG_LOG_RUN_INF("[CM_DEVICE] begin to open root, file dir %s, fs_name %s", file_dir, fs_name);
object_id_t root_obj_id = { 0 };
int32 ret = dbs_global_handle()->dbs_file_open_root_by_vstorid(fs_name, vstore_id, &root_obj_id);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] open fs root failed, by vstore id %u, ret %d, fs name %s", vstore_id, ret, fs_name);
return OG_ERROR;
}
if (path_depth == 1) {
dir_obj_id = root_obj_id;
} else {
char *fix_file_path = cm_find_fix_delim(file_dir, '/', 2);
ret = dbs_global_handle()->dbs_file_open_by_path(&root_obj_id, fix_file_path + 1, DIR_TYPE, &dir_obj_id);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] open file dir failed, ret %d, file dir %s", ret, file_dir);
return OG_ERROR;
}
}
ret = dbs_global_handle()->dbs_file_get_num(&dir_obj_id, file_num);
if (ret != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] Failed to get file num, ret %d, file dir %s", ret, file_dir);
return OG_ERROR;
}
OG_LOG_RUN_INF("[CM_DEVICE] Success to get file_num %u, file dir %s", *file_num, file_dir);
return OG_SUCCESS;
}
status_t cm_dbs_query_dir(const char *name, void *file_list, uint32 *file_num)
{
OG_LOG_RUN_INF("[CM_DEVICE] begin to get file list, file dir %s", name);
char file_dir[MAX_DBS_FILE_PATH_LEN] = { 0 };
MEMS_RETURN_IFERR(strcpy_sp(file_dir, MAX_DBS_FILE_PATH_LEN, name));
cm_remove_extra_delim(file_dir, '/');
if (cm_check_file_path(file_dir) != OG_SUCCESS) {
return OG_ERROR;
}
int path_depth = 0;
if (cm_get_file_path_depth(file_dir, "/", &path_depth) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file dir %s depth failed", file_dir);
return OG_ERROR;
}
object_id_t dir_obj_id = { 0 };
if (cm_dbs_get_dir_handle(file_dir, path_depth, &dir_obj_id) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file dir handle failed, file dir %s", file_dir);
return OG_ERROR;
}
int32 ret = dbs_global_handle()->dbs_file_get_list(&dir_obj_id, file_list, file_num);
if (ret != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] Failed to get file list, ret %d, file dir %s", ret, file_dir);
return OG_ERROR;
}
OG_LOG_RUN_INF("[CM_DEVICE] Success to get file list, file_num %u, file dir %s", *file_num, file_dir);
return OG_SUCCESS;
}
status_t cm_dbs_query_dir_vstore_id(uint32 vstore_id, const char *name, void *file_list, uint32 *file_num)
{
if (dbs_global_handle()->dbs_file_open_root_by_vstorid == NULL) {
OG_LOG_RUN_ERR("dbs_file_open_root_by_vstorid is not support\n");
return OG_ERROR;
}
OG_LOG_RUN_INF("[CM_DEVICE] begin to get file list, file dir %s", name);
char file_dir[MAX_DBS_FILE_PATH_LEN] = { 0 };
MEMS_RETURN_IFERR(strcpy_sp(file_dir, MAX_DBS_FILE_PATH_LEN, name));
cm_remove_extra_delim(file_dir, '/');
if (cm_check_file_path(file_dir) != OG_SUCCESS) {
return OG_ERROR;
}
int path_depth = 0;
if (cm_get_file_path_depth(file_dir, "/", &path_depth) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] get dbs file dir %s depth failed", file_dir);
return OG_ERROR;
}
object_id_t dir_obj_id = { 0 };
char fs_name[MAX_DBS_FS_NAME_LEN] = { 0 };
if (cm_get_fs_name(file_dir, "/", fs_name) != OG_SUCCESS) {
return OG_ERROR;
}
object_id_t root_obj_id = { 0 };
int32 ret = dbs_global_handle()->dbs_file_open_root_by_vstorid(fs_name, vstore_id, &root_obj_id);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] open fs root failed, ret %d, fs name %s", ret, fs_name);
return OG_ERROR;
}
if (path_depth == 1) {
dir_obj_id = root_obj_id;
} else {
char *fix_file_path = cm_find_fix_delim(file_dir, '/', 2);
ret = dbs_global_handle()->dbs_file_open_by_path(&root_obj_id, fix_file_path + 1, DIR_TYPE, &dir_obj_id);
if (ret != 0) {
OG_LOG_RUN_ERR("[CM_DEVICE] open file dir failed, ret %d, file dir %s", ret, file_dir);
return OG_ERROR;
}
}
if (dbs_global_handle()->dbs_file_get_list_detail != NULL) {
ret = dbs_global_handle()->dbs_file_get_list_detail(&dir_obj_id, file_list, file_num);
} else {
ret = dbs_global_handle()->dbs_file_get_list(&dir_obj_id, file_list, file_num);
}
if (ret != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] Failed to get file list, ret %d, file dir %s", ret, file_dir);
return OG_ERROR;
}
OG_LOG_RUN_INF("[CM_DEVICE] Success to get file list, file_num %u, file dir %s", *file_num, file_dir);
return OG_SUCCESS;
}
status_t cm_dbs_get_file_size(int32 handle, int64 *file_size)
{
uint64 size = 0;
if (handle == OG_INVALID_HANDLE) {
OG_LOG_RUN_ERR("[CM_DEVICE] Invalid handle %d", handle);
return OG_ERROR;
}
cm_dbs_map_item_s item = { 0 };
if (cm_dbs_map_get(handle, &item) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] Failed to get dbstor file to get file size by handle(%d).", handle);
return OG_ERROR;
}
int32 ret = dbs_global_handle()->dbs_get_file_size(&item.obj_id, &size);
if (ret != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_DEVICE] Failed to get file size, ret %d, handle %d", ret, handle);
return OG_ERROR;
}
*file_size = (int64)size;
OG_LOG_RUN_INF("[CM_DEVICE] Success to get dbstor file size by handle(%d), file size %llu.", handle, size);
return OG_SUCCESS;
}
status_t cm_dbs_ulog_archive(int32 src_file, int32 dst_file, uint64 offset, uint64 start_lsn,
uint64 arch_size, uint64 *real_arch_size, uint64 *last_lsn)
{
if (src_file == OG_INVALID_HANDLE || dst_file == OG_INVALID_HANDLE) {
OG_LOG_RUN_ERR("[CM_ARCH] invalid file handle, src %d, dst %d", src_file, dst_file);
return OG_ERROR;
}
if (offset + arch_size > DBSTOR_MAX_FILE_SIZE) {
OG_LOG_RUN_ERR("[CM_ARCH] invalid file offset %llu and arch_size %llu", offset, arch_size);
return OG_ERROR;
}
cm_dbs_map_item_s src_item = { 0 };
if (cm_dbs_map_get(src_file, &src_item) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_ARCH] Failed to get dbstor object id by handle(%d).", src_file);
return OG_ERROR;
}
cm_dbs_map_item_s dst_item = { 0 };
if (cm_dbs_map_get(dst_file, &dst_item) != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_ARCH] Failed to get dbstor object id by handle(%d).", dst_file);
return OG_ERROR;
}
ulog_archive_option_t option = { offset, arch_size, start_lsn };
ulog_archive_result_t result = { 0 };
int32 ret = dbs_global_handle()->dbs_ulog_archive(&src_item.obj_id, &dst_item.obj_id, &option, &result);
if (ret == DBSTOR_ULOG_ARCHIVE_END) {
OG_LOG_RUN_INF_LIMIT(LOG_PRINT_INTERVAL_SECOND_20,
"[CM_ARCH] redo log has been archived to the end, ret %d, offset %llu, start lsn %llu",
ret, offset, start_lsn);
*real_arch_size = 0;
return OG_SUCCESS;
}
if (ret != OG_SUCCESS) {
OG_LOG_RUN_ERR("[CM_ARCH] Failed to arch redo log, ret %d, offset %llu, start lsn %llu",
ret, offset, start_lsn);
return OG_ERROR;
}
*last_lsn = result.end_lsn;
*real_arch_size = result.real_len;
OG_LOG_RUN_INF_LIMIT(LOG_PRINT_INTERVAL_SECOND_20,
"[CM_ARCH] ulog archive redo successful, offset %llu, start lsn %llu, "
"last lsn %llu, real_arch_size %llu.", offset, start_lsn, *last_lsn, *real_arch_size);
return OG_SUCCESS;
}