Hello!
I'm currently writing tests for handling of conflicts. This wasn't done
earlier because SyncEvolution's test suite primarily targeted syncing
with SyncML servers, and behavior of those was out of control anyway.
With local syncing and/or SyncEvolution as HTTP server that's different.
My main concern at the moment are update/update conflicts where both
sides updated the same common item before syncing. libsynthesis
determines the winning item based on age (REV in vCard, LAST-MODIFIED in
iCalendar). That determines which side's single-value properties are
preserved when merging them isn't possible. I already noticed that I
need tests for both cases, because a particular SyncEvolution bug
(
https://bugs.freedesktop.org/show_bug.cgi?id=77065) only shows up in
one of the two cases.
How does this apply to arrays? Consider the following scenario: the
client adds a new TEL, the server a new EMAIL (in this order). What I
observe is that the server's item wins, preserving the server's EMAIL,
while the client's TEL array gets overwritten with the server's less
complete TEL array. The new TEL from the client thus gets lost.
That is with the following profile:
<!-- telephone numbers -->
<field name="TEL" array="yes"
type="telephone" compare="conflict"/>
<field name="TEL_FLAGS" array="yes"
type="integer" compare="conflict"/> <!-- offset 0 -->
<field name="TEL_LABEL" array="yes" type="string"
compare="conflict"/> <!-- offset 1 -->
<field name="TEL_ID" array="yes"
type="integer" compare="conflict"/> <!-- offset 2 -->
<field name="TEL_SLOT" array="yes"
type="integer" compare="never"/> <!-- offset 3 -->
<!-- emails -->
<field name="EMAIL" array="yes"
type="multiline" compare="conflict"/>
<field name="EMAIL_FLAGS" array="yes"
type="integer" compare="conflict"/> <!-- offset 0 -->
<field name="EMAIL_LABEL" array="yes" type="string"
compare="conflict"/> <!-- offset 1 -->
<field name="EMAIL_ID" array="yes"
type="integer" compare="conflict"/> <!-- offset 2 -->
<field name="EMAIL_SLOT" array="yes"
type="integer" compare="never"/> <!-- offset 3 -->
I suspect that in this case the engine really has no choice other than
treating the entire TEL array as one value. Even if it knew how to merge
the two TEL arrays (which isn't that simple when one also takes
reordering and intentional removal of entries into account), would it
know that the consecutive arrays (TEL and TEL_* resp. EMAIL and EMAIL_*)
are related?
I don't think so. That's something that is specified in the profile, but
not in the field list.
So a merge script will be needed if special handling of TEL and EMAIL is
desired, right?
The problem that I was alluding to earlier is that merging
winning: TEL = [ '1', '2' ] and
loosing: TEL = [ '1', '2', '3' ]
has no unambiguous solution. Was '3' added on the loosing side or was it
removed on the winning one?
If in doubt, probably the best approach is to pick the one which avoids
data loss, i.e. preserve '3'.
Now, consider reordering:
winning: TEL = [ '1', '2' ] and
loosing: TEL = [ '2', '1' ].
Were the entries merely reordered or were the values changed on the
loosing side? In the former case, nothing needs to be done and no
information gets lost. In the later case, the changes made on the client
get lost. I don't see a way around that (*).
Copying extra values from the loosing side can work with reordering by
looking at each value and not just at the end of the array. It's not
perfect, though, when values were edited.
Any comments so far?
(*) A three-way merge where previous copies of client and server items
are available to compute a diff would work, but that increases storage
requirements for rare situations and would require significant changes
to the engine.
--
Best Regards, Patrick Ohly
The content of this message is my personal opinion only and although
I am an employee of Intel, the statements I make here in no way
represent Intel's position on the issue, nor am I authorized to speak
on behalf of Intel on this matter.