package org.jgroups.tests; import static java.util.concurrent.TimeUnit.SECONDS; import org.jgroups.*; import org.jgroups.blocks.ReplicatedHashMap; import org.jgroups.protocols.pbcast.GMS; import org.jgroups.stack.ProtocolStack; import org.jgroups.util.Util; import org.testng.Assert; import org.testng.annotations.Test; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * Tests concurrent startup or replicated hashmap. * * @author vlada */ @Test(groups= { Global.FLUSH }, sequential=true) public class ReplicatedHashMapStartupTest extends ChannelTestBase { public void testConcurrentStartup4Members() { List<ReplicatedHashMap<Address,Integer>> channels=new ArrayList<ReplicatedHashMap<Address,Integer>>(4); try { concurrentStartupHelper(channels, 4); } catch(Exception e) { log.warn("Exception while running testConcurrentStartup4Members", e); for(ReplicatedHashMap<Address,Integer> map: channels) map.stop(); } } public void testConcurrentStartup8Members() { List<ReplicatedHashMap<Address,Integer>> channels=new ArrayList<ReplicatedHashMap<Address,Integer>>(8); try { concurrentStartupHelper(channels, 8); } catch(Exception e) { log.warn("Exception while running testConcurrentStartup8Members", e); for(ReplicatedHashMap<Address,Integer> map: channels) map.stop(); } } protected void concurrentStartupHelper(List<ReplicatedHashMap<Address,Integer>> channels, int channelCount) throws Exception { MyNotification<Address,Integer> n=new MyNotification<Address,Integer>(); JChannel first=null; for(int i=0;i < channelCount;i++) { JChannel c; if(i == 0) { c=createChannel(true, channelCount); modifyGMS(c); first=c; } else { c=createChannel(first); } ReplicatedHashMap<Address,Integer> map=new ReplicatedHashMap<Address,Integer>(c); channels.add(map); map.addNotifier(n); map.setBlockingUpdates(true); } // do a very concurrent startup for(ReplicatedHashMap<Address,Integer> map:channels) { map.getChannel().connect("ReplicatedHashMapStartupTest"); map.start(0); map.put(map.getChannel().getAddress(), new Integer(1)); Util.sleep(100); } boolean converged=false; for(int timeoutToConverge=120,counter=0;counter < timeoutToConverge && !converged;SECONDS.sleep(1),counter++) { for(ReplicatedHashMap<Address,Integer> map:channels) { converged=map.getChannel().getView().size() == channelCount; if(!converged) break; } } // verify all view are correct for(ReplicatedHashMap<Address,Integer> map:channels) Assert.assertEquals(map.getChannel().getView().size(), channelCount, "Correct view"); for(ReplicatedHashMap<Address,Integer> map:channels) map.removeNotifier(n); //verify all maps have all elements for(ReplicatedHashMap<Address,Integer> map:channels) Assert.assertEquals(map.size(), channelCount, "Correct size"); System.out.println("stopping replicated hash maps..."); for(ReplicatedHashMap<Address,Integer> map:channels) map.stop(); } private static void modifyGMS(JChannel c) { ProtocolStack stack=c.getProtocolStack(); GMS gms=(GMS)stack.findProtocol(GMS.class); if(gms != null) gms.setLogCollectMessages(false); } private class MyNotification<K, V> implements org.jgroups.blocks.ReplicatedHashMap.Notification<K,V> { public void contentsCleared() {} public void contentsSet(Map<K,V> new_entries) {} public void entryRemoved(K key) {} public void entrySet(K key, V value) {} public void viewChange(View view, List<Address> new_mbrs, List<Address> old_mbrs) { System.out.println("Got view in ReplicatedHashMap notifier " + view); } } }