Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 329987

Summary: Possible offline store corruption with rawReplication
Product: [Modeling] EMF Reporter: Pascal Lehmann <pascal.lehmann>
Component: cdo.dbAssignee: Pascal Lehmann <pascal.lehmann>
Status: CLOSED FIXED QA Contact: Eike Stepper <stepper>
Severity: normal    
Priority: P3 Flags: stepper: review+
Version: 4.0   
Target Milestone: ---   
Hardware: All   
OS: All   
Whiteboard:
Attachments:
Description Flags
Patch
none
Patch v2 - reformatted slightly
none
Patch v3 - ready to be committed none

Description Pascal Lehmann CLA 2010-11-11 07:20:10 EST
When a client rawReplicates the changes to his offline store and concurrently other changes arrive at the server, the data written to the offline store might already be revised (because it has already been revised by the other changes on the server), which will cause an 'attempt to modify historical revision'-exception on the commitRunnables for the incomming other changes on the client. This will lead to a corrupt offline store, e.g. the objects with failed commitRunnables will no longer update.
Comment 1 Pascal Lehmann CLA 2010-11-11 07:23:09 EST
Created attachment 182895 [details]
Patch

In case of a raw replication, the newest version which has already been revised on the server will get 'unrevised' to have the commitRunnables succeed.
Comment 2 Eike Stepper CLA 2010-11-13 03:40:13 EST
(In reply to comment #0)
> When a client rawReplicates the changes to his offline store and concurrently
> other changes arrive at the server, 

I'm a bit confused because all these operations should end up in a prioritized queue with the replicate operation being executed before the other change notifications. I see that your change in RepositorySynchronizer removes a potential timing issue by making sure that the replicate operation is really scheduled first.

But I don't understand your changes in the mapping strategy. Are they still needed after already preventing this tiny time gap in the synchronizer? Maybe we can discuss that on Skype next week..
Comment 3 Eike Stepper CLA 2010-11-13 03:40:52 EST
Created attachment 183073 [details]
Patch v2 - reformatted slightly
Comment 4 Pascal Lehmann CLA 2010-11-15 06:37:32 EST
The changes I made are still needed, I'll give a small example to illustrate what is happending: Assume we have the server (S) and 2 clients (C1 and C2) whereas C1 is using rawReplication.

- C1 is creating an Object O, the revisions in each store will look like this (IdVersion, Created, Revised):

  C1: Ov1 t0 0
   S: Ov1 t0 0
  C2: Ov1 t0 0

- C1 is going offline and C2 is doing one more change to O:

  C1: Ov1 t0 0
   S: Ov1 t0 t1
      Ov2 t2 0
  C2: Ov1 t0 t1
      Ov2 t2 0

- C1 is going online again and requests rawReplication from somewhere between t0 and t1:

  The Server now gets the lastCommitTimeStamp to transfer all revisions during this time period.
  Meanwhile C2 is doing another change to O.

   S: Ov1 t0 t1
      Ov2 t2 t3
      Ov3 t4 0
  C2: Ov1 t0 t1
      Ov2 t2 t3
      Ov3 t4 0

  What C1 receives is the following:
  * RawReplication Ov2 t2 t3 (already revised)
  * Invalidation   Ov3 t4

  As 0v2 is already revised when written to DB the Invalidation will fail (revision.isHistorical()) and the Object will no longer be updated.

The patch does 'unrevise' the version Ov2 so the Invalidation can proceed.
Comment 5 Eike Stepper CLA 2010-11-29 03:47:46 EST
Created attachment 184010 [details]
Patch v3 - ready to be committed
Comment 6 Pascal Lehmann CLA 2010-11-29 07:06:13 EST
Committed Patch v3 to HEAD.
Comment 7 Eike Stepper CLA 2011-06-23 03:39:43 EDT
Available in R20110608-1407