[evolution-data-server] Bug 692361 - e_cal_client_get_free_busy() broken
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Bug 692361 - e_cal_client_get_free_busy() broken
- Date: Wed, 15 Jul 2015 10:38:01 +0000 (UTC)
commit 7ac978817654842ab6fea7d519ea92759cbcbbcc
Author: Milan Crha <mcrha redhat com>
Date: Wed Jul 15 12:37:25 2015 +0200
Bug 692361 - e_cal_client_get_free_busy() broken
calendar/backends/gtasks/e-cal-backend-gtasks.c | 2 +-
calendar/libecal/e-cal-client.c | 48 ++++++++++++++++++--
calendar/libecal/e-cal-client.h | 2 +
calendar/libecal/e-cal.c | 18 ++++---
calendar/libedata-cal/e-cal-backend-sync.c | 2 +-
calendar/libedata-cal/e-cal-backend.c | 43 ++++++++++++++---
calendar/libedata-cal/e-cal-backend.h | 2 +
calendar/libedata-cal/e-data-cal.c | 42 +++++++++++++++---
calendar/libedata-cal/e-data-cal.h | 3 +-
configure.ac | 4 +-
.../org.gnome.evolution.dataserver.Calendar.xml | 1 +
tests/libecal/client/Makefile.am | 6 ---
.../libecal/client/test-cal-client-get-free-busy.c | 19 ++++----
13 files changed, 146 insertions(+), 46 deletions(-)
---
diff --git a/calendar/backends/gtasks/e-cal-backend-gtasks.c b/calendar/backends/gtasks/e-cal-backend-gtasks.c
index 0735967..912d122 100644
--- a/calendar/backends/gtasks/e-cal-backend-gtasks.c
+++ b/calendar/backends/gtasks/e-cal-backend-gtasks.c
@@ -908,7 +908,7 @@ ecb_gtasks_get_free_busy (ECalBackend *backend,
g_return_if_fail (E_IS_CAL_BACKEND_GTASKS (backend));
g_return_if_fail (E_IS_DATA_CAL (cal));
- e_data_cal_respond_get_free_busy (cal, opid, EDC_ERROR (NotSupported));
+ e_data_cal_respond_get_free_busy (cal, opid, EDC_ERROR (NotSupported), NULL);
}
static void
diff --git a/calendar/libecal/e-cal-client.c b/calendar/libecal/e-cal-client.c
index 78731f6..f3d06e2 100644
--- a/calendar/libecal/e-cal-client.c
+++ b/calendar/libecal/e-cal-client.c
@@ -4533,6 +4533,7 @@ cal_client_get_free_busy_thread (GSimpleAsyncResult *simple,
async_context->start,
async_context->end,
async_context->string_list,
+ &async_context->object_list,
cancellable, &local_error)) {
if (!local_error)
@@ -4606,10 +4607,13 @@ e_cal_client_get_free_busy (ECalClient *client,
* e_cal_client_get_free_busy_finish:
* @client: an #ECalClient
* @result: a #GAsyncResult
+ * @out_freebusy: (element-type ECalComponent): a #GSList of #ECalComponent-s with overall returned
Free/Busy data
* @error: (out): a #GError to set an error, if any
*
* Finishes previous call of e_cal_client_get_free_busy().
- * All VFREEBUSY #ECalComponent-s were received by "free-busy-data" signal.
+ * The @out_freebusy contains all VFREEBUSY #ECalComponent-s, which could be also
+ * received by "free-busy-data" signal. The client is responsible to do a merge of
+ * the components between this complete list and those received through the signal.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
@@ -4618,6 +4622,7 @@ e_cal_client_get_free_busy (ECalClient *client,
gboolean
e_cal_client_get_free_busy_finish (ECalClient *client,
GAsyncResult *result,
+ GSList **out_freebusy,
GError **error)
{
GSimpleAsyncResult *simple;
@@ -4630,7 +4635,19 @@ e_cal_client_get_free_busy_finish (ECalClient *client,
simple = G_SIMPLE_ASYNC_RESULT (result);
/* Assume success unless a GError is set. */
- return !g_simple_async_result_propagate_error (simple, error);
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ if (out_freebusy != NULL) {
+ AsyncContext *async_context;
+
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ *out_freebusy = async_context->object_list;
+ async_context->object_list = NULL;
+ }
+
+ return TRUE;
}
/**
@@ -4639,11 +4656,14 @@ e_cal_client_get_free_busy_finish (ECalClient *client,
* @start: Start time for query
* @end: End time for query
* @users: (element-type utf8): List of users to retrieve free/busy information for
+ * @out_freebusy: (element-type ECalComponent): a #GSList of #ECalComponent-s with overall returned
Free/Busy data
* @cancellable: (allow-none): a #GCancellable; can be %NULL
* @error: (out): a #GError to set an error, if any
*
* Gets free/busy information from the calendar server.
- * All VFREEBUSY #ECalComponent-s were received by "free-busy-data" signal.
+ * The @out_freebusy contains all VFREEBUSY #ECalComponent-s, which could be also
+ * received by "free-busy-data" signal. The client is responsible to do a merge of
+ * the components between this complete list and those received through the signal.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*
@@ -4654,10 +4674,11 @@ e_cal_client_get_free_busy_sync (ECalClient *client,
time_t start,
time_t end,
const GSList *users,
+ GSList **out_freebusy,
GCancellable *cancellable,
GError **error)
{
- gchar **strv;
+ gchar **strv, **freebusy_strv = NULL;
gint ii = 0;
GError *local_error = NULL;
@@ -4675,6 +4696,7 @@ e_cal_client_get_free_busy_sync (ECalClient *client,
client->priv->dbus_proxy,
(gint64) start, (gint64) end,
(const gchar * const *) strv,
+ &freebusy_strv,
cancellable, &local_error);
g_strfreev (strv);
@@ -4685,6 +4707,24 @@ e_cal_client_get_free_busy_sync (ECalClient *client,
return FALSE;
}
+ if (out_freebusy) {
+ *out_freebusy = NULL;
+
+ for (ii = 0; freebusy_strv && freebusy_strv[ii] != NULL; ii++) {
+ ECalComponent *comp;
+
+ comp = e_cal_component_new_from_string (freebusy_strv[ii]);
+ if (!comp)
+ continue;
+
+ *out_freebusy = g_slist_prepend (*out_freebusy, comp);
+ }
+
+ *out_freebusy = g_slist_reverse (*out_freebusy);
+ }
+
+ g_strfreev (freebusy_strv);
+
return TRUE;
}
diff --git a/calendar/libecal/e-cal-client.h b/calendar/libecal/e-cal-client.h
index 17124a1..172861b 100644
--- a/calendar/libecal/e-cal-client.h
+++ b/calendar/libecal/e-cal-client.h
@@ -308,11 +308,13 @@ void e_cal_client_get_free_busy (ECalClient *client,
gboolean e_cal_client_get_free_busy_finish
(ECalClient *client,
GAsyncResult *result,
+ GSList **out_freebusy,
GError **error);
gboolean e_cal_client_get_free_busy_sync (ECalClient *client,
time_t start,
time_t end,
const GSList *users,
+ GSList **out_freebusy,
GCancellable *cancellable,
GError **error);
void e_cal_client_create_object (ECalClient *client,
diff --git a/calendar/libecal/e-cal.c b/calendar/libecal/e-cal.c
index db05e2c..da0df1b 100644
--- a/calendar/libecal/e-cal.c
+++ b/calendar/libecal/e-cal.c
@@ -1588,7 +1588,7 @@ e_cal_get_free_busy (ECal *ecal,
GList **freebusy,
GError **error)
{
- GSList *slist = NULL;
+ GSList *slist = NULL, *out_freebusy = NULL, *link;
gboolean success;
g_return_val_if_fail (E_IS_CAL (ecal), FALSE);
@@ -1601,17 +1601,19 @@ e_cal_get_free_busy (ECal *ecal,
for (; users != NULL; users = g_list_next (users))
slist = g_slist_prepend (slist, users->data);
- /* FIXME ECalClient's API for this is a giant W.T.F.
- * There's no way to populate the freebusy list
- * in a way that will avoid deadlocking for all
- * cases. I guess leave the list empty and hope
- * no one notices until ECalClient grows a saner
- * free/busy API. */
success = e_cal_client_get_free_busy_sync (
- ecal->priv->client, start, end, slist, NULL, error);
+ ecal->priv->client, start, end, slist, &out_freebusy, NULL, error);
g_slist_free (slist);
+ if (success) {
+ for (link = out_freebusy; link; link = g_slist_next (link)) {
+ *freebusy = g_list_prepend (*freebusy, g_object_ref (link->data));
+ }
+ }
+
+ g_slist_free_full (out_freebusy, g_object_unref);
+
return success;
}
diff --git a/calendar/libedata-cal/e-cal-backend-sync.c b/calendar/libedata-cal/e-cal-backend-sync.c
index d415b8c..76d0e09 100644
--- a/calendar/libedata-cal/e-cal-backend-sync.c
+++ b/calendar/libedata-cal/e-cal-backend-sync.c
@@ -687,7 +687,7 @@ cal_backend_get_free_busy (ECalBackend *backend,
if (freebusyobjs)
e_data_cal_report_free_busy_data (cal, freebusyobjs);
- e_data_cal_respond_get_free_busy (cal, opid, error);
+ e_data_cal_respond_get_free_busy (cal, opid, error, freebusyobjs);
g_slist_foreach (freebusyobjs, (GFunc) g_free, NULL);
g_slist_free (freebusyobjs);
diff --git a/calendar/libedata-cal/e-cal-backend.c b/calendar/libedata-cal/e-cal-backend.c
index 6179986..68febe7 100644
--- a/calendar/libedata-cal/e-cal-backend.c
+++ b/calendar/libedata-cal/e-cal-backend.c
@@ -2197,13 +2197,17 @@ e_cal_backend_get_object_list_finish (ECalBackend *backend,
* @start: start time
* @end: end time
* @users: a %NULL-terminated array of user strings
+ * @out_freebusy: iCalendar strings with overall returned Free/Busy data
* @cancellable: optional #GCancellable object, or %NULL
* @error: return location for a #GError, or %NULL
*
* Obtains a free/busy object for the list of @users in the time interval
- * between @start and @end. The free/busy results are returned through the
- * e_data_cal_report_free_busy_data() function rather than directly through
- * this function.
+ * between @start and @end.
+ *
+ * The free/busy results can be returned through the
+ * e_data_cal_report_free_busy_data() function asynchronously. The out_freebusy
+ * will contain all the returned data, possibly again, thus the client is
+ * responsible for the data merge, if needed.
*
* If an error occurs, the function will set @error and return %FALSE.
*
@@ -2216,6 +2220,7 @@ e_cal_backend_get_free_busy_sync (ECalBackend *backend,
time_t start,
time_t end,
const gchar * const *users,
+ GSList **out_freebusy,
GCancellable *cancellable,
GError **error)
{
@@ -2235,7 +2240,7 @@ e_cal_backend_get_free_busy_sync (ECalBackend *backend,
result = e_async_closure_wait (closure);
success = e_cal_backend_get_free_busy_finish (
- backend, result, error);
+ backend, result, out_freebusy, error);
e_async_closure_free (closure);
@@ -2353,13 +2358,15 @@ e_cal_backend_get_free_busy (ECalBackend *backend,
* e_cal_backend_get_free_busy_finish:
* @backend: an #ECalBackend
* @result: a #GAsyncResult
+ * @out_freebusy: iCalendar strings with overall returned Free/Busy data
* @error: return location for a #GError, or %NULL
*
* Finishes the operation started with e_cal_backend_get_free_busy().
*
- * The free/busy results are returned through the
- * e_data_cal_report_free_busy_data() function rather than directly through
- * this function.
+ * The free/busy results can be returned through the
+ * e_data_cal_report_free_busy_data() function asynchronously. The out_freebusy
+ * will contain all the returned data, possibly again, thus the client is
+ * responsible for the data merge, if needed.
*
* If an error occurred, the function will set @error and return %FALSE.
*
@@ -2370,9 +2377,12 @@ e_cal_backend_get_free_busy (ECalBackend *backend,
gboolean
e_cal_backend_get_free_busy_finish (ECalBackend *backend,
GAsyncResult *result,
+ GSList **out_freebusy,
GError **error)
{
GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+ GSList *ical_strings = NULL;
g_return_val_if_fail (
g_simple_async_result_is_valid (
@@ -2380,11 +2390,28 @@ e_cal_backend_get_free_busy_finish (ECalBackend *backend,
e_cal_backend_get_free_busy), FALSE);
simple = G_SIMPLE_ASYNC_RESULT (result);
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
cal_backend_unblock_operations (backend, simple);
/* Assume success unless a GError is set. */
- return !g_simple_async_result_propagate_error (simple, error);
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ while (!g_queue_is_empty (&async_context->result_queue)) {
+ gchar *ical_freebusy;
+
+ ical_freebusy = g_queue_pop_head (&async_context->result_queue);
+ if (out_freebusy)
+ ical_strings = g_slist_prepend (ical_strings, ical_freebusy);
+ else
+ g_free (ical_freebusy);
+ }
+
+ if (out_freebusy)
+ *out_freebusy = g_slist_reverse (ical_strings);
+
+ return TRUE;
}
/**
diff --git a/calendar/libedata-cal/e-cal-backend.h b/calendar/libedata-cal/e-cal-backend.h
index 9ceb25d..e7bc505 100644
--- a/calendar/libedata-cal/e-cal-backend.h
+++ b/calendar/libedata-cal/e-cal-backend.h
@@ -340,6 +340,7 @@ gboolean e_cal_backend_get_free_busy_sync
time_t start,
time_t end,
const gchar * const *users,
+ GSList **out_freebusy,
GCancellable *cancellable,
GError **error);
void e_cal_backend_get_free_busy (ECalBackend *backend,
@@ -352,6 +353,7 @@ void e_cal_backend_get_free_busy (ECalBackend *backend,
gboolean e_cal_backend_get_free_busy_finish
(ECalBackend *backend,
GAsyncResult *result,
+ GSList **out_freebusy,
GError **error);
gboolean e_cal_backend_create_objects_sync
(ECalBackend *backend,
diff --git a/calendar/libedata-cal/e-data-cal.c b/calendar/libedata-cal/e-data-cal.c
index ec9e51e..99f234d 100644
--- a/calendar/libedata-cal/e-data-cal.c
+++ b/calendar/libedata-cal/e-data-cal.c
@@ -833,21 +833,38 @@ data_cal_complete_get_free_busy_cb (GObject *source_object,
gpointer user_data)
{
AsyncContext *async_context = user_data;
+ GSList *out_freebusy = NULL;
GError *error = NULL;
e_cal_backend_get_free_busy_finish (
- E_CAL_BACKEND (source_object), result, &error);
+ E_CAL_BACKEND (source_object), result, &out_freebusy, &error);
if (error == NULL) {
+ gchar **strv;
+ gint ii = 0;
+ GSList *link;
+
+ strv = g_new0 (gchar *, g_slist_length (out_freebusy) + 1);
+
+ for (link = out_freebusy; link; link = g_slist_next (link)) {
+ gchar *ical_freebusy = link->data;
+
+ strv[ii++] = e_util_utf8_make_valid (ical_freebusy);
+ }
+
e_dbus_calendar_complete_get_free_busy (
async_context->dbus_interface,
- async_context->invocation);
+ async_context->invocation,
+ (const gchar * const *) strv);
+
+ g_strfreev (strv);
} else {
data_cal_convert_to_client_error (error);
g_dbus_method_invocation_take_error (
async_context->invocation, error);
}
+ g_slist_free_full (out_freebusy, g_free);
async_context_free (async_context);
}
@@ -1783,33 +1800,46 @@ e_data_cal_respond_get_object_list (EDataCal *cal,
* e_data_cal_respond_get_free_busy:
* @cal: A calendar client interface.
* @error: Operation error, if any, automatically freed if passed it.
+ * @freebusy: a #GSList of iCalendar strings with all gathered free/busy components.
*
* Notifies listeners of the completion of the get_free_busy method call.
- * To pass actual free/busy objects to the client use e_data_cal_report_free_busy_data().
+ * To pass actual free/busy objects to the client asynchronously
+ * use e_data_cal_report_free_busy_data(), but the @freebusy should contain
+ * all the objects being used in e_data_cal_report_free_busy_data().
*
* Since: 3.2
*/
void
e_data_cal_respond_get_free_busy (EDataCal *cal,
guint32 opid,
- GError *error)
+ GError *error,
+ const GSList *freebusy)
{
ECalBackend *backend;
GSimpleAsyncResult *simple;
+ GQueue *queue = NULL;
+ const GSList *link;
g_return_if_fail (E_IS_DATA_CAL (cal));
backend = e_data_cal_ref_backend (cal);
g_return_if_fail (backend != NULL);
- simple = e_cal_backend_prepare_for_completion (backend, opid, NULL);
+ simple = e_cal_backend_prepare_for_completion (backend, opid, &queue);
g_return_if_fail (simple != NULL);
/* Translators: This is prefix to a detailed error message */
g_prefix_error (&error, "%s", _("Cannot retrieve calendar free/busy list: "));
- if (error != NULL)
+ if (error != NULL) {
g_simple_async_result_take_error (simple, error);
+ } else {
+ for (link = freebusy; link; link = g_slist_next (link)) {
+ const gchar *ical_freebusy = link->data;
+
+ g_queue_push_tail (queue, g_strdup (ical_freebusy));
+ }
+ }
g_simple_async_result_complete_in_idle (simple);
diff --git a/calendar/libedata-cal/e-data-cal.h b/calendar/libedata-cal/e-data-cal.h
index 4445c9a..97d4a11 100644
--- a/calendar/libedata-cal/e-data-cal.h
+++ b/calendar/libedata-cal/e-data-cal.h
@@ -148,7 +148,8 @@ void e_data_cal_respond_get_object_list
void e_data_cal_respond_get_free_busy
(EDataCal *cal,
guint32 opid,
- GError *error);
+ GError *error,
+ const GSList *freebusy);
void e_data_cal_respond_create_objects
(EDataCal *cal,
guint32 opid,
diff --git a/configure.ac b/configure.ac
index 625e3c5..6879e28 100644
--- a/configure.ac
+++ b/configure.ac
@@ -114,11 +114,11 @@ LIBEDATASERVERUI_CURRENT=1
LIBEDATASERVERUI_REVISION=0
LIBEDATASERVERUI_AGE=0
-LIBECAL_CURRENT=18
+LIBECAL_CURRENT=19
LIBECAL_REVISION=0
LIBECAL_AGE=0
-LIBEDATACAL_CURRENT=27
+LIBEDATACAL_CURRENT=28
LIBEDATACAL_REVISION=0
LIBEDATACAL_AGE=0
diff --git a/private/org.gnome.evolution.dataserver.Calendar.xml
b/private/org.gnome.evolution.dataserver.Calendar.xml
index 5c21327..2d8949e 100644
--- a/private/org.gnome.evolution.dataserver.Calendar.xml
+++ b/private/org.gnome.evolution.dataserver.Calendar.xml
@@ -84,6 +84,7 @@
<arg name="start" direction="in" type="x"/>
<arg name="end" direction="in" type="x"/>
<arg name="users" direction="in" type="as"/>
+ <arg name="freebusy" direction="out" type="as"/>
</method>
<method name="GetAttachmentUris">
diff --git a/tests/libecal/client/Makefile.am b/tests/libecal/client/Makefile.am
index 7d88b30..37af8f8 100644
--- a/tests/libecal/client/Makefile.am
+++ b/tests/libecal/client/Makefile.am
@@ -37,12 +37,6 @@ TESTS = \
test-cal-client-get-view \
test-cal-client-revision-view \
test-cal-client-get-revision \
- $(NULL)
-
-# test-cal-client-get-free-busy:
-# broken by design, the API needs to be fixed.
-#
-BROKEN_TESTS = \
test-cal-client-get-free-busy \
$(NULL)
diff --git a/tests/libecal/client/test-cal-client-get-free-busy.c
b/tests/libecal/client/test-cal-client-get-free-busy.c
index ac01a99..c368097 100644
--- a/tests/libecal/client/test-cal-client-get-free-busy.c
+++ b/tests/libecal/client/test-cal-client-get-free-busy.c
@@ -109,9 +109,8 @@ test_get_free_busy_sync (ETestServerFixture *fixture,
ECalClient *cal_client;
GError *error = NULL;
icaltimezone *utc;
- GSList *users = NULL;
+ GSList *users = NULL, *freebusy_data = NULL;
time_t start, end;
- gulong sig_id;
cal_client = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient);
@@ -123,16 +122,14 @@ test_get_free_busy_sync (ETestServerFixture *fixture,
end = time_add_day_with_zone (start, 2, utc);
users = g_slist_append (users, (gpointer) USER_EMAIL);
- sig_id = g_signal_connect (cal_client, "free-busy-data", G_CALLBACK (free_busy_data_cb), (gpointer)
G_STRFUNC);
-
- if (!e_cal_client_get_free_busy_sync (cal_client, start, end, users, NULL, &error))
+ if (!e_cal_client_get_free_busy_sync (cal_client, start, end, users, &freebusy_data, NULL, &error))
g_error ("get free busy sync: %s", error->message);
- g_signal_handler_disconnect (cal_client, sig_id);
-
g_slist_free (users);
- g_assert (received_free_busy_data);
+ g_assert (freebusy_data);
+
+ g_slist_free_full (freebusy_data, g_object_unref);
}
static void
@@ -143,13 +140,17 @@ async_get_free_busy_result_ready (GObject *source_object,
ECalClient *cal_client;
GError *error = NULL;
GMainLoop *loop = (GMainLoop *) user_data;
+ GSList *freebusy_data = NULL;
cal_client = E_CAL_CLIENT (source_object);
- if (!e_cal_client_get_free_busy_finish (cal_client, result, &error))
+ if (!e_cal_client_get_free_busy_finish (cal_client, result, &freebusy_data, &error))
g_error ("create object finish: %s", error->message);
g_assert (received_free_busy_data);
+ g_assert (freebusy_data);
+
+ g_slist_free_full (freebusy_data, g_object_unref);
g_main_loop_quit (loop);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]