You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by "Noriyuki Kajitani (JIRA)" <ji...@apache.org> on 2011/03/28 03:54:05 UTC

[jira] [Created] (OPENJPA-1967) Got stale data from cache in multi threaded application

Got stale data from cache in multi threaded application
-------------------------------------------------------

                 Key: OPENJPA-1967
                 URL: https://issues.apache.org/jira/browse/OPENJPA-1967
             Project: OpenJPA
          Issue Type: Bug
          Components: datacache
    Affects Versions: 2.1.0, 1.2.2
            Reporter: Noriyuki Kajitani
            Priority: Minor


In multi threaded application, I experienced getting a stale data from
OpenJPA even right after updating it.  Let's say a thread (named T1)
updates a data with a value (V0) to (V1), then retrieves it from
OpenJPA.  An another thread also retrieves it in a same time.  Here,
it is expected that T1 retrieves a value V1, but it may get old value
V0, which is not expected behavior.

The cause seems OpenJPA's putting a stale data in its cache.  It could
occur in the following three cases in both OpenJPA 1.2.2 and 2.1.0.

case 1:
See org.apache.openjpa.datacache.DataCacheStoreManager.java#load method.
Let's say a thread is going to acquire write lock at the Line 402.  At the same time, the other thread can cached the data out during its operation.  In such case, the data becomes null when it reaches the Line 404.
404:data = cache.get(sm.getObjectId());
It does not compare the data version, so stale data is cached in the following part even if data has been updated in other threads.
405:if (data != null && compareVersion(sm, sm.getVersion(),
406:                data.getVersion()) == VERSION_EARLIER)
....
410:            boolean isNew = data == null;
411:            if (isNew)
412:                data = newPCData(sm);
413:            data.store(sm, fields);
414:            if (isNew)
415:                cache.put(data);

case 2:
See org.apache.openjpa.datacache.DataCacheStoreManager.java#initialize method.
Let's say a thread is going to acquire write lock at the Line 358.  At the same time, the other thread can cached the data out during its operation.  In such case, the data becomes null when it reaches the Line 360.
360:data = cache.get(sm.getObjectId());
It does not compare the data version, so stale data is cached in the following part even if data has been updated in other threads.
361:if (data != null && compareVersion(sm, sm.getVersion(),
362:                data.getVersion()) == VERSION_EARLIER)
....
368:            if (data == null)
369:                data = newPCData(sm);
370:            data.store(sm);
371:            cache.put(data);

case 3:
See org.apache.openjpa.datacache.DataCacheStoreManager.java#updateCaches.
The cache was not locked during its access.  So it could cache a stale data in multithreaded application.  Here's a case:

The thread1 gets the data from OpenJPA.
The thread2 updates and gets the data from OpenJPA.

thread2:gets the data from cache.
thread2:sets something value to column.
thread2:updates to database.
thread2:flush
thread2:gets data from cache.
thread1:OpenJPA expires the cached data.
thread1:creates cache data.
thread2:sets something value different from previous set value to column.
thread2:puts data in cache.
thread1:puts data in cache. <= override by stale data.


--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Updated] (OPENJPA-1967) Got stale data from cache in multi threaded application

Posted by "Rick Curtis (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/OPENJPA-1967?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Rick Curtis updated OPENJPA-1967:
---------------------------------

    Attachment: OPENJPA-1967.ut.patch

Uploading the test as a patch file.

> Got stale data from cache in multi threaded application
> -------------------------------------------------------
>
>                 Key: OPENJPA-1967
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-1967
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: datacache
>    Affects Versions: 1.2.2, 2.1.0
>            Reporter: Noriyuki Kajitani
>            Priority: Minor
>         Attachments: OPENJPA-1967.ut.patch, OpenJPA-1967_UT.zip
>
>
> In multi threaded application, I experienced getting a stale data from
> OpenJPA even right after updating it.  Let's say a thread (named T1)
> updates a data with a value (V0) to (V1), then retrieves it from
> OpenJPA.  An another thread also retrieves it in a same time.  Here,
> it is expected that T1 retrieves a value V1, but it may get old value
> V0, which is not expected behavior.
> The cause seems OpenJPA's putting a stale data in its cache.  It could
> occur in the following three cases in both OpenJPA 1.2.2 and 2.1.0.
> case 1:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#load method.
> Let's say a thread is going to acquire write lock at the Line 402.  At the same time, the other thread can cached the data out during its operation.  In such case, the data becomes null when it reaches the Line 404.
> 404:data = cache.get(sm.getObjectId());
> It does not compare the data version, so stale data is cached in the following part even if data has been updated in other threads.
> 405:if (data != null && compareVersion(sm, sm.getVersion(),
> 406:                data.getVersion()) == VERSION_EARLIER)
> ....
> 410:            boolean isNew = data == null;
> 411:            if (isNew)
> 412:                data = newPCData(sm);
> 413:            data.store(sm, fields);
> 414:            if (isNew)
> 415:                cache.put(data);
> case 2:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#initialize method.
> Let's say a thread is going to acquire write lock at the Line 358.  At the same time, the other thread can cached the data out during its operation.  In such case, the data becomes null when it reaches the Line 360.
> 360:data = cache.get(sm.getObjectId());
> It does not compare the data version, so stale data is cached in the following part even if data has been updated in other threads.
> 361:if (data != null && compareVersion(sm, sm.getVersion(),
> 362:                data.getVersion()) == VERSION_EARLIER)
> ....
> 368:            if (data == null)
> 369:                data = newPCData(sm);
> 370:            data.store(sm);
> 371:            cache.put(data);
> case 3:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#updateCaches.
> The cache was not locked during its access.  So it could cache a stale data in multithreaded application.  Here's a case:
> The thread1 gets the data from OpenJPA.
> The thread2 updates and gets the data from OpenJPA.
> thread2:gets the data from cache.
> thread2:sets something value to column.
> thread2:updates to database.
> thread2:flush
> thread2:gets data from cache.
> thread1:OpenJPA expires the cached data.
> thread1:creates cache data.
> thread2:sets something value different from previous set value to column.
> thread2:puts data in cache.
> thread1:puts data in cache. <= override by stale data.

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Updated] (OPENJPA-1967) Got stale data from cache in multi threaded application

Posted by "Noriyuki Kajitani (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/OPENJPA-1967?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Noriyuki Kajitani updated OPENJPA-1967:
---------------------------------------

    Attachment: OpenJPA-1967_UT.zip

Yes, I encountered the problem while developing my application.  But
it is pretty large, so attached unit test code that reproduce the
problem.  
Cache size is set small to increase reproducibility in this unit tests.
There are four unit tests. 
It could occur three problem cases in the following tests.
testSimpleData
testLazyData
testOneToMany

The following test ensures occurring case1 problem. 
testVersionMismatchOfLazyData


> Got stale data from cache in multi threaded application
> -------------------------------------------------------
>
>                 Key: OPENJPA-1967
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-1967
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: datacache
>    Affects Versions: 1.2.2, 2.1.0
>            Reporter: Noriyuki Kajitani
>            Priority: Minor
>         Attachments: OpenJPA-1967_UT.zip
>
>
> In multi threaded application, I experienced getting a stale data from
> OpenJPA even right after updating it.  Let's say a thread (named T1)
> updates a data with a value (V0) to (V1), then retrieves it from
> OpenJPA.  An another thread also retrieves it in a same time.  Here,
> it is expected that T1 retrieves a value V1, but it may get old value
> V0, which is not expected behavior.
> The cause seems OpenJPA's putting a stale data in its cache.  It could
> occur in the following three cases in both OpenJPA 1.2.2 and 2.1.0.
> case 1:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#load method.
> Let's say a thread is going to acquire write lock at the Line 402.  At the same time, the other thread can cached the data out during its operation.  In such case, the data becomes null when it reaches the Line 404.
> 404:data = cache.get(sm.getObjectId());
> It does not compare the data version, so stale data is cached in the following part even if data has been updated in other threads.
> 405:if (data != null && compareVersion(sm, sm.getVersion(),
> 406:                data.getVersion()) == VERSION_EARLIER)
> ....
> 410:            boolean isNew = data == null;
> 411:            if (isNew)
> 412:                data = newPCData(sm);
> 413:            data.store(sm, fields);
> 414:            if (isNew)
> 415:                cache.put(data);
> case 2:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#initialize method.
> Let's say a thread is going to acquire write lock at the Line 358.  At the same time, the other thread can cached the data out during its operation.  In such case, the data becomes null when it reaches the Line 360.
> 360:data = cache.get(sm.getObjectId());
> It does not compare the data version, so stale data is cached in the following part even if data has been updated in other threads.
> 361:if (data != null && compareVersion(sm, sm.getVersion(),
> 362:                data.getVersion()) == VERSION_EARLIER)
> ....
> 368:            if (data == null)
> 369:                data = newPCData(sm);
> 370:            data.store(sm);
> 371:            cache.put(data);
> case 3:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#updateCaches.
> The cache was not locked during its access.  So it could cache a stale data in multithreaded application.  Here's a case:
> The thread1 gets the data from OpenJPA.
> The thread2 updates and gets the data from OpenJPA.
> thread2:gets the data from cache.
> thread2:sets something value to column.
> thread2:updates to database.
> thread2:flush
> thread2:gets data from cache.
> thread1:OpenJPA expires the cached data.
> thread1:creates cache data.
> thread2:sets something value different from previous set value to column.
> thread2:puts data in cache.
> thread1:puts data in cache. <= override by stale data.

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Commented] (OPENJPA-1967) Got stale data from cache in multi threaded application

Posted by "Noriyuki Kajitani (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/OPENJPA-1967?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13022046#comment-13022046 ] 

Noriyuki Kajitani commented on OPENJPA-1967:
--------------------------------------------

It is pretty difficult to know 'big enough' cache size.  For our
application, there could be hundreds of thousands of objects persisted
in the DB.  On the other side, hundreds of the clients access their
objects through our application.  So the situation here is, there's
large objects and we do not know what objects likely to be accessed.
I mean, the 'enough' cache size could be large enough to fill ups the
Java VM.

> What data *should* be returned? Currently, it will return data for version 2, even though pc1 thinks it has version 1 of the data.
It should return data for version 2.
It would be great if version is prepared for each field ,not a unit of entity or not to cache the data.

> Got stale data from cache in multi threaded application
> -------------------------------------------------------
>
>                 Key: OPENJPA-1967
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-1967
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: datacache
>    Affects Versions: 1.2.2, 2.1.0
>            Reporter: Noriyuki Kajitani
>            Priority: Minor
>         Attachments: OPENJPA-1867.ut.patch, OpenJPA-1967_UT.zip
>
>
> In multi threaded application, I experienced getting a stale data from
> OpenJPA even right after updating it.  Let's say a thread (named T1)
> updates a data with a value (V0) to (V1), then retrieves it from
> OpenJPA.  An another thread also retrieves it in a same time.  Here,
> it is expected that T1 retrieves a value V1, but it may get old value
> V0, which is not expected behavior.
> The cause seems OpenJPA's putting a stale data in its cache.  It could
> occur in the following three cases in both OpenJPA 1.2.2 and 2.1.0.
> case 1:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#load method.
> Let's say a thread is going to acquire write lock at the Line 402.  At the same time, the other thread can cached the data out during its operation.  In such case, the data becomes null when it reaches the Line 404.
> 404:data = cache.get(sm.getObjectId());
> It does not compare the data version, so stale data is cached in the following part even if data has been updated in other threads.
> 405:if (data != null && compareVersion(sm, sm.getVersion(),
> 406:                data.getVersion()) == VERSION_EARLIER)
> ....
> 410:            boolean isNew = data == null;
> 411:            if (isNew)
> 412:                data = newPCData(sm);
> 413:            data.store(sm, fields);
> 414:            if (isNew)
> 415:                cache.put(data);
> case 2:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#initialize method.
> Let's say a thread is going to acquire write lock at the Line 358.  At the same time, the other thread can cached the data out during its operation.  In such case, the data becomes null when it reaches the Line 360.
> 360:data = cache.get(sm.getObjectId());
> It does not compare the data version, so stale data is cached in the following part even if data has been updated in other threads.
> 361:if (data != null && compareVersion(sm, sm.getVersion(),
> 362:                data.getVersion()) == VERSION_EARLIER)
> ....
> 368:            if (data == null)
> 369:                data = newPCData(sm);
> 370:            data.store(sm);
> 371:            cache.put(data);
> case 3:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#updateCaches.
> The cache was not locked during its access.  So it could cache a stale data in multithreaded application.  Here's a case:
> The thread1 gets the data from OpenJPA.
> The thread2 updates and gets the data from OpenJPA.
> thread2:gets the data from cache.
> thread2:sets something value to column.
> thread2:updates to database.
> thread2:flush
> thread2:gets data from cache.
> thread1:OpenJPA expires the cached data.
> thread1:creates cache data.
> thread2:sets something value different from previous set value to column.
> thread2:puts data in cache.
> thread1:puts data in cache. <= override by stale data.

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Commented] (OPENJPA-1967) Got stale data from cache in multi threaded application

Posted by "Rick Curtis (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/OPENJPA-1967?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13017068#comment-13017068 ] 

Rick Curtis commented on OPENJPA-1967:
--------------------------------------

First off, thanks for the unit tests! These problems would be nearly impossible to find in a large application. You've done an excellent job of focusing down on a few edge cases that I don't think any of us have encountered before. I'll note that I've only have time to process two of the failing cases (testSimpleData and testVersionMismatchOfLazyData). I hope to find some time this weekend to spend more time on these.

You mentioned that you discovered these problems while developing an application that is quite large. For the testSimpleData case, did you encounter this problem when running with a cache of a reasonable size for your application? My (Mike's) thoughts are that if you were to have a cache size which makes sense for your application and you were to use a LRU backing cache map[1] this problem shouldn't occur. The thought being that if you're cache is big enough, only old "non-active" entities would be purged from the cache. 

For the testVersionMismatchOfLazyData I'm still working on a solution that seems correct. For a moment, lets ignore the case where we have the DataCache enabled. 

Lets say I have a persistence context (pc1) which contains an Entity (P1) with a version of 1 and a lazily loaded string. Another persistence context (pc2) updates/commits P1 and the version increments to 2 and the lazily loaded string field is changed. Now pc1 accesses P1's lazily loaded field. What data *should* be returned? Currently, it will return data for version 2, even though pc1 thinks it has version 1 of the data. This seems like a bit of a hole in the spec perhaps? This problem will end in an OLE at the point that pc1 is flushed/committed to the DB. Not idea, but when the transaction commits so corrupt/inconsistent data won't make it to the database. Now that I went off of a tangent, back to the actual test case. 

Now back to testVersionMismatchOfLazyData. I'm going to open a separate JIRA for this issue(and probably others) so we can separate some of these concerns.

Thanks,
Rick

[1] http://openjpa.apache.org/builds/latest/docs/manual/manual.html#ref_guide_cache_conf_lru

> Got stale data from cache in multi threaded application
> -------------------------------------------------------
>
>                 Key: OPENJPA-1967
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-1967
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: datacache
>    Affects Versions: 1.2.2, 2.1.0
>            Reporter: Noriyuki Kajitani
>            Priority: Minor
>         Attachments: OpenJPA-1967_UT.zip
>
>
> In multi threaded application, I experienced getting a stale data from
> OpenJPA even right after updating it.  Let's say a thread (named T1)
> updates a data with a value (V0) to (V1), then retrieves it from
> OpenJPA.  An another thread also retrieves it in a same time.  Here,
> it is expected that T1 retrieves a value V1, but it may get old value
> V0, which is not expected behavior.
> The cause seems OpenJPA's putting a stale data in its cache.  It could
> occur in the following three cases in both OpenJPA 1.2.2 and 2.1.0.
> case 1:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#load method.
> Let's say a thread is going to acquire write lock at the Line 402.  At the same time, the other thread can cached the data out during its operation.  In such case, the data becomes null when it reaches the Line 404.
> 404:data = cache.get(sm.getObjectId());
> It does not compare the data version, so stale data is cached in the following part even if data has been updated in other threads.
> 405:if (data != null && compareVersion(sm, sm.getVersion(),
> 406:                data.getVersion()) == VERSION_EARLIER)
> ....
> 410:            boolean isNew = data == null;
> 411:            if (isNew)
> 412:                data = newPCData(sm);
> 413:            data.store(sm, fields);
> 414:            if (isNew)
> 415:                cache.put(data);
> case 2:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#initialize method.
> Let's say a thread is going to acquire write lock at the Line 358.  At the same time, the other thread can cached the data out during its operation.  In such case, the data becomes null when it reaches the Line 360.
> 360:data = cache.get(sm.getObjectId());
> It does not compare the data version, so stale data is cached in the following part even if data has been updated in other threads.
> 361:if (data != null && compareVersion(sm, sm.getVersion(),
> 362:                data.getVersion()) == VERSION_EARLIER)
> ....
> 368:            if (data == null)
> 369:                data = newPCData(sm);
> 370:            data.store(sm);
> 371:            cache.put(data);
> case 3:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#updateCaches.
> The cache was not locked during its access.  So it could cache a stale data in multithreaded application.  Here's a case:
> The thread1 gets the data from OpenJPA.
> The thread2 updates and gets the data from OpenJPA.
> thread2:gets the data from cache.
> thread2:sets something value to column.
> thread2:updates to database.
> thread2:flush
> thread2:gets data from cache.
> thread1:OpenJPA expires the cached data.
> thread1:creates cache data.
> thread2:sets something value different from previous set value to column.
> thread2:puts data in cache.
> thread1:puts data in cache. <= override by stale data.

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Updated] (OPENJPA-1967) Got stale data from cache in multi threaded application

Posted by "Rick Curtis (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/OPENJPA-1967?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Rick Curtis updated OPENJPA-1967:
---------------------------------

    Attachment:     (was: OPENJPA-1967.ut.patch)

> Got stale data from cache in multi threaded application
> -------------------------------------------------------
>
>                 Key: OPENJPA-1967
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-1967
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: datacache
>    Affects Versions: 1.2.2, 2.1.0
>            Reporter: Noriyuki Kajitani
>            Priority: Minor
>         Attachments: OPENJPA-1867.ut.patch, OpenJPA-1967_UT.zip
>
>
> In multi threaded application, I experienced getting a stale data from
> OpenJPA even right after updating it.  Let's say a thread (named T1)
> updates a data with a value (V0) to (V1), then retrieves it from
> OpenJPA.  An another thread also retrieves it in a same time.  Here,
> it is expected that T1 retrieves a value V1, but it may get old value
> V0, which is not expected behavior.
> The cause seems OpenJPA's putting a stale data in its cache.  It could
> occur in the following three cases in both OpenJPA 1.2.2 and 2.1.0.
> case 1:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#load method.
> Let's say a thread is going to acquire write lock at the Line 402.  At the same time, the other thread can cached the data out during its operation.  In such case, the data becomes null when it reaches the Line 404.
> 404:data = cache.get(sm.getObjectId());
> It does not compare the data version, so stale data is cached in the following part even if data has been updated in other threads.
> 405:if (data != null && compareVersion(sm, sm.getVersion(),
> 406:                data.getVersion()) == VERSION_EARLIER)
> ....
> 410:            boolean isNew = data == null;
> 411:            if (isNew)
> 412:                data = newPCData(sm);
> 413:            data.store(sm, fields);
> 414:            if (isNew)
> 415:                cache.put(data);
> case 2:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#initialize method.
> Let's say a thread is going to acquire write lock at the Line 358.  At the same time, the other thread can cached the data out during its operation.  In such case, the data becomes null when it reaches the Line 360.
> 360:data = cache.get(sm.getObjectId());
> It does not compare the data version, so stale data is cached in the following part even if data has been updated in other threads.
> 361:if (data != null && compareVersion(sm, sm.getVersion(),
> 362:                data.getVersion()) == VERSION_EARLIER)
> ....
> 368:            if (data == null)
> 369:                data = newPCData(sm);
> 370:            data.store(sm);
> 371:            cache.put(data);
> case 3:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#updateCaches.
> The cache was not locked during its access.  So it could cache a stale data in multithreaded application.  Here's a case:
> The thread1 gets the data from OpenJPA.
> The thread2 updates and gets the data from OpenJPA.
> thread2:gets the data from cache.
> thread2:sets something value to column.
> thread2:updates to database.
> thread2:flush
> thread2:gets data from cache.
> thread1:OpenJPA expires the cached data.
> thread1:creates cache data.
> thread2:sets something value different from previous set value to column.
> thread2:puts data in cache.
> thread1:puts data in cache. <= override by stale data.

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Updated] (OPENJPA-1967) Got stale data from cache in multi threaded application

Posted by "Rick Curtis (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/OPENJPA-1967?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Rick Curtis updated OPENJPA-1967:
---------------------------------

    Attachment: OPENJPA-1867.ut.patch

Attaching a new patch with proper new lines.

> Got stale data from cache in multi threaded application
> -------------------------------------------------------
>
>                 Key: OPENJPA-1967
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-1967
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: datacache
>    Affects Versions: 1.2.2, 2.1.0
>            Reporter: Noriyuki Kajitani
>            Priority: Minor
>         Attachments: OPENJPA-1867.ut.patch, OpenJPA-1967_UT.zip
>
>
> In multi threaded application, I experienced getting a stale data from
> OpenJPA even right after updating it.  Let's say a thread (named T1)
> updates a data with a value (V0) to (V1), then retrieves it from
> OpenJPA.  An another thread also retrieves it in a same time.  Here,
> it is expected that T1 retrieves a value V1, but it may get old value
> V0, which is not expected behavior.
> The cause seems OpenJPA's putting a stale data in its cache.  It could
> occur in the following three cases in both OpenJPA 1.2.2 and 2.1.0.
> case 1:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#load method.
> Let's say a thread is going to acquire write lock at the Line 402.  At the same time, the other thread can cached the data out during its operation.  In such case, the data becomes null when it reaches the Line 404.
> 404:data = cache.get(sm.getObjectId());
> It does not compare the data version, so stale data is cached in the following part even if data has been updated in other threads.
> 405:if (data != null && compareVersion(sm, sm.getVersion(),
> 406:                data.getVersion()) == VERSION_EARLIER)
> ....
> 410:            boolean isNew = data == null;
> 411:            if (isNew)
> 412:                data = newPCData(sm);
> 413:            data.store(sm, fields);
> 414:            if (isNew)
> 415:                cache.put(data);
> case 2:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#initialize method.
> Let's say a thread is going to acquire write lock at the Line 358.  At the same time, the other thread can cached the data out during its operation.  In such case, the data becomes null when it reaches the Line 360.
> 360:data = cache.get(sm.getObjectId());
> It does not compare the data version, so stale data is cached in the following part even if data has been updated in other threads.
> 361:if (data != null && compareVersion(sm, sm.getVersion(),
> 362:                data.getVersion()) == VERSION_EARLIER)
> ....
> 368:            if (data == null)
> 369:                data = newPCData(sm);
> 370:            data.store(sm);
> 371:            cache.put(data);
> case 3:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#updateCaches.
> The cache was not locked during its access.  So it could cache a stale data in multithreaded application.  Here's a case:
> The thread1 gets the data from OpenJPA.
> The thread2 updates and gets the data from OpenJPA.
> thread2:gets the data from cache.
> thread2:sets something value to column.
> thread2:updates to database.
> thread2:flush
> thread2:gets data from cache.
> thread1:OpenJPA expires the cached data.
> thread1:creates cache data.
> thread2:sets something value different from previous set value to column.
> thread2:puts data in cache.
> thread1:puts data in cache. <= override by stale data.

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Commented] (OPENJPA-1967) Got stale data from cache in multi threaded application

Posted by "Rick Curtis (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/OPENJPA-1967?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13013575#comment-13013575 ] 

Rick Curtis commented on OPENJPA-1967:
--------------------------------------

Do you have an application where you encountered the problems that you detailed, or did you find these through code reviews? I'm really have trouble follow the problems that you are pointing out. 

I know this might be tough to do, but can you please write a unit test that will exhibit the described behavior?

> Got stale data from cache in multi threaded application
> -------------------------------------------------------
>
>                 Key: OPENJPA-1967
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-1967
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: datacache
>    Affects Versions: 1.2.2, 2.1.0
>            Reporter: Noriyuki Kajitani
>            Priority: Minor
>
> In multi threaded application, I experienced getting a stale data from
> OpenJPA even right after updating it.  Let's say a thread (named T1)
> updates a data with a value (V0) to (V1), then retrieves it from
> OpenJPA.  An another thread also retrieves it in a same time.  Here,
> it is expected that T1 retrieves a value V1, but it may get old value
> V0, which is not expected behavior.
> The cause seems OpenJPA's putting a stale data in its cache.  It could
> occur in the following three cases in both OpenJPA 1.2.2 and 2.1.0.
> case 1:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#load method.
> Let's say a thread is going to acquire write lock at the Line 402.  At the same time, the other thread can cached the data out during its operation.  In such case, the data becomes null when it reaches the Line 404.
> 404:data = cache.get(sm.getObjectId());
> It does not compare the data version, so stale data is cached in the following part even if data has been updated in other threads.
> 405:if (data != null && compareVersion(sm, sm.getVersion(),
> 406:                data.getVersion()) == VERSION_EARLIER)
> ....
> 410:            boolean isNew = data == null;
> 411:            if (isNew)
> 412:                data = newPCData(sm);
> 413:            data.store(sm, fields);
> 414:            if (isNew)
> 415:                cache.put(data);
> case 2:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#initialize method.
> Let's say a thread is going to acquire write lock at the Line 358.  At the same time, the other thread can cached the data out during its operation.  In such case, the data becomes null when it reaches the Line 360.
> 360:data = cache.get(sm.getObjectId());
> It does not compare the data version, so stale data is cached in the following part even if data has been updated in other threads.
> 361:if (data != null && compareVersion(sm, sm.getVersion(),
> 362:                data.getVersion()) == VERSION_EARLIER)
> ....
> 368:            if (data == null)
> 369:                data = newPCData(sm);
> 370:            data.store(sm);
> 371:            cache.put(data);
> case 3:
> See org.apache.openjpa.datacache.DataCacheStoreManager.java#updateCaches.
> The cache was not locked during its access.  So it could cache a stale data in multithreaded application.  Here's a case:
> The thread1 gets the data from OpenJPA.
> The thread2 updates and gets the data from OpenJPA.
> thread2:gets the data from cache.
> thread2:sets something value to column.
> thread2:updates to database.
> thread2:flush
> thread2:gets data from cache.
> thread1:OpenJPA expires the cached data.
> thread1:creates cache data.
> thread2:sets something value different from previous set value to column.
> thread2:puts data in cache.
> thread1:puts data in cache. <= override by stale data.

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira