/** Wrapper for e_cal_backend_store_remove_component(). * * This function does not actually remove component from cache in most cases. If * component already existed in cache and did not have cache state * E_CAL_COMPONENT_CACHE_STATE_CREATED, its state will be set to * E_CAL_COMPONENT_CACHE_STATE_REMOVED, otherwise it will be removed from cache. * * @param cb 3e calendar backend. * @param cache Calendar backend cache object. * @param uid UID of the calendar component. * @param rid RID of the detached instance of recurring event. * * @return TRUE if successfully removed, FALSE on failure (storage problem or not * found). */ gboolean e_cal_backend_3e_store_remove_component(ECalBackend3e *cb, ECalBackendStore *store, const char *uid, const char *rid) { ECalComponent *existing; gboolean retval; g_static_rw_lock_writer_lock(&cb->priv->cache_lock); existing = e_cal_backend_store_get_component(store, uid, rid); if (existing) { if (e_cal_component_get_cache_state(existing) == E_CAL_COMPONENT_CACHE_STATE_CREATED) { retval = e_cal_backend_store_remove_component(store, uid, rid); } else { e_cal_component_set_cache_state(existing, E_CAL_COMPONENT_CACHE_STATE_REMOVED); retval = e_cal_backend_store_put_component(store, existing); } g_object_unref(existing); } else { retval = FALSE; } g_static_rw_lock_writer_unlock(&cb->priv->cache_lock); return retval; }
/** Wrapper for e_cal_backend_store_put_component(). * * Keeps track of cache state of the component by using * e_cal_component_set_cache_state(). If component already existed in cache and * did not have cache state E_CAL_COMPONENT_CACHE_STATE_CREATED, its cache state will * be set to E_CAL_COMPONENT_CACHE_STATE_MODIFIED, in all other cases it will be * set to will be set to E_CAL_COMPONENT_CACHE_STATE_CREATED. * * @param cb 3e calendar backend. * @param cache Calendar backend cache object. * @param comp ECalComponent object. * * @return TRUE if successfully stored. */ gboolean e_cal_backend_3e_store_put_component(ECalBackend3e *cb, ECalBackendStore *store, ECalComponent *comp) { ECalComponentId *id; ECalComponentCacheState cache_state = E_CAL_COMPONENT_CACHE_STATE_CREATED; gboolean retval; id = e_cal_component_get_id(comp); if (id) { g_static_rw_lock_writer_lock(&cb->priv->cache_lock); ECalComponent *existing = e_cal_backend_store_get_component(store, id->uid, id->rid); if (existing) { if (e_cal_component_get_cache_state(existing) != E_CAL_COMPONENT_CACHE_STATE_CREATED) { cache_state = E_CAL_COMPONENT_CACHE_STATE_MODIFIED; } g_object_unref(existing); } e_cal_component_set_cache_state(comp, cache_state); retval = e_cal_backend_store_put_component(store, comp); g_static_rw_lock_writer_unlock(&cb->priv->cache_lock); e_cal_component_free_id(id); return retval; } return FALSE; }
/** Wrapper for e_cal_backend_store_get_component(). * * Get single component from cache. If component exists in cache but have cache * state E_CAL_COMPONENT_CACHE_STATE_REMOVED, NULL will be returned. * * @param cb 3E calendar backend. * @param cache Calendar backend cache object. * @param uid UID of the calendar component. * @param rid RID of the detached instance of recurring event. * * @return ECalComponent object or NULL. */ ECalComponent *e_cal_backend_3e_store_get_component(ECalBackend3e *cb, ECalBackendStore *store, const char *uid, const char *rid) { ECalComponent *comp; g_static_rw_lock_reader_lock(&cb->priv->cache_lock); comp = e_cal_backend_store_get_component(store, uid, rid); g_static_rw_lock_reader_unlock(&cb->priv->cache_lock); if (comp && e_cal_component_get_cache_state(comp) == E_CAL_COMPONENT_CACHE_STATE_REMOVED) { g_object_unref(comp); return NULL; } return comp; }
/* Get_object_component handler for the http backend */ static void e_cal_backend_http_get_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, gchar **object, GError **error) { ECalBackendHttp *cbhttp; ECalBackendHttpPrivate *priv; ECalComponent *comp = NULL; cbhttp = E_CAL_BACKEND_HTTP (backend); priv = cbhttp->priv; if (!priv->store) { g_propagate_error (error, EDC_ERROR (ObjectNotFound)); return; } if (rid && *rid) { comp = e_cal_backend_store_get_component (priv->store, uid, rid); if (!comp) { g_propagate_error (error, EDC_ERROR (ObjectNotFound)); return; } *object = e_cal_component_get_as_string (comp); g_object_unref (comp); } else { *object = e_cal_backend_store_get_components_by_uid_as_ical_string (priv->store, uid); if (!*object) g_propagate_error (error, EDC_ERROR (ObjectNotFound)); } }
/** Sync changes from the server to the cache. * * @param cb 3e calendar backend. * * @return TRUE on success. * * @todo Handle UID/RID. * @todo Better server error handling. * @todo Conflict resolution. */ gboolean e_cal_backend_3e_sync_server_to_cache(ECalBackend3e *cb) { GError *local_err = NULL; gboolean update_sync = TRUE; icalcomponent *ical; icalcomponent *icomp; char filter[128]; struct tm tm; time_t stamp = MAX(e_cal_backend_3e_get_sync_timestamp(cb) - 60 * 60 * 24, 0); /*XXX: always add 1 day padding to prevent timezone problems */ /* prepare query filter string */ gmtime_r(&stamp, &tm); strftime(filter, sizeof(filter), "modified_since('%F %T')", &tm); ical = get_server_objects(cb, filter); if (ical == NULL) { return FALSE; } for (icomp = icalcomponent_get_first_component(ical, ICAL_ANY_COMPONENT); icomp; icomp = icalcomponent_get_next_component(ical, ICAL_ANY_COMPONENT)) { icalcomponent_kind kind = icalcomponent_isa(icomp); icalcomponent_set_cache_state(icomp, E_CAL_COMPONENT_CACHE_STATE_NONE); if (kind == ICAL_VEVENT_COMPONENT) { ECalComponent *comp; const char *uid = icalcomponent_get_uid(icomp); gboolean server_deleted = icalcomponent_3e_status_is_deleted(icomp); ECalComponentCacheState comp_state = E_CAL_COMPONENT_CACHE_STATE_NONE; g_static_rw_lock_reader_lock(&cb->priv->cache_lock); comp = e_cal_backend_store_get_component(cb->priv->store, uid, NULL); g_static_rw_lock_reader_unlock(&cb->priv->cache_lock); if (comp) { comp_state = e_cal_component_get_cache_state(comp); } if (server_deleted) { /* deleted by the server */ if (comp && e_cal_component_get_cache_state(comp) != E_CAL_COMPONENT_CACHE_STATE_CREATED && e_cal_component_get_cache_state(comp) != E_CAL_COMPONENT_CACHE_STATE_MODIFIED) { char *object = e_cal_component_get_as_string(comp); ECalComponentId *id = e_cal_component_get_id(comp); g_static_rw_lock_writer_lock(&cb->priv->cache_lock); e_cal_backend_store_remove_component(cb->priv->store, uid, NULL); g_static_rw_lock_writer_unlock(&cb->priv->cache_lock); e_cal_backend_notify_object_removed(E_CAL_BACKEND(cb), id, object, NULL); e_cal_component_free_id(id); g_free(object); } } else { char *old_object = NULL; char *object; ECalComponent *new_comp = e_cal_component_new(); e_cal_component_set_icalcomponent(new_comp, icalcomponent_new_clone(icomp)); e_cal_component_set_cache_state(new_comp, E_CAL_COMPONENT_CACHE_STATE_NONE); e_cal_backend_3e_convert_attachment_uris_to_local(cb, new_comp); if (comp) { old_object = e_cal_component_get_as_string(comp); } object = e_cal_component_get_as_string(new_comp); if (old_object == NULL) { if (e_cal_backend_3e_download_attachments(cb, new_comp, &local_err)) { /* not in cache yet */ g_static_rw_lock_writer_lock(&cb->priv->cache_lock); e_cal_backend_store_put_component(cb->priv->store, new_comp); g_static_rw_lock_writer_unlock(&cb->priv->cache_lock); e_cal_backend_notify_object_created(E_CAL_BACKEND(cb), object); } else { e_cal_backend_notify_gerror_error(E_CAL_BACKEND(cb), "Can't download attachment.", local_err); g_clear_error(&local_err); update_sync = FALSE; } } else if (g_strcmp0(old_object, object)) { /* what is in cache and what is on server differs */ if (comp_state != E_CAL_COMPONENT_CACHE_STATE_NONE) { /* modified in cache, don't do anything */ } else { if (e_cal_backend_3e_download_attachments(cb, new_comp, &local_err)) { /* sync with server */ g_static_rw_lock_writer_lock(&cb->priv->cache_lock); e_cal_backend_store_put_component(cb->priv->store, new_comp); g_static_rw_lock_writer_unlock(&cb->priv->cache_lock); e_cal_backend_notify_object_modified(E_CAL_BACKEND(cb), old_object, object); } else { e_cal_backend_notify_gerror_error(E_CAL_BACKEND(cb), "Can't download attachment.", local_err); g_clear_error(&local_err); update_sync = FALSE; } } } g_free(old_object); g_free(object); g_object_unref(new_comp); } if (comp) { g_object_unref(comp); } } else if (kind == ICAL_VTIMEZONE_COMPONENT) { const char *tzid = icalcomponent_get_tzid(icomp); /* import non-existing timezones from the server */ if (!e_cal_backend_store_get_timezone(cb->priv->store, tzid)) { icaltimezone *zone = icaltimezone_new(); icalcomponent *zone_comp = icalcomponent_new_clone(icomp); if (icaltimezone_set_component(zone, zone_comp)) { g_static_rw_lock_writer_lock(&cb->priv->cache_lock); e_cal_backend_store_put_timezone(cb->priv->store, zone); g_static_rw_lock_writer_unlock(&cb->priv->cache_lock); } else { icalcomponent_free(zone_comp); } icaltimezone_free(zone, 1); } } else { g_warning("Unsupported component kind (%d) found on the 3e server.", kind); } } if (update_sync) { e_cal_backend_3e_set_sync_timestamp(cb, time(NULL)); } icalcomponent_free(ical); return TRUE; }
static gboolean put_component_to_store (ECalBackendHttp *cb, ECalComponent *comp) { time_t time_start, time_end; ECalBackendHttpPrivate *priv; ECalComponent *cache_comp; const gchar *uid; gchar *rid; priv = cb->priv; e_cal_component_get_uid (comp, &uid); rid = e_cal_component_get_recurid_as_string (comp); cache_comp = e_cal_backend_store_get_component (priv->store, uid, rid); g_free (rid); if (cache_comp) { gboolean changed = TRUE; struct icaltimetype stamp1, stamp2; stamp1 = icaltime_null_time (); stamp2 = icaltime_null_time (); e_cal_component_get_dtstamp (comp, &stamp1); e_cal_component_get_dtstamp (cache_comp, &stamp2); changed = (icaltime_is_null_time (stamp1) && !icaltime_is_null_time (stamp2)) || (!icaltime_is_null_time (stamp1) && icaltime_is_null_time (stamp2)) || (icaltime_compare (stamp1, stamp2) != 0); if (!changed) { struct icaltimetype *last_modified1 = NULL, *last_modified2 = NULL; e_cal_component_get_last_modified (comp, &last_modified1); e_cal_component_get_last_modified (cache_comp, &last_modified2); changed = (last_modified1 != NULL && last_modified2 == NULL) || (last_modified1 == NULL && last_modified2 != NULL) || (last_modified1 != NULL && last_modified2 != NULL && icaltime_compare (*last_modified1, *last_modified2) != 0); if (last_modified1) e_cal_component_free_icaltimetype (last_modified1); if (last_modified2) e_cal_component_free_icaltimetype (last_modified2); if (!changed) { gint *sequence1 = NULL, *sequence2 = NULL; e_cal_component_get_sequence (comp, &sequence1); e_cal_component_get_sequence (cache_comp, &sequence2); changed = (sequence1 != NULL && sequence2 == NULL) || (sequence1 == NULL && sequence2 != NULL) || (sequence1 != NULL && sequence2 != NULL && *sequence1 != *sequence2); if (sequence1) e_cal_component_free_sequence (sequence1); if (sequence2) e_cal_component_free_sequence (sequence2); } } g_object_unref (cache_comp); if (!changed) return FALSE; } e_cal_util_get_component_occur_times ( comp, &time_start, &time_end, resolve_tzid, cb, icaltimezone_get_utc_timezone (), e_cal_backend_get_kind (E_CAL_BACKEND (cb))); e_cal_backend_store_put_component_with_time_range (priv->store, comp, time_start, time_end); return TRUE; }