/*
* Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved.
*
* 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 com.hazelcast.map.impl.nearcache;
import com.hazelcast.config.Config;
import com.hazelcast.config.EvictionConfig;
import com.hazelcast.config.EvictionPolicy;
import com.hazelcast.config.InMemoryFormat;
import com.hazelcast.config.MapConfig;
import com.hazelcast.config.NearCacheConfig;
import com.hazelcast.core.ExecutionCallback;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IMap;
import com.hazelcast.internal.nearcache.NearCache;
import com.hazelcast.internal.partition.InternalPartitionService;
import com.hazelcast.map.AbstractEntryProcessor;
import com.hazelcast.monitor.LocalMapStats;
import com.hazelcast.monitor.NearCacheStats;
import com.hazelcast.query.EntryObject;
import com.hazelcast.query.Predicate;
import com.hazelcast.query.PredicateBuilder;
import com.hazelcast.query.SampleObjects.Employee;
import com.hazelcast.spi.properties.GroupProperty;
import com.hazelcast.test.AssertTask;
import com.hazelcast.test.HazelcastParametersRunnerFactory;
import com.hazelcast.test.TestHazelcastInstanceFactory;
import com.hazelcast.test.annotation.ParallelTest;
import com.hazelcast.test.annotation.QuickTest;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import static java.lang.String.format;
import static java.lang.String.valueOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@RunWith(Parameterized.class)
@Parameterized.UseParametersRunnerFactory(HazelcastParametersRunnerFactory.class)
@Category({QuickTest.class, ParallelTest.class})
public class NearCacheTest extends NearCacheTestSupport {
@Parameterized.Parameter
public boolean batchInvalidationEnabled;
@Parameterized.Parameters(name = "batchInvalidationEnabled:{0}")
public static Iterable<Object[]> parameters() {
return Arrays.asList(new Object[]{Boolean.TRUE}, new Object[]{Boolean.FALSE});
}
@Test
public void testBasicUsage() {
int clusterSize = 3;
int mapSize = 5000;
final String mapName = "testBasicUsage";
Config config = getConfig();
config.getMapConfig(mapName).setNearCacheConfig(newNearCacheConfig().setInvalidateOnChange(true));
TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(clusterSize);
final HazelcastInstance[] instances = factory.newInstances(config);
IMap<Integer, Integer> map = instances[0].getMap(mapName);
populateMap(map, mapSize);
for (HazelcastInstance instance : instances) {
IMap<Integer, Integer> instanceMap = instance.getMap(mapName);
for (int i = 0; i < mapSize; i++) {
assertNotNull(instanceMap.get(i));
}
}
for (int i = 0; i < mapSize; i++) {
map.put(i, i * 2);
}
for (HazelcastInstance instance : instances) {
IMap<Object, Object> m = instance.getMap(mapName);
for (int i = 0; i < mapSize; i++) {
assertNotNull(m.get(i));
}
}
for (HazelcastInstance instance : instances) {
int nearCacheSize = getNearCache(mapName, instance).size();
assertTrue("Near Cache size should be > 0 but was " + nearCacheSize, nearCacheSize > 0);
}
map.clear();
assertTrueEventually(new AssertTask() {
@Override
public void run() throws Exception {
for (HazelcastInstance instance : instances) {
NearCache nearCache = getNearCache(mapName, instance);
int size = nearCache.size();
assertEquals("Near Cache size should be 0 but was " + size, 0, size);
}
}
});
}
@Override
protected Config getConfig() {
Config config = super.getConfig();
config.setProperty(GroupProperty.MAP_INVALIDATION_MESSAGE_BATCH_ENABLED.getName(), valueOf(batchInvalidationEnabled));
return config;
}
@Test
public void test_whenEmptyMap_thenPopulatedNearCacheShouldReturnNull_neverNULL_OBJECT() {
int size = 10;
String mapName = randomMapName();
Config config = getConfig();
config.getMapConfig(mapName).setNearCacheConfig(newNearCacheConfig());
TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(1);
HazelcastInstance instance = factory.newHazelcastInstance(config);
// populate map
IMap<Integer, Integer> map = instance.getMap(mapName);
for (int i = 0; i < size; i++) {
// populate Near Cache
assertNull(map.get(i));
// fetch value from Near Cache
assertNull(map.get(i));
}
}
@Test
public void test_whenCacheIsFullPutOnSameKeyShouldUpdateValue_withEvictionPolicyIsNONE() {
int size = 10;
int maxSize = 5;
IMap<Integer, Integer> map = getMapConfiguredWithMaxSizeAndPolicy(EvictionPolicy.NONE, maxSize);
populateMap(map, size);
populateNearCache(map, size);
assertEquals(maxSize, getNearCacheSize(map));
assertEquals(1, map.get(1).intValue());
map.put(1, 1502);
assertEquals(1502, map.get(1).intValue());
assertEquals(1502, map.get(1).intValue());
}
@Test
public void testNearCacheEviction() {
String mapName = "testNearCacheEviction";
NearCacheConfig nearCacheConfig = newNearCacheConfigWithEntryCountEviction(EvictionPolicy.LRU, MAX_CACHE_SIZE);
Config config = getConfig();
config.getMapConfig(mapName).setNearCacheConfig(nearCacheConfig);
TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(1);
HazelcastInstance hazelcastInstance = factory.newHazelcastInstance(config);
IMap<Integer, Integer> map = hazelcastInstance.getMap(mapName);
testNearCacheEviction(map, MAX_CACHE_SIZE);
}
@Test
public void testNearCacheEviction_withMapClear() {
final int size = 10;
String mapName = "testNearCacheEvictionWithMapClear";
NearCacheConfig nearCacheConfig = newNearCacheConfig();
nearCacheConfig.setInvalidateOnChange(true);
Config config = getConfig();
config.getMapConfig(mapName).setNearCacheConfig(nearCacheConfig);
TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(2);
HazelcastInstance hazelcastInstance1 = factory.newHazelcastInstance(config);
HazelcastInstance hazelcastInstance2 = factory.newHazelcastInstance(config);
final IMap<Integer, Integer> map1 = hazelcastInstance1.getMap(mapName);
final IMap<Integer, Integer> map2 = hazelcastInstance2.getMap(mapName);
// populate map
populateMap(map1, size);
// populate Near Caches
populateNearCache(map1, size);
populateNearCache(map2, size);
// clear map should trigger Near Cache eviction
map1.clear();
assertTrueEventually(new AssertTask() {
@Override
public void run() throws Exception {
// assert that the Near Cache doesn't return any cached values
for (int i = 0; i < size; i++) {
assertNull(map1.get(i));
assertNull(map2.get(i));
}
assertEquals(0, getNearCacheStats(map1).getEvictions());
assertEquals(0, getNearCacheStats(map2).getEvictions());
}
});
}
@Test
public void testNearCacheStats() {
int mapSize = 1000;
String mapName = randomMapName();
Config config = getConfig();
config.getMapConfig(mapName).setNearCacheConfig(newNearCacheConfig().setInvalidateOnChange(false));
TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(2);
HazelcastInstance[] instances = factory.newInstances(config);
// populate map
IMap<Integer, Integer> map = instances[0].getMap(mapName);
populateMap(map, mapSize);
// populate Near Cache
populateNearCache(map, mapSize);
NearCacheStats stats = getNearCacheStats(map);
long ownedEntryCount = stats.getOwnedEntryCount();
long misses = stats.getMisses();
assertTrue(format("Near Cache entry count should be > %d but were %d", 400, ownedEntryCount), ownedEntryCount > 400);
assertEquals(format("Near Cache misses should be %d but were %d", mapSize, misses), mapSize, misses);
// make some hits
populateNearCache(map, mapSize);
long hits = stats.getHits();
misses = stats.getMisses();
long hitsAndMisses = hits + misses;
assertTrue(format("Near Cache hits should be > %d but were %d", 400, hits), hits > 400);
assertTrue(format("Near Cache misses should be > %d but were %d", 400, misses), misses > 400);
assertEquals(format("Near Cache hits + misses should be %s but were %d", mapSize * 2, hitsAndMisses), mapSize * 2,
hitsAndMisses);
}
@Test
public void testNearCacheMemoryCostCalculation() {
testNearCacheMemoryCostCalculation(1);
}
@Test
public void testNearCacheMemoryCostCalculation_withConcurrentCacheMisses() {
testNearCacheMemoryCostCalculation(10);
}
private void testNearCacheMemoryCostCalculation(int threadCount) {
String mapName = randomName();
Config config = getConfig();
NearCacheConfig nearCacheConfig = newNearCacheConfig().setCacheLocalEntries(true);
config.getMapConfig(mapName).setNearCacheConfig(nearCacheConfig.setInvalidateOnChange(false));
TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(1);
HazelcastInstance hazelcastInstance = factory.newHazelcastInstance(config);
IMap<Integer, Integer> map = hazelcastInstance.getMap(mapName);
testNearCacheMemoryCostCalculation(map, true, threadCount);
}
@Test
public void testNearCacheInvalidationByUsingMapPutAll() {
int clusterSize = 3;
int mapSize = 5000;
String mapName = randomMapName();
Config config = getConfig();
config.getMapConfig(mapName).setNearCacheConfig(newNearCacheConfig().setInvalidateOnChange(true));
TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(clusterSize);
HazelcastInstance[] instances = factory.newInstances(config);
final IMap<Integer, Integer> map = instances[0].getMap(mapName);
populateMap(map, mapSize);
populateNearCache(map, mapSize);
// more-or-less (count / no_of_nodes) should be in the Near Cache now
assertTrue(getNearCacheSize(map) > (mapSize / clusterSize - mapSize * 0.1));
Map<Integer, Integer> invalidationMap = new HashMap<Integer, Integer>(mapSize);
populateMap(invalidationMap, mapSize);
// this should invalidate the Near Cache
map.putAll(invalidationMap);
assertTrueEventually(
new AssertTask() {
@Override
public void run() {
assertEquals("Invalidation is not working on putAll()", 0, getNearCacheSize(map));
}
}
);
}
@Test
public void testMapContainsKey_withNearCache() {
int clusterSize = 3;
String mapName = randomMapName();
Config config = getConfig();
config.getMapConfig(mapName).setNearCacheConfig(newNearCacheConfig().setInvalidateOnChange(true));
HazelcastInstance instance = createHazelcastInstanceFactory(clusterSize).newInstances(config)[0];
IMap<String, String> map = instance.getMap(mapName);
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
map.get("key1");
map.get("key2");
map.get("key3");
assertTrue(map.containsKey("key1"));
assertFalse(map.containsKey("key5"));
map.remove("key1");
assertFalse(map.containsKey("key5"));
assertTrue(map.containsKey("key2"));
assertFalse(map.containsKey("key1"));
}
@Test
public void testCacheLocalEntries() {
int instanceCount = 2;
String mapName = "testCacheLocalEntries";
NearCacheConfig nearCacheConfig = newNearCacheConfig();
nearCacheConfig.setCacheLocalEntries(true);
nearCacheConfig.setInvalidateOnChange(false);
Config config = getConfig();
MapConfig mapConfig = config.getMapConfig(mapName);
mapConfig.setNearCacheConfig(nearCacheConfig);
HazelcastInstance[] instances = createHazelcastInstanceFactory(instanceCount).newInstances(config);
IMap<String, String> map = instances[0].getMap(mapName);
for (int i = 0; i < MAX_CACHE_SIZE; i++) {
map.put("key" + i, "value" + i);
}
// warm-up cache
for (int i = 0; i < MAX_CACHE_SIZE; i++) {
map.get("key" + i);
}
int nearCacheSize = getNearCacheSize(map);
assertEquals(format("Near Cache size should be %d but was %d", MAX_CACHE_SIZE, nearCacheSize),
MAX_CACHE_SIZE, nearCacheSize);
}
// issue 1570
@Test
public void testNullValueNearCache() {
int clusterSize = 2;
String mapName = "testNullValueNearCache";
Config config = getConfig();
config.getMapConfig(mapName).setNearCacheConfig(newNearCacheConfig());
HazelcastInstance instance = createHazelcastInstanceFactory(clusterSize).newInstances(config)[0];
IMap<String, String> map = instance.getMap(mapName);
for (int i = 0; i < MAX_CACHE_SIZE; i++) {
assertNull(map.get("key" + i));
}
for (int i = 0; i < MAX_CACHE_SIZE; i++) {
assertNull(map.get("key" + i));
}
LocalMapStats stats = map.getLocalMapStats();
assertTrue(
format("Near Cache operation count should be < %d but was %d", MAX_CACHE_SIZE * 2, stats.getGetOperationCount()),
stats.getGetOperationCount() < MAX_CACHE_SIZE * 2
);
}
@Test
public void testGetAll() {
int mapSize = 1000;
String mapName = "testGetAllWithNearCache";
Config config = getConfig();
NearCacheConfig nearCacheConfig = newNearCacheConfig();
nearCacheConfig.setInvalidateOnChange(false);
config.getMapConfig(mapName).setNearCacheConfig(nearCacheConfig);
TestHazelcastInstanceFactory hazelcastInstanceFactory = createHazelcastInstanceFactory(2);
HazelcastInstance[] instances = hazelcastInstanceFactory.newInstances(config);
warmUpPartitions(instances);
HazelcastInstance hazelcastInstance = instances[0];
InternalPartitionService partitionService = getPartitionService(hazelcastInstance);
// populate map
IMap<Integer, Integer> map = hazelcastInstance.getMap(mapName);
populateMap(map, mapSize);
Set<Integer> keys = map.keySet();
// populate Near Cache
int expectedHits = 0;
for (int i = 0; i < mapSize; i++) {
map.get(i);
int partitionId = partitionService.getPartitionId(i);
if (!partitionService.isPartitionOwner(partitionId)) {
// map proxy stores non-owned entries (belong to partition which its not owner) inside its Near Cache
expectedHits++;
}
}
// generate Near Cache hits
Map<Integer, Integer> allEntries = map.getAll(keys);
for (int i = 0; i < mapSize; i++) {
assertEquals(i, (int) allEntries.get(i));
}
// check Near Cache hits
long hits = getNearCacheStats(map).getHits();
assertEquals(format("Near Cache hits should be %d but were %d", expectedHits, hits), expectedHits, hits);
}
@Test
public void testGetAllIssue1863() {
int mapSize = 1000;
String mapName = "testGetAllWithNearCacheIssue1863";
Config config = getConfig();
NearCacheConfig nearCacheConfig = newNearCacheConfig().setInvalidateOnChange(true);
nearCacheConfig.setCacheLocalEntries(true);
config.getMapConfig(mapName).setNearCacheConfig(nearCacheConfig);
TestHazelcastInstanceFactory hazelcastInstanceFactory = createHazelcastInstanceFactory(2);
HazelcastInstance[] instances = hazelcastInstanceFactory.newInstances(config);
IMap<Integer, Integer> map = instances[0].getMap(mapName);
HashSet<Integer> keys = new HashSet<Integer>();
// populate Near Cache with nulls (cache local entries mode on)
for (int i = 0; i < mapSize; i++) {
map.get(i);
keys.add(i);
}
// generate Near Cache hits
Map<Integer, Integer> allEntries = map.getAll(keys);
assertEquals(0, allEntries.size());
// check Near Cache hits
long hits = getNearCacheStats(map).getHits();
assertEquals(format("Near Cache hits should be %d but were %d", mapSize, hits), mapSize, hits);
}
@Test
public void testGetAsync() {
int mapSize = 1000;
int expectedHits = 400;
String mapName = "testGetAsyncWithNearCache";
Config config = getConfig();
config.getMapConfig(mapName).setNearCacheConfig(newNearCacheConfig().setInvalidateOnChange(false));
TestHazelcastInstanceFactory hazelcastInstanceFactory = createHazelcastInstanceFactory(2);
HazelcastInstance instance1 = hazelcastInstanceFactory.newHazelcastInstance(config);
hazelcastInstanceFactory.newHazelcastInstance(config);
IMap<Integer, Integer> map = instance1.getMap(mapName);
populateMap(map, mapSize);
populateNearCache(map, mapSize);
for (int i = 0; i < mapSize; i++) {
map.getAsync(i);
}
long hits = getNearCacheStats(map).getHits();
assertTrue(format("Near Cache hits should be > %d but were %d", expectedHits, hits), hits > expectedHits);
}
@Test
public void testGetAsyncPopulatesNearCache() throws Exception {
int mapSize = 1000;
String mapName = "testGetAsyncPopulatesNearCache";
Config config = getConfig();
config.getMapConfig(mapName).setNearCacheConfig(newNearCacheConfig().setInvalidateOnChange(false));
TestHazelcastInstanceFactory hazelcastInstanceFactory = createHazelcastInstanceFactory(2);
HazelcastInstance hz = hazelcastInstanceFactory.newHazelcastInstance(config);
hazelcastInstanceFactory.newHazelcastInstance(config);
IMap<Integer, Integer> map = hz.getMap(mapName);
populateMap(map, mapSize);
// populate Near Cache
for (int i = 0; i < mapSize; i++) {
Future future = map.getAsync(i);
future.get();
}
// generate Near Cache hits
populateNearCache(map, mapSize);
long ownedEntryCount = getNearCacheStats(map).getOwnedEntryCount();
assertTrue(format("Near Cache should be populated but current size is %d", ownedEntryCount), ownedEntryCount > 0);
}
@Test
public void testGetAsyncIssue1863() throws Exception {
int mapSize = 1000;
String mapName = "testGetAsyncWithNearCacheIssue1863";
Config config = getConfig();
NearCacheConfig nearCacheConfig = newNearCacheConfig();
nearCacheConfig.setCacheLocalEntries(true);
config.getMapConfig(mapName).setNearCacheConfig(nearCacheConfig);
TestHazelcastInstanceFactory hazelcastInstanceFactory = createHazelcastInstanceFactory(2);
HazelcastInstance hz = hazelcastInstanceFactory.newHazelcastInstance(config);
hazelcastInstanceFactory.newHazelcastInstance(config);
IMap<Integer, Integer> map = hz.getMap(mapName);
populateNearCache(map, mapSize);
for (int i = 0; i < mapSize; i++) {
Future<Integer> future = map.getAsync(i);
assertNull(future.get());
}
long hits = getNearCacheStats(map).getHits();
assertEquals(format("Near Cache hits should be %d but were %d", mapSize, hits), mapSize, hits);
}
@Test
public void testAfterLoadAllWithDefinedKeysNearCacheIsInvalidated() {
int mapSize = 1000;
String mapName = randomMapName();
Config config = createNearCachedMapConfigWithMapStoreConfig(mapName);
HazelcastInstance instance = createHazelcastInstance(config);
IMap<Integer, Integer> map = instance.getMap(mapName);
populateMap(map, mapSize);
populateNearCache(map, mapSize);
Set<Integer> keys = map.keySet();
map.loadAll(keys, true);
assertEquals(0, getNearCacheStats(map).getOwnedEntryCount());
}
@Test
public void testAfterLoadAllNearCacheIsInvalidated() {
int mapSize = 1000;
String mapName = randomMapName();
Config config = createNearCachedMapConfigWithMapStoreConfig(mapName);
HazelcastInstance instance = createHazelcastInstance(config);
IMap<Integer, Integer> map = instance.getMap(mapName);
populateMap(map, mapSize);
populateNearCache(map, mapSize);
map.loadAll(true);
assertEquals(0, getNearCacheStats(map).getOwnedEntryCount());
}
@Test
public void testAfterSubmitToKeyWithCallbackNearCacheIsInvalidated() throws Exception {
int mapSize = 1000;
String mapName = randomMapName();
Random random = new Random();
Config config = createNearCachedMapConfig(mapName);
HazelcastInstance instance = createHazelcastInstance(config);
IMap<Integer, Integer> map = instance.getMap(mapName);
populateMap(map, mapSize);
populateNearCache(map, mapSize);
final CountDownLatch latch = new CountDownLatch(10);
ExecutionCallback<Integer> callback = new ExecutionCallback<Integer>() {
@Override
public void onResponse(Integer response) {
latch.countDown();
}
@Override
public void onFailure(Throwable t) {
}
};
int randomKey = random.nextInt(mapSize);
map.submitToKey(randomKey, new AbstractEntryProcessor<Integer, Integer>() {
@Override
public Object process(Map.Entry<Integer, Integer> entry) {
int currentValue = entry.getValue();
int newValue = currentValue + 1;
entry.setValue(newValue);
return newValue;
}
}, callback);
latch.await(3, TimeUnit.SECONDS);
assertEquals(mapSize - 1, getNearCacheStats(map).getOwnedEntryCount());
}
@Test
public void testAfterExecuteOnEntriesNearCacheIsInvalidated() {
int mapSize = 10;
String mapName = randomMapName();
Config config = createNearCachedMapConfig(mapName);
HazelcastInstance instance = createHazelcastInstance(config);
IMap<Integer, Employee> map = instance.getMap(mapName);
for (int i = 0; i < mapSize; i++) {
map.put(i, new Employee(i, "", 0, true, 0D));
}
populateNearCache(map, mapSize);
EntryObject e = new PredicateBuilder().getEntryObject();
Predicate predicate = e.get("salary").equal(0);
map.executeOnEntries(new AbstractEntryProcessor<Integer, Employee>() {
@Override
public Object process(Map.Entry<Integer, Employee> entry) {
Employee employee = entry.getValue();
double currentSalary = employee.getSalary();
double newSalary = currentSalary + 10;
employee.setSalary(newSalary);
return newSalary;
}
}, predicate);
assertEquals(0, getNearCacheStats(map).getOwnedEntryCount());
}
@Test
public void testNearCacheInvalidation_WithLFU_whenMaxSizeExceeded() {
int mapSize = 2000;
final int maxSize = 1000;
final IMap<Integer, Integer> map = getMapConfiguredWithMaxSizeAndPolicy(EvictionPolicy.LFU, maxSize);
populateMap(map, mapSize);
populateNearCache(map, mapSize);
assertTrueEventually(new AssertTask() {
@Override
public void run() {
triggerNearCacheEviction(map);
long ownedEntryCount = getNearCacheStats(map).getOwnedEntryCount();
assertEquals("owned entry count " + ownedEntryCount, maxSize, ownedEntryCount);
}
});
}
@Test
public void testNearCacheInvalidation_WithLRU_whenMaxSizeExceeded() {
int mapSize = 2000;
final int maxSize = 1000;
final IMap<Integer, Integer> map = getMapConfiguredWithMaxSizeAndPolicy(EvictionPolicy.LRU, maxSize);
populateMap(map, mapSize);
populateNearCache(map, mapSize);
assertTrueEventually(new AssertTask() {
@Override
public void run() {
triggerNearCacheEviction(map);
long ownedEntryCount = getNearCacheStats(map).getOwnedEntryCount();
assertEquals("owned entry count " + ownedEntryCount, maxSize, ownedEntryCount);
}
});
}
@Test
public void testNearCacheInvalidation_WithRandom_whenMaxSizeExceeded() {
testNearCacheInvalidation_whenMaxSizeExceeded(EvictionPolicy.RANDOM);
}
@Test
public void testNearCacheInvalidation_WitNone_whenMaxSizeExceeded() {
testNearCacheInvalidation_whenMaxSizeExceeded(EvictionPolicy.NONE);
}
private void testNearCacheInvalidation_whenMaxSizeExceeded(EvictionPolicy evictionPolicy) {
int mapSize = 2000;
final int maxSize = 1000;
final IMap<Integer, Integer> map = getMapConfiguredWithMaxSizeAndPolicy(evictionPolicy, maxSize);
populateMap(map, mapSize);
populateNearCache(map, mapSize);
assertTrueEventually(new AssertTask() {
@Override
public void run() {
long ownedEntryCount = getNearCacheStats(map).getOwnedEntryCount();
assertEquals(maxSize, ownedEntryCount);
}
});
}
private IMap<Integer, Integer> getMapConfiguredWithMaxSizeAndPolicy(EvictionPolicy evictionPolicy, int maxSize) {
String mapName = randomMapName();
Config config = getConfig();
config.getMapConfig(mapName).setNearCacheConfig(newNearCacheConfigWithEntryCountEviction(evictionPolicy, maxSize));
HazelcastInstance instance = createHazelcastInstance(config);
return instance.getMap(mapName);
}
@Test
public void testNearCacheGetAsyncTwice() throws Exception {
String mapName = randomName();
NearCacheConfig nearCacheConfig = newNearCacheConfig();
nearCacheConfig.setInMemoryFormat(InMemoryFormat.OBJECT);
nearCacheConfig.getEvictionConfig()
.setMaximumSizePolicy(EvictionConfig.MaxSizePolicy.ENTRY_COUNT)
.setSize(10);
Config config = getConfig();
config.addMapConfig(new MapConfig(mapName).setNearCacheConfig(nearCacheConfig));
HazelcastInstance instance = createHazelcastInstance(config);
IMap<Integer, Integer> map = instance.getMap(mapName);
map.getAsync(1).get();
sleepMillis(1000);
assertNull(map.getAsync(1).get());
}
/**
* Near Cache has its own eviction/expiration mechanism, so eviction/expiration on an IMap
* should not force any Near Cache eviction/expiration. Exceptions from this rule are direct calls to
* <ul>
* <li>{@link IMap#evict(Object)}</li>
* <li>{@link IMap#evictAll()}</li>
* </ul>
*/
@Test
public void testNearCacheEntriesNotExpired_afterIMapExpiration() {
int mapSize = 3;
String mapName = randomMapName();
Config config = createNearCachedMapConfig(mapName);
HazelcastInstance instance = createHazelcastInstance(config);
IMap<Integer, Integer> map = instance.getMap(mapName);
CountDownLatch latch = new CountDownLatch(mapSize);
addEntryEvictedListener(map, latch);
populateMapWithExpirableEntries(map, mapSize, 3, TimeUnit.SECONDS);
populateNearCache(map, mapSize);
int nearCacheSizeBeforeExpiration = getNearCacheSize(map);
waitUntilEvictionEventsReceived(latch);
// wait some extra time for possible events
sleepSeconds(2);
int nearCacheSizeAfterExpiration = getNearCacheSize(map);
NearCacheStats stats = getNearCacheStats(map);
assertEquals(0, stats.getExpirations());
assertEquals(0, stats.getEvictions());
assertEquals(nearCacheSizeBeforeExpiration, nearCacheSizeAfterExpiration);
}
@Test
public void testMapEvictAll_clearsLocalNearCache() {
int size = 1000;
final String mapName = randomMapName();
Config config = createNearCachedMapConfig(mapName);
config.setProperty(GroupProperty.PARTITION_COUNT.getName(), "1");
TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory();
final HazelcastInstance instance1 = factory.newHazelcastInstance(config);
final HazelcastInstance instance2 = factory.newHazelcastInstance(config);
final HazelcastInstance instance3 = factory.newHazelcastInstance(config);
IMap<Integer, Integer> map = instance1.getMap(mapName);
populateMap(map, size);
populateNearCache(map, size);
map.evictAll();
assertTrueEventually(new AssertTask() {
@Override
public void run() {
assertEquals(0, getNearCacheSize(instance1.getMap(mapName)));
assertEquals(0, getNearCacheSize(instance2.getMap(mapName)));
assertEquals(0, getNearCacheSize(instance3.getMap(mapName)));
}
});
}
@Test
public void testMapClear_clearsLocalNearCache() {
int size = 1000;
final String mapName = randomMapName();
Config config = createNearCachedMapConfig(mapName);
config.setProperty(GroupProperty.PARTITION_COUNT.getName(), "1");
TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory();
final HazelcastInstance instance1 = factory.newHazelcastInstance(config);
final HazelcastInstance instance2 = factory.newHazelcastInstance(config);
final HazelcastInstance instance3 = factory.newHazelcastInstance(config);
IMap<Integer, Integer> map = instance1.getMap(mapName);
populateMap(map, size);
populateNearCache(map, size);
map.clear();
assertTrueEventually(new AssertTask() {
@Override
public void run() {
assertEquals(0, getNearCacheSize(instance1.getMap(mapName)));
assertEquals(0, getNearCacheSize(instance2.getMap(mapName)));
assertEquals(0, getNearCacheSize(instance3.getMap(mapName)));
}
});
}
@Test
public void testNearCacheTTLRecordsExpired() {
String mapName = randomMapName();
Config config = getConfig();
config.getMapConfig(mapName).setNearCacheConfig(newNearCacheConfig()
.setCacheLocalEntries(true)
.setTimeToLiveSeconds(MAX_TTL_SECONDS)
);
TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(2);
HazelcastInstance instance = factory.newHazelcastInstance(config);
IMap<Integer, Integer> map = instance.getMap(mapName);
testNearCacheExpiration(map, MAX_CACHE_SIZE, MAX_TTL_SECONDS);
}
@Test
public void testNearCacheMaxIdleRecordsExpired() {
String mapName = randomMapName();
Config config = getConfig();
config.getMapConfig(mapName).setNearCacheConfig(newNearCacheConfig()
.setCacheLocalEntries(true)
.setMaxIdleSeconds(MAX_IDLE_SECONDS)
);
TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(2);
HazelcastInstance instance = factory.newHazelcastInstance(config);
IMap<Integer, Integer> map = instance.getMap(mapName);
testNearCacheExpiration(map, MAX_CACHE_SIZE, MAX_IDLE_SECONDS);
}
@Test(expected = IllegalArgumentException.class)
public void testNearCache_whenInMemoryFormatIsNative_thenThrowIllegalArgumentException() {
String mapName = randomMapName();
Config config = getConfig();
config.getMapConfig(mapName).setNearCacheConfig(newNearCacheConfig()
.setInMemoryFormat(InMemoryFormat.NATIVE)
);
TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(2);
HazelcastInstance instance = factory.newHazelcastInstance(config);
instance.getMap(mapName);
}
}