[evolution-data-server] Change how next occurrence of a recurring task is found
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Change how next occurrence of a recurring task is found
- Date: Wed, 21 Mar 2018 10:55:25 +0000 (UTC)
commit d1a6621c48612a8dcf1de8672e749b08645c07fe
Author: Milan Crha <mcrha redhat com>
Date: Wed Mar 21 11:53:38 2018 +0100
Change how next occurrence of a recurring task is found
The previous naive "set some faraway end time" approach was also
a performance hit for often-happen tasks, because e-cal-recur
computes all occurrences in the given time interval first and only
then lets the caller know with the callback, thus, with a long time
interval most of the found occurrences had been useless. The new
approach is adaptable and avoids this performance issue as well.
src/calendar/libecal/e-cal-util.c | 50 +++++++++++++++++++++++++++++-------
1 files changed, 40 insertions(+), 10 deletions(-)
---
diff --git a/src/calendar/libecal/e-cal-util.c b/src/calendar/libecal/e-cal-util.c
index c80ace3..c3fc3a8 100644
--- a/src/calendar/libecal/e-cal-util.c
+++ b/src/calendar/libecal/e-cal-util.c
@@ -1909,6 +1909,7 @@ typedef struct _NextOccurrenceData {
struct icaltimetype interval_start;
struct icaltimetype next;
gboolean found_next;
+ gboolean any_hit;
} NextOccurrenceData;
static gboolean
@@ -1923,6 +1924,8 @@ ecu_find_next_occurrence_cb (icalcomponent *comp,
g_return_val_if_fail (nod != NULL, FALSE);
+ nod->any_hit = TRUE;
+
if (icaltime_compare (nod->interval_start, instance_start) < 0) {
nod->next = instance_start;
nod->found_next = TRUE;
@@ -1943,7 +1946,10 @@ e_cal_util_find_next_occurrence (icalcomponent *vtodo,
{
NextOccurrenceData nod;
struct icaltimetype interval_start = for_time, interval_end, orig_dtstart, orig_due;
+ gint advance_days = 8;
+ icalproperty *prop;
gboolean success;
+ GError *local_error = NULL;
g_return_val_if_fail (vtodo != NULL, FALSE);
g_return_val_if_fail (out_time != NULL, FALSE);
@@ -1962,22 +1968,46 @@ e_cal_util_find_next_occurrence (icalcomponent *vtodo,
if (icaltime_is_null_time (interval_start) || !icaltime_is_valid_time (interval_start))
interval_start = icaltime_current_time_with_zone (e_cal_client_get_default_timezone
(cal_client));
- /* Some far-enough time to cover long recurrences */
- interval_end = icaltime_from_string ("30000101T000000Z");
+ prop = icalcomponent_get_first_property (vtodo, ICAL_RRULE_PROPERTY);
+ if (prop) {
+ struct icalrecurrencetype rrule;
+
+ rrule = icalproperty_get_rrule (prop);
+
+ if (rrule.freq == ICAL_WEEKLY_RECURRENCE && rrule.interval > 1)
+ advance_days = (rrule.interval * 7) + 1;
+ else if (rrule.freq == ICAL_MONTHLY_RECURRENCE)
+ advance_days = (rrule.interval >= 1 ? rrule.interval * 31 : 31) + 1;
+ else if (rrule.freq == ICAL_YEARLY_RECURRENCE)
+ advance_days = (rrule.interval >= 1 ? rrule.interval * 365 : 365) + 2;
+ }
+
+ do {
+ interval_end = interval_start;
+ icaltime_adjust (&interval_end, advance_days, 0, 0, 0);
+
+ nod.interval_start = interval_start;
+ nod.next = icaltime_null_time ();
+ nod.found_next = FALSE;
+ nod.any_hit = FALSE;
- nod.interval_start = interval_start;
- nod.next = icaltime_null_time ();
- nod.found_next = FALSE;
+ success = e_cal_recur_generate_instances_sync (vtodo, interval_start, interval_end,
+ ecu_find_next_occurrence_cb, &nod,
+ e_cal_client_resolve_tzid_sync, cal_client,
+ e_cal_client_get_default_timezone (cal_client),
+ cancellable, &local_error) || nod.found_next;
- success = e_cal_recur_generate_instances_sync (vtodo, interval_start, interval_end,
- ecu_find_next_occurrence_cb, &nod,
- e_cal_client_resolve_tzid_sync, cal_client,
- e_cal_client_get_default_timezone (cal_client),
- cancellable, error) || nod.found_next;
+ interval_start = interval_end;
+ icaltime_adjust (&interval_start, -1, 0, 0, 0);
+
+ } while (!local_error && !g_cancellable_is_cancelled (cancellable) && !nod.found_next && nod.any_hit);
if (success)
*out_time = nod.next;
+ if (local_error)
+ g_propagate_error (error, local_error);
+
if (!icaltime_is_null_time (for_time) && icaltime_is_valid_time (for_time)) {
if (icaltime_is_null_time (orig_dtstart) || !icaltime_is_valid_time (orig_dtstart))
e_cal_util_remove_property_by_kind (vtodo, ICAL_DTSTART_PROPERTY, FALSE);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]