File virtman-memleak-callbacks.patch of Package virt-manager
Subject: manager: Separate stats and state update callbacks
From: Cole Robinson crobinso@redhat.com Mon Sep 2 09:09:31 2013 -0400
Date: Mon Sep 2 09:32:50 2013 -0400:
Git: f141c77c452d4807b516bdc40a0e86235bf5243a
There's no need to be resetting row keys like VM name, state, on every
'resources-sampled' signals, since we have had finer grained status-changed
and config-changed signals for a while. This seems to reduce the memory
leak on F19 as well.
Index: virt-manager-0.9.5/src/virtManager/manager.py
===================================================================
--- virt-manager-0.9.5.orig/src/virtManager/manager.py
+++ virt-manager-0.9.5/src/virtManager/manager.py
@@ -141,9 +141,9 @@ class vmmManager(vmmGObjectUI):
# XXX: Help docs useless/out of date
self.widget("menu_help").hide()
- self.vm_selected()
- self.widget("vm-list").get_selection().connect("changed",
- self.vm_selected)
+ self.update_current_selection()
+ self.widget("vm-list").get_selection().connect(
+ "changed", self.update_current_selection)
self.max_disk_rate = 10.0
self.max_net_rate = 10.0
@@ -708,9 +708,9 @@ class vmmManager(vmmGObjectUI):
def vm_added(self, conn, vmuuid):
vm = conn.get_vm(vmuuid)
+ vm.connect("config-changed", self.vm_config_changed)
vm.connect("status-changed", self.vm_status_changed)
- vm.connect("resources-sampled", self.vm_resources_sampled)
- vm.connect("config-changed", self.vm_resources_sampled, True)
+ vm.connect("resources-sampled", self.vm_row_updated)
vm.connect("inspection-changed", self.vm_inspection_changed)
vmlist = self.widget("vm-list")
@@ -829,7 +829,7 @@ class vmmManager(vmmGObjectUI):
conn.connect("vm-added", self.vm_added)
conn.connect("vm-removed", self.vm_removed)
- conn.connect("resources-sampled", self.conn_resources_sampled)
+ conn.connect("resources-sampled", self.conn_row_updated)
conn.connect("state-changed", self.conn_state_changed)
conn.connect("connect-error", self._connect_error)
@@ -854,7 +854,7 @@ class vmmManager(vmmGObjectUI):
continue
newname = conn.get_pretty_desc_inactive(False, True)
- self.conn_resources_sampled(conn, newname)
+ self.conn_state_changed(conn, newname=newname)
def remove_conn(self, engine_ignore, uri):
model = self.widget("vm-list").get_model()
@@ -877,6 +877,29 @@ class vmmManager(vmmGObjectUI):
# State/UI updating methods #
#############################
+ def vm_row_updated(self, vm):
+ row = self.rows.get(self.vm_row_key(vm), None)
+ if row is None:
+ return
+ self.widget("vm-list").get_model().row_changed(row.path, row.iter)
+
+ def vm_config_changed(self, vm):
+ if self.vm_row_key(vm) not in self.rows:
+ return
+
+ row = self.rows[self.vm_row_key(vm)]
+ row[ROW_NAME] = vm.get_name()
+ row[ROW_STATUS] = vm.run_status()
+ row[ROW_STATUS_ICON] = vm.run_status_icon_name()
+ row[ROW_IS_VM_RUNNING] = vm.is_active()
+ row[ROW_MARKUP] = self._build_vm_markup(row)
+
+ desc = vm.get_description()
+ if not uihelpers.can_set_row_none:
+ desc = desc or ""
+ row[ROW_HINT] = util.xml_escape(desc)
+ self.vm_row_updated(vm)
+
def vm_status_changed(self, vm, oldstatus, newstatus):
ignore = newstatus
ignore = oldstatus
@@ -887,7 +910,7 @@ class vmmManager(vmmGObjectUI):
missing = True
for row in range(model.iter_n_children(parent)):
_iter = model.iter_nth_child(parent, row)
- if model.get_value(_iter, ROW_KEY) == vm.get_uuid():
+ if model.get_value(_iter, ROW_HANDLE) == vm:
missing = False
break
@@ -895,27 +918,8 @@ class vmmManager(vmmGObjectUI):
self._append_vm(model, vm, vm.conn)
# Update run/shutdown/pause button states
- self.vm_selected()
- self.vm_resources_sampled(vm)
-
- def vm_resources_sampled(self, vm, config_changed=False):
- vmlist = self.widget("vm-list")
- model = vmlist.get_model()
-
- if self.vm_row_key(vm) not in self.rows:
- return
-
- row = self.rows[self.vm_row_key(vm)]
- row[ROW_NAME] = vm.get_name()
- row[ROW_STATUS] = vm.run_status()
- row[ROW_STATUS_ICON] = vm.run_status_icon_name()
- row[ROW_IS_VM_RUNNING] = vm.is_active()
- row[ROW_MARKUP] = self._build_vm_markup(row)
-
- if config_changed:
- row[ROW_HINT] = util.xml_escape(vm.get_description())
-
- model.row_changed(row.path, row.iter)
+ self.update_current_selection()
+ self.vm_config_changed(vm)
def vm_inspection_changed(self, vm):
vmlist = self.widget("vm-list")
@@ -927,7 +931,7 @@ class vmmManager(vmmGObjectUI):
row = self.rows[self.vm_row_key(vm)]
row[ROW_INSPECTION_OS_ICON] = \
self.get_inspection_icon_pixbuf(vm, 16, 16)
- model.row_changed(row.path, row.iter)
+ self.vm_row_updated(vm)
def get_inspection_icon_pixbuf(self, vm, w, h):
# libguestfs gives us the PNG data as a string.
@@ -943,13 +947,7 @@ class vmmManager(vmmGObjectUI):
except:
return None
- def conn_state_changed(self, conn):
- self.conn_resources_sampled(conn)
- self.vm_selected()
-
- def conn_resources_sampled(self, conn, newname=None):
- vmlist = self.widget("vm-list")
- model = vmlist.get_model()
+ def conn_state_changed(self, conn, newname=None):
row = self.rows[conn.get_uri()]
if newname:
@@ -964,20 +962,27 @@ class vmmManager(vmmGObjectUI):
if conn.get_state() in [vmmConnection.STATE_DISCONNECTED,
vmmConnection.STATE_CONNECTING]:
# Connection went inactive, delete any VM child nodes
- parent = self.rows[conn.get_uri()].iter
+ parent = row.iter
if parent is not None:
+ model = self.widget("vm-list").get_model()
child = model.iter_children(parent)
while child is not None:
- del self.rows[self.vm_row_key(model.get_value(child,
- ROW_HANDLE))]
+ vm = model[child][ROW_HANDLE]
+ del self.rows[self.vm_row_key(vm)]
model.remove(child)
child = model.iter_children(parent)
+ self.conn_row_updated(conn)
+ self.update_current_selection()
+
+ def conn_row_updated(self, conn):
+ row = self.rows[conn.get_uri()]
+
self.max_disk_rate = max(self.max_disk_rate, conn.disk_io_max_rate())
self.max_net_rate = max(self.max_net_rate,
conn.network_traffic_max_rate())
- model.row_changed(row.path, row.iter)
+ self.widget("vm-list").get_model().row_changed(row.path, row.iter)
def change_run_text(self, can_restore):
if can_restore:
@@ -989,7 +994,7 @@ class vmmManager(vmmGObjectUI):
self.vmmenu_items["run"].get_child().set_label(text)
self.widget("vm-run").set_label(strip_text)
- def vm_selected(self, ignore=None):
+ def update_current_selection(self, ignore=None):
conn = self.current_conn()
vm = self.current_vm()