Simplified AtaStorageProperty by mergin Section and SubSection.

This commit is contained in:
Alexander Shaduri
2024-04-15 16:29:51 +04:00
parent 351f5edaa9
commit 876e29973c
11 changed files with 154 additions and 188 deletions
+30 -43
View File
@@ -10,17 +10,19 @@ Copyright:
/// @{
#include "local_glibmm.h"
#include <ios>
#include <map>
#include <ostream> // not iosfwd - it doesn't work
#include <sstream>
#include <iomanip>
#include <locale>
#include <stdexcept>
#include <unordered_map>
#include "hz/string_num.h" // number_to_string
#include "hz/stream_cast.h" // stream_cast<>
#include "hz/format_unit.h" // format_time_length
#include "hz/string_algo.h" // string_join
#include "hz/string_num.h" // number_to_string
#include "ata_storage_property.h"
@@ -39,7 +41,7 @@ std::ostream& operator<< (std::ostream& os, const AtaStorageCapability& p)
std::string AtaStorageAttribute::get_attr_type_name(AtaStorageAttribute::AttributeType type)
std::string AtaStorageAttribute::get_readable_attribute_type_name(AttributeType type)
{
static const std::unordered_map<AttributeType, std::string> m {
{AttributeType::Unknown, "[unknown]"},
@@ -54,7 +56,7 @@ std::string AtaStorageAttribute::get_attr_type_name(AtaStorageAttribute::Attribu
std::string AtaStorageAttribute::get_update_type_name(AtaStorageAttribute::UpdateType type)
std::string AtaStorageAttribute::get_readable_update_type_name(UpdateType type)
{
static const std::unordered_map<UpdateType, std::string> m {
{UpdateType::Unknown, "[unknown]"},
@@ -69,7 +71,7 @@ std::string AtaStorageAttribute::get_update_type_name(AtaStorageAttribute::Updat
std::string AtaStorageAttribute::get_fail_time_name(AtaStorageAttribute::FailTime type)
std::string AtaStorageAttribute::get_readable_fail_time_name(FailTime type)
{
static const std::unordered_map<FailTime, std::string> m {
{FailTime::Unknown, "[unknown]"},
@@ -152,7 +154,7 @@ std::ostream& operator<<(std::ostream& os, const AtaStorageStatistic& p)
std::string AtaStorageErrorBlock::get_displayable_error_types(const std::vector<std::string>& types)
std::string AtaStorageErrorBlock::format_readable_error_types(const std::vector<std::string>& types)
{
static const std::map<std::string, std::string> m = {
{"ABRT", _("Command aborted")},
@@ -176,9 +178,9 @@ std::string AtaStorageErrorBlock::get_displayable_error_types(const std::vector<
if (m.find(type) != m.end()) {
sv.push_back(m.at(type));
} else {
std::string name = _("Uknown type");
std::string name = _("Unknown type");
if (!type.empty()) {
name = Glib::ustring::compose(_("Uknown type: %1"), type);
name = Glib::ustring::compose(_("Unknown type: %1"), type);
}
sv.push_back(name);
}
@@ -235,13 +237,13 @@ std::ostream& operator<< (std::ostream& os, const AtaStorageErrorBlock& b)
{
os << "Error number " << b.error_num << ": "
<< hz::string_join(b.reported_types, ", ")
<< " [" << AtaStorageErrorBlock::get_displayable_error_types(b.reported_types) << "]";
<< " [" << AtaStorageErrorBlock::format_readable_error_types(b.reported_types) << "]";
return os;
}
std::string AtaStorageSelftestEntry::get_status_displayable_name(AtaStorageSelftestEntry::Status s)
std::string AtaStorageSelftestEntry::get_readable_status_name(Status s)
{
static const std::unordered_map<Status, std::string> m {
{Status::Unknown, "[unknown]"},
@@ -289,9 +291,9 @@ AtaStorageSelftestEntry::StatusSeverity AtaStorageSelftestEntry::get_status_seve
std::string AtaStorageSelftestEntry::get_status_str() const
std::string AtaStorageSelftestEntry::get_readable_status() const
{
return (status == Status::Unknown ? status_str : get_status_displayable_name(status));
return (status == Status::Unknown ? status_str : get_readable_status_name(status));
}
@@ -314,18 +316,28 @@ std::string AtaStorageSelftestEntry::format_lifetime_hours() const
std::ostream& operator<< (std::ostream& os, const AtaStorageSelftestEntry& b)
{
os << "Test entry " << b.test_num << ": "
<< b.type << ", status: " << b.get_status_str() << ", remaining: " << int(b.remaining_percent);
<< b.type << ", status: " << b.get_readable_status() << ", remaining: " << int(b.remaining_percent);
return os;
}
std::string AtaStorageProperty::get_section_name(AtaStorageProperty::Section s)
std::string AtaStorageProperty::get_readable_section_name(Section s)
{
static const std::unordered_map<Section, std::string> m {
{Section::Unknown, "unknown"},
{Section::Info, "info"},
{Section::Data, "data"},
{Section::Health, "health"},
{Section::Capabilities, "capabilities"},
{Section::Attributes, "attributes"},
{Section::Devstat, "devstat"},
{Section::ErrorLog, "error_log"},
{Section::SelftestLog, "selftest_log"},
{Section::SelectiveSelftestLog, "selective_selftest_log"},
{Section::TemperatureLog, "temperature_log"},
{Section::ErcLog, "erc_log"},
{Section::PhyLog, "phy_log"},
{Section::DirectoryLog, "directory_log"},
{Section::Internal, "internal"},
};
if (auto iter = m.find(s); iter != m.end()) {
@@ -336,31 +348,7 @@ std::string AtaStorageProperty::get_section_name(AtaStorageProperty::Section s)
std::string AtaStorageProperty::get_subsection_name(AtaStorageProperty::SubSection s)
{
static const std::unordered_map<SubSection, std::string> m {
{SubSection::Unknown, "unknown"},
{SubSection::Health, "health"},
{SubSection::Capabilities, "capabilities"},
{SubSection::Attributes, "attributes"},
{SubSection::Devstat, "devstat"},
{SubSection::ErrorLog, "error_log"},
{SubSection::SelftestLog, "selftest_log"},
{SubSection::SelectiveSelftestLog, "selective_selftest_log"},
{SubSection::TemperatureLog, "temperature_log"},
{SubSection::ErcLog, "erc_log"},
{SubSection::PhyLog, "phy_log"},
{SubSection::DirectoryLog, "directory_log"},
};
if (auto iter = m.find(s); iter != m.end()) {
return iter->second;
}
return "[internal_error]";
}
std::string AtaStorageProperty::get_value_type_name() const
std::string AtaStorageProperty::get_storable_value_type_name() const
{
if (std::holds_alternative<std::monostate>(value))
return "empty";
@@ -398,11 +386,10 @@ void AtaStorageProperty::dump(std::ostream& os, std::size_t internal_offset) con
{
const std::string offset(internal_offset, ' ');
os << offset << "[" << get_section_name(section)
<< (section == Section::Data ? (", " + get_subsection_name(subsection)) : "") << "]"
os << offset << "[" << get_readable_section_name(section) << "]"
<< " " << generic_name
// << (generic_name == reported_name ? "" : (" (" + reported_name + ")"))
<< ": [" << get_value_type_name() << "] ";
<< ": [" << get_storable_value_type_name() << "] ";
// if (!readable_value.empty())
// os << readable_value;
+11 -22
View File
@@ -12,6 +12,7 @@ Copyright:
#ifndef ATA_STORAGE_PROPERTY_H
#define ATA_STORAGE_PROPERTY_H
#include <cstddef> // std::size_t
#include <string>
#include <vector>
#include <iosfwd>
@@ -19,7 +20,6 @@ Copyright:
#include <optional>
#include <chrono>
#include <variant>
#include <unordered_map>
#include "warning_level.h"
@@ -62,7 +62,7 @@ class AtaStorageAttribute {
};
/// Get readable attribute type name
[[nodiscard]] static std::string get_attr_type_name(AttributeType type);
[[nodiscard]] static std::string get_readable_attribute_type_name(AttributeType type);
/// Attribute when-updated type
@@ -73,7 +73,7 @@ class AtaStorageAttribute {
};
/// Get readable when-updated type name
[[nodiscard]] static std::string get_update_type_name(UpdateType type);
[[nodiscard]] static std::string get_readable_update_type_name(UpdateType type);
/// Attribute when-failed type
@@ -85,7 +85,7 @@ class AtaStorageAttribute {
};
/// Get a readable when-failed type name
[[nodiscard]] static std::string get_fail_time_name(FailTime type);
[[nodiscard]] static std::string get_readable_fail_time_name(FailTime type);
/// Format raw value with commas (if it's a number)
@@ -141,7 +141,7 @@ class AtaStorageErrorBlock {
public:
/// Get readable error types from reported types
[[nodiscard]] static std::string get_displayable_error_types(const std::vector<std::string>& types);
[[nodiscard]] static std::string format_readable_error_types(const std::vector<std::string>& types);
/// Get warning level (Warning) for an error type
[[nodiscard]] static WarningLevel get_warning_level_for_error_type(const std::string& type);
@@ -192,14 +192,14 @@ class AtaStorageSelftestEntry {
};
/// Get log entry status displayable name
[[nodiscard]] static std::string get_status_displayable_name(Status s);
[[nodiscard]] static std::string get_readable_status_name(Status s);
/// Get severity of error status
[[nodiscard]] static StatusSeverity get_status_severity(Status s);
/// Get error status as a string
[[nodiscard]] std::string get_status_str() const;
[[nodiscard]] std::string get_readable_status() const;
/// Format lifetime hours with comma
@@ -230,17 +230,6 @@ class AtaStorageProperty {
enum class Section {
Unknown, ///< Used when searching in all sections
Info, ///< Short info (--info)
Data, ///< SMART DATA
Internal ///< Internal application-specific data
};
/// Get displayable section type name
[[nodiscard]] static std::string get_section_name(Section s);
/// Subsections in smart data section
enum class SubSection {
Unknown, ///< Used when searching in all subsections
Health, ///< Overall-health (-H, --health)
Capabilities, ///< General SMART Values, aka Capabilities (-c, --capabilities)
Attributes, ///< Attributes (-A, --attributes). These need decoding.
@@ -252,14 +241,15 @@ class AtaStorageProperty {
ErcLog, ///< SCT Error Recovery Control settings (--log=scterc)
PhyLog, ///< Phy log (--log=sataphy)
DirectoryLog, ///< Directory log (--log=directory)
Internal ///< Internal application-specific data
};
/// Get displayable subsection type name
[[nodiscard]] static std::string get_subsection_name(SubSection s);
/// Get displayable section type name
[[nodiscard]] static std::string get_readable_section_name(Section s);
/// Get displayable value type name
[[nodiscard]] std::string get_value_type_name() const;
[[nodiscard]] std::string get_storable_value_type_name() const;
/// Check if this is an empty object with no value set.
@@ -303,7 +293,6 @@ class AtaStorageProperty {
std::string description; ///< Property description (for tooltips, etc...). May contain markup.
Section section = Section::Unknown; ///< Section this property belongs to
SubSection subsection = SubSection::Unknown; ///< Subsection this property belongs to
std::string reported_value; ///< String representation of the value as reported
std::string readable_value; ///< User-friendly readable representation of value. if empty, use the other members.
+66 -63
View File
@@ -1571,37 +1571,37 @@ bool ata_storage_property_autoset_description(AtaStorageProperty& p, AtaStorageA
found = true;
// Section Info
} else if (p.section == AtaStorageProperty::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")
|| auto_set(p, "user_capacity/bytes", "User-serviceable drive capacity as reported to an operating system")
|| auto_set(p, "in_smartctl_database", "Whether the device is in smartctl database or not. "
"If it is, additional information may be provided; otherwise, Raw values of some attributes may be incorrectly formatted.")
|| auto_set(p, "_custom/smart_supported", "Whether the device supports SMART. If not, then only very limited information will be available.")
|| auto_set(p, "_custom/smart_enabled", "Whether the device has SMART enabled. If not, most of the reported values will be incorrect.")
|| auto_set(p, "ata_aam/enabled", "Automatic Acoustic Management (AAM) feature")
|| auto_set(p, "ata_aam/level", "Automatic Acoustic Management (AAM) level")
|| auto_set(p, "ata_apm/enabled", "Automatic Power Management (APM) feature")
|| auto_set(p, "ata_apm/level", "Advanced Power Management (APM) level")
|| auto_set(p, "ata_dsn/enabled", "Device Statistics Notification (DSN) feature")
|| auto_set(p, "power_mode", "Power mode at the time of query");
} else {
switch (p.section) {
case AtaStorageProperty::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")
|| auto_set(p, "user_capacity/bytes", "User-serviceable drive capacity as reported to an operating system")
|| auto_set(p, "in_smartctl_database", "Whether the device is in smartctl database or not. "
"If it is, additional information may be provided; otherwise, Raw values of some attributes may be incorrectly formatted.")
|| auto_set(p, "_custom/smart_supported", "Whether the device supports SMART. If not, then only very limited information will be available.")
|| auto_set(p, "_custom/smart_enabled", "Whether the device has SMART enabled. If not, most of the reported values will be incorrect.")
|| auto_set(p, "ata_aam/enabled", "Automatic Acoustic Management (AAM) feature")
|| auto_set(p, "ata_aam/level", "Automatic Acoustic Management (AAM) level")
|| auto_set(p, "ata_apm/enabled", "Automatic Power Management (APM) feature")
|| auto_set(p, "ata_apm/level", "Advanced Power Management (APM) level")
|| auto_set(p, "ata_dsn/enabled", "Device Statistics Notification (DSN) feature")
|| auto_set(p, "power_mode", "Power mode at the time of query");
// set just its name as a tooltip
if (!found) {
p.set_description(p.displayable_name);
found = true;
}
// set just its name as a tooltip
if (!found) {
p.set_description(p.displayable_name);
found = true;
}
break;
} else if (p.section == AtaStorageProperty::Section::Data) {
switch (p.subsection) {
case AtaStorageProperty::SubSection::Health:
case AtaStorageProperty::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::SubSection::Capabilities:
case AtaStorageProperty::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. "
@@ -1617,7 +1617,7 @@ bool ata_storage_property_autoset_description(AtaStorageProperty& p, AtaStorageA
|| auto_set(p, "ata_sct_capabilities/_group", "Drive properties related to temperature information.");
break;
case AtaStorageProperty::SubSection::Attributes:
case AtaStorageProperty::Section::Attributes:
found = auto_set(p, "ata_smart_attributes/revision", p.displayable_name.c_str());
if (!found) {
auto_set_attr(p, disk_type);
@@ -1625,41 +1625,43 @@ bool ata_storage_property_autoset_description(AtaStorageProperty& p, AtaStorageA
}
break;
case AtaStorageProperty::SubSection::Devstat:
case AtaStorageProperty::Section::Devstat:
found = auto_set_statistic(p);
break;
case AtaStorageProperty::SubSection::ErrorLog:
case AtaStorageProperty::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...).");
// || auto_set(p, "error_log_unsupported", "This device does not support error logging."); // the property text already says that
if (p.is_value_type<AtaStorageErrorBlock>()) {
for (size_t i = 0; i < p.get_value<AtaStorageErrorBlock>().reported_types.size(); ++i) {
p.set_description(AtaStorageErrorBlock::get_displayable_error_types(p.get_value<AtaStorageErrorBlock>().reported_types));
p.set_description(AtaStorageErrorBlock::format_readable_error_types(
p.get_value<AtaStorageErrorBlock>().reported_types));
found = true;
}
}
break;
case AtaStorageProperty::SubSection::SelftestLog:
case AtaStorageProperty::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::SubSection::SelectiveSelftestLog:
case AtaStorageProperty::Section::SelectiveSelftestLog:
// nothing here
break;
case AtaStorageProperty::SubSection::TemperatureLog:
case AtaStorageProperty::Section::TemperatureLog:
found = auto_set(p, "ata_sct_status/_not_present", "SCT support is needed for SCT temperature logging.");
break;
case AtaStorageProperty::SubSection::ErcLog:
case AtaStorageProperty::SubSection::PhyLog:
case AtaStorageProperty::SubSection::DirectoryLog:
case AtaStorageProperty::SubSection::Unknown:
case AtaStorageProperty::Section::ErcLog:
case AtaStorageProperty::Section::PhyLog:
case AtaStorageProperty::Section::DirectoryLog:
case AtaStorageProperty::Section::Unknown:
case AtaStorageProperty::Section::Internal:
// nothing
break;
}
@@ -1683,36 +1685,36 @@ WarningLevel ata_storage_property_autoset_warning(AtaStorageProperty& p)
// Section Info
} else if (p.section == AtaStorageProperty::Section::Info) {
if (name_match(p, "_custom/smart_supported") && !p.get_value<bool>()) {
w = WarningLevel::Notice;
reason = "SMART is not supported. You won't be able to read any SMART information from this drive.";
} else {
switch (p.section) {
case AtaStorageProperty::Section::Info:
if (name_match(p, "_custom/smart_supported") && !p.get_value<bool>()) {
w = WarningLevel::Notice;
reason = "SMART is not supported. You won't be able to read any SMART information from this drive.";
} else if (name_match(p, "_custom/smart_enabled") && !p.get_value<bool>()) {
w = WarningLevel::Notice;
reason = "SMART is disabled. You should enable it to read any SMART information from this drive. "
"Additionally, some drives do not log useful data with SMART disabled, so it's advisable to keep it always enabled.";
} else if (name_match(p, "_custom/smart_enabled") && !p.get_value<bool>()) {
w = WarningLevel::Notice;
reason = "SMART is disabled. You should enable it to read any SMART information from this drive. "
"Additionally, some drives do not log useful data with SMART disabled, so it's advisable to keep it always enabled.";
} else if (name_match(p, "_text_only/info_warning")) {
w = WarningLevel::Notice;
reason = "Your drive may be affected by the warning, please see the details.";
}
} else if (name_match(p, "_text_only/info_warning")) {
w = WarningLevel::Notice;
reason = "Your drive may be affected by the warning, please see the details.";
}
break;
} else if (p.section == AtaStorageProperty::Section::Data) {
switch(p.subsection) {
case AtaStorageProperty::SubSection::Health:
case AtaStorageProperty::Section::Health:
if (name_match(p, "smart_status/passed") && !p.get_value<bool>()) {
w = WarningLevel::Alert;
reason = "The drive is reporting that it will FAIL very soon. Please back up as soon as possible!";
}
break;
case AtaStorageProperty::SubSection::Capabilities:
case AtaStorageProperty::Section::Capabilities:
// nothing
break;
case AtaStorageProperty::SubSection::Attributes:
case AtaStorageProperty::Section::Attributes:
{
if (p.is_value_type<AtaStorageAttribute>()) {
@@ -1811,7 +1813,7 @@ WarningLevel ata_storage_property_autoset_warning(AtaStorageProperty& p)
break;
}
case AtaStorageProperty::SubSection::Devstat:
case AtaStorageProperty::Section::Devstat:
{
if (p.is_value_type<AtaStorageStatistic>()) {
const auto& statistic = p.get_value<AtaStorageStatistic>();
@@ -1887,7 +1889,7 @@ WarningLevel ata_storage_property_autoset_warning(AtaStorageProperty& p)
break;
}
case AtaStorageProperty::SubSection::ErrorLog:
case AtaStorageProperty::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
@@ -1924,7 +1926,7 @@ WarningLevel ata_storage_property_autoset_warning(AtaStorageProperty& p)
break;
}
case AtaStorageProperty::SubSection::SelftestLog:
case AtaStorageProperty::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
@@ -1940,11 +1942,11 @@ WarningLevel ata_storage_property_autoset_warning(AtaStorageProperty& p)
break;
}
case AtaStorageProperty::SubSection::SelectiveSelftestLog:
case AtaStorageProperty::Section::SelectiveSelftestLog:
// nothing here
break;
case AtaStorageProperty::SubSection::TemperatureLog:
case AtaStorageProperty::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;
@@ -1958,10 +1960,11 @@ WarningLevel ata_storage_property_autoset_warning(AtaStorageProperty& p)
}
break;
case AtaStorageProperty::SubSection::ErcLog:
case AtaStorageProperty::SubSection::PhyLog:
case AtaStorageProperty::SubSection::DirectoryLog:
case AtaStorageProperty::SubSection::Unknown:
case AtaStorageProperty::Section::ErcLog:
case AtaStorageProperty::Section::PhyLog:
case AtaStorageProperty::Section::DirectoryLog:
case AtaStorageProperty::Section::Unknown:
case AtaStorageProperty::Section::Internal:
// nothing here
break;
}
+1 -2
View File
@@ -77,7 +77,7 @@ std::chrono::seconds SelfTest::get_min_duration_seconds() const
}
const AtaStorageProperty p = drive_->get_property_repository().lookup_property(prop_name,
AtaStorageProperty::Section::Data, AtaStorageProperty::SubSection::Capabilities);
AtaStorageProperty::Section::Capabilities);
// p stores it as uint64_t
return (total_duration_ = (p.empty() ? 0s : p.get_value<std::chrono::seconds>()));
@@ -272,7 +272,6 @@ hz::ExpectedVoid<SelfTestError> SelfTest::update(const std::shared_ptr<CommandEx
// we use the "self-test status" capability.
AtaStorageProperty p;
for (const auto& e : property_repo.get_properties()) {
// if (e.section != AtaStorageProperty::Section::data || e.subsection != AtaStorageProperty::SubSection::selftest_log
if (e.section != AtaStorageProperty::Section::Internal
|| !e.is_value_type<AtaStorageSelftestEntry>() || e.get_value<AtaStorageSelftestEntry>().test_num != 0
|| e.generic_name != "ata_smart_data/self_test/status/passed")
+1 -2
View File
@@ -244,8 +244,7 @@ hz::ExpectedVoid<SmartctlParserError> 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::Data;
p->subsection = AtaStorageProperty::SubSection::Health;
p->section = AtaStorageProperty::Section::Health;
add_property(p.value());
}
}
+17 -30
View File
@@ -36,22 +36,21 @@ namespace {
inline AtaStorageProperty app_get_checksum_error_property(const std::string& name)
{
AtaStorageProperty p;
p.section = AtaStorageProperty::Section::Data;
if (name == "Attribute Data") {
p.subsection = AtaStorageProperty::SubSection::Attributes;
p.section = AtaStorageProperty::Section::Attributes;
p.set_name(name, "_text_only/attribute_data_checksum_error");
} else if (name == "Attribute Thresholds") {
p.subsection = AtaStorageProperty::SubSection::Attributes;
p.section = AtaStorageProperty::Section::Attributes;
p.set_name(name, "_text_only/attribute_thresholds_checksum_error");
} else if (name == "ATA Error Log") {
p.subsection = AtaStorageProperty::SubSection::ErrorLog;
p.section = AtaStorageProperty::Section::ErrorLog;
p.set_name(name, "_text_only/ata_error_log_checksum_error");
} else if (name == "Self-Test Log") {
p.subsection = AtaStorageProperty::SubSection::SelftestLog;
p.section = AtaStorageProperty::Section::SelftestLog;
p.set_name(name, "_text_only/selftest_log_checksum_error");
}
@@ -776,8 +775,7 @@ Device is: In smartctl database [for details use: -P show]
*/
AtaStorageProperty pt; // template for easy copying
pt.section = AtaStorageProperty::Section::Data;
pt.subsection = AtaStorageProperty::SubSection::Health;
pt.section = AtaStorageProperty::Section::Health;
std::string name, value;
if (app_pcre_match("/^([^:\\n]+):[ \\t]*(.*)$/mi", sub, &name, &value)) {
@@ -842,8 +840,7 @@ SCT capabilities: (0x003d) SCT Status supported.
*/
AtaStorageProperty pt; // template for easy copying
pt.section = AtaStorageProperty::Section::Data;
pt.subsection = AtaStorageProperty::SubSection::Capabilities;
pt.section = AtaStorageProperty::Section::Capabilities;
std::string sub = sub_initial;
@@ -1027,7 +1024,7 @@ hz::ExpectedVoid<SmartctlParserError> 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::Data || cap_prop.subsection != AtaStorageProperty::SubSection::Capabilities) {
if (cap_prop.section != AtaStorageProperty::Section::Capabilities) {
debug_out_error("app", DBG_FUNC_MSG << "Non-capability property passed.\n");
return hz::Unexpected(SmartctlParserError::DataError, "Non-capability property passed.");
}
@@ -1244,8 +1241,7 @@ hz::ExpectedVoid<SmartctlParserError> SmartctlTextAtaParser::parse_section_data_
hz::ExpectedVoid<SmartctlParserError> SmartctlTextAtaParser::parse_section_data_subsection_attributes(const std::string& sub)
{
AtaStorageProperty pt; // template for easy copying
pt.section = AtaStorageProperty::Section::Data;
pt.subsection = AtaStorageProperty::SubSection::Attributes;
pt.section = AtaStorageProperty::Section::Attributes;
// split to lines
std::vector<std::string> lines;
@@ -1465,8 +1461,7 @@ ID# ATTRIBUTE_NAME FLAGS VALUE WORST THRESH FAIL RAW_VALUE
hz::ExpectedVoid<SmartctlParserError> SmartctlTextAtaParser::parse_section_data_subsection_directory_log(const std::string& sub)
{
AtaStorageProperty pt; // template for easy copying
pt.section = AtaStorageProperty::Section::Data;
pt.subsection = AtaStorageProperty::SubSection::DirectoryLog;
pt.section = AtaStorageProperty::Section::DirectoryLog;
// Directory log contains:
/*
@@ -1517,8 +1512,7 @@ Address Access R/W Size Description
hz::ExpectedVoid<SmartctlParserError> SmartctlTextAtaParser::parse_section_data_subsection_error_log(const std::string& sub)
{
AtaStorageProperty pt; // template for easy copying
pt.section = AtaStorageProperty::Section::Data;
pt.subsection = AtaStorageProperty::SubSection::ErrorLog;
pt.section = AtaStorageProperty::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
@@ -1714,8 +1708,7 @@ Error 1 [0] occurred at disk power-on lifetime: 1 hours (0 days + 1 hours)
hz::ExpectedVoid<SmartctlParserError> SmartctlTextAtaParser::parse_section_data_subsection_selftest_log(const std::string& sub)
{
AtaStorageProperty pt; // template for easy copying
pt.section = AtaStorageProperty::Section::Data;
pt.subsection = AtaStorageProperty::SubSection::SelftestLog;
pt.section = AtaStorageProperty::Section::SelftestLog;
// Self-test log contains:
// * structure revision number
@@ -1893,8 +1886,7 @@ Num Test_Description Status Remaining LifeTime(hours) LBA
hz::ExpectedVoid<SmartctlParserError> SmartctlTextAtaParser::parse_section_data_subsection_selective_selftest_log(const std::string& sub)
{
AtaStorageProperty pt; // template for easy copying
pt.section = AtaStorageProperty::Section::Data;
pt.subsection = AtaStorageProperty::SubSection::SelectiveSelftestLog;
pt.section = AtaStorageProperty::Section::SelectiveSelftestLog;
// Selective self-test log contains:
/*
@@ -1950,8 +1942,7 @@ If Selective self-test is pending on power-up, resume after 0 minute delay.
hz::ExpectedVoid<SmartctlParserError> SmartctlTextAtaParser::parse_section_data_subsection_scttemp_log(const std::string& sub)
{
AtaStorageProperty pt; // template for easy copying
pt.section = AtaStorageProperty::Section::Data;
pt.subsection = AtaStorageProperty::SubSection::TemperatureLog;
pt.section = AtaStorageProperty::Section::TemperatureLog;
// scttemp log contains:
/*
@@ -2017,8 +2008,7 @@ 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::Data;
p.subsection = AtaStorageProperty::SubSection::TemperatureLog;
p.section = AtaStorageProperty::Section::TemperatureLog;
p.set_name("Current Temperature", "ata_sct_status/temperature/current");
p.reported_value = value;
p.value = hz::string_to_number_nolocale<int64_t>(value); // integer
@@ -2040,8 +2030,7 @@ Index Estimated Time Temperature Celsius
hz::ExpectedVoid<SmartctlParserError> SmartctlTextAtaParser::parse_section_data_subsection_scterc_log(const std::string& sub)
{
AtaStorageProperty pt; // template for easy copying
pt.section = AtaStorageProperty::Section::Data;
pt.subsection = AtaStorageProperty::SubSection::ErcLog;
pt.section = AtaStorageProperty::Section::ErcLog;
// scterc log contains:
/*
@@ -2089,8 +2078,7 @@ SCT Error Recovery Control:
hz::ExpectedVoid<SmartctlParserError> SmartctlTextAtaParser::parse_section_data_subsection_devstat(const std::string& sub)
{
AtaStorageProperty pt; // template for easy copying
pt.section = AtaStorageProperty::Section::Data;
pt.subsection = AtaStorageProperty::SubSection::Devstat;
pt.section = AtaStorageProperty::Section::Devstat;
// devstat log contains:
/*
@@ -2260,8 +2248,7 @@ Page Offset Size Value Description
hz::ExpectedVoid<SmartctlParserError> SmartctlTextAtaParser::parse_section_data_subsection_sataphy(const std::string& sub)
{
AtaStorageProperty pt; // template for easy copying
pt.section = AtaStorageProperty::Section::Data;
pt.subsection = AtaStorageProperty::SubSection::PhyLog;
pt.section = AtaStorageProperty::Section::PhyLog;
// sataphy log contains:
/*
-1
View File
@@ -15,7 +15,6 @@ Copyright:
#include "local_glibmm.h"
#include <string>
#include <vector>
#include <optional>
#include "smartctl_parser_types.h"
+1 -1
View File
@@ -532,7 +532,7 @@ AtaStorageProperty StorageDevice::get_health_property() const
return health_property_.value();
AtaStorageProperty p = property_repository_.lookup_property("smart_status/passed",
AtaStorageProperty::Section::Data, AtaStorageProperty::SubSection::Health);
AtaStorageProperty::Section::Health);
if (!p.empty())
health_property_ = p; // store to cache
+3 -3
View File
@@ -4,6 +4,8 @@ Copyright:
(C) 2008 - 2024 Alexander Shaduri <ashaduri@gmail.com>
******************************************************************************/
#include <string>
#include "storage_property_repository.h"
@@ -24,13 +26,11 @@ std::vector<AtaStorageProperty>& StoragePropertyRepository::get_properties_ref()
AtaStorageProperty StoragePropertyRepository::lookup_property(
const std::string& generic_name, AtaStorageProperty::Section section, AtaStorageProperty::SubSection subsection) const
const std::string& generic_name, AtaStorageProperty::Section section) const
{
for (const auto& p : properties_) {
if (section != AtaStorageProperty::Section::Unknown && p.section != section)
continue;
if (subsection != AtaStorageProperty::SubSection::Unknown && p.subsection != subsection)
continue;
if (p.generic_name == generic_name)
return p;
+3 -3
View File
@@ -21,10 +21,10 @@ class StoragePropertyRepository {
[[nodiscard]] std::vector<AtaStorageProperty>& get_properties_ref();
/// Find a property
/// 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, // if unknown, search in all.
AtaStorageProperty::SubSection subsection = AtaStorageProperty::SubSection::Unknown) const;
AtaStorageProperty::Section section = AtaStorageProperty::Section::Unknown) const;
/// Set properties
+21 -18
View File
@@ -853,7 +853,7 @@ void GscInfoWindow::fill_ui_general(const std::vector<AtaStorageProperty>& props
} else {
id_props.push_back(p);
}
} else if (p.section == AtaStorageProperty::Section::Data && p.subsection == AtaStorageProperty::SubSection::Health) {
} else if (p.section == AtaStorageProperty::Section::Health) {
health_props.push_back(p);
}
}
@@ -1011,7 +1011,7 @@ void GscInfoWindow::fill_ui_attributes(const std::vector<AtaStorageProperty>& pr
std::vector<PropertyLabel> label_strings; // outside-of-tree properties
for (const auto& p : props) {
if (p.section != AtaStorageProperty::Section::Data || p.subsection != AtaStorageProperty::SubSection::Attributes)
if (p.section != AtaStorageProperty::Section::Attributes)
continue;
// add non-attribute-type properties to label above
@@ -1033,9 +1033,11 @@ void GscInfoWindow::fill_ui_attributes(const std::vector<AtaStorageProperty>& pr
row[attribute_table_columns.worst] = Glib::Markup::escape_text(attr.worst.has_value() ? hz::number_to_string_locale(attr.worst.value()) : "-");
row[attribute_table_columns.threshold] = Glib::Markup::escape_text(attr.threshold.has_value() ? hz::number_to_string_locale(attr.threshold.value()) : "-");
row[attribute_table_columns.raw] = Glib::Markup::escape_text(attr.format_raw_value());
row[attribute_table_columns.type] = Glib::Markup::escape_text(AtaStorageAttribute::get_attr_type_name(attr.attr_type));
row[attribute_table_columns.type] = Glib::Markup::escape_text(
AtaStorageAttribute::get_readable_attribute_type_name(attr.attr_type));
// row[attribute_table_columns.updated] = Glib::Markup::escape_text(AtaStorageAttribute::get_update_type_name(attr.update_type));
row[attribute_table_columns.when_failed] = Glib::Markup::escape_text(AtaStorageAttribute::get_fail_time_name(attr.when_failed));
row[attribute_table_columns.when_failed] = Glib::Markup::escape_text(
AtaStorageAttribute::get_readable_fail_time_name(attr.when_failed));
row[attribute_table_columns.tooltip] = p.get_description(); // markup
row[attribute_table_columns.storage_property] = &p;
@@ -1102,7 +1104,7 @@ void GscInfoWindow::fill_ui_statistics(const std::vector<AtaStorageProperty>& pr
std::vector<PropertyLabel> label_strings; // outside-of-tree properties
for (const auto& p : props) {
if (p.section != AtaStorageProperty::Section::Data || p.subsection != AtaStorageProperty::SubSection::Devstat)
if (p.section != AtaStorageProperty::Section::Devstat)
continue;
// add non-entry-type properties to label above
@@ -1280,7 +1282,7 @@ void GscInfoWindow::fill_ui_self_test_log(const std::vector<AtaStorageProperty>&
std::vector<PropertyLabel> label_strings; // outside-of-tree properties
for (auto&& p : props) {
if (p.section != AtaStorageProperty::Section::Data || p.subsection != AtaStorageProperty::SubSection::SelftestLog)
if (p.section != AtaStorageProperty::Section::SelftestLog)
continue;
if (p.generic_name == "ata_smart_self_test_log/_merged") // the whole section, we don't need it
@@ -1301,7 +1303,7 @@ void GscInfoWindow::fill_ui_self_test_log(const std::vector<AtaStorageProperty>&
row[self_test_log_table_columns.log_entry_index] = sse.test_num;
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_status_str());
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.lba] = Glib::Markup::escape_text(sse.lba_of_first_error);
@@ -1377,7 +1379,7 @@ void GscInfoWindow::fill_ui_error_log(const std::vector<AtaStorageProperty>& pro
std::vector<PropertyLabel> label_strings; // outside-of-tree properties
for (auto&& p : props) {
if (p.section != AtaStorageProperty::Section::Data || p.subsection != AtaStorageProperty::SubSection::ErrorLog)
if (p.section != AtaStorageProperty::Section::ErrorLog)
continue;
// Note: Don't use property description as a tooltip here. It won't be available if there's no property.
@@ -1429,7 +1431,8 @@ void GscInfoWindow::fill_ui_error_log(const std::vector<AtaStorageProperty>& pro
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.state] = Glib::Markup::escape_text(eb.device_state);
row[error_log_table_columns.type] = Glib::Markup::escape_text(AtaStorageErrorBlock::get_displayable_error_types(eb.reported_types));
row[error_log_table_columns.type] = Glib::Markup::escape_text(
AtaStorageErrorBlock::format_readable_error_types(eb.reported_types));
row[error_log_table_columns.details] = Glib::Markup::escape_text(type_details.empty() ? "-" : type_details); // e.g. OBS has no details
row[error_log_table_columns.tooltip] = p.get_description(); // markup
row[error_log_table_columns.storage_property] = &p;
@@ -1484,7 +1487,7 @@ void GscInfoWindow::fill_ui_temperature_log(const std::vector<AtaStorageProperty
temp_prop_source = temp_attr2;
}
if (p.section != AtaStorageProperty::Section::Data || p.subsection != AtaStorageProperty::SubSection::TemperatureLog)
if (p.section != AtaStorageProperty::Section::TemperatureLog)
continue;
if (p.generic_name == "ata_sct_status/_not_present" && p.get_value<bool>()) { // only show if unsupported
@@ -1571,7 +1574,7 @@ WarningLevel GscInfoWindow::fill_ui_capabilities(const std::vector<AtaStoragePro
int index = 1;
for (auto&& p : props) {
if (p.section != AtaStorageProperty::Section::Data || p.subsection != AtaStorageProperty::SubSection::Capabilities)
if (p.section != AtaStorageProperty::Section::Capabilities)
continue;
std::string flag_value;
@@ -1614,7 +1617,7 @@ WarningLevel GscInfoWindow::fill_ui_error_recovery(const std::vector<AtaStorageP
WarningLevel max_tab_warning = WarningLevel::None;
for (auto&& p : props) {
if (p.section != AtaStorageProperty::Section::Data || p.subsection != AtaStorageProperty::SubSection::ErcLog)
if (p.section != AtaStorageProperty::Section::ErcLog)
continue;
// Note: Don't use property description as a tooltip here. It won't be available if there's no property.
@@ -1644,11 +1647,11 @@ WarningLevel GscInfoWindow::fill_ui_selective_self_test_log(const std::vector<At
WarningLevel max_tab_warning = WarningLevel::None;
for (auto&& p : props) {
if (p.section != AtaStorageProperty::Section::Data || p.subsection != AtaStorageProperty::SubSection::SelectiveSelftestLog)
if (p.section != AtaStorageProperty::Section::SelectiveSelftestLog)
continue;
// Note: Don't use property description as a tooltip here. It won't be available if there's no property.
if (p.generic_name == "SubSection::ata_smart_selective_self_test_log/_merged") {
if (p.generic_name == "ata_smart_selective_self_test_log/_merged") {
Glib::RefPtr<Gtk::TextBuffer> buffer = textview->get_buffer();
buffer->set_text("\n" + Glib::ustring::compose(_("Complete selective self-test log: %1"), "\n\n" + p.get_value<std::string>()));
@@ -1674,7 +1677,7 @@ WarningLevel GscInfoWindow::fill_ui_physical(const std::vector<AtaStoragePropert
WarningLevel max_tab_warning = WarningLevel::None;
for (auto&& p : props) {
if (p.section != AtaStorageProperty::Section::Data || p.subsection != AtaStorageProperty::SubSection::PhyLog)
if (p.section != AtaStorageProperty::Section::PhyLog)
continue;
// Note: Don't use property description as a tooltip here. It won't be available if there's no property.
@@ -1704,7 +1707,7 @@ WarningLevel GscInfoWindow::fill_ui_directory(const std::vector<AtaStorageProper
WarningLevel max_tab_warning = WarningLevel::None;
for (auto&& p : props) {
if (p.section != AtaStorageProperty::Section::Data || p.subsection != AtaStorageProperty::SubSection::DirectoryLog)
if (p.section != AtaStorageProperty::Section::DirectoryLog)
continue;
// Note: Don't use property description as a tooltip here. It won't be available if there's no property.
@@ -1909,7 +1912,7 @@ void GscInfoWindow::cell_renderer_for_capabilities(Gtk::CellRenderer* cr,
gboolean GscInfoWindow::test_idle_callback(void* data)
{
auto* self = static_cast<GscInfoWindow*>(data);
DBG_ASSERT(self);
DBG_ASSERT_RETURN(self, false);
if (!self->current_test) // shouldn't happen
return FALSE; // stop
@@ -2024,7 +2027,7 @@ gboolean GscInfoWindow::test_idle_callback(void* data)
} else {
result_msg = Glib::ustring::compose(_("<b>Test result:</b> %1."),
Glib::Markup::escape_text(AtaStorageSelftestEntry::get_status_displayable_name(status)));
Glib::Markup::escape_text(AtaStorageSelftestEntry::get_readable_status_name(status)));
// It may not reach 100% somehow, so do it manually.
if (test_completion_progressbar)