From f89ed71af80ebd54935cf14f01602ff73e8d8992 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 1 Jul 2008 18:57:23 +0200 Subject: lots of updates --- gnome-disk-health.vala | 246 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 239 insertions(+), 7 deletions(-) (limited to 'gnome-disk-health.vala') diff --git a/gnome-disk-health.vala b/gnome-disk-health.vala index 2632289..a3fcd4d 100644 --- a/gnome-disk-health.vala +++ b/gnome-disk-health.vala @@ -24,26 +24,51 @@ using DBus; using GLib; using Gtk; + +public DiskHealth disk_health; + public class DiskHealth : Gtk.Builder { string uifile = "gnome-disk-health.ui"; public bool create_widgets(string disk_string) { + test = null; + try { add_from_file (uifile); Gtk.Widget window = (Gtk.Widget) get_object("DiskHealthDialog"); + Gtk.TreeView tree_view = (Gtk.TreeView) get_object ("attributeTreeView"); + + /* id, name, text, icon, current, worst, threshold, type, verdict */ + list_store = new Gtk.ListStore(9, typeof(uint8), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string)); + + tree_view.set_model(list_store); + + tree_view.insert_column_with_attributes (-1, null, new Gtk.CellRendererPixbuf(), "icon-name", 3, null); + tree_view.insert_column_with_attributes(-1, "Name", new Gtk.CellRendererText(), "text", 1, null); + + Gtk.CellRenderer cell = new Gtk.CellRendererText(); + cell.set("xalign", 1.0, null); + tree_view.insert_column_with_attributes (-1, "Value", cell, "text", 2, null); + if (!setup_connection(disk_string)) return false; if (!fill_in_data()) return false; + setup_refresh_timer(); + window.show_all(); window.destroy += Gtk.main_quit; ((Gtk.Button) get_object("closeButton")).clicked += Gtk.main_quit; + ((Gtk.Button) get_object("refreshButton")).clicked += refresh; + + ((Gtk.Button) get_object("selfTestButton")).clicked += selfTest; + } catch (GLib.Error e) { stderr.printf("Failed to create main window: %s\n", e.message); return false; @@ -56,6 +81,8 @@ public class DiskHealth : Gtk.Builder { private dynamic DBus.Object manager; private DBus.ObjectPath dbus_path; private dynamic DBus.Object disk; + private Gtk.ListStore list_store; + private string test; public bool setup_connection(string disk_string) { try { @@ -86,6 +113,58 @@ public class DiskHealth : Gtk.Builder { return true; } + public void refresh() { + try { + disk.readSmartData(true); + fill_in_data(); + setup_refresh_timer(); + } catch (DBus.Error e) { + stderr.printf("D-Bus error: %s\n", e.message); + } + } + + public uint refresh_time; + public uint refresh_timer = 0; + + public void setup_refresh_timer() { + + uint t; + + if (refresh_time <= 0) + t = 5*60; + else if (refresh_time == 1) + t = 5; /* if 1 min is request, we do 10s + * instead, since we know that + * the minimal value is 1min */ + else + t = refresh_time*60; + + if (t > 5*60) + t = 5*60; + + stderr.printf("Setting wakeup to %u (%u)\n", t, refresh_time); + + disk_health = this; + + if (refresh_timer > 0) + Source.remove(refresh_timer); + refresh_timer = Timeout.add_seconds(t, + () => { + stderr.printf("Woke up\n"); + disk_health.refresh(); + return false; + }); + } + + public void selfTest() { + try { + disk.startSelfTest(test); + refresh(); + } catch (DBus.Error e) { + stderr.printf("D-Bus error: %s\n", e.message); + } + } + public bool fill_in_data() { try { @@ -124,10 +203,47 @@ public class DiskHealth : Gtk.Builder { ((Gtk.Label) get_object("healthLabel")).set_label(""); ((Gtk.Label) get_object("badSectorsLabel")).set_label(""); ((Gtk.Label) get_object("temperatureLabel")).set_label(""); + ((Gtk.Label) get_object("powerOnLabel")).set_label(""); return fill_in_no_self_test_data(); } + public string format_pretty(uint64 value, string unit) { + + switch (unit) { + + case "mseconds": + + if (value >= (uint64)1000*60*60*24*365) + return "%0.1f years".printf(((double) value)/(1000.0*60*60*24*365)); + else if (value >= (uint64) 1000*60*60*24*30) + return "%0.1f months".printf(((double) value)/(1000.0*60*60*24*30)); + else if (value >= 1000*60*60*24) + return "%0.1f days".printf(((double) value)/(1000.0*60*60*24)); + else if (value >= 1000*60*60) + return "%0.1f h".printf(((double) value)/(1000.0*60*60)); + else if (value >= 1000*60) + return "%0.1f min".printf(((double) value)/(1000.0*60)); + else if (value >= 1000) + return "%0.1f s".printf(((double) value)/(1000.0)); + else + return "%llu ms".printf(value); + + case "mkelvin": + return "%0.1f °C".printf(((double) value - 273150) / 1000); + + case "sectors": + return "%llu sectors".printf(value); + + case "none": + return "%llu".printf(value); + + } + + return "n/a"; + + } + public bool fill_in_smart_data() { try { @@ -136,16 +252,103 @@ public class DiskHealth : Gtk.Builder { bool b = disk.checkSmartStatus(); if (b) - ((Gtk.Label) get_object("healthLabel")).set_label("Disk reports to be healthy."); + ((Gtk.Label) get_object("healthLabel")).set_label("The disk reports to be healthy."); + else + ((Gtk.Label) get_object("healthLabel")).set_label("The disk reports that it has already failed or is expected to fail in the next 24h."); + + DBus.ObjectPath[] attrs = disk.getAttributes(); + + uint64 temp = 0; + uint64 rsc = 0; + uint64 rec = 0; + uint64 cps = 0; + uint64 ou = 0; + uint64 pon = 0; + + list_store.clear(); + + foreach (DBus.ObjectPath a in attrs) { + dynamic DBus.Object attribute; + uint8 id; + bool good, online, prefailure; + string name; + uint64 pretty_value; + string pretty_unit; + uint8 current, worst, threshold; + + attribute = connection.get_object("net.poettering.SmartKit", a, "net.poettering.SmartKit.Attribute"); + + /* id, name, text, icon, current, worst, threshold, type, verdict */ + + id = attribute.getId(); + name = attribute.getName(); + pretty_value = attribute.getPrettyValue(); + pretty_unit = attribute.getPrettyUnit(); + good = attribute.isGood(); + current = attribute.getCurrentValue(); + worst = attribute.getWorstValue(); + threshold = attribute.getThreshold(); + online = attribute.isOnline(); + prefailure = attribute.isPrefailure(); + + Gtk.TreeIter iter; + list_store.append(out iter); + list_store.set(iter, + 0, id, + 1, name, + 2, format_pretty(pretty_value, pretty_unit), + 3, good ? "dialog-ok" : "dialog-warning", + 4, "%u".printf(current), + 5, "%u".printf(worst), + 6, "%u".printf(threshold), + 7, "%s/%s".printf(online ? "Online" : "Offline", prefailure ? "Prefailure" : "Old Age"), + 8, good ? "OK" : "FAILURE", + -1); + + if (name == "reallocated-sector-count") + rsc = pretty_value; + if (name == "reallocated-event-count") + rec = pretty_value; + if (name == "current-pending-sector") + cps = pretty_value; + if (name == "offline-uncorrectable") + ou = pretty_value; + + if (name == "temperature-celsius-1" || + name == "temperature-celsius-2" || + name == "airflow-temperature-celsius") + if (pretty_value > temp) + temp = pretty_value; + + if (name == "power-on-minutes" || + name == "power-on-seconds" || + name == "power-on-hours") + pon = pretty_value; + } + + uint64 sectors = cps + ou + (rsc > rec ? rsc : rec); + if (sectors > 0) + ((Gtk.Label) get_object("badSectorsLabel")).set_markup("Warning: The disk reports to have %llu bad sectors.".printf(sectors)); + else + ((Gtk.Label) get_object("badSectorsLabel")).set_label("The disk reports to have no bad sectors."); + + if (temp > 0) + ((Gtk.Label) get_object("temperatureLabel")).set_label("The current temperature of the disk is %0.1f °C.".printf((double) (temp - 273150) / 1000)); else - ((Gtk.Label) get_object("healthLabel")).set_label("Disk reports that it has already failed or is expected to fail in the next 24h."); + ((Gtk.Label) get_object("temperatureLabel")).set_label(""); + + + if (pon > 0) + ((Gtk.Label) get_object("powerOnLabel")).set_label("The disk has been powered on for %s.".printf(format_pretty(pon, "mseconds"))); + else + ((Gtk.Label) get_object("powerOnLabel")).set_label(""); bool a = disk.getStartTestAvailable(); b = disk.getConveyanceTestAvailable(); bool c = disk.getShortAndExtendedTestAvailable(); if (a && (b || c)) - return fill_in_self_test_data(); + return fill_in_self_test_data(c, b); else return fill_in_no_self_test_data(); @@ -155,7 +358,7 @@ public class DiskHealth : Gtk.Builder { } } - public bool fill_in_self_test_data() { + public bool fill_in_self_test_data(bool sae, bool c) { try { bool show_percent = false; string text; @@ -191,7 +394,7 @@ public class DiskHealth : Gtk.Builder { text = "The previous self-test completed having a test element that failed and the device is suspected of having handling damage."; break; case "inprogress": - text = "Self-test in progres..."; + text = "Self-test in progress..."; show_percent = true; break; @@ -200,7 +403,6 @@ public class DiskHealth : Gtk.Builder { break; } - ((Gtk.Label) get_object("selfTestLabel")).set_label(text); if (show_percent) { @@ -208,11 +410,40 @@ public class DiskHealth : Gtk.Builder { ((Gtk.ProgressBar) get_object("selfTestProgressBar")).set_fraction((double) (100-percent)/100); ((Gtk.ProgressBar) get_object("selfTestProgressBar")).set_text("%u%% remaining".printf(percent)); - } else + } else { + ((Gtk.ProgressBar) get_object("selfTestProgressBar")).set_fraction(0.0); ((Gtk.ProgressBar) get_object("selfTestProgressBar")).set_text("n/a"); + } ((Gtk.ProgressBar) get_object("selfTestProgressBar")).set_sensitive(show_percent); + if (state == "inprogress") { + ((Gtk.Button) get_object("selfTestButton")).set_label("Abort Self-Test"); + bool b = disk.getAbortTestAvailable(); + ((Gtk.Button) get_object("selfTestButton")).set_sensitive(b); + + this.test = "abort"; + + if (sae) + this.refresh_time = disk.getShortTestPollingMinutes(); + else + this.refresh_time = disk.getConveyanceTestPollingMinutes(); + + + } else { + uint saet, ct; + + ((Gtk.Button) get_object("selfTestButton")).set_label("Start Self-Test"); + ((Gtk.Button) get_object("selfTestButton")).set_sensitive(true); + + if (sae) + this.test = "short"; + else + this.test = "conveyance"; + + this.refresh_time = 0; + } + } catch (DBus.Error e) { stderr.printf("D-Bus error: %s\n", e.message); return false; @@ -226,6 +457,7 @@ public class DiskHealth : Gtk.Builder { ((Gtk.Button) get_object("selfTestButton")).set_sensitive(false); ((Gtk.ProgressBar) get_object("selfTestProgressBar")).set_sensitive(false); + test = null; return true; } -- cgit