/* * 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.*; import com.hazelcast.core.*; import com.hazelcast.util.RandomBlockJUnit4ClassRunner; import org.junit.After; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import java.util.Map; import java.util.Queue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @RunWith(RandomBlockJUnit4ClassRunner.class) public class ListenerLifecycleTest { @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 /** * See <code>{@link MapEntryListenerTest#createAfterDestroyListenerTest()}</code> */ public void testListenerLifecycle() throws InterruptedException { HazelcastInstance hz = Hazelcast.newHazelcastInstance(new Config()); final String name = "testListenerLifecycle"; final int sleep = 100; // IMap IMap map = hz.getMap(name); final CountDownLatch mapLatch = new CountingCountdownLatch(2); final EntryListener el = new EntryAdapter() { public void entryAdded(EntryEvent event) { mapLatch.countDown(); } }; map.addEntryListener(el, false); map.put(1, 1); Thread.sleep(sleep); map.destroy(); map = hz.getMap(name); map.addEntryListener(el, false); map.put(2, 2); Thread.sleep(sleep); map.removeEntryListener(el); map.put(3, 3); Thread.sleep(sleep); assertTrue("Remaining:" + mapLatch.getCount(), mapLatch.await(3, TimeUnit.SECONDS)); map.destroy(); // IQueue IQueue q = hz.getQueue(name); final CountDownLatch qLatch = new CountingCountdownLatch(2); final ItemListener ql = new ItemListener() { public void itemAdded(ItemEvent itemEvent) { qLatch.countDown(); } public void itemRemoved(ItemEvent itemEvent) { } }; q.addItemListener(ql, false); q.offer(1); Thread.sleep(sleep); q.destroy(); q = hz.getQueue(name); q.addItemListener(ql, false); q.offer(2); Thread.sleep(sleep); q.removeItemListener(ql); q.offer(3); Thread.sleep(sleep); assertTrue("Remaining:" + qLatch.getCount(), qLatch.await(3, TimeUnit.SECONDS)); q.destroy(); // ITopic ITopic t = hz.getTopic(name); final CountDownLatch tLatch = new CountingCountdownLatch(2); final MessageListener ml = new MessageListener() { public void onMessage(Message message) { tLatch.countDown(); } }; t.addMessageListener(ml); t.publish(1); Thread.sleep(sleep); t.destroy(); t = hz.getTopic(name); t.addMessageListener(ml); t.publish(2); Thread.sleep(sleep); t.removeMessageListener(ml); t.publish(3); Thread.sleep(sleep); assertTrue("Remaining:" + tLatch.getCount(), tLatch.await(3, TimeUnit.SECONDS)); t.destroy(); // MultiMap MultiMap mmap = hz.getMultiMap(name); final CountDownLatch mmapLatch = new CountingCountdownLatch(2); final EntryListener el2 = new EntryAdapter() { public void entryAdded(EntryEvent event) { mmapLatch.countDown(); } }; mmap.addEntryListener(el2, false); mmap.put(1, 1); Thread.sleep(sleep); mmap.destroy(); mmap = hz.getMultiMap(name); mmap.addEntryListener(el2, false); mmap.put(2, 2); Thread.sleep(sleep); mmap.removeEntryListener(el2); mmap.put(3, 3); Thread.sleep(sleep); assertTrue("Remaining:" + mmapLatch.getCount(), mmapLatch.await(3, TimeUnit.SECONDS)); mmap.destroy(); // IList IList l = hz.getList(name); final CountDownLatch lLatch = new CountingCountdownLatch(2); final ItemListener ll = new ItemListener() { public void itemAdded(ItemEvent itemEvent) { lLatch.countDown(); } public void itemRemoved(ItemEvent itemEvent) { } }; l.addItemListener(ll, false); l.add(1); Thread.sleep(sleep); l.destroy(); l = hz.getList(name); l.addItemListener(ll, false); l.add(2); Thread.sleep(sleep); l.removeItemListener(ll); l.add(3); Thread.sleep(sleep); assertTrue("Remaining:" + lLatch.getCount(), lLatch.await(3, TimeUnit.SECONDS)); l.destroy(); // ISet ISet s = hz.getSet(name); final CountDownLatch sLatch = new CountingCountdownLatch(2); final ItemListener sl = new ItemListener() { public void itemAdded(ItemEvent itemEvent) { sLatch.countDown(); } public void itemRemoved(ItemEvent itemEvent) { } }; s.addItemListener(sl, false); s.add(1); Thread.sleep(sleep); s.destroy(); s = hz.getSet(name); s.addItemListener(sl, false); s.add(2); Thread.sleep(sleep); s.removeItemListener(sl); s.add(3); Thread.sleep(sleep); assertTrue("Remaining:" + sLatch.getCount(), sLatch.await(3, TimeUnit.SECONDS)); s.destroy(); } @Test public void testConfigListenerInitialization() throws InterruptedException { Config config = new Config(); config.addListenerConfig(new ListenerConfig(new CountdownMembershipListener())); final InstanceListener instanceListener = new CountdownInstanceListener(); config.addListenerConfig(new ListenerConfig(instanceListener)); final String configName = "testConfigListenerInitialization-"; MapConfig mapConfig = config.getMapConfig(configName + "*"); mapConfig.addEntryListenerConfig(new EntryListenerConfig(new CountdownEntryListener(), false, true)); QueueConfig queueConfig = config.getQueueConfig(configName + "*"); queueConfig.addItemListenerConfig(new ItemListenerConfig(new CountdownItemListener(), true)); TopicConfig topicConfig = config.getTopicConfig(configName + "*"); topicConfig.addMessageListenerConfig(new ListenerConfig(new CountdownMessageListener())); MultiMapConfig multiMapConfig = config.getMultiMapConfig(configName + "*"); multiMapConfig.addEntryListenerConfig(new EntryListenerConfig(new CountdownMultimapEntryListener(), false, false)); HazelcastInstance hz = null; for (int i = 0; i < CountdownMembershipListener.MEMBERS; i++) { hz = Hazelcast.newHazelcastInstance(config); } assertTrue(CountdownMembershipListener.LATCH.await(5, TimeUnit.SECONDS)); for (int i = 0; i < CountdownInstanceListener.INSTANCES; i++) { Map map = hz.getMap(configName + i); for (int j = 0; j < CountdownEntryListener.ENTRIES; j++) { map.put(j, j); } MultiMap mm = hz.getMultiMap(configName + i); for (int j = 0; j < CountdownMultimapEntryListener.ENTRIES; j++) { mm.put(j, j); } Queue q = hz.getQueue(configName + i); for (int j = 0; j < CountdownItemListener.ENTRIES; j++) { q.offer(j); } ITopic t = hz.getTopic(configName + i); for (int j = 0; j < CountdownMessageListener.MESSAGES; j++) { t.publish(j); } } assertTrue(CountdownInstanceListener.LATCH.await(5, TimeUnit.SECONDS)); assertTrue("Remaining: " + CountdownEntryListener.LATCH.getCount(), CountdownEntryListener.LATCH.await(5, TimeUnit.SECONDS)); assertTrue("Remaining: " + CountdownMultimapEntryListener.LATCH.getCount(), CountdownMultimapEntryListener.LATCH.await(5, TimeUnit.SECONDS)); assertTrue("Remaining: " + CountdownItemListener.LATCH.getCount(), CountdownItemListener.LATCH.await(5, TimeUnit.SECONDS)); assertTrue("Remaining: " + CountdownMessageListener.LATCH.getCount(), CountdownMessageListener.LATCH.await(5, TimeUnit.SECONDS)); } public static class CountdownMembershipListener implements MembershipListener { static final int MEMBERS = 3; static final int EVENT_TOTAL = 6; static final CountDownLatch LATCH = new CountingCountdownLatch(EVENT_TOTAL); public void memberAdded(MembershipEvent membershipEvent) { LATCH.countDown(); } public void memberRemoved(MembershipEvent membershipEvent) { } } public static class CountdownInstanceListener implements InstanceListener { static final int INSTANCES = 5; static final int EVENT_TOTAL = INSTANCES * CountdownMembershipListener.MEMBERS * 5; // map, multimap, topic, queue x2 static final CountDownLatch LATCH = new CountingCountdownLatch(EVENT_TOTAL); public void instanceCreated(InstanceEvent event) { LATCH.countDown(); } public void instanceDestroyed(InstanceEvent event) { } } public static class CountdownEntryListener extends EntryAdapter { static final int ENTRIES = 15; static final int EVENT_TOTAL = CountdownMembershipListener.MEMBERS * CountdownInstanceListener.INSTANCES * ENTRIES; static final CountDownLatch LATCH = new CountingCountdownLatch(EVENT_TOTAL); public void entryAdded(EntryEvent event) { LATCH.countDown(); } } public static class CountdownMultimapEntryListener extends EntryAdapter { static final int ENTRIES = 15; static final int EVENT_TOTAL = CountdownMembershipListener.MEMBERS * CountdownInstanceListener.INSTANCES * ENTRIES; static final CountDownLatch LATCH = new CountingCountdownLatch(EVENT_TOTAL); public void entryAdded(EntryEvent event) { LATCH.countDown(); } } public static class CountdownItemListener implements ItemListener { static final int ENTRIES = 15; static final int EVENT_TOTAL = CountdownMembershipListener.MEMBERS * CountdownInstanceListener.INSTANCES * ENTRIES; static final CountDownLatch LATCH = new CountingCountdownLatch(EVENT_TOTAL); public void itemAdded(ItemEvent itemEvent) { LATCH.countDown(); } public void itemRemoved(ItemEvent itemEvent) { } } public static class CountdownMessageListener implements MessageListener { static final int MESSAGES = 15; static final int EVENT_TOTAL = CountdownMembershipListener.MEMBERS * CountdownInstanceListener.INSTANCES * MESSAGES; static final CountDownLatch LATCH = new CountingCountdownLatch(EVENT_TOTAL); public void onMessage(Message message) { LATCH.countDown(); } } public static class CountingCountdownLatch extends CountDownLatch { final AtomicInteger count; public CountingCountdownLatch(int count) { super(count); this.count = new AtomicInteger(count); } public void countDown() { if (count.decrementAndGet() < 0) { fail("Countdown to negative!"); } super.countDown(); } public void await() throws InterruptedException { super.await(); checkCount(); } public boolean await(long timeout, TimeUnit unit) throws InterruptedException { if (super.await(timeout, unit)) { checkCount(); return true; } return false; } void checkCount() { int c = 0; if ((c = count.get()) < 0) { fail("Countdown to negative = " + c); } } } }