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()
 
openSUSE Build Service is sponsored by