On Wed, 2012-08-08 at 02:42 +0200, Ove Kåven wrote:
On 07. aug. 2012 18:10, Patrick Ohly wrote:
> On Tue, 2012-08-07 at 17:41 +0200, Ove Kåven wrote:
>> On 07. aug. 2012 10:15, Patrick Ohly wrote:
>>>> Would
>>>> it be safer to generate the anchor in beginSync, so if the user does
>>>> anything during the sync, the next sync can catch it?
>>>
>>> Then changes made by SyncEvolution after beginSync() would be reported
>>> in the next sync as changes which need to be transmitted to the peer,
>>> which would be wrong.
>>
>> Is that really a big issue? I figured we're selecting on last
>> modification times here. By causality, assuming all clocks are mostly in
>> sync, typical events transmitted in a synchronization would have a
>> last-modification-time *before* the sync began, and that same
>> last-modification time would be replicated on the other side, and thus
>> also be before the beginSync time, and therefore, not picked up by the
>> next beginSync.
>
> I'm thinking of the items which are added or modified during the sync on
> behalf of the remote peer. The last-modified stamp is that of the local
> storage, not the original one from the peer, and thus it is higher than
> the beginSync time stamp.
As far as I can tell from the sources, at least KCalExtended's Tracker
storage stores and selects on the stamp of the time stored in the
received entry, not the local time of reception.
There's three different UTC time stamps in iCalendar 2.0:
* CREATED - set when created in the local storage (once per
storage)
* LAST-MODIFIED - set each time the item is updated in the local
storage (possibly multiple times per storage); the standard just
says that it gets updated when "information associated with the
calendar component was last revised in the calendar
store" (which implies some kind of semantic check), but also
compares it with "modification date and time for a file in the
file system", which is closer to a "updated by storage on each
write".
* DTSTAMP - generated each time the calendar item is turned into
iCalendar 2.0 text format (each time when reading from local
storage)
I was talking about change tracking based on LAST-MODIFIED and assumed
that the storage enforces updating it on each write. CREATED can be used
to find new items without comparing lists of items. The Synthesis engine
keeps track of all items and needs a complete list of current items from
the storage backend, so CREATED doesn't help much.
It makes sense that the created-time and modified-time in the entry
should be the time the *user* modified the data, otherwise sane conflict
resolution becomes impossible. Thus, I'd say an implementation that does
what you say is broken.
You seem to assume that LAST-MODIFIED is taken from the incoming data
and thus marks the time when the data was last modified somewhere. But
that's not how it works. According to the spec, the incoming
LAST-MODIFIED needs to be overwritten with the time when the modified
item actually hits the local storage.
The spec makes sense because relying on all peers having a synchronized
time base is risky. It's hard enough to ensure locally.
Depending on synchronized time cannot be avoided completely:
LAST-MODIFIED values from different machines still get compared when
resolving conflicts. That happens a lot less than change detection,
which must work reliably each time a sync is done.
(I did see one instance of possible brokenness
in KCalExtended's SQLite backend regarding the created-time, but not in
the Tracker backend, which is probably what's actually used here.) If
the local storage time is of interest, it should probably be kept
separate. And KCalExtended doesn't bother with keeping track of that, I
think.
There were bugs regarding these time stamps, but I reported them and as
far as I remember, they were fixed to conform with the spec.
> It has to be assigned by the local storage, because if it is
not, then a
> third party app on the local side will incorrectly conclude that a
> modified item is old and unmodified when in fact it was modified after
> that app last looked at the database.
Why would that be?
Here's an example.
Assume there is an item X with LAST-MODIFIED time x1 = 150 and CREATED =
0 in the local storage. At time a1 = 200, sync app A checks for "updated
items" since time a0 = 100, the time of its last check. The app sees the
item update and remembers a1 for the next check. At time b1 = 250, app B
stores an updated version of X that it received from somewhere with x2 =
190.
If the LAST-MODIFIED value is stored as it is, then another check by app
A for items "modified >= a1 = 200" will not report the modified item,
because x2 = 190 < 200. The app therefore fails to react to the change.
If the LAST-MODIFIED value is updated to b1 = 250, app A will see the
change, as it should be.
There are ways to avoid this scenario (only sync app stores
LAST-MODIFIED of the peer, all other apps update it when writing), but
that's not how LAST-MODIFIED and the KCalExtended API are defined at the
moment.
--
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.