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

Bug 312404

Summary: Wrong order of CommitRunnables in RepositorySynchronizer
Product: [Modeling] EMF Reporter: Erwin Betschart <erwin>
Component: cdo.coreAssignee: Eike Stepper <stepper>
Status: CLOSED FIXED QA Contact: Eike Stepper <stepper>
Severity: major    
Priority: P1 CC: cyril.jaquier
Version: 3.0   
Target Milestone: ---   
Hardware: PC   
OS: All   
Whiteboard:
Attachments:
Description Flags
Debug screenshot
none
Patch v1 none

Description Erwin Betschart CLA 2010-05-11 08:08:22 EDT
Build Identifier: 3.0.0

The RepositorySynchronizer has a queue of Runnables. I can happen that the order of CommitRunnables is wrong.
Example (see also attached picture):
The currently processed CommitRunnable depends on revision 17 and there is a CommitRunnable in the qeueue of the RepositorySynchronizer which depends on revision 16. 
Therefore an  IllegalStateException("Origin revision not found for " + delta) will be thrown in TransactionCommitContext:579


Reproducible: Sometimes

Steps to Reproduce:
It is difficult to reproduce.
- The problem occurs more often in case of a bigger master database.
- Do commits on the master while a client synchronizes its clone repository.
Comment 1 Erwin Betschart CLA 2010-05-11 08:10:43 EDT
Created attachment 167901 [details]
Debug screenshot

Shows a CommitRunnable with version 16 in the queue of the repository synchronizer and a CommitRunnable with version 17 which is currently processed.
Comment 2 Eike Stepper CLA 2010-05-18 11:44:19 EDT
Created attachment 168954 [details]
Patch v1

Erwin, please try the patch and give feedback...
Comment 3 Eike Stepper CLA 2010-05-19 12:08:35 EDT
Added org.eclipse.emf.cdo.tests.OfflineDelayed2Test.testCommitOrder()

Committed to HEAD.
Comment 4 Eike Stepper CLA 2010-05-19 12:27:01 EDT
I found out that exceptions during TransactionCommitContext.write() have not been propagated to the client. This commit mechanism seems to be way older than the generic ability of Net4j to transport server exceptions to the client. I added this now. The original patch v1 seems to do a good job now. The test is passing.

Committed to HEAD
Comment 5 Erwin Betschart CLA 2010-05-28 11:10:45 EDT
Reopening because the patch introduces some new problems:

1. There should be a termination condition in CommitRunnable.run() -> Atm busy loop if the CommitRunnable can never be successfully committed on the clone repository.

2. The retry should only be done for commits which are out of order (IllegalStateException("Origin revision not found for " + delta)
). E.g. the following exception (and probably other) cause an infinite busy loop.

!ENTRY org.eclipse.emf.cdo.server 4 0 2010-05-26 16:42:12.515
!MESSAGE org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: BASE_SCENARIO_OOBNODE_IDX0 ON PANTHERREPO.BASE_SCENARIO_OOBNODE(CDO_ID, CDO_VERSION, CDO_BRANCH); SQL statement:
INSERT INTO base_scenario_OobNode(cdo_id, cdo_version, cdo_branch, cdo_class, cdo_created, cdo_revised, cdo_resource, cdo_container, cdo_feature, id, lastEditTime, lastEditName, description, state_F686, userInCharge, userDeputy, unitType, staff, visibleInOrgChart, manualPosition, iconSet, name, layerElement) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [23001-117]
!STACK 0
org.eclipse.net4j.db.DBException: org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: BASE_SCENARIO_OOBNODE_IDX0 ON PANTHERREPO.BASE_SCENARIO_OOBNODE(CDO_ID, CDO_VERSION, CDO_BRANCH); SQL statement:
INSERT INTO base_scenario_OobNode(cdo_id, cdo_version, cdo_branch, cdo_class, cdo_created, cdo_revised, cdo_resource, cdo_container, cdo_feature, id, lastEditTime, lastEditName, description, state_F686, userInCharge, userDeputy, unitType, staff, visibleInOrgChart, manualPosition, iconSet, name, layerElement) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [23001-117]
at org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.HorizontalBranchingClassMapping.writeValues(HorizontalBranchingClassMapping.java:497)
at org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.HorizontalBranchingClassMapping.writeRevision(HorizontalBranchingClassMapping.java:636)
at org.eclipse.emf.cdo.server.internal.db.DBStoreAccessor.writeRevision(DBStoreAccessor.java:387)
at org.eclipse.emf.cdo.server.internal.db.DBStoreAccessor.writeRevisions(DBStoreAccessor.java:368)
at org.eclipse.emf.cdo.spi.server.StoreAccessor.write(StoreAccessor.java:191)
at org.eclipse.emf.cdo.internal.server.TransactionCommitContext.write(TransactionCommitContext.java:299)
at org.eclipse.emf.cdo.internal.server.syncing.SynchronizableRepository.handleCommitInfo(SynchronizableRepository.java:185)
at org.eclipse.emf.cdo.internal.server.syncing.RepositorySynchronizer$CommitRunnable.run(RepositorySynchronizer.java:461)
at org.eclipse.net4j.util.concurrent.QueueRunner.work(QueueRunner.java:26)
at org.eclipse.net4j.util.concurrent.QueueRunner.work(QueueRunner.java:1)
at org.eclipse.net4j.util.concurrent.QueueWorker.work(QueueWorker.java:75)
at org.eclipse.net4j.util.concurrent.Worker$WorkerThread.run(Worker.java:188)
Caused by: org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: BASE_SCENARIO_OOBNODE_IDX0 ON PANTHERREPO.BASE_SCENARIO_OOBNODE(CDO_ID, CDO_VERSION, CDO_BRANCH); SQL statement:
INSERT INTO base_scenario_OobNode(cdo_id, cdo_version, cdo_branch, cdo_class, cdo_created, cdo_revised, cdo_resource, cdo_container, cdo_feature, id, lastEditTime, lastEditName, description, state_F686, userInCharge, userDeputy, unitType, staff, visibleInOrgChart, manualPosition, iconSet, name, layerElement) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [23001-117]
at org.h2.message.Message.getSQLException(Message.java:105)
at org.h2.message.Message.getSQLException(Message.java:116)
at org.h2.message.Message.getSQLException(Message.java:75)
at org.h2.index.BaseIndex.getDuplicateKeyException(BaseIndex.java:154)
at org.h2.index.BtreeLeaf.add(BtreeLeaf.java:65)
at org.h2.index.BtreeNode.add(BtreeNode.java:104)
at org.h2.index.BtreeNode.add(BtreeNode.java:104)
at org.h2.index.BtreeIndex.add(BtreeIndex.java:228)
at org.h2.table.TableData.addRow(TableData.java:123)
at org.h2.command.dml.Insert.update(Insert.java:101)
at org.h2.command.CommandContainer.update(CommandContainer.java:72)
at org.h2.command.Command.executeUpdate(Command.java:208)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:140)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:129)
at org.eclipse.emf.cdo.server.db.CDODBUtil.sqlUpdate(CDODBUtil.java:185)
at org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.HorizontalBranchingClassMapping.writeValues(HorizontalBranchingClassMapping.java:493)
... 11 more
Comment 6 Eike Stepper CLA 2010-06-05 04:55:31 EDT
I've added these properties to IRepositorySynchronizer for controlling the attempts for "recommits":

  public int getMaxRecommits();
  public void setMaxRecommits(int maxRecommits);
  public int getRecommitInterval();
  public void setRecommitInterval(int recommitInterval);
Comment 7 Eike Stepper CLA 2010-06-05 05:40:51 EDT
Committed to HEAD
Comment 8 Eike Stepper CLA 2010-06-29 04:35:29 EDT
Available in 3.0 GA:
http://download.eclipse.org/modeling/emf/cdo/updates/3.0-releases/