[nautilus] bookmark-list: make sure to avoid sync I/O while loading/saving



commit e098781b3ede80517ceea56daa7f5a8c1c95f2af
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Mon Apr 30 10:15:24 2012 -0400

    bookmark-list: make sure to avoid sync I/O while loading/saving
    
    Last patch introduces sync I/O in the load and save paths; avoid that by
    explicitly using separate threads for saving and loading, thanks to
    g_simple_async_result_run_in_thread().

 src/nautilus-bookmark-list.c |  243 ++++++++++++++++++++++--------------------
 1 files changed, 129 insertions(+), 114 deletions(-)
---
diff --git a/src/nautilus-bookmark-list.c b/src/nautilus-bookmark-list.c
index c66a417..07e5a0c 100644
--- a/src/nautilus-bookmark-list.c
+++ b/src/nautilus-bookmark-list.c
@@ -462,82 +462,142 @@ nautilus_bookmark_list_length (NautilusBookmarkList *bookmarks)
 }
 
 static void
-load_file_finish (NautilusBookmarkList *bookmarks,
-		  GObject *source,
-		  GAsyncResult *res)
+process_next_op (NautilusBookmarkList *bookmarks);
+
+static void
+op_processed_cb (NautilusBookmarkList *self)
 {
-	GError *error = NULL;
-	gchar *contents = NULL;
-
-	g_file_load_contents_finish (G_FILE (source),
-				     res, &contents, NULL, NULL, &error);
-
-	if (error == NULL) {
-        	char **lines;
-      		int i;
-
-		lines = g_strsplit (contents, "\n", -1);
-      	 	for (i = 0; lines[i]; i++) {
-			/* Ignore empty or invalid lines that cannot be parsed properly */
-	  		if (lines[i][0] != '\0' && lines[i][0] != ' ') {
-				/* gtk 2.7/2.8 might have labels appended to bookmarks which are separated by a space */
-				/* we must seperate the bookmark uri and the potential label */
- 				char *space, *label;
-
-				label = NULL;
-      				space = strchr (lines[i], ' ');
-      				if (space) {
-					*space = '\0';
-					label = g_strdup (space + 1);
-				}
-				insert_bookmark_internal (bookmarks, 
-						          new_bookmark_from_uri (lines[i], label), 
-						          -1);
-
-				g_free (label);
+	g_queue_pop_tail (self->pending_ops);
+
+	if (!g_queue_is_empty (self->pending_ops)) {
+		process_next_op (self);
+	}
+}
+
+static void
+load_callback (GObject *source,
+	       GAsyncResult *res,
+	       gpointer user_data)
+{
+	NautilusBookmarkList *self = NAUTILUS_BOOKMARK_LIST (source);
+	gchar *contents;
+	char **lines;
+	int i;
+
+	contents = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res));
+
+	if (contents == NULL) {
+		return;
+	}
+
+	lines = g_strsplit (contents, "\n", -1);
+	for (i = 0; lines[i]; i++) {
+		/* Ignore empty or invalid lines that cannot be parsed properly */
+		if (lines[i][0] != '\0' && lines[i][0] != ' ') {
+			/* gtk 2.7/2.8 might have labels appended to bookmarks which are separated by a space */
+			/* we must seperate the bookmark uri and the potential label */
+			char *space, *label;
+
+			label = NULL;
+			space = strchr (lines[i], ' ');
+			if (space) {
+				*space = '\0';
+				label = g_strdup (space + 1);
 			}
-		}
-      		g_free (contents);
-       		g_strfreev (lines);
 
-		g_signal_emit (bookmarks, signals[CHANGED], 0);
-	} else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
-		g_warning ("Could not load bookmark file: %s\n", error->message);
-		g_error_free (error);
+			insert_bookmark_internal (self, new_bookmark_from_uri (lines[i], label), -1);
+			g_free (label);
+		}
 	}
+
+	g_signal_emit (self, signals[CHANGED], 0);
+	op_processed_cb (self);
+
+	g_strfreev (lines);
 }
 
 static void
-load_file_async (NautilusBookmarkList *self,
-		 GAsyncReadyCallback callback)
+load_io_thread (GSimpleAsyncResult *result,
+		GObject *object,
+		GCancellable *cancellable)
 {
 	GFile *file;
+	gchar *contents;
+	GError *error = NULL;
 
 	file = nautilus_bookmark_list_get_file ();
 	if (!g_file_query_exists (file, NULL)) {
 		file = nautilus_bookmark_list_get_legacy_file ();
 	}
 
+	g_file_load_contents (file, NULL, &contents, NULL, NULL, &error);
+
+	if (error != NULL) {
+		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
+			g_warning ("Could not load bookmark file: %s\n", error->message);
+		}
+		g_error_free (error);
+	} else {
+		g_simple_async_result_set_op_res_gpointer (result, contents, g_free);
+	}
+}
+
+static void
+load_file_async (NautilusBookmarkList *self)
+{
+	GSimpleAsyncResult *result;
+
 	/* Wipe out old list. */
 	clear (self);
 
-	/* keep the bookmark list alive */
-	g_object_ref (self);
-	g_file_load_contents_async (file, NULL, callback, self);
+	result = g_simple_async_result_new (G_OBJECT (self), 
+					    load_callback, NULL, NULL);
+	g_simple_async_result_run_in_thread (result, load_io_thread,
+					     G_PRIORITY_DEFAULT, NULL);
+	g_object_unref (result);
+}
 
+static void
+save_callback (GObject *source,
+	       GAsyncResult *res,
+	       gpointer user_data)
+{
+	NautilusBookmarkList *self = NAUTILUS_BOOKMARK_LIST (source);
+	GFile *file;
+
+	/* re-enable bookmark file monitoring */
+	file = nautilus_bookmark_list_get_file ();
+	self->monitor = g_file_monitor_file (file, 0, NULL, NULL);
 	g_object_unref (file);
+
+	g_file_monitor_set_rate_limit (self->monitor, 1000);
+	g_signal_connect (self->monitor, "changed",
+			  G_CALLBACK (bookmark_monitor_changed_cb), self);
+
+	op_processed_cb (self);
 }
 
 static void
-save_file_finish (NautilusBookmarkList *bookmarks,
-		  GObject *source,
-		  GAsyncResult *res)
+save_io_thread (GSimpleAsyncResult *result,
+		GObject *object,
+		GCancellable *cancellable)
 {
+	gchar *contents, *path;
+	GFile *parent, *file;
 	GError *error = NULL;
-	GFile *file;
 
-	g_file_replace_contents_finish (G_FILE (source),
-					res, NULL, &error);
+	file = nautilus_bookmark_list_get_file ();
+	parent = g_file_get_parent (file);
+	path = g_file_get_path (parent);
+	g_mkdir_with_parents (path, 0700);
+	g_free (path);
+	g_object_unref (parent);
+
+	contents = g_simple_async_result_get_op_res_gpointer (result);
+	g_file_replace_contents (file, 
+				 contents, strlen (contents),
+				 NULL, FALSE, 0, NULL,
+				 NULL, &error);
 
 	if (error != NULL) {
 		g_warning ("Unable to replace contents of the bookmarks file: %s",
@@ -545,37 +605,26 @@ save_file_finish (NautilusBookmarkList *bookmarks,
 		g_error_free (error);
 	}
 
-	file = nautilus_bookmark_list_get_file ();
-
-	/* re-enable bookmark file monitoring */
-	bookmarks->monitor = g_file_monitor_file (file, 0, NULL, NULL);
-	g_file_monitor_set_rate_limit (bookmarks->monitor, 1000);
-	g_signal_connect (bookmarks->monitor, "changed",
-			  G_CALLBACK (bookmark_monitor_changed_cb), bookmarks);
-
 	g_object_unref (file);
 }
 
 static void
-save_file_async (NautilusBookmarkList *bookmarks,
-		 GAsyncReadyCallback callback)
+save_file_async (NautilusBookmarkList *self)
 {
-	GFile *file;
-	GList *l;
+	GSimpleAsyncResult *result;
 	GString *bookmark_string;
-	GFile *parent;
-	char *path;
+	gchar *contents;
+	GList *l;
+
+	bookmark_string = g_string_new (NULL);
 
 	/* temporarily disable bookmark file monitoring when writing file */
-	if (bookmarks->monitor != NULL) {
-		g_file_monitor_cancel (bookmarks->monitor);
-		bookmarks->monitor = NULL;
+	if (self->monitor != NULL) {
+		g_file_monitor_cancel (self->monitor);
+		self->monitor = NULL;
 	}
 
-	file = nautilus_bookmark_list_get_file ();
-	bookmark_string = g_string_new (NULL);
-
-	for (l = bookmarks->list; l; l = l->next) {
+	for (l = self->list; l; l = l->next) {
 		NautilusBookmark *bookmark;
 
 		bookmark = NAUTILUS_BOOKMARK (l->data);
@@ -597,48 +646,14 @@ save_file_async (NautilusBookmarkList *bookmarks,
 		}
 	}
 
-	/* keep the bookmark list alive */
-	g_object_ref (bookmarks);
-
-	parent = g_file_get_parent (file);
-	path = g_file_get_path (parent);
-	g_mkdir_with_parents (path, 0700);
-	g_free (path);
-	g_object_unref (parent);
-
-	g_file_replace_contents_async (file, bookmark_string->str,
-				       bookmark_string->len, NULL,
-				       FALSE, 0, NULL, callback,
-				       bookmarks);
-
-	g_object_unref (file);
-}
-
-static void
-process_next_op (NautilusBookmarkList *bookmarks);
-
-static void
-op_processed_cb (GObject *source,
-		 GAsyncResult *res,
-		 gpointer user_data)
-{
-	NautilusBookmarkList *self = user_data;
-	int op;
-
-	op = GPOINTER_TO_INT (g_queue_pop_tail (self->pending_ops));
-
-	if (op == LOAD_JOB) {
-		load_file_finish (self, source, res);
-	} else {
-		save_file_finish (self, source, res);
-	}
-
-	if (!g_queue_is_empty (self->pending_ops)) {
-		process_next_op (self);
-	}
+	result = g_simple_async_result_new (G_OBJECT (self),
+					    save_callback, NULL, NULL);
+	contents = g_string_free (bookmark_string, FALSE);
+	g_simple_async_result_set_op_res_gpointer (result, contents, g_free);
 
-	/* release the reference acquired during the _async method */
-	g_object_unref (self);
+	g_simple_async_result_run_in_thread (result, save_io_thread,
+					     G_PRIORITY_DEFAULT, NULL);
+	g_object_unref (result);
 }
 
 static void
@@ -649,9 +664,9 @@ process_next_op (NautilusBookmarkList *bookmarks)
 	op = GPOINTER_TO_INT (g_queue_peek_tail (bookmarks->pending_ops));
 
 	if (op == LOAD_JOB) {
-		load_file_async (bookmarks, op_processed_cb);
+		load_file_async (bookmarks);
 	} else {
-		save_file_async (bookmarks, op_processed_cb);
+		save_file_async (bookmarks);
 	}
 }
 



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