mirror of
https://github.com/ashaduri/gsmartcontrol.git
synced 2026-09-25 05:15:33 +00:00
Rate individual error log entries for error severity.
This commit is contained in:
+3
-3
@@ -32,6 +32,8 @@ Add ability (through ctrl-C?) to copy selected rows from attributes and statisti
|
||||
|
||||
Add menu item - "update drive database"
|
||||
Run it in terminal in Linux for verbosity.
|
||||
xterm -hold -e 'update-smart-drivedb'
|
||||
require xterm in rpm/deb deps.
|
||||
|
||||
|
||||
Testing:
|
||||
@@ -40,11 +42,9 @@ Testing:
|
||||
Detect running tests on launch (maybe ask the user too? some tests
|
||||
may be stuck due to bad firmware, e.g. 3ware/windows).
|
||||
|
||||
Parse "==> WARNING"
|
||||
|
||||
|
||||
Per-line selftest error highlighting.
|
||||
Tab highlighting according to error severity.
|
||||
|
||||
Parse all test data.
|
||||
|
||||
|
||||
|
||||
@@ -76,22 +76,23 @@ std::ostream& operator<<(std::ostream& os, const StorageStatistic& p)
|
||||
|
||||
std::string StorageErrorBlock::get_readable_error_types(const std::vector<std::string>& types)
|
||||
{
|
||||
std::map<std::string, std::string> m;
|
||||
|
||||
m["ABRT"] = "Command aborted";
|
||||
m["AMNF"] = "Address mark not found";
|
||||
m["CCTO"] = "Command completion timed out";
|
||||
m["EOM"] = "End of media";
|
||||
m["ICRC"] = "Interface CRC error";
|
||||
m["IDNF"] = "Identity not found";
|
||||
m["ILI"] = "(Packet command-set specific)";
|
||||
m["MC"] = "Media changed";
|
||||
m["MCR"] = "Media change request";
|
||||
m["NM"] = "No media";
|
||||
m["obs"] = "Obsolete";
|
||||
m["TK0NF"] = "Track 0 not found";
|
||||
m["UNC"] = "Uncorrectable error in data";
|
||||
m["WP"] = "Media is write protected";
|
||||
static std::map<std::string, std::string> m;
|
||||
if (m.empty()) {
|
||||
m["ABRT"] = "Command aborted";
|
||||
m["AMNF"] = "Address mark not found";
|
||||
m["CCTO"] = "Command completion timed out";
|
||||
m["EOM"] = "End of media";
|
||||
m["ICRC"] = "Interface CRC error";
|
||||
m["IDNF"] = "Identity not found";
|
||||
m["ILI"] = "(Packet command-set specific)";
|
||||
m["MC"] = "Media changed";
|
||||
m["MCR"] = "Media change request";
|
||||
m["NM"] = "No media";
|
||||
m["obs"] = "Obsolete";
|
||||
m["TK0NF"] = "Track 0 not found";
|
||||
m["UNC"] = "Uncorrectable error in data";
|
||||
m["WP"] = "Media is write protected";
|
||||
}
|
||||
|
||||
std::vector<std::string> sv;
|
||||
for (std::vector<std::string>::const_iterator iter = types.begin(); iter != types.end(); ++iter) {
|
||||
@@ -107,6 +108,34 @@ std::string StorageErrorBlock::get_readable_error_types(const std::vector<std::s
|
||||
|
||||
|
||||
|
||||
int StorageErrorBlock::get_warning_level_for_error_type(std::string& type)
|
||||
{
|
||||
static std::map<std::string, StorageProperty::warning_t> m;
|
||||
if (m.empty()) {
|
||||
m["ABRT"] = StorageProperty::warning_none;
|
||||
m["AMNF"] = StorageProperty::warning_alert;
|
||||
m["CCTO"] = StorageProperty::warning_warn;
|
||||
m["EOM"] = StorageProperty::warning_warn;
|
||||
m["ICRC"] = StorageProperty::warning_warn;
|
||||
m["IDNF"] = StorageProperty::warning_alert;
|
||||
m["ILI"] = StorageProperty::warning_notice;
|
||||
m["MC"] = StorageProperty::warning_none;
|
||||
m["MCR"] = StorageProperty::warning_none;
|
||||
m["NM"] = StorageProperty::warning_none;
|
||||
m["obs"] = StorageProperty::warning_none;
|
||||
m["TK0NF"] = StorageProperty::warning_alert;
|
||||
m["UNC"] = StorageProperty::warning_alert;
|
||||
m["WP"] = StorageProperty::warning_none;
|
||||
}
|
||||
|
||||
if (m.find(type) != m.end()) {
|
||||
return int(m[type]);
|
||||
}
|
||||
return StorageProperty::warning_none; // unknown error
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string StorageErrorBlock::format_lifetime_hours() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
@@ -188,6 +188,9 @@ class StorageErrorBlock {
|
||||
/// Get readable error types from reported types
|
||||
static std::string get_readable_error_types(const std::vector<std::string>& types);
|
||||
|
||||
/// Get warning level (warning_t) for an error type
|
||||
static int get_warning_level_for_error_type(std::string& type);
|
||||
|
||||
/// Format lifetime hours with comma
|
||||
std::string format_lifetime_hours() const;
|
||||
|
||||
|
||||
@@ -1615,6 +1615,13 @@ bool storage_property_autoset_description(StorageProperty& p, StorageAttribute::
|
||||
found = auto_set(p, "error_log_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
|
||||
if (p.value_type == StorageProperty::value_type_error_block) {
|
||||
for (size_t i = 0; i < p.value_error_block.reported_types.size(); ++i) {
|
||||
p.set_description(StorageErrorBlock::get_readable_error_types(p.value_error_block.reported_types));
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case StorageProperty::subsection_selftest_log:
|
||||
@@ -1851,7 +1858,7 @@ StorageProperty::warning_t storage_property_autoset_warning(StorageProperty& p)
|
||||
// the tooltips.
|
||||
|
||||
if (name_match(p, "error_log_error_count") && p.value_integer > 0) {
|
||||
w = StorageProperty::warning_warn;
|
||||
w = StorageProperty::warning_notice;
|
||||
reason = "The drive is reporting internal errors. Usually this means uncorrectable data loss and similar severe errors. "
|
||||
"Check the actual errors for details.";
|
||||
|
||||
@@ -1860,7 +1867,20 @@ StorageProperty::warning_t storage_property_autoset_warning(StorageProperty& p)
|
||||
reason = "The drive does not support error logging. This means that SMART error history is unavailable.";
|
||||
}
|
||||
|
||||
// TODO Rate individual error log entries.
|
||||
// Rate individual error log entries.
|
||||
if (!p.value_error_block.reported_types.empty()) {
|
||||
StorageProperty::warning_t error_block_warning = StorageProperty::warning_none;
|
||||
for (size_t i = 0; i < p.value_error_block.reported_types.size(); ++i) {
|
||||
int individual_warning = StorageErrorBlock::get_warning_level_for_error_type(p.value_error_block.reported_types[i]);
|
||||
if (individual_warning > int(error_block_warning)) {
|
||||
error_block_warning = StorageProperty::warning_t(individual_warning);
|
||||
}
|
||||
}
|
||||
if (int(error_block_warning) > int(StorageProperty::warning_none)) {
|
||||
w = error_block_warning;
|
||||
reason = "The drive is reporting internal errors. Your data may be at risk depending on error severity.";
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
@@ -108,32 +108,8 @@ namespace {
|
||||
|
||||
|
||||
|
||||
/// Cell renderer functions for attribute cells
|
||||
inline void app_attr_cell_renderer_func(Gtk::CellRenderer* cr, const Gtk::TreeModel::iterator& iter,
|
||||
Gtk::TreeModelColumn<const StorageProperty*> storage_column)
|
||||
{
|
||||
const StorageProperty* p = (*iter)[storage_column];
|
||||
Gtk::CellRendererText* crt = hz::down_cast<Gtk::CellRendererText*>(cr);
|
||||
if (crt) {
|
||||
std::string fg, bg;
|
||||
if (app_property_get_row_highlight_colors(p->warning, fg, bg)) {
|
||||
// Note: property_cell_background makes horizontal tree lines disappear around it,
|
||||
// but property_background doesn't play nice with sorted column color.
|
||||
crt->property_cell_background() = bg;
|
||||
crt->property_foreground() = fg;
|
||||
} else {
|
||||
// this is needed because cellrenderer is shared in column, so the previous call
|
||||
// may set the color for all subsequent cells.
|
||||
crt->property_cell_background().reset_value();
|
||||
crt->property_foreground().reset_value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Cell renderer functions for attribute cells
|
||||
inline void app_statistic_cell_renderer_func(Gtk::CellRenderer* cr, const Gtk::TreeModel::iterator& iter,
|
||||
/// Cell renderer functions for list cells
|
||||
inline void app_list_cell_renderer_func(Gtk::CellRenderer* cr, const Gtk::TreeModel::iterator& iter,
|
||||
Gtk::TreeModelColumn<const StorageProperty*> storage_column)
|
||||
{
|
||||
const StorageProperty* p = (*iter)[storage_column];
|
||||
@@ -667,7 +643,7 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
|
||||
for (unsigned int i = 0; i < num_tree_cols; ++i) {
|
||||
Gtk::TreeViewColumn* tcol = treeview->get_column(i);
|
||||
tcol->set_cell_data_func(*(tcol->get_first_cell()),
|
||||
sigc::bind(sigc::ptr_fun(app_attr_cell_renderer_func), col_storage));
|
||||
sigc::bind(sigc::ptr_fun(app_list_cell_renderer_func), col_storage));
|
||||
}
|
||||
|
||||
|
||||
@@ -783,7 +759,7 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
|
||||
for (unsigned int i = 0; i < num_tree_cols; ++i) {
|
||||
Gtk::TreeViewColumn* tcol = treeview->get_column(i);
|
||||
tcol->set_cell_data_func(*(tcol->get_first_cell()),
|
||||
sigc::bind(sigc::ptr_fun(app_statistic_cell_renderer_func), col_storage));
|
||||
sigc::bind(sigc::ptr_fun(app_list_cell_renderer_func), col_storage));
|
||||
}
|
||||
|
||||
|
||||
@@ -988,7 +964,7 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
|
||||
for (unsigned int i = 0; i < num_tree_cols; ++i) {
|
||||
Gtk::TreeViewColumn* tcol = treeview->get_column(i);
|
||||
tcol->set_cell_data_func(*(tcol->get_first_cell()),
|
||||
sigc::bind(sigc::ptr_fun(app_attr_cell_renderer_func), col_storage));
|
||||
sigc::bind(sigc::ptr_fun(app_list_cell_renderer_func), col_storage));
|
||||
}
|
||||
|
||||
|
||||
@@ -1099,7 +1075,7 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
|
||||
for (unsigned int i = 0; i < num_tree_cols; ++i) {
|
||||
Gtk::TreeViewColumn* tcol = treeview->get_column(i);
|
||||
tcol->set_cell_data_func(*(tcol->get_first_cell()),
|
||||
sigc::bind(sigc::ptr_fun(app_attr_cell_renderer_func), col_storage));
|
||||
sigc::bind(sigc::ptr_fun(app_list_cell_renderer_func), col_storage));
|
||||
}
|
||||
|
||||
|
||||
@@ -1157,7 +1133,7 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
|
||||
row[col_details] = (type_details.empty() ? "-" : type_details); // e.g. OBS has no details
|
||||
// There are no descriptions in self-test log entries, so don't display
|
||||
// "No description available" for all of them.
|
||||
// row[col_tooltip] = iter->get_description();
|
||||
row[col_tooltip] = iter->get_description();
|
||||
row[col_storage] = &(*iter);
|
||||
row[col_mark_name] = "Error " + hz::number_to_string(iter->value_error_block.error_num);
|
||||
}
|
||||
@@ -1309,7 +1285,7 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
|
||||
for (unsigned int i = 0; i < num_tree_cols; ++i) {
|
||||
Gtk::TreeViewColumn* tcol = treeview->get_column(i);
|
||||
tcol->set_cell_data_func(*(tcol->get_first_cell()),
|
||||
sigc::bind(sigc::ptr_fun(app_attr_cell_renderer_func), col_storage));
|
||||
sigc::bind(sigc::ptr_fun(app_list_cell_renderer_func), col_storage));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user