diff options
author | Razvan Chitu <razvan.ch95@gmail.com> | 2016-03-14 11:18:55 +0200 |
---|---|---|
committer | Razvan Chitu <razvan.ch95@gmail.com> | 2016-04-08 00:13:44 +0300 |
commit | a99b4cf8f1163a2ef8a6cd1d713482978deebf7b (patch) | |
tree | 5362246d0b2e50a4e4f90d7b9748c8ab099d43ab /libnautilus-private | |
parent | 0e3ebc7cdbba0df6673c3ba1ee1c2fc26d11f8f5 (diff) | |
download | nautilus-a99b4cf8f1163a2ef8a6cd1d713482978deebf7b.tar.gz |
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
Diffstat (limited to 'libnautilus-private')
-rw-r--r-- | 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 695b87e82..fd26421aa 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); } |