SF #2095433: regression in 0.8: one-way sync of virtual birthday calendar

"refresh-from-client" works again for the birthday calendar.

In contrast to previous releases SyncEvolution now does some sanity checks
that the sync mode is right. For all modes other than "refresh-from-server"
and "slow" the following error is reported:

22:39:34 [INFO] ical20: sync mode is 'refresh from server'
22:39:34 [ERROR] ical20: could not read revision identifier for item pas-id-43C0ED3900000001-anniversary-rid: only refresh-from-client synchronization is supported

"slow" syncs may or may not work, depending on whether the server sends
back updates. Better don't use it. If the server sends back items during a
slow sync, then the error message is a bit cryptic:

22:47:02 [INFO] ical20: eg2fVHx6bZ6VF2MR5TgdHQ==: add
22:47:02 [INFO] ical20: eg2fVHx6bZ6VF2MR5TgdHQ==: exists already, updating instead
22:47:02 [ERROR] ical20: updating item eg2fVHx6bZ6VF2MR5TgdHQ==: Unknown error


git-svn-id: https://zeitsenke.de/svn/SyncEvolution/trunk@752 15ad00c4-1369-45f4-8270-35d70d36bdcd
This commit is contained in:
Patrick Ohly 2008-10-09 20:51:56 +00:00
parent 777d91b915
commit 0cb88c7cd1
4 changed files with 41 additions and 7 deletions

View file

@ -726,8 +726,12 @@ string EvolutionCalendarSource::getItemModTime(ECalComponent *ecomp)
{
struct icaltimetype *modTime;
e_cal_component_get_last_modified(ecomp, &modTime);
eptr<struct icaltimetype, struct icaltimetype, EvolutionUnrefFree<struct icaltimetype> > modTimePtr(modTime, "item without modification time");
return icalTime2Str(*modTimePtr);
eptr<struct icaltimetype, struct icaltimetype, EvolutionUnrefFree<struct icaltimetype> > modTimePtr(modTime);
if (!modTimePtr) {
return "";
} else {
return icalTime2Str(*modTimePtr);
}
}
string EvolutionCalendarSource::getItemModTime(const ItemID &id)
@ -735,11 +739,11 @@ string EvolutionCalendarSource::getItemModTime(const ItemID &id)
eptr<icalcomponent> icomp(retrieveItem(id));
icalproperty *lastModified = icalcomponent_get_first_property(icomp, ICAL_LASTMODIFIED_PROPERTY);
if (!lastModified) {
throwError("getItemModTime(): item without modification time");
return "";
} else {
struct icaltimetype modTime = icalproperty_get_lastmodified(lastModified);
return icalTime2Str(modTime);
}
struct icaltimetype modTime = icalproperty_get_lastmodified(lastModified);
return icalTime2Str(modTime);
}
string EvolutionCalendarSource::icalTime2Str(const icaltimetype &tt)

View file

@ -151,12 +151,14 @@ class EvolutionCalendarSource : public TrackingSyncSource
/**
* Extract modification string from calendar item.
* @return empty string if no time was available
*/
string getItemModTime(ECalComponent *ecomp);
/**
* Extract modification string of an item stored in
* the calendar.
* @return empty string if no time was available
*/
string getItemModTime(const ItemID &id);

View file

@ -53,6 +53,18 @@ void TrackingSyncSource::beginSyncThrow(bool needAll,
const string &uid = mapping.first;
const string &revision = mapping.second;
// uid must always be non-empty whereas
// revision may be empty when doing refresh-from-client
// syncs; refresh-from-client cannot be distinguished
// from slow syncs, so allow slow syncs, too
if (uid.empty()) {
throwError("could not read UID for an item");
}
bool fromClient = needAll && !needPartial && !deleteLocal;
if (!fromClient && revision.empty()) {
throwError(string("could not read revision identifier for item ") + uid + ": only refresh-from-client synchronization is supported");
}
if (deleteLocal) {
deleteItem(uid);
} else {
@ -132,6 +144,9 @@ int TrackingSyncSource::addItemThrow(SyncItem& item)
{
InsertItemResult res = insertItem("", item);
item.setKey(res.m_uid.c_str());
if (res.m_uid.empty() || res.m_revision.empty()) {
throwError("could not add item");
}
m_trackingNode->setProperty(res.m_uid, res.m_revision);
return res.m_merged ? STC_CONFLICT_RESOLVED_WITH_MERGE : STC_OK;
}
@ -144,6 +159,9 @@ int TrackingSyncSource::updateItemThrow(SyncItem& item)
m_trackingNode->removeProperty(uid);
}
item.setKey(res.m_uid.c_str());
if (res.m_uid.empty() || res.m_revision.empty()) {
throwError("could not update item");
}
m_trackingNode->setProperty(res.m_uid, res.m_revision);
return res.m_merged ? STC_CONFLICT_RESOLVED_WITH_MERGE : STC_OK;
}

View file

@ -92,6 +92,14 @@ class TrackingSyncSource : public EvolutionSyncSource
/**
* fills the complete mapping from UID to revision string of all
* currently existing items
*
* Usually both UID and revision string must be non-empty. The
* only exception is a refresh-from-client: in that case the
* revision string may be empty. The implementor of this call
* cannot know whether empty strings are allowed, therefore it
* should not throw errors when it cannot create a non-empty
* string. The caller of this method will detect situations where
* a non-empty string is necessary and none was provided.
*/
virtual void listAllItems(RevisionMap_t &revisions) = 0;
@ -130,7 +138,9 @@ class TrackingSyncSource : public EvolutionSyncSource
* This error should be reported instead of covering it up by
* (re)creating the item.
*
* Errors are signalled by throwing an exception.
* Errors are signalled by throwing an exception. Returning empty
* strings in the result is an error which triggers an "item could
* not be stored" error.
*
* @param uid identifies the item to be modified, empty for creating
* @param item contains the new content of the item and its MIME type