package com.hazelcast.examples.splitbrain.custom;
import com.hazelcast.cache.CacheEntryView;
import com.hazelcast.cache.CacheMergePolicy;
import com.hazelcast.cache.impl.HazelcastServerCachingProvider;
import com.hazelcast.config.Config;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.examples.splitbrain.AbstractCacheSplitBrainSample;
import javax.cache.Cache;
import javax.cache.CacheManager;
import javax.cache.spi.CachingProvider;
import java.util.concurrent.CountDownLatch;
import static com.hazelcast.examples.helper.CommonUtils.assertClusterSizeEventually;
import static com.hazelcast.examples.helper.CommonUtils.assertOpenEventually;
import static com.hazelcast.examples.helper.CommonUtils.assertTrue;
import static com.hazelcast.examples.helper.HazelcastUtils.generateKeyOwnedBy;
/**
* Base class for jcache split-brain sample based on `custom cache merge policy.
*
* Custom cache merge policy implements {@link com.hazelcast.cache.CacheMergePolicy} and handles its own logic.
*/
abstract class AbstractCacheSplitBrainSampleWithCustomCacheMergePolicy extends AbstractCacheSplitBrainSample {
private static final String CACHE_NAME = BASE_CACHE_NAME + "-custom";
protected abstract Config getConfig();
protected abstract Cache getCache(String cacheName, CacheManager cacheManager);
protected void run() {
try {
Config config = getConfig();
HazelcastInstance h1 = Hazelcast.newHazelcastInstance(config);
HazelcastInstance h2 = Hazelcast.newHazelcastInstance(config);
CountDownLatch splitBrainCompletedLatch = simulateSplitBrain(h1, h2);
CachingProvider cachingProvider1 = HazelcastServerCachingProvider.createCachingProvider(h1);
CachingProvider cachingProvider2 = HazelcastServerCachingProvider.createCachingProvider(h2);
CacheManager cacheManager1 = cachingProvider1.getCacheManager();
CacheManager cacheManager2 = cachingProvider2.getCacheManager();
Cache<String, Object> cache1 = getCache(CACHE_NAME, cacheManager1);
Cache<String, Object> cache2 = getCache(CACHE_NAME, cacheManager2);
// TODO: we assume that until here and also while doing get/put, cluster is still split
// this assumptions seems fragile due to time sensitivity
String key = generateKeyOwnedBy(h1);
cache1.put(key, "value");
cache2.put(key, Integer.valueOf(1));
assertOpenEventually(splitBrainCompletedLatch);
assertClusterSizeEventually(2, h1);
assertClusterSizeEventually(2, h2);
Cache<String, Object> cacheTest = cacheManager2.getCache(CACHE_NAME);
Object value = cacheTest.get(key);
assertTrue("Value with key `" + key + "` should be there!", value != null);
assertTrue("Value with key `" + key + "` should be Integer!", value instanceof Integer);
} finally {
Hazelcast.shutdownAll();
}
}
public static class CustomCacheMergePolicy implements CacheMergePolicy {
@Override
public Object merge(String cacheName, CacheEntryView mergingEntry, CacheEntryView existingEntry) {
if (mergingEntry.getValue() instanceof Integer) {
return mergingEntry.getValue();
}
return null;
}
}
}