nautilus r13697 - in trunk: . libnautilus-private



Author: alexl
Date: Wed Feb  6 15:06:19 2008
New Revision: 13697
URL: http://svn.gnome.org/viewvc/nautilus?rev=13697&view=rev

Log:
2008-02-06  Alexander Larsson  <alexl redhat com>

        * libnautilus-private/nautilus-directory-async.c:
        * libnautilus-private/nautilus-directory-private.h:
	Change how we handle cancellation of the directory count
	and mime list for files in a directory. We now make sure
	that the callback for the cancelled operation is run before
	starting a new one.
	
	This was causing problems when viewing a directory that had
	a subdirectory getting a lot of new files added, as for each
	new file added the directory count would be cancelled and
	re-started, leading to lots of outstanding (cancelled)
	operations. Each of these was using a file descriptor for
	the readdir operation, which wasn't really leaking (it was
	eventually freed) but could cause temporary out-of-fd errors.

	Perhaps we should do something similar for all kinds of
	operations, but its worst for dir count and mime list due to
	nautilus_directory_invalidate_count_and_mime_list() which is
	called on file creation.



Modified:
   trunk/ChangeLog
   trunk/libnautilus-private/nautilus-directory-async.c
   trunk/libnautilus-private/nautilus-directory-private.h

Modified: trunk/libnautilus-private/nautilus-directory-async.c
==============================================================================
--- trunk/libnautilus-private/nautilus-directory-async.c	(original)
+++ trunk/libnautilus-private/nautilus-directory-async.c	Wed Feb  6 15:06:19 2008
@@ -100,6 +100,7 @@
 
 struct MimeListState {
 	NautilusDirectory *directory;
+	NautilusFile *mime_list_file;
 	GCancellable *cancellable;
 	GFileEnumerator *enumerator;
 	GHashTable *mime_list_hash;
@@ -118,6 +119,7 @@
 
 struct DirectoryCountState {
 	NautilusDirectory *directory;
+	NautilusFile *count_file;
 	GCancellable *cancellable;
 	GFileEnumerator *enumerator;
 	int file_count;
@@ -309,7 +311,7 @@
 				(g_str_hash, g_str_equal,
 				 "nautilus-directory-async.c: async_jobs");
 		}
-		uri = = nautilus_directory_get_uri (directory);
+		uri = nautilus_directory_get_uri (directory);
 		key = g_strconcat (uri, ": ", job, NULL);
 		if (g_hash_table_lookup (async_jobs, key) != NULL) {
 			g_warning ("same job twice: %s in %s",
@@ -418,12 +420,6 @@
 {
 	if (directory->details->count_in_progress != NULL) {
 		g_cancellable_cancel (directory->details->count_in_progress->cancellable);
-		directory->details->count_in_progress->directory = NULL;
-		directory->details->count_in_progress = NULL;
-		directory->details->count_file = NULL;
-		
-
-		async_job_end (directory, "directory count");
 	}
 }
 
@@ -449,15 +445,7 @@
 mime_list_cancel (NautilusDirectory *directory)
 {
 	if (directory->details->mime_list_in_progress != NULL) {
-		g_assert (NAUTILUS_IS_FILE (directory->details->mime_list_file));
-
 		g_cancellable_cancel (directory->details->mime_list_in_progress->cancellable);
-		
-		directory->details->mime_list_in_progress->directory = NULL;
-		directory->details->mime_list_in_progress = NULL;
-		directory->details->mime_list_file = NULL;
-
-		async_job_end (directory, "MIME list");
 	}
 }
 
@@ -1538,16 +1526,18 @@
 	/* Check if it's a file that's currently being worked on.
 	 * If so, make that NULL so it gets canceled right away.
 	 */
-	if (directory->details->count_file == file) {
-		directory->details->count_file = NULL;
+	if (directory->details->count_in_progress != NULL &&
+	    directory->details->count_in_progress->count_file == file) {
+		directory->details->count_in_progress->count_file = NULL;
 		changed = TRUE;
 	}
 	if (directory->details->deep_count_file == file) {
 		directory->details->deep_count_file = NULL;
 		changed = TRUE;
 	}
-	if (directory->details->mime_list_file == file) {
-		directory->details->mime_list_file = NULL;
+	if (directory->details->mime_list_in_progress != NULL &&
+	    directory->details->mime_list_in_progress->mime_list_file == file) {
+		directory->details->mime_list_in_progress->mime_list_file = NULL;
 		changed = TRUE;
 	}
 	if (directory->details->get_info_file == file) {
@@ -2383,7 +2373,7 @@
 	NautilusFile *file;
 
 	if (directory->details->count_in_progress != NULL) {
-		file = directory->details->count_file;
+		file = directory->details->count_in_progress->count_file;
 		if (file != NULL) {
 			g_assert (NAUTILUS_IS_FILE (file));
 			g_assert (file->details->directory == directory);
@@ -2418,17 +2408,12 @@
 
 static void
 count_children_done (NautilusDirectory *directory,
+		     NautilusFile *count_file,
 		     gboolean succeeded,
 		     int count)
 {
-	NautilusFile *count_file;
-
-	count_file = directory->details->count_file;
-	
 	g_assert (NAUTILUS_IS_FILE (count_file));
 
-	nautilus_directory_ref (directory);
-
 	count_file->details->directory_count_is_up_to_date = TRUE;
 
 	/* Record either a failure or success. */
@@ -2441,7 +2426,6 @@
 		count_file->details->got_directory_count = TRUE;
 		count_file->details->directory_count = count;
 	}
-	directory->details->count_file = NULL;
 	directory->details->count_in_progress = NULL;
 
 	/* Send file-changed even if count failed, so interested parties can
@@ -2452,8 +2436,6 @@
 	/* Start up the next one. */
 	async_job_end (directory, "directory count");
 	nautilus_directory_async_state_changed (directory);
-
-	nautilus_directory_unref (directory);
 }
 
 static void
@@ -2467,6 +2449,7 @@
 		g_object_unref (state->enumerator);
 	}
 	g_object_unref (state->cancellable);
+	nautilus_directory_unref (state->directory);
 	g_free (state);
 }
 
@@ -2481,15 +2464,20 @@
 	GList *files;
 
 	state = user_data;
-
-	if (state->directory == NULL) {
+	directory = state->directory;
+	
+	if (g_cancellable_is_cancelled (state->cancellable)) {
 		/* Operation was cancelled. Bail out */
+		directory->details->count_in_progress = NULL;
+
+		async_job_end (directory, "directory count");
+		nautilus_directory_async_state_changed (directory);
+		
 		directory_count_state_free (state);
+
 		return;
 	}
 
-	directory = nautilus_directory_ref (state->directory);
-	
 	g_assert (directory->details->count_in_progress != NULL);
 	g_assert (directory->details->count_in_progress == state);
 
@@ -2500,7 +2488,8 @@
 	state->file_count += count_non_skipped_files (files);
 	
 	if (files == NULL) {
-		count_children_done (directory, TRUE, state->file_count);
+		count_children_done (directory, state->count_file,
+				     TRUE, state->file_count);
 		directory_count_state_free (state);
 	} else {
 		g_file_enumerator_next_files_async (state->enumerator,
@@ -2513,8 +2502,6 @@
 
 	eel_g_object_list_free (files);
 
-	nautilus_directory_unref (directory);
-	
 	if (error) {
 		g_error_free (error);
 	}
@@ -2527,13 +2514,21 @@
 {
 	DirectoryCountState *state;
 	GFileEnumerator *enumerator;
+	NautilusDirectory *directory;
 	GError *error;
 
 	state = user_data;
 
-	if (state->directory == NULL) {
+	if (g_cancellable_is_cancelled (state->cancellable)) {
 		/* Operation was cancelled. Bail out */
+		directory = state->directory;
+		directory->details->count_in_progress = NULL;
+
+		async_job_end (directory, "directory count");
+		nautilus_directory_async_state_changed (directory);
+		
 		directory_count_state_free (state);
+
 		return;
 	}
 	
@@ -2542,7 +2537,9 @@
 							res, &error);
 
 	if (enumerator == NULL) {
-		count_children_done (state->directory, FALSE, 0);
+		count_children_done (state->directory,
+				     state->count_file,
+				     FALSE, 0);
 		g_error_free (error);
 		directory_count_state_free (state);
 		return;
@@ -2591,10 +2588,9 @@
 	}
 
 	/* Start counting. */
-	directory->details->count_file = file;
-
 	state = g_new0 (DirectoryCountState, 1);
-	state->directory = directory;
+	state->count_file = file;
+	state->directory = nautilus_directory_ref (directory);
 	state->cancellable = g_cancellable_new ();
 	
 	directory->details->count_in_progress = state;
@@ -2603,7 +2599,7 @@
 	g_message ("load_directory called to get shallow file count for %s", uri);
 #endif
 	location = nautilus_file_get_location (file);
-	
+
 	g_file_enumerate_children_async (location,
 					 G_FILE_ATTRIBUTE_STANDARD_NAME ","
 					 G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN ","
@@ -2898,7 +2894,7 @@
 	NautilusFile *file;
 
 	if (directory->details->mime_list_in_progress != NULL) {
-		file = directory->details->mime_list_file;
+		file = directory->details->mime_list_in_progress->mime_list_file;
 		if (file != NULL) {
 			g_assert (NAUTILUS_IS_FILE (file));
 			g_assert (file->details->directory == directory);
@@ -2908,7 +2904,7 @@
 				return;
 			}
 		}
-
+		
 		/* The count is not wanted, so stop it. */
 		mime_list_cancel (directory);
 	}
@@ -2926,6 +2922,7 @@
 	}
 	g_object_unref (state->cancellable);
 	istr_set_destroy (state->mime_list_hash);
+	nautilus_directory_unref (state->directory);
 	g_free (state);
 }
 
@@ -2939,7 +2936,7 @@
 	directory = state->directory;
 	g_assert (directory != NULL);
 	
-	file = directory->details->mime_list_file;
+	file = state->mime_list_file;
 	
 	file->details->mime_list_is_up_to_date = TRUE;
 	eel_g_list_free_deep (file->details->mime_list);
@@ -2951,7 +2948,6 @@
 		file->details->mime_list = istr_set_get_as_list	(state->mime_list_hash);
 	}
 	directory->details->mime_list_in_progress = NULL;
-	directory->details->mime_list_file = NULL;
 
 	/* Send file-changed even if getting the item type list
 	 * failed, so interested parties can distinguish between
@@ -2962,7 +2958,6 @@
 	/* Start up the next one. */
 	async_job_end (directory, "MIME list");
 	nautilus_directory_async_state_changed (directory);
-	
 }
 
 static void
@@ -2994,15 +2989,20 @@
 	GFileInfo *info;
 
 	state = user_data;
+	directory = state->directory;
 
-	if (state->directory == NULL) {
+	if (g_cancellable_is_cancelled (state->cancellable)) {
 		/* Operation was cancelled. Bail out */
+		directory->details->mime_list_in_progress = NULL;
+
+		async_job_end (directory, "MIME list");
+		nautilus_directory_async_state_changed (directory);
+		
 		mime_list_state_free (state);
+
 		return;
 	}
 
-	directory = nautilus_directory_ref (state->directory);
-	
 	g_assert (directory->details->mime_list_in_progress != NULL);
 	g_assert (directory->details->mime_list_in_progress == state);
 
@@ -3029,8 +3029,6 @@
 	}
 
 	g_list_free (files);
-
-	nautilus_directory_unref (directory);
 	
 	if (error) {
 		g_error_free (error);
@@ -3044,13 +3042,21 @@
 {
 	MimeListState *state;
 	GFileEnumerator *enumerator;
+	NautilusDirectory *directory;
 	GError *error;
 
 	state = user_data;
 
-	if (state->directory == NULL) {
+	if (g_cancellable_is_cancelled (state->cancellable)) {
 		/* Operation was cancelled. Bail out */
+		directory = state->directory;
+		directory->details->mime_list_in_progress = NULL;
+
+		async_job_end (directory, "MIME list");
+		nautilus_directory_async_state_changed (directory);
+		
 		mime_list_state_free (state);
+
 		return;
 	}
 	
@@ -3113,11 +3119,11 @@
 
 
 	state = g_new0 (MimeListState, 1);
-	state->directory = directory;
+	state->mime_list_file = file;
+	state->directory = nautilus_directory_ref (directory);
 	state->cancellable = g_cancellable_new ();
 	state->mime_list_hash = istr_set_new ();
 
-	directory->details->mime_list_file = file;
 	directory->details->mime_list_in_progress = state;
 
 #ifdef DEBUG_LOAD_DIRECTORY		
@@ -4347,7 +4353,8 @@
 cancel_directory_count_for_file (NautilusDirectory *directory,
 				 NautilusFile      *file)
 {
-	if (directory->details->count_file == file) {
+	if (directory->details->count_in_progress != NULL &&
+	    directory->details->count_in_progress->count_file == file) {
 		directory_count_cancel (directory);
 	}
 }
@@ -4365,7 +4372,8 @@
 cancel_mime_list_for_file (NautilusDirectory *directory,
 			   NautilusFile      *file)
 {
-	if (directory->details->mime_list_file == file) {
+	if (directory->details->mime_list_in_progress != NULL &&
+	    directory->details->mime_list_in_progress->mime_list_file == file) {
 		mime_list_cancel (directory);
 	}
 }

Modified: trunk/libnautilus-private/nautilus-directory-private.h
==============================================================================
--- trunk/libnautilus-private/nautilus-directory-private.h	(original)
+++ trunk/libnautilus-private/nautilus-directory-private.h	Wed Feb  6 15:06:19 2008
@@ -88,13 +88,11 @@
 
 	GList *new_files_in_progress; /* list of NewFilesState * */
 
-	NautilusFile *count_file;
 	DirectoryCountState *count_in_progress;
 
 	NautilusFile *deep_count_file;
 	DeepCountState *deep_count_in_progress;
 
-	NautilusFile *mime_list_file;
 	MimeListState *mime_list_in_progress;
 
 	NautilusFile *get_info_file;



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