NautilusFile: keep free space information directly

There were previously some tricks in nautilus to this effect:

 - when you call nautilus_file_get_volume_free_space() on a
   NautilusFile, the return result is NULL at first and later you get a
   "changed" signal on the file after the value is filled in

 - the value is being stored inside the NautilusDirectory equivalent for
   the file that is created when the call is first performed and kept
   around until after the change signal fires (so that the person
   receiving the change signal can still get the data).  This is done to
   save space by not expanding NautilusFile.

   The NautilusDirectory is then dropped after the change signal is done
   firing.

 - the nautilus properties window has a 200ms timeout after changes to
   files being reported before it re-queries the properties

The end result is that the NautilusDirectory (which holds the
information about the free space) is already freed by the time the
properties window tries to update the free space display.  This results
in the directory being recreated and the process starting over again.
The end result is that we never get the free space shown in the dialog
and instead we have an infinite loop of CPU usage (fortunately repeating
only every 200ms, so you get ~5% CPU usage instead of 100%).

We can solve the problem by just storing the free space information
directly in the NautilusFile details structure and dropping the dance
with NautilusDirectory; nothing in NautilusDirectory is actually using
that information anyway.

https://bugzilla.gnome.org/show_bug.cgi?id=673550
This commit is contained in:
Ryan Lortie 2012-04-05 10:48:41 -04:00
parent 07f22b823c
commit ba04ec0e74
4 changed files with 18 additions and 27 deletions

View file

@ -136,9 +136,6 @@ struct NautilusDirectoryDetails
GList *file_operations_in_progress; /* list of FileOperation * */
GHashTable *hidden_file_hash;
guint64 free_space; /* (guint)-1 for unknown */
time_t free_space_read; /* The time free_space was updated, or 0 for never */
};
NautilusDirectory *nautilus_directory_get_existing (GFile *location);

View file

@ -116,7 +116,6 @@ nautilus_directory_init (NautilusDirectory *directory)
directory->details->high_priority_queue = nautilus_file_queue_new ();
directory->details->low_priority_queue = nautilus_file_queue_new ();
directory->details->extension_queue = nautilus_file_queue_new ();
directory->details->free_space = (guint64)-1;
}
NautilusDirectory *

View file

@ -220,6 +220,9 @@ struct NautilusFileDetails
eel_boolean_bit filesystem_info_is_up_to_date : 1;
time_t trash_time; /* 0 is unknown */
guint64 free_space; /* (guint)-1 for unknown */
time_t free_space_read; /* The time free_space was updated, or 0 for never */
};
typedef struct {

View file

@ -165,6 +165,8 @@ nautilus_file_init (NautilusFile *file)
nautilus_file_clear_info (file);
nautilus_file_invalidate_extension_info_internal (file);
file->details->free_space = -1;
}
static GObject*
@ -6619,12 +6621,11 @@ get_fs_free_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
NautilusDirectory *directory;
NautilusFile *file;
guint64 free_space;
GFileInfo *info;
directory = NAUTILUS_DIRECTORY (user_data);
file = NAUTILUS_FILE (user_data);
free_space = (guint64)-1;
info = g_file_query_filesystem_info_finish (G_FILE (source_object),
@ -6636,15 +6637,12 @@ get_fs_free_cb (GObject *source_object,
g_object_unref (info);
}
if (directory->details->free_space != free_space) {
directory->details->free_space = free_space;
file = nautilus_directory_get_existing_corresponding_file (directory);
if (file) {
nautilus_file_emit_changed (file);
nautilus_file_unref (file);
}
if (file->details->free_space != free_space) {
file->details->free_space = free_space;
nautilus_file_emit_changed (file);
}
nautilus_directory_unref (directory);
nautilus_file_unref (file);
}
/**
@ -6657,35 +6655,29 @@ get_fs_free_cb (GObject *source_object,
char *
nautilus_file_get_volume_free_space (NautilusFile *file)
{
NautilusDirectory *directory;
GFile *location;
char *res;
time_t now;
directory = nautilus_directory_get_for_file (file);
now = time (NULL);
/* Update first time and then every 2 seconds */
if (directory->details->free_space_read == 0 ||
(now - directory->details->free_space_read) > 2) {
directory->details->free_space_read = now;
if (file->details->free_space_read == 0 ||
(now - file->details->free_space_read) > 2) {
file->details->free_space_read = now;
location = nautilus_file_get_location (file);
g_file_query_filesystem_info_async (location,
G_FILE_ATTRIBUTE_FILESYSTEM_FREE,
0, NULL,
get_fs_free_cb,
directory); /* Inherits ref */
nautilus_file_ref (file));
g_object_unref (location);
} else {
nautilus_directory_unref (directory);
}
res = NULL;
if (directory->details->free_space != (guint64)-1) {
res = g_format_size (directory->details->free_space);
if (file->details->free_space != (guint64)-1) {
res = g_format_size (file->details->free_space);
}
return res;
}