Show Error Log and Self-Test Log support.

Support attributes with undefined values like "---".
This commit is contained in:
Alexander Shaduri
2011-03-06 20:31:39 +00:00
parent 90bbc19923
commit 02428a26c0
7 changed files with 86 additions and 31 deletions
+3 -3
View File
@@ -38,7 +38,9 @@ TODO:
Add debian/ubuntu's su-to-root support to gsmartcontrol-root.
Add support for parsing SSD outputs.
Add support for SSD smartctl attribute names (they're totally different).
Check smartctl sources, they print those names.
Testing:
If ETA time has elapsed, but it's still only at 10% completion,
@@ -105,8 +107,6 @@ Monitor:
Periodically see if drives were added / removed (possibly use OS callbacks
instead of polling?)
Fix inability to detect types in some error logs.
Options->Prefs->Drives
Add a hint about "pd0" for Windows version.
+52 -11
View File
@@ -997,16 +997,23 @@ bool SmartctlParser::parse_section_data_subsection_attributes(const std::string&
// named "Head flying hours". So, parse until we encounter the next column.
// * One WD drive had non-integer flags, something like "PO--C-", with several
// lines of their descriptions after the attributes block (each line started with spaces and |).
// * SSD drives may show "---" in value/worst/threshold fields.
// " 1 Raw_Read_Error_Rate 0x000f 115 099 006 Pre-fail Always - 90981479"
// " 12 Power_Cycle_Count 0x0000 --- --- --- Old_age Offline - 167"
bool attr_found = false; // at least one attribute was found
bool attr_format_with_updated = false; // UPDATED column present
pcrecpp::RE re_up = app_pcre_re("/[ \\t]*([0-9]+) ([^\\t\\n]+)[ \\t]+((?:0x[a-fA-F0-9]+)|(?:[A-Z-]{2,}))[ \\t]+([0-9]+)[ \\t]+([0-9]+)[ \\t]+([0-9]+)[ \\t]+"
"([^ \\t\\n]+)[ \\t]+([^ \\t\\n]+)[ \\t]+([^ \\t\\n]+)[ \\t]+(.+)[ \\t]*/mi");
std::string base_re = "[ \\t]*([0-9]+) ([^\\t\\n]+)[ \\t]+((?:0x[a-fA-F0-9]+)|(?:[A-Z-]{2,}))[ \\t]+" // name / flag
"([0-9-]+)[ \\t]+([0-9-]+)[ \\t]+([0-9-]+)[ \\t]+" // value / worst / threshold
"([^ \\t\\n]+)[ \\t]+"; // type
pcrecpp::RE re_noup = app_pcre_re("/[ \\t]*([0-9]+) ([^\\t\\n]+)[ \\t]+((?:0x[a-fA-F0-9]+)|(?:[A-Z-]{2,}))[ \\t]+([0-9]+)[ \\t]+([0-9]+)[ \\t]+([0-9]+)[ \\t]+"
"([^ \\t\\n]+)[ \\t]+([^ \\t\\n]+)[ \\t]+(.+)[ \\t]*/mi");
pcrecpp::RE re_up = app_pcre_re("/" + base_re
+ "([^ \\t\\n]+)[ \\t]+([^ \\t\\n]+)[ \\t]+(.+)[ \\t]*/mi"); // updated / when_failed / raw
pcrecpp::RE re_noup = app_pcre_re("/" + base_re
+ "([^ \\t\\n]+)[ \\t]+(.+)[ \\t]*/mi"); // when_failed / raw
pcrecpp::RE re_flag_descr = app_pcre_re("/^[\\t ]+\\|/mi");
@@ -1080,9 +1087,17 @@ bool SmartctlParser::parse_section_data_subsection_attributes(const std::string&
StorageAttribute a;
hz::string_is_numeric(hz::string_trim_copy(id), a.id, true, 10);
a.flag = hz::string_trim_copy(flag);
hz::string_is_numeric(hz::string_trim_copy(value), a.value, true, 10);
hz::string_is_numeric(hz::string_trim_copy(worst), a.worst, true, 10);
hz::string_is_numeric(hz::string_trim_copy(threshold), a.threshold, true, 10);
uint8_t norm_value = 0, worst_value = 0, threshold_value = 0;
if (hz::string_is_numeric(hz::string_trim_copy(value), norm_value, true, 10)) {
a.value = norm_value;
}
if (hz::string_is_numeric(hz::string_trim_copy(worst), worst_value, true, 10)) {
a.worst = worst_value;
}
if (hz::string_is_numeric(hz::string_trim_copy(threshold), threshold_value, true, 10)) {
a.threshold = threshold_value;
}
a.attr_type = (attr_type == "Pre-fail" ? StorageAttribute::attr_type_prefail
: (attr_type == "Old_age" ? StorageAttribute::attr_type_oldage : StorageAttribute::attr_type_unknown));
@@ -1139,7 +1154,7 @@ bool SmartctlParser::parse_section_data_subsection_error_log(const std::string&
bool data_found = false;
// error log version
// Error log version
{
pcrecpp::RE re = app_pcre_re("/^(SMART Error Log Version):[ \\t]*(.*)$/mi");
@@ -1162,7 +1177,20 @@ bool SmartctlParser::parse_section_data_subsection_error_log(const std::string&
}
}
// error log count
// Error log support
{
pcrecpp::RE re = app_pcre_re("/^(Warning: device does not support Error Logging)$/mi");
if (re.PartialMatch(sub)) {
StorageProperty p(pt);
p.set_name("error_log_unsupported");
p.readable_name = "Warning";
p.readable_value = "Device does not support error logging";
add_property(p);
}
}
// Error log enty count
{
// note: these represent the same information
pcrecpp::RE re1 = app_pcre_re("/^ATA Error Count:[ \\t]*([0-9]+)/mi");
@@ -1279,7 +1307,7 @@ bool SmartctlParser::parse_section_data_subsection_selftest_log(const std::strin
bool data_found = false; // true if something was found.
// the whole subsection
// The whole subsection
{
StorageProperty p(pt);
p.set_name("SMART Self-test log", "selftest_log");
@@ -1292,7 +1320,20 @@ bool SmartctlParser::parse_section_data_subsection_selftest_log(const std::strin
}
// self-test log version
// Self-test log support
{
pcrecpp::RE re = app_pcre_re("/^(Warning: device does not support Self Test Logging)$/mi");
if (re.PartialMatch(sub)) {
StorageProperty p(pt);
p.set_name("selftest_log_unsupported");
p.readable_name = "Warning";
p.readable_value = "Device does not support self-test logging";
add_property(p);
}
}
// Self-test log version
{
// newer smartctl (since smartctl 5.1-16)
pcrecpp::RE re1 = app_pcre_re("/(SMART Self-test log structure[^\\n0-9]*)([^ \\n]+)[ \\t]*$/mi");
@@ -31,9 +31,13 @@ std::ostream& operator<< (std::ostream& os, const StorageCapability& p)
std::ostream& operator<< (std::ostream& os, const StorageAttribute& p)
{
os
// << p.name << ": "
<< static_cast<int>(p.value) << " (" << p.raw_value_int << ")";
// os << p.name << ": "
if (p.value.defined()) {
os << static_cast<int>(p.value.value());
} else {
os << "-";
}
os << " (" << p.raw_value_int << ")";
return os;
}
+9 -9
View File
@@ -11,6 +11,7 @@
#include <vector>
#include <iosfwd>
#include "hz/optional_value.h"
#include "hz/cstdint.h"
@@ -96,22 +97,21 @@ class StorageAttribute {
}
StorageAttribute() : id(-1), value(0), worst(0), threshold(0),
attr_type(attr_type_unknown), update_type(update_type_unknown),
StorageAttribute() : id(-1), attr_type(attr_type_unknown), update_type(update_type_unknown),
when_failed(fail_time_unknown), raw_value_int(0)
{ }
int32_t id;
std::string flag; // some have it in 0xXXXX format, others in "PO--C-" format (some WD drives?).
uint8_t value;
uint8_t worst;
uint8_t threshold;
int32_t id; ///< Attribute ID (most vendors agree on this)
std::string flag; ///< Some have it in 0xXXXX format, others in "PO--C-" format (some WD drives?).
hz::OptionalValue<uint8_t> value; ///< Normalized value. May be unset ("---").
hz::OptionalValue<uint8_t> worst; ///< Worst ever value. May be unset ("---").
hz::OptionalValue<uint8_t> threshold; ///< Threshold for normalized value. May be unset ("---").
attr_t attr_type;
update_t update_type;
fail_time_t when_failed;
std::string raw_value; // as presented by smartctl (formatted).
int64_t raw_value_int; // same as raw_value, but parsed as int. original value is 6 bytes I think.
std::string raw_value; ///< as presented by smartctl (formatted).
int64_t raw_value_int; ///< same as raw_value, but parsed as int. original value is 6 bytes I think.
};
@@ -106,7 +106,6 @@ bool storage_property_autoset_description(StorageProperty& p)
p.set_description("Checksum errors indicate that SMART data is invalid. This shouldn't happen in normal circumstances.");
found = true;
// Section Info
} else if (p.section == StorageProperty::section_info) {
found = auto_set(p, "Serial Number", "Serial number, unique to each physical drive.")
@@ -265,10 +264,12 @@ bool storage_property_autoset_description(StorageProperty& p)
} else if (p.section == StorageProperty::section_data && p.subsection == StorageProperty::subsection_error_log) {
found = auto_set(p, "error_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
} else if (p.section == StorageProperty::section_data && p.subsection == StorageProperty::subsection_selftest_log) {
found = auto_set(p, "selftest_num_entries", "Number of tests in selftest log. Note: This log usually contains only the last 20 or so manual tests. ");
// || auto_set(p, "selftest_log_unsupported", "This device does not support self-test logging."); // the property text already says that
} else if (p.section == StorageProperty::section_data && p.subsection == StorageProperty::subsection_selective_selftest_log) {
// nothing here
@@ -388,6 +389,10 @@ StorageProperty::warning_t storage_property_autoset_warning(StorageProperty& p)
w = StorageProperty::warning_warn;
reason = "The drive is reporting internal errors. Usually this means uncorrectable data loss and similar severe errors. "
"Check the actual errors for details.";
} else if (name_match(p, "error_log_unsupported")) {
w = StorageProperty::warning_notice;
reason = "The drive does not support error logging. This means that SMART error history is unavailable.";
}
@@ -395,6 +400,11 @@ StorageProperty::warning_t storage_property_autoset_warning(StorageProperty& p)
// don't include selftest warnings - they may be old or something.
// self-tests are carried manually anyway, so the user is expected to check their status anyway.
if (name_match(p, "selftest_log_unsupported")) {
w = StorageProperty::warning_notice;
reason = "The drive does not support self-test logging. This means that SMART test results won't be logged.";
}
} else if (p.section == StorageProperty::section_data && p.subsection == StorageProperty::subsection_selective_selftest_log) {
// nothing here
+3 -3
View File
@@ -659,9 +659,9 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
row[col_id] = iter->value_attribute.id;
row[col_name] = iter->readable_name;
row[col_flag_value] = iter->value_attribute.flag; // it's a string, not int.
row[col_value] = hz::number_to_string(iter->value_attribute.value);
row[col_worst] = hz::number_to_string(iter->value_attribute.worst);
row[col_threshold] = hz::number_to_string(iter->value_attribute.threshold);
row[col_value] = (iter->value_attribute.value.defined() ? hz::number_to_string(iter->value_attribute.value.value()) : "-");
row[col_worst] = (iter->value_attribute.worst.defined() ? hz::number_to_string(iter->value_attribute.worst.value()) : "-");
row[col_threshold] = (iter->value_attribute.threshold.defined() ? hz::number_to_string(iter->value_attribute.threshold.value()) : "-");
row[col_raw] = iter->value_attribute.raw_value;
row[col_type] = attr_type;
row[col_updated] = StorageAttribute::get_update_type_name(iter->value_attribute.update_type);
+1 -1
View File
@@ -27,7 +27,7 @@ class OptionalValue {
typedef T value_type;
OptionalValue() : value_(), defined_(true)
OptionalValue() : value_(), defined_(false)
{ }