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

Bug 369646

Summary: [DB] ClassCastException after setBranch when server cache contains partially loaded collections
Product: [Modeling] EMF Reporter: Stefan Winkler <stefan>
Component: cdo.dbAssignee: Eike Stepper <stepper>
Status: CLOSED FIXED QA Contact: Eike Stepper <stepper>
Severity: normal    
Priority: P2    
Version: 4.1   
Target Milestone: ---   
Hardware: All   
OS: All   
Whiteboard:

Description Stefan Winkler CLA 2012-01-25 07:00:46 EST
The following code fails at the last line:

    // set up a resource with 1 object as content
    CDOSession session = openSession();
    CDOTransaction transaction = session.openTransaction();
    CDOResource res = transaction.createResource(getResourcePath("/test"));

    Category c = getModel1Factory().createCategory();
    c.setName("Test");
    res.getContents().add(c);
    transaction.commit();

    // create two cascading branches
    CDOBranch sub1 = transaction.getBranch().createBranch("sub1");
    CDOBranch sub2 = sub1.createBranch("sub2");

    // now delete the contents in the sub2 branch
    transaction.setBranch(sub2);
    res.getContents().remove(0);
    transaction.commit();

    // and now try to switch the transaction to the parent branch
    transaction.setBranch(sub1);
    
The exception is:
org.eclipse.net4j.signal.RemoteException: java.lang.ClassCastException: org.eclipse.emf.cdo.common.revision.CDORevisionUtil$Uninitialized cannot be cast to org.eclipse.emf.cdo.common.id.CDOID
	at org.eclipse.net4j.signal.RequestWithConfirmation.getRemoteException(RequestWithConfirmation.java:139)
	at org.eclipse.net4j.signal.RequestWithConfirmation.setRemoteException(RequestWithConfirmation.java:128)
	at org.eclipse.net4j.signal.SignalProtocol.handleRemoteException(SignalProtocol.java:460)
	at org.eclipse.net4j.signal.RemoteExceptionIndication.indicating(RemoteExceptionIndication.java:63)
	at org.eclipse.net4j.signal.Indication.doExtendedInput(Indication.java:55)
	at org.eclipse.net4j.signal.Signal.doInput(Signal.java:326)
	at org.eclipse.net4j.signal.Indication.execute(Indication.java:49)
	at org.eclipse.net4j.signal.Signal.runSync(Signal.java:251)
	at org.eclipse.net4j.signal.Signal.run(Signal.java:147)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:680)
Caused by: java.lang.ClassCastException: org.eclipse.emf.cdo.common.revision.CDORevisionUtil$Uninitialized cannot be cast to org.eclipse.emf.cdo.common.id.CDOID
	at org.eclipse.emf.cdo.internal.server.Session.provideCDOID(Session.java:352)
	at org.eclipse.emf.cdo.internal.common.revision.delta.CDOSingleValueFeatureDeltaImpl.writeValue(CDOSingleValueFeatureDeltaImpl.java:86)
	at org.eclipse.emf.cdo.internal.common.revision.delta.CDOSingleValueFeatureDeltaImpl.write(CDOSingleValueFeatureDeltaImpl.java:62)
	at org.eclipse.emf.cdo.internal.common.protocol.CDODataOutputImpl.writeCDOFeatureDelta(CDODataOutputImpl.java:495)
	at org.eclipse.emf.cdo.internal.common.revision.delta.CDOListFeatureDeltaImpl.write(CDOListFeatureDeltaImpl.java:136)
	at org.eclipse.emf.cdo.internal.common.protocol.CDODataOutputImpl.writeCDOFeatureDelta(CDODataOutputImpl.java:495)
	at org.eclipse.emf.cdo.internal.common.revision.delta.CDORevisionDeltaImpl.write(CDORevisionDeltaImpl.java:168)
	at org.eclipse.emf.cdo.internal.common.protocol.CDODataOutputImpl.writeCDORevisionDelta(CDODataOutputImpl.java:490)
	at org.eclipse.emf.cdo.server.internal.net4j.protocol.SwitchTargetIndication.responding(SwitchTargetIndication.java:84)
	at org.eclipse.emf.cdo.server.internal.net4j.protocol.CDOServerIndicationWithMonitoring.responding(CDOServerIndicationWithMonitoring.java:170)
	at org.eclipse.net4j.signal.IndicationWithMonitoring.responding(IndicationWithMonitoring.java:90)
	at org.eclipse.net4j.signal.IndicationWithResponse.doExtendedOutput(IndicationWithResponse.java:96)
	at org.eclipse.net4j.signal.Signal.doOutput(Signal.java:296)
	at org.eclipse.net4j.signal.IndicationWithResponse.execute(IndicationWithResponse.java:65)
	at org.eclipse.net4j.signal.IndicationWithMonitoring.execute(IndicationWithMonitoring.java:63)
	at org.eclipse.emf.cdo.server.internal.net4j.protocol.CDOServerReadIndicationWithMonitoring.execute(CDOServerReadIndicationWithMonitoring.java:36)
	... 5 more
Comment 1 Stefan Winkler CLA 2012-01-25 07:10:04 EST
Testcase contained in 

commit b7e8c99d19db29a9a116e657faf890109515608f
Author: Stefan Winkler <stefan@winklerweb.net> 2012-01-25 13:03:37
Committer: Stefan Winkler <stefan@winklerweb.net> 2012-01-25 13:05:16
Parent: bf4a6bfcbf48c59a10e115e5eb48a2344bf2a0ec (Add a missing if(TRACER.isEnabled()) line)
Branches: origin/bugs/369646, bugs/369646

[369646] [DB] ClassCastException after setBranch
https://bugs.eclipse.org/bugs/show_bug.cgi?id=369646
Comment 2 Stefan Winkler CLA 2012-01-30 05:16:57 EST
The bug is caused by a revision of which the lists are not fully loaded (e.g., because of partial collection loading). 
If such an object is contained in the server's revision cache, switchViewTarget (the server-side operation of setBranch) will cause a ClassCastException.
The problem is most likely not DB-specific, but a general core bug.
Comment 3 Eike Stepper CLA 2012-04-05 08:49:05 EDT
The test case passes here:
commit 3629bad6bcc17723ba9bbfc4249e2abac3686244
Comment 4 Eike Stepper CLA 2012-04-05 08:49:37 EDT
I suspect a duplicate of bug 337587.

*** This bug has been marked as a duplicate of bug 337587 ***
Comment 5 Eike Stepper CLA 2012-04-05 12:10:42 EDT
Sorry, with H2 the test does fail. Investigating further...
Comment 6 Eike Stepper CLA 2012-04-28 10:13:59 EDT
Three observations:

1) The test case does not use PCL.
2) The test case has never failed outside the H2 suites.
3) The test case reproducibly fails in the H2 branching-with-ranges suites.

Moving back to cdo.db.
Stefan, please have a look...
Comment 7 Eike Stepper CLA 2012-04-28 10:14:50 EDT
BTW. this is somewhat urgent because the Hudson suite is affected.
Comment 8 Stefan Winkler CLA 2012-04-29 09:23:14 EDT
Ok, as discussed on Skype, here's what I did:
1. merged the current master into bugs/369646 to make it current
2. added a second test case showing a branch switch with PCL
3. added a condition to the check for incomplete revisions in RevisionDeltaImpl 
4. provided a fix for the bug by ensuring that both oldRevision and newRevision are fully loaded before creating the ResourceDeltas

Re 2.:
Both test cases fail with DBStore, but not with MEMStore. 
I then put a breakpoint in the MEMStoreChunkReader to check if it is called: it actually is not. So I guess the MEMStore does not really do PCL nor simulate it somehow.
It just fulfills the API, or so it seems ...

Re 3.:
Eike, I think the ElementProxy is the client-side representation in the list (as you said, to track moves of elements). 
The CDOListImpl.UNINITIALIZED seems to be the server-side representation to mark the fact, that the element at this position has not been loaded.
So I added the check for the latter (then I get the more correct exception that PCL is not supported with the testcases)

Re 4:
As discussed, I added calls to Repository.ensureChunks() for both revisions in View.changeViewTarget. This makes the test cases pass.


Please check out the result in the branch. I'm assigning you again to check, if the solution (4.) is acceptable for now. If so, please go ahead and merge into master.

commit 7698f3a56562e5e538ce5584e427ada9390b9e87
Author: Stefan Winkler <stefan@winklerweb.net> 2012-04-29 15:02:21
Committer: Stefan Winkler <stefan@winklerweb.net> 2012-04-29 15:02:21
Parent: d58f2f8c74651fd147568141314eb4df614e60fa ([369646] [DB] ClassCastException after setBranch when server cache contains partially loaded collections  https://bugs.eclipse.org/bugs/show_bug.cgi?id=369646)
Branches: bugs/369646, origin/bugs/369646

[369646] [DB] ClassCastException after setBranch when server cache
contains partially loaded collections 
https://bugs.eclipse.org/bugs/show_bug.cgi?id=369646

Proposed fix for bug: ensure that both revisions are fully loaded,
before doing the compare.

(makes branch switching slower, but handles PCL correctly)
Comment 9 Eike Stepper CLA 2012-05-02 06:24:07 EDT
I applied an optimization. In the new BaseCDORevision.flags I now maintain an UNCHUNKED flag to bypass CDOElementProxy resolution whenever it's not needed (anymore).
Comment 10 Eike Stepper CLA 2012-05-02 06:24:36 EDT
commit 442b3dee3931d65fba39842912584ef8cb0215f9
Comment 11 Eike Stepper CLA 2012-09-21 07:15:46 EDT
Closing.