Skip to content

Commit

Permalink
Remove outdated warnings regarding TTL from IMap's javadoc (#12336)
Browse files Browse the repository at this point in the history
There were outdated warnings in IMap javadoc regarding expiration and
TTL behavior of mutating methods don't accepting TTL as a parameter.

1. Added the tests to verify the current behavior and to make sure we
won't silently break it in the future one more time.

2. Removed the warnings themselves.

3. Added javadoc describing the current TTL behavior.

Fixes: #12144
  • Loading branch information
taburet committed Feb 15, 2018
1 parent 28a593f commit 64dc3d4
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 37 deletions.
56 changes: 19 additions & 37 deletions hazelcast/src/main/java/com/hazelcast/core/IMap.java
Expand Up @@ -139,6 +139,22 @@
* {@link MapStore} methods to load, store or remove data. Each method's
* javadoc describes the way of its interaction with the map store.
*
* <p><b>Mutating methods without TTL</b>
* <p>
* Certain {@link IMap} methods perform the entry set mutation and don't accept TTL as a parameter. Entries
* created or updated by such methods are subjects for the following TTL calculation procedure:
* <ul>
* <li>If the entry is new, i.e. the entry was created, it receives the default TTL value configured for
* the map using {@code time-to-live-seconds} configuration setting. If this setting is not provided for
* the map, the entry receives an infinite TTL value.
* <li>If the entry already exists, i.e. the entry was updated, its TTL value remains unchanged and its
* lifetime is prolonged by this TTL value.
* </ul>
* The methods to which this procedure applies: {@link #put(Object, Object) put}, {@link #set(Object, Object) set},
* {@link #putAsync(Object, Object) putAsync}, {@link #setAsync(Object, Object) setAsync},
* {@link #tryPut(Object, Object, long, TimeUnit) tryPut}, {@link #putAll(Map) putAll},
* {@link #replace(Object, Object, Object)} and {@link #replace(Object, Object)}.
*
* @param <K> key
* @param <V> value
* @see java.util.concurrent.ConcurrentMap
Expand All @@ -150,11 +166,6 @@ public interface IMap<K, V> extends ConcurrentMap<K, V>, LegacyAsyncMap<K, V> {
* <p>
* No atomicity guarantees are given. It could be that in case of failure
* some of the key/value-pairs get written, while others are not.
* <p>
* <b>Warning:</b>
* <p>
* If you have previously set a TTL for the key, the TTL remains unchanged and the entry will
* expire when the initial TTL has elapsed.
*
* <p><b>Interactions with the map store</b>
* <p>
Expand Down Expand Up @@ -252,11 +263,6 @@ public interface IMap<K, V> extends ConcurrentMap<K, V>, LegacyAsyncMap<K, V> {
* the {@code key}, not the actual implementations of {@code hashCode} and {@code equals}
* defined in the {@code key}'s class.
* <p>
* <b>Warning 3:</b>
* <p>
* If you have previously set a TTL for the key, the TTL remains unchanged and the entry will
* expire when the initial TTL has elapsed.
* <p>
* <p><b>Note:</b>
* Use {@link #set(Object, Object)} if you don't need the return value, it's slightly more efficient.
*
Expand Down Expand Up @@ -612,17 +618,12 @@ public interface IMap<K, V> extends ConcurrentMap<K, V>, LegacyAsyncMap<K, V> {
* }</pre>
* ExecutionException is never thrown.
* <p>
* <b>Warning 1:</b>
* <b>Warning:</b>
* <p>
* This method uses {@code hashCode} and {@code equals} of the binary form of
* the {@code key}, not the actual implementations of {@code hashCode} and {@code equals}
* defined in the {@code key}'s class.
* <p>
* <b>Warning 2:</b>
* <p>
* If you have previously set a TTL for the key, the TTL remains unchanged and the entry will
* expire when the initial TTL has elapsed.
* <p>
* <p><b>Note:</b>
* Use {@link #setAsync(Object, Object)} if you don't need the return value, it's slightly more efficient.
*
Expand Down Expand Up @@ -774,16 +775,11 @@ public interface IMap<K, V> extends ConcurrentMap<K, V>, LegacyAsyncMap<K, V> {
* }</pre>
* ExecutionException is never thrown.
* <p>
* <b>Warning 1:</b>
* <b>Warning:</b>
* <p>
* This method uses {@code hashCode} and {@code equals} of the binary form of
* the {@code key}, not the actual implementations of {@code hashCode} and {@code equals}
* defined in the {@code key}'s class.
* <p>
* <b>Warning 2:</b>
* <p>
* If you have previously set a TTL for the key, the TTL remains unchanged and the entry will
* expire when the initial TTL has elapsed.
*
* <p><b>Interactions with the map store</b>
* <p>
Expand Down Expand Up @@ -953,16 +949,11 @@ public interface IMap<K, V> extends ConcurrentMap<K, V>, LegacyAsyncMap<K, V> {
* the caller thread could not acquire the lock for the key within the
* timeout duration, thus the put operation is not successful.
* <p>
* <b>Warning 1:</b>
* <b>Warning:</b>
* <p>
* This method uses {@code hashCode} and {@code equals} of the binary form of
* the {@code key}, not the actual implementations of {@code hashCode} and {@code equals}
* defined in the {@code key}'s class.
* <p>
* <b>Warning 2:</b>
* <p>
* If you have previously set a TTL for the key, the TTL remains unchanged and the entry will
* expire when the initial TTL has elapsed.
*
* <p><b>Interactions with the map store</b>
* <p>
Expand Down Expand Up @@ -1195,10 +1186,6 @@ public interface IMap<K, V> extends ConcurrentMap<K, V>, LegacyAsyncMap<K, V> {
* <p>
* This method returns a clone of the previous value, not the original (identically equal) value
* previously put into the map.
* <p>
* <b>Warning 3:</b>
* <p>
* If you have previously set a TTL for the key, the same TTL will be again set on the new value.
*
* <p><b>Interactions with the map store</b>
* <p>
Expand Down Expand Up @@ -1231,11 +1218,6 @@ public interface IMap<K, V> extends ConcurrentMap<K, V>, LegacyAsyncMap<K, V> {
* This method uses {@code hashCode} and {@code equals} of the binary form of
* the {@code key}, not the actual implementations of {@code hashCode} and {@code equals}
* defined in the {@code key}'s class.
* <p>
* <b>Warning 3:</b>
* <p>
* If you have previously set a TTL for the key, the TTL remains unchanged and the entry will
* expire when the initial TTL has elapsed.
*
* <p><b>Interactions with the map store</b>
* <p>
Expand Down
68 changes: 68 additions & 0 deletions hazelcast/src/test/java/com/hazelcast/map/EvictionTest.java
Expand Up @@ -38,16 +38,19 @@
import com.hazelcast.test.annotation.NightlyTest;
import com.hazelcast.test.annotation.ParallelTest;
import com.hazelcast.test.annotation.QuickTest;
import com.hazelcast.test.annotation.SlowTest;
import com.hazelcast.util.Clock;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
Expand Down Expand Up @@ -107,6 +110,71 @@ public void testTTL_appliedFromLastUpdate() {
assertTrue(map.containsKey(1));
}

@Test
public void testTTL_prolongationAfterNonTTLUpdate_Quick() {
final IMap<Integer, String> map = createSimpleMap();

map.put(1, "value0", 3, TimeUnit.SECONDS);
// 1 second safety margin before eviction
sleepSeconds(2);
assertTrue(map.containsKey(1));

// this should prolong the life of the entry for another 3 seconds
map.put(1, "value1");
// 4 seconds of wait time in total, 1 second safety margin after a potential eviction
sleepSeconds(2);
assertTrue(map.containsKey(1));
}

@Test
@Category(SlowTest.class)
public void testTTL_prolongationAfterNonTTLUpdate_Slow() throws ExecutionException, InterruptedException {
final IMap<Integer, String> map = createSimpleMap();

map.put(1, "value0", 3, TimeUnit.SECONDS);
// 1 second safety margin before eviction
sleepSeconds(2);
assertTrue(map.containsKey(1));

// this should prolong the life of the entry for another 3 seconds
map.put(1, "value1");
// 4 seconds of wait time in total, 1 second safety margin after a potential eviction
sleepSeconds(2);
assertTrue(map.containsKey(1));

map.set(1, "value2");
sleepSeconds(2);
assertTrue(map.containsKey(1));

final HashMap<Integer, String> items = new HashMap<Integer, String>();
items.put(1, "value3");
items.put(2, "value1");
items.put(3, "value1");
map.putAll(items);
sleepSeconds(2);
assertTrue(map.containsKey(1));

map.putAsync(1, "value4").get();
sleepSeconds(2);
assertTrue(map.containsKey(1));

map.setAsync(1, "value5").get();
sleepSeconds(2);
assertTrue(map.containsKey(1));

assertTrue(map.tryPut(1, "value6", 333, TimeUnit.MILLISECONDS));
sleepSeconds(2);
assertTrue(map.containsKey(1));

map.replace(1, "value7");
sleepSeconds(2);
assertTrue(map.containsKey(1));

map.replace(1, "value7", "value8");
sleepSeconds(2);
assertTrue(map.containsKey(1));
}

@Test
public void testGetEntryView_withTTL() {
IMap<Integer, String> map = createSimpleMap();
Expand Down

0 comments on commit 64dc3d4

Please sign in to comment.