From 5efefd3576c76553377c30cc85d6ed09243b9fd9 Mon Sep 17 00:00:00 2001 From: Alexander Shaduri Date: Tue, 7 May 2024 19:36:40 +0400 Subject: [PATCH] Implemented NVMe self-test log parsing. Refactoring AtaStorageProperty -> StorageProperty. --- src/applib/CMakeLists.txt | 8 +- .../examples/example_smartctl_parser.cpp | 4 +- src/applib/selftest.cpp | 14 +- src/applib/smartctl_json_ata_parser.cpp | 265 ++++++++--------- src/applib/smartctl_json_basic_parser.cpp | 39 +-- src/applib/smartctl_json_nvme_parser.cpp | 279 +++++++++--------- src/applib/smartctl_json_nvme_parser.h | 2 +- src/applib/smartctl_json_parser_helpers.h | 48 ++- src/applib/smartctl_parser.cpp | 4 +- src/applib/smartctl_parser.h | 4 +- src/applib/smartctl_parser_types.h | 2 +- src/applib/smartctl_text_ata_parser.cpp | 144 ++++----- src/applib/smartctl_text_ata_parser.h | 4 +- src/applib/smartctl_text_basic_parser.cpp | 42 +-- src/applib/smartctl_version_parser.h | 2 +- src/applib/storage_device.cpp | 15 +- src/applib/storage_device.h | 6 +- src/applib/storage_device_detected_type.h | 2 +- ...rage_property.cpp => storage_property.cpp} | 69 ++--- ..._storage_property.h => storage_property.h} | 185 ++++++++++-- ...y_descr.cpp => storage_property_descr.cpp} | 68 ++--- ...perty_descr.h => storage_property_descr.h} | 4 +- src/applib/storage_property_repository.cpp | 14 +- src/applib/storage_property_repository.h | 16 +- src/applib/warning_colors.h | 6 +- src/gsc_info_window.cpp | 72 ++--- src/gsc_info_window.h | 32 +- src/gsc_main_window.cpp | 2 +- src/gsc_main_window_iconview.h | 4 +- 29 files changed, 733 insertions(+), 623 deletions(-) rename src/applib/{ata_storage_property.cpp => storage_property.cpp} (90%) rename src/applib/{ata_storage_property.h => storage_property.h} (65%) rename src/applib/{ata_storage_property_descr.cpp => storage_property_descr.cpp} (98%) rename src/applib/{ata_storage_property_descr.h => storage_property_descr.h} (90%) diff --git a/src/applib/CMakeLists.txt b/src/applib/CMakeLists.txt index 02256e8..86534e4 100644 --- a/src/applib/CMakeLists.txt +++ b/src/applib/CMakeLists.txt @@ -13,10 +13,6 @@ target_sources(applib PRIVATE app_gtkmm_tools.cpp app_gtkmm_tools.h app_pcrecpp.h - ata_storage_property.cpp - ata_storage_property.h - ata_storage_property_descr.cpp - ata_storage_property_descr.h command_executor.h command_executor.cpp command_executor_3ware.h @@ -62,6 +58,10 @@ target_sources(applib PRIVATE storage_detector_win32.h storage_device.cpp storage_device.h + storage_property.cpp + storage_property.h + storage_property_descr.cpp + storage_property_descr.h storage_property_repository.cpp storage_property_repository.h storage_settings.h diff --git a/src/applib/examples/example_smartctl_parser.cpp b/src/applib/examples/example_smartctl_parser.cpp index 031a65b..44fd4f7 100644 --- a/src/applib/examples/example_smartctl_parser.cpp +++ b/src/applib/examples/example_smartctl_parser.cpp @@ -20,7 +20,7 @@ Copyright: #include "libdebug/libdebug.h" #include "hz/fs.h" -#include "applib/ata_storage_property.h" +#include "applib/storage_property.h" #include "applib/smartctl_text_ata_parser.h" @@ -48,7 +48,7 @@ int main(int argc, char* argv[]) return EXIT_FAILURE; } - const std::vector& props = parser.get_property_repository().get_properties(); + const std::vector& props = parser.get_property_repository().get_properties(); for(const auto& prop : props) { debug_out_dump("app", prop << "\n"); } diff --git a/src/applib/selftest.cpp b/src/applib/selftest.cpp index 69bed3c..77ffac7 100644 --- a/src/applib/selftest.cpp +++ b/src/applib/selftest.cpp @@ -16,10 +16,10 @@ Copyright: #include #include "app_pcrecpp.h" -#include "ata_storage_property.h" +#include "storage_property.h" #include "smartctl_text_ata_parser.h" #include "selftest.h" -#include "ata_storage_property_descr.h" +#include "storage_property_descr.h" #include "smartctl_version_parser.h" @@ -77,8 +77,8 @@ std::chrono::seconds SelfTest::get_min_duration_seconds() const case TestType::Conveyance: prop_name = "ata_smart_data/self_test/polling_minutes/conveyance"; break; } - const AtaStorageProperty p = drive_->get_property_repository().lookup_property(prop_name, - AtaStorageProperty::Section::Capabilities); + const StorageProperty p = drive_->get_property_repository().lookup_property(prop_name, + StorageProperty::Section::Capabilities); // p stores it as uint64_t return (total_duration_ = (p.empty() ? 0s : p.get_value())); @@ -104,7 +104,7 @@ bool SelfTest::is_supported() const case TestType::Conveyance: prop_name = "ata_smart_data/capabilities/conveyance_self_test_supported"; break; } - const AtaStorageProperty p = drive_->get_property_repository().lookup_property(prop_name); + const StorageProperty p = drive_->get_property_repository().lookup_property(prop_name); return (!p.empty() && p.get_value()); } @@ -192,7 +192,7 @@ hz::ExpectedVoid SelfTest::force_stop(const std::shared_ptrget_property_repository().lookup_property( + const StorageProperty p = drive_->get_property_repository().lookup_property( "ata_smart_data/capabilities/offline_is_aborted_upon_new_cmd"); if (!p.empty() && p.get_value()) { // if empty, give a chance to abort anyway. return hz::Unexpected(SelfTestError::StopUnsupported, _("Aborting this test is unsupported by the drive.")); @@ -271,7 +271,7 @@ hz::ExpectedVoid SelfTest::update(const std::shared_ptr() || e.get_value().test_num != 0 || e.generic_name != "ata_smart_data/self_test/status/_merged") diff --git a/src/applib/smartctl_json_ata_parser.cpp b/src/applib/smartctl_json_ata_parser.cpp index 70fa2d3..1fc51c4 100644 --- a/src/applib/smartctl_json_ata_parser.cpp +++ b/src/applib/smartctl_json_ata_parser.cpp @@ -15,13 +15,14 @@ Copyright: #include #include #include +#include #include #include #include #include "json/json.hpp" -#include "ata_storage_property.h" +#include "storage_property.h" #include "hz/debug.h" #include "hz/string_algo.h" // #include "smartctl_version_parser.h" @@ -29,6 +30,7 @@ Copyright: #include "hz/error_container.h" #include "hz/string_num.h" #include "smartctl_json_parser_helpers.h" +#include "smartctl_parser_types.h" /* @@ -94,7 +96,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse(std::string_v return hz::Unexpected(SmartctlParserError::SyntaxError, std::string("Invalid JSON data: ") + e.what()); } - AtaStorageProperty merged_property, full_property; + StorageProperty merged_property, full_property; auto version_parse_status = SmartctlJsonParserHelpers::parse_version(json_root_node, merged_property, full_property); if (!version_parse_status) { return version_parse_status; @@ -111,78 +113,78 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse(std::string_v // Add properties for each parsed section so that the UI knows which tabs to show or hide { auto section_parse_status = parse_section_health(json_root_node); - AtaStorageProperty p; - p.section = AtaStorageProperty::Section::Health; + StorageProperty p; + p.section = StorageProperty::Section::Health; p.set_name("_parser/health_section_available"); p.value = section_parse_status.has_value() || section_parse_status.error().data() != SmartctlParserError::NoSection; } { auto section_parse_status = parse_section_capabilities(json_root_node); - AtaStorageProperty p; - p.section = AtaStorageProperty::Section::Capabilities; + StorageProperty p; + p.section = StorageProperty::Section::Capabilities; p.set_name("_parser/capabilities_section_available"); p.value = section_parse_status.has_value() || section_parse_status.error().data() != SmartctlParserError::NoSection; } { auto section_parse_status = parse_section_attributes(json_root_node); - AtaStorageProperty p; - p.section = AtaStorageProperty::Section::Attributes; + StorageProperty p; + p.section = StorageProperty::Section::Attributes; p.set_name("_parser/attributes_section_available"); p.value = section_parse_status.has_value() || section_parse_status.error().data() != SmartctlParserError::NoSection; } { auto section_parse_status = parse_section_directory_log(json_root_node); - AtaStorageProperty p; - p.section = AtaStorageProperty::Section::DirectoryLog; + StorageProperty p; + p.section = StorageProperty::Section::DirectoryLog; p.set_name("_parser/directory_log_section_available"); p.value = section_parse_status.has_value() || section_parse_status.error().data() != SmartctlParserError::NoSection; } { auto section_parse_status = parse_section_error_log(json_root_node); - AtaStorageProperty p; - p.section = AtaStorageProperty::Section::ErrorLog; + StorageProperty p; + p.section = StorageProperty::Section::ErrorLog; p.set_name("_parser/error_log_section_available"); p.value = section_parse_status.has_value() || section_parse_status.error().data() != SmartctlParserError::NoSection; } { auto section_parse_status = parse_section_selftest_log(json_root_node); - AtaStorageProperty p; - p.section = AtaStorageProperty::Section::SelftestLog; + StorageProperty p; + p.section = StorageProperty::Section::SelftestLog; p.set_name("_parser/selftest_log_section_available"); p.value = section_parse_status.has_value() || section_parse_status.error().data() != SmartctlParserError::NoSection; } { auto section_parse_status = parse_section_selective_selftest_log(json_root_node); - AtaStorageProperty p; - p.section = AtaStorageProperty::Section::SelectiveSelftestLog; + StorageProperty p; + p.section = StorageProperty::Section::SelectiveSelftestLog; p.set_name("_parser/selective_selftest_log_section_available"); p.value = section_parse_status.has_value() || section_parse_status.error().data() != SmartctlParserError::NoSection; } { auto section_parse_status = parse_section_scttemp_log(json_root_node); - AtaStorageProperty p; - p.section = AtaStorageProperty::Section::TemperatureLog; + StorageProperty p; + p.section = StorageProperty::Section::TemperatureLog; p.set_name("_parser/temperature_log_section_available"); p.value = section_parse_status.has_value() || section_parse_status.error().data() != SmartctlParserError::NoSection; } { auto section_parse_status = parse_section_scterc_log(json_root_node); - AtaStorageProperty p; - p.section = AtaStorageProperty::Section::ErcLog; + StorageProperty p; + p.section = StorageProperty::Section::ErcLog; p.set_name("_parser/erc_log_section_available"); p.value = section_parse_status.has_value() || section_parse_status.error().data() != SmartctlParserError::NoSection; } { auto section_parse_status = parse_section_devstat(json_root_node); - AtaStorageProperty p; - p.section = AtaStorageProperty::Section::Devstat; + StorageProperty p; + p.section = StorageProperty::Section::Devstat; p.set_name("_parser/devstat_section_available"); p.value = section_parse_status.has_value() || section_parse_status.error().data() != SmartctlParserError::NoSection; } { auto section_parse_status = parse_section_sataphy(json_root_node); - AtaStorageProperty p; - p.section = AtaStorageProperty::Section::PhyLog; + StorageProperty p; + p.section = StorageProperty::Section::PhyLog; p.set_name("_parser/phy_log_section_available"); p.value = section_parse_status.has_value() || section_parse_status.error().data() != SmartctlParserError::NoSection; } @@ -203,10 +205,10 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_info( {"device/type", _("Smartctl Device Type"), // nvme, sat, etc. [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { if (auto jval = get_node_data(root_node, "device/type"); jval.has_value()) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); p.value = jval.value(); p.show_in_ui = false; @@ -222,14 +224,14 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_info( {"wwn/_merged", _("World Wide Name"), [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { auto jval1 = get_node_data(root_node, "wwn/naa"); auto jval2 = get_node_data(root_node, "wwn/oui"); auto jval3 = get_node_data(root_node, "wwn/id"); if (jval1 && jval2 && jval3) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); // p.readable_value = std::format("{:X} {:X} {:X}", jval1.value(), jval2.value(), jval3.value()); p.readable_value = std::format("{:X}-{:06X}-{:08X}", jval1.value(), jval2.value(), jval3.value()); @@ -254,10 +256,10 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_info( {"user_capacity/bytes/_short", _("Capacity"), [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { if (auto jval = get_node_data(root_node, "user_capacity/bytes"); jval) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); p.readable_value = hz::format_size(static_cast(jval.value()), true); p.value = jval.value(); @@ -270,7 +272,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_info( {"physical_block_size/_and/logical_block_size", _("Sector Size"), [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { std::vector values; if (auto jval1 = get_node_data(root_node, "logical_block_size"); jval1) { @@ -280,7 +282,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_info( values.emplace_back(std::format("{} bytes physical", jval2.value())); } if (!values.empty()) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); p.readable_value = hz::string_join(values, ", "); p.value = p.readable_value; @@ -290,20 +292,8 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_info( } }, - {"rotation_rate", _("Rotation Rate"), // (S)ATA, used to detect HDD vs SSD - [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue - { - if (auto jval = get_node_data(root_node, key); jval) { - AtaStorageProperty p; - p.set_name(key, key, displayable_name); - p.readable_value = std::format("{} RPM", jval.value()); - p.value = jval.value(); - return p; - } - return hz::Unexpected(SmartctlParserError::KeyNotFound, std::format("Error getting key {} from JSON data.", key)); - } - }, + // (S)ATA, used to detect HDD vs SSD + {"rotation_rate", _("Rotation Rate"), integer_formatter("{} RPM")}, {"form_factor/name", _("Form Factor"), string_formatter()}, {"trim/supported", _("TRIM Supported"), bool_formatter(_("Yes"), _("No"))}, @@ -313,7 +303,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_info( {"interface_speed/_merged", _("Interface Speed"), [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { std::vector values; if (auto jval1 = get_node_data(root_node, "interface_speed/max/string"); jval1) { @@ -323,7 +313,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_info( values.emplace_back(std::format("Current: {}", jval2.value())); } if (!values.empty()) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); p.readable_value = hz::string_join(values, ", "); p.value = p.readable_value; @@ -341,32 +331,27 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_info( {"ata_aam/enabled", _("AAM Feature"), bool_formatter(_("Enabled"), _("Disabled"))}, {"ata_aam/level", _("AAM Level"), [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { int64_t level = get_node_data(root_node, "ata_aam/level").value_or(0); std::string level_string = get_node_data(root_node, "ata_aam/string").value_or(""); - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); p.readable_value = std::format("{} ({})", level_string, level); p.value = level; return p; } }, - {"ata_aam/recommended_level", _("AAM Recommended Level"), - custom_string_formatter([](int64_t value) - { - return std::format("{}", value); - }) - }, + {"ata_aam/recommended_level", _("AAM Recommended Level"), integer_formatter()}, {"ata_apm/enabled", _("APM Feature"), bool_formatter(_("Enabled"), _("Disabled"))}, {"ata_apm/level", _("APM Level"), [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { int64_t level = get_node_data(root_node, "ata_apm/level").value_or(0); std::string level_string = get_node_data(root_node, "ata_apm/string").value_or(""); - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); p.readable_value = std::format("{} ({})", level_string, level); p.value = level; @@ -386,7 +371,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_info( auto p = retrieval_func(json_root_node, key, displayable_name); if (p.has_value()) { // ignore if not found - p->section = AtaStorageProperty::Section::Info; + p->section = StorageProperty::Section::Info; add_property(p.value()); any_found = true; } @@ -413,7 +398,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_healt auto p = retrieval_func(json_root_node, key, displayable_name); if (p.has_value()) { // ignore if not found - p->section = AtaStorageProperty::Section::Health; + p->section = StorageProperty::Section::Health; add_property(p.value()); } } @@ -441,11 +426,11 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_capab {"ata_smart_data/offline_data_collection/status/_auto_enabled", _("Automatic offline data collection status"), [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { auto value_val = get_node_data(root_node, "ata_smart_data/offline_data_collection/status/value"); if (value_val.has_value()) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); p.value = static_cast(value_val.value() & 0x80); // taken from ataprint.cpp p.readable_value = p.get_value() ? _("Enabled") : _("Disabled"); @@ -459,7 +444,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_capab // Last self-test status {"ata_smart_data/offline_data_collection/status/value/_decoded", "Last offline data collection status", [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { auto value_val = get_node_data(root_node, "ata_smart_data/offline_data_collection/status/value"); if (value_val.has_value()) { @@ -474,8 +459,8 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_capab case 0x06: status_str = _("Aborted by the device with a fatal error"); break; default: status_str = ((value_val.value() & 0x7f) > 0x40 ? _("In vendor-specific state") : _("In reserved state")); break; } - AtaStorageProperty p; - p.section = AtaStorageProperty::Section::Capabilities; + StorageProperty p; + p.section = StorageProperty::Section::Capabilities; p.set_name(key, key, displayable_name); p.value = status_str; return p; @@ -486,11 +471,11 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_capab {"ata_smart_data/offline_data_collection/completion_seconds", _("Time to complete offline data collection"), [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { auto value_val = get_node_data(root_node, key); if (value_val.has_value()) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); p.value = std::chrono::seconds(value_val.value()); return p; @@ -501,7 +486,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_capab {"ata_smart_data/self_test/status/value/_decoded", _("Self-test execution status"), [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { // Testing: // "status": { @@ -537,7 +522,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_capab default: status = AtaStorageSelftestEntry::Status::Reserved; break; } - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); p.value = AtaStorageSelftestEntry::get_readable_status_name(status); return p; @@ -547,13 +532,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_capab } }, - {"ata_smart_data/self_test/status/remaining_percent", _("Self-test remaining percentage"), - custom_string_formatter([](int64_t value) - { - return std::format("{} %", value); - }) - }, - + {"ata_smart_data/self_test/status/remaining_percent", _("Self-test remaining percentage"), integer_formatter("{} %")}, {"ata_smart_data/capabilities/self_tests_supported", _("Self-tests supported"), bool_formatter(_("Yes"), _("No"))}, @@ -566,11 +545,11 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_capab {"ata_smart_data/self_test/polling_minutes/short", _("Short self-test status recommended polling time"), [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { auto value_val = get_node_data(root_node, key); if (value_val.has_value()) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); p.value = std::chrono::minutes(value_val.value()); return p; @@ -581,11 +560,11 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_capab {"ata_smart_data/self_test/polling_minutes/extended", _("Extended self-test status recommended polling time"), [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { auto value_val = get_node_data(root_node, key); if (value_val.has_value()) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); p.value = std::chrono::minutes(value_val.value()); return p; @@ -596,11 +575,11 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_capab {"ata_smart_data/self_test/polling_minutes/conveyance", _("Conveyance self-test status recommended polling time"), [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { auto value_val = get_node_data(root_node, key); if (value_val.has_value()) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); p.value = std::chrono::minutes(value_val.value()); return p; @@ -617,11 +596,11 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_capab {"ata_sct_capabilities/_supported", _("SCT capabilities supported"), [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { auto value_val = get_node_exists(root_node, "ata_sct_capabilities"); if (value_val.has_value()) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); p.value = value_val.value(); return p; @@ -641,7 +620,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_capab DBG_ASSERT(retrieval_func != nullptr); auto p = retrieval_func(json_root_node, key, displayable_name); if (p.has_value()) { // ignore if not found - p->section = AtaStorageProperty::Section::Capabilities; + p->section = StorageProperty::Section::Capabilities; add_property(p.value()); section_properties_found = true; } @@ -649,7 +628,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_capab if (!section_properties_found) { return hz::Unexpected(SmartctlParserError::NoSection, - std::format("No section {} parsed.", AtaStorageProperty::get_readable_section_name(AtaStorageProperty::Section::Capabilities))); + std::format("No section {} parsed.", StorageProperty::get_readable_section_name(StorageProperty::Section::Capabilities))); } return {}; @@ -665,9 +644,9 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_attri // Revision if (get_node_exists(json_root_node, "ata_smart_attributes/revision").value_or(false)) { - AtaStorageProperty p; + StorageProperty p; p.set_name("ata_smart_attributes/revision", "ata_smart_attributes/revision", _("Data structure revision number")); - p.section = AtaStorageProperty::Section::Attributes; + p.section = StorageProperty::Section::Attributes; p.value = get_node_data(json_root_node, "ata_smart_attributes/revision").value_or(0); add_property(p); section_properties_found = true; @@ -701,9 +680,9 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_attri a.raw_value = get_node_data(table_entry, "raw/string").value_or(std::string()); a.raw_value_int = get_node_data(table_entry, "raw/value").value_or(0); - AtaStorageProperty p; + StorageProperty p; p.set_name(get_node_data(table_entry, "name").value_or(std::string())); - p.section = AtaStorageProperty::Section::Attributes; + p.section = StorageProperty::Section::Attributes; p.value = a; add_property(p); @@ -713,7 +692,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_attri if (!section_properties_found) { return hz::Unexpected(SmartctlParserError::NoSection, - std::format("No section {} parsed.", AtaStorageProperty::get_readable_section_name(AtaStorageProperty::Section::Attributes))); + std::format("No section {} parsed.", StorageProperty::get_readable_section_name(StorageProperty::Section::Attributes))); } return {}; @@ -731,9 +710,9 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_direc std::vector lines; if (get_node_exists(json_root_node, "ata_log_directory/gp_dir_version").value_or(false)) { - AtaStorageProperty p; + StorageProperty p; p.set_name("ata_log_directory/gp_dir_version", "ata_log_directory/gp_dir_version", _("General purpose log directory version")); - p.section = AtaStorageProperty::Section::DirectoryLog; + p.section = StorageProperty::Section::DirectoryLog; p.value = get_node_data(json_root_node, "ata_log_directory/gp_dir_version").value_or(0); add_property(p); @@ -741,9 +720,9 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_direc section_properties_found = true; } if (get_node_exists(json_root_node, "ata_log_directory/smart_dir_version").value_or(false)) { - AtaStorageProperty p; + StorageProperty p; p.set_name("ata_log_directory/smart_dir_version", "ata_log_directory/smart_dir_version", _("SMART log directory version")); - p.section = AtaStorageProperty::Section::DirectoryLog; + p.section = StorageProperty::Section::DirectoryLog; p.value = get_node_data(json_root_node, "ata_log_directory/smart_dir_version").value_or(0); add_property(p); @@ -751,9 +730,9 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_direc section_properties_found = true; } if (get_node_exists(json_root_node, "ata_log_directory/smart_dir_multi_sector").value_or(false)) { - AtaStorageProperty p; + StorageProperty p; p.set_name("ata_log_directory/smart_dir_multi_sector", "ata_log_directory/smart_dir_multi_sector", _("Multi-sector log support")); - p.section = AtaStorageProperty::Section::DirectoryLog; + p.section = StorageProperty::Section::DirectoryLog; p.value = get_node_data(json_root_node, "ata_log_directory/smart_dir_multi_sector").value_or(0); add_property(p); @@ -791,9 +770,9 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_direc // The whole section { - AtaStorageProperty p; + StorageProperty p; p.set_name("General Purpose Log Directory", "ata_log_directory/_merged"); - p.section = AtaStorageProperty::Section::DirectoryLog; + p.section = StorageProperty::Section::DirectoryLog; p.reported_value = hz::string_join(lines, "\n"); p.value = p.reported_value; // string-type value @@ -805,7 +784,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_direc if (!section_properties_found) { return hz::Unexpected(SmartctlParserError::NoSection, - std::format("No section {} parsed.", AtaStorageProperty::get_readable_section_name(AtaStorageProperty::Section::DirectoryLog))); + std::format("No section {} parsed.", StorageProperty::get_readable_section_name(StorageProperty::Section::DirectoryLog))); } return {}; @@ -821,18 +800,18 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_error // Revision if (get_node_exists(json_root_node, "ata_smart_error_log/extended/revision").value_or(false)) { - AtaStorageProperty p; + StorageProperty p; p.set_name("ata_smart_error_log/extended/revision", "ata_smart_error_log/extended/revision", _("SMART extended comprehensive error log version")); - p.section = AtaStorageProperty::Section::ErrorLog; + p.section = StorageProperty::Section::ErrorLog; p.value = get_node_data(json_root_node, "ata_smart_error_log/extended/revision").value_or(0); add_property(p); section_properties_found = true; } // Count if (get_node_exists(json_root_node, "ata_smart_error_log/extended/count").value_or(false)) { - AtaStorageProperty p; + StorageProperty p; p.set_name("ata_smart_error_log/extended/count", "ata_smart_error_log/extended/count", _("ATA error count")); - p.section = AtaStorageProperty::Section::ErrorLog; + p.section = StorageProperty::Section::ErrorLog; p.value = get_node_data(json_root_node, "ata_smart_error_log/extended/count").value_or(0); add_property(p); section_properties_found = true; @@ -852,9 +831,9 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_error block.lba = get_node_data(table_entry, "completion_registers/lba").value_or(0); block.type_more_info = get_node_data(table_entry, "error_description").value_or(std::string()); - AtaStorageProperty p; + StorageProperty p; p.set_name(std::format("Error {}", block.error_num)); - p.section = AtaStorageProperty::Section::ErrorLog; + p.section = StorageProperty::Section::ErrorLog; p.value = block; add_property(p); } @@ -864,7 +843,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_error if (!section_properties_found) { return hz::Unexpected(SmartctlParserError::NoSection, - std::format("No section {} parsed.", AtaStorageProperty::get_readable_section_name(AtaStorageProperty::Section::ErrorLog))); + std::format("No section {} parsed.", StorageProperty::get_readable_section_name(StorageProperty::Section::ErrorLog))); } return {}; @@ -880,9 +859,9 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_selft // Revision if (get_node_exists(json_root_node, "ata_smart_self_test_log/extended/revision").value_or(false)) { - AtaStorageProperty p; + StorageProperty p; p.set_name("ata_smart_self_test_log/extended/revision", "ata_smart_self_test_log/extended/revision", _("SMART extended self-test log version")); - p.section = AtaStorageProperty::Section::SelftestLog; + p.section = StorageProperty::Section::SelftestLog; p.value = get_node_data(json_root_node, "ata_smart_self_test_log/extended/revision").value_or(0); add_property(p); section_properties_found = true; @@ -892,9 +871,9 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_selft // Count { - AtaStorageProperty p; + StorageProperty p; p.set_name("ata_smart_self_test_log/extended/count", "ata_smart_self_test_log/extended/count", _("Self-test count")); - p.section = AtaStorageProperty::Section::SelftestLog; + p.section = StorageProperty::Section::SelftestLog; p.value = get_node_data(json_root_node, "ata_smart_self_test_log/extended/count").value_or(0); p.show_in_ui = false; add_property(p); @@ -902,9 +881,9 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_selft } // Error Count { - AtaStorageProperty p; + StorageProperty p; p.set_name("ata_smart_self_test_log/extended/error_count_total", "ata_smart_self_test_log/extended/error_count_total", _("Total error count")); - p.section = AtaStorageProperty::Section::SelftestLog; + p.section = StorageProperty::Section::SelftestLog; p.value = get_node_data(json_root_node, "ata_smart_self_test_log/extended/error_count_total").value_or(0); p.show_in_ui = false; add_property(p); @@ -912,9 +891,9 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_selft } // Outdated Error Count { - AtaStorageProperty p; + StorageProperty p; p.set_name("ata_smart_self_test_log/extended/error_count_outdated", "ata_smart_self_test_log/extended/error_count_outdated", _("Outdated error count")); - p.section = AtaStorageProperty::Section::SelftestLog; + p.section = StorageProperty::Section::SelftestLog; p.value = get_node_data(json_root_node, "ata_smart_self_test_log/extended/error_count_outdated").value_or(0); p.show_in_ui = false; add_property(p); @@ -923,9 +902,9 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_selft // Displayed Counts if (!counts.empty()) { - AtaStorageProperty p; + StorageProperty p; p.set_name("ata_smart_self_test_log/extended/_counts", "ata_smart_self_test_log/extended/_counts", _("Entries")); - p.section = AtaStorageProperty::Section::SelftestLog; + p.section = StorageProperty::Section::SelftestLog; p.value = hz::string_join(counts, "; "); add_property(p); @@ -960,9 +939,9 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_selft entry.status = AtaStorageSelftestEntry::Status::Unknown; } - AtaStorageProperty p; + StorageProperty p; p.set_name(std::format("Self-test entry {}", entry.test_num)); - p.section = AtaStorageProperty::Section::SelftestLog; + p.section = StorageProperty::Section::SelftestLog; p.value = entry; add_property(p); @@ -974,7 +953,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_selft if (!section_properties_found) { return hz::Unexpected(SmartctlParserError::NoSection, - std::format("No section {} parsed.", AtaStorageProperty::get_readable_section_name(AtaStorageProperty::Section::SelftestLog))); + std::format("No section {} parsed.", StorageProperty::get_readable_section_name(StorageProperty::Section::SelftestLog))); } return {}; @@ -992,29 +971,29 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_selec std::vector lines; if (get_node_exists(json_root_node, "ata_smart_selective_self_test_log/revision").value_or(false)) { - AtaStorageProperty p; + StorageProperty p; p.set_name("ata_smart_selective_self_test_log/revision", "ata_smart_selective_self_test_log/revision", _("SMART Selective self-test log data structure revision number")); - p.section = AtaStorageProperty::Section::SelectiveSelftestLog; + p.section = StorageProperty::Section::SelectiveSelftestLog; p.value = get_node_data(json_root_node, "ata_smart_selective_self_test_log/revision").value_or(0); add_property(p); section_properties_found = true; } if (get_node_exists(json_root_node, "ata_smart_selective_self_test_log/power_up_scan_resume_minutes").value_or(false)) { - AtaStorageProperty p; + StorageProperty p; p.set_name("ata_smart_selective_self_test_log/power_up_scan_resume_minutes", "ata_smart_selective_self_test_log/power_up_scan_resume_minutes", _("If Selective self-test is pending on power-up, resume delay (minutes)")); - p.section = AtaStorageProperty::Section::SelectiveSelftestLog; + p.section = StorageProperty::Section::SelectiveSelftestLog; p.value = get_node_data(json_root_node, "ata_smart_selective_self_test_log/power_up_scan_resume_minutes").value_or(0); add_property(p); section_properties_found = true; } if (get_node_exists(json_root_node, "ata_smart_selective_self_test_log/remainder_scan_enabled").value_or(false)) { - AtaStorageProperty p; + StorageProperty p; p.set_name("ata_smart_selective_self_test_log/remainder_scan_enabled", "ata_smart_selective_self_test_log/remainder_scan_enabled", _("After scanning selected spans, scan remainder of the drive")); - p.section = AtaStorageProperty::Section::SelectiveSelftestLog; + p.section = StorageProperty::Section::SelectiveSelftestLog; p.value = get_node_data(json_root_node, "ata_smart_selective_self_test_log/remainder_scan_enabled").value_or(0); add_property(p); section_properties_found = true; @@ -1043,9 +1022,9 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_selec // The whole section { - AtaStorageProperty p; + StorageProperty p; p.set_name("SMART selective self-test log", "ata_smart_selective_self_test_log/_merged"); - p.section = AtaStorageProperty::Section::SelectiveSelftestLog; + p.section = StorageProperty::Section::SelectiveSelftestLog; p.reported_value = hz::string_join(lines, "\n"); p.value = p.reported_value; // string-type value @@ -1057,7 +1036,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_selec if (!section_properties_found) { return hz::Unexpected(SmartctlParserError::NoSection, - std::format("No section {} parsed.", AtaStorageProperty::get_readable_section_name(AtaStorageProperty::Section::SelectiveSelftestLog))); + std::format("No section {} parsed.", StorageProperty::get_readable_section_name(StorageProperty::Section::SelectiveSelftestLog))); } return {}; @@ -1133,9 +1112,9 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_sctte // The whole section if (!lines.empty()) { - AtaStorageProperty p; + StorageProperty p; p.set_name("Temperature log", "ata_sct_status/_and/ata_sct_temperature_history/_merged"); - p.section = AtaStorageProperty::Section::TemperatureLog; + p.section = StorageProperty::Section::TemperatureLog; p.reported_value = hz::string_join(lines, "\n"); p.value = p.reported_value; // string-type value add_property(p); @@ -1147,7 +1126,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_sctte if (!section_properties_found) { return hz::Unexpected(SmartctlParserError::NoSection, - std::format("No section {} parsed.", AtaStorageProperty::get_readable_section_name(AtaStorageProperty::Section::TemperatureLog))); + std::format("No section {} parsed.", StorageProperty::get_readable_section_name(StorageProperty::Section::TemperatureLog))); } return {}; @@ -1177,9 +1156,9 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_scter // The whole section if (!lines.empty()) { - AtaStorageProperty p; + StorageProperty p; p.set_name("SCT error recovery log", "ata_sct_erc/_merged"); - p.section = AtaStorageProperty::Section::ErcLog; + p.section = StorageProperty::Section::ErcLog; p.reported_value = hz::string_join(lines, "\n"); p.value = p.reported_value; // string-type value add_property(p); @@ -1189,7 +1168,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_scter if (!section_properties_found) { return hz::Unexpected(SmartctlParserError::NoSection, - std::format("No section {} parsed.", AtaStorageProperty::get_readable_section_name(AtaStorageProperty::Section::ErcLog))); + std::format("No section {} parsed.", StorageProperty::get_readable_section_name(StorageProperty::Section::ErcLog))); } return {}; @@ -1213,9 +1192,9 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_devst page_stat.is_header = true; page_stat.page = get_node_data(page_entry, "number").value_or(0); - AtaStorageProperty page_prop; + StorageProperty page_prop; page_prop.set_name(get_node_data(page_entry, "name").value_or(std::string())); - page_prop.section = AtaStorageProperty::Section::Devstat; + page_prop.section = StorageProperty::Section::Devstat; page_prop.value = page_stat; add_property(page_prop); @@ -1231,9 +1210,9 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_devst s.value = std::to_string(get_node_data(table_entry, "value").value_or(0)); s.offset = get_node_data(table_entry, "offset").value_or(0); - AtaStorageProperty p; + StorageProperty p; p.set_name(get_node_data(table_entry, "name").value_or(std::string())); - p.section = AtaStorageProperty::Section::Devstat; + p.section = StorageProperty::Section::Devstat; p.value = s; add_property(p); } @@ -1245,7 +1224,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_devst if (!section_properties_found) { return hz::Unexpected(SmartctlParserError::NoSection, - std::format("No section {} parsed.", AtaStorageProperty::get_readable_section_name(AtaStorageProperty::Section::Devstat))); + std::format("No section {} parsed.", StorageProperty::get_readable_section_name(StorageProperty::Section::Devstat))); } return {}; @@ -1285,9 +1264,9 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_satap // The whole section { - AtaStorageProperty p; + StorageProperty p; p.set_name("SATA Phy Log", "sata_phy_event_counters/_merged"); - p.section = AtaStorageProperty::Section::PhyLog; + p.section = StorageProperty::Section::PhyLog; p.reported_value = hz::string_join(lines, "\n"); p.value = p.reported_value; // string-type value @@ -1299,7 +1278,7 @@ hz::ExpectedVoid SmartctlJsonAtaParser::parse_section_satap if (!section_properties_found) { return hz::Unexpected(SmartctlParserError::NoSection, - std::format("No section {} parsed.", AtaStorageProperty::get_readable_section_name(AtaStorageProperty::Section::PhyLog))); + std::format("No section {} parsed.", StorageProperty::get_readable_section_name(StorageProperty::Section::PhyLog))); } return {}; diff --git a/src/applib/smartctl_json_basic_parser.cpp b/src/applib/smartctl_json_basic_parser.cpp index 2ee17c4..e8416ed 100644 --- a/src/applib/smartctl_json_basic_parser.cpp +++ b/src/applib/smartctl_json_basic_parser.cpp @@ -30,7 +30,7 @@ Copyright: //#include "app_pcrecpp.h" //#include "smartctl_text_ata_parser.h" //#include "ata_storage_property_descr.h" -#include "ata_storage_property.h" +#include "storage_property.h" #include "smartctl_json_parser_helpers.h" #include "smartctl_parser_types.h" //#include "smartctl_version_parser.h" @@ -54,7 +54,7 @@ hz::ExpectedVoid SmartctlJsonBasicParser::parse(std::string return hz::Unexpected(SmartctlParserError::SyntaxError, std::string("Invalid JSON data: ") + e.what()); } - AtaStorageProperty merged_property, full_property; + StorageProperty merged_property, full_property; auto version_parse_status = SmartctlJsonParserHelpers::parse_version(json_root_node, merged_property, full_property); if (!version_parse_status) { return version_parse_status; @@ -78,10 +78,10 @@ hz::ExpectedVoid SmartctlJsonBasicParser::parse_section_bas {"device/type", _("Smartctl Device Type"), // nvme, sat, etc. [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { if (auto jval = get_node_data(root_node, "device/type"); jval.has_value()) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); p.value = jval.value(); p.show_in_ui = false; @@ -117,10 +117,10 @@ hz::ExpectedVoid SmartctlJsonBasicParser::parse_section_bas {"user_capacity/bytes/_short", _("Capacity"), [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { if (auto jval = get_node_data(root_node, "user_capacity/bytes"); jval) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); p.readable_value = hz::format_size(static_cast(jval.value()), true); p.value = jval.value(); @@ -133,7 +133,7 @@ hz::ExpectedVoid SmartctlJsonBasicParser::parse_section_bas {"physical_block_size/_and/logical_block_size", _("Sector Size"), [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { std::vector values; if (auto jval1 = get_node_data(root_node, "logical_block_size"); jval1) { @@ -143,7 +143,7 @@ hz::ExpectedVoid SmartctlJsonBasicParser::parse_section_bas values.emplace_back(std::format("{} bytes physical", jval2.value())); } if (!values.empty()) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); p.readable_value = hz::string_join(values, ", "); p.value = p.readable_value; @@ -162,7 +162,7 @@ hz::ExpectedVoid SmartctlJsonBasicParser::parse_section_bas {"interface_speed/_merged", _("Interface Speed"), [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { std::vector values; if (auto jval1 = get_node_data(root_node, "interface_speed/max/string"); jval1) { @@ -172,7 +172,7 @@ hz::ExpectedVoid SmartctlJsonBasicParser::parse_section_bas values.emplace_back(std::format("Current: {}", jval2.value())); } if (!values.empty()) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); p.readable_value = hz::string_join(values, ", "); p.value = p.readable_value; @@ -189,23 +189,10 @@ hz::ExpectedVoid SmartctlJsonBasicParser::parse_section_bas {"smart_status/passed", _("Overall Health Self-Assessment Test"), bool_formatter(_("PASSED"), _("FAILED"))}, - {"rotation_rate", _("Rotation Rate"), // (S)ATA, used to detect HDD vs SSD - [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue - { - if (auto jval = get_node_data(root_node, key); jval) { - AtaStorageProperty p; - p.set_name(key, key, displayable_name); - p.readable_value = std::format("{} RPM", jval.value()); - p.value = jval.value(); - return p; - } - return hz::Unexpected(SmartctlParserError::KeyNotFound, std::format("Error getting key {} from JSON data.", key)); - } - }, + // (S)ATA, used to detect HDD vs SSD + {"rotation_rate", _("Rotation Rate"), integer_formatter("{} RPM")}, {"form_factor/name", _("Form Factor"), string_formatter()}, - }; for (const auto& [key, displayable_name, retrieval_func] : info_keys) { @@ -213,7 +200,7 @@ hz::ExpectedVoid SmartctlJsonBasicParser::parse_section_bas auto p = retrieval_func(json_root_node, key, displayable_name); if (p.has_value()) { // ignore if not found - p->section = AtaStorageProperty::Section::Info; + p->section = StorageProperty::Section::Info; add_property(p.value()); } } diff --git a/src/applib/smartctl_json_nvme_parser.cpp b/src/applib/smartctl_json_nvme_parser.cpp index 284a010..ca22ea9 100644 --- a/src/applib/smartctl_json_nvme_parser.cpp +++ b/src/applib/smartctl_json_nvme_parser.cpp @@ -22,7 +22,7 @@ Copyright: #include "json/json.hpp" -#include "ata_storage_property.h" +#include "storage_property.h" #include "hz/debug.h" #include "hz/string_algo.h" // #include "smartctl_version_parser.h" @@ -49,7 +49,7 @@ hz::ExpectedVoid SmartctlJsonNvmeParser::parse(std::string_ return hz::Unexpected(SmartctlParserError::SyntaxError, std::string("Invalid JSON data: ") + e.what()); } - AtaStorageProperty merged_property, full_property; + StorageProperty merged_property, full_property; auto version_parse_status = SmartctlJsonParserHelpers::parse_version(json_root_node, merged_property, full_property); if (!version_parse_status) { return version_parse_status; @@ -66,29 +66,29 @@ hz::ExpectedVoid SmartctlJsonNvmeParser::parse(std::string_ // Add properties for each parsed section so that the UI knows which tabs to show or hide { auto section_parse_status = parse_section_health(json_root_node); - AtaStorageProperty p; - p.section = AtaStorageProperty::Section::Health; + StorageProperty p; + p.section = StorageProperty::Section::Health; p.set_name("_parser/health_section_available"); p.value = section_parse_status.has_value() || section_parse_status.error().data() != SmartctlParserError::NoSection; } { auto section_parse_status = parse_section_error_log(json_root_node); - AtaStorageProperty p; - p.section = AtaStorageProperty::Section::ErrorLog; + StorageProperty p; + p.section = StorageProperty::Section::ErrorLog; p.set_name("_parser/error_log_section_available"); p.value = section_parse_status.has_value() || section_parse_status.error().data() != SmartctlParserError::NoSection; } { auto section_parse_status = parse_section_selftest_log(json_root_node); - AtaStorageProperty p; - p.section = AtaStorageProperty::Section::SelftestLog; + StorageProperty p; + p.section = StorageProperty::Section::SelftestLog; p.set_name("_parser/selftest_log_section_available"); p.value = section_parse_status.has_value() || section_parse_status.error().data() != SmartctlParserError::NoSection; } { - auto section_parse_status = parse_section_health_log(json_root_node); - AtaStorageProperty p; - p.section = AtaStorageProperty::Section::Devstat; + auto section_parse_status = parse_section_nvme_attributes(json_root_node); + StorageProperty p; + p.section = StorageProperty::Section::Devstat; p.set_name("_parser/devstat_section_available"); p.value = section_parse_status.has_value() || section_parse_status.error().data() != SmartctlParserError::NoSection; } @@ -109,10 +109,10 @@ hz::ExpectedVoid SmartctlJsonNvmeParser::parse_section_info {"device/type", _("Smartctl Device Type"), // nvme, sat, etc. [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { if (auto jval = get_node_data(root_node, "device/type"); jval.has_value()) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); p.value = jval.value(); p.show_in_ui = false; @@ -158,10 +158,10 @@ hz::ExpectedVoid SmartctlJsonNvmeParser::parse_section_info {"user_capacity/bytes/_short", _("Capacity"), [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { if (auto jval = get_node_data(root_node, "user_capacity/bytes"); jval) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); p.readable_value = hz::format_size(static_cast(jval.value()), true); p.value = jval.value(); @@ -172,30 +172,12 @@ hz::ExpectedVoid SmartctlJsonNvmeParser::parse_section_info } }, - {"logical_block_size", _("Logical Block Size"), - custom_string_formatter([](int64_t value) - { - return std::format("{} bytes", value); - }) - }, - - {"power_cycle_count", _("Number of Power Cycles"), string_formatter()}, - {"power_on_time/hours", _("Powered for"), - custom_string_formatter([](int64_t value) - { - return std::format("{} hours", value); - }) - }, - - {"temperature/current", _("Current Temperature"), - custom_string_formatter([](int64_t value) - { - return std::format("{}° Celsius", value); - }) - }, + {"logical_block_size", _("Logical Block Size"), integer_formatter("{} bytes")}, + {"power_cycle_count", _("Number of Power Cycles"), integer_formatter()}, + {"power_on_time/hours", _("Powered for"), integer_formatter("{} hours")}, + {"temperature/current", _("Current Temperature"), integer_formatter("{}° Celsius")}, {"nvme_version/string", _("NVMe Version"), string_formatter()}, - {"local_time/asctime", _("Scanned on"), string_formatter()}, {"smart_support/available", _("SMART Supported"), bool_formatter(_("Yes"), _("No"))}, @@ -208,7 +190,7 @@ hz::ExpectedVoid SmartctlJsonNvmeParser::parse_section_info auto p = retrieval_func(json_root_node, key, displayable_name); if (p.has_value()) { // ignore if not found - p->section = AtaStorageProperty::Section::Info; + p->section = StorageProperty::Section::Info; add_property(p.value()); any_found = true; } @@ -226,8 +208,19 @@ hz::ExpectedVoid SmartctlJsonNvmeParser::parse_section_heal { using namespace SmartctlJsonParserHelpers; + bool section_properties_found = false; + const std::vector> health_keys = { {"smart_status/passed", _("Overall Health Self-Assessment Test"), bool_formatter(_("PASSED"), _("FAILED"))}, + + // These are included when smart_status/passed is false + {"smart_status/nvme/spare_below_threshold", _("Available Spare Fallen Below Threshold"), bool_formatter(_("Yes"), _("No"))}, + {"smart_status/nvme/temperature_above_or_below_threshold", _("Temperature Outside Limits"), bool_formatter(_("Yes"), _("No"))}, + {"smart_status/nvme/reliability_degraded", _("NVM Subsystem Reliability Degraded"), bool_formatter(_("Yes"), _("No"))}, + {"smart_status/nvme/media_read_only", _("Media Placed in Read-Only Mode"), bool_formatter(_("Yes"), _("No"))}, + {"smart_status/nvme/volatile_memory_backup_failed", _("Volatile Memory Backup Failed"), bool_formatter(_("Yes"), _("No"))}, + {"smart_status/nvme/persistent_memory_region_unreliable", _("Persistent Memory Region Is Read-Only or Unreliable"), bool_formatter(_("Yes"), _("No"))}, + {"smart_status/nvme/other", _("Unknown Critical Warnings"), bool_formatter(_("Yes"), _("No"))}, }; for (const auto& [key, displayable_name, retrieval_func] : health_keys) { @@ -235,11 +228,18 @@ hz::ExpectedVoid SmartctlJsonNvmeParser::parse_section_heal auto p = retrieval_func(json_root_node, key, displayable_name); if (p.has_value()) { // ignore if not found - p->section = AtaStorageProperty::Section::Health; + p->section = StorageProperty::Section::Health; add_property(p.value()); + + section_properties_found = true; } } + if (!section_properties_found) { + return hz::Unexpected(SmartctlParserError::NoSection, + std::format("No section {} parsed.", StorageProperty::get_readable_section_name(StorageProperty::Section::Health))); + } + return {}; } @@ -256,7 +256,7 @@ hz::ExpectedVoid SmartctlJsonNvmeParser::parse_section_erro if (!section_properties_found) { return hz::Unexpected(SmartctlParserError::NoSection, - std::format("No section {} parsed.", AtaStorageProperty::get_readable_section_name(AtaStorageProperty::Section::ErrorLog))); + std::format("No section {} parsed.", StorageProperty::get_readable_section_name(StorageProperty::Section::ErrorLog))); } return {}; @@ -272,91 +272,92 @@ hz::ExpectedVoid SmartctlJsonNvmeParser::parse_section_self bool section_properties_found = false; - // Revision - if (get_node_exists(json_root_node, "ata_smart_self_test_log/extended/revision").value_or(false)) { - AtaStorageProperty p; - p.set_name("ata_smart_self_test_log/extended/revision", "ata_smart_self_test_log/extended/revision", _("SMART extended self-test log version")); - p.section = AtaStorageProperty::Section::SelftestLog; - p.value = get_node_data(json_root_node, "ata_smart_self_test_log/extended/revision").value_or(0); - add_property(p); - section_properties_found = true; - } - - std::vector counts; - - // Count { - AtaStorageProperty p; - p.set_name("ata_smart_self_test_log/extended/count", "ata_smart_self_test_log/extended/count", _("Self-test count")); - p.section = AtaStorageProperty::Section::SelftestLog; - p.value = get_node_data(json_root_node, "ata_smart_self_test_log/extended/count").value_or(0); - p.show_in_ui = false; - add_property(p); - counts.emplace_back(std::format("Self-test entries: {}", p.get_value())); + StorageProperty p; + p.set_name("nvme_self_test_log/current_self_test_operation/value/_decoded", + "nvme_self_test_log/current_self_test_operation/value/_decoded", _("Current Self-Test Operation")); + p.section = StorageProperty::Section::SelftestLog; + + auto value_val = get_node_data(json_root_node, "nvme_self_test_log/current_self_test_operation/value"); + NvmeSelfTestCurrentOperationType operation = NvmeSelfTestCurrentOperationType::Unknown; + if (value_val.has_value()) { + switch (value_val.value()) { + // Data from smartmontools/nvmeprint.cpp + case 0x0: operation = NvmeSelfTestCurrentOperationType::None; break; + case 0x1: operation = NvmeSelfTestCurrentOperationType::ShortInProgress; break; + case 0x2: operation = NvmeSelfTestCurrentOperationType::ExtendedInProgress; break; + case 0xe: operation = NvmeSelfTestCurrentOperationType::VendorSpecificInProgress; break; + default: break; // Unknown + } + p.value = NvmeSelfTestCurrentOperationTypeExt::get_storable_name(operation); + p.readable_value = NvmeSelfTestCurrentOperationTypeExt::get_displayable_name(operation); + add_property(p); + + section_properties_found = true; + } } - // Error Count + { - AtaStorageProperty p; - p.set_name("ata_smart_self_test_log/extended/error_count_total", "ata_smart_self_test_log/extended/error_count_total", _("Total error count")); - p.section = AtaStorageProperty::Section::SelftestLog; - p.value = get_node_data(json_root_node, "ata_smart_self_test_log/extended/error_count_total").value_or(0); - p.show_in_ui = false; - add_property(p); - counts.emplace_back(std::format("Total error count: {}", p.get_value())); - } - // Outdated Error Count - { - AtaStorageProperty p; - p.set_name("ata_smart_self_test_log/extended/error_count_outdated", "ata_smart_self_test_log/extended/error_count_outdated", _("Outdated error count")); - p.section = AtaStorageProperty::Section::SelftestLog; - p.value = get_node_data(json_root_node, "ata_smart_self_test_log/extended/error_count_outdated").value_or(0); - p.show_in_ui = false; - add_property(p); - counts.emplace_back(std::format("Outdated error count: {}", p.get_value())); + StorageProperty p; + p.set_name("nvme_self_test_log/current_self_test_operation/current_self_test_completion_percent", + "nvme_self_test_log/current_self_test_operation/current_self_test_completion_percent", _("Current Self-Test Completion Percentage")); + p.section = StorageProperty::Section::SelftestLog; + + auto value_val = get_node_data(json_root_node, "nvme_self_test_log/current_self_test_operation/current_self_test_completion_percent"); + if (value_val.has_value()) { + p.value = value_val.value(); + p.readable_value = std::format("{} %", value_val.value()); + add_property(p); + } } - // Displayed Counts - if (!counts.empty()) { - AtaStorageProperty p; - p.set_name("ata_smart_self_test_log/extended/_counts", "ata_smart_self_test_log/extended/_counts", _("Entries")); - p.section = AtaStorageProperty::Section::SelftestLog; - p.value = hz::string_join(counts, "; "); - add_property(p); - - section_properties_found = true; - } - - const std::string table_key = "ata_smart_self_test_log/extended/table"; + const std::string table_key = "nvme_self_test_log/table"; auto table_node = get_node(json_root_node, table_key); // Entries if (table_node.has_value() && table_node->is_array()) { uint32_t entry_num = 1; for (const auto& table_entry : table_node.value()) { - AtaStorageSelftestEntry entry; + NvmeStorageSelftestEntry entry; entry.test_num = entry_num; - entry.type = get_node_data(table_entry, "type/string").value_or(std::string()); // FIXME use type/value for i18n - entry.status_str = get_node_data(table_entry, "status/string").value_or(std::string()); - entry.remaining_percent = get_node_data(table_entry, "status/remaining_percent").value_or(0); - entry.lifetime_hours = get_node_data(table_entry, "lifetime_hours").value_or(0); - entry.passed = get_node_data(table_entry, "status/passed").value_or(false); - if (get_node_exists(table_entry, "lba").value_or(false)) { - entry.lba_of_first_error = std::format("0x{:X}", get_node_data(table_entry, "lba").value_or(0)); - } else { - entry.lba_of_first_error = "-"; + NvmeSelfTestType test_type = NvmeSelfTestType::Unknown; + if (get_node_exists(table_entry, "self_test_code/value").value_or(false)) { + const int32_t type_value = get_node_data(table_entry, "self_test_code/value").value_or(int(NvmeSelfTestType::Unknown)); + switch(type_value) { + case 0x1: test_type = NvmeSelfTestType::Short; break; + case 0x2: test_type = NvmeSelfTestType::Extended; break; + case 0xe: test_type = NvmeSelfTestType::VendorSpecific; break; + default: break; // Unknown + } } - if (get_node_exists(table_entry, "status/value").value_or(false)) { - const uint8_t status_value = get_node_data(table_entry, "status/value").value_or(0); - entry.status = static_cast(status_value >> 4); - } else { - entry.status = AtaStorageSelftestEntry::Status::Unknown; + NvmeSelfTestResultType test_result = NvmeSelfTestResultType::Unknown; + if (get_node_exists(table_entry, "self_test_code/value").value_or(false)) { + const int32_t type_value = get_node_data(table_entry, "self_test_code/value").value_or(int(NvmeSelfTestType::Unknown)); + switch(type_value) { + case 0x0: test_result = NvmeSelfTestResultType::CompletedNoError; break; + case 0x1: test_result = NvmeSelfTestResultType::AbortedSelfTestCommand; break; + case 0x2: test_result = NvmeSelfTestResultType::AbortedControllerReset; break; + case 0x3: test_result = NvmeSelfTestResultType::AbortedNamespaceRemoved; break; + case 0x4: test_result = NvmeSelfTestResultType::AbortedFormatNvmCommand; break; + case 0x5: test_result = NvmeSelfTestResultType::FatalOrUnknownTestError; break; + case 0x6: test_result = NvmeSelfTestResultType::CompletedUnknownFailedSegment; break; + case 0x7: test_result = NvmeSelfTestResultType::CompletedFailedSegments; break; + case 0x8: test_result = NvmeSelfTestResultType::AbortedUnknownReason; break; + case 0x9: test_result = NvmeSelfTestResultType::AbortedSanitizeOperation; break; + default: break; // Unknown + } } - AtaStorageProperty p; + entry.type = test_type; + entry.result = test_result; + entry.power_on_hours = get_node_data(table_entry, "power_on_hours").value_or(0); + entry.lba = get_node_data(table_entry, "lba").value_or(0); + + StorageProperty p; p.set_name(std::format("Self-test entry {}", entry.test_num)); - p.section = AtaStorageProperty::Section::SelftestLog; + p.section = StorageProperty::Section::SelftestLog; p.value = entry; add_property(p); @@ -368,7 +369,7 @@ hz::ExpectedVoid SmartctlJsonNvmeParser::parse_section_self if (!section_properties_found) { return hz::Unexpected(SmartctlParserError::NoSection, - std::format("No section {} parsed.", AtaStorageProperty::get_readable_section_name(AtaStorageProperty::Section::SelftestLog))); + std::format("No section {} parsed.", StorageProperty::get_readable_section_name(StorageProperty::Section::SelftestLog))); } return {}; @@ -376,49 +377,37 @@ hz::ExpectedVoid SmartctlJsonNvmeParser::parse_section_self -hz::ExpectedVoid SmartctlJsonNvmeParser::parse_section_health_log(const nlohmann::json& json_root_node) +hz::ExpectedVoid SmartctlJsonNvmeParser::parse_section_nvme_attributes(const nlohmann::json& json_root_node) { - // nvme_smart_health_information_log - using namespace SmartctlJsonParserHelpers; bool section_properties_found = false; - const std::string pages_key = "ata_device_statistics/pages"; - auto page_node = get_node(json_root_node, pages_key); + const std::vector> health_keys = { + {"nvme_smart_health_information_log/available_spare", _("Available Spare"), integer_formatter("{}%")}, + {"nvme_smart_health_information_log/available_spare_threshold", _("Available Spare Threshold"), integer_formatter("{}%")}, + {"nvme_smart_health_information_log/percentage_used", _("Percentage Used"), integer_formatter("{}%")}, + {"nvme_smart_health_information_log/data_units_read", _("Data Units Read"), integer_formatter()}, + {"nvme_smart_health_information_log/data_units_written", _("Data Units Written"), integer_formatter()}, + {"nvme_smart_health_information_log/host_reads", _("Host Read Commands"), integer_formatter()}, + {"nvme_smart_health_information_log/host_writes", _("Host Write Commands"), integer_formatter()}, + {"nvme_smart_health_information_log/controller_busy_time", _("Controller Busy Time"), integer_formatter()}, + {"nvme_smart_health_information_log/power_cycles", _("Power Cycles"), integer_formatter()}, + {"nvme_smart_health_information_log/power_on_hours", _("Power On Hours"), integer_formatter()}, + {"nvme_smart_health_information_log/unsafe_shutdowns", _("Unsafe Shutdowns"), integer_formatter()}, + {"nvme_smart_health_information_log/media_errors", _("Media and Data Integrity Errors"), integer_formatter()}, + {"nvme_smart_health_information_log/num_err_log_entries", _("Error Information Log Entries"), integer_formatter()}, + {"nvme_smart_health_information_log/warning_temp_time", _("Warning Comp. Temperature Time"), integer_formatter()}, + {"nvme_smart_health_information_log/critical_comp_time", _("Critical Comp. Temperature Time"), integer_formatter()}, + }; - // Entries - if (page_node.has_value() && page_node->is_array()) { - for (const auto& page_entry : page_node.value()) { - AtaStorageStatistic page_stat; - page_stat.is_header = true; - page_stat.page = get_node_data(page_entry, "number").value_or(0); + for (const auto& [key, displayable_name, retrieval_func] : health_keys) { + DBG_ASSERT(retrieval_func != nullptr); - AtaStorageProperty page_prop; - page_prop.set_name(get_node_data(page_entry, "name").value_or(std::string())); - page_prop.section = AtaStorageProperty::Section::Devstat; - page_prop.value = page_stat; - add_property(page_prop); - - const std::string table_key = "table"; - auto table_node = get_node(page_entry, table_key); - - if (table_node.has_value() && table_node->is_array()) { - for (const auto& table_entry : table_node.value()) { - AtaStorageStatistic s; - s.page = page_stat.page; - s.flags = get_node_data(table_entry, "flags/string").value_or(std::string()); - s.value_int = get_node_data(table_entry, "value").value_or(0); - s.value = std::to_string(get_node_data(table_entry, "value").value_or(0)); - s.offset = get_node_data(table_entry, "offset").value_or(0); - - AtaStorageProperty p; - p.set_name(get_node_data(table_entry, "name").value_or(std::string())); - p.section = AtaStorageProperty::Section::Devstat; - p.value = s; - add_property(p); - } - } + auto p = retrieval_func(json_root_node, key, displayable_name); + if (p.has_value()) { // ignore if not found + p->section = StorageProperty::Section::NvmeAttributes; + add_property(p.value()); section_properties_found = true; } @@ -426,7 +415,7 @@ hz::ExpectedVoid SmartctlJsonNvmeParser::parse_section_heal if (!section_properties_found) { return hz::Unexpected(SmartctlParserError::NoSection, - std::format("No section {} parsed.", AtaStorageProperty::get_readable_section_name(AtaStorageProperty::Section::Devstat))); + std::format("No section {} parsed.", StorageProperty::get_readable_section_name(StorageProperty::Section::NvmeAttributes))); } return {}; diff --git a/src/applib/smartctl_json_nvme_parser.h b/src/applib/smartctl_json_nvme_parser.h index f5c3624..d43aaa6 100644 --- a/src/applib/smartctl_json_nvme_parser.h +++ b/src/applib/smartctl_json_nvme_parser.h @@ -48,7 +48,7 @@ class SmartctlJsonNvmeParser : public SmartctlParser { hz::ExpectedVoid parse_section_selftest_log(const nlohmann::json& json_root_node); /// Parse a section from json data - hz::ExpectedVoid parse_section_health_log(const nlohmann::json& json_root_node); + hz::ExpectedVoid parse_section_nvme_attributes(const nlohmann::json& json_root_node); }; diff --git a/src/applib/smartctl_json_parser_helpers.h b/src/applib/smartctl_json_parser_helpers.h index 3b604ca..c5943ac 100644 --- a/src/applib/smartctl_json_parser_helpers.h +++ b/src/applib/smartctl_json_parser_helpers.h @@ -26,7 +26,7 @@ Copyright: #include "smartctl_version_parser.h" #include "hz/format_unit.h" #include "hz/error_container.h" -#include "ata_storage_property.h" +#include "storage_property.h" @@ -158,7 +158,7 @@ get_node_exists(const nlohmann::json& root, std::string_view path) /// A signature for a property retrieval function. using PropertyRetrievalFunc = std::function< auto(const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue >; + -> hz::ExpectedValue >; @@ -166,10 +166,10 @@ using PropertyRetrievalFunc = std::function< inline auto string_formatter() { return [](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { if (auto jval = get_node_data(root_node, key); jval) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); // p.reported_value = jval.value(); p.readable_value = jval.value(); @@ -184,10 +184,10 @@ inline auto string_formatter() /// Return a lambda which returns a return_property if conditional_path exists. /// If the path doesn't exist, an error is returned. -inline auto conditional_formatter(const std::string_view conditional_path, AtaStorageProperty return_property) +inline auto conditional_formatter(const std::string_view conditional_path, StorageProperty return_property) { return [conditional_path, return_property](const nlohmann::json& root_node, const std::string& key, [[maybe_unused]] const std::string& displayable_name) mutable - -> hz::ExpectedValue + -> hz::ExpectedValue { auto node_exists_result = get_node_exists(root_node, conditional_path); if (!node_exists_result.has_value()) { @@ -210,10 +210,10 @@ inline auto conditional_formatter(const std::string_view conditional_path, AtaSt inline auto bool_formatter(const std::string_view& true_str, const std::string_view& false_str) { return [true_str, false_str](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { if (auto jval = get_node_data(root_node, key); jval) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); // p.reported_value = (jval.value() ? true_str : false_str); p.readable_value = (jval.value() ? true_str : false_str); @@ -226,15 +226,37 @@ inline auto bool_formatter(const std::string_view& true_str, const std::string_v +/// Return a lambda which retrieves a key value as an integer of type IntegerType +/// and formats it using locale, placing it in format_string. +template +auto integer_formatter(const std::string& format_string = "{}") +{ + return [format_string](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) + -> hz::ExpectedValue + { + if (auto jval = get_node_data(root_node, key); jval) { + StorageProperty p; + p.set_name(key, key, displayable_name); + // p.reported_value = (jval.value() ? true_str : false_str); + p.readable_value = std::vformat(format_string, std::make_format_args(hz::number_to_string_locale(jval.value()))); + p.value = jval.value(); + return p; + } + return hz::Unexpected(SmartctlParserError::KeyNotFound, std::format("Error getting key {} from JSON data.", key)); + }; +} + + + /// Return a lambda which retrieves a key value as a string (formatted using another lambda), and sets it as a property. template auto custom_string_formatter(std::function formatter) { return [formatter](const nlohmann::json& root_node, const std::string& key, const std::string& displayable_name) - -> hz::ExpectedValue + -> hz::ExpectedValue { if (auto jval = get_node_data(root_node, key); jval) { - AtaStorageProperty p; + StorageProperty p; p.set_name(key, key, displayable_name); // p.reported_value = formatter(jval.value()); p.readable_value = formatter(jval.value()); @@ -249,7 +271,7 @@ auto custom_string_formatter(std::function formatter) /// Parse version from json output, returning 2 properties. [[nodiscard]] inline hz::ExpectedVoid parse_version(const nlohmann::json& json_root_node, - AtaStorageProperty& merged_property, AtaStorageProperty& full_property) + StorageProperty& merged_property, StorageProperty& full_property) { using namespace SmartctlJsonParserHelpers; @@ -276,7 +298,7 @@ auto custom_string_formatter(std::function formatter) // p.reported_value = smartctl_version; merged_property.readable_value = smartctl_version; merged_property.value = smartctl_version; // string-type value - merged_property.section = AtaStorageProperty::Section::Info; // add to info section + merged_property.section = StorageProperty::Section::Info; // add to info section } { full_property.set_name("Smartctl version", "smartctl/version/_merged_full", "Smartctl Version"); @@ -286,7 +308,7 @@ auto custom_string_formatter(std::function formatter) get_node_data(json_root_node, "smartctl/build_info", {}).value_or(std::string()) ); full_property.value = full_property.readable_value; // string-type value - full_property.section = AtaStorageProperty::Section::Info; // add to info section + full_property.section = StorageProperty::Section::Info; // add to info section } if (!SmartctlVersionParser::check_format_supported(SmartctlOutputFormat::Json, smartctl_version)) { debug_out_warn("app", DBG_FUNC_MSG << "Incompatible smartctl version. Returning.\n"); diff --git a/src/applib/smartctl_parser.cpp b/src/applib/smartctl_parser.cpp index 5840bcf..9c6507d 100644 --- a/src/applib/smartctl_parser.cpp +++ b/src/applib/smartctl_parser.cpp @@ -15,7 +15,7 @@ Copyright: #include #include "smartctl_parser.h" -#include "ata_storage_property.h" +#include "storage_property.h" #include "hz/error_container.h" #include "smartctl_text_ata_parser.h" #include "smartctl_json_ata_parser.h" @@ -92,7 +92,7 @@ const StoragePropertyRepository& SmartctlParser::get_property_repository() const // adds a property into property list, looks up and sets its description. // Yes, there's no place for this in the Parser, but whatever... -void SmartctlParser::add_property(AtaStorageProperty p) +void SmartctlParser::add_property(StorageProperty p) { properties_.add_property(std::move(p)); } diff --git a/src/applib/smartctl_parser.h b/src/applib/smartctl_parser.h index d469bd8..fdc0942 100644 --- a/src/applib/smartctl_parser.h +++ b/src/applib/smartctl_parser.h @@ -15,7 +15,7 @@ Copyright: #include #include -#include "ata_storage_property.h" +#include "storage_property.h" #include "smartctl_parser_types.h" #include "hz/error_container.h" #include "storage_property_repository.h" @@ -70,7 +70,7 @@ class SmartctlParser { protected: /// Add a property into property list, look up and set its description - void add_property(AtaStorageProperty p); + void add_property(StorageProperty p); private: diff --git a/src/applib/smartctl_parser_types.h b/src/applib/smartctl_parser_types.h index c0a3769..360c4d5 100644 --- a/src/applib/smartctl_parser_types.h +++ b/src/applib/smartctl_parser_types.h @@ -64,7 +64,7 @@ struct SmartctlParserPreferenceTypeExt SmartctlParserPreferenceTypeExt, Glib::ustring> { - static constexpr inline SmartctlParserPreferenceType default_value = SmartctlParserPreferenceType::Auto; + static constexpr SmartctlParserPreferenceType default_value = SmartctlParserPreferenceType::Auto; static std::unordered_map> build_enum_map() { diff --git a/src/applib/smartctl_text_ata_parser.cpp b/src/applib/smartctl_text_ata_parser.cpp index 004806e..371f57d 100644 --- a/src/applib/smartctl_text_ata_parser.cpp +++ b/src/applib/smartctl_text_ata_parser.cpp @@ -21,7 +21,7 @@ Copyright: #include // #include "hz/locale_tools.h" // ScopedCLocale, locale_c_get(). -#include "ata_storage_property.h" +#include "storage_property.h" #include "hz/string_algo.h" // string_* #include "hz/string_num.h" // string_is_numeric, number_to_string #include "hz/debug.h" // debug_* @@ -40,24 +40,24 @@ namespace { /// Get storage property by checksum error name (which corresponds to /// an output section). - inline AtaStorageProperty app_get_checksum_error_property(const std::string& name) + inline StorageProperty app_get_checksum_error_property(const std::string& name) { - AtaStorageProperty p; + StorageProperty p; if (name == "Attribute Data") { - p.section = AtaStorageProperty::Section::Attributes; + p.section = StorageProperty::Section::Attributes; p.set_name(name, "_text_only/attribute_data_checksum_error"); } else if (name == "Attribute Thresholds") { - p.section = AtaStorageProperty::Section::Attributes; + p.section = StorageProperty::Section::Attributes; p.set_name(name, "_text_only/attribute_thresholds_checksum_error"); } else if (name == "ATA Error Log") { - p.section = AtaStorageProperty::Section::ErrorLog; + p.section = StorageProperty::Section::ErrorLog; p.set_name(name, "_text_only/ata_error_log_checksum_error"); } else if (name == "Self-Test Log") { - p.section = AtaStorageProperty::Section::SelftestLog; + p.section = StorageProperty::Section::SelftestLog; p.set_name(name, "_text_only/selftest_log_checksum_error"); } @@ -213,19 +213,19 @@ hz::ExpectedVoid SmartctlTextAtaParser::parse(std::string_v } { - AtaStorageProperty p; + StorageProperty p; p.set_name("Smartctl version", "smartctl/version/_merged", "Smartctl Version"); p.reported_value = version; p.value = p.reported_value; // string-type value - p.section = AtaStorageProperty::Section::Info; // add to info section + p.section = StorageProperty::Section::Info; // add to info section add_property(p); } { - AtaStorageProperty p; + StorageProperty p; p.set_name("Smartctl version", "smartctl/version/_merged_full", "Smartctl Version"); p.reported_value = version_full; p.value = p.reported_value; // string-type value - p.section = AtaStorageProperty::Section::Info; // add to info section + p.section = StorageProperty::Section::Info; // add to info section add_property(p); } @@ -318,7 +318,7 @@ hz::ExpectedVoid SmartctlTextAtaParser::parse_section_info( { this->set_data_section_info(body); - const AtaStorageProperty::Section section = AtaStorageProperty::Section::Info; + const StorageProperty::Section section = StorageProperty::Section::Info; // split by lines. // e.g. Device Model: ST3500630AS @@ -339,7 +339,7 @@ hz::ExpectedVoid SmartctlTextAtaParser::parse_section_info( warning_msg += "\n" + line; } else { expecting_warning_lines = false; - AtaStorageProperty p; + StorageProperty p; p.section = section; p.set_name("Warning", "_text_only/info_warning", "Warning"); p.reported_value = warning_msg; @@ -401,7 +401,7 @@ http://knowledge.seagate.com/articles/en_US/FAQ/213891en hz::string_trim(name); hz::string_trim(value); - AtaStorageProperty p; + StorageProperty p; p.section = section; p.set_name(name); p.reported_value = value; @@ -426,10 +426,10 @@ http://knowledge.seagate.com/articles/en_US/FAQ/213891en // Parse a component (one line) of the info section -hz::ExpectedVoid SmartctlTextAtaParser::parse_section_info_property(AtaStorageProperty& p) +hz::ExpectedVoid SmartctlTextAtaParser::parse_section_info_property(StorageProperty& p) { // ---- Info - if (p.section != AtaStorageProperty::Section::Info) { + if (p.section != StorageProperty::Section::Info) { debug_out_error("app", DBG_FUNC_MSG << "Called with non-info section!\n"); return hz::Unexpected(SmartctlParserError::InternalError, "Internal parser error."); } @@ -781,8 +781,8 @@ Form Factor: 2.5 inches Device is: In smartctl database [for details use: -P show] */ - AtaStorageProperty pt; // template for easy copying - pt.section = AtaStorageProperty::Section::Health; + StorageProperty pt; // template for easy copying + pt.section = StorageProperty::Section::Health; std::string name, value; if (app_pcre_match("/^([^:\\n]+):[ \\t]*(.*)$/mi", sub, &name, &value)) { @@ -846,8 +846,8 @@ SCT capabilities: (0x003d) SCT Status supported. SCT Data Table supported. */ - AtaStorageProperty pt; // template for easy copying - pt.section = AtaStorageProperty::Section::Capabilities; + StorageProperty pt; // template for easy copying + pt.section = StorageProperty::Section::Capabilities; std::string sub = sub_initial; @@ -934,7 +934,7 @@ SCT capabilities: (0x003d) SCT Status supported. numvalue *= 60; // convert to seconds // add as a time property - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name(name); // well, not really as reported, but still... p.reported_value.append(numvalue_orig).append(" | ").append(strvalue_orig); @@ -950,7 +950,7 @@ SCT capabilities: (0x003d) SCT Status supported. // AtaStorageCapability properties (capabilities are flag lists) } else { - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name(name); // well, not really as reported, but still... p.reported_value.append(numvalue_orig).append(" | ").append(strvalue_orig); @@ -988,7 +988,7 @@ SCT capabilities: (0x003d) SCT Status supported. // Check the capabilities for internal properties we can use. -hz::ExpectedVoid SmartctlTextAtaParser::parse_section_data_internal_capabilities(AtaStorageProperty& cap_prop) +hz::ExpectedVoid SmartctlTextAtaParser::parse_section_data_internal_capabilities(StorageProperty& cap_prop) { // Some special capabilities we're interested in. @@ -1031,7 +1031,7 @@ hz::ExpectedVoid SmartctlTextAtaParser::parse_section_data_ const pcrecpp::RE re_selftest_long_time = app_pcre_re("/^(Extended self-test routine recommended polling time)/mi"); const pcrecpp::RE re_conv_selftest_time = app_pcre_re("/^(Conveyance self-test routine recommended polling time)/mi"); - if (cap_prop.section != AtaStorageProperty::Section::Capabilities) { + if (cap_prop.section != StorageProperty::Section::Capabilities) { debug_out_error("app", DBG_FUNC_MSG << "Non-capability property passed.\n"); return hz::Unexpected(SmartctlParserError::DataError, "Non-capability property passed."); } @@ -1064,9 +1064,9 @@ hz::ExpectedVoid SmartctlTextAtaParser::parse_section_data_ if (re_selftest_status.PartialMatch(cap_prop.reported_name)) { // The last self-test status. break up into pieces. - AtaStorageProperty p; + StorageProperty p; // p.section = AtaStorageProperty::Section::Internal; - p.section = AtaStorageProperty::Section::Capabilities; + p.section = StorageProperty::Section::Capabilities; p.set_name("ata_smart_data/self_test/status/_merged"); AtaStorageSelftestEntry sse; @@ -1171,9 +1171,9 @@ hz::ExpectedVoid SmartctlTextAtaParser::parse_section_data_ // debug_out_dump("app", "Looking for internal capability in: \"" << sv << "\"\n"); - AtaStorageProperty p; + StorageProperty p; // p.section = AtaStorageProperty::Section::Internal; - p.section = AtaStorageProperty::Section::Capabilities; + p.section = StorageProperty::Section::Capabilities; // Note: We don't set reported_value on internal properties. std::string name, value; @@ -1249,8 +1249,8 @@ hz::ExpectedVoid SmartctlTextAtaParser::parse_section_data_ hz::ExpectedVoid SmartctlTextAtaParser::parse_section_data_subsection_attributes(const std::string& sub) { - AtaStorageProperty pt; // template for easy copying - pt.section = AtaStorageProperty::Section::Attributes; + StorageProperty pt; // template for easy copying + pt.section = StorageProperty::Section::Attributes; // split to lines std::vector lines; @@ -1348,7 +1348,7 @@ ID# ATTRIBUTE_NAME FLAGS VALUE WORST THRESH FAIL RAW_VALUE int64_t value_num = 0; hz::string_is_numeric_nolocale(value, value_num, false); - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name(name, "ata_smart_attributes/revision"); p.reported_value = value; p.value = value_num; // integer-type value @@ -1447,7 +1447,7 @@ ID# ATTRIBUTE_NAME FLAGS VALUE WORST THRESH FAIL RAW_VALUE attr.raw_value = hz::string_trim_copy(raw_value); hz::string_is_numeric_nolocale(hz::string_trim_copy(raw_value), attr.raw_value_int, false); // same as raw_value, but parsed as int. - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name(hz::string_trim_copy(name)); p.reported_value = line; // use the whole line here p.value = attr; // attribute-type value; @@ -1469,8 +1469,8 @@ ID# ATTRIBUTE_NAME FLAGS VALUE WORST THRESH FAIL RAW_VALUE hz::ExpectedVoid SmartctlTextAtaParser::parse_section_data_subsection_directory_log(const std::string& sub) { - AtaStorageProperty pt; // template for easy copying - pt.section = AtaStorageProperty::Section::DirectoryLog; + StorageProperty pt; // template for easy copying + pt.section = StorageProperty::Section::DirectoryLog; // Directory log contains: /* @@ -1491,7 +1491,7 @@ Address Access R/W Size Description // the whole subsection { - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name("General Purpose Log Directory", "ata_log_directory/_merged"); p.reported_value = sub; p.value = p.reported_value; // string-type value @@ -1502,7 +1502,7 @@ Address Access R/W Size Description // supported / unsupported { - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name("General Purpose Log Directory supported", "_text_only/directory_log_supported"); // p.reported_value; // nothing @@ -1520,8 +1520,8 @@ Address Access R/W Size Description hz::ExpectedVoid SmartctlTextAtaParser::parse_section_data_subsection_error_log(const std::string& sub) { - AtaStorageProperty pt; // template for easy copying - pt.section = AtaStorageProperty::Section::ErrorLog; + StorageProperty pt; // template for easy copying + pt.section = StorageProperty::Section::ErrorLog; // Note: The format of this section was changed somewhere between 5.0-x and 5.30. // The old format is doesn't really give any useful info, and whatever's left is somewhat @@ -1577,7 +1577,7 @@ Error 1 [0] occurred at disk power-on lifetime: 1 hours (0 days + 1 hours) hz::string_trim(name); hz::string_trim(value); - AtaStorageProperty p(pt); + StorageProperty p(pt); // Note: For extended logs, the path has "extended". // For standard logs, the path has "summary" (?) p.set_name(name, "ata_smart_error_log/extended/revision"); @@ -1597,7 +1597,7 @@ Error 1 [0] occurred at disk power-on lifetime: 1 hours (0 days + 1 hours) const pcrecpp::RE re = app_pcre_re("/^(Warning: device does not support Error Logging)|(SMART Error Log not supported)$/mi"); if (re.PartialMatch(sub)) { - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name("ata_smart_error_log/_not_present"); p.displayable_name = "Warning"; p.readable_value = "Device does not support error logging"; @@ -1615,7 +1615,7 @@ Error 1 [0] occurred at disk power-on lifetime: 1 hours (0 days + 1 hours) if (re1.PartialMatch(sub, &value) || re2.PartialMatch(sub)) { hz::string_trim(value); - AtaStorageProperty p(pt); + StorageProperty p(pt); // Note: For Extended Error Log, the path has "extended". // For simple error log, the path has "summary". p.set_name("ATA Error Count", "ata_smart_error_log/extended/count"); @@ -1661,7 +1661,7 @@ Error 1 [0] occurred at disk power-on lifetime: 1 hours (0 days + 1 hours) re_state.PartialMatch(block, &state); re_type.PartialMatch(block, &etypes_str, &emore); - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name(hz::string_trim_copy(name)); // "Error 6" p.reported_value = block; @@ -1690,7 +1690,7 @@ Error 1 [0] occurred at disk power-on lifetime: 1 hours (0 days + 1 hours) // the whole subsection { - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name("SMART Error Log", "ata_smart_error_log/_merged"); p.reported_value = sub; p.value = p.reported_value; // string-type value @@ -1716,8 +1716,8 @@ Error 1 [0] occurred at disk power-on lifetime: 1 hours (0 days + 1 hours) hz::ExpectedVoid SmartctlTextAtaParser::parse_section_data_subsection_selftest_log(const std::string& sub) { - AtaStorageProperty pt; // template for easy copying - pt.section = AtaStorageProperty::Section::SelftestLog; + StorageProperty pt; // template for easy copying + pt.section = StorageProperty::Section::SelftestLog; // Self-test log contains: // * structure revision number @@ -1740,7 +1740,7 @@ Num Test_Description Status Remaining LifeTime(hours) LBA // The whole subsection { - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name("SMART Self-Test Log", "ata_smart_self_test_log/_merged"); p.reported_value = sub; p.value = p.reported_value; // string-type value @@ -1755,7 +1755,7 @@ Num Test_Description Status Remaining LifeTime(hours) LBA const pcrecpp::RE re = app_pcre_re("/^(Warning: device does not support Self Test Logging)|(SMART Self-test Log not supported)$/mi"); if (re.PartialMatch(sub)) { - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name("ata_smart_self_test_log/_present"); p.displayable_name = "Warning"; p.readable_value = "Device does not support self-test logging"; @@ -1778,7 +1778,7 @@ Num Test_Description Status Remaining LifeTime(hours) LBA if (re1.PartialMatch(sub, &name, &value) || re1_ex.PartialMatch(sub, &name, &value) || re2.PartialMatch(sub, &name, &value)) { hz::string_trim(value); - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name(hz::string_trim_copy(name), "ata_smart_self_test_log/extended/revision"); p.reported_value = value; @@ -1808,7 +1808,7 @@ Num Test_Description Status Remaining LifeTime(hours) LBA while (re.FindAndConsume(&input, &line, &num, &type, &status_str, &remaining, &hours, &lba)) { hz::string_trim(num); - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name("Self-test entry " + num); p.reported_value = hz::string_trim_copy(line); @@ -1868,7 +1868,7 @@ Num Test_Description Status Remaining LifeTime(hours) LBA // number of tests. // Note: "No self-tests have been logged" is sometimes absent, so don't rely on it. { - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name("Number of entries in self-test log", "ata_smart_self_test_log/extended/table/count"); // p.reported_value; // nothing p.value = test_count; // integer @@ -1894,8 +1894,8 @@ Num Test_Description Status Remaining LifeTime(hours) LBA hz::ExpectedVoid SmartctlTextAtaParser::parse_section_data_subsection_selective_selftest_log(const std::string& sub) { - AtaStorageProperty pt; // template for easy copying - pt.section = AtaStorageProperty::Section::SelectiveSelftestLog; + StorageProperty pt; // template for easy copying + pt.section = StorageProperty::Section::SelectiveSelftestLog; // Selective self-test log contains: /* @@ -1915,7 +1915,7 @@ If Selective self-test is pending on power-up, resume after 0 minute delay. // the whole subsection { - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name("SMART selective self-test log", "ata_smart_selective_self_test_log/_merged"); p.reported_value = sub; p.value = p.reported_value; // string-type value @@ -1926,7 +1926,7 @@ If Selective self-test is pending on power-up, resume after 0 minute delay. // supported / unsupported { - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name("Selective self-tests supported", "ata_smart_data/capabilities/selective_self_test_supported"); // p.reported_value; // nothing @@ -1950,8 +1950,8 @@ If Selective self-test is pending on power-up, resume after 0 minute delay. hz::ExpectedVoid SmartctlTextAtaParser::parse_section_data_subsection_scttemp_log(const std::string& sub) { - AtaStorageProperty pt; // template for easy copying - pt.section = AtaStorageProperty::Section::TemperatureLog; + StorageProperty pt; // template for easy copying + pt.section = StorageProperty::Section::TemperatureLog; // scttemp log contains: /* @@ -1988,7 +1988,7 @@ Index Estimated Time Temperature Celsius // the whole subsection { - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name("SCT temperature log", "ata_sct_status/_and/ata_sct_temperature_history/_merged"); p.reported_value = sub; p.value = p.reported_value; // string-type value @@ -1999,7 +1999,7 @@ Index Estimated Time Temperature Celsius // supported / unsupported { - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name("SCT commands unsupported", "ata_sct_status/_not_present"); // p.reported_value; // nothing @@ -2016,8 +2016,8 @@ Index Estimated Time Temperature Celsius { std::string name, value; if (app_pcre_match("/^(Current Temperature):[ \\t]+(.*) Celsius$/mi", sub, &name, &value)) { - AtaStorageProperty p; - p.section = AtaStorageProperty::Section::TemperatureLog; + StorageProperty p; + p.section = StorageProperty::Section::TemperatureLog; p.set_name("Current Temperature", "ata_sct_status/temperature/current"); p.reported_value = value; p.value = hz::string_to_number_nolocale(value); // integer @@ -2038,8 +2038,8 @@ Index Estimated Time Temperature Celsius hz::ExpectedVoid SmartctlTextAtaParser::parse_section_data_subsection_scterc_log(const std::string& sub) { - AtaStorageProperty pt; // template for easy copying - pt.section = AtaStorageProperty::Section::ErcLog; + StorageProperty pt; // template for easy copying + pt.section = StorageProperty::Section::ErcLog; // scterc log contains: /* @@ -2051,7 +2051,7 @@ SCT Error Recovery Control: // the whole subsection { - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name("SCT ERC log", "ata_sct_erc/_merged"); p.reported_value = sub; p.value = p.reported_value; // string-type value @@ -2062,7 +2062,7 @@ SCT Error Recovery Control: // supported / unsupported { - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name("SCT ERC supported", "ata_sct_erc/_present"); // p.reported_value; // nothing @@ -2086,8 +2086,8 @@ SCT Error Recovery Control: hz::ExpectedVoid SmartctlTextAtaParser::parse_section_data_subsection_devstat(const std::string& sub) { - AtaStorageProperty pt; // template for easy copying - pt.section = AtaStorageProperty::Section::Devstat; + StorageProperty pt; // template for easy copying + pt.section = StorageProperty::Section::Devstat; // devstat log contains: /* @@ -2134,7 +2134,7 @@ Page Offset Size Value Description // supported / unsupported bool supported = true; { - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name("Device statistics supported", "ata_device_statistics/_present"); // p.reported_value; // nothing @@ -2236,7 +2236,7 @@ Page Offset Size Value Description description = hz::string_trim_copy(hz::string_trim_copy(description, "=")); } - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name(hz::string_trim_copy(description)); p.reported_value = line; // use the whole line here p.value = st; // statistic-type value @@ -2256,8 +2256,8 @@ Page Offset Size Value Description hz::ExpectedVoid SmartctlTextAtaParser::parse_section_data_subsection_sataphy(const std::string& sub) { - AtaStorageProperty pt; // template for easy copying - pt.section = AtaStorageProperty::Section::PhyLog; + StorageProperty pt; // template for easy copying + pt.section = StorageProperty::Section::PhyLog; // sataphy log contains: /* @@ -2277,7 +2277,7 @@ ID Size Value Description // the whole subsection { - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name("SATA Phy log", "sata_phy_event_counters/_merged"); p.reported_value = sub; p.value = p.reported_value; // string-type value @@ -2288,7 +2288,7 @@ ID Size Value Description // supported / unsupported { - AtaStorageProperty p(pt); + StorageProperty p(pt); p.set_name("SATA Phy log supported", "sata_phy_event_counters/_present"); // p.reported_value; // nothing diff --git a/src/applib/smartctl_text_ata_parser.h b/src/applib/smartctl_text_ata_parser.h index 237620e..640b086 100644 --- a/src/applib/smartctl_text_ata_parser.h +++ b/src/applib/smartctl_text_ata_parser.h @@ -43,7 +43,7 @@ class SmartctlTextAtaParser : public SmartctlParser { hz::ExpectedVoid parse_section_info(const std::string& body); /// Parse a component (one line) of the info section - hz::ExpectedVoid parse_section_info_property(AtaStorageProperty& p); + hz::ExpectedVoid parse_section_info_property(StorageProperty& p); /// Parse the Data section (without "===" header) @@ -63,7 +63,7 @@ class SmartctlTextAtaParser : public SmartctlParser { hz::ExpectedVoid parse_section_data_subsection_sataphy(const std::string& sub); /// Check the capabilities for internal properties we can use. - hz::ExpectedVoid parse_section_data_internal_capabilities(AtaStorageProperty& cap_prop); + hz::ExpectedVoid parse_section_data_internal_capabilities(StorageProperty& cap_prop); /// Set "info" section data ("smartctl -i" output, or the first part of "smartctl -x" output) diff --git a/src/applib/smartctl_text_basic_parser.cpp b/src/applib/smartctl_text_basic_parser.cpp index 2ee1456..c942350 100644 --- a/src/applib/smartctl_text_basic_parser.cpp +++ b/src/applib/smartctl_text_basic_parser.cpp @@ -19,7 +19,7 @@ Copyright: #include // #include "hz/locale_tools.h" // ScopedCLocale, locale_c_get(). -#include "ata_storage_property.h" +#include "storage_property.h" #include "hz/string_algo.h" // string_* #include "hz/string_num.h" // string_is_numeric, number_to_string //#include "hz/debug.h" // debug_* @@ -51,19 +51,19 @@ hz::ExpectedVoid SmartctlTextBasicParser::parse(std::string return hz::Unexpected(SmartctlParserError::NoVersion, "Cannot extract smartctl version information."); } { - AtaStorageProperty p; + StorageProperty p; p.set_name("Smartctl version", "smartctl/version/_merged", "Smartctl Version"); p.reported_value = version; p.value = p.reported_value; // string-type value - p.section = AtaStorageProperty::Section::Info; // add to info section + p.section = StorageProperty::Section::Info; // add to info section add_property(p); } { - AtaStorageProperty p; + StorageProperty p; p.set_name("Smartctl version", "smartctl/version/_merged_full", "Smartctl Version"); p.reported_value = version_full; p.value = p.reported_value; // string-type value - p.section = AtaStorageProperty::Section::Info; // add to info section + p.section = StorageProperty::Section::Info; // add to info section add_property(p); } @@ -77,22 +77,22 @@ hz::ExpectedVoid SmartctlTextBasicParser::parse(std::string // NOTE: CD/DVD detection does not work in "-d scsi" mode. if (app_pcre_match("/this device: CD\\/DVD/mi", output) || app_pcre_match("/^Device type:\\s+CD\\/DVD/mi", output)) { - AtaStorageProperty p; + StorageProperty p; p.set_name("Drive type", "_custom/parser_detected_drive_type", "Parser-Detected Drive Type"); p.reported_value = "CD/DVD"; p.value = StorageDeviceDetectedTypeExt::get_storable_name(StorageDeviceDetectedType::CdDvd); - p.section = AtaStorageProperty::Section::Info; // add to info section + p.section = StorageProperty::Section::Info; // add to info section add_property(p); // This was encountered on a csmi soft-raid under windows with pd0. // The device reported that it had smart supported and enabled. // Product: Raid 5 Volume } else if (app_pcre_match("/Product:[ \\t]*Raid/mi", output)) { - AtaStorageProperty p; + StorageProperty p; p.set_name("Drive type", "_custom/parser_detected_drive_type", "Parser-Detected Drive Type"); p.reported_value = "RAID"; p.value = StorageDeviceDetectedTypeExt::get_storable_name(StorageDeviceDetectedType::UnsupportedRaid); - p.section = AtaStorageProperty::Section::Info; // add to info section + p.section = StorageProperty::Section::Info; // add to info section add_property(p); is_raid = true; @@ -132,17 +132,17 @@ hz::ExpectedVoid SmartctlTextBasicParser::parse(std::string } { - AtaStorageProperty p; + StorageProperty p; p.set_name("SMART Supported", "smart_support/available", "SMART Supported"); p.value = smart_supported; - p.section = AtaStorageProperty::Section::Info; // add to info section + p.section = StorageProperty::Section::Info; // add to info section add_property(p); } { - AtaStorageProperty p; + StorageProperty p; p.set_name("SMART Enabled", "smart_support/enabled", "SMART Enabled"); p.value = smart_enabled; - p.section = AtaStorageProperty::Section::Info; // add to info section + p.section = StorageProperty::Section::Info; // add to info section add_property(p); } @@ -150,14 +150,14 @@ hz::ExpectedVoid SmartctlTextBasicParser::parse(std::string std::string model; if (app_pcre_match("/^Device Model:[ \\t]*(.*)$/mi", output, &model)) { // HDDs and CDROMs model = hz::string_remove_adjacent_duplicates_copy(hz::string_trim_copy(model), ' '); - AtaStorageProperty p; + StorageProperty p; p.set_name("Device Model", "model_name", "Device Model"); p.value = p.reported_value; // string-type value add_property(p); } else if (app_pcre_match("/^(?:Device|Product):[ \\t]*(.*)$/mi", output, &model)) { // usb flash drives model = hz::string_remove_adjacent_duplicates_copy(hz::string_trim_copy(model), ' '); - AtaStorageProperty p; + StorageProperty p; p.set_name("Device Model", "model_name", "Device Model"); p.value = model; add_property(p); @@ -167,7 +167,7 @@ hz::ExpectedVoid SmartctlTextBasicParser::parse(std::string std::string family; // this is from smartctl's database if (app_pcre_match("/^Model Family:[ \\t]*(.*)$/mi", output, &family)) { family = hz::string_remove_adjacent_duplicates_copy(hz::string_trim_copy(family), ' '); - AtaStorageProperty p; + StorageProperty p; p.set_name("Model Family", "model_family", "Model Family"); p.value = family; add_property(p); @@ -176,7 +176,7 @@ hz::ExpectedVoid SmartctlTextBasicParser::parse(std::string std::string serial; if (app_pcre_match("/^Serial Number:[ \\t]*(.*)$/mi", output, &serial)) { serial = hz::string_remove_adjacent_duplicates_copy(hz::string_trim_copy(serial), ' '); - AtaStorageProperty p; + StorageProperty p; p.set_name("Serial Number", "serial_number", "Serial Number"); p.value = serial; add_property(p); @@ -184,11 +184,11 @@ hz::ExpectedVoid SmartctlTextBasicParser::parse(std::string std::string rpm_str; if (app_pcre_match("/^Rotation Rate:[ \\t]*(.*)$/mi", output, &rpm_str)) { - AtaStorageProperty p; + StorageProperty p; p.set_name("Rotation Rate", "rotation_rate", "Rotation Rate"); p.reported_value = rpm_str; p.value = hz::string_to_number_nolocale(rpm_str, false); - p.section = AtaStorageProperty::Section::Info; // add to info section + p.section = StorageProperty::Section::Info; // add to info section add_property(p); } @@ -198,12 +198,12 @@ hz::ExpectedVoid SmartctlTextBasicParser::parse(std::string if (app_pcre_match("/^User Capacity:[ \\t]*(.*)$/mi", output, &size)) { int64_t bytes = 0; const std::string readable_size = SmartctlTextParserHelper::parse_byte_size(size, bytes, false); - AtaStorageProperty p; + StorageProperty p; p.set_name("User Capacity", "user_capacity/bytes/_short", "Capacity"); p.reported_value = size; p.value = bytes; p.readable_value = readable_size; - p.section = AtaStorageProperty::Section::Info; // add to info section + p.section = StorageProperty::Section::Info; // add to info section add_property(p); } diff --git a/src/applib/smartctl_version_parser.h b/src/applib/smartctl_version_parser.h index 3394e2a..362a98f 100644 --- a/src/applib/smartctl_version_parser.h +++ b/src/applib/smartctl_version_parser.h @@ -18,7 +18,7 @@ Copyright: #include #include "smartctl_parser_types.h" -#include "ata_storage_property_descr.h" +#include "storage_property_descr.h" #include "storage_device_detected_type.h" diff --git a/src/applib/storage_device.cpp b/src/applib/storage_device.cpp index 54c9901..fda3109 100644 --- a/src/applib/storage_device.cpp +++ b/src/applib/storage_device.cpp @@ -33,7 +33,7 @@ Copyright: #include "storage_settings.h" #include "smartctl_executor.h" #include "smartctl_version_parser.h" -#include "ata_storage_property_descr.h" +#include "storage_property_descr.h" #include "build_config.h" //#include "smartctl_text_parser_helper.h" //#include "ata_storage_property_descr.h" @@ -238,13 +238,16 @@ hz::ExpectedVoid StorageDevice::fetch_full_data_and_parse( command_options = "--health --info --get=all --capabilities --attributes --format=brief --log=xerror,50,error --log=xselftest,50,selftest --log=selective --log=directory --log=scttemp --log=scterc --log=devstat --log=sataphy"; break; case StorageDeviceDetectedType::Nvme: - command_options = "--health --info --get=all --capabilities --attributes --format=brief --log=xerror,50,error --log=xselftest,50,selftest --log=selective --log=directory --log=scttemp --log=scterc --log=devstat --log=sataphy"; + // We don't care if something is added to json output. + // Same as: --health --info --capabilities --attributes --log=error --log=selftest + command_options = "--xall"; break; case StorageDeviceDetectedType::BasicScsi: case StorageDeviceDetectedType::CdDvd: case StorageDeviceDetectedType::UnsupportedRaid: // SCSI equivalent of -x: - command_options = "--health --info --attributes --log=error --log=selftest --log=background --log=sasphy"; + // command_options = "--health --info --attributes --log=error --log=selftest --log=background --log=sasphy"; + command_options = "--xall"; break; } @@ -726,13 +729,13 @@ std::string StorageDevice::get_device_size_str() const -AtaStorageProperty StorageDevice::get_health_property() const +StorageProperty StorageDevice::get_health_property() const { if (health_property_.has_value()) // cached return value return health_property_.value(); - AtaStorageProperty p = property_repository_.lookup_property("smart_status/passed", - AtaStorageProperty::Section::Health); + StorageProperty p = property_repository_.lookup_property("smart_status/passed", + StorageProperty::Section::Health); if (!p.empty()) health_property_ = p; // store to cache diff --git a/src/applib/storage_device.h b/src/applib/storage_device.h index c4d9d53..fe1ab4a 100644 --- a/src/applib/storage_device.h +++ b/src/applib/storage_device.h @@ -19,7 +19,7 @@ Copyright: #include #include "hz/fs_ns.h" -#include "ata_storage_property.h" +#include "storage_property.h" #include "smartctl_text_ata_parser.h" // prop_list_t #include "smartctl_executor.h" #include "storage_property_repository.h" @@ -137,7 +137,7 @@ class StorageDevice { [[nodiscard]] std::string get_device_size_str() const; /// Get the overall health property - [[nodiscard]] AtaStorageProperty get_health_property() const; + [[nodiscard]] StorageProperty get_health_property() const; /// Get device name (e.g. /dev/sda) @@ -296,7 +296,7 @@ class StorageDevice { std::optional family_name_; ///< Family name std::optional serial_number_; ///< Serial number std::optional size_; ///< Formatted size - mutable std::optional health_property_; ///< Cached health property. + mutable std::optional health_property_; ///< Cached health property. /// Emitted whenever new information is available diff --git a/src/applib/storage_device_detected_type.h b/src/applib/storage_device_detected_type.h index dc39dab..53d274b 100644 --- a/src/applib/storage_device_detected_type.h +++ b/src/applib/storage_device_detected_type.h @@ -39,7 +39,7 @@ struct StorageDeviceDetectedTypeExt StorageDeviceDetectedTypeExt, Glib::ustring> { - static constexpr inline StorageDeviceDetectedType default_value = StorageDeviceDetectedType::Unknown; + static constexpr StorageDeviceDetectedType default_value = StorageDeviceDetectedType::Unknown; static std::unordered_map> build_enum_map() { diff --git a/src/applib/ata_storage_property.cpp b/src/applib/storage_property.cpp similarity index 90% rename from src/applib/ata_storage_property.cpp rename to src/applib/storage_property.cpp index 26c8daf..6497707 100644 --- a/src/applib/ata_storage_property.cpp +++ b/src/applib/storage_property.cpp @@ -24,7 +24,7 @@ Copyright: #include "hz/format_unit.h" // format_time_length #include "hz/string_algo.h" // string_join -#include "ata_storage_property.h" +#include "storage_property.h" @@ -218,21 +218,6 @@ WarningLevel AtaStorageErrorBlock::get_warning_level_for_error_type(const std::s -std::string AtaStorageErrorBlock::format_lifetime_hours() const -{ - std::stringstream ss; - try { - ss.imbue(std::locale("")); - } - catch (const std::runtime_error& e) { - // something is wrong with system locale, can't do anything here. - } - ss << std::fixed << lifetime_hours; - return ss.str(); -} - - - std::ostream& operator<< (std::ostream& os, const AtaStorageErrorBlock& b) { os << "Error number " << b.error_num << ": " @@ -298,21 +283,6 @@ std::string AtaStorageSelftestEntry::get_readable_status() const -std::string AtaStorageSelftestEntry::format_lifetime_hours() const -{ - std::stringstream ss; - try { - ss.imbue(std::locale("")); - } - catch (const std::runtime_error& e) { - // something is wrong with system locale, can't do anything here. - } - ss << std::fixed << lifetime_hours; - return ss.str(); -} - - - std::ostream& operator<< (std::ostream& os, const AtaStorageSelftestEntry& b) { os << "Test entry " << b.test_num << ": " @@ -322,7 +292,18 @@ std::ostream& operator<< (std::ostream& os, const AtaStorageSelftestEntry& b) -std::string AtaStorageProperty::get_readable_section_name(Section s) +std::ostream& operator<<(std::ostream& os, const NvmeStorageSelftestEntry& b) +{ + return os << "Test entry " << b.test_num << ": " + << NvmeSelfTestTypeExt::get_storable_name(b.type) + << ", result: " << NvmeSelfTestResultTypeExt::get_storable_name(b.result) + << ", power on hours: " << int(b.power_on_hours) + << ", lba: " << int(b.lba); +} + + + +std::string StorageProperty::get_readable_section_name(Section s) { static const std::unordered_map m { {Section::Unknown, "unknown"}, @@ -348,7 +329,7 @@ std::string AtaStorageProperty::get_readable_section_name(Section s) -std::string AtaStorageProperty::get_storable_value_type_name() const +std::string StorageProperty::get_storable_value_type_name() const { if (std::holds_alternative(value)) return "empty"; @@ -369,20 +350,22 @@ std::string AtaStorageProperty::get_storable_value_type_name() const if (std::holds_alternative(value)) return "error_block"; if (std::holds_alternative(value)) - return "selftest_entry"; + return "ata_selftest_entry"; + if (std::holds_alternative(value)) + return "nvme_selftest_entry"; return "[internal_error]"; } -bool AtaStorageProperty::empty() const +bool StorageProperty::empty() const { return std::holds_alternative(value); } -void AtaStorageProperty::dump(std::ostream& os, std::size_t internal_offset) const +void StorageProperty::dump(std::ostream& os, std::size_t internal_offset) const { const std::string offset(internal_offset, ' '); @@ -414,12 +397,14 @@ void AtaStorageProperty::dump(std::ostream& os, std::size_t internal_offset) con os << std::get(value); } else if (std::holds_alternative(value)) { os << std::get(value); + } else if (std::holds_alternative(value)) { + os << std::get(value); } } -std::string AtaStorageProperty::format_value(bool add_reported_too) const +std::string StorageProperty::format_value(bool add_reported_too) const { if (!readable_value.empty()) return readable_value; @@ -444,13 +429,15 @@ std::string AtaStorageProperty::format_value(bool add_reported_too) const return hz::stream_cast(std::get(value)); if (std::holds_alternative(value)) return hz::stream_cast(std::get(value)); + if (std::holds_alternative(value)) + return hz::stream_cast(std::get(value)); return "[internal_error]"; } -std::string AtaStorageProperty::get_description(bool clean) const +std::string StorageProperty::get_description(bool clean) const { if (clean) return this->description; @@ -459,14 +446,14 @@ std::string AtaStorageProperty::get_description(bool clean) const -void AtaStorageProperty::set_description(const std::string& descr) +void StorageProperty::set_description(const std::string& descr) { this->description = descr; } -void AtaStorageProperty::set_name(const std::string& rep_name, const std::string& gen_name, const std::string& read_name) +void StorageProperty::set_name(const std::string& rep_name, const std::string& gen_name, const std::string& read_name) { this->reported_name = rep_name; this->generic_name = (gen_name.empty() ? this->reported_name : gen_name); @@ -475,7 +462,7 @@ void AtaStorageProperty::set_name(const std::string& rep_name, const std::string -std::ostream& operator<<(std::ostream& os, const AtaStorageProperty& p) +std::ostream& operator<<(std::ostream& os, const StorageProperty& p) { p.dump(os); return os; diff --git a/src/applib/ata_storage_property.h b/src/applib/storage_property.h similarity index 65% rename from src/applib/ata_storage_property.h rename to src/applib/storage_property.h index 3c4b795..822429d 100644 --- a/src/applib/ata_storage_property.h +++ b/src/applib/storage_property.h @@ -9,11 +9,14 @@ Copyright: /// \weakgroup applib /// @{ -#ifndef ATA_STORAGE_PROPERTY_H -#define ATA_STORAGE_PROPERTY_H +#ifndef STORAGE_PROPERTY_H +#define STORAGE_PROPERTY_H + +#include "local_glibmm.h" #include // std::size_t #include +#include #include #include #include @@ -22,11 +25,12 @@ Copyright: #include #include "warning_level.h" +#include "hz/enum_helper.h" -/// Holds one block of "capabilities" subsection -/// (only for non-time-interval blocks). +/// Holds one block of "capabilities" subsection (only for non-time-interval blocks). +/// ATA only. class AtaStorageCapability { public: std::string reported_flag_value; ///< original flag value as a string @@ -43,7 +47,8 @@ std::ostream& operator<< (std::ostream& os, const AtaStorageCapability& p); -/// Holds one line of "attributes" subsection +/// Holds one line of "attributes" subsection. +/// ATA only. class AtaStorageAttribute { public: @@ -112,7 +117,8 @@ std::ostream& operator<< (std::ostream& os, const AtaStorageAttribute& p); -/// Holds one line of "devstat" subsection +/// Holds one line of "devstat" subsection. +/// ATA only. class AtaStorageStatistic { public: @@ -136,7 +142,8 @@ std::ostream& operator<< (std::ostream& os, const AtaStorageStatistic& p); -/// Holds one error block of "error log" subsection +/// Holds one error block of "error log" subsection. +/// ATA only. class AtaStorageErrorBlock { public: @@ -146,8 +153,6 @@ class AtaStorageErrorBlock { /// Get warning level (Warning) for an error type [[nodiscard]] static WarningLevel get_warning_level_for_error_type(const std::string& type); - /// Format lifetime hours with comma - [[nodiscard]] std::string format_lifetime_hours() const; uint32_t error_num = 0; ///< Error number uint64_t log_index = 0; ///< Log index @@ -167,6 +172,7 @@ std::ostream& operator<< (std::ostream& os, const AtaStorageErrorBlock& b); /// Holds one entry of selftest_log subsection. /// Also, holds "Self-test execution status" capability's "internal" section version. +/// ATA only. class AtaStorageSelftestEntry { public: @@ -205,10 +211,6 @@ class AtaStorageSelftestEntry { [[nodiscard]] std::string get_readable_status() const; - /// Format lifetime hours with comma - [[nodiscard]] std::string format_lifetime_hours() const; - - uint32_t test_num = 0; ///< Test number. always starts from 1. larger means older or newer, depending on model. 0 for capability. std::string type; ///< Extended offline, Short offline, Conveyance offline, etc. . capability: unused. std::string status_str; ///< Self-test routine in progress, Completed without error, etc. (as reported by log or capability) @@ -226,8 +228,147 @@ std::ostream& operator<< (std::ostream& os, const AtaStorageSelftestEntry& b); +/// Decoded of nvme_self_test_log/current_self_test_operation/value +enum class NvmeSelfTestCurrentOperationType { + Unknown = -1, + None = 0x0, + ShortInProgress = 0x1, + ExtendedInProgress = 0x2, + VendorSpecificInProgress = 0xe, +}; + + + +/// Helper structure for enum-related functions +struct NvmeSelfTestCurrentOperationTypeExt + : public hz::EnumHelper< + NvmeSelfTestCurrentOperationType, + NvmeSelfTestCurrentOperationTypeExt, + Glib::ustring> +{ + static constexpr NvmeSelfTestCurrentOperationType default_value = NvmeSelfTestCurrentOperationType::Unknown; + + static std::unordered_map> build_enum_map() + { + return { + {NvmeSelfTestCurrentOperationType::Unknown, {"unknown", _("Unknown")}}, + {NvmeSelfTestCurrentOperationType::None, {"none", _("None")}}, + {NvmeSelfTestCurrentOperationType::ShortInProgress, {"shortInProgress", _("Short Test in Progress")}}, + {NvmeSelfTestCurrentOperationType::ExtendedInProgress, {"extendedInProgress", _("Extended Test in Progress")}}, + {NvmeSelfTestCurrentOperationType::VendorSpecificInProgress, {"vendorSpecificInProgress", _("Vendor-Specific Test in Progress")}}, + }; + } +}; + + + +/// Self-test types in log +enum class NvmeSelfTestType { + Unknown = -1, + Short = 0x1, + Extended = 0x2, + VendorSpecific = 0xe, ///< Can be encountered in log +}; + + + +/// Helper structure for enum-related functions +struct NvmeSelfTestTypeExt + : public hz::EnumHelper< + NvmeSelfTestType, + NvmeSelfTestTypeExt, + Glib::ustring> +{ + static constexpr NvmeSelfTestType default_value = NvmeSelfTestType::Unknown; + + static std::unordered_map> build_enum_map() + { + return { + {NvmeSelfTestType::Unknown, {"unknown", _("Unknown")}}, + {NvmeSelfTestType::Short, {"short", _("Short Test")}}, + {NvmeSelfTestType::Extended, {"extended", _("Extended Test")}}, + {NvmeSelfTestType::VendorSpecific, {"vendorSpecific", _("Vendor-Specific Test")}}, + }; + } +}; + + + +/// Self-test log entry status. +enum class NvmeSelfTestResultType { + Unknown = -1, ///< Unknown result + // Values correspond to "nvme_self_test_log/table/self_test_result/value". + CompletedNoError = 0x0, ///< Completed with no error + AbortedSelfTestCommand = 0x1, ///< Aborted: Self-test command (manually aborted) + AbortedControllerReset = 0x2, ///< Aborted: Controller Reset + AbortedNamespaceRemoved = 0x3, ///< Aborted: Namespace removed + AbortedFormatNvmCommand = 0x4, ///< Aborted: Format NVM command + FatalOrUnknownTestError = 0x5, ///< Fatal or unknown test error + CompletedUnknownFailedSegment = 0x6, ///< Completed: unknown failed segment + CompletedFailedSegments = 0x7, ///< Completed: failed segments + AbortedUnknownReason = 0x8, ///< Aborted: unknown reason + AbortedSanitizeOperation = 0x9, ///< Aborted: sanitize operation +}; + + + +/// Helper structure for enum-related functions +struct NvmeSelfTestResultTypeExt + : public hz::EnumHelper< + NvmeSelfTestResultType, + NvmeSelfTestResultTypeExt, + Glib::ustring> +{ + static constexpr NvmeSelfTestResultType default_value = NvmeSelfTestResultType::Unknown; + + static std::unordered_map> build_enum_map() + { + return { + {NvmeSelfTestResultType::Unknown, {"unknown", _("Unknown")}}, + {NvmeSelfTestResultType::CompletedNoError, {"completedNoError", _("Completed with No Error")}}, + {NvmeSelfTestResultType::AbortedSelfTestCommand, {"abortedSelfTestCommand", _("Aborted: Self-Test Command")}}, + {NvmeSelfTestResultType::AbortedControllerReset, {"abortedControllerReset", _("Aborted: Controller Reset")}}, + {NvmeSelfTestResultType::AbortedNamespaceRemoved, {"abortedNamespaceRemoved", _("Aborted: Namespace Removed")}}, + {NvmeSelfTestResultType::AbortedFormatNvmCommand, {"abortedFormatNvmCommand", _("Aborted: Format NVM Command")}}, + {NvmeSelfTestResultType::FatalOrUnknownTestError, {"fatalOrUnknownTestError", _("Fatal or Unknown Test Error")}}, + {NvmeSelfTestResultType::CompletedUnknownFailedSegment, {"completedUnknownFailedSegment", _("Completed: Unknown Failed Segment")}}, + {NvmeSelfTestResultType::CompletedFailedSegments, {"completedFailedSegments", _("Completed: Failed Segments")}}, + {NvmeSelfTestResultType::AbortedUnknownReason, {"abortedUnknownReason", _("Aborted: Unknown Reason")}}, + {NvmeSelfTestResultType::AbortedSanitizeOperation, {"abortedSanitizeOperation", _("Aborted: Sanitize Operation")}}, + }; + } +}; + + + +/// Holds one entry of nvme_self_test_log section. +/// NVMe only. +class NvmeStorageSelftestEntry { + public: + + /// Self-test error severity + enum class StatusSeverity { + None, + Warning, + Error + }; + + uint32_t test_num = 0; ///< Test number, auto-generated + NvmeSelfTestType type = NvmeSelfTestType::Unknown; ///< Test type + NvmeSelfTestResultType result = NvmeSelfTestResultType::Unknown; ///< Test result + uint32_t power_on_hours = 0; ///< When the test happened (in power-on hours). + uint64_t lba = 0; ///< LBA of the first error. +}; + + +/// Output operator for debug purposes +std::ostream& operator<< (std::ostream& os, const NvmeStorageSelftestEntry& b); + + + + /// A single parser-extracted property -class AtaStorageProperty { +class StorageProperty { public: /// Sections in output @@ -245,6 +386,7 @@ class AtaStorageProperty { ErcLog, ///< SCT Error Recovery Control settings (--log=scterc) PhyLog, ///< Phy log (--log=sataphy) DirectoryLog, ///< Directory log (--log=directory) + NvmeAttributes, ///< NVMe attributes (health log) (-A, --attributes) // Internal ///< Internal application-specific data }; @@ -262,15 +404,16 @@ class AtaStorageProperty { AtaStorageAttribute, ///< Value (if it's an attribute) AtaStorageStatistic, ///< Value (if it's a statistic from devstat) AtaStorageErrorBlock, ///< Value (if it's a error block) - AtaStorageSelftestEntry ///< Value (if it's a self-test entry) + AtaStorageSelftestEntry, ///< Value (if it's ATA self-test log entry) + NvmeStorageSelftestEntry ///< Value (if it's NVMe self-test log entry) >; /// Constructor - AtaStorageProperty() = default; + StorageProperty() = default; /// Constructor - AtaStorageProperty(Section section_, ValueVariantType value_) + StorageProperty(Section section_, ValueVariantType value_) : section(section_), value(std::move(value_)) { } @@ -313,7 +456,7 @@ class AtaStorageProperty { void set_name(const std::string& rep_name, const std::string& gen_name = "", const std::string& read_name = ""); - std::string reported_name; ///< Property name as reported by smartctl. + std::string reported_name; ///< Property name as reported by smartctl. Mainly used by Text parser. std::string generic_name; ///< Generic (internal) name. May be same as reported_name, or something more program-identifiable. std::string displayable_name; ///< Readable property name. May be same as reported_name, or something more user-readable. Possibly translatable. @@ -337,7 +480,7 @@ class AtaStorageProperty { /// Output operator for debug purposes -std::ostream& operator<< (std::ostream& os, const AtaStorageProperty& p); +std::ostream& operator<< (std::ostream& os, const StorageProperty& p); @@ -348,7 +491,7 @@ std::ostream& operator<< (std::ostream& os, const AtaStorageProperty& p); template -const T& AtaStorageProperty::get_value() const +const T& StorageProperty::get_value() const { return std::get(value); } @@ -356,7 +499,7 @@ const T& AtaStorageProperty::get_value() const template -bool AtaStorageProperty::is_value_type() const +bool StorageProperty::is_value_type() const { return std::holds_alternative(value); } diff --git a/src/applib/ata_storage_property_descr.cpp b/src/applib/storage_property_descr.cpp similarity index 98% rename from src/applib/ata_storage_property_descr.cpp rename to src/applib/storage_property_descr.cpp index 2a91a39..577123c 100644 --- a/src/applib/ata_storage_property_descr.cpp +++ b/src/applib/storage_property_descr.cpp @@ -18,7 +18,7 @@ Copyright: #include "hz/string_algo.h" // string_replace_copy #include "applib/app_pcrecpp.h" -#include "ata_storage_property_descr.h" +#include "storage_property_descr.h" #include "warning_colors.h" @@ -1396,7 +1396,7 @@ namespace { /// Check if a property matches a name (generic or reported) - inline bool name_match(AtaStorageProperty& p, const std::string& name) + inline bool name_match(StorageProperty& p, const std::string& name) { if (p.generic_name.empty()) { return hz::string_to_lower_copy(p.reported_name) == hz::string_to_lower_copy(name); @@ -1407,7 +1407,7 @@ namespace { /// Check if a property matches a name (generic or reported) and if it does, /// set a description on it. - inline bool auto_set(AtaStorageProperty& p, const std::string& name, const char* descr) + inline bool auto_set(StorageProperty& p, const std::string& name, const char* descr) { if (name_match(p, name)) { p.set_description(descr); @@ -1419,7 +1419,7 @@ namespace { /// Check if a property is an attribute and matches a generic name - inline bool attr_match(AtaStorageProperty& p, const std::string& generic_name) + inline bool attr_match(StorageProperty& p, const std::string& generic_name) { return (p.is_value_type() && p.generic_name == generic_name); } @@ -1428,7 +1428,7 @@ namespace { /// Find a property's attribute in the attribute database and fill the property /// with all the readable information we can gather. - inline void auto_set_attr(AtaStorageProperty& p, StorageDeviceDetectedType drive_type) + inline void auto_set_attr(StorageProperty& p, StorageDeviceDetectedType drive_type) { AttributeDescription attr = get_attribute_db().find(p.reported_name, p.get_value().id, drive_type); @@ -1525,7 +1525,7 @@ namespace { /// Find a property's statistic in the statistics database and fill the property /// with all the readable information we can gather. - inline bool auto_set_statistic(AtaStorageProperty& p) + inline bool auto_set_statistic(StorageProperty& p) { StatisticDescription sd = get_devstat_db().find(p.reported_name); @@ -1560,7 +1560,7 @@ namespace { -bool ata_storage_property_autoset_description(AtaStorageProperty& p, StorageDeviceDetectedType device_type) +bool ata_storage_property_autoset_description(StorageProperty& p, StorageDeviceDetectedType device_type) { bool found = false; @@ -1573,7 +1573,7 @@ bool ata_storage_property_autoset_description(AtaStorageProperty& p, StorageDevi // Section Info } else { switch (p.section) { - case AtaStorageProperty::Section::Info: + case StorageProperty::Section::Info: found = auto_set(p, "model_family", "Model family (from smartctl database)") || auto_set(p, "model_name", "Device model") || auto_set(p, "serial_number", "Serial number, unique to each physical drive") @@ -1597,12 +1597,12 @@ bool ata_storage_property_autoset_description(AtaStorageProperty& p, StorageDevi } break; - case AtaStorageProperty::Section::Health: + case StorageProperty::Section::Health: found = auto_set(p, "smart_status/passed", "Overall health self-assessment test result. Note: If the drive passes this test, it doesn't mean it's OK. " "However, if the drive doesn't pass it, then it's either already dead, or it's predicting its own failure within the next 24 hours. In this case do a backup immediately!"); break; - case AtaStorageProperty::Section::Capabilities: + case StorageProperty::Section::Capabilities: found = auto_set(p, "ata_smart_data/offline_data_collection/status/_group", "Offline Data Collection (a.k.a. Offline test) is usually automatically performed when the device is idle or every fixed amount of time. " "This should show if Automatic Offline Data Collection is enabled.") || auto_set(p, "ata_smart_data/offline_data_collection/completion_seconds", "Offline Data Collection (a.k.a. Offline test) is usually automatically performed when the device is idle or every fixed amount of time. " @@ -1618,7 +1618,7 @@ bool ata_storage_property_autoset_description(AtaStorageProperty& p, StorageDevi || auto_set(p, "ata_sct_capabilities/_group", "Drive properties related to temperature information."); break; - case AtaStorageProperty::Section::Attributes: + case StorageProperty::Section::Attributes: found = auto_set(p, "ata_smart_attributes/revision", p.displayable_name.c_str()); if (!found) { auto_set_attr(p, device_type); @@ -1626,11 +1626,11 @@ bool ata_storage_property_autoset_description(AtaStorageProperty& p, StorageDevi } break; - case AtaStorageProperty::Section::Devstat: + case StorageProperty::Section::Devstat: found = auto_set_statistic(p); break; - case AtaStorageProperty::Section::ErrorLog: + case StorageProperty::Section::ErrorLog: found = auto_set(p, "ata_smart_error_log/extended/revision", p.displayable_name.c_str()) || auto_set(p, "ata_smart_error_log/extended/count", "Number of errors in error log. Note: Some manufacturers may list completely harmless errors in this log " "(e.g., command invalid, not implemented, etc.)."); @@ -1644,24 +1644,24 @@ bool ata_storage_property_autoset_description(AtaStorageProperty& p, StorageDevi } break; - case AtaStorageProperty::Section::SelftestLog: + case StorageProperty::Section::SelftestLog: found = auto_set(p, "ata_smart_self_test_log/extended/revision", p.displayable_name.c_str()) || auto_set(p, "ata_smart_self_test_log/extended/table/count", "Number of tests in selftest log. Note: The number of entries may be limited to the newest manual tests."); // || auto_set(p, "ata_smart_self_test_log/_present", "This device does not support self-test logging."); // the property text already says that break; - case AtaStorageProperty::Section::SelectiveSelftestLog: + case StorageProperty::Section::SelectiveSelftestLog: // nothing here break; - case AtaStorageProperty::Section::TemperatureLog: + case StorageProperty::Section::TemperatureLog: found = auto_set(p, "ata_sct_status/_not_present", "SCT support is needed for SCT temperature logging."); break; - case AtaStorageProperty::Section::ErcLog: - case AtaStorageProperty::Section::PhyLog: - case AtaStorageProperty::Section::DirectoryLog: - case AtaStorageProperty::Section::Unknown: + case StorageProperty::Section::ErcLog: + case StorageProperty::Section::PhyLog: + case StorageProperty::Section::DirectoryLog: + case StorageProperty::Section::Unknown: // case AtaStorageProperty::Section::Internal: // nothing break; @@ -1674,7 +1674,7 @@ bool ata_storage_property_autoset_description(AtaStorageProperty& p, StorageDevi -WarningLevel ata_storage_property_autoset_warning(AtaStorageProperty& p) +WarningLevel ata_storage_property_autoset_warning(StorageProperty& p) { WarningLevel w = WarningLevel::None; std::string reason; @@ -1688,7 +1688,7 @@ WarningLevel ata_storage_property_autoset_warning(AtaStorageProperty& p) // Section Info } else { switch (p.section) { - case AtaStorageProperty::Section::Info: + case StorageProperty::Section::Info: if (name_match(p, "smart_support/available") && !p.get_value()) { w = WarningLevel::Notice; reason = "SMART is not supported. You won't be able to read any SMART information from this drive."; @@ -1704,18 +1704,18 @@ WarningLevel ata_storage_property_autoset_warning(AtaStorageProperty& p) } break; - case AtaStorageProperty::Section::Health: + case StorageProperty::Section::Health: if (name_match(p, "smart_status/passed") && !p.get_value()) { w = WarningLevel::Alert; reason = "The drive is reporting that it will FAIL very soon. Please back up as soon as possible!"; } break; - case AtaStorageProperty::Section::Capabilities: + case StorageProperty::Section::Capabilities: // nothing break; - case AtaStorageProperty::Section::Attributes: + case StorageProperty::Section::Attributes: { if (p.is_value_type()) { @@ -1814,7 +1814,7 @@ WarningLevel ata_storage_property_autoset_warning(AtaStorageProperty& p) break; } - case AtaStorageProperty::Section::Devstat: + case StorageProperty::Section::Devstat: { if (p.is_value_type()) { const auto& statistic = p.get_value(); @@ -1890,7 +1890,7 @@ WarningLevel ata_storage_property_autoset_warning(AtaStorageProperty& p) break; } - case AtaStorageProperty::Section::ErrorLog: + case StorageProperty::Section::ErrorLog: { // Note: The error list table doesn't display any descriptions, so if any // error-entry related descriptions are added here, don't forget to enable @@ -1927,7 +1927,7 @@ WarningLevel ata_storage_property_autoset_warning(AtaStorageProperty& p) break; } - case AtaStorageProperty::Section::SelftestLog: + case StorageProperty::Section::SelftestLog: { // Note: The error list table doesn't display any descriptions, so if any // error-entry related descriptions are added here, don't forget to enable @@ -1943,11 +1943,11 @@ WarningLevel ata_storage_property_autoset_warning(AtaStorageProperty& p) break; } - case AtaStorageProperty::Section::SelectiveSelftestLog: + case StorageProperty::Section::SelectiveSelftestLog: // nothing here break; - case AtaStorageProperty::Section::TemperatureLog: + case StorageProperty::Section::TemperatureLog: // Don't highlight SCT Unsupported as warning, it's harmless. // if (name_match(p, "ata_sct_status/_not_present") && p.value_bool) { // w = WarningLevel::notice; @@ -1961,10 +1961,10 @@ WarningLevel ata_storage_property_autoset_warning(AtaStorageProperty& p) } break; - case AtaStorageProperty::Section::ErcLog: - case AtaStorageProperty::Section::PhyLog: - case AtaStorageProperty::Section::DirectoryLog: - case AtaStorageProperty::Section::Unknown: + case StorageProperty::Section::ErcLog: + case StorageProperty::Section::PhyLog: + case StorageProperty::Section::DirectoryLog: + case StorageProperty::Section::Unknown: // case AtaStorageProperty::Section::Internal: // nothing here break; diff --git a/src/applib/ata_storage_property_descr.h b/src/applib/storage_property_descr.h similarity index 90% rename from src/applib/ata_storage_property_descr.h rename to src/applib/storage_property_descr.h index ccdc92a..525f4b9 100644 --- a/src/applib/ata_storage_property_descr.h +++ b/src/applib/storage_property_descr.h @@ -9,8 +9,8 @@ Copyright: /// \weakgroup applib /// @{ -#ifndef ATA_STORAGE_PROPERTY_DESCR_H -#define ATA_STORAGE_PROPERTY_DESCR_H +#ifndef STORAGE_PROPERTY_DESCR_H +#define STORAGE_PROPERTY_DESCR_H #include "storage_property_repository.h" #include "storage_device_detected_type.h" diff --git a/src/applib/storage_property_repository.cpp b/src/applib/storage_property_repository.cpp index 7416fa5..d5f7696 100644 --- a/src/applib/storage_property_repository.cpp +++ b/src/applib/storage_property_repository.cpp @@ -11,25 +11,25 @@ Copyright: -const std::vector& StoragePropertyRepository::get_properties() const +const std::vector& StoragePropertyRepository::get_properties() const { return properties_; } -std::vector& StoragePropertyRepository::get_properties_ref() +std::vector& StoragePropertyRepository::get_properties_ref() { return properties_; } -AtaStorageProperty StoragePropertyRepository::lookup_property( - const std::string& generic_name, AtaStorageProperty::Section section) const +StorageProperty StoragePropertyRepository::lookup_property( + const std::string& generic_name, StorageProperty::Section section) const { for (const auto& p : properties_) { - if (section != AtaStorageProperty::Section::Unknown && p.section != section) + if (section != StorageProperty::Section::Unknown && p.section != section) continue; if (p.generic_name == generic_name) @@ -40,14 +40,14 @@ AtaStorageProperty StoragePropertyRepository::lookup_property( -void StoragePropertyRepository::set_properties(std::vector properties) +void StoragePropertyRepository::set_properties(std::vector properties) { properties_ = std::move(properties); } -void StoragePropertyRepository::add_property(AtaStorageProperty property) +void StoragePropertyRepository::add_property(StorageProperty property) { properties_.push_back(std::move(property)); } diff --git a/src/applib/storage_property_repository.h b/src/applib/storage_property_repository.h index a97e0a3..050f255 100644 --- a/src/applib/storage_property_repository.h +++ b/src/applib/storage_property_repository.h @@ -8,7 +8,7 @@ Copyright: #include #include -#include "ata_storage_property.h" +#include "storage_property.h" /// A repository of properties. Used to store and look up drive properties. @@ -16,23 +16,23 @@ class StoragePropertyRepository { public: /// Get all properties - [[nodiscard]] const std::vector& get_properties() const; + [[nodiscard]] const std::vector& get_properties() const; /// Get all properties - [[nodiscard]] std::vector& get_properties_ref(); + [[nodiscard]] std::vector& get_properties_ref(); /// Find a property. /// If section is Section::Unknown, search in all sections. - [[nodiscard]] AtaStorageProperty lookup_property(const std::string& generic_name, - AtaStorageProperty::Section section = AtaStorageProperty::Section::Unknown) const; + [[nodiscard]] StorageProperty lookup_property(const std::string& generic_name, + StorageProperty::Section section = StorageProperty::Section::Unknown) const; /// Set properties - void set_properties(std::vector properties); + void set_properties(std::vector properties); /// Add a property - void add_property(AtaStorageProperty property); + void add_property(StorageProperty property); /// Clear all properties void clear(); @@ -40,7 +40,7 @@ class StoragePropertyRepository { private: - std::vector properties_; ///< Parsed data properties + std::vector properties_; ///< Parsed data properties }; diff --git a/src/applib/warning_colors.h b/src/applib/warning_colors.h index 3b9254c..be8cf69 100644 --- a/src/applib/warning_colors.h +++ b/src/applib/warning_colors.h @@ -14,7 +14,7 @@ Copyright: #include "local_glibmm.h" -#include "ata_storage_property.h" +#include "storage_property.h" @@ -62,7 +62,7 @@ inline bool app_property_get_label_highlight_color(WarningLevel warning, std::st /// Format warning text, but without description -inline std::string storage_property_get_warning_reason(const AtaStorageProperty& p) +inline std::string storage_property_get_warning_reason(const StorageProperty& p) { std::string fg, start = "", stop = ""; if (app_property_get_label_highlight_color(p.warning_level, fg)) { @@ -92,7 +92,7 @@ inline std::string storage_property_get_warning_reason(const AtaStorageProperty& /// Append warning text to description and set it on the property -inline void storage_property_autoset_warning_descr(AtaStorageProperty& p) +inline void storage_property_autoset_warning_descr(StorageProperty& p) { std::string reason = storage_property_get_warning_reason(p); p.set_description(p.get_description() + (reason.empty() ? "" : "\n\n" + reason)); diff --git a/src/gsc_info_window.cpp b/src/gsc_info_window.cpp index c027ccc..e8bc106 100644 --- a/src/gsc_info_window.cpp +++ b/src/gsc_info_window.cpp @@ -28,7 +28,7 @@ Copyright: #include "applib/warning_colors.h" #include "applib/gui_utils.h" // gui_show_error_dialog #include "applib/smartctl_executor_gui.h" -#include "applib/ata_storage_property.h" +#include "applib/storage_property.h" #include "gsc_text_window.h" #include "gsc_info_window.h" @@ -44,12 +44,12 @@ using namespace std::literals; /// A label for AtaStorageProperty struct PropertyLabel { /// Constructor - PropertyLabel(std::string label_, const AtaStorageProperty* prop, bool markup_ = false) : + PropertyLabel(std::string label_, const StorageProperty* prop, bool markup_ = false) : label(std::move(label_)), property(prop), markup(markup_) { } std::string label; ///< Label text - const AtaStorageProperty* property = nullptr; ///< Storage property + const StorageProperty* property = nullptr; ///< Storage property bool markup = false; ///< Whether the label text uses markup }; @@ -841,13 +841,13 @@ void GscInfoWindow::on_test_type_combo_changed() -void GscInfoWindow::fill_ui_general(const std::vector& props) +void GscInfoWindow::fill_ui_general(const std::vector& props) { // filter out some properties - std::vector id_props, version_props, health_props; + std::vector id_props, version_props, health_props; for (auto&& p : props) { - if (p.section == AtaStorageProperty::Section::Info) { + if (p.section == StorageProperty::Section::Info) { if (p.generic_name == "smartctl/version/_merged_full") { version_props.push_back(p); } else if (p.generic_name == "smartctl/version/_merged") { @@ -855,7 +855,7 @@ void GscInfoWindow::fill_ui_general(const std::vector& props } else { id_props.push_back(p); } - } else if (p.section == AtaStorageProperty::Section::Health) { + } else if (p.section == StorageProperty::Section::Health) { health_props.push_back(p); } } @@ -932,7 +932,7 @@ void GscInfoWindow::fill_ui_general(const std::vector& props -void GscInfoWindow::fill_ui_attributes(const std::vector& props) +void GscInfoWindow::fill_ui_attributes(const std::vector& props) { auto* treeview = lookup_widget("attributes_treeview"); @@ -1013,7 +1013,7 @@ void GscInfoWindow::fill_ui_attributes(const std::vector& pr std::vector label_strings; // outside-of-tree properties for (const auto& p : props) { - if (p.section != AtaStorageProperty::Section::Attributes || !p.show_in_ui) + if (p.section != StorageProperty::Section::Attributes || !p.show_in_ui) continue; // add non-attribute-type properties to label above @@ -1057,7 +1057,7 @@ void GscInfoWindow::fill_ui_attributes(const std::vector& pr -void GscInfoWindow::fill_ui_statistics(const std::vector& props) +void GscInfoWindow::fill_ui_statistics(const std::vector& props) { auto* treeview = lookup_widget("statistics_treeview"); @@ -1106,7 +1106,7 @@ void GscInfoWindow::fill_ui_statistics(const std::vector& pr std::vector label_strings; // outside-of-tree properties for (const auto& p : props) { - if (p.section != AtaStorageProperty::Section::Devstat || !p.show_in_ui) + if (p.section != StorageProperty::Section::Devstat || !p.show_in_ui) continue; // add non-entry-type properties to label above @@ -1228,7 +1228,7 @@ void GscInfoWindow::fill_ui_self_test_info() -void GscInfoWindow::fill_ui_self_test_log(const std::vector& props) +void GscInfoWindow::fill_ui_self_test_log(const std::vector& props) { auto* treeview = lookup_widget("selftest_log_treeview"); @@ -1284,7 +1284,7 @@ void GscInfoWindow::fill_ui_self_test_log(const std::vector& std::vector label_strings; // outside-of-tree properties for (auto&& p : props) { - if (p.section != AtaStorageProperty::Section::SelftestLog || !p.show_in_ui) + if (p.section != StorageProperty::Section::SelftestLog || !p.show_in_ui) continue; if (p.generic_name == "ata_smart_self_test_log/_merged") // the whole section, we don't need it @@ -1307,7 +1307,7 @@ void GscInfoWindow::fill_ui_self_test_log(const std::vector& row[self_test_log_table_columns.type] = Glib::Markup::escape_text(sse.type); row[self_test_log_table_columns.status] = Glib::Markup::escape_text(sse.get_readable_status()); row[self_test_log_table_columns.percent] = Glib::Markup::escape_text(hz::number_to_string_locale(100 - sse.remaining_percent) + "%"); - row[self_test_log_table_columns.hours] = Glib::Markup::escape_text(sse.format_lifetime_hours()); + row[self_test_log_table_columns.hours] = Glib::Markup::escape_text(hz::number_to_string_locale(sse.lifetime_hours)); row[self_test_log_table_columns.lba] = Glib::Markup::escape_text(sse.lba_of_first_error); // There are no descriptions in self-test log entries, so don't display // "No description available" for all of them. @@ -1328,7 +1328,7 @@ void GscInfoWindow::fill_ui_self_test_log(const std::vector& -void GscInfoWindow::fill_ui_error_log(const std::vector& props) +void GscInfoWindow::fill_ui_error_log(const std::vector& props) { auto* treeview = lookup_widget("error_log_treeview"); @@ -1381,7 +1381,7 @@ void GscInfoWindow::fill_ui_error_log(const std::vector& pro std::vector label_strings; // outside-of-tree properties for (auto&& p : props) { - if (p.section != AtaStorageProperty::Section::ErrorLog || !p.show_in_ui) + if (p.section != StorageProperty::Section::ErrorLog || !p.show_in_ui) continue; // Note: Don't use property description as a tooltip here. It won't be available if there's no property. @@ -1431,7 +1431,7 @@ void GscInfoWindow::fill_ui_error_log(const std::vector& pro Gtk::TreeRow row = *(list_store->append()); row[error_log_table_columns.log_entry_index] = eb.error_num; - row[error_log_table_columns.hours] = Glib::Markup::escape_text(eb.format_lifetime_hours()); + row[error_log_table_columns.hours] = Glib::Markup::escape_text(hz::number_to_string_locale(eb.lifetime_hours)); row[error_log_table_columns.state] = Glib::Markup::escape_text(eb.device_state); std::string details_str = eb.type_more_info; // parsed in JSON @@ -1459,7 +1459,7 @@ void GscInfoWindow::fill_ui_error_log(const std::vector& pro -void GscInfoWindow::fill_ui_temperature_log(const std::vector& props) +void GscInfoWindow::fill_ui_temperature_log(const std::vector& props) { auto* textview = lookup_widget("temperature_log_textview"); @@ -1467,7 +1467,7 @@ void GscInfoWindow::fill_ui_temperature_log(const std::vector label_strings; // outside-of-tree properties std::string temperature; - AtaStorageProperty temp_property; + StorageProperty temp_property; enum { temp_attr2 = 1, temp_attr1, temp_stat, temp_sct }; // less important to more important int temp_prop_source = 0; @@ -1494,7 +1494,7 @@ void GscInfoWindow::fill_ui_temperature_log(const std::vector()) { // only show if unsupported @@ -1537,7 +1537,7 @@ void GscInfoWindow::fill_ui_temperature_log(const std::vector& props) +WarningLevel GscInfoWindow::fill_ui_capabilities(const std::vector& props) { auto* treeview = lookup_widget("capabilities_treeview"); @@ -1581,7 +1581,7 @@ WarningLevel GscInfoWindow::fill_ui_capabilities(const std::vector& props) +WarningLevel GscInfoWindow::fill_ui_error_recovery(const std::vector& props) { auto* textview = lookup_widget("erc_log_textview"); WarningLevel max_tab_warning = WarningLevel::None; for (auto&& p : props) { - if (p.section != AtaStorageProperty::Section::ErcLog || !p.show_in_ui) + if (p.section != StorageProperty::Section::ErcLog || !p.show_in_ui) continue; // Note: Don't use property description as a tooltip here. It won't be available if there's no property. @@ -1647,14 +1647,14 @@ WarningLevel GscInfoWindow::fill_ui_error_recovery(const std::vector& props) +WarningLevel GscInfoWindow::fill_ui_selective_self_test_log(const std::vector& props) { auto* textview = lookup_widget("selective_selftest_log_textview"); WarningLevel max_tab_warning = WarningLevel::None; for (auto&& p : props) { - if (p.section != AtaStorageProperty::Section::SelectiveSelftestLog || !p.show_in_ui) + if (p.section != StorageProperty::Section::SelectiveSelftestLog || !p.show_in_ui) continue; // Note: Don't use property description as a tooltip here. It won't be available if there's no property. @@ -1677,14 +1677,14 @@ WarningLevel GscInfoWindow::fill_ui_selective_self_test_log(const std::vector& props) +WarningLevel GscInfoWindow::fill_ui_physical(const std::vector& props) { auto* textview = lookup_widget("phy_log_textview"); WarningLevel max_tab_warning = WarningLevel::None; for (auto&& p : props) { - if (p.section != AtaStorageProperty::Section::PhyLog || !p.show_in_ui) + if (p.section != StorageProperty::Section::PhyLog || !p.show_in_ui) continue; // Note: Don't use property description as a tooltip here. It won't be available if there's no property. @@ -1707,14 +1707,14 @@ WarningLevel GscInfoWindow::fill_ui_physical(const std::vector& props) +WarningLevel GscInfoWindow::fill_ui_directory(const std::vector& props) { auto* textview = lookup_widget("directory_log_textview"); WarningLevel max_tab_warning = WarningLevel::None; for (auto&& p : props) { - if (p.section != AtaStorageProperty::Section::DirectoryLog || !p.show_in_ui) + if (p.section != StorageProperty::Section::DirectoryLog || !p.show_in_ui) continue; // Note: Don't use property description as a tooltip here. It won't be available if there's no property. @@ -1738,7 +1738,7 @@ WarningLevel GscInfoWindow::fill_ui_directory(const std::vectorattribute_table_columns.storage_property]; + const StorageProperty* prop = (*iter)[this->attribute_table_columns.storage_property]; if (!prop) { return; } @@ -1811,7 +1811,7 @@ void GscInfoWindow::cell_renderer_for_attributes(Gtk::CellRenderer* cr, void GscInfoWindow::cell_renderer_for_statistics(Gtk::CellRenderer* cr, const Gtk::TreeModel::iterator& iter, [[maybe_unused]] int column_index) const { - const AtaStorageProperty* prop = (*iter)[this->statistics_table_columns.storage_property]; + const StorageProperty* prop = (*iter)[this->statistics_table_columns.storage_property]; if (!prop) { return; } @@ -1844,7 +1844,7 @@ void GscInfoWindow::cell_renderer_for_statistics(Gtk::CellRenderer* cr, void GscInfoWindow::cell_renderer_for_self_test_log(Gtk::CellRenderer* cr, const Gtk::TreeModel::iterator& iter, [[maybe_unused]] int column_index) const { - const AtaStorageProperty* prop = (*iter)[this->self_test_log_table_columns.storage_property]; + const StorageProperty* prop = (*iter)[this->self_test_log_table_columns.storage_property]; if (!prop) { return; } @@ -1878,7 +1878,7 @@ void GscInfoWindow::cell_renderer_for_self_test_log(Gtk::CellRenderer* cr, void GscInfoWindow::cell_renderer_for_error_log(Gtk::CellRenderer* cr, const Gtk::TreeModel::iterator& iter, [[maybe_unused]] int column_index) const { - const AtaStorageProperty* prop = (*iter)[this->error_log_table_columns.storage_property]; + const StorageProperty* prop = (*iter)[this->error_log_table_columns.storage_property]; if (!prop) { return; } @@ -1907,7 +1907,7 @@ void GscInfoWindow::cell_renderer_for_error_log(Gtk::CellRenderer* cr, void GscInfoWindow::cell_renderer_for_capabilities(Gtk::CellRenderer* cr, const Gtk::TreeModel::iterator& iter, [[maybe_unused]] int column_index) const { - const AtaStorageProperty* prop = (*iter)[this->capabilities_table_columns.storage_property]; + const StorageProperty* prop = (*iter)[this->capabilities_table_columns.storage_property]; if (!prop) { return; } diff --git a/src/gsc_info_window.h b/src/gsc_info_window.h index 6cd3e4e..1c7dc2f 100644 --- a/src/gsc_info_window.h +++ b/src/gsc_info_window.h @@ -58,40 +58,40 @@ class GscInfoWindow : public AppBuilderWidget { protected: /// fill_ui_with_info() helper - void fill_ui_general(const std::vector& props); + void fill_ui_general(const std::vector& props); /// fill_ui_with_info() helper - void fill_ui_attributes(const std::vector& props); + void fill_ui_attributes(const std::vector& props); /// fill_ui_with_info() helper - void fill_ui_statistics(const std::vector& props); + void fill_ui_statistics(const std::vector& props); /// fill_ui_with_info() helper void fill_ui_self_test_info(); /// fill_ui_with_info() helper - void fill_ui_self_test_log(const std::vector& props); + void fill_ui_self_test_log(const std::vector& props); /// fill_ui_with_info() helper - void fill_ui_error_log(const std::vector& props); + void fill_ui_error_log(const std::vector& props); /// fill_ui_with_info() helper - void fill_ui_temperature_log(const std::vector& props); + void fill_ui_temperature_log(const std::vector& props); /// fill_ui_with_info() helper - WarningLevel fill_ui_capabilities(const std::vector& props); + WarningLevel fill_ui_capabilities(const std::vector& props); /// fill_ui_with_info() helper - WarningLevel fill_ui_error_recovery(const std::vector& props); + WarningLevel fill_ui_error_recovery(const std::vector& props); /// fill_ui_with_info() helper - WarningLevel fill_ui_selective_self_test_log(const std::vector& props); + WarningLevel fill_ui_selective_self_test_log(const std::vector& props); /// fill_ui_with_info() helper - WarningLevel fill_ui_physical(const std::vector& props); + WarningLevel fill_ui_physical(const std::vector& props); /// fill_ui_with_info() helper - WarningLevel fill_ui_directory(const std::vector& props); + WarningLevel fill_ui_directory(const std::vector& props); // ---------- Helpers @@ -221,7 +221,7 @@ class GscInfoWindow : public AppBuilderWidget { // Gtk::TreeModelColumn updated; Gtk::TreeModelColumn flag_value; Gtk::TreeModelColumn tooltip; - Gtk::TreeModelColumn storage_property; + Gtk::TreeModelColumn storage_property; } attribute_table_columns; /// Statistics table model columns @@ -231,7 +231,7 @@ class GscInfoWindow : public AppBuilderWidget { Gtk::TreeModelColumn flags; Gtk::TreeModelColumn page_offset; Gtk::TreeModelColumn tooltip; - Gtk::TreeModelColumn storage_property; + Gtk::TreeModelColumn storage_property; } statistics_table_columns; /// Self-test log table model columns @@ -243,7 +243,7 @@ class GscInfoWindow : public AppBuilderWidget { Gtk::TreeModelColumn hours; Gtk::TreeModelColumn lba; Gtk::TreeModelColumn tooltip; - Gtk::TreeModelColumn storage_property; + Gtk::TreeModelColumn storage_property; } self_test_log_table_columns; /// Error log table model columns @@ -254,7 +254,7 @@ class GscInfoWindow : public AppBuilderWidget { Gtk::TreeModelColumn lba; Gtk::TreeModelColumn details; Gtk::TreeModelColumn tooltip; - Gtk::TreeModelColumn storage_property; + Gtk::TreeModelColumn storage_property; Gtk::TreeModelColumn mark_name; } error_log_table_columns; @@ -265,7 +265,7 @@ class GscInfoWindow : public AppBuilderWidget { Gtk::TreeModelColumn flag_value; Gtk::TreeModelColumn str_values; Gtk::TreeModelColumn tooltip; - Gtk::TreeModelColumn storage_property; + Gtk::TreeModelColumn storage_property; } capabilities_table_columns; // "Test type" combobox columns diff --git a/src/gsc_main_window.cpp b/src/gsc_main_window.cpp index dde8b4e..3da621c 100644 --- a/src/gsc_main_window.cpp +++ b/src/gsc_main_window.cpp @@ -943,7 +943,7 @@ void GscMainWindow::update_status_widgets() app_gtkmm_set_widget_tooltip(*name_label_, info_str, false); // in case it doesn't fit } - AtaStorageProperty health_prop = drive->get_health_property(); + StorageProperty health_prop = drive->get_health_property(); if (health_label_) { if (health_prop.generic_name == "smart_status/passed") { diff --git a/src/gsc_main_window_iconview.h b/src/gsc_main_window_iconview.h index d4dcbba..8d3403d 100644 --- a/src/gsc_main_window_iconview.h +++ b/src/gsc_main_window_iconview.h @@ -310,7 +310,7 @@ class GscMainWindowIconView : public Gtk::IconView { if (rconfig::get_data("gui/icons_show_serial_number") && !drive->get_serial_number().empty()) { name += "\n" + Glib::Markup::escape_text(drive->get_serial_number()); } - AtaStorageProperty scan_time_prop; + StorageProperty scan_time_prop; if (drive->get_is_virtual()) { scan_time_prop = drive->get_property_repository().lookup_property("local_time/asctime"); if (!scan_time_prop.empty() && !scan_time_prop.get_value().empty()) { @@ -362,7 +362,7 @@ class GscMainWindowIconView : public Gtk::IconView { break; } - const AtaStorageProperty health_prop = drive->get_health_property(); + const StorageProperty health_prop = drive->get_health_property(); if (health_prop.warning_level != WarningLevel::None && health_prop.generic_name == "smart_status/passed") { if (icon) { icon = icon->copy(); // work on a copy