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

Bug 266159

Summary: IllegalArgumentException: Could not find feature CDOFeature...
Product: [Modeling] EMF Reporter: Anders Forsell <aforsell1971>
Component: cdo.coreAssignee: Eike Stepper <stepper>
Status: CLOSED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: smcduff, stepper
Version: 2.0   
Target Milestone: M7   
Hardware: PC   
OS: Windows Vista   
Whiteboard:
Bug Depends on: 265435    
Bug Blocks:    

Description Anders Forsell CLA 2009-02-25 11:35:25 EST
I have a scenario with two clients connected to the same repository. The first client creates two resources of two different .ecore packages. The second client modifies the same resources upon request from the first client. When the second client committs the transaction the following error occurs:

I have found that if I create separate sessions for the two resources, the error will not occur.

I will try to find time to reproduce this scenario with .ecore files that I can send.

ERROR    [ERROR] Rollback in MEMStore: java.lang.IllegalArgumentException: Could not find feature CDOFeature(ID=3, name=xxx, type=CDOClassRef(http://www.xyz.com/model, 22)) in class CDOClass(ID=23, name=yyy)
	at org.eclipse.emf.cdo.spi.common.revision.AbstractCDORevision.basicSet(AbstractCDORevision.java:543)
	at org.eclipse.emf.cdo.spi.common.revision.AbstractCDORevision.setValue(AbstractCDORevision.java:508)
	at org.eclipse.emf.cdo.spi.common.revision.AbstractCDORevision.set(AbstractCDORevision.java:448)
	at org.eclipse.emf.cdo.internal.common.revision.delta.CDOSetFeatureDeltaImpl.apply(CDOSetFeatureDeltaImpl.java:47)
	at org.eclipse.emf.cdo.internal.common.revision.delta.CDORevisionDeltaImpl.apply(CDORevisionDeltaImpl.java:161)
	at org.eclipse.emf.cdo.internal.server.TransactionCommitContextImpl.computeDirtyObject(TransactionCommitContextImpl.java:471)
	at org.eclipse.emf.cdo.internal.server.TransactionCommitContextImpl.computeDirtyObjects(TransactionCommitContextImpl.java:446)
	at org.eclipse.emf.cdo.internal.server.TransactionCommitContextImpl.write(TransactionCommitContextImpl.java:253)
	at org.eclipse.emf.cdo.internal.server.protocol.CommitTransactionIndication$1.runLoop(CommitTransactionIndication.java:74)
	at org.eclipse.emf.cdo.internal.server.protocol.CommitTransactionIndication$1.runLoop(CommitTransactionIndication.java:1)
	at org.eclipse.net4j.util.om.monitor.ProgressDistributor.run(ProgressDistributor.java:97)
	at org.eclipse.emf.cdo.internal.server.protocol.CommitTransactionIndication.indicatingCommit(CommitTransactionIndication.java:349)
	at org.eclipse.emf.cdo.internal.server.protocol.CommitTransactionIndication.indicating(CommitTransactionIndication.java:228)
	at org.eclipse.emf.cdo.internal.server.protocol.CommitTransactionIndication.indicating(CommitTransactionIndication.java:170)
	at org.eclipse.net4j.signal.IndicationWithMonitoring.indicating(IndicationWithMonitoring.java:84)
	at org.eclipse.net4j.signal.IndicationWithResponse.doExtendedInput(IndicationWithResponse.java:90)
	at org.eclipse.net4j.signal.Signal.doInput(Signal.java:317)
	at org.eclipse.net4j.signal.IndicationWithResponse.execute(IndicationWithResponse.java:63)
	at org.eclipse.net4j.signal.IndicationWithMonitoring.execute(IndicationWithMonitoring.java:63)
	at org.eclipse.net4j.signal.Signal.runSync(Signal.java:237)
	at org.eclipse.net4j.signal.Signal.run(Signal.java:145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ArrayIndexOutOfBoundsException: -1
	at org.eclipse.emf.cdo.internal.common.revision.CDORevisionImpl.getValue(CDORevisionImpl.java:82)
	at org.eclipse.emf.cdo.spi.common.revision.AbstractCDORevision.basicSet(AbstractCDORevision.java:537)
Comment 1 Simon Mc Duff CLA 2009-02-25 12:41:38 EST
hi Anders,

Which kind of package initialization are you using ?
- Manually (e.g.: session.getPackageRegistry().putEPackage(getModel1Package());)
- Eager
- Lazy

In the newsgroup you said you used the same session. Is it still the case ?


Simon
Comment 2 Simon Mc Duff CLA 2009-02-25 12:43:17 EST
I'm able to reproduce it with two different sessions... 

    {
      CDOSession session = openSession();
      CDOTransaction transaction = session.openTransaction();
      CDOSession session2 = openSession();
      CDOTransaction transaction2 = session2.openTransaction();
      session.getPackageRegistry().putEPackage(getModel1Package());
      session2.getPackageRegistry().putEPackage(getModel1Package());

      CDOResource res = transaction.createResource("/res");
      Company specialPurchaseOrder = getModel1Factory().createCompany();
      res.getContents().add(specialPurchaseOrder);
      transaction.commit();

      CDOResource res2 = transaction2.getResource("/res");
      Company specialPurchaseOrder2 = getModel1Factory().createCompany();
      res2.getContents().add(specialPurchaseOrder2);
      ((Company)res2.getContents().get(0)).setName("saas");
      transaction2.commit(); << FAILING
    }

Does it looks like what your applications is doing ?
Comment 3 Simon Mc Duff CLA 2009-02-25 13:02:36 EST
Here my observation:

Session1 open
Session2 open
Session1 -> Trans1
Session2 -> Trans2
Trans1->registered packages PACK1
Trans2->registered packages PACK1
Trans1 create objects1
Trans1.commit
Trans2.modify object1'
trans2 commit.

For trans2,  CDOCLass of object'1 seems new... it will think it is a new packages. 

I think some work will need to be done to handle Commit at the same time with the same CDOPackages.
Should we handle the fact that we could have many instances of CDOCLass/CDOFeature at the server.. or
Make sure we have only one copy.

Simon

Comment 4 Eike Stepper CLA 2009-02-25 13:10:13 EST
I think I discovered this issue in my current refactoring. I couldn't find a signal that transports new packages (or package infos) to existing sessions. this will be done in CommitTransactionIndication.responding() in the future.
Comment 5 Anders Forsell CLA 2009-02-26 01:43:00 EST
I am manually registering the two top-level packages I am using (one of them have two sub-packages).

I was able to workaround the error by using separate sessions for the two resources I have. The two resources are instances of the two different packages and they have no inter-dependencies.

I can easily switch back to one session and see if a potential fix resolves my issue.
Comment 6 Simon Mc Duff CLA 2009-03-04 11:47:12 EST
Adding the dependency for the following bug!!

Maybe it i fixed now!

Comment 7 Simon Mc Duff CLA 2009-03-04 11:48:49 EST
(In reply to comment #6)
> Adding the dependency for the following bug!!
> Maybe it i fixed now!

I mean in EMF-Server branch!
Comment 8 Simon Mc Duff CLA 2009-03-11 06:55:58 EDT
(In reply to comment #7)
> (In reply to comment #6)
> > Adding the dependency for the following bug!!
> > Maybe it i fixed now!
> I mean in EMF-Server branch!

I tried it and it is not fixed. :-( 
Comment 9 Simon Mc Duff CLA 2009-03-15 11:35:00 EDT
EIke,

This problems is related to the fact that new PackageRegistry received as Committed notification are hidden from the new packages!

It comes down to these questions:
How should we behave when users add duplicate EPackage in the Registry ?
Let's say.. 
- CDOPackageRegistry as model1 state == loaded or proxy
- User add the same packageRegistry (with the same URI)

I think we should throw an exception! Not allowed! Since we do not support model evolution.

Another case:
- CDOPackageRegistry of session1 as model1 state == NEW
- Another session commit that model1.
- session1 receives that packages... it should be update and not considered as new... right ?

LEt me know what you think!

Simon

Comment 10 Eike Stepper CLA 2009-03-29 23:32:03 EDT
Anders, can you confirm that the problem stilll persists after we resolved bug 265435 ?
Comment 11 Eike Stepper CLA 2009-04-03 06:22:25 EDT
Anders, please just re-open when you see this happen again.
Comment 12 Anders Forsell CLA 2009-04-03 09:55:03 EDT
I just tried with CDO 2.0 M6b and I get the same problem, although a different stack trace (below).
The featureID is '-1' and thus causes the AIOOBE on the repository (MEMStore):

Daemon Thread [Thread-5] (Suspended (exception ArrayIndexOutOfBoundsException))	
	CDOClassInfoImpl.getFeatureIndex(int) line: 83	
	CDOClassInfoImpl.getFeatureIndex(EStructuralFeature) line: 78	
	CDORevisionImpl(AbstractCDORevision).basicSet(EStructuralFeature, Object) line: 545	
	CDORevisionImpl(AbstractCDORevision).setValue(EStructuralFeature, Object) line: 515	
	CDORevisionImpl(AbstractCDORevision).set(EStructuralFeature, int, Object) line: 450	
	CDOSetFeatureDeltaImpl.apply(CDORevision) line: 48	
	CDORevisionDeltaImpl.apply(CDORevision) line: 163	
	TransactionCommitContextImpl.computeDirtyObject(InternalCDORevisionDelta, boolean) line: 464	
	TransactionCommitContextImpl.computeDirtyObjects(boolean, OMMonitor) line: 439	
	TransactionCommitContextImpl.write(OMMonitor) line: 258	
	CommitTransactionIndication$1.runLoop(int, Transaction$InternalCommitContext, OMMonitor) line: 73	
	CommitTransactionIndication$1.runLoop(int, Object, OMMonitor) line: 1	
	Store$1(ProgressDistributor).run(ProgressDistributable<CONTEXT>[], CONTEXT, OMMonitor) line: 96	
	CommitTransactionIndication.indicatingCommit(OMMonitor) line: 324	
	CommitTransactionIndication.indicating(CDODataInput, OMMonitor) line: 197	
	CommitTransactionIndication.indicating(ExtendedDataInputStream, OMMonitor) line: 139	
	CommitTransactionIndication(IndicationWithMonitoring).indicating(ExtendedDataInputStream) line: 84	
	CommitTransactionIndication(IndicationWithResponse).doExtendedInput(ExtendedDataInputStream) line: 90	
	CommitTransactionIndication(Signal).doInput(BufferInputStream) line: 317	
	CommitTransactionIndication(IndicationWithResponse).execute(BufferInputStream, BufferOutputStream) line: 63	
	CommitTransactionIndication(IndicationWithMonitoring).execute(BufferInputStream, BufferOutputStream) line: 63	
	CommitTransactionIndication(Signal).runSync() line: 237	
	CommitTransactionIndication(Signal).run() line: 145	
	ThreadPoolExecutor$Worker.runTask(Runnable) line: not available	
	ThreadPoolExecutor$Worker.run() line: not available	
	Thread.run() line: not available	

Just as before I can workaround opening separate sessions for the resources.
Comment 13 Eike Stepper CLA 2009-04-04 00:00:34 EDT
Darn it ;-)
Comment 14 Eike Stepper CLA 2009-04-04 00:35:00 EDT
Investigating
Comment 15 Eike Stepper CLA 2009-04-04 01:48:34 EDT
Committed to HEAD.

I tried to simulate some special situations like the one described here in test cases. After a fix in CDOPackageRegistry they're all passing now. Since I'm not 100% sure if I caught your situation (test case was missing), please update from HEAD, retest and re-open, if bugzilla necessary.
Comment 16 Eike Stepper CLA 2009-05-06 06:39:43 EDT
Fix available in EMF CDO 2.0.0M7
Comment 17 Eike Stepper CLA 2009-06-27 11:49:37 EDT
Generally available.