/* * Copyright (c) 2008-2012, Hazel Bilisim Ltd. 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.impl; import com.hazelcast.config.Config; import com.hazelcast.config.WanReplicationConfig; import com.hazelcast.config.WanReplicationRef; import com.hazelcast.config.WanTargetClusterConfig; import com.hazelcast.core.Hazelcast; import com.hazelcast.core.HazelcastInstance; import com.hazelcast.impl.wan.WanMergeListener; import com.hazelcast.merge.PassThroughMergePolicy; import org.junit.After; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import static com.hazelcast.impl.TestUtil.getConcurrentMapManager; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; @RunWith(com.hazelcast.util.RandomBlockJUnit4ClassRunner.class) public class WanReplicationTest { @BeforeClass public static void init() throws Exception { System.setProperty(GroupProperties.PROP_WAIT_SECONDS_BEFORE_JOIN, "1"); System.setProperty(GroupProperties.PROP_VERSION_CHECK_ENABLED, "false"); Hazelcast.shutdownAll(); } @After public void cleanup() throws Exception { Hazelcast.shutdownAll(); } @Test public void testWANClustering() throws Exception { Config c1 = new Config(); Config c2 = new Config(); c1.getGroupConfig().setName("newyork"); c1.addWanReplicationConfig(new WanReplicationConfig() .setName("my-wan") .addTargetClusterConfig(new WanTargetClusterConfig() .addEndpoint("127.0.0.1:5702").setGroupName("london"))); c1.getMapConfig("default").setWanReplicationRef(new WanReplicationRef() .setName("my-wan") .setMergePolicy(PassThroughMergePolicy.NAME)); c2.getGroupConfig().setName("london"); c2.addWanReplicationConfig(new WanReplicationConfig() .setName("my-wan") .addTargetClusterConfig(new WanTargetClusterConfig() .addEndpoint("127.0.0.1:5701").setGroupName("newyork"))); c2.getMapConfig("default").setWanReplicationRef(new WanReplicationRef() .setName("my-wan") .setMergePolicy(PassThroughMergePolicy.NAME)); HazelcastInstance h1 = Hazelcast.newHazelcastInstance(c1); HazelcastInstance h2 = Hazelcast.newHazelcastInstance(c2); HazelcastInstance h12 = Hazelcast.newHazelcastInstance(c1); HazelcastInstance h13 = Hazelcast.newHazelcastInstance(c1); HazelcastInstance h22 = Hazelcast.newHazelcastInstance(c2); int size = 100; MergeLatch mergeLatch1 = new MergeLatch(2 * size); MergeLatch mergeLatch2 = new MergeLatch(size); getConcurrentMapManager(h1).addWanMergeListener(mergeLatch1); getConcurrentMapManager(h12).addWanMergeListener(mergeLatch1); getConcurrentMapManager(h13).addWanMergeListener(mergeLatch1); getConcurrentMapManager(h2).addWanMergeListener(mergeLatch2); getConcurrentMapManager(h22).addWanMergeListener(mergeLatch2); for (int i = 0; i < size; i++) { h2.getMap("default").put(i, "value" + i); h22.getMap("default").put(size + i, "value" + (size + i)); } assertTrue("Latch state: " + mergeLatch1, mergeLatch1.await(60, TimeUnit.SECONDS)); Thread.sleep(1000); assertEquals(0, mergeLatch2.totalOperations()); assertEquals(2 * size, mergeLatch1.getUpdateCount()); assertEquals(2 * size, mergeLatch1.totalOperations()); assertEquals(2 * size, h2.getMap("default").size()); assertEquals(2 * size, h1.getMap("default").size()); assertEquals(2 * size, h12.getMap("default").size()); assertEquals(2 * size, h13.getMap("default").size()); assertEquals(2 * size, h22.getMap("default").size()); mergeLatch1.reset(); for (int i = 0; i < size / 2; i++) { h1.getMap("default").remove(i); h13.getMap("default").remove(size + i); } assertTrue("Latch state: " + mergeLatch2, mergeLatch2.await(60, TimeUnit.SECONDS)); Thread.sleep(1000); assertEquals(size, mergeLatch2.getRemoveCount()); assertEquals(size, mergeLatch2.totalOperations()); assertEquals(0, mergeLatch1.totalOperations()); assertEquals(size, h1.getMap("default").size()); assertEquals(size, h2.getMap("default").size()); assertEquals(size, h12.getMap("default").size()); assertEquals(size, h13.getMap("default").size()); assertEquals(size, h22.getMap("default").size()); } @Test public void testWANClustering2() throws Exception { Config c1 = new Config(); Config c2 = new Config(); c1.getGroupConfig().setName("newyork"); c1.addWanReplicationConfig(new WanReplicationConfig() .setName("my-wan") .addTargetClusterConfig(new WanTargetClusterConfig() .addEndpoint("127.0.0.1:5703").setGroupName("london"))); c1.getMapConfig("default").setWanReplicationRef(new WanReplicationRef() .setName("my-wan") .setMergePolicy(PassThroughMergePolicy.NAME)); c2.getGroupConfig().setName("london"); c2.addWanReplicationConfig(new WanReplicationConfig() .setName("my-wan") .addTargetClusterConfig(new WanTargetClusterConfig() .addEndpoint("127.0.0.1:5701").setGroupName("newyork"))); c2.getMapConfig("default").setWanReplicationRef(new WanReplicationRef() .setName("my-wan") .setMergePolicy(PassThroughMergePolicy.NAME)); HazelcastInstance h10 = Hazelcast.newHazelcastInstance(c1); HazelcastInstance h11 = Hazelcast.newHazelcastInstance(c1); int size = 1000; HazelcastInstance h20 = Hazelcast.newHazelcastInstance(c2); HazelcastInstance h21 = Hazelcast.newHazelcastInstance(c2); HazelcastInstance h12 = Hazelcast.newHazelcastInstance(c1); MergeLatch mergeLatch1 = new MergeLatch(size); getConcurrentMapManager(h10).addWanMergeListener(mergeLatch1); getConcurrentMapManager(h11).addWanMergeListener(mergeLatch1); getConcurrentMapManager(h12).addWanMergeListener(mergeLatch1); MergeLatch mergeLatch2 = new MergeLatch(size); getConcurrentMapManager(h20).addWanMergeListener(mergeLatch2); getConcurrentMapManager(h21).addWanMergeListener(mergeLatch2); for (int i = 0; i < size; i++) { h11.getMap("default").put(i, "value" + i); } assertTrue("Latch state: " + mergeLatch2, mergeLatch2.await(60, TimeUnit.SECONDS)); Thread.sleep(1000); assertEquals(size, mergeLatch2.totalOperations()); assertEquals(0, mergeLatch1.totalOperations()); assertEquals(size, h10.getMap("default").size()); assertEquals(size, h20.getMap("default").size()); assertEquals(size, h12.getMap("default").size()); assertEquals(size, h11.getMap("default").size()); assertEquals(size, h21.getMap("default").size()); mergeLatch2.reset(); for (int i = 0; i < size; i++) { h21.getMap("default").put(size + i, "value" + (size + i)); } assertTrue("Latch state: " + mergeLatch1, mergeLatch1.await(60, TimeUnit.SECONDS)); Thread.sleep(1000); assertEquals(size, mergeLatch1.totalOperations()); assertEquals(0, mergeLatch2.totalOperations()); assertEquals(2 * size, h10.getMap("default").size()); assertEquals(2 * size, h20.getMap("default").size()); assertEquals(2 * size, h12.getMap("default").size()); assertEquals(2 * size, h11.getMap("default").size()); assertEquals(2 * size, h21.getMap("default").size()); mergeLatch1.reset(size / 2); mergeLatch2.reset(size / 2); for (int i = 0; i < size / 2; i++) { h10.getMap("default").remove(i); h21.getMap("default").remove(size + i); } assertTrue("Latch state: " + mergeLatch1, mergeLatch1.await(60, TimeUnit.SECONDS)); assertTrue("Latch state: " + mergeLatch2, mergeLatch2.await(60, TimeUnit.SECONDS)); Thread.sleep(1000); assertEquals(size / 2, mergeLatch1.totalOperations()); assertEquals(size / 2, mergeLatch2.totalOperations()); assertEquals(size, h10.getMap("default").size()); assertEquals(size, h20.getMap("default").size()); assertEquals(size, h12.getMap("default").size()); assertEquals(size, h11.getMap("default").size()); assertEquals(size, h21.getMap("default").size()); } @Test public void testWANClusteringActivePassive() throws Exception { Config c1 = new Config(); Config c2 = new Config(); c1.getGroupConfig().setName("newyork"); c1.addWanReplicationConfig(new WanReplicationConfig() .setName("my-wan") .addTargetClusterConfig(new WanTargetClusterConfig() .addEndpoint("127.0.0.1:5702").setGroupName("london"))); c1.getMapConfig("default").setWanReplicationRef(new WanReplicationRef() .setName("my-wan") .setMergePolicy(PassThroughMergePolicy.NAME)); c2.getGroupConfig().setName("london"); c2.getMapConfig("default").setWanReplicationRef(new WanReplicationRef() .setName("my-wan") .setMergePolicy(PassThroughMergePolicy.NAME)); HazelcastInstance h10 = Hazelcast.newHazelcastInstance(c1); HazelcastInstance h20 = Hazelcast.newHazelcastInstance(c2); int size = 1000; MergeLatch mergeLatch2 = new MergeLatch(size); getConcurrentMapManager(h20).addWanMergeListener(mergeLatch2); for (int i = 0; i < size; i++) { h10.getMap("default").put(i, "value" + i); } assertTrue("Latch state: " + mergeLatch2, mergeLatch2.await(60, TimeUnit.SECONDS)); Thread.sleep(1000); assertEquals(size, mergeLatch2.totalOperations()); assertEquals(size, h10.getMap("default").size()); assertEquals(size, h20.getMap("default").size()); for (int i = 0; i < size; i++) { assertEquals("value" + i, h20.getMap("default").get(i)); } } class MergeLatch implements WanMergeListener { final AtomicInteger removeCount = new AtomicInteger(); final AtomicInteger updateCount = new AtomicInteger(); final AtomicInteger ignoreCount = new AtomicInteger(); final AtomicReference<CountDownLatch> latch; MergeLatch(int count) { latch = new AtomicReference<CountDownLatch>(new CountDownLatch(count)); } public long getCount() { return latch.get().getCount(); } public void countDown() { CountDownLatch l = latch.get(); if (l != null) { l.countDown(); } } public void entryRemoved() { removeCount.incrementAndGet(); countDown(); } public void entryUpdated() { updateCount.incrementAndGet(); countDown(); } public void entryIgnored() { ignoreCount.incrementAndGet(); countDown(); } public int totalOperations() { return getIgnoreCount() + getRemoveCount() + getUpdateCount(); } public int getRemoveCount() { return removeCount.get(); } public int getUpdateCount() { return updateCount.get(); } public int getIgnoreCount() { return ignoreCount.get(); } public void reset() { removeCount.set(0); updateCount.set(0); ignoreCount.set(0); } public void reset(int count) { latch.set(new CountDownLatch(count)); reset(); } public boolean await(int time, TimeUnit timeUnit) throws InterruptedException { return latch.get().await(time, timeUnit); } @Override public String toString() { return "MergeLatch{" + "count=" + getCount() + ", removeCount=" + removeCount.get() + ", updateCount=" + updateCount.get() + ", ignoreCount=" + ignoreCount.get() + '}'; } } }