[
https://issues.jboss.org/browse/ISPN-8959?page=com.atlassian.jira.plugin....
]
Paul Ferraro updated ISPN-8959:
-------------------------------
Description:
If a Cache.get(...) needs to load an entry from the cache store, it uses the
PersistenceUtil.loadAndStoreInDataContainer(...) method.
This method utilizes a DataContainer.compute(...) operation. However, when the data
container is backed by a caffeine BoundedLocalCache, the key of the ComputeAction may not
be the same as the key from the command, since caffeine wraps keys with an object (e.g.
weak reference) which uses the hashCode returned by System.identityHashCode(...). Since
loadAndStoreInDataContainer(...) method calls the loadAndCheckExpiration(...) method using
the key from the ComputeAction instead of the key from the command, it these instances are
not the same, it will fail to locate the entry in the cache store.
While I have yet to successfully create a reproducer, I've verified the situation in
the WF testsuite using the following failed assertion:
{noformat}
public static <K, V> InternalCacheEntry<K,V>
loadAndStoreInDataContainer(DataContainer<K, V> dataContainer, final
PersistenceManager persistenceManager,
K key, final InvocationContext
ctx, final TimeService timeService,
final
AtomicReference<Boolean> isLoaded) {
final ByRef<Boolean> expired = new ByRef<>(null);
InternalCacheEntry<K,V> entry = dataContainer.compute(key, (k, oldEntry,
factory) -> {
//under the lock, check if the entry exists in the DataContainer
if (oldEntry != null) {
if (isLoaded != null) {
isLoaded.set(null); //not loaded
}
if (oldEntry.canExpire() &&
oldEntry.isExpired(timeService.wallClockTime())) {
expired.set(Boolean.TRUE);
return oldEntry;
}
return oldEntry; //no changes in container
}
assert key == k : "Expected key type " + key.getClass().getName() +
" but compute action uses " + k.getClass().getName();
MarshalledEntry loaded = loadAndCheckExpiration(persistenceManager, k, ctx,
timeService);
if (loaded == null) {
if (isLoaded != null) {
isLoaded.set(Boolean.FALSE); //not loaded
}
return null; //no changed in container
}
InternalCacheEntry<K, V> newEntry = convert(loaded, factory);
if (isLoaded != null) {
isLoaded.set(Boolean.TRUE); //loaded!
}
return newEntry;
});
if (expired.get() == Boolean.TRUE) {
return null;
} else {
return entry;
}
}
{noformat}
was:
If a Cache.get(...) needs to load an entry from the cache store, it uses the
PersistenceUtil.loadAndStoreInDataContainer(...) method.
This method utilizes a DataContainer.compute(...) operation. However, when the data
container is backed by a caffeine BoundedLocalCache, the key of the ComputeAction may not
be the same as the key from the command, since caffeine wraps keys with an object (e.g.
weak reference) which uses the hashCode returned by System.identityHashCode(...). Since
loadAndStoreInDataContainer(...) method calls the loadAndCheckExpiration(...) method using
the key from the ComputeAction instead of the key from the command, it these instances are
not the same, it will fail to locate the entry in the cache store.
Infinispan occasionally fails to locate an entry in a cache store
when using a bounded data container
-----------------------------------------------------------------------------------------------------
Key: ISPN-8959
URL:
https://issues.jboss.org/browse/ISPN-8959
Project: Infinispan
Issue Type: Bug
Components: Core, Eviction
Affects Versions: 9.2.0.Final
Reporter: Paul Ferraro
Assignee: Paul Ferraro
Priority: Blocker
If a Cache.get(...) needs to load an entry from the cache store, it uses the
PersistenceUtil.loadAndStoreInDataContainer(...) method.
This method utilizes a DataContainer.compute(...) operation. However, when the data
container is backed by a caffeine BoundedLocalCache, the key of the ComputeAction may not
be the same as the key from the command, since caffeine wraps keys with an object (e.g.
weak reference) which uses the hashCode returned by System.identityHashCode(...). Since
loadAndStoreInDataContainer(...) method calls the loadAndCheckExpiration(...) method using
the key from the ComputeAction instead of the key from the command, it these instances are
not the same, it will fail to locate the entry in the cache store.
While I have yet to successfully create a reproducer, I've verified the situation in
the WF testsuite using the following failed assertion:
{noformat}
public static <K, V> InternalCacheEntry<K,V>
loadAndStoreInDataContainer(DataContainer<K, V> dataContainer, final
PersistenceManager persistenceManager,
K key, final InvocationContext
ctx, final TimeService timeService,
final
AtomicReference<Boolean> isLoaded) {
final ByRef<Boolean> expired = new ByRef<>(null);
InternalCacheEntry<K,V> entry = dataContainer.compute(key, (k, oldEntry,
factory) -> {
//under the lock, check if the entry exists in the DataContainer
if (oldEntry != null) {
if (isLoaded != null) {
isLoaded.set(null); //not loaded
}
if (oldEntry.canExpire() &&
oldEntry.isExpired(timeService.wallClockTime())) {
expired.set(Boolean.TRUE);
return oldEntry;
}
return oldEntry; //no changes in container
}
assert key == k : "Expected key type " + key.getClass().getName() +
" but compute action uses " + k.getClass().getName();
MarshalledEntry loaded = loadAndCheckExpiration(persistenceManager, k, ctx,
timeService);
if (loaded == null) {
if (isLoaded != null) {
isLoaded.set(Boolean.FALSE); //not loaded
}
return null; //no changed in container
}
InternalCacheEntry<K, V> newEntry = convert(loaded, factory);
if (isLoaded != null) {
isLoaded.set(Boolean.TRUE); //loaded!
}
return newEntry;
});
if (expired.get() == Boolean.TRUE) {
return null;
} else {
return entry;
}
}
{noformat}
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)