[evolution-data-server] google: Fix cancellation and progress reporting for cold-cache queries
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] google: Fix cancellation and progress reporting for cold-cache queries
- Date: Wed, 17 Aug 2011 16:40:40 +0000 (UTC)
commit f03645977340f1377264d1e9df8a651e0b9157ef
Author: Philip Withnall <philip tecnocode co uk>
Date: Wed Aug 17 00:41:10 2011 +0100
google: Fix cancellation and progress reporting for cold-cache queries
See: https://bugzilla.gnome.org/show_bug.cgi?id=619135#c3
Closes: bgo#619135
.../backends/google/e-book-backend-google.c | 111 ++++++++++++++++++--
1 files changed, 100 insertions(+), 11 deletions(-)
---
diff --git a/addressbook/backends/google/e-book-backend-google.c b/addressbook/backends/google/e-book-backend-google.c
index 923ddff..e6eea16 100644
--- a/addressbook/backends/google/e-book-backend-google.c
+++ b/addressbook/backends/google/e-book-backend-google.c
@@ -552,10 +552,60 @@ process_contact_finish (EBookBackend *backend, GDataEntry *entry)
g_object_unref (new_contact);
}
+typedef struct {
+ EBookBackend *backend;
+ GCancellable *cancellable;
+ GError *gdata_error;
+
+ /* These two don't need locking; they're only accessed from the main thread. */
+ gboolean update_complete;
+ guint num_contacts_pending_photos;
+} GetContactsData;
+
+static void
+check_get_new_contacts_finished (GetContactsData *data)
+{
+ __debug__ (G_STRFUNC);
+
+ /* Are we finished yet? */
+ if (data->update_complete == FALSE || data->num_contacts_pending_photos > 0) {
+ __debug__ ("Bailing from check_get_new_contacts_finished(): update_complete: %u, num_contacts_pending_photos: %u, data: %p",
+ data->update_complete, data->num_contacts_pending_photos, data);
+ return;
+ }
+
+ __debug__ ("Proceeding with check_get_new_contacts_finished() for data: %p.", data);
+
+ finish_operation (data->backend, 0);
+ on_sequence_complete (data->backend, data->gdata_error);
+
+ /* Tidy up */
+ g_object_unref (data->cancellable);
+ g_object_unref (data->backend);
+
+ g_slice_free (GetContactsData, data);
+}
+
#ifdef HAVE_LIBGDATA_0_9
+typedef struct {
+ GetContactsData *parent_data;
+
+ GCancellable *cancellable;
+ gulong cancelled_handle;
+} PhotoData;
+
+static void
+process_contact_photo_cancelled_cb (GCancellable *parent_cancellable, GCancellable *photo_cancellable)
+{
+ __debug__ (G_STRFUNC);
+
+ g_cancellable_cancel (photo_cancellable);
+}
+
static void
-process_contact_photo_cb (GDataContactsContact *gdata_contact, GAsyncResult *async_result, EBookBackend *backend)
+process_contact_photo_cb (GDataContactsContact *gdata_contact, GAsyncResult *async_result, PhotoData *data)
{
+ EBookBackend *backend = data->parent_data->backend;
guint8 *photo_data = NULL;
gsize photo_length;
gchar *photo_content_type = NULL;
@@ -590,12 +640,22 @@ process_contact_photo_cb (GDataContactsContact *gdata_contact, GAsyncResult *asy
g_free (photo_data);
g_free (photo_content_type);
+
+ /* Disconnect from the cancellable. */
+ g_cancellable_disconnect (data->parent_data->cancellable, data->cancelled_handle);
+ g_object_unref (data->cancellable);
+
+ data->parent_data->num_contacts_pending_photos--;
+ check_get_new_contacts_finished (data->parent_data);
+
+ g_slice_free (PhotoData, data);
}
#endif /* HAVE_LIBGDATA_0_9 */
static void
-process_contact_cb (GDataEntry *entry, guint entry_key, guint entry_count, EBookBackend *backend)
+process_contact_cb (GDataEntry *entry, guint entry_key, guint entry_count, GetContactsData *data)
{
+ EBookBackend *backend = data->backend;
gboolean is_deleted, is_cached;
const gchar *uid;
@@ -643,10 +703,28 @@ process_contact_cb (GDataEntry *entry, guint entry_key, guint entry_count, EBook
if ((old_photo_etag == NULL && new_photo_etag != NULL) ||
(old_photo_etag != NULL && new_photo_etag != NULL && strcmp (old_photo_etag, new_photo_etag) != 0)) {
+ GCancellable *cancellable;
+ PhotoData *photo_data;
+
+ photo_data = g_slice_new (PhotoData);
+ photo_data->parent_data = data;
+
+ /* Increment the count of contacts whose photos we're waiting for. */
+ data->num_contacts_pending_photos++;
+
+ /* Cancel downloading if the get_new_contacts() operation is cancelled. */
+ cancellable = g_cancellable_new ();
+
+ photo_data->cancellable = g_object_ref (cancellable);
+ photo_data->cancelled_handle = g_cancellable_connect (data->cancellable, (GCallback) process_contact_photo_cancelled_cb,
+ g_object_ref (cancellable), (GDestroyNotify) g_object_unref);
+
/* Download the photo. */
gdata_contacts_contact_get_photo_async (GDATA_CONTACTS_CONTACT (entry),
- GDATA_CONTACTS_SERVICE (E_BOOK_BACKEND_GOOGLE (backend)->priv->service), NULL,
- (GAsyncReadyCallback) process_contact_photo_cb, backend);
+ GDATA_CONTACTS_SERVICE (E_BOOK_BACKEND_GOOGLE (backend)->priv->service), cancellable,
+ (GAsyncReadyCallback) process_contact_photo_cb, photo_data);
+
+ g_object_unref (cancellable);
g_free (old_photo_etag);
return;
@@ -661,8 +739,9 @@ process_contact_cb (GDataEntry *entry, guint entry_key, guint entry_count, EBook
}
static void
-get_new_contacts_cb (GDataService *service, GAsyncResult *result, EBookBackend *backend)
+get_new_contacts_cb (GDataService *service, GAsyncResult *result, GetContactsData *data)
{
+ EBookBackend *backend = data->backend;
GDataFeed *feed;
GError *gdata_error = NULL;
@@ -683,13 +762,14 @@ get_new_contacts_cb (GDataService *service, GAsyncResult *result, EBookBackend *
cache_set_last_update (backend, ¤t_time);
}
- finish_operation (backend, 0);
- on_sequence_complete (backend, gdata_error);
-
/* Thaw the cache again */
cache_thaw (backend);
- g_clear_error (&gdata_error);
+ /* Note: The operation's only marked as finished when all the
+ * process_contact_photo_cb() callbacks have been called as well. */
+ data->update_complete = TRUE;
+ data->gdata_error = gdata_error;
+ check_get_new_contacts_finished (data);
}
static void
@@ -700,6 +780,7 @@ get_new_contacts (EBookBackend *backend)
GTimeVal updated;
GDataQuery *query;
GCancellable *cancellable;
+ GetContactsData *data;
__debug__ (G_STRFUNC);
g_return_if_fail (backend_is_authorized (backend));
@@ -721,17 +802,25 @@ get_new_contacts (EBookBackend *backend)
/* Query for new contacts asynchronously */
cancellable = start_operation (backend, 0, NULL, _("Querying for updated contactsâ"));
+
+ data = g_slice_new (GetContactsData);
+ data->backend = g_object_ref (backend);
+ data->cancellable = g_object_ref (cancellable);
+ data->gdata_error = NULL;
+ data->num_contacts_pending_photos = 0;
+ data->update_complete = FALSE;
+
gdata_contacts_service_query_contacts_async (
GDATA_CONTACTS_SERVICE (priv->service),
query,
cancellable,
(GDataQueryProgressCallback) process_contact_cb,
- backend,
+ data,
#ifdef HAVE_LIBGDATA_0_9
(GDestroyNotify) NULL,
#endif
(GAsyncReadyCallback) get_new_contacts_cb,
- backend);
+ data);
g_object_unref (cancellable);
g_object_unref (query);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]