Issue Details (XML | Word | Printable)

Key: OPENJPA-35
Type: Bug Bug
Status: Resolved Resolved
Resolution: Fixed
Priority: Critical Critical
Assignee: Unassigned
Reporter: Pinaki Poddar
Votes: 0
Watchers: 1
Operations

If you were logged in you would be able to see more operations.
OpenJPA

In-memory Delete operation fails with active DataCache

Created: 28/Aug/06 11:36 PM   Updated: 27/May/08 09:06 PM
Return to search
Component/s: datacache, query
Affects Version/s: 0.9.0, 0.9.6
Fix Version/s: 0.9.7

Time Tracking:
Not Specified

File Attachments:
  Size
Zip Archive openjpa-35.test.zip 2007-02-28 09:35 PM Pinaki Poddar 3 kB
Text File openjpa-35.trace.txt 2007-02-28 11:50 PM Pinaki Poddar 5 kB
Environment:
Only happens when DataCache is active
<property name="openjpa.DataCache" value="true"/>
<property name="openjpa.RemoteCommitProvider" value="sjvm"/>

Resolution Date: 10/Mar/07 03:18 PM


 Description  « Hide
Delete through query such as
Query query = em.createQuery("DELETE FROM Node n");
query.executeUpdate();

fails with following exception (only when DataCache is active)
Exception in thread "main" <4|false|0.0.0> org.apache.openjpa.persistence.ArgumentException: org.apache.openjpa.datacache.QueryCacheStoreQuery
at org.apache.openjpa.kernel.QueryImpl.deleteInMemory(QueryImpl.java:1029)
at org.apache.openjpa.kernel.ExpressionStoreQuery$DataStoreExecutor.executeDelete(ExpressionStoreQuery.java:665)
at org.apache.openjpa.datacache.QueryCacheStoreQuery$QueryCacheExecutor.executeDelete(QueryCacheStoreQuery.java:348)
at org.apache.openjpa.kernel.QueryImpl.delete(QueryImpl.java:1012)
at org.apache.openjpa.kernel.QueryImpl.execute(QueryImpl.java:768)
at org.apache.openjpa.kernel.QueryImpl.deleteAll(QueryImpl.java:831)
at org.apache.openjpa.kernel.QueryImpl.deleteAll(QueryImpl.java:827)
at org.apache.openjpa.kernel.DelegatingQuery.deleteAll(DelegatingQuery.java:544)
at org.apache.openjpa.persistence.QueryImpl.executeUpdate(QueryImpl.java:299)
at control.Test.clear(Test.java:87)
at control.Test.run(Test.java:37)
at control.Test.main(Test.java:178)
Caused by: java.lang.ClassCastException: org.apache.openjpa.datacache.QueryCacheStoreQuery
at org.apache.openjpa.kernel.ExpressionStoreQuery$DataStoreExecutor.executeQuery(ExpressionStoreQuery.java:651)
at org.apache.openjpa.kernel.QueryImpl.execute(QueryImpl.java:949)
at org.apache.openjpa.kernel.QueryImpl.deleteInMemory(QueryImpl.java:1018)
... 11 more


 All   Comments   Work Log   Change History   Subversion Commits      Sort Order: Ascending order - Click to sort in descending order
Pinaki Poddar added a comment - 28/Feb/07 09:34 PM
I am not seeing this particular error anymore -- but I am seeing something else that does not appear right.

a) When datacache is active, even after an instance is deleted via query, the entitymanager is committed and cleared, EntityManager find() finds the instance -- not from its L1 cache but from its L2 cache.

If this is a known limitation -- it should be documented (could not find it in OpenJPA User's guide)

b) When openjpa.datacache=false, the application can still obtain a non-null reference to StoreCache, however its delegate is null.
What should OpenJPAEntityManagerFactory.getStoreCache() return when openjpa.datacache=false ?

c) delete directly i.e. em.remove() does the 'right' thing i.e. subsequent em.find() returns null.

d) Setting "openjpa.BrokerImpl" to "EvictFromDataCache=true" did not change the behavior (nor was expected)

The observations are based on the attached TestCase

Pinaki Poddar added a comment - 28/Feb/07 09:35 PM
Attached test case shows that after deleting via query, L2 cache still maintains a copy and em.find() finds the instance.

Patrick Linskey added a comment - 28/Feb/07 09:58 PM
What happens if the user modifies the object or if the user obtains a read lock on the instance?

Pinaki Poddar added a comment - 28/Feb/07 11:50 PM
Added a trace output of the test case that is failing.

shows that the deleted instance (PObject-4501) is in L2 Cache.

Please note the instance was locked and modified *after* delete by query (as we still has its reference).
Does that give the cache a chance to heal?

Please note that PObject-4501 has a DetachedStateManager when we lock/modify it after delete.

Patrick Linskey added a comment - 28/Feb/07 11:58 PM
I haven't looked at your test, but I'm guessing that since it has a DetachedStateManager, it's the same instance that you had been using earlier.

I would expect that if you deleted some instances with a bulk delete, then looked up an instance that had been deleted via a data cache hit, then tried to do anything involving a lock with that instance, you'd get a failure at commit time (assuming optimistic transactions and a @Version column).

Patrick Linskey added a comment - 28/Feb/07 11:59 PM
... to finish that thought, I'd then expect that the instance would get cleared from the cache due to the optimistic lock failure, and a second transaction involving the instance (a newly-looked-up copy) would succeed.

Pinaki Poddar added a comment - 01/Mar/07 12:44 AM
Right -- a newly looked up copy (the copy comes out of L2 cache and not from the database where it really do not exist anymore) -- is essentially not usable i.e. any commit set containing that object fails. The L2 cache heals as soon as the commit fails.

So let me summarize
a) delete via query leaves a copy in the L2 cache
b) the cached copy can be located via em.find()
c) however, any modify operation on this ghost copy will fail
d) this failure will signal to clear the copy from the L2 cache.

Do you think, it is worth mentioning in the doc?
   

Patrick Linskey added a comment - 01/Mar/07 12:56 AM
Well, I think that it's worth *fixing*, and shouldn't really be all that hard, either. But, assuming that we can't prioritize it appropriately to fix it, we should document it prior to the next release, yes.

Craig Russell added a comment - 01/Mar/07 01:25 AM
I agree this bug is worth fixing and pending the fix, worth documenting as a bug. I'd be against documenting it as a "feature".

Patrick Linskey added a comment - 08/Mar/07 09:35 AM
> b) When openjpa.datacache=false, the application can still obtain a
> non-null reference to StoreCache, however its delegate is null.
> What should OpenJPAEntityManagerFactory.getStoreCache() return
> when openjpa.datacache=false ?

I think that this is fine behavior. You generally shouldn't need to get the StoreCache's delegate. The current behavior is nice because user code doesn't need to check whether or not a cache is active; instead, user code can just perform cache operations. Sure, they're no-ops when the cache isn't on, but that's fine.