[gnome-boxes] Add update CPU graph
- From: Marc-Andre Lureau <malureau src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-boxes] Add update CPU graph
- Date: Mon, 14 Nov 2011 19:00:02 +0000 (UTC)
commit effa223f1536e0ffc6544720ebafb4f1a0b075c8
Author: Marc-Andrà Lureau <marcandre lureau gmail com>
Date: Wed Nov 9 23:32:56 2011 +0100
Add update CPU graph
data/gtk-style.css | 7 +++
src/libvirt-machine.vala | 132 +++++++++++++++++++++++++++++++++++++++++++---
src/machine.vala | 27 +++++++++-
src/mini-graph.vala | 2 +-
src/properties.vala | 35 ++++++++++--
5 files changed, 187 insertions(+), 16 deletions(-)
---
diff --git a/data/gtk-style.css b/data/gtk-style.css
index 77f5dab..6b269ac 100644
--- a/data/gtk-style.css
+++ b/data/gtk-style.css
@@ -39,6 +39,12 @@
font-weight: bold;
}
+.boxes-graph-label {
+ font-size: 8;
+ font-family: monospace;
+ color: #989898;
+}
+
.boxes-source-nb {
border-radius: 15;
}
@@ -53,6 +59,7 @@
from (@boxes_selected_color),
to (darker (@boxes_selected_color)));
}
+
.boxes-continue:insensitive {
background-image: none;
}
diff --git a/src/libvirt-machine.vala b/src/libvirt-machine.vala
index 14d85b3..13ff4df 100644
--- a/src/libvirt-machine.vala
+++ b/src/libvirt-machine.vala
@@ -35,10 +35,10 @@ private class Boxes.LibvirtMachine: Boxes.Machine {
if (state == DomainState.PAUSED) {
started_id = domain.resumed.connect (() => {
- domain.disconnect (started_id);
- started_id = 0;
- connect_display ();
- });
+ domain.disconnect (started_id);
+ started_id = 0;
+ connect_display ();
+ });
try {
domain.resume ();
} catch (GLib.Error error) {
@@ -46,10 +46,10 @@ private class Boxes.LibvirtMachine: Boxes.Machine {
}
} else {
started_id = domain.started.connect (() => {
- domain.disconnect (started_id);
- started_id = 0;
- connect_display ();
- });
+ domain.disconnect (started_id);
+ started_id = 0;
+ connect_display ();
+ });
try {
domain.start (0);
} catch (GLib.Error error) {
@@ -62,6 +62,24 @@ private class Boxes.LibvirtMachine: Boxes.Machine {
update_display ();
}
+ struct MachineStat {
+ int64 timestamp;
+ double cpu_time;
+ double cpu_time_abs;
+ double cpu_guest_percent;
+ double memory_percent;
+ uint disk_read;
+ uint disk_write;
+ uint net_read;
+ uint net_write;
+ }
+
+ static const int STATS_SIZE = 20;
+ private MachineStat[] stats;
+ construct {
+ stats = new MachineStat[STATS_SIZE];
+ }
+
public LibvirtMachine (CollectionSource source, Boxes.App app,
GVir.Connection connection, GVir.Domain domain) {
base (source, app, domain.get_name ());
@@ -71,6 +89,104 @@ private class Boxes.LibvirtMachine: Boxes.Machine {
this.domain = domain;
set_screenshot_enable (true);
+ set_stats_enable (true);
+ }
+
+ private void update_cpu_stat (DomainInfo info, ref MachineStat stat) {
+ var prev = stats[STATS_SIZE - 1];
+
+ if (info.state == DomainState.CRASHED ||
+ info.state == DomainState.SHUTOFF)
+ return;
+
+ stat.cpu_time = info.cpuTime - prev.cpu_time_abs;
+ stat.cpu_time_abs = info.cpuTime;
+ // hmm, where does this x10 come from?
+ var dt = (stat.timestamp - prev.timestamp) * 10;
+ var percent = stat.cpu_time / dt;
+ percent = percent / info.nrVirtCpu;
+ stat.cpu_guest_percent = percent.clamp (0, 100);
+ }
+
+ private void update_mem_stat (DomainInfo info, ref MachineStat stat) {
+ if (!is_running ())
+ return;
+
+ stat.memory_percent = info.memory * 100.0 / info.maxMem;
+ }
+
+ private void update_io_stat (ref MachineStat stat) {
+ }
+
+
+ public signal void stats_updated ();
+
+ public double[] cpu_stats;
+ public double[] io_stats;
+ public double[] net_stats;
+ private void update_stats () {
+ cpu_stats = {};
+ io_stats = {};
+ net_stats = {};
+
+ foreach (var s in stats) {
+ cpu_stats += s.cpu_guest_percent;
+ }
+
+ stats_updated ();
+ }
+
+ private void update_net_stat (ref MachineStat stat) {
+ try {
+ // var xmldoc = domain.get_config (0).doc;
+ // var target_dev = extract_xpath (xmldoc,
+ // "string(/domain/devices/interface[ type='network']/target/@dev)", true);
+ // if (target_dev == "")
+ // return;
+ // var interfaces = domain.get_interfaces ();
+ // foreach (var iface in interfaces)
+ // message (iface.name);
+ } catch (GLib.Error err) {
+ }
+ }
+
+ private uint stats_id;
+ public void set_stats_enable (bool enable) {
+ if (enable) {
+ if (stats_id != 0)
+ return;
+
+ stats_id = Timeout.add_seconds (1, () => {
+ try {
+ var now = get_monotonic_time ();
+ var stat = MachineStat () { timestamp = now };
+ var info = domain.get_info ();
+
+ // message (domain.get_config (0).to_xml ());
+ // message (domain.get_config (0).get_node_content ("devices"));
+ // var devices = domain.get_config (0).get_devices ().data;
+ // foreach (var d in devices) {
+ // message (d.to_xml ());
+ // }
+ update_cpu_stat (info, ref stat);
+ update_mem_stat (info, ref stat);
+ update_io_stat (ref stat);
+ update_net_stat (ref stat);
+
+ stats = stats[1:STATS_SIZE];
+ stats += stat;
+
+ update_stats ();
+ } catch (GLib.Error err) {
+ warning (err.message);
+ }
+ return true;
+ });
+ } else {
+ if (stats_id != 0)
+ GLib.Source.remove (stats_id);
+ stats_id = 0;
+ }
}
public override List<Pair<string, Widget>> get_properties (Boxes.PropertiesPage page) {
diff --git a/src/machine.vala b/src/machine.vala
index 8435c98..fe06859 100644
--- a/src/machine.vala
+++ b/src/machine.vala
@@ -233,6 +233,7 @@ private class Boxes.MachineActor: Boxes.UI {
public override Clutter.Actor actor { get { return box; } }
public Clutter.Box box;
+ private Clutter.BindConstraint yconstraint;
private GtkClutter.Texture screenshot;
private GtkClutter.Actor gtk_vbox;
private GtkClutter.Actor? display;
@@ -240,6 +241,14 @@ private class Boxes.MachineActor: Boxes.UI {
private Gtk.VBox vbox; // and the vbox under it
private Gtk.Entry password_entry;
private Machine machine;
+ private ulong height_id;
+
+ static const int properties_y = 200;
+
+ ~MachineActor() {
+ machine.app.actor.disconnect (height_id);
+ height_id = 0;
+ }
public MachineActor (Machine machine) {
this.machine = machine;
@@ -287,6 +296,14 @@ private class Boxes.MachineActor: Boxes.UI {
actor_add (gtk_vbox, box);
actor.set_reactive (true);
+
+ yconstraint = new Clutter.BindConstraint (machine.app.actor, BindCoordinate.Y,
+ machine.app.actor.height - properties_y);
+ height_id = machine.app.actor.notify["height"].connect (() => {
+ yconstraint.set_offset (machine.app.actor.height - properties_y);
+ });
+
+ yconstraint.enabled = false;
}
public void scale_screenshot (float scale = 1.5f) {
@@ -320,6 +337,7 @@ private class Boxes.MachineActor: Boxes.UI {
public override void ui_state_changed () {
int width, height;
+ yconstraint.enabled = false;
machine.app.window.get_size (out width, out height);
switch (ui_state) {
@@ -376,12 +394,17 @@ private class Boxes.MachineActor: Boxes.UI {
display.width = (float) width;
display.height = (float) height;
actor_add (display, machine.app.stage);
+ display.add_constraint (yconstraint);
display.animate (Clutter.AnimationMode.LINEAR, Boxes.App.duration,
"x", 10.0f,
"y", height - 200.0f,
- "width", 190.0f,
- "height", 130.0f);
+ "width", 180.0f,
+ "height", 130.0f).completed.connect (() => {
+ message ("enabled");
+ yconstraint.enabled = true;
+ });
+
break;
default:
diff --git a/src/mini-graph.vala b/src/mini-graph.vala
index dbf2ab8..275e1a9 100644
--- a/src/mini-graph.vala
+++ b/src/mini-graph.vala
@@ -44,7 +44,7 @@ private class Boxes.MiniGraph: Gtk.DrawingArea {
int width = get_allocated_width ();
int height = get_allocated_height ();
- Gdk.cairo_set_source_color (cr, get_style ().dark[get_state ()]);
+ Gdk.cairo_set_source_rgba (cr, get_boxes_bg_color ());
cr.rectangle (0, 0, width, height);
cr.fill ();
diff --git a/src/properties.vala b/src/properties.vala
index 9be7d58..6361393 100644
--- a/src/properties.vala
+++ b/src/properties.vala
@@ -53,6 +53,7 @@ private class Boxes.Properties: Boxes.UI {
private MiniGraph cpu;
private MiniGraph io;
private MiniGraph net;
+ private ulong stats_id;
private class PageWidget {
public Gtk.Widget widget;
@@ -142,6 +143,13 @@ private class Boxes.Properties: Boxes.UI {
}
tree_view.get_selection ().select_path (new Gtk.TreePath.from_string ("0"));
+
+ var machine = app.current_item as LibvirtMachine;
+ if (machine != null) {
+ stats_id = machine.stats_updated.connect (() => {
+ cpu.points = machine.cpu_stats;
+ });
+ }
}
private void setup_ui () {
@@ -195,20 +203,32 @@ private class Boxes.Properties: Boxes.UI {
vbox.pack_start (tree_view, true, true, 0);
var grid = new Gtk.Grid ();
- vbox.pack_start (grid, true, true, 0);
+ vbox.pack_start (grid, false, false, 0);
grid.column_homogeneous = true;
-
- grid.attach (new Gtk.Label (_("CPU:")), 0, 0, 1, 1);
+ grid.column_spacing = 2;
+ grid.margin_left = 10;
+ grid.margin_right = 10;
+ /* this will need to be FIXME */
+ grid.margin_bottom = 30;
+ grid.margin_top = 200;
+
+ var label = new Gtk.Label (_("CPU:"));
+ label.get_style_context ().add_class ("boxes-graph-label");
+ grid.attach (label, 0, 0, 1, 1);
cpu = new MiniGraph.with_ymax ({}, 100.0, 20);
cpu.hexpand = true;
grid.attach (cpu, 1, 0, 1, 1);
- grid.attach (new Gtk.Label (_("I/O:")), 2, 0, 1, 1);
+ label = new Gtk.Label (_("I/O:"));
+ label.get_style_context ().add_class ("boxes-graph-label");
+ grid.attach (label, 2, 0, 1, 1);
io = new MiniGraph.with_ymax ({}, 100.0, 20);
io.hexpand = true;
grid.attach (io, 3, 0, 1, 1);
- grid.attach (new Gtk.Label (_("Net:")), 4, 0, 1, 1);
+ label = new Gtk.Label (_("Net:"));
+ label.get_style_context ().add_class ("boxes-graph-label");
+ grid.attach (label, 4, 0, 1, 1);
net = new MiniGraph.with_ymax ({}, 100.0, 20);
net.hexpand = true;
grid.attach (net, 5, 0, 1, 1);
@@ -218,6 +238,11 @@ private class Boxes.Properties: Boxes.UI {
}
public override void ui_state_changed () {
+ if (stats_id != 0) {
+ app.current_item.disconnect (stats_id);
+ stats_id = 0;
+ }
+
switch (ui_state) {
case UIState.PROPERTIES:
toolbar_label_bind = app.current_item.bind_property ("name", toolbar_label, "label", BindingFlags.SYNC_CREATE);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]