/* Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
 * openUBMC 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.
 */

#include <math.h>
#include "platform.h"
#include "sml_errcodes.h"
#include "sml_public.h"
#include "histore/tool_lib.h"
#include "histore/lib_api.h"
#include "hs_misc.h"
#include "hs_ld.h"

#define SUB_ARRAY_BIT    0x8000

typedef struct {
    guint8 raw_value;
    guint8 state;
} LD_STATE_MAP;

typedef struct {
    guint8 raw_value;
    guint8 raid_level;
} RAID_LEVEL_MAP;

static LD_STATE_MAP g_ld_state_maps[] = {
    {ADM_LUN_STATUS_NORMAL, LD_STATE_OPTIMAL},
    {ADM_LUN_STATUS_FAULT, LD_STATE_FAILED},
    {ADM_LUN_STATUS_DEGRADE, LD_STATE_DEGRADED},
    {ADM_LUN_STATUS_NOTFORMATTED, LD_STATE_NOT_FORMATTED},
    {ADM_LUN_STATUS_FORMATTING, LD_STATE_FORMATTING},
    {ADM_LUN_STATUS_SANITIZING, LD_STATE_SANITIZING},
    {ADM_LUN_STATUS_INITIALIZING, LD_STATE_INITIALIZING},
    {ADM_LUN_STATUS_INITIALIZEFAIL, LD_STATE_INITIALIZEFAIL},
    {ADM_LUN_STATUS_DELETING, LD_STATE_DELETING},
    {ADM_LUN_STATUS_DELETEFAIL, LD_STATE_DELETEFAIL},
    {ADM_LUN_STATUS_WRITE_PROTECT, LD_STATE_WRITE_PROTECT},
};

static RAID_LEVEL_MAP g_raid_level_maps[] = {
    {CMD_RAID_LEVEL_RAID0, RAID_LEVEL_0},
    {CMD_RAID_LEVEL_RAID1, RAID_LEVEL_1},
    {CMD_RAID_LEVEL_RAID5, RAID_LEVEL_5},
    {CMD_RAID_LEVEL_RAID6, RAID_LEVEL_6},
    {CMD_RAID_LEVEL_RAID10, RAID_LEVEL_10},
    {CMD_RAID_LEVEL_RAID50, RAID_LEVEL_50},
    {CMD_RAID_LEVEL_RAID60, RAID_LEVEL_60},
};

/*
 * Description: 获取逻辑盘ID列表
 */
gint32 histore_get_ctrl_ld_list(guint32 ctrl_id, gpointer data)
{
    if (data == NULL) {
        return SML_ERR_NULL_DATA;
    }

    struct cmd_vds_id vd_list;
    (void)memset_s(&vd_list, sizeof(vd_list), 0, sizeof(vd_list));
    gint32 ret = get_vd_list(ctrl_id, &vd_list);
    if (ret != SML_SUCCESS) {
        return ret;
    }

    SML_LD_LIST_S *pLDlist = (SML_LD_LIST_S *)data;
    pLDlist->ld_count = MIN(vd_list.num, VDS_ID_NODE_NUM);
    for (guint16 i = 0; i < pLDlist->ld_count; i++) {
        pLDlist->target_ids[i] = vd_list.ids[i];
    }

    /* vd列表刷新，清除无效的vd缓存 */
    remove_invalid_vd_cache(ctrl_id, &vd_list);
    return SML_SUCCESS;
}

/*
 * Description: 从hash表获取vd信息，若没有则发命令向RAID卡获取，并更新到hash表
 */
static gint32 get_vd_info_by_hash(guint32 ctrl_id, guint16 target_id, struct cmd_vd_info *vd_info)
{
    CACHED_VD_INFO cached_vd_info;
    (void)memset_s(&cached_vd_info, sizeof(cached_vd_info), 0, sizeof(cached_vd_info));

    if (find_data_from_hash_table(ctrl_id, target_id, (gpointer)&cached_vd_info, sizeof(cached_vd_info),
        CACHE_TYPE_VD) == RET_OK) {
        if (cached_vd_info.read_count > 0) {
            cached_vd_info.read_count--;
            (void)memcpy_s(vd_info, sizeof(struct cmd_vd_info), &cached_vd_info.vd_info,
                sizeof(cached_vd_info.vd_info));
            insert_data_to_hash_table(ctrl_id, target_id, (gpointer)&cached_vd_info, sizeof(cached_vd_info),
                CACHE_TYPE_VD);
            return RET_OK;
        }
    }

    gint32 ret = get_vd_info(ctrl_id, target_id, vd_info);
    if (ret != SML_SUCCESS) {
        return ret;
    }

    cached_vd_info.read_count = 3;   // 同一个vd的缓存数据最多被读取3次
    (void)memcpy_s(&cached_vd_info.vd_info, sizeof(cached_vd_info.vd_info), vd_info, sizeof(struct cmd_vd_info));
    insert_data_to_hash_table(ctrl_id, target_id, (gpointer)&cached_vd_info, sizeof(cached_vd_info), CACHE_TYPE_VD);
    return RET_OK;
}

/*
 * Description: 解析逻辑盘RAID级别
 */
static guint8 parse_raid_level(guint8 raw_value)
{
    for (guint8 i = 0; i < G_N_ELEMENTS(g_raid_level_maps); i++) {
        if (raw_value == g_raid_level_maps[i].raw_value) {
            return g_raid_level_maps[i].raid_level;
        }
    }

    return RAID_LEVEL_UNKNOWN;
}

/*
 * Description: 转换为卡侧RAID级别
 */
static guint8 convert_to_raid_level(guint8 value)
{
    for (guint8 i = 0; i < G_N_ELEMENTS(g_raid_level_maps); i++) {
        if (value == g_raid_level_maps[i].raid_level) {
            return g_raid_level_maps[i].raw_value;
        }
    }

    return CMD_RAID_DEFAULT_VALUE;
}

/*
 * Description: 解析逻辑盘状态
 */
static guint8 parse_ld_status(guint8 raw_value)
{
    for (guint8 i = 0; i < G_N_ELEMENTS(g_ld_state_maps); i++) {
        if (raw_value == g_ld_state_maps[i].raw_value) {
            return g_ld_state_maps[i].state;
        }
    }

    return LD_STATE_UNKNOWN;
}

/*
 * Description: 解析逻辑盘读策略
 */
static guint8 parse_ld_rcache(guint8 raw_value)
{
    if (raw_value == ADM_NO_AHEAD) {
        return LD_CACHE_NO_READ_AHEAD;
    } else if (raw_value == ADM_AHEAD) {
        return LD_CACHE_READ_AHEAD;
    } else {
        return STORAGE_INFO_INVALID_BYTE;
    }
}

/*
 * Description: 转换为卡侧读策略
 */
static guint8 convert_to_rcache(guint8 value)
{
    if (value == LD_CACHE_READ_AHEAD) {
        /* 固定预读 */
        return ADM_AHEAD;
    }

    /* 不预读 */
    return ADM_NO_AHEAD;
}

/*
 * Description: 解析逻辑盘写策略
 */
static guint8 parse_ld_wcache(guint8 raw_value)
{
    if (raw_value == ADM_WB) {
        return LD_CACHE_WRITE_BACK;
    } else if (raw_value == ADM_WT) {
        return LD_CACHE_WRITE_THROUGH;
    } else if (raw_value == ADM_WBE) {
        return LD_CACHE_WRITE_CACHE_IF_BAD_BBU;
    } else {
        return STORAGE_INFO_INVALID_BYTE;
    }
}

/*
 * Description: 转换为卡侧写策略
 */
static guint8 convert_to_wcache(guint8 value)
{
    if (value == LD_CACHE_WRITE_BACK) {
        /* WB写回 */
        return ADM_WB;
    } else if (value == LD_CACHE_WRITE_CACHE_IF_BAD_BBU) {
        /* WBE强制写回 */
        return ADM_WBE;
    }

    /* 默认值：WT写穿 */
    return ADM_WT;
}

/*
 * Description: 解析逻辑盘的硬盘缓存策略
 */
static guint8 parse_ld_dcp(guint8 raw_value)
{
    if (raw_value == ADM_DISK_CAHE_SWITCH_OFF) {
        return PD_CACHE_DISABLE;
    } else if (raw_value == ADM_DISK_CAHE_SWITCH_ON) {
        return PD_CACHE_ENABLE;
    } else if (raw_value == ADM_DISK_CAHE_DEFAULT) {
        return PD_CACHE_UNCHANGED;
    } else {
        return STORAGE_INFO_INVALID_BYTE;
    }
}

/*
 * Description: 转换为卡侧硬盘缓存策略
 */
static guint8 convert_to_dcp(guint8 value)
{
    if (value == PD_CACHE_DISABLE) {
        return ADM_DISK_CAHE_SWITCH_OFF;
    } else if (value == PD_CACHE_ENABLE) {
        return ADM_DISK_CAHE_SWITCH_ON;
    }
    return ADM_DISK_CAHE_DEFAULT;
}

/*
 * Description: 解析逻辑盘的初始化状态
 */
static void parse_ld_init(SML_LD_BASIC_INFO_S *pLDinfo, const struct cmd_vd_info *vd_info)
{
    // formatting是前台, initializing是后台
    pLDinfo->progress_info.current_fgi_state = (vd_info->vd_status == ADM_LUN_STATUS_FORMATTING);
    pLDinfo->progress_info.fgi =
        (vd_info->vd_status == ADM_LUN_STATUS_FORMATTING) ? vd_info->init_progress : STORAGE_INFO_INVALID_BYTE;
    return;
}

/*
 * Description: 从hash表获取rg信息，若没有则发命令向RAID卡获取，并更新到hash表
 */
static gint32 get_rg_info_by_hash(guint32 ctrl_id, guint16 target_id, struct cmd_rg_info *rg_info)
{
    CACHED_RG_INFO cached_rg_info;
    (void)memset_s(&cached_rg_info, sizeof(cached_rg_info), 0, sizeof(cached_rg_info));

    if (find_data_from_hash_table(ctrl_id, target_id, (gpointer)&cached_rg_info, sizeof(cached_rg_info),
        CACHE_TYPE_RG) == RET_OK) {
        if (cached_rg_info.read_count > 0) {
            cached_rg_info.read_count--;
            (void)memcpy_s(rg_info, sizeof(struct cmd_rg_info), &cached_rg_info.rg_info,
                sizeof(cached_rg_info.rg_info));
            insert_data_to_hash_table(ctrl_id, target_id, (gpointer)&cached_rg_info, sizeof(cached_rg_info),
                CACHE_TYPE_RG);
            return RET_OK;
        }
    }

    gint32 ret = get_rg_info(ctrl_id, target_id, rg_info);
    if (ret != SML_SUCCESS) {
        return ret;
    }

    cached_rg_info.read_count = 3;   // 同一个rg的缓存数据最多被读取3次
    (void)memcpy_s(&cached_rg_info.rg_info, sizeof(cached_rg_info.rg_info), rg_info, sizeof(struct cmd_rg_info));
    insert_data_to_hash_table(ctrl_id, target_id, (gpointer)&cached_rg_info, sizeof(cached_rg_info), CACHE_TYPE_RG);
    return RET_OK;
}

/*
 * Description: 获取小于目标id的所有vd的sg数量之和
 */
static guint16 get_sg_total_count_behind(guint32 ctrl_id, guint16 target_id)
{
    GHashTable *hash_table = get_cache_hash_table(ctrl_id, CACHE_TYPE_VD);
    if (hash_table == NULL) {
        return 0;
    }

    if (g_hash_table_size(hash_table) == 0) {
        return 0;
    }

    guint16 count = 0;
    GHashTableIter iter;
    gpointer key = NULL;
    gpointer value = NULL;
    g_hash_table_iter_init(&iter, hash_table);
    while (g_hash_table_iter_next(&iter, &key, &value)) {
        guint16 vd_id = POINTER_TO_UINT16(key);
        if (vd_id >= target_id || value == NULL) {
            continue;
        }

        struct cmd_vd_info *vd_info = (struct cmd_vd_info *)value;
        count += vd_info->sg_num;
    }

    return count;
}

/*
 * Description: 不支持的字段，赋无效值
 */
static void set_ld_properties_unsupported(SML_LD_BASIC_INFO_S *pLDinfo)
{
    pLDinfo->accelerator = STORAGE_INFO_INVALID_BYTE;
    pLDinfo->cache_line_size = STORAGE_INFO_INVALID_BYTE;
    pLDinfo->access_policy = STORAGE_INFO_INVALID_BYTE;
    pLDinfo->default_cache_policy = STORAGE_INFO_INVALID_BYTE;
    pLDinfo->current_cache_policy = STORAGE_INFO_INVALID_BYTE;
    pLDinfo->init_state = STORAGE_INFO_INVALID_BYTE;
    pLDinfo->consistent_check = STORAGE_INFO_INVALID_BYTE;
    pLDinfo->bgi_enabled = STORAGE_INFO_INVALID_BYTE;
    pLDinfo->is_sscd = STORAGE_INFO_INVALID_BYTE;
    return;
}

/*
 * Description: 获取逻辑盘的关联阵列
 */
static void get_ld_ref_array(guint32 ctrl_id, guint16 target_id, SML_LD_BASIC_INFO_S *pLDinfo, guint16 rg_id,
    const struct cmd_rg_info *rg_info)
{
    pLDinfo->ref_array[0] = rg_id; // 0的位置留给rg

    // 获取hash表中除了当前vd的剩余所有vd总共占了几个sg，当前vd的sg往后依次编号
    guint16 sg_total_count_behind = get_sg_total_count_behind(ctrl_id, target_id);
    for (guint8 i = 0; i < rg_info->sg_num; i++) {
        guint8 idx = i + 1;  // 0已经留给rg，则sg从1开始存放
        if (idx >= SML_MAX_SPAN_DEPTH) {
            break;
        }

        SUB_GROUP_INDEX_S sg_idx_info = {0};
        sg_idx_info.rg_id = rg_id;
        sg_idx_info.sg_index = i;

        // 给sg编号
        guint16 sub_array_id = SUB_ARRAY_BIT | (sg_total_count_behind + i);
        // 保存到hash表
        insert_data_to_hash_table(ctrl_id, sub_array_id, &sg_idx_info, sizeof(sg_idx_info), CACHE_TYPE_SG);
        pLDinfo->ref_array[idx] = sub_array_id;
    }
    guint8 array_count = 1 + rg_info->sg_num;   // rg + sg的总个数
    pLDinfo->array_count = MIN(array_count, SML_MAX_SPAN_DEPTH);
    return;
}

/*
 * Description: 获取逻辑盘信息
 */
gint32 histore_get_ld_info(guint32 ctrl_id, guint16 target_id, gpointer data)
{
    if (data == NULL) {
        return SML_ERR_NULL_DATA;
    }

    struct cmd_vd_info vd_info;
    (void)memset_s(&vd_info, sizeof(vd_info), 0, sizeof(vd_info));
    gint32 ret = get_vd_info_by_hash(ctrl_id, target_id, &vd_info);
    if (ret != SML_SUCCESS) {
        return ret;
    }

    SML_LD_BASIC_INFO_S *pLDinfo = (SML_LD_BASIC_INFO_S *)data;
    // 1、基本信息
    errno_t securec_rv =
        strncpy_s(pLDinfo->name, sizeof(pLDinfo->name), (gchar *)vd_info.name, strlen((gchar *)vd_info.name));
    if (securec_rv != EOK) {
        debug_log(DLOG_ERROR, "%s: strncpy_s failed, ret = %d", __FUNCTION__, securec_rv);
    }
    pLDinfo->target_id = target_id;
    pLDinfo->raid_level = parse_raid_level(vd_info.rg_level);
    pLDinfo->drive_state = parse_ld_status(vd_info.vd_status);
    pLDinfo->strip_size = log(vd_info.su_size) / log(2) + 1; // 单位已经KB，以2为底进行转换
    pLDinfo->size = vd_info.capacity;
    pLDinfo->default_read_policy = parse_ld_rcache(vd_info.rcache);
    pLDinfo->current_read_policy = parse_ld_rcache(vd_info.rcache);
    pLDinfo->default_write_policy = parse_ld_wcache(vd_info.wcache);
    pLDinfo->current_write_policy = parse_ld_wcache(vd_info.real_wcache);
    parse_ld_init(pLDinfo, &vd_info);
    pLDinfo->span_depth = vd_info.sg_num;
    pLDinfo->num_drive_per_span = vd_info.sg_disk_num;
    pLDinfo->bootable = vd_info.is_boot;
    pLDinfo->boot_priority = ((vd_info.is_boot == TRUE) ? BOOT_PRIORITY_PRIMARY : BOOT_PRIORITY_NONE);

    struct cmd_rg_info rg_info;
    (void)memset_s(&rg_info, sizeof(rg_info), 0, sizeof(rg_info));
    guint16 rg_id = (guint16)vd_info.rg_id;
    ret = get_rg_info_by_hash(ctrl_id, rg_id, &rg_info);
    if (ret != SML_SUCCESS) {
        return ret;
    }

    pLDinfo->disk_cache_policy = parse_ld_dcp(rg_info.disk_cache_sw);

    // 2、获取关联热备盘
    pLDinfo->spare_count = MIN(rg_info.hsp_num, SML_MAX_PHYSICAL_DRIVES);
    for (guint8 i = 0; i < pLDinfo->spare_count; i++) {
        pLDinfo->spare_pd_ids[i] = rg_info.hsp_disks[i].did;
        pLDinfo->spare_pd_slots[i] = rg_info.hsp_disks[i].slot_id;
        pLDinfo->spare_pd_enclosure_ids[i] = rg_info.hsp_disks[i].enc_id;
    }

    // 3、获取关联阵列（包括rg和sg）
    get_ld_ref_array(ctrl_id, target_id, pLDinfo, rg_id, &rg_info);

    // 4、不支持的字段赋无效值
    set_ld_properties_unsupported(pLDinfo);
    return SML_SUCCESS;
}

/*
 * Description: 获取逻辑盘的成员盘列表
 */
gint32 histore_get_ld_pd_list(guint32 ctrl_id, guint16 target_id, gpointer data)
{
    if (data == NULL) {
        return SML_ERR_NULL_DATA;
    }

    struct cmd_vd_info ld_info;
    (void)memset_s(&ld_info, sizeof(ld_info), 0, sizeof(ld_info));
    gint32 ret = get_vd_info_by_hash(ctrl_id, target_id, &ld_info);
    if (ret != SML_SUCCESS) {
        return ret;
    }

    struct cmd_rg_info rg_info;
    (void)memset_s(&rg_info, sizeof(rg_info), 0, sizeof(rg_info));
    ret = get_rg_info_by_hash(ctrl_id, (guint16)ld_info.rg_id, &rg_info);
    if (ret != SML_SUCCESS) {
        return ret;
    }

    SML_PD_LIST_S *pLDinfo = (SML_PD_LIST_S *)data;
    pLDinfo->pd_count = MIN(MIN(rg_info.member_disk_num, SML_MAX_PHYSICAL_DRIVES), CMD_MEMB_DISK_MAX_NUM);
    for (guint8 i = 0; i < pLDinfo->pd_count; i++) {
        pLDinfo->device_ids[i] = rg_info.disks[i].did;
    }

    return SML_SUCCESS;
}

/*
 * Description: 获取RAID组列表
 */
static gint32 get_rg_list(guint8 ctrl_id, struct cmd_rgs_id *rgs_id)
{
    struct lib_cmd_param lib_param;
    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    lib_param.opcode = ADM_RAID_READ;
    lib_param.subopcode = ADM_CMD_SHOW_RGS_ID;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.data = rgs_id;
    lib_param.data_len = (guint16)sizeof(struct cmd_rgs_id);
    return process_histore_cmd(&lib_param);
}

/*
 * Description: 获取硬盘阵列ID列表
 */
gint32 histore_get_ctrl_array_list(guint32 ctrl_id, gpointer data)
{
    if (data == NULL) {
        return SML_ERR_NULL_DATA;
    }

    struct cmd_rgs_id rgs_id;
    (void)memset_s(&rgs_id, sizeof(rgs_id), 0, sizeof(rgs_id));

    gint32 ret = get_rg_list(ctrl_id, &rgs_id);
    if (ret != SML_SUCCESS) {
        return ret;
    }

    if (rgs_id.num > SML_MAX_ARRAY) {
        return SML_ERR_DATA_INVALID;
    }

    SML_ARRAY_LIST_S *pArraylist = (SML_ARRAY_LIST_S *)data;

    guint16 i;
    for (i = 0; i < rgs_id.num; i++) {
        pArraylist->array_refs[i] = rgs_id.ids[i];  // 0 ~ rgs_id.num - 1留给rg
    }

    // 指定一个无效的LD ID，用于统计sg的总数
    guint16 sg_total_count = get_sg_total_count_behind(ctrl_id, STORAGE_INFO_INVALID_WORD);

    guint8 idx = rgs_id.num; // sg从rgs_id.num开始填
    for (i = 0; i < sg_total_count; i++) {
        if (idx >= SML_MAX_ARRAY) {
            break;    // 防越界
        }

        pArraylist->array_refs[idx++] = SUB_ARRAY_BIT | i;
    }

    guint8 array_count = rgs_id.num + sg_total_count;   // rg + sg的总个数
    pArraylist->array_count = MIN(array_count, SML_MAX_ARRAY);

    /* rg列表刷新，清除无效的rg缓存 */
    remove_invalid_rg_cache(ctrl_id, &rgs_id);
    return SML_SUCCESS;
}

/*
 * Description: 获取阵列关联物理盘
 */
static void get_array_ref_pd(SML_ARRAY_INFO_S *pArrayInfo, const struct cmd_rg_info *rg_info, guint8 sg_index,
    gboolean sub_flag)
{
    guint8 i;

    if (sub_flag) {
        guint8 j = 0;
        for (i = 0; i < rg_info->member_disk_num; i++) {
            if (rg_info->disks[i].sg_index != sg_index) {
                continue;
            }

            if (j >= SML_MAX_PHYSICAL_DRIVES_PER_ARRAY) {
                break;
            }
            pArrayInfo->pd_ids[j] = rg_info->disks[i].did;
            pArrayInfo->pd_slots[j] = rg_info->disks[i].slot_id;
            pArrayInfo->pd_enclosures[j] = rg_info->disks[i].enc_id;
            j++;
        }
        pArrayInfo->pd_count = j;
    } else {
        pArrayInfo->pd_count = MIN(rg_info->member_disk_num, SML_MAX_PHYSICAL_DRIVES_PER_ARRAY);
        for (i = 0; i < pArrayInfo->pd_count; i++) {
            pArrayInfo->pd_ids[i] = rg_info->disks[i].did;
            pArrayInfo->pd_slots[i] = rg_info->disks[i].slot_id;
            pArrayInfo->pd_enclosures[i] = rg_info->disks[i].enc_id;
        }
    }
    return;
}

/*
 * Description: 获取阵列容量
 */
static gint32 get_array_capacity(SML_ARRAY_INFO_S *pArrayInfo, struct cmd_rg_info *rg_info, gboolean sub_flag)
{
    guint8 div_num = (sub_flag ? rg_info->sg_num : 1); // 如果是rg，已使用容量和空闲容量按原值显示；如果是sg，除以sg的个数
    if (div_num == 0) {
        debug_log(DLOG_ERROR, "%s: sg_num = 0.", __FUNCTION__);
        return SML_ERR_DATA_INVALID;
    }
    pArrayInfo->used_space = (rg_info->total_capacity - rg_info->free_capacity) / div_num;
    pArrayInfo->total_free_space = rg_info->free_capacity / div_num;
    pArrayInfo->free_blocks_count = MIN(rg_info->free_block_num, SML_MAX_HOLES_IN_ARRAY);
    guint8 idx = 0;
    for (guint8 i = 0; i < rg_info->block_num; i++) {
        if (rg_info->block_info[i].used_flag != 0) { // 0表示空闲
            continue;
        }

        if (idx >= SML_MAX_HOLES_IN_ARRAY) {
            break;
        }
        pArrayInfo->free_blocks_space[idx++] = rg_info->block_info[i].capacity / div_num;
    }
    return SML_SUCCESS;
}

/*
 * Description: 获取硬盘阵列信息
 */
gint32 histore_get_array_info(guint32 ctrl_id, guint16 array_ref, gpointer data)
{
    if (data == NULL) {
        return SML_ERR_NULL_DATA;
    }

    guint16 rg_id = array_ref;
    guint8 sg_index = STORAGE_INFO_INVALID_BYTE;
    gboolean sub_flag = FALSE;

    // 解析id，如果标志位置位，按sg获取，否则按rg获取
    if (array_ref & SUB_ARRAY_BIT) {   // 按子组给
        SUB_GROUP_INDEX_S sg_idx_info = {0};
        if (find_data_from_hash_table(ctrl_id, array_ref, (gpointer)&sg_idx_info, sizeof(sg_idx_info),
            CACHE_TYPE_SG) != RET_OK) {
            debug_log(DLOG_ERROR, "%s: invalid array id = 0x%x", __FUNCTION__, array_ref);
            return SML_ERR_ARRAY_INVALID_ARRAY_REF;
        }
        rg_id = sg_idx_info.rg_id;
        sg_index = sg_idx_info.sg_index;
        sub_flag = TRUE;
    }

    struct cmd_rg_info rg_info;
    (void)memset_s(&rg_info, sizeof(rg_info), 0, sizeof(rg_info));
    gint32 ret = get_rg_info_by_hash(ctrl_id, rg_id, &rg_info);
    if (ret != SML_SUCCESS) {
        return ret;
    }

    // 获取关联ld
    SML_ARRAY_INFO_S *pArrayInfo = (SML_ARRAY_INFO_S *)data;
    pArrayInfo->ld_count = MIN(rg_info.vd_num, SML_MAX_LOGICAL_DRIVES_PER_ARRAY);
    for (guint8 i = 0; i < pArrayInfo->ld_count; i++) {
        pArrayInfo->ld_ids[i] = rg_info.vd_list[i];
    }

    // 获取关联pd
    get_array_ref_pd(pArrayInfo, &rg_info, sg_index, sub_flag);

    // 获取容量信息
    return get_array_capacity(pArrayInfo, &rg_info, sub_flag);
}

/*
 * Description: 填充通用参数
 */
static void fill_common_param(struct cmd_create_vd *vd_info, const SML_CREATE_LD_COMMON_PROPERTIES_S *prop)
{
#define STRIP_SIZE_DEFAULT      32  /* 条带大小默认值32KB */
    if (vd_info == NULL || prop == NULL) {
        return;
    }
    /* 名称，包含结束符 */
    if (strlen(prop->ld_name) == 0) {
        strcpy_s((gchar*)vd_info->name, sizeof(vd_info->name), STORAGE_INFO_INVALID_STRING);
    } else {
        (void)strncpy_s((gchar*)vd_info->name, sizeof(vd_info->name), prop->ld_name, sizeof(vd_info->name) - 1);
    }

    /* 逻辑盘大小，单位 MB，输入数据必须是整数，取值范围：16MB到RAID组剩余容量；全F表示全部剩余容量） */
    if (prop->capacity == STORAGE_INFO_INVALID_DWORD || prop->capacity == 0) {
        vd_info->size = STORAGE_INFO_INVALID_QWORD;  // 按默认容量创建，也就是最大值
    } else {
        vd_info->size = (guint64)prop->capacity;
    }
    /* 条带大小，单位KB，默认值32KB */
    if (prop->strip_size == STORAGE_INFO_INVALID_BYTE || prop->strip_size == 0) {
        vd_info->strip_unit_size = STRIP_SIZE_DEFAULT;  // 按默认条带大小创建
    } else {
        vd_info->strip_unit_size = pow(2, prop->strip_size - 1); // 以2为底进行转换
    }

    /* 初始化类型，fast：快速初始化（默认值），front：前台初始化，background：后台初始化 */
    if (prop->init_state == LD_INIT_STATE_FRONT) {
        vd_info->init = ADM_INIT_FRONT;
    } else if (prop->init_state == LD_INIT_STATE_BACKGROUND) {
        vd_info->init = ADM_INIT_BACKGROUND;
    } else {
        vd_info->init = ADM_INIT_FAST;
    }

    /* VD写cache策略 */
    vd_info->wcache = convert_to_wcache(prop->write_policy);

    /* VD预读策略 */
    vd_info->rcache = convert_to_rcache(prop->read_policy);

    /* SCSI: ADM_RAID_SCSI(0) NVMe : ADM_RAID_NVME(1) */
    vd_info->map_type = ADM_RAID_SCSI;

    /* VD冷热属性，默认值：无冷热属性 */
    vd_info->cold_hot = ADM_LUN_FREQ_NORMAL;

    /* 功能端口 */
    vd_info->pf = ADM_RAID_PF0;

    return;
}

/*
 * Description: 检查物理盘是否存在于rg
 */
static gboolean is_pd_in_rg(guint32 ctrl_id, guint16 device_id)
{
    gint32 ret;
    struct cmd_show_disk pd_info = { 0 };

    ret = get_pd_basic_info(ctrl_id, device_id, &pd_info);
    if (ret != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "[%s]: get_pd_basic_info fail ret %x ctrl_id %d device_id %d",
            __FUNCTION__, ret, ctrl_id, device_id);
        return FALSE;
    }

    if (pd_info.rg_id != STORAGE_INFO_INVALID_BYTE) {
        return TRUE;
    }
    return FALSE;
}

/*
 * Description: 填充在新阵列上创建逻辑盘的参数
 */
static gint32 fill_on_new_array_param(guint32 ctrl_id, struct cmd_create_vd *vd_info,
    SML_CREATE_LD_ON_NEW_ARRAY_S *ld_new_array)
{
    /* 是否指定RAID组ID */
    vd_info->rg_id_used = FALSE;

    /* RAID组ID */
    vd_info->rg_id = 0;

    /* vd所属RAID组级别 */
    vd_info->level = convert_to_raid_level(ld_new_array->raid_level);

    /* 成员物理磁盘数量 */
    vd_info->member_disk_num = ld_new_array->span_depth * ld_new_array->num_drive_per_span;

    /* 成员物理磁盘 */
    vd_info->locationtype = DISK_LOC_DID;
    gsize count = (gsize)G_N_ELEMENTS(vd_info->did);
    for (guint16 i = 0; i < vd_info->member_disk_num && i < count; i++) {
        vd_info->did[i] = ld_new_array->pd_sel[i];
        /* 检查物理盘是否已经存在于某rg下 */
        if (is_pd_in_rg(ctrl_id, vd_info->did[i])) {
            return SML_ERR_CONFIG_INVALID_PD_IN_USE;
        }
    }

    /* VD所属硬盘写Cache开关 */
    vd_info->disk_cache_sw = convert_to_dcp(ld_new_array->props.disk_cache_policy);

    if (ld_new_array->raid_level == RAID_LEVEL_50 || ld_new_array->raid_level == RAID_LEVEL_60) {
        /* RAID子组的成员盘数量 */
        vd_info->sg_disk_num = ld_new_array->num_drive_per_span;
    }

    return SML_SUCCESS;
}

/*
 * Description: 填充在已有阵列上创建逻辑盘的参数
 */
static void fill_on_existed_array_param(guint32 ctrl_id, struct cmd_create_vd *vd_info,
    const SML_CREATE_LD_ON_EXISTED_ARRAY_S *ld_existed_array)
{
    /* 是否指定RAID组ID */
    vd_info->rg_id_used = TRUE;

    /* RAID组ID */
    vd_info->rg_id = ld_existed_array->array_ref;

    /* vd所属RAID组级别 */
    vd_info->level = STORAGE_INFO_INVALID_BYTE;

    /* VD所属硬盘写Cache开关 */
    vd_info->disk_cache_sw = STORAGE_INFO_INVALID_BYTE;

    /* 成员物理磁盘数量需要置0 */
    vd_info->member_disk_num = 0;

    return;
}

/*
 * Description: 创建逻辑盘
 */
static gint32 create_ld(guint32 ctrl_id, struct cmd_create_vd *vd_info)
{
    struct lib_cmd_param lib_param;
    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    lib_param.opcode = ADM_RAID_SET;
    lib_param.subopcode = ADM_CMD_CREATE_VD;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.param_len = (guint16)sizeof(struct cmd_create_vd);
    lib_param.p_param = vd_info;
    lib_param.timeout_ms = HISTORE_CMD_TIMEOUT_MAX; /* 创lun超时时间60s */
    return process_histore_cmd(&lib_param);
}

/*
 * Description: 删除逻辑盘
 */
static gint32 delete_ld(guint32 ctrl_id, guint16 target_id)
{
    struct lib_cmd_param lib_param;
    struct cmd_del_vd del_vd;

    (void)memset_s(&del_vd, sizeof(del_vd), 0, sizeof(del_vd));
    del_vd.loc.vd_id = target_id;
    del_vd.discardcache = ADM_CACHE_METHOD_DEFAULT;

    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    lib_param.opcode = ADM_RAID_SET;
    lib_param.subopcode = ADM_CMD_DELETE_VD;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.param_len = (guint16)sizeof(struct cmd_del_vd);
    lib_param.timeout_ms = HISTORE_CMD_TIMEOUT_MAX; /* 删lun超时时间60s */
    errno_t securec_rv = memcpy_s(lib_param.cmd_param, sizeof(lib_param.cmd_param), &del_vd, sizeof(struct cmd_del_vd));
    if (securec_rv != EOK) {
        debug_log(DLOG_ERROR, "%s: memcpy_s failed, ret = %d", __FUNCTION__, securec_rv);
    }
    return process_histore_cmd(&lib_param);
}

/*
 * Description: 设置启动盘
 */
static gint32 set_boot_status(guint32 ctrl_id, guint16 target_id, guint8 boot_status)
{
    struct lib_cmd_param lib_param;
    struct cmd_vd_boot vd_boot;

    (void)memset_s(&vd_boot, sizeof(vd_boot), 0, sizeof(vd_boot));
    vd_boot.loc.vd_id = target_id;
    vd_boot.boot_status = boot_status;

    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    lib_param.opcode = ADM_RAID_SET;
    lib_param.subopcode = ADM_CMD_SET_VD_BOOT;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.param_len = (guint16)sizeof(struct cmd_vd_boot);
    errno_t securec_rv = memcpy_s(lib_param.cmd_param, sizeof(lib_param.cmd_param), &vd_boot,
                                  sizeof(struct cmd_vd_boot));
    if (securec_rv != EOK) {
        debug_log(DLOG_ERROR, "%s: memcpy_s failed, ret = %d", __FUNCTION__, securec_rv);
    }

    return process_histore_cmd(&lib_param);
}

/*
 * Description: 设置逻辑盘属性
 */
static gint32 set_ld_properties(guint32 ctrl_id, struct cmd_set_vd_attr *vd_attr)
{
    struct lib_cmd_param lib_param;

    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    lib_param.opcode = ADM_RAID_SET;
    lib_param.subopcode = ADM_CMD_SET_VD_ATTR;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.param_len = (guint16)sizeof(struct cmd_set_vd_attr);
    lib_param.p_param = vd_attr;
    return process_histore_cmd(&lib_param);
}

/*
 * Description: 设置指定逻辑盘的启动优先级
 */
static gint32 set_boot_priority(guint32 ctrl_id, guint16 target_id, guint8 boot_priority)
{
    guint8 boot_status;

    if (boot_priority == BOOT_PRIORITY_NONE) {
        boot_status = CMD_BOOT_OFF;
    } else if (boot_priority == BOOT_PRIORITY_PRIMARY) {
        boot_status = CMD_BOOT_ON;
    } else {
        debug_log(DLOG_ERROR, "%s:invalid boot priority = %d", __FUNCTION__, boot_priority);
        return SML_ERR_DATA_INVALID;
    }

    gint32 ret = set_boot_status(ctrl_id, target_id, boot_status);
    if (ret != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "%s:Set VD as boot drive failed, target id = %d, return 0x%0x ",
            __FUNCTION__, target_id, ret);
    } else {
        /* 由于启动盘是全局联动属性，清除所有vd的cache可读次数，使得下次轮询周期获取底层信息 */
        clear_vd_cache_read_count_all(ctrl_id);
    }

    return ret;
}

/*
 * Description: 设置逻辑盘属性
 */
static gint32 set_ld_prop(guint32 ctrl_id, guint16 target_id, SML_LD_SET_PROPERTIES_S *properties)
{
    struct cmd_set_vd_attr vd_attr;

    (void)memset_s(&vd_attr, sizeof(vd_attr), 0, sizeof(vd_attr));

    if ((properties->setting_options & LD_PROP_SETTING_NAME) != 0) {
        vd_attr.type = VD_ATTR_NAME;
        (void)strncpy_s((gchar*)vd_attr.name, sizeof(vd_attr.name), properties->ld_name,
            sizeof(vd_attr.name) - 1);
    }

    if ((properties->setting_options & LD_PROP_SETTING_WRITE_POLICY) != 0) {
        vd_attr.type = VD_ATTR_WCACHE;
        vd_attr.value = (guint32)convert_to_wcache(properties->write_policy);
    }

    if ((properties->setting_options & LD_PROP_SETTING_READ_POLICY) != 0) {
        vd_attr.type = VD_ATTR_RCACHE;
        vd_attr.value = (guint32)convert_to_rcache(properties->read_policy);
    }

    vd_attr.loc.vd_id = target_id;

    gint32 ret = set_ld_properties(ctrl_id, &vd_attr);
    if (ret != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "%s:Set VD property failed, target id = %d, type = %d, return 0x%0x ",
            __FUNCTION__, target_id, vd_attr.type, ret);
    } else {
        clear_vd_cache_read_count(ctrl_id, target_id);
    }

    return ret;
}

/*
 * Description: 查找指定逻辑盘id是否存在于vd列表
 */
static gboolean is_ld_id_exist(guint16 ld_id, struct cmd_vds_id *vd_list)
{
    for (guint16 i = 0; i < vd_list->num && i < VDS_ID_NODE_NUM; i++) {
        if (ld_id == vd_list->ids[i]) {
            return TRUE;
        }
    }

    return FALSE;
}

/*
 * Description: 获取新的逻辑盘id
 */
static guint16 get_new_ld_id(guint32 ctrl_id, struct cmd_vds_id *vd_list)
{
    struct cmd_vds_id new_vd_list;

    (void)memset_s(&new_vd_list, sizeof(new_vd_list), 0, sizeof(new_vd_list));
    gint32 ret = get_vd_list(ctrl_id, &new_vd_list);
    if (ret != SML_SUCCESS) {
        return STORAGE_INFO_INVALID_WORD;
    }

    if ((vd_list->num + 1) != new_vd_list.num) {
        return STORAGE_INFO_INVALID_WORD;
    }

    for (guint16 i = 0; i < new_vd_list.num && i < VDS_ID_NODE_NUM; i++) {
        if (is_ld_id_exist(new_vd_list.ids[i], vd_list) == FALSE) {
            return new_vd_list.ids[i];
        }
    }

    return STORAGE_INFO_INVALID_WORD;
}

/*
 * Description: RAID配置相关操作
 */
gint32 histore_config_operations(guint32 ctrl_id, guint8 operation, gpointer param, guint32 param_length)
{
    struct cmd_create_vd vd_info;
    gint32 ret;

    (void)memset_s(&vd_info, sizeof(vd_info), 0, sizeof(vd_info));

    SML_CREATE_LD_COMMON_PROPERTIES_S *prop = NULL;
    SML_CREATE_LD_RETURN_PARAM_S *ret_param = NULL;
    SML_CREATE_LD_ON_NEW_ARRAY_S *ld_new_array = (SML_CREATE_LD_ON_NEW_ARRAY_S *)param;
    SML_CREATE_LD_ON_EXISTED_ARRAY_S *ld_existed_array = (SML_CREATE_LD_ON_EXISTED_ARRAY_S *)param;

    if ((param == NULL) || (param_length == 0)) {
        return SML_ERR_NULL_DATA;
    }

    if (operation == CONFIG_OPERATION_CREATE_LD_ON_NEW_ARRAY) {
        /* 匹配其他RAID行为，剩余空间创lun只允许传一个pd下来 */
        ret = fill_on_new_array_param(ctrl_id, &vd_info, ld_new_array);
        if (ret != SML_SUCCESS) {
            return ret;
        }
        prop = &ld_new_array->props;
        ret_param = &ld_new_array->ret_param;
    } else if (operation == CONFIG_OPERATION_CREATE_LD_ON_EXISTED_ARRAY) {
        fill_on_existed_array_param(ctrl_id, &vd_info, ld_existed_array);
        prop = &ld_existed_array->props;
        ret_param = &ld_existed_array->ret_param;
    } else if (operation == CONFIG_OPERATION_CREATE_CACHECADE_LD) {
        debug_log(DLOG_ERROR, "%s: cachecade not supported", __FUNCTION__);
        return SML_ERR_CONFIG_OPERATION_NOT_SUPPORT;
    }

    struct cmd_vds_id vd_list;
    (void)memset_s(&vd_list, sizeof(vd_list), 0, sizeof(vd_list));
    ret = get_vd_list(ctrl_id, &vd_list);
    if (ret != SML_SUCCESS) {
        return ret;
    }

    fill_common_param(&vd_info, prop);

    ret = create_ld(ctrl_id, &vd_info);
    if (ret == SML_SUCCESS) {
        /* 获取ld_id */
        if (ret_param == NULL) {
            return SML_ERR_NULL_DATA;
        }
        ret_param->ld_target_id = get_new_ld_id(ctrl_id, &vd_list);
    }

    return ret;
}

/*
 * Description: 逻辑盘相关操作
 */
gint32 histore_ld_operations(guint32 ctrl_id, guint16 target_id, guint8 operation, gpointer param,
    guint32 param_length)
{
    gint32 ret;

    switch (operation) {
        case LD_OPERATION_DELETE:
            ret = delete_ld(ctrl_id, target_id);
            break;
        case LD_OPERATION_SET_BOOTABLE:
            if (param == NULL) {
                return SML_ERR_NULL_DATA;
            }
            ret = set_boot_priority(ctrl_id, target_id, *(guint8 *)param);
            break;
        case LD_OPERATION_SET_PROPERTIES:
            if ((param == NULL) || (param_length == 0)) {
                return SML_ERR_NULL_DATA;
            }
            SML_LD_SET_PROPERTIES_S *properties = (SML_LD_SET_PROPERTIES_S *)param;
            ret = set_ld_prop(ctrl_id, target_id, properties);
            break;
        default:
            ret = SML_ERR_LD_OPERATION_NOT_SUPPORT;
            break;
    }

    return ret;
}

