summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gnome-disk-health.glade301
-rw-r--r--gnome-disk-health.vala246
-rw-r--r--smartkitd.vala49
3 files changed, 443 insertions, 153 deletions
diff --git a/gnome-disk-health.glade b/gnome-disk-health.glade
index c345aba..a1a122f 100644
--- a/gnome-disk-health.glade
+++ b/gnome-disk-health.glade
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
-<!--Generated with glade3 3.4.4 on Mon Jun 30 23:57:51 2008 -->
+<!--Generated with glade3 3.4.4 on Tue Jul 1 17:44:40 2008 -->
<glade-interface>
<widget class="GtkDialog" id="DiskHealthDialog">
<property name="border_width">5</property>
@@ -48,54 +48,66 @@
<property name="column_spacing">6</property>
<property name="row_spacing">6</property>
<child>
- <widget class="GtkLabel" id="label5">
+ <widget class="GtkLabel" id="firmwareLabel">
<property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">&lt;b&gt;Path:&lt;/b&gt;</property>
- <property name="use_markup">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">label</property>
</widget>
<packing>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label6">
+ <widget class="GtkLabel" id="serialLabel">
<property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">&lt;b&gt;Size:&lt;/b&gt;</property>
- <property name="use_markup">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">label</property>
</widget>
<packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label7">
+ <widget class="GtkLabel" id="modelLabel">
<property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">&lt;b&gt;Model:&lt;/b&gt;</property>
- <property name="use_markup">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">label</property>
</widget>
<packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
- <property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label8">
+ <widget class="GtkLabel" id="sizeLabel">
<property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">&lt;b&gt;Serial Number:&lt;/b&gt;</property>
- <property name="use_markup">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">label</property>
</widget>
<packing>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="x_options">GTK_FILL</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="pathLabel">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">label</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
</packing>
</child>
<child>
@@ -112,66 +124,54 @@
</packing>
</child>
<child>
- <widget class="GtkLabel" id="pathLabel">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">label</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="sizeLabel">
+ <widget class="GtkLabel" id="label8">
<property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">label</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">&lt;b&gt;Serial Number:&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
</widget>
<packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="modelLabel">
+ <widget class="GtkLabel" id="label7">
<property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">label</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">&lt;b&gt;Model:&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
</widget>
<packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="serialLabel">
+ <widget class="GtkLabel" id="label6">
<property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">label</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">&lt;b&gt;Size:&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
</widget>
<packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="firmwareLabel">
+ <widget class="GtkLabel" id="label5">
<property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">label</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">&lt;b&gt;Path:&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
</widget>
<packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
</packing>
</child>
</widget>
@@ -236,6 +236,16 @@
<property name="position">3</property>
</packing>
</child>
+ <child>
+ <widget class="GtkLabel" id="powerOnLabel">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">The disk has been powered on for 3.1 months.</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="padding">16</property>
@@ -299,67 +309,58 @@
<property name="column_spacing">6</property>
<property name="row_spacing">6</property>
<child>
- <widget class="GtkLabel" id="label21">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">&lt;b&gt;Name:&lt;/b&gt;</property>
- <property name="use_markup">True</property>
- </widget>
- <packing>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label22">
+ <widget class="GtkLabel" id="verdictLabel">
<property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">&lt;b&gt;ID:&lt;/b&gt;</property>
- <property name="use_markup">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">n/a</property>
</widget>
<packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">6</property>
+ <property name="bottom_attach">7</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label23">
+ <widget class="GtkLabel" id="label33">
<property name="visible">True</property>
<property name="xalign">1</property>
- <property name="label" translatable="yes">&lt;b&gt;Current Value:&lt;/b&gt;</property>
+ <property name="label" translatable="yes">&lt;b&gt;Verdict:&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
+ <property name="top_attach">6</property>
+ <property name="bottom_attach">7</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label24">
+ <widget class="GtkLabel" id="typeLabel">
<property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">&lt;b&gt;Worst Value:&lt;/b&gt;</property>
- <property name="use_markup">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">n/a</property>
</widget>
<packing>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label25">
+ <widget class="GtkLabel" id="thresholdLabel">
<property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">&lt;b&gt;Threshold:&lt;/b&gt;</property>
- <property name="use_markup">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">n/a</property>
</widget>
<packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
@@ -367,28 +368,31 @@
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label26">
+ <widget class="GtkLabel" id="worstLabel">
<property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">&lt;b&gt;Type:&lt;/b&gt;</property>
- <property name="use_markup">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">n/a</property>
</widget>
<packing>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="nameLabel">
+ <widget class="GtkLabel" id="currentLabel">
<property name="visible">True</property>
<property name="xalign">0</property>
- <property name="label" translatable="yes">label</property>
+ <property name="label" translatable="yes">n/a</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
@@ -397,7 +401,7 @@
<widget class="GtkLabel" id="idLabel">
<property name="visible">True</property>
<property name="xalign">0</property>
- <property name="label" translatable="yes">label</property>
+ <property name="label" translatable="yes">n/a</property>
</widget>
<packing>
<property name="left_attach">1</property>
@@ -409,44 +413,40 @@
</packing>
</child>
<child>
- <widget class="GtkLabel" id="currentLabel">
+ <widget class="GtkLabel" id="nameLabel">
<property name="visible">True</property>
<property name="xalign">0</property>
- <property name="label" translatable="yes">label</property>
+ <property name="label" translatable="yes">n/a</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="worstLabel">
+ <widget class="GtkLabel" id="label26">
<property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">label</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">&lt;b&gt;Type:&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
</widget>
<packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="thresholdLabel">
+ <widget class="GtkLabel" id="label25">
<property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">label</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">&lt;b&gt;Threshold:&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
</widget>
<packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
@@ -454,45 +454,55 @@
</packing>
</child>
<child>
- <widget class="GtkLabel" id="typeLabel">
+ <widget class="GtkLabel" id="label24">
<property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">label</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">&lt;b&gt;Worst Value:&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
</widget>
<packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label33">
+ <widget class="GtkLabel" id="label23">
<property name="visible">True</property>
<property name="xalign">1</property>
- <property name="label" translatable="yes">&lt;b&gt;Verdict:&lt;/b&gt;</property>
+ <property name="label" translatable="yes">&lt;b&gt;Current Value:&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
- <property name="top_attach">6</property>
- <property name="bottom_attach">7</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="verdictLabel">
+ <widget class="GtkLabel" id="label22">
<property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">label</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">&lt;b&gt;ID:&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label21">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">&lt;b&gt;Name:&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
</widget>
<packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">6</property>
- <property name="bottom_attach">7</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
@@ -598,7 +608,17 @@
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
- <property name="layout_style">GTK_BUTTONBOX_END</property>
+ <property name="layout_style">GTK_BUTTONBOX_EDGE</property>
+ <child>
+ <widget class="GtkButton" id="refreshButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="label" translatable="yes">gtk-refresh</property>
+ <property name="use_stock">True</property>
+ <property name="response_id">0</property>
+ </widget>
+ </child>
<child>
<widget class="GtkButton" id="closeButton">
<property name="visible">True</property>
@@ -608,6 +628,9 @@
<property name="use_stock">True</property>
<property name="response_id">0</property>
</widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
</child>
</widget>
<packing>
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("<b>Warning:</b> 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;
}
diff --git a/smartkitd.vala b/smartkitd.vala
index 7e60403..1cbc41e 100644
--- a/smartkitd.vala
+++ b/smartkitd.vala
@@ -85,13 +85,14 @@ public interface DiskAPI {
public abstract uint getExtendedTestPollingMinutes() throws Error;
public abstract uint getConveyanceTestPollingMinutes() throws Error;
-/* public abstract DBus.ObjectPath[] getAttributes() throws Error; */
+ public abstract DBus.ObjectPath[] getAttributes() throws Error;
}
[DBus (name = "net.poettering.SmartKit.Manager")]
public interface ManagerAPI {
public abstract DBus.ObjectPath getDiskByUDI(string udi) throws Error;
public abstract DBus.ObjectPath getDiskByPath(string path) throws Error;
+ public abstract DBus.ObjectPath[] getDisks() throws Error;
}
string clean_path(string s) {
@@ -114,7 +115,7 @@ public class Attribute : GLib.Object, AttributeAPI {
public Disk disk { get; construct; }
public DBus.Connection connection { get; construct; }
- public uint8 id;
+ public uint8 _id;
public string name;
public SmartAttributeUnit pretty_unit;
public uint8 threshold;
@@ -132,7 +133,7 @@ public class Attribute : GLib.Object, AttributeAPI {
}
public void set(SmartAttributeParsedData a) {
- id = a.id;
+ _id = a.id;
name = a.name;
pretty_unit = a.pretty_unit;
threshold = a.threshold;
@@ -153,7 +154,7 @@ public class Attribute : GLib.Object, AttributeAPI {
}
public uint8 getId() throws Error {
- return id;
+ return _id;
}
public string getName() throws Error {
@@ -169,10 +170,12 @@ public class Attribute : GLib.Object, AttributeAPI {
return "none";
case SmartAttributeUnit.MSECONDS:
return "mseconds";
+ case SmartAttributeUnit.SECTORS:
+ return "sectors";
case SmartAttributeUnit.MKELVIN:
return "mkelvin";
default:
- throw new Error.UNKNOWN_UNIT("Unit unknown.");
+ throw new Error.UNKNOWN_UNIT("Unit unknown %i.", pretty_unit);
}
}
@@ -245,6 +248,12 @@ public class Disk : GLib.Object, DiskAPI {
}
private void attribute_callback(void* disk, SmartAttributeParsedData a) {
+ foreach (Attribute attr in attributes)
+ if (attr._id == a.id) {
+ attr.set(a);
+ return;
+ }
+
Attribute attr;
attr = new Attribute(this, this.connection);
@@ -350,9 +359,11 @@ public class Disk : GLib.Object, DiskAPI {
if (this.disk.smart_read_data() < 0)
throw new Error.SYSTEM("smart_read_data() failed: %s", Smart.strerror(Smart.errno));
+
+ populate_attributes();
}
- public void startSelfTest(string test) {
+ public void startSelfTest(string test) throws Error {
SmartSelfTest t;
switch (test) {
@@ -373,7 +384,7 @@ public class Disk : GLib.Object, DiskAPI {
throw new Error.SYSTEM("smart_self_test() failed: %s", Smart.strerror(Smart.errno));
}
- public void abortSelfTest() {
+ public void abortSelfTest() throws Error {
if (this.disk.smart_self_test(SmartSelfTest.ABORT) < 0)
throw new Error.SYSTEM("smart_self_test() failed: %s", Smart.strerror(Smart.errno));
@@ -517,6 +528,18 @@ public class Disk : GLib.Object, DiskAPI {
return d->conveyance_test_polling_minutes;
}
+ public DBus.ObjectPath[] getAttributes() throws Error {
+ DBus.ObjectPath[] p = new DBus.ObjectPath[attributes.length()];
+
+ int i = 0;
+ foreach (Attribute a in attributes) {
+ p[i++] = new DBus.ObjectPath(a.dbus_path);
+ }
+
+ return p;
+ }
+
+
/* public uint64 size { */
/* get { */
/* uint64 s; */
@@ -581,6 +604,18 @@ public class Manager : GLib.Object, ManagerAPI {
throw new Error.NOT_FOUND("Device not found");
}
+
+ public DBus.ObjectPath[] getDisks() throws Error {
+ DBus.ObjectPath[] p = new DBus.ObjectPath[disks.length()];
+
+ int i = 0;
+ foreach (Disk d in disks) {
+ p[i++] = new DBus.ObjectPath(d.dbus_path);
+ }
+
+ return p;
+ }
+
}
int main() {