[nautilus] trash-monitor: change trash monitoring process



commit a99b4cf8f1163a2ef8a6cd1d713482978deebf7b
Author: Razvan Chitu <razvan ch95 gmail com>
Date:   Mon Mar 14 11:18:55 2016 +0200

    trash-monitor: change trash monitoring process
    
    In Nautilus, the trash is monitored for state changes - going from empty to
    non-empty and the other way round. Monitoring is done by handling change signals
    from a regular file monitor. On each signal, an enumeration of the trash
    contents is started in order to see if it is empty or not. This causes issues
    when many files are trashed, because the gvfs trash backend is flooded with
    enumeration requests, resulting in CPU usage spikes. In order to fix this, the
    "item-count" attribute of the trash should be queried instead.
    
    Replace asynchronous enumeration with asynchronous information query and update
    the trash state based on the "item-count" attribute.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=763218

 libnautilus-private/nautilus-trash-monitor.c |   65 +++++++++++---------------
 1 files changed, 28 insertions(+), 37 deletions(-)
---
diff --git a/libnautilus-private/nautilus-trash-monitor.c b/libnautilus-private/nautilus-trash-monitor.c
index 695b87e..fd26421 100644
--- a/libnautilus-private/nautilus-trash-monitor.c
+++ b/libnautilus-private/nautilus-trash-monitor.c
@@ -97,44 +97,35 @@ update_empty_info (NautilusTrashMonitor *trash_monitor,
                       trash_monitor->details->empty);
 }
 
+/* Use G_FILE_ATTRIBUTE_TRASH_ITEM_COUNT since we only want to know whether the
+ * trash is empty or not, not access its children. This is available for the
+ * trash backend since it uses a cache. In this way we prevent flooding the
+ * trash backend with enumeration requests when trashing > 1000 files
+ */
 static void
-enumerate_next_files_cb (GObject *source,
-                        GAsyncResult *res,
-                        gpointer user_data)
+trash_query_info_cb (GObject *source,
+                     GAsyncResult *res,
+                     gpointer user_data)
 {
-       NautilusTrashMonitor *trash_monitor = user_data;
-       GList *infos;
-
-       infos = g_file_enumerator_next_files_finish (G_FILE_ENUMERATOR (source), res, NULL);
-       if (!infos) {
-               update_empty_info (trash_monitor, TRUE);
-       } else {
-               update_empty_info (trash_monitor, FALSE);
-               g_list_free_full (infos, g_object_unref);
-       }
+        NautilusTrashMonitor *trash_monitor = user_data;
+        GFileInfo *info;
+        guint32 item_count;
+        gboolean is_empty = TRUE;
 
-       g_object_unref (trash_monitor);
-}
+        info = g_file_query_info_finish (G_FILE (source), res, NULL);
 
-static void
-enumerate_children_cb (GObject *source,
-                      GAsyncResult *res,
-                      gpointer user_data)
-{
-       GFileEnumerator *enumerator;
-       NautilusTrashMonitor *trash_monitor = user_data;
+        if (info != NULL) {
+                item_count = g_file_info_get_attribute_uint32 (info,
+                                                               G_FILE_ATTRIBUTE_TRASH_ITEM_COUNT);
+                is_empty = item_count == 0;
 
-       enumerator = g_file_enumerate_children_finish (G_FILE (source), res, NULL);
-       if (!enumerator) {
-               update_empty_info (trash_monitor, TRUE);
-               g_object_unref (trash_monitor);
-               return;
-       }
+                g_object_unref (info);
+
+        }
+
+        update_empty_info (trash_monitor, is_empty);
 
-       g_file_enumerator_next_files_async (enumerator, 1,
-                                           G_PRIORITY_DEFAULT, NULL,
-                                           enumerate_next_files_cb, trash_monitor);
-       g_object_unref (enumerator);
+        g_object_unref (trash_monitor);
 }
 
 static void
@@ -143,11 +134,11 @@ schedule_update_info (NautilusTrashMonitor *trash_monitor)
        GFile *location;
 
        location = g_file_new_for_uri ("trash:///");
-       g_file_enumerate_children_async (location,
-                                        G_FILE_ATTRIBUTE_STANDARD_TYPE,
-                                        G_FILE_QUERY_INFO_NONE,
-                                        G_PRIORITY_DEFAULT, NULL,
-                                        enumerate_children_cb, g_object_ref (trash_monitor));
+        g_file_query_info_async (location,
+                                 G_FILE_ATTRIBUTE_TRASH_ITEM_COUNT,
+                                 G_FILE_QUERY_INFO_NONE,
+                                 G_PRIORITY_DEFAULT, NULL,
+                                 trash_query_info_cb, g_object_ref (trash_monitor));
        
        g_object_unref (location);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]