/* * Copyright Terracotta, Inc. * * 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 org.ehcache.clustered.replication; import org.ehcache.Cache; import org.ehcache.CacheManager; import org.ehcache.PersistentCacheManager; import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.clustered.client.config.builders.ClusteredStoreConfigurationBuilder; import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder; import org.ehcache.clustered.common.Consistency; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; import org.terracotta.testing.rules.BasicExternalCluster; import org.terracotta.testing.rules.Cluster; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import static java.util.Arrays.asList; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; @RunWith(Parameterized.class) public class BasicClusteredCacheOpsReplicationTest { private static final String RESOURCE_CONFIG = "<config xmlns:ohr='http://www.terracotta.org/config/offheap-resource'>" + "<ohr:offheap-resources>" + "<ohr:resource name=\"primary-server-resource\" unit=\"MB\">16</ohr:resource>" + "</ohr:offheap-resources>" + "</config>\n"; private static PersistentCacheManager CACHE_MANAGER; private static Cache<Long, String> CACHE1; private static Cache<Long, String> CACHE2; @Parameters(name = "consistency={0}") public static Consistency[] data() { return Consistency.values(); } @Parameter public Consistency cacheConsistency; @ClassRule public static Cluster CLUSTER = new BasicExternalCluster(new File("build/cluster"), 2, Collections.emptyList(), "", RESOURCE_CONFIG, ""); @Before public void startServers() throws Exception { CLUSTER.getClusterControl().startAllServers(); CLUSTER.getClusterControl().waitForActive(); CLUSTER.getClusterControl().waitForRunningPassivesInStandby(); final CacheManagerBuilder<PersistentCacheManager> clusteredCacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder() .with(ClusteringServiceConfigurationBuilder.cluster(CLUSTER.getConnectionURI().resolve("/cm-replication")) .autoCreate() .defaultServerResource("primary-server-resource")); CACHE_MANAGER = clusteredCacheManagerBuilder.build(true); CacheConfiguration<Long, String> config = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(100, EntryUnit.ENTRIES) .with(ClusteredResourcePoolBuilder.clusteredDedicated("primary-server-resource", 4, MemoryUnit.MB))) .add(ClusteredStoreConfigurationBuilder.withConsistency(cacheConsistency)) .build(); CACHE1 = CACHE_MANAGER.createCache("clustered-cache", config); CACHE2 = CACHE_MANAGER.createCache("another-cache", config); } @After public void tearDown() throws Exception { CACHE_MANAGER.close(); CACHE_MANAGER.destroy(); } @Test public void testCRUD() throws Exception { List<Cache<Long, String>> caches = new ArrayList<>(); caches.add(CACHE1); caches.add(CACHE2); caches.forEach(x -> { x.put(1L, "The one"); x.put(2L, "The two"); x.put(1L, "Another one"); x.put(3L, "The three"); x.put(4L, "The four"); assertThat(x.get(1L), equalTo("Another one")); assertThat(x.get(2L), equalTo("The two")); assertThat(x.get(3L), equalTo("The three")); x.remove(4L); }); CLUSTER.getClusterControl().terminateActive(); caches.forEach(x -> { assertThat(x.get(1L), equalTo("Another one")); assertThat(x.get(2L), equalTo("The two")); assertThat(x.get(3L), equalTo("The three")); assertThat(x.get(4L), nullValue()); }); } @Test public void testBulkOps() throws Exception { List<Cache<Long, String>> caches = new ArrayList<>(); caches.add(CACHE1); caches.add(CACHE2); Map<Long, String> entriesMap = new HashMap<>(); entriesMap.put(1L, "one"); entriesMap.put(2L, "two"); entriesMap.put(3L, "three"); entriesMap.put(4L, "four"); entriesMap.put(5L, "five"); entriesMap.put(6L, "six"); caches.forEach(cache -> cache.putAll(entriesMap)); CLUSTER.getClusterControl().terminateActive(); Set<Long> keySet = entriesMap.keySet(); caches.forEach(cache -> { Map<Long, String> all = cache.getAll(keySet); assertThat(all.get(1L), is("one")); assertThat(all.get(2L), is("two")); assertThat(all.get(3L), is("three")); assertThat(all.get(4L), is("four")); assertThat(all.get(5L), is("five")); assertThat(all.get(6L), is("six")); }); } @Test public void testCAS() throws Exception { List<Cache<Long, String>> caches = new ArrayList<>(); caches.add(CACHE1); caches.add(CACHE2); caches.forEach(cache -> { assertThat(cache.putIfAbsent(1L, "one"), nullValue()); assertThat(cache.putIfAbsent(2L, "two"), nullValue()); assertThat(cache.putIfAbsent(3L, "three"), nullValue()); assertThat(cache.replace(3L, "another one", "yet another one"), is(false)); }); CLUSTER.getClusterControl().terminateActive(); caches.forEach(cache -> { assertThat(cache.putIfAbsent(1L, "another one"), is("one")); assertThat(cache.remove(2L, "not two"), is(false)); assertThat(cache.replace(3L, "three", "another three"), is(true)); assertThat(cache.replace(2L, "new two"), is("two")); }); } @Test public void testClear() throws Exception { List<Cache<Long, String>> caches = new ArrayList<>(); caches.add(CACHE1); caches.add(CACHE2); Map<Long, String> entriesMap = new HashMap<>(); entriesMap.put(1L, "one"); entriesMap.put(2L, "two"); entriesMap.put(3L, "three"); entriesMap.put(4L, "four"); entriesMap.put(5L, "five"); entriesMap.put(6L, "six"); caches.forEach(cache -> cache.putAll(entriesMap)); Set<Long> keySet = entriesMap.keySet(); caches.forEach(cache -> { Map<Long, String> all = cache.getAll(keySet); assertThat(all.get(1L), is("one")); assertThat(all.get(2L), is("two")); assertThat(all.get(3L), is("three")); assertThat(all.get(4L), is("four")); assertThat(all.get(5L), is("five")); assertThat(all.get(6L), is("six")); }); CACHE1.clear(); CACHE2.clear(); CLUSTER.getClusterControl().terminateActive(); keySet.forEach(x -> assertThat(CACHE1.get(x), nullValue())); keySet.forEach(x -> assertThat(CACHE2.get(x), nullValue())); } }