summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Ohly <patrick.ohly@intel.com>2011-06-14 15:24:08 +0200
committerPatrick Ohly <patrick.ohly@intel.com>2011-06-20 17:21:39 +0200
commitc6d28760b98f49b4f8f0aaae891029690fc97a8f (patch)
treefebb7a2f638e4047c090d071911721a753482749
parent55540e2685f0ef029a13003deeaeb2d127c5b70b (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.cpp55
-rw-r--r--src/syncevo/configs/datatypes/10calendar-fieldlist.xml107
-rw-r--r--src/syncevo/configs/datatypes/12calendar-types.xml6
-rw-r--r--src/syncevo/configs/scripting/11calendar.xml25
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>