/* 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 <sys/file.h>
#include <stdio.h>
#include "sml_errcodes.h"
#include "sml.h"

/* 本模块头文件 */
#include "pd_log_process.h"
#include "sata_log.h"
#include "sas_log.h"
#include "utils/file_securec.h"
#include "diagnose_defs.h"
#include "io_deterioration_log_process.h"
#define IO_DETERIORATION_LOG_PATH "/var/log/storage/IODeterioration"

/* ----------------------------------------------*
 * 宏定义                                       *
 * ---------------------------------------------- */
#define MAGNETIC_HEAD_NUM 24

#define PD_LOG_COLLECT_INTERVAL (24 * 60 * 60)  // 硬盘日志收集的默认间隔时间24h
#define PD_LOG_COLLECT_TIMEOUT (180 * 1000)     // 单个日志数据收集的超时时间180s

#define YEAR_1900      1900
#define LOG_PAGE_SECTOR_NUM 32
#define FARM_LOG_RAW_MASK 0x00FFFFFFFFFFFFFFUL
#define FARM_LOG_PARAM_LENGTH 24
#define BER_DECIMAL_MASK 0X00000000FFFFFFFFUL
#define BER_DECIMAL_MULTIPLE 10000
#define BER_INTEGER_MASK 0X0000FFFF00000000UL
#define BER_INTEGER_OFFSET 32
#define FH_INTEGER_OFFSET 8


typedef enum TAG_SAS_ERROR_COUNTER_TYPE {
    SAS_ERROR_COUNTER_TYPE_READ = 0,
    SAS_ERROR_COUNTER_TYPE_WRITE,
    SAS_ERROR_COUNTER_TYPE_VERIFY,
    SAS_ERROR_COUNTER_TYPE_NONMEDIUM,
} SAS_ERROR_COUNTER_TYPE;

typedef struct TAG_IO_DETERIORATION_DIAG_SEAGATE_INFO {
    gdouble cur_ber[MAGNETIC_HEAD_NUM];
    guint16 cur_fh_outer[MAGNETIC_HEAD_NUM];
    guint16 cur_fh_inner[MAGNETIC_HEAD_NUM];
    guint16 cur_fh_middle[MAGNETIC_HEAD_NUM];
    guint16 cur_mr[MAGNETIC_HEAD_NUM];
    guint16 fac_mr[MAGNETIC_HEAD_NUM];
} IO_DETERIORATION_DIAG_SEAGATE_INFO;

typedef struct farm_descripe {
    gchar *desc;
    guint32 offset;
    guint32 size;
} FARM_DESCRIPE;

LOCAL const FARM_DESCRIPE g_farm_descripe_table[] = {
    // farm log page 2
    {
        "Total Number of Read Commands",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, read_cmd_num),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->read_cmd_num)
    }, {
        "Total Number of Write Commands",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, write_cmd_num),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->write_cmd_num)
    }, {
        "Total Number of Random Read Commands",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, random_read_cmd_num),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->random_read_cmd_num)
    }, {
        "Total Number of Random Write Commands",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, random_write_cmd_num),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->random_write_cmd_num)
    }, {
        "Total Number Of Other Commands",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, other_cmd_num),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->other_cmd_num)
    }, {
        "Logical Sectors Written",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, logic_sector_written),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->logic_sector_written)
    }, {
        "Logical Sectors Read",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, logic_sector_read),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->logic_sector_read)
    },
    // farm log page 3
    {
        "Number of Unrecoverable Read Errors",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, unrecover_read_errors),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->unrecover_read_errors)
    }, {
        "Number of Unrecoverable Write Errors",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, unrecover_write_errors),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->unrecover_write_errors)
    }, {
        "Number of Reallocated Sectors",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, reallocated_sectors),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->reallocated_sectors)
    }, {
        "Number of Read Recovery Attempts",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, read_recovery_attempts),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->read_recovery_attempts)
    }, {
        "Number of Mechanical Start Failures",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, mechanical_start_failures),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->mechanical_start_failures)
    }, {
        "Number of Reallocation Candidate Sectors",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, reallocated_candidate_sectors),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->reallocated_candidate_sectors)
    }, {
        "Number of ASR Events",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, asr_events),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->asr_events)
    }, {
        "Number of Interface CRC Errors",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, interface_crc_errors),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->interface_crc_errors)
    }, {
        "Spin Retry Count (Most recent value from array at byte 401 of attribute sector)",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, spin_retry_count),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->spin_retry_count)
    }, {
        "Spin Retry Count (SMART Attribute 10 Normalized)",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, spin_retry_count_normalized),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->spin_retry_count_normalized)
    }, {
        "Spin Retry Count (SMART Attribute 10 Worst Ever)",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, spin_retry_count_worst),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->spin_retry_count_worst)
    }, {
        "Number of IOEDC Errors (SMART Attribute 184 Raw)",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, ioedc_errors),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->ioedc_errors)
    }, {
        "CTO Count Total (SMART Attribute 188 Raw[0..1]) ",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, cto_total),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->cto_total)
    }, {
        "CTO Count Over 5s (SMART Attribute 188 Raw[2..3])",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, cto_over_5s),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->cto_over_5s)
    }, {
        "CTO Count Over 7.5s (SMART Attribute 188 Raw[4..5])",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, cto_over_7_5s),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->cto_over_7_5s)
    }, {
        "Total Flash LED (Assert) Events",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, flash_led_events),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->flash_led_events)
    }, {
        "Uncorrectable errors (SMART Attribute 187 Raw) (SATA Only)",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, uncorrectable_errors),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->uncorrectable_errors)
    },
    // farm log page 4
    {
        "High Fly Write Count (SMART Attribute 189 Raw)",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, high_fly_write_count),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->high_fly_write_count)
    },
    // farm log page 5
    {
        "Magnitude of Disc Slip in micro-inches by Head",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, disc_slip_micro_inches),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->disc_slip_micro_inches)
    }, {
        "Bit Error Rate of Zone 0 by Drive Head",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, bit_error_rate_zone),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->bit_error_rate_zone)
    }, {
        "Servo Status",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, glist_reclamations_num),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->glist_reclamations_num)
    }, {
        "Servo Status",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, servo_status),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->servo_status)
    }, {
        "Number of Slipped Sectors Before IDD Scan",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, alts_list_before_idd),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->alts_list_before_idd)
    }, {
        "Number of Slipped Sectors After IDD Scan",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, alts_list_after_idd),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->alts_list_after_idd)
    }, {
        "Number of Resident Reallocated Sectors Before IDD Scan",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, resident_glist_before_idd),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->resident_glist_before_idd)
    }, {
        "Number of Resident Reallocated Sectors After IDD Scan",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, resident_glist_after_idd),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->resident_glist_after_idd)
    }, {
        "Number of Successfully Scrubbed Sectors Before IDD Scan",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, scrubs_list_before_idd),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->scrubs_list_before_idd)
    }, {
        "Number of Successfully Scrubbed Sectors After IDD Scan",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, scrubs_list_after_idd),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->scrubs_list_after_idd)
    }, {
        "Number of DOS Scans Performed",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, dos_scans_performed_num),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->dos_scans_performed_num)
    }, {
        "Number of LBAs Corrected by ISP",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, lbas_corrected_by_isp_num),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->lbas_corrected_by_isp_num)
    }, {
        "Number of Valid Parity Sectors",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, valid_parity_sectors_num),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->valid_parity_sectors_num)
    }, {
        "DOS Write Refresh Count",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, dos_write_refresh_count),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->dos_write_refresh_count)
    }, {
        "Number of RAW Operations",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, raw_operations_num),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->raw_operations_num)
    }, {
        "DVGA Skip Write Detect by Head7",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, dvga_skip_write_detect),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->dvga_skip_write_detect)
    }, {
        "RVGA Skip Write Detect by Head",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, rvga_skip_write_detect),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->rvga_skip_write_detect)
    }, {
        "FVGA Skip Write Detect by Head",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, fvga_skip_write_detect),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->fvga_skip_write_detect)
    }, {
        "Skip Write Detect Threshold Exceeded Count by Head",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, skip_write_detect_thred),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->skip_write_detect_thred)
    }, {
        "Error Rate (SMART Attribute 1 Raw)",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, error_rate_raw),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->error_rate_raw)
    }, {
        "MicroActuator Lock-out, head mask accumulated over last 3 Summary Frames",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, micro_actuator_lockout_accumulated),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->micro_actuator_lockout_accumulated)
    }, {
        "ACFF Sine 1X, value from most recent SMART Summary Frame by Head",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, acff_sine_1x),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->acff_sine_1x)
    }, {
        "ACFF Cosine 1X, value from most recent SMART Summary Frame by Head",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, acff_cosine_1x),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->acff_cosine_1x)
    }, {
        "PZT Calibration, value from most recent SMART Summary Frame by Head",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, pzt_calibration),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->pzt_calibration)
    }, {
        "MR Head Resistance from most recent SMART Summary Frame by Head",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, mr_head_resistance),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->mr_head_resistance)
    }, {
        "Number of TMD over last 3 SMART Summary Frames by Head",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, tmd_num),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->tmd_num)
    }, {
        "Velocity Observer over last 3 SMART Summary Frames by Head",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, velocity_observer),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->velocity_observer)
    }, {
        "Number of Velocity Observer over last 3 SMART Summary Frames by Head",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, velocity_observer_num),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->velocity_observer_num)
    }, {
        "Current H2SAT trimmed mean bits in error by Head, by Test Zone 0",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, current_h2sat_trimmed_mean_zone_0),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->current_h2sat_trimmed_mean_zone_0)
    }, {
        "Current H2SAT trimmed mean bits in error by Head, by Test Zone 1",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, current_h2sat_trimmed_mean_zone_1),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->current_h2sat_trimmed_mean_zone_1)
    }, {
        "Current H2SAT trimmed mean bits in error by Head, by Test Zone 2",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, current_h2sat_trimmed_mean_zone_2),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->current_h2sat_trimmed_mean_zone_2)
    }, {
        "Current H2SAT iterations to converge by Head, by Test Zone 0",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, current_h2sat_iterations_zone_0),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->current_h2sat_iterations_zone_0)
    }, {
        "Current H2SAT iterations to converge by Head, by Test Zone 1",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, current_h2sat_iterations_zone_1),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->current_h2sat_iterations_zone_1)
    }, {
        "Current H2SAT iterations to converge by Head, by Test Zone 2",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, current_h2sat_iterations_zone_2),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->current_h2sat_iterations_zone_2)
    }, {
        "Current H2SAT percentage of codewords at iteration level by Head, averaged across Test Zones",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, current_h2sat_percentage_codewords),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->current_h2sat_percentage_codewords)
    }, {
        "Current H2SAT amplitude by Head, averaged across Test Zones",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, h2sat_amplitude),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->h2sat_amplitude)
    }, {
        "Current H2SAT asymmetry by Head, averaged across Test Zones",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, h2sat_asymmetry),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->h2sat_asymmetry)
    }, {
        "Applied fly height clearance delta per head in thousandths of one Angstrom outer",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, flyheight_clearance_delta_outer),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->flyheight_clearance_delta_outer)
    }, {
        "Applied fly height clearance delta per head in thousandths of one Angstrom inner",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, flyheight_clearance_delta_inner),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->flyheight_clearance_delta_inner)
    }, {
        "Applied fly height clearance delta per head in thousandths of one Angstrom middle",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, flyheight_clearance_delta_middle),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->flyheight_clearance_delta_middle)
    }, {
        "Number of disc slip recalibrations performed",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, disc_slip_recalibration_performed),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->disc_slip_recalibration_performed)
    }, {
        "Second MR Head resistance per head for MSMR",
        G_STRUCT_OFFSET(IO_DETERIORATION_DIAG_SEA_LOG_PARAM, second_mr_head_resistance),
        sizeof(((IO_DETERIORATION_DIAG_SEA_LOG_PARAM*)0)->second_mr_head_resistance)
    }
};
/* ----------------------------------------------*
 * 内部函数原型说明                             *
 * ---------------------------------------------- */

/*
 * 函 数 名  : get_farm_log_page5_data
 * 功能描述  : 获取farm log page 5信息
 */
static void get_farm_log_page5_data(
    IO_DETERIORATION_DIAG_SEA_LOG_PARAM *diag_param, ATA_SEAGATE_FARM_RELIA_STAT_S *relia)
{
#define ZONE_INDEX 0
#define ONE_INDEX 1
#define TWO_INDEX 2
    diag_param->glist_reclamations_num = relia->GListReclamationsNum & FARM_LOG_RAW_MASK;
    diag_param->servo_status = relia->servoStatus & FARM_LOG_RAW_MASK;
    diag_param->alts_list_before_idd = relia->altsListBeforeIDD & FARM_LOG_RAW_MASK;
    diag_param->alts_list_after_idd = relia->altsListAfterIDD & FARM_LOG_RAW_MASK;
    diag_param->resident_glist_before_idd = relia->residentGlistBeforeIDD & FARM_LOG_RAW_MASK;
    diag_param->resident_glist_after_idd = relia->residentGlistAfterIDD & FARM_LOG_RAW_MASK;
    diag_param->scrubs_list_before_idd = relia->scrubsListBeforeIDD & FARM_LOG_RAW_MASK;
    diag_param->scrubs_list_after_idd = relia->scrubsListAfterIDD & FARM_LOG_RAW_MASK;
    diag_param->dos_scans_performed_num = relia->DOSScansPerformedNum & FARM_LOG_RAW_MASK;
    diag_param->lbas_corrected_by_isp_num = relia->LBAsCorrectedByISPNum & FARM_LOG_RAW_MASK;
    diag_param->valid_parity_sectors_num = relia->validParitySectorsNum & FARM_LOG_RAW_MASK;
    diag_param->raw_operations_num = relia->RAWOperationsNum & FARM_LOG_RAW_MASK;
    diag_param->error_rate_raw = relia->errorRateRaw & FARM_LOG_RAW_MASK;
    diag_param->micro_actuator_lockout_accumulated = relia->microActuatorLockoutAccumulated & FARM_LOG_RAW_MASK;
    diag_param->disc_slip_recalibration_performed = relia->discSlipRecalibrationPerformed & FARM_LOG_RAW_MASK;

    for (guint8 idx = 0; idx < FARM_LOG_PARAM_LENGTH; idx++) {
        diag_param->disc_slip_micro_inches[idx] = relia->discSlip[idx];
        diag_param->bit_error_rate_zone[idx] = relia->errorRateOfZone0[idx];
        diag_param->dos_write_refresh_count[idx] = relia->DOSWriteRefreshCount[idx];
        diag_param->dvga_skip_write_detect[idx] = relia->DVGASkipWriteDetect[idx];
        diag_param->rvga_skip_write_detect[idx] = relia->RVGASkipWriteDetect[idx];
        diag_param->fvga_skip_write_detect[idx] = relia->FVGASkipWriteDetect[idx];
        diag_param->skip_write_detect_thred[idx] = relia->skipWriteDetectThred[idx];
        diag_param->acff_sine_1x[idx] = relia->ACFFSine1X[idx];
        diag_param->acff_cosine_1x[idx] = relia->ACFFCosine1X[idx];
        diag_param->pzt_calibration[idx] = relia->PZTCalibration[idx];
        diag_param->mr_head_resistance[idx] = relia->MRHeadResistance[idx];
        diag_param->tmd_num[idx] = relia->TMDNum[idx];
        diag_param->velocity_observer[idx] = relia->velocityObserver[idx];
        diag_param->velocity_observer_num[idx] = relia->velocityObserverNum[idx];
        diag_param->current_h2sat_trimmed_mean_zone_0[idx] =
            relia->currentH2SATTrimmedMeanBitsInError[idx][ZONE_INDEX];
        diag_param->current_h2sat_trimmed_mean_zone_1[idx] = relia->currentH2SATTrimmedMeanBitsInError[idx][ONE_INDEX];
        diag_param->current_h2sat_trimmed_mean_zone_2[idx] = relia->currentH2SATTrimmedMeanBitsInError[idx][TWO_INDEX];
        diag_param->current_h2sat_iterations_zone_0[idx] = relia->currentH2SATIterationsToConverge[idx][ZONE_INDEX];
        diag_param->current_h2sat_iterations_zone_1[idx] = relia->currentH2SATIterationsToConverge[idx][ONE_INDEX];
        diag_param->current_h2sat_iterations_zone_2[idx] = relia->currentH2SATIterationsToConverge[idx][TWO_INDEX];
        diag_param->current_h2sat_percentage_codewords[idx] = relia->currentH2SATCodewordsAtIterationLevel[idx];
        diag_param->h2sat_amplitude[idx] = relia->H2SATAmplitude[idx];
        diag_param->h2sat_asymmetry[idx] = relia->H2SATAsymmetry[idx];
        diag_param->flyheight_clearance_delta_outer[idx] = relia->flyheightClearanceDelta[idx][ZONE_INDEX];
        diag_param->flyheight_clearance_delta_inner[idx] = relia->flyheightClearanceDelta[idx][ONE_INDEX];
        diag_param->flyheight_clearance_delta_middle[idx] = relia->flyheightClearanceDelta[idx][TWO_INDEX];
        diag_param->second_mr_head_resistance[idx] = relia->SecondMRHeadResistance[idx];
    }
}

/*
 * 函 数 名  : get_farm_log_data
 * 功能描述  : 慢盘检测从farm_log获取Seagate物理盘数据
 */
gint32 get_farm_log_data(SML_PD_LOG_DATA_S *farm_log, IO_DETERIORATION_DIAG_SEA_LOG_PARAM *diag_param)
{
    if (farm_log->result != SML_SUCCESS || farm_log->data == NULL || farm_log->data_length == 0) {
        debug_log(DLOG_ERROR, "%s: Can not get farm_log", __FUNCTION__);
        return RET_ERR;
    }
    // 每个log_page的size为32个sector，每个sector为512字节
    const guint32 page_size = LOG_PAGE_SECTOR_NUM * PD_BLOCK_SIZE_512;
    if (farm_log->data_length < page_size * 5 + sizeof(ATA_SEAGATE_FARM_RELIA_STAT_S)) {
        debug_log(DLOG_ERROR, "%s: farm log data_length:%u smaller than parse_length:%u", __FUNCTION__,
            farm_log->data_length, page_size * 5);
        return RET_ERR;
    }
    ATA_SEAGATE_FARM_WORKLOAD_STAT_S *work_load = (ATA_SEAGATE_FARM_WORKLOAD_STAT_S *)(farm_log->data + page_size * 2);
    ATA_SEAGATE_FARM_ERROR_STAT_S *error = (ATA_SEAGATE_FARM_ERROR_STAT_S *)(farm_log->data + page_size * 3);
    ATA_SEAGATE_FARM_ENV_STAT_S *env = (ATA_SEAGATE_FARM_ENV_STAT_S *)(farm_log->data + page_size * 4);
    ATA_SEAGATE_FARM_RELIA_STAT_S *relia = (ATA_SEAGATE_FARM_RELIA_STAT_S *)(farm_log->data + page_size * 5);

    // farm log page 2
    diag_param->read_cmd_num = work_load->readCmdNum & FARM_LOG_RAW_MASK;
    diag_param->write_cmd_num = work_load->writeCmdNum & FARM_LOG_RAW_MASK;
    diag_param->random_read_cmd_num = work_load->rReadCmdNum & FARM_LOG_RAW_MASK;
    diag_param->random_write_cmd_num = work_load->rWriteCmdNum & FARM_LOG_RAW_MASK;
    diag_param->other_cmd_num = work_load->otherCmdNum & FARM_LOG_RAW_MASK;
    diag_param->logic_sector_written = work_load->lSectorWritten & FARM_LOG_RAW_MASK;
    diag_param->logic_sector_read = work_load->lSectorRead & FARM_LOG_RAW_MASK;
    // farm log page 3
    diag_param->unrecover_read_errors = error->unrecoverReadErrors & FARM_LOG_RAW_MASK;
    diag_param->unrecover_write_errors = error->unrecoverWriteErrors & FARM_LOG_RAW_MASK;
    diag_param->reallocated_sectors = error->reallocatedSectors & FARM_LOG_RAW_MASK;
    diag_param->read_recovery_attempts = error->readRecoveryAttempts & FARM_LOG_RAW_MASK;
    diag_param->mechanical_start_failures = error->mechanicalStartFailures & FARM_LOG_RAW_MASK;
    diag_param->reallocated_candidate_sectors = error->reallocatedCandidateSectors & FARM_LOG_RAW_MASK;
    diag_param->asr_events = error->ASREvents & FARM_LOG_RAW_MASK;
    diag_param->interface_crc_errors = error->interfaceCRCErrors & FARM_LOG_RAW_MASK;
    diag_param->spin_retry_count = error->spinRetryCount & FARM_LOG_RAW_MASK;
    diag_param->spin_retry_count_normalized = error->spinRetryCountNormalized & FARM_LOG_RAW_MASK;
    diag_param->spin_retry_count_worst = error->spinRetryCountWorst & FARM_LOG_RAW_MASK;
    diag_param->ioedc_errors = error->IOEDCErrors & FARM_LOG_RAW_MASK;
    diag_param->cto_total = error->CTOTotal & FARM_LOG_RAW_MASK;
    diag_param->cto_over_5s = error->CTOOver5s & FARM_LOG_RAW_MASK;
    diag_param->cto_over_7_5s = error->CTOOver7_5s & FARM_LOG_RAW_MASK;
    diag_param->flash_led_events = error->flashLEDEvents & FARM_LOG_RAW_MASK;
    diag_param->uncorrectable_errors = error->uncorrectableErrors & FARM_LOG_RAW_MASK;
    // farm log page 4
    diag_param->high_fly_write_count = env->highFlyWriteCount & FARM_LOG_RAW_MASK;
    // farm log page 5
    get_farm_log_page5_data(diag_param, relia);
    return RET_OK;
}

/*
 * 函 数 名  : io_deterioration_handle_get_farm_log_data
 * 功能描述  : 慢盘检测从farm_log获取Seagate物理盘数据
 */
static gint32 io_deterioration_handle_get_farm_log_data(PD_LOG_S *pd_log, IO_DETERIORATION_PD_INFO *pd_info)
{
    if (pd_log_check_cur_farm_supported(pd_log) == FALSE) {
        return RET_OK;
    }
    gint32 ret = get_farm_log_data(&pd_log->SATADevice.seagate_farm, &pd_info->log.sea_param);
    if (ret != RET_OK) {
        debug_log(DLOG_ERROR, "%s: get farm log failed", __FUNCTION__);
        return RET_ERR;
    }

    // 获取factory farm log
    gboolean is_support = pd_log_check_factory_farm_supported(pd_log);
    gboolean is_collect_fail = pd_log->SATADevice.seagate_factory_farm.result != SML_SUCCESS ||
                               pd_log->SATADevice.seagate_factory_farm.data == NULL ||
                               pd_log->SATADevice.seagate_factory_farm.data_length == 0;
    if (is_support && !is_collect_fail) {
        pd_info->factory_farm_state = FACTORY_FARM_LOG_SUPPORT_COLLECT_DATA;
        gint32 ret = get_farm_log_data(&pd_log->SATADevice.seagate_factory_farm, &pd_info->log.sea_factory_param);
        if (ret != RET_OK) {
            debug_log(DLOG_ERROR, "%s: get factory farm log failed", __FUNCTION__);
            return RET_ERR;
        }
    }

    return RET_OK;
}

/*
 * 函 数 名  : io_deterioration_handle_type_convert
 * 功能描述  : 通过type获取标准
 */
static gint32 io_deterioration_handle_type_convert(
    guint8 *error_cnt_std, gchar *error_type, guint8 buff_len, guint8 type)
{
    switch (type) {
        case SAS_ERROR_COUNTER_TYPE_READ:
            *error_cnt_std = SCSI_LOG_PAGE_READ_ERROR_COUNTER;
            (void)strcpy_s(error_type, buff_len, "Read");
            break;
        case SAS_ERROR_COUNTER_TYPE_WRITE:
            *error_cnt_std = SCSI_LOG_PAGE_WRITE_ERROR_COUNTER;
            (void)strcpy_s(error_type, buff_len, "Write");
            break;
        case SAS_ERROR_COUNTER_TYPE_VERIFY:
            *error_cnt_std = SCSI_LOG_PAGE_VERIFY_ERROR_COUNTER;
            (void)strcpy_s(error_type, buff_len, "Verify");
            break;
        case SAS_ERROR_COUNTER_TYPE_NONMEDIUM:
            *error_cnt_std = SCSI_LOG_PAGE_NON_MEDIUM_ERROR;
            (void)strcpy_s(error_type, buff_len, "Non Medium");
            break;
        default:
            debug_log(DLOG_ERROR, "Invalid error_cnt_type!");
            return RET_ERR;
    }
    return RET_OK;
}

/*
 * 函 数 名  : io_deterioration_handle_divide_sas_data
 * 功能描述  : 将SAS物理盘数据中的read\write\verify的error count按照是否修正进行拆分
 */
static gint32 io_deterioration_handle_divide_sas_data(SML_PD_LOG_DATA_S *error_cnt, guint8 type, gpointer error_arr)
{
    guint8 error_cnt_std = 0;
    gchar error_type[TMP_STR_LEN] = {0};
    if (io_deterioration_handle_type_convert(&error_cnt_std, error_type, sizeof(error_type), type) != RET_OK) {
        return RET_ERR;
    }

    gboolean error_flag =
        ((error_cnt->result != SML_SUCCESS && error_cnt->result != SML_ERR_PD_SCSI_RESP_TRUNCATED) ||
            error_cnt->data == NULL || error_cnt->data_length == 0 || error_cnt->data_length > PD_LOG_DATA_MAX_LEN);
    if (error_flag) {
        debug_log(DLOG_ERROR, "%s: error_cnt can not be divided", __FUNCTION__);
        return RET_ERR;
    }

    guint8 *error_data = g_malloc0(PD_LOG_DATA_MAX_LEN);
    if (error_data == NULL) {
        debug_log(DLOG_ERROR, "%s: g_malloc0 failed", __FUNCTION__);
        return RET_ERR;
    }

    errno_t safe_fun_ret = memcpy_s(error_data, PD_LOG_DATA_MAX_LEN, error_cnt->data, error_cnt->data_length);
    if (safe_fun_ret != EOK) {
        debug_log(DLOG_ERROR, "%s: memcpy_s fail, ret = %d", __FUNCTION__, safe_fun_ret);
        g_free(error_data);
        return RET_ERR;
    }

    if ((error_data[0] & 0x3f) != error_cnt_std) {
        debug_log(DLOG_ERROR, "%s Error counter Log Sense Failed, page mismatch", error_type);
        g_free(error_data);
        return RET_ERR;
    } else {
        if (type == SAS_ERROR_COUNTER_TYPE_NONMEDIUM) {
            pd_log_scsi_decode_non_medium_err_counter(
                error_data, PD_LOG_DATA_MAX_LEN, (SCSI_NON_MEDIUM_ERROR_S *)error_arr);
        } else {
            pd_log_scsi_decode_err_counter(
                error_data, PD_LOG_DATA_MAX_LEN, (SCSI_ERROR_COUNTER_S *)error_arr, sizeof(SCSI_ERROR_COUNTER_S));
        }
        g_free(error_data);
        return RET_OK;
    }
}

/*
 * 功能描述  : 获取SAS物理盘的glist计数
 */
static guint32 io_get_sas_glist_count(PD_LOG_S *pd_log)
{
    if (pd_log == NULL) {
        return 0;
    }

    if ((pd_log->SASDevice.glist.result != SML_SUCCESS &&
        pd_log->SASDevice.glist.result != SML_ERR_PD_SCSI_RESP_TRUNCATED) ||
        pd_log->SASDevice.glist.data == NULL || pd_log->SASDevice.glist.data_length == 0 ||
        pd_log->SASDevice.glist.data_length > PD_LOG_DATA_MAX_LEN) {
        return 0;
    }

    guint8 *glist_data = (guint8 *)g_malloc0(PD_LOG_DATA_MAX_LEN);
    if (glist_data == NULL) {
        return 0;
    }
    (void)memset_s(glist_data, PD_LOG_DATA_MAX_LEN, 0, PD_LOG_DATA_MAX_LEN);
    errno_t safe_fun_ret =
        memcpy_s(glist_data, PD_LOG_DATA_MAX_LEN, pd_log->SASDevice.glist.data, pd_log->SASDevice.glist.data_length);
    if (safe_fun_ret != EOK) {
        debug_log(DLOG_ERROR, "%s: memcpy_s fail, ret = %d\n", __FUNCTION__, safe_fun_ret);
    }

    guint32 length = (glist_data[4] << 24) + (glist_data[5] << 16) + (glist_data[6] << 8) + glist_data[7];
    if (length == 0) {
        g_free(glist_data);
        return 0;
    }

    guint8 format_type = (glist_data[1] & 0x7);
    g_free(glist_data);
    guint8 format_len = pd_log_sas_glist_get_format_len(format_type);
    if (format_len == 0) {
        return 0;
    }
    return length / format_len;
}

/*
 * 函 数 名  : io_deterioration_handle_get_sas_data
 * 功能描述  : 慢盘检测获取SAS物理盘数据
 */
static gint32 io_deterioration_handle_get_sas_data(PD_LOG_S *pd_log, IO_DETERIORATION_PD_INFO *pd_info)
{
    gint32 ret;
    SCSI_ERROR_COUNTER_S error_cnt_arr[3];
    SCSI_NON_MEDIUM_ERROR_S nonmedium_error_cnt;

    guint32 sas_grown_list = io_get_sas_glist_count(pd_log);
    pd_info->log.sas_param.grown_list = sas_grown_list;
    ret = io_deterioration_handle_divide_sas_data(
        &pd_log->SASDevice.read_error_cnt, SAS_ERROR_COUNTER_TYPE_READ, &error_cnt_arr[0]);
    if (ret != RET_OK) {
        debug_log(DLOG_ERROR, "%s: Failed to divide read_error_cnt.", __FUNCTION__);
        return RET_ERR;
    }
    ret = io_deterioration_handle_divide_sas_data(
        &pd_log->SASDevice.write_error_cnt, SAS_ERROR_COUNTER_TYPE_WRITE, &error_cnt_arr[1]);
    if (ret != RET_OK) {
        debug_log(DLOG_ERROR, "%s: Failed to divide write_error_cnt.", __FUNCTION__);
        return RET_ERR;
    }
    ret = io_deterioration_handle_divide_sas_data(&pd_log->SASDevice.verify_error_cnt,
        SAS_ERROR_COUNTER_TYPE_VERIFY,
        &error_cnt_arr[2]);  // 2：error_cnt_arr中存储error_cnt_verify信息的位置
    if (ret != RET_OK) {
        debug_log(DLOG_ERROR, "%s: Failed to divide verify_error_cnt.", __FUNCTION__);
        return RET_ERR;
    }
    ret = io_deterioration_handle_divide_sas_data(
        &pd_log->SASDevice.nonmedium_error_cnt, SAS_ERROR_COUNTER_TYPE_NONMEDIUM, &nonmedium_error_cnt);
    if (ret != RET_OK) {
        debug_log(DLOG_ERROR, "%s: Failed to get nonmedium_error_cnt.", __FUNCTION__);
        return RET_ERR;
    }
    // 对于一个error_cnt_arr.counter，它由8个guint64组成，其中第4位存储的是corrected信息，第7位存储的是uncorrected信息
    pd_info->log.sas_param.corrected_err_cnt_r = error_cnt_arr[0].counter[3];    // 3：特定取值位置
    pd_info->log.sas_param.uncorrected_err_cnt_r = error_cnt_arr[0].counter[6];  // 6：特定取值位置
    pd_info->log.sas_param.corrected_err_cnt_w = error_cnt_arr[1].counter[3];    // 3：特定取值位置
    pd_info->log.sas_param.uncorrected_err_cnt_w = error_cnt_arr[1].counter[6];  // 6：特定取值位置
    pd_info->log.sas_param.corrected_err_cnt_v = error_cnt_arr[2].counter[3];    // 2、3：特定取值位置
    pd_info->log.sas_param.uncorrected_err_cnt_v = error_cnt_arr[2].counter[6];  // 2、6：特定取值位置
    pd_info->log.sas_param.nonmedium_err_cnt = nonmedium_error_cnt.counter_pc0;
    return RET_OK;
}

/*
 * 函 数 名  : io_deterioration_is_sata_data_empty
 * 功能描述  : 慢盘检测检查SATA获得的物理盘原始数据是否为空
 */
static gboolean io_deterioration_is_sata_data_valid(PD_LOG_S *pd_log)
{
    gboolean tmp_data_error = (pd_log->SATADevice.smart_attribute.result != SML_SUCCESS &&
                               pd_log->SATADevice.smart_attribute.result != SML_ERR_PD_SCSI_RESP_TRUNCATED &&
                               pd_log->SATADevice.smart_attribute.result != SML_ERR_PD_SCSI_RESP_NO_DATA);
    if (tmp_data_error) {
        debug_log(DLOG_ERROR, "%s: Get SMART Attribute failed.", __FUNCTION__);
        return FALSE;
    }
    tmp_data_error =
        (pd_log->SATADevice.smart_attribute.result == SML_ERR_PD_SCSI_RESP_NO_DATA ||
            pd_log->SATADevice.smart_attribute.data == NULL || pd_log->SATADevice.smart_attribute.data_length == 0);
    if (tmp_data_error) {
        debug_log(DLOG_ERROR, "%s: SMART Attribute Data is empty.", __FUNCTION__);
        return FALSE;
    }
    return TRUE;
}

/*
 * 函 数 名  : io_deterioration_handle_switch_sata_data
 * 功能描述  : 根据attr_info的id字段填充pd_info中对应的值
 */
static void io_deterioration_handle_switch_sata_data(
    ATA_SMART_ATTRIBUTE_S *attr_info, IO_DETERIORATION_PD_INFO *pd_info, guint64 raw_value)
{
    switch (attr_info->id) {
        case ATA_SMART_ATTRIBUTE_ID_RAW_READ_ERROR_RATE:
            pd_info->log.sata_param.raw_read_error_rate = raw_value;
            break;
        case ATA_SMART_ATTRIBUTE_ID_REALLOCATED_SECTORS_COUNT:
            pd_info->log.sata_param.reallocated_sector_count = raw_value;
            break;
        case ATA_SMART_ATTRIBUTE_ID_SEEK_ERROR_RATE:
            pd_info->log.sata_param.seek_error_rate = raw_value;
            break;
        case ATA_SMART_ATTRIBUTE_ID_CURRENT_PENDING_SECTOR:
            pd_info->log.sata_param.current_pending_sector = raw_value;
            break;
        case ATA_SMART_ATTRIBUTE_ID_OFFLINE_UNCORRECTABLE:
            pd_info->log.sata_param.offline_uncorrectable = raw_value;
            break;
        case ATA_SMART_ATTRIBUTE_ID_THROUGHPUT_PERFORMANCE:
            pd_info->log.sata_param.typical_sata_param.other_sata_param.throughput_performance = raw_value;
            break;
        case ATA_SMART_ATTRIBUTE_ID_SEEK_TIME_PERFORMANCE:
            pd_info->log.sata_param.typical_sata_param.other_sata_param.seek_time_performance = raw_value;
            break;
        case ATA_SMART_ATTRIBUTE_ID_COMMAND_TIMEOUT:
            pd_info->log.sata_param.typical_sata_param.sea_sata_param.command_timeout_count = raw_value;
            break;
        case ATA_SMART_ATTRIBUTE_ID_REPORTED_UNCORRECTABLE_ERRORS:
            pd_info->log.sata_param.typical_sata_param.sea_sata_param.reported_uncorrectables = raw_value;
            break;
        default:
            break;
    }
    return;
}

/*
 * 函 数 名  : io_deterioration_handle_get_sata_data
 * 功能描述  : 慢盘检测从smart信息中获取SATA物理盘数据
 */
static gint32 io_deterioration_handle_get_sata_data(PD_LOG_S *pd_log, IO_DETERIORATION_PD_INFO *pd_info)
{
    ATA_SMART_ATTRIBUTE_S *attr_info = NULL;
    guint64 raw_value = 0;
    guint64 temp_value = 0;
    size_t raw_value_size = 0;
    guint32 idx = 0;
    size_t i;
    // 判断原始数据是否为空
    if (!io_deterioration_is_sata_data_valid(pd_log)) {
        return RET_ERR;
    }
    // 解析原始数据，从中剥离出需要的参数
    ATA_SMART_DATA_S *smart_data = (ATA_SMART_DATA_S *)pd_log->SATADevice.smart_attribute.data;
    /* smart 信息的个数为30 */
    for (idx = 0; idx < G_N_ELEMENTS(smart_data->smartAttribute); idx++) {
        attr_info = &smart_data->smartAttribute[idx];
        raw_value = 0;
        raw_value_size = G_N_ELEMENTS(attr_info->raw);

        // 拼接raw_value
        /* 结构体中数组的大小为6 */
        for (i = 0; i < raw_value_size; i++) {
            temp_value = attr_info->raw[i];
            temp_value = temp_value << (8 * i);  // 8：一个字节是8位
            raw_value |= temp_value;
        }
        io_deterioration_handle_switch_sata_data(attr_info, pd_info, raw_value);
    }
    return RET_OK;
}

/*
 * 函 数 名  : io_deterioration_handle_get_basic_data
 * 功能描述  : 慢盘检测处理物理盘基础数据
 */
static gint32 io_deterioration_handle_get_basic_data(PD_LOG_S *pd_log, IO_DETERIORATION_PD_INFO *pd_info)
{
    pd_info->pd_interface_type = pd_log->pd_interface_type;
    errno_t ret = strncpy_s(pd_info->pd_serial_number, sizeof(pd_info->pd_serial_number), pd_log->pd_serial_number,
                            sizeof(pd_info->pd_serial_number) - 1);
    if (ret != EOK) {
        debug_log(DLOG_ERROR, "%s: strncpy_s failed, ret = %d", __FUNCTION__, ret);
        return RET_ERR;
    }

    ret = strncpy_s(pd_info->pd_manufacturer, sizeof(pd_info->pd_manufacturer), pd_log->pd_manufacturer,
                    sizeof(pd_info->pd_manufacturer) - 1);
    if (ret != EOK) {
        debug_log(DLOG_ERROR, "%s: strncpy_s failed, ret = %d", __FUNCTION__, ret);
        return RET_ERR;
    }

    ret = strncpy_s(pd_info->pd_device_name, sizeof(pd_info->pd_device_name), pd_log->pd_device_name,
                    sizeof(pd_info->pd_device_name) - 1);
    if (ret != EOK) {
        debug_log(DLOG_ERROR, "%s: strncpy_s failed, ret = %d", __FUNCTION__, ret);
        return RET_ERR;
    }

    return RET_OK;
}

/*
 * 函 数 名  : io_deterioration_handle_get_raid_data
 * 功能描述  : 慢盘检测处理raid卡数据
 */
static void io_deterioration_handle_get_raid_data(PD_LOG_S *pd_log, IO_DETERIORATION_DIAG_CTRL_PARAM *diag_ctrl_param)
{
    diag_ctrl_param->health_status = pd_log->pd_health;
    diag_ctrl_param->rebuild_progress = pd_log->pd_rebuild_progress;
    diag_ctrl_param->media_error_cnt = pd_log->pd_media_error_count;
    diag_ctrl_param->other_err_count = pd_log->pd_other_error_count;
    diag_ctrl_param->prefail_error_cnt = pd_log->pd_perfail_error_count;
}

/*
 * 函 数 名  : io_deterioration_handle_data_get_data
 * 功能描述  : 慢盘检测处理物理盘数据
 */
static gint32 io_deterioration_handle_data_get_data(PD_LOG_S *pd_log, IO_DETERIORATION_PD_INFO *pd_info)
{
    gint32 ret;
    // 基础信息
    ret = io_deterioration_handle_get_basic_data(pd_log, pd_info);
    if (ret != RET_OK) {
        debug_log(DLOG_ERROR, "%s: io_deterioration_handle_get_basic_data failed, ret = %d", __FUNCTION__, ret);
        return RET_ERR;
    }
    // SATA盘和SAS盘不同的信息
    if (pd_log->pd_interface_type == PD_INTERFACE_TYPE_SATA) {
        ret = io_deterioration_handle_get_sata_data(pd_log, pd_info);
        if (ret != RET_OK) {
            debug_log(DLOG_ERROR, "%s: io_deterioration_handle_get_sata_data failed, ret = %d", __FUNCTION__, ret);
            return RET_ERR;
        }
    } else if (pd_log->pd_interface_type == PD_INTERFACE_TYPE_SAS) {
        ret = io_deterioration_handle_get_sas_data(pd_log, pd_info);
        if (ret != RET_OK) {
            debug_log(DLOG_ERROR, "%s: io_deterioration_handle_get_sas_data failed, ret = %d", __FUNCTION__, ret);
            return RET_ERR;
        }
    }
    // SEAGATE厂商 SATA盘特有信息
    if (strstr(pd_log->pd_manufacturer, PD_VENDOR_NAME_SEAGATE) != NULL &&
        pd_log->pd_interface_type == PD_INTERFACE_TYPE_SATA) {
        ret = io_deterioration_handle_get_farm_log_data(pd_log, pd_info);
        if (ret != RET_OK) {
            debug_log(DLOG_ERROR, "%s: io_deterioration_handle_get_farm_log_data failed, ret = %d", __FUNCTION__, ret);
            return RET_ERR;
        }
    }
    io_deterioration_handle_get_raid_data(pd_log, &pd_info->log.ctrl_param);

    return RET_OK;
}

Json *json_object_new_array_from_gdouble(gdouble array[], size_t size)
{
    Json *json_array = NULL;
    if (JsonArrayCreate(&json_array) != JSON_OK) {
        return NULL;
    }

    guint32 array_size = 0;
    for (guint8 i = 0; i < size; i++) {
        Json *json_double = NULL;
        if (JsonDoubleCreate(array[i], &json_double) != JSON_OK) {
            return json_array;
        }
        JsonArraySizeGet(json_array, &array_size);
        JsonArrayItemInsert(json_array, array_size, json_double);
    }
    return json_array;
}

Json *json_object_new_array_from_guint64(guint16 array[], size_t size)
{
    Json *json_array = NULL;
    if (JsonArrayCreate(&json_array) != JSON_OK) {
        return NULL;
    }

    guint32 array_size = 0;
    for (guint8 i = 0; i < size; i++) {
        Json *json_uint16 = NULL;
        if (JsonIntegerCreate((int64_t)array[i], &json_uint16) != JSON_OK) {
            return json_array;
        }
        JsonArraySizeGet(json_array, &array_size);
        JsonArrayItemInsert(json_array, array_size, json_uint16);
    }
    return json_array;
}

/*
 * 函 数 名  : handle_io_diagnose_seagate_info
 * 功能描述  : 慢盘检测写入希捷盘数据
 */
static void handle_io_diagnose_seagate_info(
    IO_DETERIORATION_DIAG_SEAGATE_INFO *seagate_info, Json *pd_io_info_jso)
{
    if (pd_io_info_jso == NULL) {
        return;
    }
    
    Json *json_array_ber = json_object_new_array_from_gdouble(seagate_info->cur_ber, MAGNETIC_HEAD_NUM);
    if (json_array_ber != NULL) {
        JsonObjectItemSet(pd_io_info_jso, "ber", json_array_ber);
    }
    Json *json_array_fh_outer = json_object_new_array_from_guint64(
        seagate_info->cur_fh_outer, MAGNETIC_HEAD_NUM);
    if (json_array_fh_outer != NULL) {
        JsonObjectItemSet(pd_io_info_jso, "fh_outer", json_array_fh_outer);
    }
    Json *json_array_fh_inner = json_object_new_array_from_guint64(
        seagate_info->cur_fh_inner, MAGNETIC_HEAD_NUM);
    if (json_array_fh_inner != NULL) {
        JsonObjectItemSet(pd_io_info_jso, "fh_inner", json_array_fh_inner);
    }
    Json *json_array_fh_middle = json_object_new_array_from_guint64(
        seagate_info->cur_fh_middle, MAGNETIC_HEAD_NUM);
    if (json_array_fh_middle != NULL) {
        JsonObjectItemSet(pd_io_info_jso, "fh_middle", json_array_fh_middle);
    }
    Json *json_array_cur_mr = json_object_new_array_from_guint64(seagate_info->cur_mr, MAGNETIC_HEAD_NUM);
    if (json_array_cur_mr != NULL) {
        JsonObjectItemSet(pd_io_info_jso, "cur_mr", json_array_cur_mr);
    }
    Json *json_array_fac_mr = json_object_new_array_from_guint64(seagate_info->fac_mr, MAGNETIC_HEAD_NUM);
    if (json_array_fac_mr != NULL) {
        JsonObjectItemSet(pd_io_info_jso, "fac_mr", json_array_fac_mr);
    }
}

/*
 * 函 数 名  : pd_handle_io_diagnose_seagate_info
 * 功能描述  : 慢盘检测处理希捷盘数据
 */
static void pd_handle_io_diagnose_seagate_info(IO_DETERIORATION_PD_INFO *pd_info, Json *pd_io_info_jso)
{
    if (pd_io_info_jso == NULL) {
        return;
    }

    IO_DETERIORATION_DIAG_SEA_LOG_PARAM *cur_farm = &pd_info->log.sea_param;
    IO_DETERIORATION_DIAG_SEA_LOG_PARAM *factory_farm = &pd_info->log.sea_factory_param;

    IO_DETERIORATION_DIAG_SEAGATE_INFO *seagate_info = g_malloc0(sizeof(IO_DETERIORATION_DIAG_SEAGATE_INFO));

    for (guint8 i = 0; i < MAGNETIC_HEAD_NUM; i++) {
        // 0-3字节为小数部分,4-5字节为正负整数部分
        gdouble ber_1 = (gdouble)(guint32)(cur_farm->bit_error_rate_zone[i] & BER_DECIMAL_MASK) / BER_DECIMAL_MULTIPLE;
        gdouble ber_2 = (gdouble)(gint16)((cur_farm->bit_error_rate_zone[i] & BER_INTEGER_MASK) >> BER_INTEGER_OFFSET);
        if (ber_2 < 0) {
            ber_1 = -ber_1;
        }
        seagate_info->cur_ber[i] = ber_1 + ber_2;
        // 正负整数,0-6字节为有效数据,再除10取绝对值
        seagate_info->cur_fh_outer[i] =
            ((guint64)(ABS((gint64)(cur_farm->flyheight_clearance_delta_outer[i] << FH_INTEGER_OFFSET))) >>
            FH_INTEGER_OFFSET) / 10;
        seagate_info->cur_fh_inner[i] =
            ((guint64)(ABS((gint64)(cur_farm->flyheight_clearance_delta_inner[i] << FH_INTEGER_OFFSET))) >>
            FH_INTEGER_OFFSET) / 10;
        seagate_info->cur_fh_middle[i] =
            ((guint64)(ABS((gint64)(cur_farm->flyheight_clearance_delta_middle[i] << FH_INTEGER_OFFSET))) >>
            FH_INTEGER_OFFSET) / 10;
        // 正整数,0-6字节为有效数据
        seagate_info->cur_mr[i] = cur_farm->mr_head_resistance[i];
        seagate_info->fac_mr[i] = factory_farm->mr_head_resistance[i];
    }

    handle_io_diagnose_seagate_info(seagate_info, pd_io_info_jso);
    g_free(seagate_info);
}

static void prepare_io_prop_value(IO_DETERIORATION_PD_INFO *pd_info, guint64 *glist_cnt, guint64 *plist_cnt,
    guint64 *unc_static, guint64 *cmd_timeout)
{
    if (pd_info->pd_interface_type == PD_INTERFACE_TYPE_SATA) {
        *glist_cnt = pd_info->log.sata_param.reallocated_sector_count;
        *plist_cnt = pd_info->log.sata_param.current_pending_sector;
        *unc_static = pd_info->log.sata_param.offline_uncorrectable;
        *cmd_timeout = pd_info->log.sata_param.typical_sata_param.sea_sata_param.command_timeout_count;
        return;
    }
    
    if (pd_info->pd_interface_type == PD_INTERFACE_TYPE_SAS) {
        *glist_cnt = pd_info->log.sas_param.grown_list;
        *unc_static = pd_info->log.sas_param.uncorrected_err_cnt_r + pd_info->log.sas_param.uncorrected_err_cnt_w +
            pd_info->log.sas_param.uncorrected_err_cnt_v;
    }
}

/*
 * 函 数 名  : pd_handle_io_diagnose_info
 * 功能描述  : 慢盘检测处理物理盘数据
 */
static void pd_handle_io_diagnose_info(IO_DETERIORATION_PD_INFO *pd_info, Json *pd_io_info_jso)
{
    if (pd_io_info_jso == NULL) {
        return;
    }

    gint32 iRet = -1;
    guint64 glist_cnt = 0;
    guint64 plist_cnt = 0;
    guint64 unc_static = 0;
    guint64 cmd_timeout = 0;
    prepare_io_prop_value(pd_info, &glist_cnt, &plist_cnt, &unc_static, &cmd_timeout);

    gchar tmp_str[ATA_LOG_STRING_LENGTH] = {0};

    iRet = snprintf_s(tmp_str, ATA_LOG_STRING_LENGTH, ATA_LOG_STRING_LENGTH - 1, "%llu", glist_cnt);
    if (iRet <= 0) {
        debug_log(DLOG_ERROR, "%s:snprintf_s for glist_cnt failed.", __FUNCTION__);
    }
    Json *string_json_obj = NULL;
    (void)JsonStringCreate(tmp_str, &string_json_obj);
    JsonObjectItemSet(pd_io_info_jso, "glist_cnt", string_json_obj);

    (void)memset_s(tmp_str, ATA_LOG_STRING_LENGTH, 0, ATA_LOG_STRING_LENGTH);
    iRet = snprintf_s(tmp_str, ATA_LOG_STRING_LENGTH, ATA_LOG_STRING_LENGTH - 1, "%llu", plist_cnt);
    if (iRet <= 0) {
        debug_log(DLOG_ERROR, "%s:snprintf_s for plist_cnt failed.", __FUNCTION__);
    }
    Json *plist_cnt_obj = NULL;
    (void)JsonStringCreate(tmp_str, &plist_cnt_obj);
    JsonObjectItemSet(pd_io_info_jso, "plist_cnt", plist_cnt_obj);

    (void)memset_s(tmp_str, ATA_LOG_STRING_LENGTH, 0, ATA_LOG_STRING_LENGTH);
    iRet = snprintf_s(tmp_str, ATA_LOG_STRING_LENGTH, ATA_LOG_STRING_LENGTH - 1, "%llu", unc_static);
    if (iRet <= 0) {
        debug_log(DLOG_ERROR, "%s:snprintf_s for unc_static failed.", __FUNCTION__);
    }
    Json *unc_static_obj = NULL;
    (void)JsonStringCreate(tmp_str, &unc_static_obj);
    JsonObjectItemSet(pd_io_info_jso, "unc_static", unc_static_obj);

    (void)memset_s(tmp_str, ATA_LOG_STRING_LENGTH, 0, ATA_LOG_STRING_LENGTH);
    iRet = snprintf_s(tmp_str, ATA_LOG_STRING_LENGTH, ATA_LOG_STRING_LENGTH - 1, "%llu", cmd_timeout);
    if (iRet <= 0) {
        debug_log(DLOG_ERROR, "%s:snprintf_s for cmd_timeout failed.", __FUNCTION__);
    }
    Json *cmd_timeout_obj = NULL;
    (void)JsonStringCreate(tmp_str, &cmd_timeout_obj);
    JsonObjectItemSet(pd_io_info_jso, "cmd_timeout", cmd_timeout_obj);

    if (strstr(pd_info->pd_manufacturer, PD_VENDOR_NAME_SEAGATE) != NULL) {
        pd_handle_io_diagnose_seagate_info(pd_info, pd_io_info_jso);
    }
}

/*
 * 函 数 名  : io_deterioration_handle_basic_data
 * 功能描述  : 慢盘检测处理物理盘基础数据
 */
void io_deterioration_handle_basic_data(PD_LOG_S *pd_log, Json *pd_io_info_jso)
{
    if (pd_io_info_jso == NULL) {
        return;
    }

    gint32 iRet = -1;
    static const gchar *pd_media_type_str[] = {
        MEDIA_TYPE_HDD,
        MEDIA_TYPE_SSD,
        MEDIA_TYPE_SSM
    };

    gchar tmp_str[ATA_LOG_STRING_LENGTH] = {0};
    iRet = snprintf_s(tmp_str, ATA_LOG_STRING_LENGTH, ATA_LOG_STRING_LENGTH - 1, "%s", pd_log->pd_device_name);
    if (iRet <= 0) {
        debug_log(DLOG_ERROR, "%s:snprintf_s for device_name failed.", __FUNCTION__);
    }
    Json *json_string_obj = NULL;
    (void)JsonStringCreate(tmp_str, &json_string_obj);
    JsonObjectItemSet(pd_io_info_jso, "drive_name", json_string_obj);

    if (pd_log->pd_media_type <= PD_MEDIA_TYPE_SSM_FLASH) {
        iRet = snprintf_s(tmp_str, ATA_LOG_STRING_LENGTH, ATA_LOG_STRING_LENGTH - 1, "%s",
            pd_media_type_str[pd_log->pd_media_type]);
        if (iRet <= 0) {
            debug_log(DLOG_ERROR, "%s:snprintf_s for media_type failed.", __FUNCTION__);
        }
        Json *media_type_obj1 = NULL;
        (void)JsonStringCreate(tmp_str, &media_type_obj1);
        JsonObjectItemSet(pd_io_info_jso, "media_type", media_type_obj1);
    } else {
        Json *media_type_obj2 = NULL;
        (void)JsonStringCreate("N/A", &media_type_obj2);
        JsonObjectItemSet(pd_io_info_jso, "media_type", media_type_obj2);
    }

    iRet = snprintf_s(tmp_str, ATA_LOG_STRING_LENGTH, ATA_LOG_STRING_LENGTH - 1, "%s", pd_log->pd_manufacturer);
    if (iRet <= 0) {
        debug_log(DLOG_ERROR, "%s:snprintf_s for manufacturer failed.", __FUNCTION__);
    }
    Json *manufacturer_obj = NULL;
    JsonStringCreate(tmp_str, &manufacturer_obj);
    JsonObjectItemSet(pd_io_info_jso, "manufacturer", manufacturer_obj);

    iRet = snprintf_s(tmp_str, ATA_LOG_STRING_LENGTH, ATA_LOG_STRING_LENGTH - 1, "%s", pd_log->pd_serial_number);
    if (iRet <= 0) {
        debug_log(DLOG_ERROR, "%s:snprintf_s for serial_number failed.", __FUNCTION__);
    }
    Json *serial_number_obj = NULL;
    JsonStringCreate(tmp_str, &serial_number_obj);
    JsonObjectItemSet(pd_io_info_jso, "serial_number", serial_number_obj);
}

/*
 * 函 数 名  : io_deterioration_handle_print_basic_data
 * 功能描述  : 打印慢盘检测基础数据到日志文件
 */
LOCAL void io_deterioration_handle_print_basic_data(FILE *fp, IO_DETERIORATION_PD_INFO *pd_info)
{
    (void)fprintf(fp, "\n%-20s: %s\n", "Serial Number", pd_info->pd_serial_number);
    (void)fprintf(fp, "%-20s: %s\n", "Manufacturer", pd_info->pd_manufacturer);
    (void)fprintf(fp, "%-20s: %s\n", "Type", (pd_info->pd_interface_type == PD_INTERFACE_TYPE_SATA) ? "SATA" : "SAS");
    return;
}

/*
 * 函 数 名  : io_deterioration_handle_print_farm_log_data
 * 功能描述  : 打印收集到的SEAGATE厂商的盘特有信息
 */
LOCAL void io_deterioration_handle_print_farm_log_data(FILE *fp, IO_DETERIORATION_DIAG_SEA_LOG_PARAM *farm_info)
{
    guint64 *data = (guint64 *)g_malloc0(sizeof(IO_DETERIORATION_DIAG_SEA_LOG_PARAM));
    if (data == NULL) {
        return;
    }
    errno_t ret = memcpy_s(data, sizeof(IO_DETERIORATION_DIAG_SEA_LOG_PARAM),
        farm_info, sizeof(IO_DETERIORATION_DIAG_SEA_LOG_PARAM));
    if (ret != EOK) {
        debug_log(DLOG_ERROR, "%s: memcpy_s fail, ret = %d\n", __FUNCTION__, ret);
    }

    for (int i = 0; i < G_N_ELEMENTS(g_farm_descripe_table); i++) {
        if (g_farm_descripe_table[i].size == sizeof(guint64)) {
            (void)fprintf(fp, "%-100s: 0X%016"G_GUINT64_HEX_FORMAT"\n", g_farm_descripe_table[i].desc,
                *(data + g_farm_descripe_table[i].offset / sizeof(guint64)));
        } else {
            (void)fprintf(fp, "%-100s:", g_farm_descripe_table[i].desc);
            for (size_t j = 0; j < g_farm_descripe_table[i].size / sizeof(guint64); j++) {
                (void)fprintf(fp, " 0X%016"G_GUINT64_HEX_FORMAT,
                    *(data + g_farm_descripe_table[i].offset / sizeof(guint64) + j));
            }
            (void)fprintf(fp, "\n");
        }
    }
    g_free(data);
    return;
}

/*
 * 函 数 名  : io_deterioration_handle_print_raid_data
 * 功能描述  : 打印收集到的RAID信息
 */
LOCAL void io_deterioration_handle_print_raid_data(FILE *fp, IO_DETERIORATION_DIAG_CTRL_PARAM *diag_ctrl_param)
{
    (void)fprintf(fp, "%-24s: %u\n", "Health Status", diag_ctrl_param->health_status);
    (void)fprintf(fp, "%-24s: %u\n", "Rebuild in Progress", diag_ctrl_param->rebuild_progress);
    (void)fprintf(fp, "%-24s: %u\n", "Media Error Count", diag_ctrl_param->media_error_cnt);
    (void)fprintf(fp, "%-24s: %u\n", "Prefail Error Count", diag_ctrl_param->prefail_error_cnt);
    return;
}

/*
 * 函 数 名  : io_deterioration_handle_print_static_data
 * 功能描述  : 打印慢盘检测基础数据到日志文件
 */
LOCAL void io_deterioration_handle_print_static_data(FILE *fp, IO_DETERIORATION_PD_INFO *pd_info)
{
    (void)fprintf(fp, "Static Parameters:\n");
    if (pd_info->pd_interface_type == PD_INTERFACE_TYPE_SATA) {
        (void)fprintf(fp, "%-32s: 0X%016"G_GUINT64_HEX_FORMAT"\n", "Raw_Read_Error_Rate",
            pd_info->log.sata_param.raw_read_error_rate);
        (void)fprintf(fp, "%-32s: 0X%016"G_GUINT64_HEX_FORMAT"\n", "Reallocated_Sector_Count",
            pd_info->log.sata_param.reallocated_sector_count);
        (void)fprintf(fp, "%-32s: 0X%016"G_GUINT64_HEX_FORMAT"\n", "Seek_Error_Rate",
            pd_info->log.sata_param.seek_error_rate);
        (void)fprintf(fp, "%-32s: 0X%016"G_GUINT64_HEX_FORMAT"\n", "Current_Pending_Sector",
            pd_info->log.sata_param.current_pending_sector);
        if (strstr(pd_info->pd_manufacturer, PD_VENDOR_NAME_SEAGATE) != NULL) {
            (void)fprintf(fp, "%-32s: 0X%016"G_GUINT64_HEX_FORMAT"\n", "Throughout_Performance",
                pd_info->log.sata_param.typical_sata_param.other_sata_param.throughput_performance);
            (void)fprintf(fp, "%-32s: 0X%016"G_GUINT64_HEX_FORMAT"\n", "Seek_Time_Performance",
                pd_info->log.sata_param.typical_sata_param.other_sata_param.seek_time_performance);
            (void)fprintf(fp, "%-32s: 0\n", "Command_Timeout_Count");
            (void)fprintf(fp, "%-32s: 0\n", "Reported_Uncorrectables");
        } else {
            (void)fprintf(fp, "%-32s: 0\n", "Throughout_Performance");
            (void)fprintf(fp, "%-32s: 0\n", "Seek_Time_Performance");
            (void)fprintf(fp, "%-32s: 0X%016"G_GUINT64_HEX_FORMAT"\n", "Command_Timeout_Count",
                pd_info->log.sata_param.typical_sata_param.sea_sata_param.command_timeout_count);
            (void)fprintf(fp, "%-32s: 0X%016"G_GUINT64_HEX_FORMAT"\n", "Reported_Uncorrectables",
                pd_info->log.sata_param.typical_sata_param.sea_sata_param.reported_uncorrectables);
        }
    } else if (pd_info->pd_interface_type == PD_INTERFACE_TYPE_SAS) {
        (void)fprintf(fp, "%-32s: %u\n", "Elements in grown defect list", pd_info->log.sas_param.grown_list);
        (void)fprintf(fp, "%-32s: %u\n", "Corrected Error Count(read)", pd_info->log.sas_param.corrected_err_cnt_r);
        (void)fprintf(fp, "%-32s: %u\n", "Corrected Error Count(write)", pd_info->log.sas_param.corrected_err_cnt_w);
        (void)fprintf(fp, "%-32s: %u\n", "Corrected Error Count(verify)", pd_info->log.sas_param.corrected_err_cnt_v);
        (void)fprintf(fp, "%-32s: %u\n", "Non Medium Error Count", pd_info->log.sas_param.nonmedium_err_cnt);
    }
    if (strstr(pd_info->pd_manufacturer, PD_VENDOR_NAME_SEAGATE) != NULL) {
        io_deterioration_handle_print_farm_log_data(fp, &pd_info->log.sea_param);
        if (pd_info->factory_farm_state == FACTORY_FARM_LOG_SUPPORT_COLLECT_DATA ||
            pd_info->factory_farm_state == FACTORY_FARM_LOG_SUPPORT_COLLECT_DATA_DB) {
            (void)fprintf(fp, "Factory farm log:\n");
            io_deterioration_handle_print_farm_log_data(fp, &pd_info->log.sea_factory_param);
        }
    }
    return;
}

/*
 * 函 数 名  : get_limited_time
 * 功能描述  : 获得BMC期限时间，当time_limit为0时输出当前时间
 */
LOCAL void get_limited_time(gchar *time_str, guint8 str_size, guint8 time_limit)
{
    struct tm cur_tm;
    (void)dal_localtime_r(NULL, &cur_tm);
    time_t cur_tm_s = mktime(&cur_tm);
    if (cur_tm_s != -1) {
        cur_tm_s = cur_tm_s - PD_LOG_COLLECT_INTERVAL * time_limit;
        (void)localtime_r(&cur_tm_s, &cur_tm);
    }
    gint32 ret = snprintf_s(time_str, str_size, str_size - 1, "%04d-%02d-%02d",
        cur_tm.tm_year + YEAR_1900, cur_tm.tm_mon + 1, cur_tm.tm_mday);
    if (ret <= 0) {
        debug_log(DLOG_ERROR, "%s: get time_str failed", __FUNCTION__);
        (void)strcpy_s(time_str, str_size, "1900-01-01");
    }
    return;
}

/*
 * 函 数 名  : io_deterioration_handle_print_dynamic_data
 * 功能描述  : 打印慢盘检测动态数据到日志文件
 */
LOCAL void io_deterioration_handle_print_dynamic_data(FILE *fp, IO_DETERIORATION_PD_INFO *pd_info)
{
    (void)fprintf(fp, "Dynamic Parameters:\n");
    gchar time_str[PROP_VAL_LENGTH] = {0};
    get_limited_time(time_str, sizeof(time_str), 0);
    (void)fprintf(fp, "%-32s: %s\n", "TimeStamp", time_str);

    (void)fprintf(fp, "%-32s: %lu\n", "OfflineUncorrectable", pd_info->log.sata_param.offline_uncorrectable);
    (void)fprintf(fp, "%-32s: %u\n", "UncorrectedErrorCountRead", pd_info->log.sas_param.uncorrected_err_cnt_r);
    (void)fprintf(fp, "%-32s: %u\n", "UncorrectedErrorCountWrite", pd_info->log.sas_param.uncorrected_err_cnt_w);
    (void)fprintf(fp, "%-32s: %u\n", "UncorrectedErrorCountVerify", pd_info->log.sas_param.uncorrected_err_cnt_v);
    (void)fprintf(fp, "%-32s: %u\n", "MediaErrCnt", pd_info->log.ctrl_param.media_error_cnt);
    (void)fprintf(fp, "%-32s: %u\n", "OtherErrCnt", pd_info->log.ctrl_param.other_err_count);
    (void)fprintf(fp, "%-32s: %u\n", "UnexpectedSense", pd_info->log.ctrl_param.unexpected_sense);
    (void)fprintf(fp, "%-32s: %lu\n", "CommandTimeout",
        pd_info->log.sata_param.typical_sata_param.sea_sata_param.command_timeout_count);
    (void)fprintf(fp, "%-32s: %u\n", "Reset", pd_info->log.ctrl_param.reset_with_type);
    (void)fprintf(fp, "%-32s: %u\n", "POR", pd_info->log.ctrl_param.power_reset);

    return;
}


/*
 * 函 数 名  : io_deterioration_handle_print_data
 * 功能描述  : 打印慢盘检测数据到日志文件
 */
void io_deterioration_handle_print_data(IO_DETERIORATION_PD_INFO *pd_info)
{
    struct stat file_stat;
    if (stat_s(STORAGE_DIAGNOSE_LOG_BASE_PATH, &file_stat) < 0) {
        if (g_mkdir_with_parents(STORAGE_DIAGNOSE_LOG_BASE_PATH, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) ==
            -1) {
            debug_log(DLOG_ERROR, "%s: mkdir storage diagnose log file failed.", __FUNCTION__);
            return;
        }
        (void)chmod_s(STORAGE_DIAGNOSE_LOG_BASE_PATH, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
    }

    FILE *fp = fopen_s(IO_DETERIORATION_LOG_PATH, "a+", IO_DETERIORATION_LOG_PATH);
    if (fp == NULL) {
        debug_log(DLOG_ERROR, "%s: io_deterioration_clean_printed_data failed", __FUNCTION__);
        return;
    }

    // 打印基础信息
    io_deterioration_handle_print_basic_data(fp, pd_info);
    // 打印Static信息
    io_deterioration_handle_print_static_data(fp, pd_info);
    // 打印raid参数信息
    io_deterioration_handle_print_raid_data(fp, &pd_info->log.ctrl_param);
    // 打印Dynamic信息
    io_deterioration_handle_print_dynamic_data(fp, pd_info);

    (void)fclose_s(fp);
    return;
}

/*
 * 函 数 名  : io_deterioration_handle_data
 * 功能描述  : 慢盘检测处理物理盘数据
 */
void io_deterioration_handle_data(PD_LOG_S *pd_log, Json *pd_io_info_jso)
{
    if (pd_log == NULL || pd_io_info_jso == NULL) {
        debug_log(DLOG_ERROR, "%s: Invalid input", __FUNCTION__);
        return;
    }

    IO_DETERIORATION_PD_INFO *pd_info = g_malloc0(sizeof(IO_DETERIORATION_PD_INFO));
    if (pd_info == NULL) {
        debug_log(DLOG_ERROR, "%s: pd_info malloc failed", __FUNCTION__);
        return;
    }

    // 整理出需要的各项参数
    gint32 ret = io_deterioration_handle_data_get_data(pd_log, pd_info);
    if (ret != RET_OK) {
        debug_log(DLOG_ERROR, "%s: get data from %s failed", __FUNCTION__, pd_log->pd_device_name);
        g_free(pd_info);
        return;
    }
    io_deterioration_handle_print_data(pd_info);

    pd_handle_io_diagnose_info(pd_info, pd_io_info_jso);
    g_free(pd_info);
    return;
}