package org.infinispan.stats.topK;
import static org.infinispan.test.TestingUtil.k;
import static org.testng.AssertJUnit.fail;
import java.lang.reflect.Method;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.transaction.RollbackException;
import javax.transaction.Transaction;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.interceptors.impl.TxInterceptor;
import org.infinispan.stats.AbstractTopKeyTest;
import org.infinispan.test.TestingUtil;
import org.infinispan.test.fwk.CleanupAfterTest;
import org.infinispan.util.concurrent.IsolationLevel;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
* @author Pedro Ruivo
* @since 6.0
*/
@Test(groups = "functional", testName = "stats.topK.LocalTopKeyTest")
@CleanupAfterTest
public class LocalTopKeyTest extends AbstractTopKeyTest {
@BeforeMethod(alwaysRun = true)
public void resetBeforeTest() {
getTopKey(cache(0)).resetStatistics();
}
public void testPut(Method method) {
final String key1 = k(method, 1);
final String key2 = k(method, 2);
cache(0).put(key1, "value1");
cache(0).put(key2, "value2");
assertTopKeyAccesses(cache(0), key1, 1, false);
assertTopKeyAccesses(cache(0), key2, 1, false);
assertTopKeyAccesses(cache(0), key1, 0, true);
assertTopKeyAccesses(cache(0), key2, 0, true);
assertLockInformation(cache(0), key1, 1, 0, 0);
assertLockInformation(cache(0), key2, 1, 0, 0);
assertWriteSkew(cache(0), key1, 0);
assertWriteSkew(cache(0), key2, 0);
}
public void testGet(Method method) {
final String key1 = k(method, 1);
final String key2 = k(method, 2);
cache(0).get(key1);
cache(0).get(key2);
assertTopKeyAccesses(cache(0), key1, 0, false);
assertTopKeyAccesses(cache(0), key2, 0, false);
assertTopKeyAccesses(cache(0), key1, 1, true);
assertTopKeyAccesses(cache(0), key2, 1, true);
assertLockInformation(cache(0), key1, 0, 0, 0);
assertLockInformation(cache(0), key2, 0, 0, 0);
assertWriteSkew(cache(0), key1, 0);
assertWriteSkew(cache(0), key2, 0);
}
public void testLockFailed(Method method) throws InterruptedException, TimeoutException, ExecutionException {
final String key = k(method, 0);
PrepareCommandBlocker blocker = addPrepareBlockerIfAbsent(cache(0));
blocker.reset();
Future<Void> f = fork(() -> {
cache(0).put(key, "value");
return null;
});
blocker.awaitUntilPrepareBlocked();
//at this point, the key is locked...
try {
cache(0).put(key, "value");
Assert.fail("The key should be locked!");
} catch (Throwable t) {
//expected
}
blocker.unblock();
f.get(30, TimeUnit.SECONDS);
assertTopKeyAccesses(cache(0), key, 2, false);
assertTopKeyAccesses(cache(0), key, 0, true);
assertLockInformation(cache(0), key, 2, 1, 1);
assertWriteSkew(cache(0), key, 0);
}
public void testWriteSkew(Method method) throws Exception {
final String key = k(method, 0);
cache(0).put(key, "init");
tm(0).begin();
cache(0).get(key);
Transaction transaction = tm(0).suspend();
cache(0).put(key, "value");
try {
tm(0).resume(transaction);
cache(0).put(key, "value1");
tm(0).commit();
fail("The write skew should be detected");
} catch (RollbackException t) {
//expected
}
assertTopKeyAccesses(cache(0), key, 3, false);
assertTopKeyAccesses(cache(0), key, 1, true);
//the last put will originate an write skew
assertLockInformation(cache(0), key, 3, 0, 0);
assertWriteSkew(cache(0), key, 1);
}
@Override
protected void createCacheManagers() throws Throwable {
ConfigurationBuilder builder = getDefaultClusteredCacheConfig(CacheMode.LOCAL, true);
builder.customInterceptors().addInterceptor()
.before(TxInterceptor.class)
.interceptor(new CacheUsageInterceptor());
builder.locking().isolationLevel(IsolationLevel.REPEATABLE_READ)
.lockAcquisitionTimeout(TestingUtil.shortTimeoutMillis());
addClusterEnabledCacheManager(builder);
}
}