package org.infinispan.container.offheap;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import org.infinispan.Cache;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.configuration.cache.StorageType;
import org.infinispan.eviction.EvictionType;
import org.infinispan.util.concurrent.IsolationLevel;
import org.testng.annotations.Test;
/**
*/
@Test(groups = "functional", testName = "container.offheap.OffHeapBoundedSingleNodeTest")
public class OffHeapBoundedSingleNodeTest extends OffHeapSingleNodeTest {
private static final int COUNT = 100;
@Override
protected void createCacheManagers() throws Throwable {
ConfigurationBuilder dcc = getDefaultClusteredCacheConfig(CacheMode.LOCAL, true);
dcc.memory().storageType(StorageType.OFF_HEAP).size(COUNT).evictionType(EvictionType.COUNT);
dcc.locking().isolationLevel(IsolationLevel.READ_COMMITTED);
// Only start up the 1 cache
addClusterEnabledCacheManager(dcc);
}
public void testMoreWriteThanSize() {
Cache<String, String> cache = cache(0);
for (int i = 0; i < COUNT + 5; ++i) {
cache.put("key" + i, "value" + i);
}
assertEquals(COUNT, cache.size());
}
public void testMultiThreaded() throws ExecutionException, InterruptedException, TimeoutException {
Cache<String, String> cache = cache(0);
AtomicInteger offset = new AtomicInteger();
AtomicBoolean collision = new AtomicBoolean();
int threadCount = 5;
List<Future> futures = new ArrayList<>(threadCount);
for (int i = 0; i < threadCount; ++i) {
futures.add(fork(() -> {
boolean collide = collision.get();
// We could have overrides, that is fine
collision.set(!collide);
int value = collide ? offset.get() : offset.incrementAndGet();
for (int j = 0; j < COUNT + 5; ++j) {
if (Thread.interrupted()) {
log.tracef("Test was ordered to stop!");
return;
}
String key = "key" + value + "-" + j;
cache.put(key, "value" + value + "-" + j);
}
}));
}
for (Future future : futures) {
try {
future.get(10, TimeUnit.SECONDS);
} catch (Exception e) {
// If we have an exception we need to stop all the others
futures.forEach(f -> f.cancel(true));
throw e;
}
}
int cacheSize = cache.size();
if (cacheSize > COUNT) {
log.fatal("Entries were: " + cache.entrySet().stream().map(Object::toString).collect(Collectors.joining(",")));
}
assertTrue("Cache size was " + cacheSize, cacheSize <= COUNT);
}
}