diff options
author | Michael Catanzaro <mcatanzaro@igalia.com> | 2019-06-20 17:17:05 -0500 |
---|---|---|
committer | Michael Catanzaro <mcatanzaro@igalia.com> | 2019-06-22 13:52:52 -0500 |
commit | cc32bc817bb6e57928a59d36b051e15be8b91bd0 (patch) | |
tree | e7ac41be05aa9ab9ea70d696bb07fc2e9e0957f1 /src/bookmarks | |
parent | c5ccd9f7ef801e2deff08bf5d8ec1996656f5e2e (diff) | |
download | epiphany-cc32bc817bb6e57928a59d36b051e15be8b91bd0.tar.gz |
Make ephy_bookmarks_manager_save_to_file_async() actually async
Currently it looks like an asynchronous function, but it actually does
sync I/O, which is bad.
This also requires also making ephy_bookmarks_export() async, which
required adding gvdb_table_write_contents_async(), which I upstreamed to
GVDB. (It was added to Epiphany in the previous commit.)
It also requires adding GCancellable parameters where required, to avoid
introducing new crashes. This means we need a way for external code to
access the EphyBookmarkManager's cancellable or we would need to get rid
of the warn_on_error convenience callback.
Also, remove ephy_bookmarks_manager_load_from_file(), since it's only
one line long and only used in one place.
Finally, rename the functions according to Carlos's feedback.
Fixes #336
Diffstat (limited to 'src/bookmarks')
-rw-r--r-- | src/bookmarks/ephy-add-bookmark-popover.c | 14 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmark-properties-grid.c | 7 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmarks-export.c | 54 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmarks-export.h | 11 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmarks-import.c | 7 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmarks-manager.c | 194 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmarks-manager.h | 66 |
7 files changed, 237 insertions, 116 deletions
diff --git a/src/bookmarks/ephy-add-bookmark-popover.c b/src/bookmarks/ephy-add-bookmark-popover.c index 0ba8159eb..bb331f039 100644 --- a/src/bookmarks/ephy-add-bookmark-popover.c +++ b/src/bookmarks/ephy-add-bookmark-popover.c @@ -123,9 +123,10 @@ ephy_add_bookmark_popover_closed_cb (GtkPopover *popover, self = EPHY_ADD_BOOKMARK_POPOVER (popover); manager = ephy_shell_get_bookmarks_manager (ephy_shell_get_default ()); - ephy_bookmarks_manager_save_to_file_async (manager, NULL, - ephy_bookmarks_manager_save_to_file_warn_on_error_cb, - NULL); + ephy_bookmarks_manager_save (manager, + ephy_bookmarks_manager_save_warn_on_error_cancellable (manager), + ephy_bookmarks_manager_save_warn_on_error_cb, + NULL); g_clear_pointer (&self->address, g_free); g_clear_pointer (&self->grid, gtk_widget_destroy); @@ -184,9 +185,10 @@ ephy_add_bookmark_popover_update_bookmarked_status_cb (EphyAddBookmarkPopover *s EPHY_LOCATION_ENTRY_BOOKMARK_ICON_EMPTY); } - ephy_bookmarks_manager_save_to_file_async (manager, NULL, - ephy_bookmarks_manager_save_to_file_warn_on_error_cb, - NULL); + ephy_bookmarks_manager_save (manager, + ephy_bookmarks_manager_save_warn_on_error_cancellable (manager), + ephy_bookmarks_manager_save_warn_on_error_cb, + NULL); gtk_widget_hide (GTK_WIDGET (self)); } diff --git a/src/bookmarks/ephy-bookmark-properties-grid.c b/src/bookmarks/ephy-bookmark-properties-grid.c index 63899ff05..9703f93b5 100644 --- a/src/bookmarks/ephy-bookmark-properties-grid.c +++ b/src/bookmarks/ephy-bookmark-properties-grid.c @@ -421,9 +421,10 @@ ephy_bookmark_properties_grid_finalize (GObject *object) if (self->bookmark_is_modified && !self->bookmark_is_removed) g_signal_emit_by_name (self->manager, "synchronizable-modified", self->bookmark, FALSE); - ephy_bookmarks_manager_save_to_file_async (self->manager, NULL, - ephy_bookmarks_manager_save_to_file_warn_on_error_cb, - NULL); + ephy_bookmarks_manager_save (self->manager, + ephy_bookmarks_manager_save_warn_on_error_cancellable (self->manager), + ephy_bookmarks_manager_save_warn_on_error_cb, + NULL); G_OBJECT_CLASS (ephy_bookmark_properties_grid_parent_class)->finalize (object); } diff --git a/src/bookmarks/ephy-bookmarks-export.c b/src/bookmarks/ephy-bookmarks-export.c index 47f55d785..6363473e0 100644 --- a/src/bookmarks/ephy-bookmarks-export.c +++ b/src/bookmarks/ephy-bookmarks-export.c @@ -63,7 +63,8 @@ build_variant (EphyBookmark *bookmark) } static void -add_bookmark_to_table (EphyBookmark *bookmark, GHashTable *table) +add_bookmark_to_table (EphyBookmark *bookmark, + GHashTable *table) { gvdb_hash_table_insert_variant (table, ephy_bookmark_get_url (bookmark), @@ -71,19 +72,41 @@ add_bookmark_to_table (EphyBookmark *bookmark, GHashTable *table) } static void -add_tag_to_table (const char *tag, GHashTable *table) +add_tag_to_table (const char *tag, + GHashTable *table) { gvdb_hash_table_insert (table, tag); } -gboolean -ephy_bookmarks_export (EphyBookmarksManager *manager, - const char *filename, - GError **error) +static void +write_contents_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + g_autoptr(GTask) task = user_data; + GHashTable *root_table; + GError *error = NULL; + + root_table = g_task_get_task_data (task); + + if (!gvdb_table_write_contents_finish (root_table, result, &error)) { + g_task_return_error (task, error); + return; + } + + g_task_return_boolean (task, TRUE); +} + +void +ephy_bookmarks_export (EphyBookmarksManager *manager, + const char *filename, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { GHashTable *root_table; GHashTable *table; - gboolean result; + GTask *task; root_table = gvdb_hash_table_new (NULL, NULL); @@ -95,8 +118,19 @@ ephy_bookmarks_export (EphyBookmarksManager *manager, g_sequence_foreach (ephy_bookmarks_manager_get_bookmarks (manager), (GFunc)add_bookmark_to_table, table); g_hash_table_unref (table); - result = gvdb_table_write_contents (root_table, filename, FALSE, error); - g_hash_table_unref (root_table); + task = g_task_new (manager, cancellable, callback, user_data); + g_task_set_task_data (task, root_table, (GDestroyNotify)g_hash_table_unref); + + gvdb_table_write_contents_async (root_table, filename, FALSE, + cancellable, write_contents_cb, task); +} + +gboolean +ephy_bookmarks_export_finish (EphyBookmarksManager *manager, + GAsyncResult *result, + GError **error) +{ + g_assert (g_task_is_valid (result, manager)); - return result; + return g_task_propagate_boolean (G_TASK (result), error); } diff --git a/src/bookmarks/ephy-bookmarks-export.h b/src/bookmarks/ephy-bookmarks-export.h index bd36b0e12..8bc087f48 100644 --- a/src/bookmarks/ephy-bookmarks-export.h +++ b/src/bookmarks/ephy-bookmarks-export.h @@ -24,8 +24,13 @@ G_BEGIN_DECLS -gboolean ephy_bookmarks_export (EphyBookmarksManager *manager, - const char *filename, - GError **error); +void ephy_bookmarks_export (EphyBookmarksManager *manager, + const char *filename, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean ephy_bookmarks_export_finish (EphyBookmarksManager *manager, + GAsyncResult *result, + GError **error); G_END_DECLS diff --git a/src/bookmarks/ephy-bookmarks-import.c b/src/bookmarks/ephy-bookmarks-import.c index cdc8dded5..048f45c7e 100644 --- a/src/bookmarks/ephy-bookmarks-import.c +++ b/src/bookmarks/ephy-bookmarks-import.c @@ -105,7 +105,12 @@ ephy_bookmarks_import (EphyBookmarksManager *manager, gsize length; guint i; - /* Create a new table to hold data stored in file. */ + /* Create a new table to hold data stored in file. + * + * FIXME: This uses mmap so it's doing sync I/O, which is not cool. It's + * not straightforward to fix, but it would be nice to have an async + * constructor in GVDB. Then we could make ephy_bookmarks_import() async. + */ root_table = gvdb_table_new (filename, TRUE, error); if (!root_table) { res = FALSE; diff --git a/src/bookmarks/ephy-bookmarks-manager.c b/src/bookmarks/ephy-bookmarks-manager.c index 4860997f2..f44a4a9c3 100644 --- a/src/bookmarks/ephy-bookmarks-manager.c +++ b/src/bookmarks/ephy-bookmarks-manager.c @@ -34,12 +34,14 @@ #define EPHY_BOOKMARKS_FILE "bookmarks.gvdb" struct _EphyBookmarksManager { - GObject parent_instance; + GObject parent_instance; - GSequence *bookmarks; - GSequence *tags; + GCancellable *cancellable; - gchar *gvdb_filename; + GSequence *bookmarks; + GSequence *tags; + + gchar *gvdb_filename; }; static void list_model_iface_init (GListModelInterface *iface); @@ -66,17 +68,6 @@ enum { static guint signals[LAST_SIGNAL]; static void -ephy_bookmarks_manager_save_to_file (EphyBookmarksManager *self, GTask *task) -{ - gboolean result; - - result = ephy_bookmarks_export (self, self->gvdb_filename, NULL); - - if (task) - g_task_return_boolean (task, result); -} - -static void ephy_bookmarks_manager_copy_tags_from_bookmark (EphyBookmarksManager *self, EphyBookmark *dest, EphyBookmark *source) @@ -107,6 +98,19 @@ ephy_bookmarks_manager_create_tags_from_bookmark (EphyBookmarksManager *self, } static void +ephy_bookmarks_manager_dispose (GObject *object) +{ + EphyBookmarksManager *self = EPHY_BOOKMARKS_MANAGER (object); + + if (self->cancellable) { + g_cancellable_cancel (self->cancellable); + g_clear_object (&self->cancellable); + } + + G_OBJECT_CLASS (ephy_bookmarks_manager_parent_class)->dispose (object); +} + +static void ephy_bookmarks_manager_finalize (GObject *object) { EphyBookmarksManager *self = EPHY_BOOKMARKS_MANAGER (object); @@ -124,6 +128,7 @@ ephy_bookmarks_manager_class_init (EphyBookmarksManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + object_class->dispose = ephy_bookmarks_manager_dispose; object_class->finalize = ephy_bookmarks_manager_finalize; signals[BOOKMARK_ADDED] = @@ -205,6 +210,10 @@ ephy_bookmarks_manager_class_init (EphyBookmarksManagerClass *klass) static void ephy_bookmarks_manager_init (EphyBookmarksManager *self) { + g_autoptr(GError) error = NULL; + + self->cancellable = g_cancellable_new (); + self->gvdb_filename = g_build_filename (ephy_profile_dir (), EPHY_BOOKMARKS_FILE, NULL); @@ -218,10 +227,12 @@ ephy_bookmarks_manager_init (EphyBookmarksManager *self) NULL); /* Create DB file if it doesn't already exists */ - if (!g_file_test (self->gvdb_filename, G_FILE_TEST_EXISTS)) - ephy_bookmarks_manager_save_to_file (self, NULL); + if (!g_file_test (self->gvdb_filename, G_FILE_TEST_EXISTS)) { + if (!ephy_bookmarks_manager_save_sync (self, &error)) + g_warning ("Failed to save bookmarks: %s", error->message); + } - ephy_bookmarks_manager_load_from_file (self); + ephy_bookmarks_import (self, self->gvdb_filename, NULL); } static void @@ -329,9 +340,9 @@ ephy_bookmarks_manager_add_bookmark_internal (EphyBookmarksManager *self, } if (should_save) - ephy_bookmarks_manager_save_to_file_async (self, NULL, - (GAsyncReadyCallback)ephy_bookmarks_manager_save_to_file_warn_on_error_cb, - NULL); + ephy_bookmarks_manager_save (self, self->cancellable, + (GAsyncReadyCallback)ephy_bookmarks_manager_save_warn_on_error_cb, + NULL); } void @@ -362,9 +373,9 @@ ephy_bookmarks_manager_add_bookmarks (EphyBookmarksManager *self, g_signal_emit_by_name (self, "synchronizable-modified", bookmark, FALSE); } - ephy_bookmarks_manager_save_to_file_async (self, NULL, - (GAsyncReadyCallback)ephy_bookmarks_manager_save_to_file_warn_on_error_cb, - NULL); + ephy_bookmarks_manager_save (self, self->cancellable, + (GAsyncReadyCallback)ephy_bookmarks_manager_save_warn_on_error_cb, + NULL); } static void @@ -396,9 +407,9 @@ ephy_bookmarks_manager_remove_bookmark_internal (EphyBookmarksManager *self, g_list_model_items_changed (G_LIST_MODEL (self), position, 1, 0); g_signal_emit (self, signals[BOOKMARK_REMOVED], 0, bookmark); - ephy_bookmarks_manager_save_to_file_async (self, NULL, - (GAsyncReadyCallback)ephy_bookmarks_manager_save_to_file_warn_on_error_cb, - NULL); + ephy_bookmarks_manager_save (self, self->cancellable, + (GAsyncReadyCallback)ephy_bookmarks_manager_save_warn_on_error_cb, + NULL); ephy_bookmarks_manager_unwatch_bookmark (self, bookmark); g_object_unref (bookmark); @@ -580,50 +591,111 @@ ephy_bookmarks_manager_get_tags (EphyBookmarksManager *self) } void -ephy_bookmarks_manager_save_to_file_async (EphyBookmarksManager *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +ephy_bookmarks_manager_save_warn_on_error_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + EphyBookmarksManager *self = EPHY_BOOKMARKS_MANAGER (object); + gboolean ret; + g_autoptr(GError) error = NULL; + + ret = ephy_bookmarks_manager_save_finish (self, result, &error); + if (ret == FALSE) + g_warning ("%s", error->message); +} + +GCancellable * +ephy_bookmarks_manager_save_warn_on_error_cancellable (EphyBookmarksManager *self) +{ + g_assert (EPHY_IS_BOOKMARKS_MANAGER (self)); + + return self->cancellable; +} + +static void +bookmarks_export_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + EphyBookmarksManager *self = EPHY_BOOKMARKS_MANAGER (source_object); + g_autoptr(GTask) task = user_data; + GError *error; + + if (!ephy_bookmarks_export_finish (self, result, &error)) { + g_task_return_error (task, error); + return; + } + + g_task_return_boolean (task, TRUE); +} + +void +ephy_bookmarks_manager_save (EphyBookmarksManager *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { GTask *task; task = g_task_new (self, cancellable, callback, user_data); - ephy_bookmarks_manager_save_to_file (self, task); - - g_object_unref (task); + ephy_bookmarks_export (self, self->gvdb_filename, + cancellable, bookmarks_export_cb, task); } gboolean -ephy_bookmarks_manager_save_to_file_finish (EphyBookmarksManager *self, - GAsyncResult *result, - GError **error) +ephy_bookmarks_manager_save_finish (EphyBookmarksManager *self, + GAsyncResult *result, + GError **error) { g_assert (g_task_is_valid (result, self)); return g_task_propagate_boolean (G_TASK (result), error); } -void -ephy_bookmarks_manager_load_from_file (EphyBookmarksManager *self) +typedef struct { + GMainLoop *main_loop; + gboolean result; + GError *error; +} SaveToFileData; + +static void +save_to_file_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - ephy_bookmarks_import (self, self->gvdb_filename, NULL); + EphyBookmarksManager *self = EPHY_BOOKMARKS_MANAGER (source_object); + SaveToFileData *data = user_data; + + data->result = ephy_bookmarks_manager_save_finish (self, result, &data->error); + + g_main_loop_quit (data->main_loop); } -void -ephy_bookmarks_manager_save_to_file_warn_on_error_cb (GObject *object, - GAsyncResult *result, - gpointer user_data) +gboolean +ephy_bookmarks_manager_save_sync (EphyBookmarksManager *self, + GError **error) { - EphyBookmarksManager *self = EPHY_BOOKMARKS_MANAGER (object); - gboolean ret; - GError *error; + g_autoptr(GMainContext) context = NULL; + SaveToFileData *data; + gboolean result; - ret = ephy_bookmarks_manager_save_to_file_finish (self, result, &error); - if (ret == FALSE) { - g_warning ("%s", error->message); - g_error_free (error); - } + context = g_main_context_new (); + data = g_new (SaveToFileData, 1); + data->main_loop = g_main_loop_new (context, FALSE); + + g_main_context_push_thread_default (context); + ephy_bookmarks_manager_save (self, NULL, save_to_file_cb, data); + g_main_loop_run (data->main_loop); + g_main_context_pop_thread_default (context); + + result = data->result; + g_propagate_error (error, data->error); + + g_main_loop_unref (data->main_loop); + g_free (data); + + return result; } static GType @@ -725,9 +797,9 @@ synchronizable_manager_save (EphySynchronizableManager *manager, { EphyBookmarksManager *self = EPHY_BOOKMARKS_MANAGER (manager); - ephy_bookmarks_manager_save_to_file_async (self, NULL, - (GAsyncReadyCallback)ephy_bookmarks_manager_save_to_file_warn_on_error_cb, - NULL); + ephy_bookmarks_manager_save (self, self->cancellable, + (GAsyncReadyCallback)ephy_bookmarks_manager_save_warn_on_error_cb, + NULL); } static GPtrArray * @@ -815,9 +887,9 @@ next: } /* Commit changes to file. */ - ephy_bookmarks_manager_save_to_file_async (self, NULL, - (GAsyncReadyCallback)ephy_bookmarks_manager_save_to_file_warn_on_error_cb, - NULL); + ephy_bookmarks_manager_save (self, self->cancellable, + (GAsyncReadyCallback)ephy_bookmarks_manager_save_warn_on_error_cb, + NULL); g_hash_table_unref (dont_upload); return to_upload; @@ -893,9 +965,9 @@ next: } /* Commit changes to file. */ - ephy_bookmarks_manager_save_to_file_async (self, NULL, - (GAsyncReadyCallback)ephy_bookmarks_manager_save_to_file_warn_on_error_cb, - NULL); + ephy_bookmarks_manager_save (self, self->cancellable, + (GAsyncReadyCallback)ephy_bookmarks_manager_save_warn_on_error_cb, + NULL); return to_upload; } diff --git a/src/bookmarks/ephy-bookmarks-manager.h b/src/bookmarks/ephy-bookmarks-manager.h index 797187335..fa70e8094 100644 --- a/src/bookmarks/ephy-bookmarks-manager.h +++ b/src/bookmarks/ephy-bookmarks-manager.h @@ -35,42 +35,44 @@ G_DECLARE_FINAL_TYPE (EphyBookmarksManager, ephy_bookmarks_manager, EPHY, BOOKMA #define EPHY_BOOKMARKS_MOBILE_TAG N_("Mobile") #define FIREFOX_BOOKMARKS_MOBILE_FOLDER "Mobile Bookmarks" -EphyBookmarksManager *ephy_bookmarks_manager_new (void); +EphyBookmarksManager *ephy_bookmarks_manager_new (void); -void ephy_bookmarks_manager_add_bookmark (EphyBookmarksManager *self, - EphyBookmark *bookmark); -void ephy_bookmarks_manager_add_bookmarks (EphyBookmarksManager *self, - GSequence *bookmarks); -void ephy_bookmarks_manager_remove_bookmark (EphyBookmarksManager *self, - EphyBookmark *bookmark); -EphyBookmark *ephy_bookmarks_manager_get_bookmark_by_url (EphyBookmarksManager *self, - const char *url); -EphyBookmark *ephy_bookmarks_manager_get_bookmark_by_id (EphyBookmarksManager *self, - const char *id); +void ephy_bookmarks_manager_add_bookmark (EphyBookmarksManager *self, + EphyBookmark *bookmark); +void ephy_bookmarks_manager_add_bookmarks (EphyBookmarksManager *self, + GSequence *bookmarks); +void ephy_bookmarks_manager_remove_bookmark (EphyBookmarksManager *self, + EphyBookmark *bookmark); +EphyBookmark *ephy_bookmarks_manager_get_bookmark_by_url (EphyBookmarksManager *self, + const char *url); +EphyBookmark *ephy_bookmarks_manager_get_bookmark_by_id (EphyBookmarksManager *self, + const char *id); -void ephy_bookmarks_manager_create_tag (EphyBookmarksManager *self, - const char *tag); -void ephy_bookmarks_manager_delete_tag (EphyBookmarksManager *self, - const char *tag); -gboolean ephy_bookmarks_manager_tag_exists (EphyBookmarksManager *self, - const char *tag); +void ephy_bookmarks_manager_create_tag (EphyBookmarksManager *self, + const char *tag); +void ephy_bookmarks_manager_delete_tag (EphyBookmarksManager *self, + const char *tag); +gboolean ephy_bookmarks_manager_tag_exists (EphyBookmarksManager *self, + const char *tag); -GSequence *ephy_bookmarks_manager_get_bookmarks (EphyBookmarksManager *self); -GSequence *ephy_bookmarks_manager_get_bookmarks_with_tag (EphyBookmarksManager *self, - const char *tag); -GSequence *ephy_bookmarks_manager_get_tags (EphyBookmarksManager *self); +GSequence *ephy_bookmarks_manager_get_bookmarks (EphyBookmarksManager *self); +GSequence *ephy_bookmarks_manager_get_bookmarks_with_tag (EphyBookmarksManager *self, + const char *tag); +GSequence *ephy_bookmarks_manager_get_tags (EphyBookmarksManager *self); -void ephy_bookmarks_manager_save_to_file_async (EphyBookmarksManager *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean ephy_bookmarks_manager_save_to_file_finish (EphyBookmarksManager *self, - GAsyncResult *result, - GError **error); -void ephy_bookmarks_manager_load_from_file (EphyBookmarksManager *self); +gboolean ephy_bookmarks_manager_save_sync (EphyBookmarksManager *self, + GError **error); +void ephy_bookmarks_manager_save (EphyBookmarksManager *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean ephy_bookmarks_manager_save_finish (EphyBookmarksManager *self, + GAsyncResult *result, + GError **error); -void ephy_bookmarks_manager_save_to_file_warn_on_error_cb (GObject *object, - GAsyncResult *result, - gpointer user_data); +void ephy_bookmarks_manager_save_warn_on_error_cb (GObject *object, + GAsyncResult *result, + gpointer user_data); +GCancellable *ephy_bookmarks_manager_save_warn_on_error_cancellable (EphyBookmarksManager *self); G_END_DECLS |