diff --git a/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java index b9cb0c854e..dc15958981 100644 --- a/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java +++ b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/DelegatingLoaderWriterStore.java @@ -106,12 +106,12 @@ public Iterator>> iterator() { } @Override - public ValueHolder getAndCompute(K key, BiFunction mappingFunction) throws StoreAccessException { + public ValueHolder getAndCompute(K key, BiFunction, ? extends V> mappingFunction) throws StoreAccessException { throw new UnsupportedOperationException("Implement me"); } @Override - public ValueHolder computeAndGet(K key, BiFunction mappingFunction, Supplier replaceEqual, Supplier invokeWriter) throws StoreAccessException { + public ValueHolder computeAndGet(K key, BiFunction, ? extends V> mappingFunction, Supplier replaceEqual, Supplier invokeWriter) throws StoreAccessException { throw new UnsupportedOperationException("Implement me"); } @@ -121,12 +121,12 @@ public ValueHolder computeIfAbsent(K key, Function ma } @Override - public Map> bulkCompute(Set keys, Function>, Iterable>> remappingFunction) throws StoreAccessException { + public Map> bulkCompute(Set keys, Function>>, Iterable>> remappingFunction) throws StoreAccessException { return delegate.bulkCompute(keys, remappingFunction); } @Override - public Map> bulkCompute(Set keys, Function>, Iterable>> remappingFunction, Supplier replaceEqual) throws StoreAccessException { + public Map> bulkCompute(Set keys, Function>>, Iterable>> remappingFunction, Supplier replaceEqual) throws StoreAccessException { throw new UnsupportedOperationException("Implement me"); } diff --git a/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java index 015590af2c..438f26a6e3 100644 --- a/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java +++ b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/store/ClusteredStore.java @@ -49,6 +49,7 @@ import org.ehcache.core.spi.service.ExecutionService; import org.ehcache.core.spi.service.StatisticsService; import org.ehcache.core.spi.store.Store; +import org.ehcache.core.spi.store.Store.ValueHolder; import org.ehcache.core.spi.store.events.StoreEventFilter; import org.ehcache.core.spi.store.events.StoreEventListener; import org.ehcache.core.spi.store.events.StoreEventSource; @@ -478,13 +479,13 @@ public Cache.Entry> next() throws StoreAccessException { } @Override - public ValueHolder getAndCompute(final K key, final BiFunction mappingFunction) { + public ValueHolder getAndCompute(final K key, final BiFunction, ? extends V> mappingFunction) { // TODO: Make appropriate ServerStoreProxy call throw new UnsupportedOperationException("Implement me"); } @Override - public ValueHolder computeAndGet(final K key, final BiFunction mappingFunction, final Supplier replaceEqual, Supplier invokeWriter) { + public ValueHolder computeAndGet(final K key, final BiFunction, ? extends V> mappingFunction, final Supplier replaceEqual, Supplier invokeWriter) { // TODO: Make appropriate ServerStoreProxy call throw new UnsupportedOperationException("Implement me"); } @@ -499,7 +500,7 @@ public ValueHolder computeIfAbsent(final K key, final Function> bulkCompute(final Set keys, final Function>, Iterable>> remappingFunction) + public Map> bulkCompute(final Set keys, final Function>>, Iterable>> remappingFunction) throws StoreAccessException { Map> valueHolderMap = new HashMap<>(); if(remappingFunction instanceof Ehcache.PutAllFunction) { @@ -525,7 +526,7 @@ public Map> bulkCompute(final Set keys, final Fun } @Override - public Map> bulkCompute(final Set keys, final Function>, Iterable>> remappingFunction, final Supplier replaceEqual) { + public Map> bulkCompute(final Set keys, final Function>>, Iterable>> remappingFunction, final Supplier replaceEqual) { // TODO: Make appropriate ServerStoreProxy call throw new UnsupportedOperationException("Implement me"); } diff --git a/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java index 735a293a39..40d8b0836d 100644 --- a/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java +++ b/clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/store/ClusteredStoreTest.java @@ -520,7 +520,7 @@ public void testBulkComputeRemoveAll() throws Exception { @Test(expected = UnsupportedOperationException.class) public void testBulkComputeThrowsForGenericFunction() throws Exception { @SuppressWarnings("unchecked") - Function>, Iterable>> remappingFunction + Function>>, Iterable>> remappingFunction = mock(Function.class); store.bulkCompute(new HashSet<>(Arrays.asList(1L, 2L)), remappingFunction); } diff --git a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java index 60959d9c5a..161b7b3516 100644 --- a/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java +++ b/clustered/integration-test/src/test/java/org/ehcache/clustered/JCacheClusteredTest.java @@ -47,6 +47,7 @@ public class JCacheClusteredTest { private static final Properties TCK_PROPERTIES = new Properties(); static { + TCK_PROPERTIES.setProperty("org.jsr107.tck.support.server.address", "127.0.0.1"); TCK_PROPERTIES.setProperty("java.net.preferIPv4Stack", "true"); TCK_PROPERTIES.setProperty("javax.management.builder.initial", "org.ehcache.jsr107.internal.tck.Eh107MBeanServerBuilder"); TCK_PROPERTIES.setProperty("org.jsr107.tck.management.agentId", "Eh107MBeanServer"); diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreBulkComputeTest.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreBulkComputeTest.java index 1ffdf221ff..5ca4315e22 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreBulkComputeTest.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreBulkComputeTest.java @@ -81,8 +81,8 @@ public void remappingFunctionReturnsIterableOfEntriesForEachInputEntry() throws try { Map> mapFromRemappingFunction = kvStore.bulkCompute(inputKeys, entries -> { Map update = new HashMap<>(); - for (Map.Entry entry : entries) { - update.put(entry.getKey(), entry.getValue()); + for (Map.Entry> entry : entries) { + update.put(entry.getKey(), entry.getValue().get()); } return update.entrySet(); } @@ -134,7 +134,7 @@ public void mappingIsRemovedFromStoreForNullValueEntriesFromRemappingFunction() try { kvStore.bulkCompute(inputKeys, entries -> { Map update = new HashMap<>(); - for (Map.Entry entry : entries) { + for (Map.Entry> entry : entries) { update.put(entry.getKey(), null); } return update.entrySet(); @@ -167,13 +167,13 @@ public void remappingFunctionGetsIterableWithMappedStoreEntryValueOrNull() throw try { kvStore.bulkCompute(inputKeys, entries -> { Map update = new HashMap<>(); - for (Map.Entry entry : entries) { + for (Map.Entry> entry : entries) { if (mappedEntries.containsKey(entry.getKey())) { - assertThat(entry.getValue(), is(mappedEntries.get(entry.getKey()))); + assertThat(entry.getValue().get(), is(mappedEntries.get(entry.getKey()))); } else { assertThat(entry.getValue(), is(nullValue())); } - update.put(entry.getKey(), entry.getValue()); + update.put(entry.getKey(), entry.getValue().get()); } return update.entrySet(); } @@ -199,7 +199,7 @@ public void computeValuesForEveryKeyUsingARemappingFunction() throws Exception { try { kvStore.bulkCompute(inputKeys, entries -> { Map update = new HashMap<>(); - for (Map.Entry entry : entries) { + for (Map.Entry> entry : entries) { update.put(entry.getKey(), computedEntries.get(entry.getKey())); } return update.entrySet(); @@ -230,7 +230,7 @@ public void remappingFunctionProducesWrongKeyType() throws Exception { try { kvStore.bulkCompute(inputKeys, entries -> { Map update = new HashMap<>(); - for (Map.Entry entry : entries) { + for (Map.Entry> entry : entries) { if (factory.getKeyType() == String.class) { update.put((K)new StringBuffer(entry.getKey().toString()), computedEntries.get(entry.getKey())); } else { @@ -264,7 +264,7 @@ public void remappingFunctionProducesWrongValueType() throws Exception { try { kvStore.bulkCompute(inputKeys, entries -> { Map update = new HashMap<>(); - for (Map.Entry entry : entries) { + for (Map.Entry> entry : entries) { if (factory.getKeyType() == String.class) { update.put(entry.getKey(), (V)new StringBuffer(computedEntries.get(entry.getKey()).toString())); } else { diff --git a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreGetAndComputeTest.java b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreGetAndComputeTest.java index 5c65c5153b..0dfb424ab9 100644 --- a/core-spi-test/src/main/java/org/ehcache/internal/store/StoreGetAndComputeTest.java +++ b/core-spi-test/src/main/java/org/ehcache/internal/store/StoreGetAndComputeTest.java @@ -226,7 +226,7 @@ public void testExceptionOnSupplier() throws Exception { kvStore.put(key, value); assertThat(kvStore.get(key).get(), is(value)); - kvStore.computeAndGet(key, (keyParam, oldValue) -> oldValue, () -> { throw re; }, () -> false); + kvStore.computeAndGet(key, (keyParam, oldValue) -> oldValue.get(), () -> { throw re; }, () -> false); } catch (StoreAccessException e) { assertThat(e.getCause(), is(re)); } @@ -248,7 +248,7 @@ public void testPassThroughExceptionOnSupplier() throws Exception { kvStore.put(key, value); assertThat(kvStore.get(key).get(), is(value)); - kvStore.computeAndGet(key, (keyParam, oldValue) -> oldValue, () -> { throw re; }, () -> false); + kvStore.computeAndGet(key, (keyParam, oldValue) -> oldValue.get(), () -> { throw re; }, () -> false); } catch (RuntimeException e) { assertThat(e, is(exception)); } @@ -268,7 +268,7 @@ public void testComputeExpiresOnAccess() throws Exception { try { kvStore.put(key, value); - Store.ValueHolder result = kvStore.getAndCompute(key, (k, v) -> v); + Store.ValueHolder result = kvStore.getAndCompute(key, (k, v) -> v.get()); assertThat(result.get(), is(value)); assertThat(kvStore.get(key), nullValue()); } catch (StoreAccessException e) { diff --git a/ehcache-107/build.gradle b/ehcache-107/build.gradle index 3d439ff733..cce388592e 100644 --- a/ehcache-107/build.gradle +++ b/ehcache-107/build.gradle @@ -109,6 +109,7 @@ task tckTest(type: Test, dependsOn: unpackTckTests) { reports.junitXml.destination = file("$buildDir/tck-tests-results") reports.html.destination = file("$buildDir/reports/tck-tests") + systemProperty 'org.jsr107.tck.support.server.address', '127.0.0.1' systemProperty 'java.net.preferIPv4Stack', 'true' systemProperty 'javax.management.builder.initial', 'org.ehcache.jsr107.internal.tck.Eh107MBeanServerBuilder' systemProperty 'org.jsr107.tck.management.agentId', 'Eh107MBeanServer' diff --git a/ehcache-core/src/main/java/org/ehcache/core/Ehcache.java b/ehcache-core/src/main/java/org/ehcache/core/Ehcache.java index f908f957b4..5c1c7ff1c0 100644 --- a/ehcache-core/src/main/java/org/ehcache/core/Ehcache.java +++ b/ehcache-core/src/main/java/org/ehcache/core/Ehcache.java @@ -183,15 +183,14 @@ public void compute(K key, final BiFunction c getObserver.begin(); try { - BiFunction fn = (mappedKey, mappedValue) -> { + BiFunction, V> fn = (mappedKey, mappedValue) -> { if (mappedValue == null) { getObserver.end(GetOutcome.MISS); + return computeFunction.apply(mappedKey, null); } else { getObserver.end(GetOutcome.HIT); + return computeFunction.apply(mappedKey, mappedValue.get()); } - - return computeFunction.apply(mappedKey, mappedValue); - }; ValueHolder compute = store.computeAndGet(key, fn, replaceEqual, invokeWriter); @@ -259,7 +258,7 @@ public V getAndPut(K key, final V value) { // The compute function that will return the keys to their NEW values, taking the keys to their old values as input; // but this could happen in batches, i.e. not necessary containing all of the entries of the Iterable passed to this method - public static class PutAllFunction implements Function>, Iterable>> { + public static class PutAllFunction implements Function>>, Iterable>> { private final Logger logger; private final Map entriesToRemap; @@ -274,13 +273,13 @@ public PutAllFunction(Logger logger, Map entriesToRemap, ExpiryPolicy> apply(final Iterable> entries) { + public Iterable> apply(final Iterable>> entries) { Map mutations = new LinkedHashMap<>(); // then record we handled these mappings - for (Map.Entry entry: entries) { + for (Map.Entry> entry: entries) { K key = entry.getKey(); - V existingValue = entry.getValue(); + ValueHolder existingValue = entry.getValue(); V newValue = entriesToRemap.remove(key); if (newValueAlreadyExpired(key, existingValue, newValue)) { @@ -302,7 +301,7 @@ public Map getEntriesToRemap() { return entriesToRemap; } - private boolean newValueAlreadyExpired(K key, V oldValue, V newValue) { + private boolean newValueAlreadyExpired(K key, ValueHolder oldValue, V newValue) { return EhcacheBase.newValueAlreadyExpired(logger, expiry, key, oldValue, newValue); } @@ -315,17 +314,17 @@ public AtomicInteger getActualUpdateCount() { } } - public static class RemoveAllFunction implements Function>, Iterable>> { + public static class RemoveAllFunction implements Function>>, Iterable>> { private final AtomicInteger actualRemoveCount = new AtomicInteger(); @Override - public Iterable> apply(final Iterable> entries) { + public Iterable> apply(final Iterable>> entries) { Map results = new LinkedHashMap<>(); - for (Map.Entry entry : entries) { + for (Map.Entry> entry : entries) { K key = entry.getKey(); - V existingValue = entry.getValue(); + ValueHolder existingValue = entry.getValue(); if (existingValue != null) { actualRemoveCount.incrementAndGet(); diff --git a/ehcache-core/src/main/java/org/ehcache/core/EhcacheBase.java b/ehcache-core/src/main/java/org/ehcache/core/EhcacheBase.java index 3b4e482cef..21d5093b3e 100644 --- a/ehcache-core/src/main/java/org/ehcache/core/EhcacheBase.java +++ b/ehcache-core/src/main/java/org/ehcache/core/EhcacheBase.java @@ -385,7 +385,7 @@ public void putAll(Map entries) throws BulkCacheWritin protected abstract void doPutAll(Map entries) throws StoreAccessException, BulkCacheWritingException; - protected boolean newValueAlreadyExpired(K key, V oldValue, V newValue) { + protected boolean newValueAlreadyExpired(K key, ValueHolder oldValue, V newValue) { return newValueAlreadyExpired(logger, runtimeConfiguration.getExpiryPolicy(), key, oldValue, newValue); } @@ -424,7 +424,7 @@ public void removeAll(Set keys) throws BulkCacheWritingException { protected abstract void doRemoveAll(Set keys) throws BulkCacheWritingException, StoreAccessException; - protected static boolean newValueAlreadyExpired(Logger logger, ExpiryPolicy expiry, K key, V oldValue, V newValue) { + protected static boolean newValueAlreadyExpired(Logger logger, ExpiryPolicy expiry, K key, ValueHolder oldValue, V newValue) { if (newValue == null) { return false; } @@ -434,7 +434,7 @@ protected static boolean newValueAlreadyExpired(Logger logger, ExpiryPoli if (oldValue == null) { duration = expiry.getExpiryForCreation(key, newValue); } else { - duration = expiry.getExpiryForUpdate(key, () -> oldValue, newValue); + duration = expiry.getExpiryForUpdate(key, oldValue, newValue); } } catch (RuntimeException re) { logger.error("Expiry computation caused an exception - Expiry duration will be 0 ", re); @@ -680,7 +680,7 @@ private void loadAllReplace(Set keys, final Function { Collection keys1 = new ArrayList<>(); - for (Map.Entry entry : entries) { + for (Map.Entry> entry : entries) { keys1.add(entry.getKey()); } return cacheLoaderWriterLoadAllForKeys(keys1, loadFunction).entrySet(); diff --git a/ehcache-core/src/main/java/org/ehcache/core/spi/store/Store.java b/ehcache-core/src/main/java/org/ehcache/core/spi/store/Store.java index d3c0fd82ff..4d08974ff2 100644 --- a/ehcache-core/src/main/java/org/ehcache/core/spi/store/Store.java +++ b/ehcache-core/src/main/java/org/ehcache/core/spi/store/Store.java @@ -333,7 +333,7 @@ default ValueHolder getAndRemove(K key) throws StoreAccessException { * @throws StoreAccessException if the mapping can't be changed * */ - ValueHolder getAndCompute(K key, BiFunction mappingFunction) throws StoreAccessException; + ValueHolder getAndCompute(K key, BiFunction, ? extends V> mappingFunction) throws StoreAccessException; /** * Compute the value for the given key by invoking the given function to produce the value. @@ -376,7 +376,7 @@ default ValueHolder getAndRemove(K key) throws StoreAccessException { * @throws StoreAccessException if the mapping can't be changed * */ - ValueHolder computeAndGet(K key, BiFunction mappingFunction, Supplier replaceEqual, Supplier invokeWriter) throws StoreAccessException; + ValueHolder computeAndGet(K key, BiFunction, ? extends V> mappingFunction, Supplier replaceEqual, Supplier invokeWriter) throws StoreAccessException; /** * Compute the value for the given key (only if absent or expired) by invoking the given function to produce the value. @@ -438,7 +438,7 @@ default ValueHolder getAndRemove(K key) throws StoreAccessException { * @throws NullPointerException if any of the arguments is null * @throws StoreAccessException if mappings can't be changed */ - Map> bulkCompute(Set keys, Function>, Iterable>> remappingFunction) throws StoreAccessException; + Map> bulkCompute(Set keys, Function>>, Iterable>> remappingFunction) throws StoreAccessException; /** * Compute a value for every key passed in the {@link Set} {@code keys} argument, using the {@code remappingFunction} to compute the value. @@ -467,7 +467,7 @@ default ValueHolder getAndRemove(K key) throws StoreAccessException { * @throws NullPointerException if any of the arguments is null * @throws StoreAccessException if mappings can't be changed */ - Map> bulkCompute(Set keys, Function>, Iterable>> remappingFunction, Supplier replaceEqual) throws StoreAccessException; + Map> bulkCompute(Set keys, Function>>, Iterable>> remappingFunction, Supplier replaceEqual) throws StoreAccessException; /** * Compute a value for every key passed in the {@link Set} keys argument using the mappingFunction diff --git a/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java index f08ef6c502..b6ba29a699 100644 --- a/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java +++ b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicCrudBase.java @@ -385,7 +385,7 @@ public ValueHolder getValue() { * this.{@link Store#getAndCompute(Object, BiFunction)} (keys, mappingFunction, () -> { returns true; }) */ @Override - public ValueHolder getAndCompute(final String key, final BiFunction mappingFunction) + public ValueHolder getAndCompute(final String key, final BiFunction, ? extends String> mappingFunction) throws StoreAccessException { return this.computeAndGet(key, mappingFunction, REPLACE_EQUAL_TRUE, INVOKE_WRITER_FALSE); } @@ -409,12 +409,12 @@ public ValueHolder getAndCompute(final String key, final BiFunction mappingFunction, + final BiFunction, ? extends String> mappingFunction, final Supplier replaceEqual) throws StoreAccessException { String remappedValue; try { - remappedValue = mappingFunction.apply(key, (currentValue == null ? null : currentValue.get())); + remappedValue = mappingFunction.apply(key, currentValue); } catch (StorePassThroughException cpte) { Throwable cause = cpte.getCause(); if(cause instanceof RuntimeException) { @@ -449,7 +449,7 @@ private FakeValueHolder computeInternal( @Override public ValueHolder computeAndGet( final String key, - final BiFunction mappingFunction, + final BiFunction, ? extends String> mappingFunction, final Supplier replaceEqual, Supplier invokeWriter) throws StoreAccessException { this.checkFailingKey(key); @@ -497,7 +497,7 @@ public ValueHolder computeIfAbsent(final String key, final Function> bulkCompute( final Set keys, - final Function>, Iterable>> remappingFunction) + final Function>>, Iterable>> remappingFunction) throws StoreAccessException { return this.bulkCompute(keys, remappingFunction, REPLACE_EQUAL_TRUE); } @@ -511,7 +511,7 @@ public Map> bulkCompute( @Override public Map> bulkCompute( final Set keys, - final Function>, Iterable>> remappingFunction, + final Function>>, Iterable>> remappingFunction, final Supplier replaceEqual) throws StoreAccessException { @@ -519,7 +519,7 @@ public Map> bulkCompute( for (final String key : keys) { final ValueHolder newValue = this.computeAndGet(key, (key1, oldValue) -> { - final Entry entry = new AbstractMap.SimpleEntry<>(key1, oldValue); + final Entry> entry = new AbstractMap.SimpleEntry<>(key1, oldValue); final Entry remappedEntry = remappingFunction.apply(Collections.singletonList(entry)).iterator().next(); return remappedEntry.getValue(); diff --git a/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicPutAllTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicPutAllTest.java index 6825c526ab..571bca79f2 100644 --- a/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicPutAllTest.java +++ b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicPutAllTest.java @@ -300,7 +300,7 @@ static Set getAnyStringSet() { * @return a Mockito {@code any} matcher for {@code Function} */ @SuppressWarnings("unchecked") - static Function>, Iterable>> getAnyEntryIterableFunction() { + static Function>>, Iterable>> getAnyEntryIterableFunction() { return any(Function.class); // unchecked } diff --git a/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicRemoveAllTest.java b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicRemoveAllTest.java index a852c81f28..c5a0bd1154 100644 --- a/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicRemoveAllTest.java +++ b/ehcache-core/src/test/java/org/ehcache/core/EhcacheBasicRemoveAllTest.java @@ -271,7 +271,7 @@ static Set getAnyStringSet() { * @return a Mockito {@code any} matcher for {@code Function} */ @SuppressWarnings("unchecked") - static Function>, Iterable>> getAnyEntryIterableFunction() { + static Function>>, Iterable>> getAnyEntryIterableFunction() { return any(Function.class); // unchecked } diff --git a/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java index 8ff6b2af6c..e7ef2f8982 100644 --- a/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java +++ b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/basic/NopStore.java @@ -163,12 +163,12 @@ public Cache.Entry> next() { } @Override - public ValueHolder getAndCompute(K key, BiFunction mappingFunction) { + public ValueHolder getAndCompute(K key, BiFunction, ? extends V> mappingFunction) { return null; } @Override - public ValueHolder computeAndGet(K key, BiFunction mappingFunction, Supplier replaceEqual, Supplier invokeWriter) { + public ValueHolder computeAndGet(K key, BiFunction, ? extends V> mappingFunction, Supplier replaceEqual, Supplier invokeWriter) { return null; } @@ -178,12 +178,12 @@ public ValueHolder computeIfAbsent(K key, Function ma } @Override - public Map> bulkCompute(Set keys, Function>, Iterable>> remappingFunction) throws StoreAccessException { + public Map> bulkCompute(Set keys, Function>>, Iterable>> remappingFunction) throws StoreAccessException { return bulkCompute(keys, remappingFunction, null); } @Override - public Map> bulkCompute(Set keys, Function>, Iterable>> remappingFunction, Supplier replaceEqual) { + public Map> bulkCompute(Set keys, Function>>, Iterable>> remappingFunction, Supplier replaceEqual) { Map> map = new HashMap<>(keys.size()); for(K key : keys) { map.put(key, null); diff --git a/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java index 63fddcc792..f484c8b999 100644 --- a/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java +++ b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/heap/OnHeapStore.java @@ -93,6 +93,7 @@ import java.util.function.Function; import java.util.function.Supplier; +import static java.util.Collections.singletonMap; import static org.ehcache.config.Eviction.noAdvice; import static org.ehcache.core.config.ExpiryUtils.isExpiryDurationInfinite; import static org.ehcache.core.exceptions.StorePassThroughException.handleException; @@ -1109,7 +1110,7 @@ public boolean equals(Object obj) { } @Override - public ValueHolder getAndCompute(K key, BiFunction mappingFunction) throws StoreAccessException { + public ValueHolder getAndCompute(K key, BiFunction, ? extends V> mappingFunction) throws StoreAccessException { checkKey(key); computeObserver.begin(); @@ -1131,13 +1132,12 @@ public ValueHolder getAndCompute(K key, BiFunction holder; - V existingValue = mappedValue == null ? null : mappedValue.get(); if (mappedValue != null) { oldValue.set(mappedValue); } - V computedValue = mappingFunction.apply(mappedKey, existingValue); + V computedValue = mappingFunction.apply(mappedKey, mappedValue); if (computedValue == null) { - if (existingValue != null) { + if (mappedValue != null) { eventSink.removed(mappedKey, mappedValue); outcome.set(StoreOperationOutcomes.ComputeOutcome.REMOVED); delta -= mappedValue.size(); @@ -1177,7 +1177,7 @@ public ValueHolder getAndCompute(K key, BiFunction computeAndGet(K key, BiFunction mappingFunction, Supplier replaceEqual, Supplier invokeWriter) throws StoreAccessException { + public ValueHolder computeAndGet(K key, BiFunction, ? extends V> mappingFunction, Supplier replaceEqual, Supplier invokeWriter) throws StoreAccessException { checkKey(key); computeObserver.begin(); @@ -1199,16 +1199,15 @@ public ValueHolder computeAndGet(K key, BiFunction holder; - V existingValue = mappedValue == null ? null : mappedValue.get(); - V computedValue = mappingFunction.apply(mappedKey, existingValue); + V computedValue = mappingFunction.apply(mappedKey, mappedValue); if (computedValue == null) { - if (existingValue != null) { + if (mappedValue != null) { eventSink.removed(mappedKey, mappedValue); outcome.set(StoreOperationOutcomes.ComputeOutcome.REMOVED); delta -= mappedValue.size(); } holder = null; - } else if (Objects.equals(existingValue, computedValue) && !replaceEqual.get() && mappedValue != null) { + } else if (mappedValue != null && !replaceEqual.get() && Objects.equals(mappedValue.get(), computedValue)) { holder = strategy.setAccessAndExpiryWhenCallerlUnderLock(key, mappedValue, now, eventSink); outcome.set(StoreOperationOutcomes.ComputeOutcome.HIT); if (holder == null) { @@ -1358,12 +1357,12 @@ public List getConfigurationChangeListeners() } @Override - public Map> bulkCompute(Set keys, Function>, Iterable>> remappingFunction) throws StoreAccessException { + public Map> bulkCompute(Set keys, Function>>, Iterable>> remappingFunction) throws StoreAccessException { return bulkCompute(keys, remappingFunction, REPLACE_EQUALS_TRUE); } @Override - public Map> bulkCompute(Set keys, Function>, Iterable>> remappingFunction, Supplier replaceEqual) throws StoreAccessException { + public Map> bulkCompute(Set keys, Function>>, Iterable>> remappingFunction, Supplier replaceEqual) throws StoreAccessException { // The Store here is free to slice & dice the keys as it sees fit // As this OnHeapStore doesn't operate in segments, the best it can do is do a "bulk" write in batches of... one! @@ -1373,8 +1372,7 @@ public Map> bulkCompute(Set keys, Function newValue = computeAndGet(key, (k, oldValue) -> { - Set> entrySet = Collections.singletonMap(k, oldValue).entrySet(); - Iterable> entries = remappingFunction.apply(entrySet); + Iterable> entries = remappingFunction.apply(Collections.singletonMap(k, oldValue).entrySet()); java.util.Iterator> iterator = entries.iterator(); Entry next = iterator.next(); diff --git a/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java index 066bf01033..e997a7eff9 100644 --- a/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java +++ b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/loaderwriter/LocalLoaderWriterStore.java @@ -85,7 +85,7 @@ public boolean containsKey(K key) throws StoreAccessException { @Override public PutStatus put(K key, V value) throws StoreAccessException { - BiFunction remappingFunction = (key1, previousValue) -> { + BiFunction, V> remappingFunction = (key1, previousValue) -> { try { cacheLoaderWriter.write(key1, value); } catch (Exception e) { @@ -132,7 +132,7 @@ public ValueHolder putIfAbsent(K key, V value, Consumer put) throws public boolean remove(K key) throws StoreAccessException { boolean[] modified = { false }; - BiFunction remappingFunction = (key1, previousValue) -> { + BiFunction, V> remappingFunction = (key1, previousValue) -> { modified[0] = (previousValue != null); try { @@ -150,14 +150,14 @@ public boolean remove(K key) throws StoreAccessException { @Override public RemoveStatus remove(K key, V value) throws StoreAccessException { boolean[] hitRemoved = { false, false }; // index 0 = hit, 1 = removed - BiFunction remappingFunction = (k, inCache) -> { - inCache = loadFromLoaderWriter(key, inCache); - if(inCache == null) { + BiFunction, V> remappingFunction = (k, inCache) -> { + V existingValue = loadFromLoaderWriter(key, inCache); + if(existingValue == null) { return null; } hitRemoved[0] = true; - if (value.equals(inCache)) { + if (value.equals(existingValue)) { try { cacheLoaderWriter.delete(k); } catch (Exception e) { @@ -166,7 +166,7 @@ public RemoveStatus remove(K key, V value) throws StoreAccessException { hitRemoved[1] = true; return null; } - return inCache; + return existingValue; }; delegate.computeAndGet(key, remappingFunction, SUPPLY_FALSE, SUPPLY_FALSE); @@ -186,9 +186,9 @@ public ValueHolder replace(K key, V value) throws StoreAccessException { @SuppressWarnings("unchecked") V[] old = (V[]) new Object[1]; - BiFunction remappingFunction = (k, inCache) -> { - inCache = loadFromLoaderWriter(key, inCache); - if(inCache == null) { + BiFunction, V> remappingFunction = (k, inCache) -> { + V existingValue = loadFromLoaderWriter(key, inCache); + if(existingValue == null) { return null; } @@ -198,9 +198,9 @@ public ValueHolder replace(K key, V value) throws StoreAccessException { throw new StorePassThroughException(newCacheWritingException(e)); } - old[0] = inCache; + old[0] = existingValue; - if (newValueAlreadyExpired(LOG, expiry, key, inCache, value)) { + if (newValueAlreadyExpired(LOG, expiry, key, () -> existingValue, value)) { return null; } return value; @@ -217,14 +217,14 @@ public ValueHolder replace(K key, V value) throws StoreAccessException { public ReplaceStatus replace(K key, V oldValue, V newValue) throws StoreAccessException { boolean[] successHit = { false, false }; // index 0 = success, 1 = hit - BiFunction remappingFunction = (k, inCache) -> { - inCache = loadFromLoaderWriter(key, inCache); - if(inCache == null) { + BiFunction, V> remappingFunction = (k, inCache) -> { + V existingValue = loadFromLoaderWriter(key, inCache); + if(existingValue == null) { return null; } successHit[1] = true; - if (oldValue.equals(inCache)) { + if (oldValue.equals(existingValue)) { try { cacheLoaderWriter.write(key, newValue); } catch (Exception e) { @@ -233,12 +233,13 @@ public ReplaceStatus replace(K key, V oldValue, V newValue) throws StoreAccessEx successHit[0] = true; - if (newValueAlreadyExpired(LOG, expiry, key, oldValue, newValue)) { + if (newValueAlreadyExpired(LOG, expiry, key, () -> existingValue, newValue)) { return null; } return newValue; + } else { + return existingValue; } - return inCache; }; delegate.computeAndGet(key, remappingFunction, SUPPLY_FALSE, SUPPLY_FALSE); @@ -269,7 +270,7 @@ public Iterator>> iterator() { } @Override - public ValueHolder getAndCompute(K key, BiFunction mappingFunction) throws StoreAccessException { + public ValueHolder getAndCompute(K key, BiFunction, ? extends V> mappingFunction) throws StoreAccessException { return delegate.getAndCompute(key, (mappedKey, mappedValue) -> { V newValue = mappingFunction.apply(mappedKey, mappedValue); if (newValue == null) { @@ -294,9 +295,9 @@ public ValueHolder getAndCompute(K key, BiFunction computeAndGet(K key, BiFunction mappingFunction, Supplier replaceEqual, Supplier invokeWriter) throws StoreAccessException { + public ValueHolder computeAndGet(K key, BiFunction, ? extends V> mappingFunction, Supplier replaceEqual, Supplier invokeWriter) throws StoreAccessException { - BiFunction remappingFunction = (mappedKey, mappedValue) -> { + BiFunction, ? extends V> remappingFunction = (mappedKey, mappedValue) -> { V newValue = mappingFunction.apply(mappedKey, mappedValue); if (invokeWriter.get()) { try { @@ -321,7 +322,7 @@ public ValueHolder computeIfAbsent(K key, Function ma } @Override - public Map> bulkCompute(Set keys, Function>, Iterable>> remappingFunction) throws StoreAccessException { + public Map> bulkCompute(Set keys, Function>>, Iterable>> remappingFunction) throws StoreAccessException { // we are not expecting failures and these two maps are only used in case of failures. So keep them small Set successes = new HashSet<>(1); Map failures = new HashMap<>(1); @@ -347,16 +348,16 @@ private Map> getkValueHolderMap(Set keys) throws int[] actualRemoveCount = { 0 }; - Function>, Iterable>> removalFunction = + Function>>, Iterable>> removalFunction = entries -> { Set unknowns = cacheLoaderWriterDeleteAllCall(entries, entriesToRemove, deleteSuccesses, deleteFailures); int size = CollectionUtil.findBestCollectionSize(entries, 1); Map results = new LinkedHashMap<>(size); - for (Map.Entry entry : entries) { + for (Map.Entry> entry : entries) { K key = entry.getKey(); - V existingValue = entry.getValue(); + ValueHolder existingValue = entry.getValue(); if (deleteSuccesses.contains(key)) { if (existingValue != null) { @@ -368,7 +369,7 @@ private Map> getkValueHolderMap(Set keys) throws if (unknowns.contains(key)) { results.put(key, null); } else { - results.put(key, existingValue); + results.put(key, existingValue.get()); } } } @@ -393,7 +394,7 @@ private Map> getkValueHolderMap(Ehcache.PutAllFunction r // The compute function that will return the keys to their NEW values, taking the keys to their old values as input; // but this could happen in batches, i.e. not necessary containing all of the entries of the Iterable passed to this method - Function>, Iterable>> computeFunction = + Function>>, Iterable>> computeFunction = entries1 -> { // If we have a writer, first write this batch cacheLoaderWriterWriteAllCall(entries1, entriesToRemap, successes, failures); @@ -402,9 +403,9 @@ private Map> getkValueHolderMap(Ehcache.PutAllFunction r Map mutations = new LinkedHashMap<>(size); // then record we handled these mappings - for (Map.Entry entry : entries1) { + for (Map.Entry> entry : entries1) { K key = entry.getKey(); - V existingValue = entry.getValue(); + ValueHolder existingValue = entry.getValue(); V newValue = entriesToRemap.remove(key); if (newValueAlreadyExpired(LOG, expiry, key, existingValue, newValue)) { @@ -414,7 +415,7 @@ private Map> getkValueHolderMap(Ehcache.PutAllFunction r mutations.put(key, newValue); } else { - mutations.put(key, existingValue); + mutations.put(key, existingValue == null ? null : existingValue.get()); } } @@ -430,7 +431,7 @@ private Map> getkValueHolderMap(Ehcache.PutAllFunction r } @Override - public Map> bulkCompute(Set keys, Function>, Iterable>> remappingFunction, Supplier replaceEqual) throws StoreAccessException { + public Map> bulkCompute(Set keys, Function>>, Iterable>> remappingFunction, Supplier replaceEqual) throws StoreAccessException { return null; } @@ -494,27 +495,25 @@ public List getConfigurationChangeListeners() return delegate.getConfigurationChangeListeners(); } - private V loadFromLoaderWriter(K key, V inCache) { + private V loadFromLoaderWriter(K key, ValueHolder inCache) { if (inCache == null) { if (useLoaderInAtomics) { try { - inCache = cacheLoaderWriter.load(key); - if (inCache == null) { - return null; - } + return cacheLoaderWriter.load(key); } catch (Exception e) { throw new StorePassThroughException(newCacheLoadingException(e)); } } else { return null; } + } else { + return inCache.get(); } - return inCache; } - private void cacheLoaderWriterWriteAllCall(Iterable> entries, Map entriesToRemap, Set successes, Map failures) throws IllegalStateException { + private void cacheLoaderWriterWriteAllCall(Iterable>> entries, Map entriesToRemap, Set successes, Map failures) throws IllegalStateException { Map toWrite = new HashMap<>(); - for (Map.Entry entry: entries) { + for (Map.Entry> entry: entries) { V value = entriesToRemap.get(entry.getKey()); if (value == null) { continue; @@ -537,10 +536,10 @@ private void cacheLoaderWriterWriteAllCall(Iterable cacheLoaderWriterDeleteAllCall(Iterable> entries, Map entriesToRemove, Set successes, Map failures) { + private Set cacheLoaderWriterDeleteAllCall(Iterable>> entries, Map entriesToRemove, Set successes, Map failures) { Set unknowns = new HashSet<>(); Set toDelete = new HashSet<>(); - for (Map.Entry entry : entries) { + for (Map.Entry> entry : entries) { K key = entry.getKey(); if (entriesToRemove.containsKey(key)) { toDelete.add(key); @@ -573,7 +572,7 @@ private void collectSuccessesAndFailures(BulkCacheLoadingException bcle, Map)bcle.getFailures()); } - private static boolean newValueAlreadyExpired(Logger logger, ExpiryPolicy expiry, K key, V oldValue, V newValue) { + private static boolean newValueAlreadyExpired(Logger logger, ExpiryPolicy expiry, K key, Supplier oldValue, V newValue) { if (newValue == null) { return false; } @@ -583,7 +582,7 @@ private static boolean newValueAlreadyExpired(Logger logger, ExpiryPolicy if (oldValue == null) { duration = expiry.getExpiryForCreation(key, newValue); } else { - duration = expiry.getExpiryForUpdate(key, () -> oldValue, newValue); + duration = expiry.getExpiryForUpdate(key, oldValue, newValue); } } catch (RuntimeException re) { logger.error("Expiry computation caused an exception - Expiry duration will be 0 ", re); diff --git a/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java index fda2c6cb8a..3d6675b0c5 100644 --- a/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java +++ b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStore.java @@ -18,6 +18,7 @@ import java.io.Serializable; import java.time.Duration; +import java.util.AbstractMap; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -525,7 +526,7 @@ public ValueHolder getValue() { } @Override - public ValueHolder getAndCompute(K key, BiFunction mappingFunction) throws StoreAccessException { + public ValueHolder getAndCompute(K key, BiFunction, ? extends V> mappingFunction) throws StoreAccessException { checkKey(key); computeObserver.begin(); @@ -536,17 +537,15 @@ public ValueHolder getAndCompute(K key, BiFunction eventSink = eventDispatcher.eventSink(); BiFunction, OffHeapValueHolder> computeFunction = (mappedKey, mappedValue) -> { long now = timeSource.getTimeMillis(); - V existingValue = null; if (mappedValue == null || mappedValue.isExpired(now)) { if (mappedValue != null) { onExpiration(mappedKey, mappedValue, eventSink); } mappedValue = null; } else { - existingValue = mappedValue.get(); existingValueHolder.set(mappedValue); } - V computedValue = mappingFunction.apply(mappedKey, existingValue); + V computedValue = mappingFunction.apply(mappedKey, mappedValue); if (computedValue == null) { if (mappedValue != null) { write.set(true); @@ -594,7 +593,7 @@ public ValueHolder getAndCompute(K key, BiFunction computeAndGet(final K key, final BiFunction mappingFunction, final Supplier replaceEqual, Supplier invokeWriter) throws StoreAccessException { + public ValueHolder computeAndGet(final K key, final BiFunction, ? extends V> mappingFunction, final Supplier replaceEqual, Supplier invokeWriter) throws StoreAccessException { checkKey(key); computeObserver.begin(); @@ -604,23 +603,20 @@ public ValueHolder computeAndGet(final K key, final BiFunction eventSink = eventDispatcher.eventSink(); BiFunction, OffHeapValueHolder> computeFunction = (mappedKey, mappedValue) -> { long now = timeSource.getTimeMillis(); - V existingValue = null; if (mappedValue == null || mappedValue.isExpired(now)) { if (mappedValue != null) { onExpiration(mappedKey, mappedValue, eventSink); } mappedValue = null; - } else { - existingValue = mappedValue.get(); } - V computedValue = mappingFunction.apply(mappedKey, existingValue); + V computedValue = mappingFunction.apply(mappedKey, mappedValue); if (computedValue == null) { if (mappedValue != null) { write.set(true); eventSink.removed(mappedKey, mappedValue); } return null; - } else if (safeEquals(existingValue, computedValue) && !replaceEqual.get()) { + } else if (!replaceEqual.get() && safeEquals(mappedValue == null ? null : mappedValue.get(), computedValue)) { if (mappedValue != null) { OffHeapValueHolder valueHolder = setAccessTimeAndExpiryThenReturnMapping(mappedKey, mappedValue, now, eventSink); if (valueHolder == null) { @@ -752,34 +748,20 @@ private Store.ValueHolder internalComputeIfAbsent(final K key, final Function } @Override - public Map> bulkCompute(Set keys, Function>, Iterable>> remappingFunction) throws StoreAccessException { + public Map> bulkCompute(Set keys, Function>>, Iterable>> remappingFunction) throws StoreAccessException { return bulkCompute(keys, remappingFunction, REPLACE_EQUALS_TRUE); } @Override - public Map> bulkCompute(Set keys, final Function>, Iterable>> remappingFunction, Supplier replaceEqual) throws StoreAccessException { + public Map> bulkCompute(Set keys, final Function>>, Iterable>> remappingFunction, Supplier replaceEqual) throws StoreAccessException { Map> result = new HashMap<>(keys.size()); for (K key : keys) { checkKey(key); - BiFunction biFunction = (k, v) -> { - Map.Entry entry = new Map.Entry() { - @Override - public K getKey() { - return k; - } - - @Override - public V getValue() { - return v; - } - - @Override - public V setValue(V value) { - throw new UnsupportedOperationException(); - } - }; + BiFunction, V> biFunction = (k, v) -> { + Map.Entry> entry = new AbstractMap.SimpleImmutableEntry<>(k, v); java.util.Iterator> iterator = remappingFunction.apply(Collections .singleton(entry)).iterator(); + Map.Entry result1 = iterator.next(); if (result1 != null) { checkKey(result1.getKey()); diff --git a/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java index c814b54b0e..e3ed9dd957 100644 --- a/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java +++ b/ehcache-impl/src/main/java/org/ehcache/impl/internal/store/tiering/TieredStore.java @@ -302,7 +302,7 @@ public ValueHolder getValue() { } @Override - public ValueHolder getAndCompute(final K key, final BiFunction mappingFunction) throws StoreAccessException { + public ValueHolder getAndCompute(final K key, final BiFunction, ? extends V> mappingFunction) throws StoreAccessException { try { return authoritativeTier.getAndCompute(key, mappingFunction); } finally { @@ -311,7 +311,7 @@ public ValueHolder getAndCompute(final K key, final BiFunction computeAndGet(final K key, final BiFunction mappingFunction, final Supplier replaceEqual, Supplier invokeWriter) throws StoreAccessException { + public ValueHolder computeAndGet(final K key, final BiFunction, ? extends V> mappingFunction, final Supplier replaceEqual, Supplier invokeWriter) throws StoreAccessException { try { return authoritativeTier.computeAndGet(key, mappingFunction, replaceEqual, () -> false); } finally { @@ -334,7 +334,7 @@ public ValueHolder computeIfAbsent(final K key, final Function> bulkCompute(Set keys, Function>, Iterable>> remappingFunction) throws StoreAccessException { + public Map> bulkCompute(Set keys, Function>>, Iterable>> remappingFunction) throws StoreAccessException { try { return authoritativeTier.bulkCompute(keys, remappingFunction); } finally { @@ -345,7 +345,7 @@ public Map> bulkCompute(Set keys, Function> bulkCompute(Set keys, Function>, Iterable>> remappingFunction, Supplier replaceEqual) throws StoreAccessException { + public Map> bulkCompute(Set keys, Function>>, Iterable>> remappingFunction, Supplier replaceEqual) throws StoreAccessException { try { return authoritativeTier.bulkCompute(keys, remappingFunction, replaceEqual); } finally { diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/BaseOnHeapStoreTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/BaseOnHeapStoreTest.java index 51589f8839..595b9a3c60 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/BaseOnHeapStoreTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/BaseOnHeapStoreTest.java @@ -575,7 +575,7 @@ public void testComputeReplaceTrue() throws Exception { long accessTime = installedHolder.lastAccessTime(); timeSource.advanceTime(1); - ValueHolder newValue = store.computeAndGet("key", (mappedKey, mappedValue) -> mappedValue, () -> true, () -> false); + ValueHolder newValue = store.computeAndGet("key", (mappedKey, mappedValue) -> mappedValue.get(), () -> true, () -> false); assertThat(newValue.get(), equalTo("value")); assertThat(createTime + 1, equalTo(newValue.creationTime())); @@ -596,7 +596,7 @@ public void testComputeReplaceFalse() throws Exception { long accessTime = installedHolder.lastAccessTime(); timeSource.advanceTime(1); - ValueHolder newValue = store.computeAndGet("key", (mappedKey, mappedValue) -> mappedValue, () -> false, () -> false); + ValueHolder newValue = store.computeAndGet("key", (mappedKey, mappedValue) -> mappedValue.get(), () -> false, () -> false); assertThat(newValue.get(), equalTo("value")); assertThat(createTime, equalTo(newValue.creationTime())); @@ -672,7 +672,7 @@ public void testGetAndComputeExistingValue() throws Exception { ValueHolder oldValue = store.getAndCompute("key", (mappedKey, mappedValue) -> { assertThat(mappedKey, equalTo("key")); - assertThat(mappedValue, equalTo("value")); + assertThat(mappedValue.get(), equalTo("value")); return "value2"; }); @@ -731,7 +731,7 @@ public void testComputeWhenExpireOnAccess() throws Exception { OnHeapStore store = newStore(timeSource, expiry().access(Duration.ZERO).build()); store.put("key", "value"); - ValueHolder result = store.computeAndGet("key", (key, value) -> value, () -> false, () -> false); + ValueHolder result = store.computeAndGet("key", (key, value) -> value.get(), () -> false, () -> false); assertThat(result, valueHeld("value")); } diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java index b065a01694..33e3c3fd62 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreBulkMethodsTest.java @@ -84,8 +84,8 @@ public void testBulkComputeFunctionGetsValuesOfEntries() throws Exception { Map> result = store.bulkCompute(new HashSet(Arrays.asList(1, 2, 3, 4, 5, 6)), entries -> { Map newValues = new HashMap<>(); - for (Map.Entry entry : entries) { - final Number currentValue = entry.getValue(); + for (Map.Entry> entry : entries) { + final Store.ValueHolder currentValue = entry.getValue(); if(currentValue == null) { if(entry.getKey().equals(4)) { newValues.put(entry.getKey(), null); @@ -93,7 +93,7 @@ public void testBulkComputeFunctionGetsValuesOfEntries() throws Exception { newValues.put(entry.getKey(), 0); } } else { - newValues.put(entry.getKey(), currentValue.intValue() * 2); + newValues.put(entry.getKey(), currentValue.get().intValue() * 2); } } @@ -133,7 +133,7 @@ public void testBulkComputeHappyPath() throws Exception { Map> result = store.bulkCompute(new HashSet(Arrays.asList(1, 2)), entries -> { Map newValues = new HashMap<>(); - for (Map.Entry entry : entries) { + for (Map.Entry> entry : entries) { if(entry.getKey().intValue() == 1) { newValues.put(entry.getKey(), "un"); } else if (entry.getKey().intValue() == 2) { @@ -164,7 +164,7 @@ public void testBulkComputeStoreRemovesValueWhenFunctionReturnsNullMappings() th Map> result = store.bulkCompute(new HashSet(Arrays.asList(2, 1, 5)), entries -> { Map newValues = new HashMap<>(); - for (Map.Entry entry : entries) { + for (Map.Entry> entry : entries) { newValues.put(entry.getKey(), null); } return newValues.entrySet(); @@ -188,13 +188,13 @@ public void testBulkComputeRemoveNullValueEntriesFromFunctionReturn() throws Exc Map> result = store.bulkCompute(new HashSet(Arrays.asList(1, 2, 3)), entries -> { Map result1 = new HashMap<>(); - for (Map.Entry entry : entries) { + for (Map.Entry> entry : entries) { if (entry.getKey().equals(1)) { result1.put(entry.getKey(), null); } else if (entry.getKey().equals(3)) { result1.put(entry.getKey(), null); } else { - result1.put(entry.getKey(), entry.getValue()); + result1.put(entry.getKey(), entry.getValue().get()); } } return result1.entrySet(); diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java index fbe6a7b7da..6936fa9dd8 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreKeyCopierTest.java @@ -136,13 +136,13 @@ public void testCompute() throws StoreAccessException { if (copyForWrite) { assertThat(value, nullValue()); } else { - assertThat(value, is(VALUE)); + assertThat(value.get(), is(VALUE)); assertThat(key, is(copyKey)); if (copyForRead) { key.state = "Changed!"; } } - return value; + return value == null ? null : value.get(); }); if (copyForRead) { @@ -162,13 +162,13 @@ public void testComputeWithoutReplaceEqual() throws StoreAccessException { if (copyForWrite) { assertThat(value, nullValue()); } else { - assertThat(value, is(VALUE)); + assertThat(value.get(), is(VALUE)); assertThat(key, is(copyKey)); if (copyForRead) { key.state = "Changed!"; } } - return value; + return value == null ? null : value.get(); }, NOT_REPLACE_EQUAL, () -> false); if (copyForRead) { @@ -188,13 +188,13 @@ public void testComputeWithReplaceEqual() throws StoreAccessException { if (copyForWrite) { assertThat(value, nullValue()); } else { - assertThat(value, is(VALUE)); + assertThat(value.get(), is(VALUE)); assertThat(key, is(copyKey)); if (copyForRead) { key.state = "Changed!"; } } - return value; + return value == null ? null : value.get(); }, REPLACE_EQUAL, () -> false); if (copyForRead) { diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java index 27c649133b..f0676c4826 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/OnHeapStoreValueCopierTest.java @@ -37,9 +37,11 @@ import java.util.Collection; import java.util.Map; import java.util.function.Supplier; +import java.util.stream.StreamSupport; import static java.util.Collections.singleton; import static java.util.Collections.singletonMap; +import static java.util.stream.Collectors.toMap; import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -125,8 +127,8 @@ public void testGetAndCompute() throws StoreAccessException { Store.ValueHolder computedVal = store.getAndCompute(KEY, (aLong, value) -> VALUE); Store.ValueHolder oldValue = store.get(KEY); store.getAndCompute(KEY, (aLong, value) -> { - compareReadValues(value, oldValue.get()); - return value; + compareReadValues(value.get(), oldValue.get()); + return value.get(); }); compareValues(VALUE, computedVal.get()); @@ -136,8 +138,8 @@ public void testGetAndCompute() throws StoreAccessException { public void testComputeWithoutReplaceEqual() throws StoreAccessException { final Store.ValueHolder firstValue = store.computeAndGet(KEY, (aLong, value) -> VALUE, NOT_REPLACE_EQUAL, () -> false); store.computeAndGet(KEY, (aLong, value) -> { - compareReadValues(value, firstValue.get()); - return value; + compareReadValues(value.get(), firstValue.get()); + return value.get(); }, NOT_REPLACE_EQUAL, () -> false); compareValues(VALUE, firstValue.get()); @@ -147,8 +149,8 @@ public void testComputeWithoutReplaceEqual() throws StoreAccessException { public void testComputeWithReplaceEqual() throws StoreAccessException { final Store.ValueHolder firstValue = store.computeAndGet(KEY, (aLong, value) -> VALUE, REPLACE_EQUAL, () -> false); store.computeAndGet(KEY, (aLong, value) -> { - compareReadValues(value, firstValue.get()); - return value; + compareReadValues(value.get(), firstValue.get()); + return value.get(); }, REPLACE_EQUAL, () -> false); compareValues(VALUE, firstValue.get()); @@ -169,8 +171,8 @@ public void testComputeIfAbsent() throws StoreAccessException { public void testBulkCompute() throws StoreAccessException { final Map> results = store.bulkCompute(singleton(KEY), entries -> singletonMap(KEY, VALUE).entrySet()); store.bulkCompute(singleton(KEY), entries -> { - compareReadValues(results.get(KEY).get(), entries.iterator().next().getValue()); - return entries; + compareReadValues(results.get(KEY).get(), entries.iterator().next().getValue().get()); + return StreamSupport.stream(entries.spliterator(), false).collect(toMap(e -> e.getKey(), e -> e.getValue().get())).entrySet(); }); compareValues(VALUE, results.get(KEY).get()); } @@ -179,8 +181,8 @@ public void testBulkCompute() throws StoreAccessException { public void testBulkComputeWithoutReplaceEqual() throws StoreAccessException { final Map> results = store.bulkCompute(singleton(KEY), entries -> singletonMap(KEY, VALUE).entrySet(), NOT_REPLACE_EQUAL); store.bulkCompute(singleton(KEY), entries -> { - compareReadValues(results.get(KEY).get(), entries.iterator().next().getValue()); - return entries; + compareReadValues(results.get(KEY).get(), entries.iterator().next().getValue().get()); + return StreamSupport.stream(entries.spliterator(), false).collect(toMap(e -> e.getKey(), e -> e.getValue().get())).entrySet(); }, NOT_REPLACE_EQUAL); compareValues(VALUE, results.get(KEY).get()); } @@ -189,8 +191,8 @@ public void testBulkComputeWithoutReplaceEqual() throws StoreAccessException { public void testBulkComputeWithReplaceEqual() throws StoreAccessException { final Map> results = store.bulkCompute(singleton(KEY), entries -> singletonMap(KEY, VALUE).entrySet(), REPLACE_EQUAL); store.bulkCompute(singleton(KEY), entries -> { - compareReadValues(results.get(KEY).get(), entries.iterator().next().getValue()); - return entries; + compareReadValues(results.get(KEY).get(), entries.iterator().next().getValue().get()); + return StreamSupport.stream(entries.spliterator(), false).collect(toMap(e -> e.getKey(), e -> e.getValue().get())).entrySet(); }, REPLACE_EQUAL); compareValues(VALUE, results.get(KEY).get()); } diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteAccountingTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteAccountingTest.java index a8606d372e..4782293b72 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteAccountingTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/ByteAccountingTest.java @@ -435,7 +435,7 @@ public void testComputeExpiryOnAccess() throws StoreAccessException { OnHeapStoreForTests store = newStore(timeSource, expiry().access(Duration.ZERO).build()); store.put(KEY, VALUE); - store.computeAndGet(KEY, (s, s2) -> s2, () -> false, () -> false); + store.computeAndGet(KEY, (s, s2) -> s2.get(), () -> false, () -> false); assertThat(store.getCurrentUsageInBytes(), is(0L)); } @@ -446,7 +446,7 @@ public void testGetAndComputeExpiryOnUpdate() throws StoreAccessException { OnHeapStoreForTests store = newStore(timeSource, expiry().update(Duration.ZERO).build()); store.put(KEY, VALUE); - store.getAndCompute(KEY, (s, s2) -> s2); + store.getAndCompute(KEY, (s, s2) -> s2.get()); assertThat(store.getCurrentUsageInBytes(), is(0L)); } diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java index ee820d73ff..8537234c85 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/heap/bytesized/OnHeapStoreBulkMethodsTest.java @@ -91,8 +91,8 @@ public void testBulkComputeFunctionGetsValuesOfEntries() throws Exception { Map> result = store.bulkCompute(new HashSet(Arrays.asList(1, 2, 3, 4, 5, 6)), entries -> { Map newValues = new HashMap<>(); - for (Map.Entry entry : entries) { - final Number currentValue = entry.getValue(); + for (Map.Entry> entry : entries) { + final Store.ValueHolder currentValue = entry.getValue(); if(currentValue == null) { if(entry.getKey().equals(4)) { newValues.put(entry.getKey(), null); @@ -100,7 +100,7 @@ public void testBulkComputeFunctionGetsValuesOfEntries() throws Exception { newValues.put(entry.getKey(), 0); } } else { - newValues.put(entry.getKey(), currentValue.intValue() * 2); + newValues.put(entry.getKey(), currentValue.get().intValue() * 2); } } diff --git a/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java index bc04a52acb..46902d2019 100644 --- a/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java +++ b/ehcache-impl/src/test/java/org/ehcache/impl/internal/store/offheap/AbstractOffHeapStoreTest.java @@ -376,7 +376,7 @@ public void testComputeExpiresOnAccess() throws StoreAccessException { expiry().access(Duration.ZERO).update(Duration.ZERO).build()); offHeapStore.put("key", "value"); - Store.ValueHolder result = offHeapStore.computeAndGet("key", (s, s2) -> s2, () -> false, () -> false); + Store.ValueHolder result = offHeapStore.computeAndGet("key", (s, s2) -> s2.get(), () -> false, () -> false); assertThat(result, valueHeld("value")); } diff --git a/ehcache-transactions/src/common/java/org/ehcache/transactions/xa/internal/XATransactionContext.java b/ehcache-transactions/src/common/java/org/ehcache/transactions/xa/internal/XATransactionContext.java index dfe0408795..96ab432ac5 100644 --- a/ehcache-transactions/src/common/java/org/ehcache/transactions/xa/internal/XATransactionContext.java +++ b/ehcache-transactions/src/common/java/org/ehcache/transactions/xa/internal/XATransactionContext.java @@ -120,12 +120,6 @@ public XAValueHolder newValueHolderOf(K key) { return command != null ? command.getNewValueHolder() : null; } - public V newValueOf(K key) { - Command command = commands.get(key); - XAValueHolder valueHolder = command == null ? null : command.getNewValueHolder(); - return valueHolder == null ? null : valueHolder.get(); - } - public int prepare() throws StoreAccessException, IllegalStateException, TransactionTimeoutException { try { if (hasTimedOut()) { diff --git a/ehcache-transactions/src/jakarta/java/org/ehcache/transactions/xa/internal/XAStore.java b/ehcache-transactions/src/jakarta/java/org/ehcache/transactions/xa/internal/XAStore.java index ae145f9592..560991a2d3 100644 --- a/ehcache-transactions/src/jakarta/java/org/ehcache/transactions/xa/internal/XAStore.java +++ b/ehcache-transactions/src/jakarta/java/org/ehcache/transactions/xa/internal/XAStore.java @@ -22,41 +22,41 @@ import jakarta.transaction.Transaction; import jakarta.transaction.TransactionManager; import org.ehcache.Cache; -import org.ehcache.config.EvictionAdvisor; import org.ehcache.config.ResourceType; import org.ehcache.core.CacheConfigurationChangeListener; -import org.ehcache.core.collections.ConcurrentWeakIdentityHashMap; +import org.ehcache.config.EvictionAdvisor; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.core.spi.service.StatisticsService; -import org.ehcache.core.spi.store.Store; import org.ehcache.core.spi.store.WrapperStore; -import org.ehcache.core.spi.store.events.StoreEventSource; -import org.ehcache.core.spi.time.TimeSource; -import org.ehcache.core.spi.time.TimeSourceService; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.core.store.StoreSupport; +import org.ehcache.impl.store.BaseStore; +import org.ehcache.spi.resilience.StoreAccessException; import org.ehcache.expiry.ExpiryPolicy; import org.ehcache.impl.config.copy.DefaultCopierConfiguration; import org.ehcache.impl.copy.SerializingCopier; -import org.ehcache.impl.store.BaseStore; -import org.ehcache.spi.copy.Copier; -import org.ehcache.spi.copy.CopyProvider; -import org.ehcache.spi.resilience.StoreAccessException; +import org.ehcache.core.spi.time.TimeSource; +import org.ehcache.core.spi.time.TimeSourceService; import org.ehcache.spi.serialization.StatefulSerializer; import org.ehcache.spi.service.OptionalServiceDependencies; +import org.ehcache.spi.service.ServiceProvider; +import org.ehcache.core.spi.store.Store; +import org.ehcache.core.spi.store.events.StoreEventSource; +import org.ehcache.spi.copy.Copier; +import org.ehcache.spi.copy.CopyProvider; import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceConfiguration; import org.ehcache.spi.service.ServiceDependencies; -import org.ehcache.spi.service.ServiceProvider; import org.ehcache.transactions.xa.XACacheException; -import org.ehcache.transactions.xa.configuration.XAStoreConfiguration; import org.ehcache.transactions.xa.internal.commands.StoreEvictCommand; import org.ehcache.transactions.xa.internal.commands.StorePutCommand; import org.ehcache.transactions.xa.internal.commands.StoreRemoveCommand; +import org.ehcache.transactions.xa.configuration.XAStoreConfiguration; import org.ehcache.transactions.xa.internal.journal.Journal; import org.ehcache.transactions.xa.internal.journal.JournalProvider; import org.ehcache.transactions.xa.txmgr.TransactionManagerWrapper; import org.ehcache.transactions.xa.txmgr.provider.TransactionManagerProvider; +import org.ehcache.core.collections.ConcurrentWeakIdentityHashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -236,7 +236,7 @@ public boolean remove(K key) throws StoreAccessException { XATransactionContext currentContext = getCurrentContext(); if (currentContext.touched(key)) { V oldValue = currentContext.oldValueOf(key); - V newValue = currentContext.newValueOf(key); + ValueHolder newValue = currentContext.newValueHolderOf(key); currentContext.addCommand(key, new StoreRemoveCommand<>(oldValue)); return newValue != null; } @@ -261,7 +261,7 @@ public ValueHolder putIfAbsent(K key, V value, Consumer put) throws XATransactionContext currentContext = getCurrentContext(); if (currentContext.touched(key)) { V oldValue = currentContext.oldValueOf(key); - V newValue = currentContext.newValueOf(key); + ValueHolder newValue = currentContext.newValueHolderOf(key); if (newValue == null) { currentContext.addCommand(key, new StorePutCommand<>(oldValue, new XAValueHolder<>(value, timeSource.getTimeMillis()))); return null; @@ -292,10 +292,10 @@ public RemoveStatus remove(K key, V value) throws StoreAccessException { XATransactionContext currentContext = getCurrentContext(); if (currentContext.touched(key)) { V oldValue = currentContext.oldValueOf(key); - V newValue = currentContext.newValueOf(key); + ValueHolder newValue = currentContext.newValueHolderOf(key); if (newValue == null) { return RemoveStatus.KEY_MISSING; - } else if (!newValue.equals(value)) { + } else if (!newValue.get().equals(value)) { return RemoveStatus.KEY_PRESENT; } else { currentContext.addCommand(key, new StoreRemoveCommand<>(oldValue)); @@ -326,7 +326,7 @@ public ValueHolder replace(K key, V value) throws StoreAccessException { checkValue(value); XATransactionContext currentContext = getCurrentContext(); if (currentContext.touched(key)) { - V newValue = currentContext.newValueOf(key); + ValueHolder newValue = currentContext.newValueHolderOf(key); if (newValue == null) { return null; } else { @@ -360,10 +360,10 @@ public ReplaceStatus replace(K key, V oldValue, V newValue) throws StoreAccessEx checkValue(newValue); XATransactionContext currentContext = getCurrentContext(); if (currentContext.touched(key)) { - V modifiedValue = currentContext.newValueOf(key); + ValueHolder modifiedValue = currentContext.newValueHolderOf(key); if (modifiedValue == null) { return ReplaceStatus.MISS_NOT_PRESENT; - } else if (!modifiedValue.equals(oldValue)) { + } else if (!modifiedValue.get().equals(oldValue)) { return ReplaceStatus.MISS_PRESENT; } else { V previousValue = currentContext.oldValueOf(key); @@ -511,7 +511,7 @@ public Cache.Entry> next() throws StoreAccessException { } @Override - public ValueHolder computeAndGet(K key, BiFunction mappingFunction, Supplier replaceEqual, Supplier invokeWriter) throws StoreAccessException { + public ValueHolder computeAndGet(K key, BiFunction, ? extends V> mappingFunction, Supplier replaceEqual, Supplier invokeWriter) throws StoreAccessException { checkKey(key); XATransactionContext currentContext = getCurrentContext(); if (currentContext.touched(key)) { @@ -522,9 +522,9 @@ public ValueHolder computeAndGet(K key, BiFunction softLock = softLockValueHolder == null ? null : softLockValueHolder.get(); V oldValue = softLock == null ? null : softLock.getOldValue(); - V newValue = mappingFunction.apply(key, oldValue); + V newValue = mappingFunction.apply(key, oldValue == null ? null : new XAValueHolder(oldValue, softLockValueHolder.creationTime())); XAValueHolder xaValueHolder = newValue == null ? null : new XAValueHolder<>(newValue, timeSource.getTimeMillis()); - if (Objects.equals(oldValue, newValue) && !replaceEqual.get()) { + if (!replaceEqual.get() && Objects.equals(oldValue, newValue)) { return xaValueHolder; } if (newValue != null) { @@ -547,26 +547,26 @@ public ValueHolder computeAndGet(K key, BiFunction getAndCompute(K key, BiFunction mappingFunction) throws StoreAccessException { + public ValueHolder getAndCompute(K key, BiFunction, ? extends V> mappingFunction) throws StoreAccessException { checkKey(key); XATransactionContext currentContext = getCurrentContext(); if (currentContext.touched(key)) { - V computed = mappingFunction.apply(key, currentContext.newValueOf(key)); + V computed = mappingFunction.apply(key, currentContext.newValueHolderOf(key)); XAValueHolder returnValueholder = null; if (computed != null) { checkValue(computed); XAValueHolder xaValueHolder = new XAValueHolder<>(computed, timeSource.getTimeMillis()); - V returnValue = currentContext.newValueOf(key); + ValueHolder returnValue = currentContext.newValueHolderOf(key); V oldValue = currentContext.oldValueOf(key); if (returnValue != null) { - returnValueholder = new XAValueHolder<>(returnValue, timeSource.getTimeMillis()); + returnValueholder = new XAValueHolder<>(returnValue.get(), timeSource.getTimeMillis()); } currentContext.addCommand(key, new StorePutCommand<>(oldValue, xaValueHolder)); } else { - V returnValue = currentContext.newValueOf(key); + ValueHolder returnValue = currentContext.newValueHolderOf(key); V oldValue = currentContext.oldValueOf(key); if (returnValue != null) { - returnValueholder = new XAValueHolder<>(returnValue, timeSource.getTimeMillis()); + returnValueholder = new XAValueHolder<>(returnValue.get(), timeSource.getTimeMillis()); } if (oldValue != null) { currentContext.addCommand(key, new StoreRemoveCommand<>(oldValue)); @@ -582,7 +582,7 @@ public ValueHolder getAndCompute(K key, BiFunction oldValueHolder = null; SoftLock softLock = softLockValueHolder == null ? null : softLockValueHolder.get(); V oldValue = softLock == null ? null : softLock.getOldValue(); - V newValue = mappingFunction.apply(key, oldValue); + V newValue = mappingFunction.apply(key, oldValue == null ? null : new XAValueHolder(oldValue, softLockValueHolder.creationTime())); XAValueHolder xaValueHolder = newValue == null ? null : new XAValueHolder<>(newValue, timeSource.getTimeMillis()); if (newValue != null) { checkValue(newValue); @@ -647,8 +647,8 @@ public ValueHolder computeIfAbsent(K key, final Function updateCommandForKey(K key, BiFunction mappingFunction, Supplier replaceEqual, XATransactionContext currentContext) { - V newValue = mappingFunction.apply(key, currentContext.newValueOf(key)); + private ValueHolder updateCommandForKey(K key, BiFunction, ? extends V> mappingFunction, Supplier replaceEqual, XATransactionContext currentContext) { + V newValue = mappingFunction.apply(key, currentContext.newValueHolderOf(key)); XAValueHolder xaValueHolder = null; V oldValue = currentContext.oldValueOf(key); if (newValue == null) { @@ -680,18 +680,18 @@ private ValueHolder updateCommandForKey(K key, Function> bulkCompute(Set keys, Function>, Iterable>> remappingFunction) throws StoreAccessException { + public Map> bulkCompute(Set keys, Function>>, Iterable>> remappingFunction) throws StoreAccessException { return bulkCompute(keys, remappingFunction, REPLACE_EQUALS_TRUE); } @Override - public Map> bulkCompute(Set keys, final Function>, Iterable>> remappingFunction, Supplier replaceEqual) throws StoreAccessException { + public Map> bulkCompute(Set keys, final Function>>, Iterable>> remappingFunction, Supplier replaceEqual) throws StoreAccessException { Map> result = new HashMap<>(); for (K key : keys) { checkKey(key); final ValueHolder newValue = computeAndGet(key, (k, oldValue) -> { - final Set> entrySet = Collections.singletonMap(k, oldValue).entrySet(); + final Set>> entrySet = Collections.singletonMap(k, oldValue).entrySet(); final Iterable> entries = remappingFunction.apply(entrySet); final java.util.Iterator> iterator = entries.iterator(); final Map.Entry next = iterator.next(); @@ -793,7 +793,7 @@ public Store createStore(Configuration storeConfig, ServiceCo List> serviceConfigList = Arrays.asList(serviceConfigs); Store.Provider underlyingStoreProvider = StoreSupport.selectStoreProvider(serviceProvider, - storeConfig.getResourcePools().getResourceTypeSet(), serviceConfigList); + storeConfig.getResourcePools().getResourceTypeSet(), serviceConfigList); String uniqueXAResourceId = xaServiceConfiguration.getUniqueXAResourceId(); List> underlyingServiceConfigs = new ArrayList<>(serviceConfigList.size() + 5); // pad a bit because we add stuff @@ -868,7 +868,7 @@ public Duration getExpiryForUpdate(K key, Supplier> oldSof } else { // there is an old value -> it's an UPDATE, update -> some time V value = oldSoftLock.getNewValueHolder() == null ? null : oldSoftLock - .getNewValueHolder().get(); + .getNewValueHolder().get(); Duration duration; try { duration = configuredExpiry.getExpiryForUpdate(key, oldSoftLock::getOldValue, value); @@ -923,16 +923,16 @@ public Duration getExpiryForUpdate(K key, Supplier> oldSof AtomicReference> softLockSerializerRef = new AtomicReference<>(); SoftLockValueCombinedSerializer softLockValueCombinedSerializer; if (storeConfig.getValueSerializer() instanceof StatefulSerializer) { - softLockValueCombinedSerializer = new StatefulSoftLockValueCombinedSerializer<>(softLockSerializerRef, storeConfig + softLockValueCombinedSerializer = new StatefulSoftLockValueCombinedSerializer(softLockSerializerRef, storeConfig .getValueSerializer()); } else { - softLockValueCombinedSerializer = new SoftLockValueCombinedSerializer<>(softLockSerializerRef, storeConfig + softLockValueCombinedSerializer = new SoftLockValueCombinedSerializer(softLockSerializerRef, storeConfig .getValueSerializer()); } // create the underlying store Class> softLockClass = uncheckedCast(SoftLock.class); - Configuration> underlyingStoreConfig = new StoreConfigurationImpl<>(storeConfig.getKeyType(), softLockClass, evictionAdvisor, + Store.Configuration> underlyingStoreConfig = new StoreConfigurationImpl<>(storeConfig.getKeyType(), softLockClass, evictionAdvisor, storeConfig.getClassLoader(), expiry, storeConfig.getResourcePools(), storeConfig.getDispatcherConcurrency(), storeConfig .getKeySerializer(), softLockValueCombinedSerializer); Store> underlyingStore = underlyingStoreProvider.createStore(underlyingStoreConfig, underlyingServiceConfigs.toArray(new ServiceConfiguration[0])); @@ -949,7 +949,7 @@ public Duration getExpiryForUpdate(K key, Supplier> oldSof // create the softLockSerializer lifecycle helper SoftLockValueCombinedSerializerLifecycleHelper helper = - new SoftLockValueCombinedSerializerLifecycleHelper<>(softLockSerializerRef, storeConfig.getClassLoader()); + new SoftLockValueCombinedSerializerLifecycleHelper(softLockSerializerRef, storeConfig.getClassLoader()); createdStores.put(store, new CreatedStoreRef(underlyingStoreProvider, helper)); return store; diff --git a/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java index 21dd1acd09..12595de8b8 100644 --- a/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java +++ b/ehcache-transactions/src/main/java/org/ehcache/transactions/xa/internal/XAStore.java @@ -22,6 +22,7 @@ import org.ehcache.config.EvictionAdvisor; import org.ehcache.core.spi.service.DiskResourceService; import org.ehcache.core.spi.service.StatisticsService; +import org.ehcache.core.spi.store.AbstractValueHolder; import org.ehcache.core.spi.store.WrapperStore; import org.ehcache.core.store.StoreConfigurationImpl; import org.ehcache.core.store.StoreSupport; @@ -75,6 +76,7 @@ import java.util.function.Function; import java.util.function.Supplier; +import javax.annotation.Nonnull; import javax.transaction.RollbackException; import javax.transaction.Synchronization; import javax.transaction.SystemException; @@ -237,7 +239,7 @@ public boolean remove(K key) throws StoreAccessException { XATransactionContext currentContext = getCurrentContext(); if (currentContext.touched(key)) { V oldValue = currentContext.oldValueOf(key); - V newValue = currentContext.newValueOf(key); + ValueHolder newValue = currentContext.newValueHolderOf(key); currentContext.addCommand(key, new StoreRemoveCommand<>(oldValue)); return newValue != null; } @@ -262,7 +264,7 @@ public ValueHolder putIfAbsent(K key, V value, Consumer put) throws XATransactionContext currentContext = getCurrentContext(); if (currentContext.touched(key)) { V oldValue = currentContext.oldValueOf(key); - V newValue = currentContext.newValueOf(key); + ValueHolder newValue = currentContext.newValueHolderOf(key); if (newValue == null) { currentContext.addCommand(key, new StorePutCommand<>(oldValue, new XAValueHolder<>(value, timeSource.getTimeMillis()))); return null; @@ -293,10 +295,10 @@ public RemoveStatus remove(K key, V value) throws StoreAccessException { XATransactionContext currentContext = getCurrentContext(); if (currentContext.touched(key)) { V oldValue = currentContext.oldValueOf(key); - V newValue = currentContext.newValueOf(key); + ValueHolder newValue = currentContext.newValueHolderOf(key); if (newValue == null) { return RemoveStatus.KEY_MISSING; - } else if (!newValue.equals(value)) { + } else if (!newValue.get().equals(value)) { return RemoveStatus.KEY_PRESENT; } else { currentContext.addCommand(key, new StoreRemoveCommand<>(oldValue)); @@ -327,7 +329,7 @@ public ValueHolder replace(K key, V value) throws StoreAccessException { checkValue(value); XATransactionContext currentContext = getCurrentContext(); if (currentContext.touched(key)) { - V newValue = currentContext.newValueOf(key); + ValueHolder newValue = currentContext.newValueHolderOf(key); if (newValue == null) { return null; } else { @@ -361,10 +363,10 @@ public ReplaceStatus replace(K key, V oldValue, V newValue) throws StoreAccessEx checkValue(newValue); XATransactionContext currentContext = getCurrentContext(); if (currentContext.touched(key)) { - V modifiedValue = currentContext.newValueOf(key); + ValueHolder modifiedValue = currentContext.newValueHolderOf(key); if (modifiedValue == null) { return ReplaceStatus.MISS_NOT_PRESENT; - } else if (!modifiedValue.equals(oldValue)) { + } else if (!modifiedValue.get().equals(oldValue)) { return ReplaceStatus.MISS_PRESENT; } else { V previousValue = currentContext.oldValueOf(key); @@ -512,7 +514,7 @@ public Cache.Entry> next() throws StoreAccessException { } @Override - public ValueHolder computeAndGet(K key, BiFunction mappingFunction, Supplier replaceEqual, Supplier invokeWriter) throws StoreAccessException { + public ValueHolder computeAndGet(K key, BiFunction, ? extends V> mappingFunction, Supplier replaceEqual, Supplier invokeWriter) throws StoreAccessException { checkKey(key); XATransactionContext currentContext = getCurrentContext(); if (currentContext.touched(key)) { @@ -523,9 +525,9 @@ public ValueHolder computeAndGet(K key, BiFunction softLock = softLockValueHolder == null ? null : softLockValueHolder.get(); V oldValue = softLock == null ? null : softLock.getOldValue(); - V newValue = mappingFunction.apply(key, oldValue); + V newValue = mappingFunction.apply(key, oldValue == null ? null : new XAValueHolder(oldValue, softLockValueHolder.creationTime())); XAValueHolder xaValueHolder = newValue == null ? null : new XAValueHolder<>(newValue, timeSource.getTimeMillis()); - if (Objects.equals(oldValue, newValue) && !replaceEqual.get()) { + if (!replaceEqual.get() && Objects.equals(oldValue, newValue)) { return xaValueHolder; } if (newValue != null) { @@ -548,26 +550,26 @@ public ValueHolder computeAndGet(K key, BiFunction getAndCompute(K key, BiFunction mappingFunction) throws StoreAccessException { + public ValueHolder getAndCompute(K key, BiFunction, ? extends V> mappingFunction) throws StoreAccessException { checkKey(key); XATransactionContext currentContext = getCurrentContext(); if (currentContext.touched(key)) { - V computed = mappingFunction.apply(key, currentContext.newValueOf(key)); + V computed = mappingFunction.apply(key, currentContext.newValueHolderOf(key)); XAValueHolder returnValueholder = null; if (computed != null) { checkValue(computed); XAValueHolder xaValueHolder = new XAValueHolder<>(computed, timeSource.getTimeMillis()); - V returnValue = currentContext.newValueOf(key); + ValueHolder returnValue = currentContext.newValueHolderOf(key); V oldValue = currentContext.oldValueOf(key); if (returnValue != null) { - returnValueholder = new XAValueHolder<>(returnValue, timeSource.getTimeMillis()); + returnValueholder = new XAValueHolder<>(returnValue.get(), timeSource.getTimeMillis()); } currentContext.addCommand(key, new StorePutCommand<>(oldValue, xaValueHolder)); } else { - V returnValue = currentContext.newValueOf(key); + ValueHolder returnValue = currentContext.newValueHolderOf(key); V oldValue = currentContext.oldValueOf(key); if (returnValue != null) { - returnValueholder = new XAValueHolder<>(returnValue, timeSource.getTimeMillis()); + returnValueholder = new XAValueHolder<>(returnValue.get(), timeSource.getTimeMillis()); } if (oldValue != null) { currentContext.addCommand(key, new StoreRemoveCommand<>(oldValue)); @@ -583,7 +585,7 @@ public ValueHolder getAndCompute(K key, BiFunction oldValueHolder = null; SoftLock softLock = softLockValueHolder == null ? null : softLockValueHolder.get(); V oldValue = softLock == null ? null : softLock.getOldValue(); - V newValue = mappingFunction.apply(key, oldValue); + V newValue = mappingFunction.apply(key, oldValue == null ? null : new XAValueHolder(oldValue, softLockValueHolder.creationTime())); XAValueHolder xaValueHolder = newValue == null ? null : new XAValueHolder<>(newValue, timeSource.getTimeMillis()); if (newValue != null) { checkValue(newValue); @@ -648,8 +650,8 @@ public ValueHolder computeIfAbsent(K key, final Function updateCommandForKey(K key, BiFunction mappingFunction, Supplier replaceEqual, XATransactionContext currentContext) { - V newValue = mappingFunction.apply(key, currentContext.newValueOf(key)); + private ValueHolder updateCommandForKey(K key, BiFunction, ? extends V> mappingFunction, Supplier replaceEqual, XATransactionContext currentContext) { + V newValue = mappingFunction.apply(key, currentContext.newValueHolderOf(key)); XAValueHolder xaValueHolder = null; V oldValue = currentContext.oldValueOf(key); if (newValue == null) { @@ -681,18 +683,18 @@ private ValueHolder updateCommandForKey(K key, Function> bulkCompute(Set keys, Function>, Iterable>> remappingFunction) throws StoreAccessException { + public Map> bulkCompute(Set keys, Function>>, Iterable>> remappingFunction) throws StoreAccessException { return bulkCompute(keys, remappingFunction, REPLACE_EQUALS_TRUE); } @Override - public Map> bulkCompute(Set keys, final Function>, Iterable>> remappingFunction, Supplier replaceEqual) throws StoreAccessException { + public Map> bulkCompute(Set keys, final Function>>, Iterable>> remappingFunction, Supplier replaceEqual) throws StoreAccessException { Map> result = new HashMap<>(); for (K key : keys) { checkKey(key); final ValueHolder newValue = computeAndGet(key, (k, oldValue) -> { - final Set> entrySet = Collections.singletonMap(k, oldValue).entrySet(); + final Set>> entrySet = Collections.singletonMap(k, oldValue).entrySet(); final Iterable> entries = remappingFunction.apply(entrySet); final java.util.Iterator> iterator = entries.iterator(); final Map.Entry next = iterator.next(); diff --git a/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java index 896ee04a57..1cf64d29da 100644 --- a/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java +++ b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/XAStoreTest.java @@ -710,14 +710,14 @@ public void testGetAndCompute() throws Exception { assertThat(xaStore.get(1L).get(), equalTo("one")); Store.ValueHolder computed2 = xaStore.getAndCompute(1L, (aLong, s) -> { assertThat(aLong, is(1L)); - assertThat(s, equalTo("one")); + assertThat(s.get(), equalTo("one")); return "un"; }); assertThat(computed2.get(), equalTo("one")); assertThat(xaStore.get(1L).get(), equalTo("un")); Store.ValueHolder computed3 = xaStore.getAndCompute(1L, (aLong, s) -> { assertThat(aLong, is(1L)); - assertThat(s, equalTo("un")); + assertThat(s.get(), equalTo("un")); return null; }); assertThat(computed3.get(), equalTo("un")); @@ -738,7 +738,7 @@ public void testGetAndCompute() throws Exception { assertThat(xaStore.get(1L).get(), equalTo("one")); Store.ValueHolder computed2 = xaStore.getAndCompute(1L, (aLong, s) -> { assertThat(aLong, is(1L)); - assertThat(s, equalTo("one")); + assertThat(s.get(), equalTo("one")); return null; }); assertThat(computed2.get(), equalTo("one")); @@ -759,7 +759,7 @@ public void testGetAndCompute() throws Exception { assertThat(xaStore.get(1L).get(), equalTo("one")); Store.ValueHolder computed2 = xaStore.getAndCompute(1L, (aLong, s) -> { assertThat(aLong, is(1L)); - assertThat(s, equalTo("one")); + assertThat(s.get(), equalTo("one")); return null; }); assertThat(computed2.get(), equalTo("one")); @@ -780,7 +780,7 @@ public void testGetAndCompute() throws Exception { assertThat(xaStore.get(1L).get(), equalTo("one")); Store.ValueHolder computed2 = xaStore.getAndCompute(1L, (aLong, s) -> { assertThat(aLong, is(1L)); - assertThat(s, equalTo("one")); + assertThat(s.get(), equalTo("one")); return "un"; }); assertThat(computed2.get(), equalTo("one")); @@ -794,7 +794,7 @@ public void testGetAndCompute() throws Exception { { Store.ValueHolder computed = xaStore.getAndCompute(1L, (aLong, s) -> { assertThat(aLong, is(1L)); - assertThat(s, equalTo("un")); + assertThat(s.get(), equalTo("un")); return "eins"; }); assertThat(computed.get(), equalTo("un")); @@ -808,7 +808,7 @@ public void testGetAndCompute() throws Exception { { Store.ValueHolder computed = xaStore.getAndCompute(1L, (aLong, s) -> { assertThat(aLong, is(1L)); - assertThat(s, equalTo("eins")); + assertThat(s.get(), equalTo("eins")); return null; }); assertThat(computed.get(), equalTo("eins")); @@ -822,7 +822,7 @@ public void testGetAndCompute() throws Exception { { Store.ValueHolder computed1 = xaStore.getAndCompute(1L, (aLong, s) -> { assertThat(aLong, is(1L)); - assertThat(s, equalTo("eins")); + assertThat(s.get(), equalTo("eins")); return null; }); assertThat(computed1.get(), equalTo("eins")); @@ -899,13 +899,13 @@ public void testCompute() throws Exception { assertThat(computed1.get(), equalTo("one")); Store.ValueHolder computed2 = xaStore.computeAndGet(1L, (aLong, s) -> { assertThat(aLong, is(1L)); - assertThat(s, equalTo("one")); + assertThat(s.get(), equalTo("one")); return "un"; }, SUPPLY_TRUE, SUPPLY_FALSE); assertThat(computed2.get(), equalTo("un")); Store.ValueHolder computed3 = xaStore.computeAndGet(1L, (aLong, s) -> { assertThat(aLong, is(1L)); - assertThat(s, equalTo("un")); + assertThat(s.get(), equalTo("un")); return null; }, SUPPLY_TRUE, SUPPLY_FALSE); assertThat(computed3, is(nullValue())); @@ -924,7 +924,7 @@ public void testCompute() throws Exception { assertThat(computed1.get(), equalTo("one")); Store.ValueHolder computed2 = xaStore.computeAndGet(1L, (aLong, s) -> { assertThat(aLong, is(1L)); - assertThat(s, equalTo("one")); + assertThat(s.get(), equalTo("one")); return null; }, SUPPLY_FALSE, SUPPLY_FALSE); assertThat(computed2, is(nullValue())); @@ -943,7 +943,7 @@ public void testCompute() throws Exception { assertThat(computed1.get(), equalTo("one")); Store.ValueHolder computed2 = xaStore.computeAndGet(1L, (aLong, s) -> { assertThat(aLong, is(1L)); - assertThat(s, equalTo("one")); + assertThat(s.get(), equalTo("one")); return null; }, SUPPLY_TRUE, SUPPLY_FALSE); assertThat(computed2, is(nullValue())); @@ -962,7 +962,7 @@ public void testCompute() throws Exception { assertThat(computed1.get(), equalTo("one")); Store.ValueHolder computed2 = xaStore.computeAndGet(1L, (aLong, s) -> { assertThat(aLong, is(1L)); - assertThat(s, equalTo("one")); + assertThat(s.get(), equalTo("one")); return "un"; }, SUPPLY_TRUE, SUPPLY_FALSE); assertThat(computed2.get(), equalTo("un")); @@ -975,7 +975,7 @@ public void testCompute() throws Exception { { Store.ValueHolder computed = xaStore.computeAndGet(1L, (aLong, s) -> { assertThat(aLong, is(1L)); - assertThat(s, equalTo("un")); + assertThat(s.get(), equalTo("un")); return "eins"; }, SUPPLY_TRUE, SUPPLY_FALSE); assertThat(computed.get(), equalTo("eins")); @@ -988,7 +988,7 @@ public void testCompute() throws Exception { { Store.ValueHolder computed = xaStore.computeAndGet(1L, (aLong, s) -> { assertThat(aLong, is(1L)); - assertThat(s, equalTo("eins")); + assertThat(s.get(), equalTo("eins")); return null; }, SUPPLY_TRUE, SUPPLY_FALSE); assertThat(computed, is(nullValue())); @@ -1001,7 +1001,7 @@ public void testCompute() throws Exception { { Store.ValueHolder computed1 = xaStore.computeAndGet(1L, (aLong, s) -> { assertThat(aLong, is(1L)); - assertThat(s, equalTo("eins")); + assertThat(s.get(), equalTo("eins")); return null; }, SUPPLY_TRUE, SUPPLY_FALSE); assertThat(computed1, is(nullValue())); @@ -1295,9 +1295,9 @@ public void testBulkCompute() throws Exception { { Map> computedMap = xaStore.bulkCompute(asSet(1L, 2L, 3L), entries -> { Map result = new HashMap<>(); - for (Map.Entry entry : entries) { + for (Map.Entry> entry : entries) { Long key = entry.getKey(); - String value = entry.getValue(); + Store.ValueHolder value = entry.getValue(); assertThat(value, is(nullValue())); result.put(key, "stuff#" + key); } @@ -1311,9 +1311,9 @@ public void testBulkCompute() throws Exception { computedMap = xaStore.bulkCompute(asSet(0L, 1L, 3L), entries -> { Map result = new HashMap<>(); - for (Map.Entry entry : entries) { + for (Map.Entry> entry : entries) { Long key = entry.getKey(); - String value = entry.getValue(); + Store.ValueHolder value = entry.getValue(); switch (key.intValue()) { case 0: @@ -1321,7 +1321,7 @@ public void testBulkCompute() throws Exception { break; case 1: case 3: - assertThat(value, equalTo("stuff#" + key)); + assertThat(value.get(), equalTo("stuff#" + key)); break; } diff --git a/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/XATransactionContextTest.java b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/XATransactionContextTest.java index 261e0c34c6..9ab3937b12 100644 --- a/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/XATransactionContextTest.java +++ b/ehcache-transactions/src/test/java/org/ehcache/transactions/xa/internal/XATransactionContextTest.java @@ -86,7 +86,6 @@ public void testSimpleCommands() { assertThat(xaTransactionContext.evicted(1L), is(false)); assertThat(xaTransactionContext.newValueHolderOf(1L), is(nullValue())); assertThat(xaTransactionContext.oldValueOf(1L), is(nullValue())); - assertThat(xaTransactionContext.newValueOf(1L), is(nullValue())); xaTransactionContext.addCommand(1L, new StorePutCommand<>("old", new XAValueHolder<>("new", timeSource.getTimeMillis()))); assertThat(xaTransactionContext.touched(1L), is(true)); @@ -95,7 +94,6 @@ public void testSimpleCommands() { assertThat(xaTransactionContext.evicted(1L), is(false)); assertThat(xaTransactionContext.newValueHolderOf(1L).get(), equalTo("new")); assertThat(xaTransactionContext.oldValueOf(1L), equalTo("old")); - assertThat(xaTransactionContext.newValueOf(1L), equalTo("new")); xaTransactionContext.addCommand(1L, new StoreRemoveCommand<>("old")); assertThat(xaTransactionContext.touched(1L), is(true)); @@ -104,7 +102,6 @@ public void testSimpleCommands() { assertThat(xaTransactionContext.evicted(1L), is(false)); assertThat(xaTransactionContext.newValueHolderOf(1L), is(nullValue())); assertThat(xaTransactionContext.oldValueOf(1L), equalTo("old")); - assertThat(xaTransactionContext.newValueOf(1L), is(nullValue())); xaTransactionContext.addCommand(1L, new StoreEvictCommand<>("old")); assertThat(xaTransactionContext.touched(1L), is(true)); @@ -113,7 +110,6 @@ public void testSimpleCommands() { assertThat(xaTransactionContext.evicted(1L), is(true)); assertThat(xaTransactionContext.newValueHolderOf(1L), is(nullValue())); assertThat(xaTransactionContext.oldValueOf(1L), equalTo("old")); - assertThat(xaTransactionContext.newValueOf(1L), is(nullValue())); } @Test @@ -126,7 +122,6 @@ public void testCommandsOverrideEachOther() { assertThat(xaTransactionContext.evicted(1L), is(false)); assertThat(xaTransactionContext.newValueHolderOf(1L).get(), equalTo("new")); assertThat(xaTransactionContext.oldValueOf(1L), equalTo("old")); - assertThat(xaTransactionContext.newValueOf(1L), equalTo("new")); xaTransactionContext.addCommand(1L, new StoreRemoveCommand<>("old")); assertThat(xaTransactionContext.touched(1L), is(true)); @@ -135,7 +130,6 @@ public void testCommandsOverrideEachOther() { assertThat(xaTransactionContext.evicted(1L), is(false)); assertThat(xaTransactionContext.newValueHolderOf(1L), is(nullValue())); assertThat(xaTransactionContext.oldValueOf(1L), equalTo("old")); - assertThat(xaTransactionContext.newValueOf(1L), is(nullValue())); xaTransactionContext.addCommand(1L, new StoreRemoveCommand<>("old2")); assertThat(xaTransactionContext.touched(1L), is(true)); @@ -144,7 +138,6 @@ public void testCommandsOverrideEachOther() { assertThat(xaTransactionContext.evicted(1L), is(false)); assertThat(xaTransactionContext.newValueHolderOf(1L), is(nullValue())); assertThat(xaTransactionContext.oldValueOf(1L), equalTo("old2")); - assertThat(xaTransactionContext.newValueOf(1L), is(nullValue())); xaTransactionContext.addCommand(1L, new StorePutCommand<>("old2", new XAValueHolder<>("new2", timeSource.getTimeMillis()))); assertThat(xaTransactionContext.touched(1L), is(true)); @@ -153,7 +146,6 @@ public void testCommandsOverrideEachOther() { assertThat(xaTransactionContext.evicted(1L), is(false)); assertThat(xaTransactionContext.newValueHolderOf(1L).get(), equalTo("new2")); assertThat(xaTransactionContext.oldValueOf(1L), equalTo("old2")); - assertThat(xaTransactionContext.newValueOf(1L), equalTo("new2")); } @Test @@ -167,7 +159,6 @@ public void testEvictCommandCannotBeOverridden() { assertThat(xaTransactionContext.evicted(1L), is(false)); assertThat(xaTransactionContext.newValueHolderOf(1L).get(), equalTo("new")); assertThat(xaTransactionContext.oldValueOf(1L), equalTo("old")); - assertThat(xaTransactionContext.newValueOf(1L), equalTo("new")); xaTransactionContext.addCommand(1L, new StoreEvictCommand<>("old")); assertThat(xaTransactionContext.touched(1L), is(true)); @@ -176,7 +167,6 @@ public void testEvictCommandCannotBeOverridden() { assertThat(xaTransactionContext.evicted(1L), is(true)); assertThat(xaTransactionContext.newValueHolderOf(1L), is(nullValue())); assertThat(xaTransactionContext.oldValueOf(1L), equalTo("old")); - assertThat(xaTransactionContext.newValueOf(1L), is(nullValue())); xaTransactionContext.addCommand(1L, new StorePutCommand<>("old2", new XAValueHolder<>("new2", timeSource.getTimeMillis()))); assertThat(xaTransactionContext.touched(1L), is(true)); @@ -185,7 +175,6 @@ public void testEvictCommandCannotBeOverridden() { assertThat(xaTransactionContext.evicted(1L), is(true)); assertThat(xaTransactionContext.newValueHolderOf(1L), is(nullValue())); assertThat(xaTransactionContext.oldValueOf(1L), equalTo("old")); - assertThat(xaTransactionContext.newValueOf(1L), is(nullValue())); } @Test diff --git a/integration-test/src/test/java/org/ehcache/integration/DeserializationOnRemovalTest.java b/integration-test/src/test/java/org/ehcache/integration/DeserializationOnRemovalTest.java new file mode 100644 index 0000000000..9c573f34ea --- /dev/null +++ b/integration-test/src/test/java/org/ehcache/integration/DeserializationOnRemovalTest.java @@ -0,0 +1,124 @@ +/* + * Copyright Terracotta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ehcache.integration; + +import org.ehcache.Cache; +import org.ehcache.CacheManager; +import org.ehcache.config.ResourcePools; +import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.config.builders.ResourcePoolsBuilder; +import org.ehcache.core.internal.resilience.ThrowingResilienceStrategy; +import org.ehcache.impl.config.persistence.CacheManagerPersistenceConfiguration; +import org.ehcache.impl.serialization.PlainJavaSerializer; +import org.ehcache.spi.serialization.SerializerException; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.terracotta.org.junit.rules.TemporaryFolder; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Collection; + +import static java.util.Collections.singleton; +import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; +import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder; +import static org.ehcache.config.units.EntryUnit.ENTRIES; +import static org.ehcache.config.units.MemoryUnit.MB; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; + +@RunWith(Parameterized.class) +public class DeserializationOnRemovalTest { + + @Rule + public final TemporaryFolder folder = new TemporaryFolder(); + + private final ResourcePools resources; + + @Parameterized.Parameters(name = "{0}") + public static Collection data() { + return Arrays.asList(new Object[][] { + //1 tier + { newResourcePoolsBuilder().offheap(1, MB) }, + { newResourcePoolsBuilder().disk(1, MB) }, + + //2 tiers + { newResourcePoolsBuilder().heap(1, MB).offheap(2, MB) }, + { newResourcePoolsBuilder().heap(1, ENTRIES).offheap(2, MB) }, + { newResourcePoolsBuilder().heap(1, MB).disk(2, MB) }, + { newResourcePoolsBuilder().heap(1, ENTRIES).disk(2, MB) }, + + //3 tiers + { newResourcePoolsBuilder().heap(1, MB).offheap(2, MB).disk(3, MB) }, + { newResourcePoolsBuilder().heap(1, ENTRIES).offheap(2, MB).disk(3, MB) } + }); + } + + public DeserializationOnRemovalTest(ResourcePoolsBuilder poolBuilder) { + this.resources = poolBuilder.build(); + } + + @Test + public void testForDeserializationOnRemove() throws IOException { + try (CacheManager manager = CacheManagerBuilder.newCacheManagerBuilder() + .with(new CacheManagerPersistenceConfiguration(folder.newFolder())) + .withCache("test-cache", newCacheConfigurationBuilder(Long.class, String.class, resources) + .withResilienceStrategy(new ThrowingResilienceStrategy<>()) + .withValueSerializer(new PlainJavaSerializer(DeserializationOnRemovalTest.class.getClassLoader()) { + @Override + public String read(ByteBuffer entry) throws SerializerException { + throw new AssertionError("No deserialization allowed"); + } + })).build(true)) { + + Cache cache = manager.getCache("test-cache", Long.class, String.class); + + cache.put(1L, "one"); + cache.remove(1L); + + assertThat(cache.get(1L), is(nullValue())); + } + } + + @Test + public void testForDeserializationOnRemoveAll() throws IOException { + try (CacheManager manager = CacheManagerBuilder.newCacheManagerBuilder() + .with(new CacheManagerPersistenceConfiguration(folder.newFolder())) + .withCache("test-cache", newCacheConfigurationBuilder(Long.class, String.class, resources) + .withResilienceStrategy(new ThrowingResilienceStrategy<>()) + .withValueSerializer(new PlainJavaSerializer(DeserializationOnRemovalTest.class.getClassLoader()) { + @Override + public String read(ByteBuffer entry) throws SerializerException { + throw new AssertionError("No deserialization allowed"); + } + })).build(true)) { + + Cache cache = manager.getCache("test-cache", Long.class, String.class); + + cache.put(1L, "one"); + cache.removeAll(singleton(1L)); + + assertThat(cache.get(1L), is(nullValue())); + } + + } + + +} diff --git a/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java b/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java index f514ffd5e6..9d6bd91968 100644 --- a/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java +++ b/integration-test/src/test/java/org/ehcache/integration/EhcacheBulkMethodsITest.java @@ -536,7 +536,7 @@ public Store createStore(Store.Configuration storeConfig, Ser final Copier defaultCopier = new IdentityCopier(); return new OnHeapStore(storeConfig, SystemTimeSource.INSTANCE, defaultCopier, defaultCopier, new NoopSizeOfEngine(), NullStoreEventDispatcher.nullStoreEventDispatcher(), new DefaultStatisticsService()) { @Override - public Map> bulkCompute(Set keys, Function>, Iterable>> remappingFunction) throws StoreAccessException { + public Map> bulkCompute(Set keys, Function>>, Iterable>> remappingFunction) throws StoreAccessException { throw new StoreAccessException("Problem trying to bulk compute"); }