diff options
author | Patrick Ohly <patrick.ohly@intel.com> | 2011-06-14 15:24:08 +0200 |
---|---|---|
committer | Patrick Ohly <patrick.ohly@intel.com> | 2011-06-20 17:21:39 +0200 |
commit | c6d28760b98f49b4f8f0aaae891029690fc97a8f (patch) | |
tree | febb7a2f638e4047c090d071911721a753482749 | |
parent | 55540e2685f0ef029a13003deeaeb2d127c5b70b (diff) |
local sync: better calendar slow sync (partly fixes BMC #14804)bmc14804
This patch replaces the ugly configuration translation with a runtime
check in a comparescript.
This is a first step towards detecting properly at runtime whether a
peer supports UID/RECURRENCE-ID semantic in calendar data. Currently
this check is still based on the "local sync == use UID/RECURRENCE-ID"
shortcut.
This patch depends on a libsynthesis which supports the COMPAREMODE()
method.
-rw-r--r-- | src/syncevo/SyncContext.cpp | 55 | ||||
-rw-r--r-- | src/syncevo/configs/datatypes/10calendar-fieldlist.xml | 107 | ||||
-rw-r--r-- | src/syncevo/configs/datatypes/12calendar-types.xml | 6 | ||||
-rw-r--r-- | src/syncevo/configs/scripting/11calendar.xml | 25 |
4 files changed, 90 insertions, 103 deletions
diff --git a/src/syncevo/SyncContext.cpp b/src/syncevo/SyncContext.cpp index c4e456d1..c06059db 100644 --- a/src/syncevo/SyncContext.cpp +++ b/src/syncevo/SyncContext.cpp @@ -2279,6 +2279,9 @@ void SyncContext::getConfigXML(string &xml, string &configname) " delayedabort = FALSE;\n" " INTEGER alarmTimeToUTC;\n" " alarmTimeToUTC = FALSE;\n" + " // for VCALENDAR_COMPARE_SCRIPT: don't use UID by default\n" + " INTEGER VCALENDAR_COMPARE_UID;\n" + " VCALENDAR_COMPARE_UID = FALSE;\n" " ]]></sessioninitscript>\n"; ostringstream clientorserver; @@ -2342,47 +2345,6 @@ void SyncContext::getConfigXML(string &xml, string &configname) clientorserver.str(), true); - // Poor man's regex match/replace: - // turn compare="foo/bar" into compare="foo" or compare="bar", - // depending on whether the first or second value is - // desired. See 10calendar-fieldlist.xml. - ostringstream modified; - size_t last = 0; - std::string value; - value.reserve(20); - static std::string sep("compare=\""); - // Choosing between the parts is a hack: in local sync mode, - // the iCalendar 2.0 semantic is always picked. - bool useFirst = !m_localSync; - for (size_t next = xml.find(sep, last); - next != xml.npos; - next = xml.find(sep, last)) { - modified.write(xml.c_str() + last, next - last); - modified << sep; - last = next + sep.size(); - value.clear(); - char c; - bool collect = true; - while (last != xml.size() && - (c = xml[last]) != '"') { - if (c == '/') { - if (useFirst) { - collect = false; - } else { - // forget first value, use second one instead - value.clear(); - } - } else if (collect) { - value += c; - } - last++; - } - modified << value; - } - modified.write(xml.c_str() + last, xml.size() - last); - xml = modified.str(); - modified.str(""); - tag = "<debug/>"; index = xml.find(tag); if (index != xml.npos) { @@ -3396,6 +3358,17 @@ SyncMLStatus SyncContext::doSync() // (not needed for OBEX) } + // Choosing between comparing UID/RECURRENCE-ID vs. other + // iCalendar 2.0 properties is a hack: in local sync mode, the + // iCalendar 2.0 semantic is always picked. + if (m_serverMode && m_localSync) { + SharedKey sessionKey = m_engine.OpenSessionKey(session); + SharedKey contextKey = m_engine.OpenKeyByPath(sessionKey, "/sessionvars"); + m_engine.SetInt32Value(contextKey, + "VCALENDAR_COMPARE_UID", + true); + } + // Sync main loop: runs until SessionStep() signals end or error. // Exceptions are caught and lead to a call of SessionStep() with // parameter STEPCMD_ABORT -> abort session as soon as possible. diff --git a/src/syncevo/configs/datatypes/10calendar-fieldlist.xml b/src/syncevo/configs/datatypes/10calendar-fieldlist.xml index a3d9d240..246c6faf 100644 --- a/src/syncevo/configs/datatypes/10calendar-fieldlist.xml +++ b/src/syncevo/configs/datatypes/10calendar-fieldlist.xml @@ -1,21 +1,4 @@ - <!-- - Common field list for events and todos (both represented by vCalendar/iCalendar). - - The compare parameters are replaced while assembling the complete config (SyncContext.cpp), - depending whether SyncEvolution operates in normal mode (first value) or - iCalendar 2.0 mode (second value) - - slowsync/scripted => slowsync (normal) resp. scripted (iCalendar 2.0) - - ... - - The key difference is that in iCalendar 2.0 mode, only UID/RECURRENCE-ID - are used to find pairs in all cases, while the rest is still relevant for - merging ("compare=scripted" instead of "never"). - - It would be nice if the final values could be chosen dynamically at runtime - for each source and the peer, but that is not currently possible. The - "replace beforehand" approach is a stop-gap measure that works well enough - for now for local sync which can always use iCalendar 2.0. - --> + <!-- common field list for events and todos (both represented by vCalendar/iCalendar) --> <fieldlist name="calendar"> <field name="SYNCLVL" type="integer" compare="never"/> <field name="ISEVENT" type="integer" compare="always"/> @@ -25,65 +8,65 @@ <field name="DGENERATED" type="timestamp" compare="never"/> - <field name="UID" type="string" compare="never/always"/> + <field name="UID" type="string" compare="never"/> - <field name="CATEGORIES" array="yes" type="string" compare="conflict/scripted" merge="fillempty"/> - <field name="CLASS" type="integer" compare="conflict/scripted" merge="fillempty"/> - <field name="TRANSP" type="integer" compare="conflict/scripted" merge="fillempty"/> + <field name="CATEGORIES" array="yes" type="string" compare="conflict" merge="fillempty"/> + <field name="CLASS" type="integer" compare="conflict" merge="fillempty"/> + <field name="TRANSP" type="integer" compare="conflict" merge="fillempty"/> - <field name="SUMMARY" type="multiline" compare="always/scripted"/> - <field name="DESCRIPTION" type="multiline" compare="slowsync/scripted" merge="lines"/> - <field name="LOCATION" type="multiline" compare="slowsync/scripted" merge="lines"/> - <field name="URL" type="url" compare="conflict/scripted" merge="fillempty"/> + <field name="SUMMARY" type="multiline" compare="always"/> + <field name="DESCRIPTION" type="multiline" compare="slowsync" merge="lines"/> + <field name="LOCATION" type="multiline" compare="slowsync" merge="lines"/> + <field name="URL" type="url" compare="conflict" merge="fillempty"/> <!-- recurrence rule block, fields must be in that order, including DTSTART as last field !! --> - <field name="RR_FREQ" type="string" compare="conflict/scripted"/> - <field name="RR_INTERVAL" type="integer" compare="conflict/scripted"/> - <field name="RR_FMASK" type="integer" compare="conflict/scripted"/> - <field name="RR_LMASK" type="integer" compare="conflict/scripted"/> - <field name="RR_END" type="timestamp" compare="conflict/scripted"/> + <field name="RR_FREQ" type="string" compare="conflict"/> + <field name="RR_INTERVAL" type="integer" compare="conflict"/> + <field name="RR_FMASK" type="integer" compare="conflict"/> + <field name="RR_LMASK" type="integer" compare="conflict"/> + <field name="RR_END" type="timestamp" compare="conflict"/> <!-- Note: DTSTART/DTEND are compared in the <comparescript>, therefore compare is set no "never" here --> - <field name="DTSTART" type="timestamp" compare="never/scripted"/> - <field name="DTEND" type="timestamp" compare="never/scripted"/> - <field name="DURATION" type="timestamp" compare="never/scripted"/> - <field name="COMPLETED" type="timestamp" compare="never/scripted"/> - <field name="DUE" type="timestamp" compare="never/scripted"/> - - <field name="GEO_LAT" type="string" compare="never/scripted"/> - <field name="GEO_LONG" type="string" compare="never/scripted"/> - - <field name="PRIORITY" type="integer" compare="conflict/scripted"/> - <field name="STATUS" type="integer" compare="conflict/scripted" merge="fillempty"/> - <field name="PERCENT_COMPLETE" type="integer" compare="conflict/scripted"/> - - <field name="ALARM_TIME" type="timestamp" compare="conflict/scripted"/> - <field name="ALARM_SNOOZE" type="string" compare="conflict/scripted"/> - <field name="ALARM_REPEAT" type="string" compare="conflict/scripted"/> - <field name="ALARM_MSG" type="string" compare="conflict/scripted"/> - <field name="ALARM_ACTION" type="string" compare="conflict/scripted"/> - <field name="ALARM_REL" type="integer" compare="never/scripted"/> + <field name="DTSTART" type="timestamp" compare="never"/> + <field name="DTEND" type="timestamp" compare="never"/> + <field name="DURATION" type="timestamp" compare="never"/> + <field name="COMPLETED" type="timestamp" compare="never"/> + <field name="DUE" type="timestamp" compare="never"/> + + <field name="GEO_LAT" type="string" compare="never"/> + <field name="GEO_LONG" type="string" compare="never"/> + + <field name="PRIORITY" type="integer" compare="conflict"/> + <field name="STATUS" type="integer" compare="conflict" merge="fillempty"/> + <field name="PERCENT_COMPLETE" type="integer" compare="conflict"/> + + <field name="ALARM_TIME" type="timestamp" compare="conflict"/> + <field name="ALARM_SNOOZE" type="string" compare="conflict"/> + <field name="ALARM_REPEAT" type="string" compare="conflict"/> + <field name="ALARM_MSG" type="string" compare="conflict"/> + <field name="ALARM_ACTION" type="string" compare="conflict"/> + <field name="ALARM_REL" type="integer" compare="never"/> <field name="ALARM_UID" type="string" compare="never" merge="fillempty"/> <!-- non-standard --> - <field name="PARENT_UID" type="string" compare="never/scripted"/> + <field name="PARENT_UID" type="string" compare="never"/> <!-- for events --> - <field name="EXDATES" array="yes" type="timestamp" compare="never/scripted"/> + <field name="EXDATES" array="yes" type="timestamp" compare="never"/> - <field name="ORIGSTART" array="no" type="timestamp" compare="never/always"/> + <field name="ORIGSTART" array="no" type="timestamp" compare="never"/> <field name="SEQNO" array="no" type="integer" compare="never"/> - <field name="ATTENDEES" array="yes" type="string" compare="never/scripted"/> - <field name="ATTENDEE_CNS" array="yes" type="string" compare="never/scripted"/> - <field name="ATTENDEE_PARTSTATS" array="yes" type="integer" compare="never/scripted"/> - <field name="ATTENDEE_ROLE" array="yes" type="integer" compare="never/scripted"/> - <field name="ATTENDEE_RSVP" array="yes" type="integer" compare="never/scripted"/> - <field name="ATTENDEE_LANG" array="yes" type="string" compare="never/scripted"/> - <field name="ATTENDEE_CUTYPE" array="yes" type="integer" compare="never/scripted"/> - <field name="ORGANIZER" array="no" type="string" compare="never/scripted"/> - <field name="ORGANIZER_CN" array="no" type="string" compare="never/scripted"/> + <field name="ATTENDEES" array="yes" type="string" compare="never"/> + <field name="ATTENDEE_CNS" array="yes" type="string" compare="never"/> + <field name="ATTENDEE_PARTSTATS" array="yes" type="integer" compare="never"/> + <field name="ATTENDEE_ROLE" array="yes" type="integer" compare="never"/> + <field name="ATTENDEE_RSVP" array="yes" type="integer" compare="never"/> + <field name="ATTENDEE_LANG" array="yes" type="string" compare="never"/> + <field name="ATTENDEE_CUTYPE" array="yes" type="integer" compare="never"/> + <field name="ORGANIZER" array="no" type="string" compare="never"/> + <field name="ORGANIZER_CN" array="no" type="string" compare="never"/> </fieldlist> diff --git a/src/syncevo/configs/datatypes/12calendar-types.xml b/src/syncevo/configs/datatypes/12calendar-types.xml index 15c64c08..4c698048 100644 --- a/src/syncevo/configs/datatypes/12calendar-types.xml +++ b/src/syncevo/configs/datatypes/12calendar-types.xml @@ -11,6 +11,9 @@ $VCALENDAR_OUTGOING_SCRIPT ]]></outgoingscript> + <comparescript><![CDATA[ + $VCALENDAR_COMPARE_SCRIPT + ]]></comparescript> </datatype> @@ -27,5 +30,8 @@ $VCALENDAR_OUTGOING_SCRIPT ]]></outgoingscript> + <comparescript><![CDATA[ + $VCALENDAR_COMPARE_SCRIPT + ]]></comparescript> </datatype> diff --git a/src/syncevo/configs/scripting/11calendar.xml b/src/syncevo/configs/scripting/11calendar.xml index 809b3e02..c2ea003c 100644 --- a/src/syncevo/configs/scripting/11calendar.xml +++ b/src/syncevo/configs/scripting/11calendar.xml @@ -187,3 +187,28 @@ ALARM_TIME = CONVERTTOZONE(ALARM_TIME, "UTC"); } ]]></macro> + + <!-- Uses the UID/RECURRENCE-ID fields as the only criteria for + comparing calendar data if the VCALENDAR_COMPARE_UID session + variable is true, else does a normal comparison of the + fields. That comparison is based on the datatype definition + and ignores UID because it is not trusted to be + preserved and/or implemented by peers. + + In case of a UID match, the DMODIFIED fields are compared + to determine the older item. + --> + <macro name="VCALENDAR_COMPARE_SCRIPT"><![CDATA[ + INTEGER RES; + if (COMPARISONMODE() != "age" && SESSIONVAR("VCALENDAR_COMPARE_UID") ) { + if (TARGET.UID == REFERENCE.UID && + TARGET.ORIGSTART == REFERENCE.ORIGSTART) { + RES = 0; + } else { + RES = -999; + } + } else { + RES = COMPAREFIELDS(); + } + return RES; + ]]></macro> |