/* * 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.MapStoreConfig; import com.hazelcast.core.*; import org.junit.After; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import java.util.*; import java.util.concurrent.*; import static org.junit.Assert.*; @RunWith(com.hazelcast.util.RandomBlockJUnit4ClassRunner.class) public class ClusterQueueTest { @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 testOffer() throws Exception { HazelcastInstance h1 = Hazelcast.newHazelcastInstance(new Config()); HazelcastInstance h2 = Hazelcast.newHazelcastInstance(new Config()); final IQueue q1 = h1.getQueue("default"); final IQueue q2 = h2.getQueue("default"); for (int i = 0; i < 100; i++) { assertTrue(q1.offer("item" + i, 100, TimeUnit.SECONDS)); assertTrue(q2.offer("item" + i, 100, TimeUnit.SECONDS)); } assertEquals("item0", q1.peek()); assertEquals("item0", q2.peek()); for (int i = 0; i < 100; i++) { assertEquals("item" + i, q1.poll()); assertEquals("item" + i, q2.poll()); } } @Test public void testDeadTaker() throws Exception { final HazelcastInstance h1 = Hazelcast.newHazelcastInstance(new Config()); final HazelcastInstance h2 = Hazelcast.newHazelcastInstance(new Config()); final IQueue q1 = h1.getQueue("default"); final IQueue q2 = h2.getQueue("default"); new Thread(new Runnable() { public void run() { try { q2.take(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); final CountDownLatch shutdownLatch = new CountDownLatch(1); new Thread(new Runnable() { public void run() { try { Thread.sleep(2000); h2.getLifecycleService().kill(); shutdownLatch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); assertTrue(shutdownLatch.await(100, TimeUnit.SECONDS)); q1.offer("item"); assertEquals(1, q1.size()); assertEquals("item", q1.poll()); } @Test public void testPollTxn() throws Exception { final HazelcastInstance h1 = Hazelcast.newHazelcastInstance(new Config()); final HazelcastInstance h2 = Hazelcast.newHazelcastInstance(new Config()); final HazelcastInstance h3 = Hazelcast.newHazelcastInstance(new Config()); final IQueue q1 = h1.getQueue("default"); final IQueue q2 = h2.getQueue("default"); final IQueue q3 = h3.getQueue("default"); assertTrue(q2.offer("item")); assertEquals(1, h2.getMap("q:default").size()); final CountDownLatch latch = new CountDownLatch(1); new Thread(new Runnable() { public void run() { Transaction txn = h3.getTransaction(); txn.begin(); assertEquals("item", q3.poll()); latch.countDown(); } }).start(); assertTrue(latch.await(50, TimeUnit.SECONDS)); h3.getLifecycleService().shutdown(); Thread.sleep(4000); assertEquals(1, h2.getMap("q:default").size()); assertEquals("item", q2.poll()); final HazelcastInstance h4 = Hazelcast.newHazelcastInstance(new Config()); final IQueue q4 = h4.getQueue("default"); final CountDownLatch latch2 = new CountDownLatch(1); assertTrue(q2.offer("item2")); new Thread(new Runnable() { public void run() { Transaction txn = h1.getTransaction(); txn.begin(); assertEquals("item2", q1.poll()); latch2.countDown(); } }).start(); assertTrue(latch2.await(100, TimeUnit.SECONDS)); h1.getLifecycleService().shutdown(); Thread.sleep(4000); assertEquals("item2", q2.poll()); } @Test public void testShutdown() throws Exception { HazelcastInstance h1 = Hazelcast.newHazelcastInstance(new Config()); HazelcastInstance h2 = Hazelcast.newHazelcastInstance(new Config()); final IQueue q1 = h1.getQueue("default"); final IQueue q2 = h2.getQueue("default"); for (int i = 0; i < 40; ) { assertTrue(q1.offer("item" + i++, 100, TimeUnit.SECONDS)); assertTrue(q2.offer("item" + i++, 100, TimeUnit.SECONDS)); } h1.getLifecycleService().shutdown(); for (int i = 40; i < 100; ) { assertTrue(q2.offer("item" + i++, 100, TimeUnit.SECONDS)); } for (int i = 0; i < 100; i++) { assertEquals("item" + i, q2.poll()); } } @Test public void testPollNull() throws Exception { HazelcastInstance h1 = Hazelcast.newHazelcastInstance(new Config()); HazelcastInstance h2 = Hazelcast.newHazelcastInstance(new Config()); final IQueue q1 = h1.getQueue("default"); final IQueue q2 = h2.getQueue("default"); for (int i = 0; i < 100; i++) { assertNull(q1.poll()); assertNull(q2.poll()); } assertNull(q1.poll(2, TimeUnit.SECONDS)); assertNull(q2.poll(2, TimeUnit.SECONDS)); } @Test public void testTake() throws Exception { HazelcastInstance h1 = Hazelcast.newHazelcastInstance(new Config()); HazelcastInstance h2 = Hazelcast.newHazelcastInstance(new Config()); final IQueue q1 = h1.getQueue("default"); final IQueue q2 = h2.getQueue("default"); new Thread(new Runnable() { public void run() { try { Thread.sleep(3000); for (int i = 0; i < 100; i++) { assertTrue(q1.offer("item")); assertTrue(q2.offer("item")); } } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); final ExecutorService es = Executors.newFixedThreadPool(50); final CountDownLatch latch = new CountDownLatch(200); for (int i = 0; i < 100; i++) { es.execute(new Runnable() { public void run() { try { assertEquals("item", q1.take()); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } }); es.execute(new Runnable() { public void run() { try { assertEquals("item", q2.take()); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } }); } assertTrue(latch.await(100, TimeUnit.SECONDS)); es.shutdown(); } @Test public void testPollLong() throws Exception { HazelcastInstance h1 = Hazelcast.newHazelcastInstance(new Config()); HazelcastInstance h2 = Hazelcast.newHazelcastInstance(new Config()); final IQueue q1 = h1.getQueue("default"); final IQueue q2 = h2.getQueue("default"); Thread.sleep(1000); new Thread(new Runnable() { public void run() { for (int i = 0; i < 100; i++) { assertTrue(q1.offer("item")); assertTrue(q2.offer("item")); } } }).start(); final ExecutorService es = Executors.newFixedThreadPool(50); final CountDownLatch latch = new CountDownLatch(200); Thread.sleep(3000); for (int i = 0; i < 100; i++) { es.execute(new Runnable() { public void run() { try { assertEquals("item", q1.poll(5, TimeUnit.SECONDS)); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } }); es.execute(new Runnable() { public void run() { try { assertEquals("item", q2.poll(5, TimeUnit.SECONDS)); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } }); } assertTrue(latch.await(100, TimeUnit.SECONDS)); es.shutdown(); } @Test public void testOfferLong() throws Exception { Config config = new Config(); config.getQueueConfig("default").setBackingMapRef("default").setMaxSizePerJVM(100); HazelcastInstance h1 = Hazelcast.newHazelcastInstance(config); HazelcastInstance h2 = Hazelcast.newHazelcastInstance(config); final IQueue q1 = h1.getQueue("default"); final IQueue q2 = h2.getQueue("default"); for (int i = 0; i < 100; i++) { assertTrue(q1.offer("item" + i, 100, TimeUnit.SECONDS)); assertTrue(q2.offer("item" + i, 100, TimeUnit.SECONDS)); } assertFalse(q1.offer("item")); assertFalse(q2.offer("item")); assertFalse(q1.offer("item", 2, TimeUnit.SECONDS)); assertFalse(q2.offer("item", 2, TimeUnit.SECONDS)); new Thread(new Runnable() { public void run() { try { Thread.sleep(3000); for (int i = 0; i < 100; i++) { assertEquals("item" + i, q1.poll(2, TimeUnit.SECONDS)); assertEquals("item" + i, q2.poll(2, TimeUnit.SECONDS)); } } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); final ExecutorService es = Executors.newFixedThreadPool(50); final CountDownLatch latch = new CountDownLatch(200); for (int i = 0; i < 100; i++) { es.execute(new Runnable() { public void run() { try { assertTrue(q1.offer("item", 30, TimeUnit.SECONDS)); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } }); es.execute(new Runnable() { public void run() { try { assertTrue(q2.offer("item", 30, TimeUnit.SECONDS)); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } }); } assertTrue(latch.await(100, TimeUnit.SECONDS)); es.shutdown(); } /** * Test case for issue 289. * <p/> * 1. Create instanceA then instanceB, and then a queue on each (same queue name) * 2. put a message on queue from instanceB * 3. take message off on instanceA * 4. shutdown instanceA, then check if queue is still empty on instanceB * * @throws Exception */ @Test public void testQueueAfterShutdown() throws Exception { final HazelcastInstance h1 = Hazelcast.newHazelcastInstance(null); final HazelcastInstance h2 = Hazelcast.newHazelcastInstance(null); IQueue q1 = h1.getQueue("default"); IQueue q2 = h2.getQueue("default"); q2.offer("item"); assertEquals(1, q1.size()); assertEquals(1, q2.size()); assertEquals("item", q1.take()); assertEquals(0, q1.size()); assertEquals(0, q2.size()); h1.getLifecycleService().shutdown(); assertEquals(0, q2.size()); } /** * @throws Exception */ @Test public void testQueueAfterShutdown2() throws Exception { final HazelcastInstance h1 = Hazelcast.newHazelcastInstance(null); final HazelcastInstance h2 = Hazelcast.newHazelcastInstance(null); IQueue q1 = h1.getQueue("default"); IQueue q2 = h2.getQueue("default"); q1.offer("item"); assertEquals(1, q1.size()); assertEquals(1, q2.size()); assertEquals("item", q2.take()); assertEquals(0, q1.size()); assertEquals(0, q2.size()); h2.getLifecycleService().shutdown(); assertEquals(0, q1.size()); } @Test public void queueEntriesShouldBeConsistentAfterShutdown() throws Exception { HazelcastInstance h1 = Hazelcast.newHazelcastInstance(null); HazelcastInstance h2 = Hazelcast.newHazelcastInstance(null); Queue<String> q1 = h1.getQueue("q"); Queue<String> q2 = h2.getQueue("q"); for (int i = 0; i < 5; i++) { q1.offer("item" + i); } assertEquals(5, q1.size()); assertEquals(5, q2.size()); assertEquals("item0", q2.poll()); assertEquals("item1", q2.poll()); assertEquals("item2", q2.poll()); Thread.sleep(10000); assertEquals(2, q1.size()); assertEquals(2, q2.size()); h1.getLifecycleService().shutdown(); Thread.sleep(5000); assertEquals(2, q2.size()); } @Test public void queueEntriesShouldBeConsistentAfterShutdown2() throws Exception { HazelcastInstance h1 = Hazelcast.newHazelcastInstance(null); HazelcastInstance h2 = Hazelcast.newHazelcastInstance(null); Queue<String> q1 = h1.getQueue("q"); Queue<String> q2 = h2.getQueue("q"); for (int i = 0; i < 5; i++) { q1.offer("item" + i); } assertEquals(5, q1.size()); assertEquals(5, q2.size()); assertEquals("item0", q1.poll()); assertEquals("item1", q1.poll()); assertEquals("item2", q1.poll()); Thread.sleep(10000); assertEquals(2, q1.size()); assertEquals(2, q2.size()); h1.getLifecycleService().shutdown(); Thread.sleep(5000); assertEquals(2, q2.size()); } /** * Test case for issue 323 */ @Test public void testSuperClientWithQueues() { Config configSuperClient = new Config(); configSuperClient.setLiteMember(true); HazelcastInstance hNormal = Hazelcast.newHazelcastInstance(new Config()); final HazelcastInstance hSuper = Hazelcast.newHazelcastInstance(configSuperClient); final Queue qSuper = hSuper.getQueue("default"); final Queue qNormal = hNormal.getQueue("default"); for (int i = 0; i < 12000; i++) { String item = "item" + i; qSuper.offer(item); assertEquals(item, qNormal.poll()); } for (int i = 0; i < 5000; i++) { String item = "item" + i; qNormal.offer(item); assertEquals(item, qSuper.poll()); } } @Test(timeout = 100000) public void storedQueueWithExistingItemsAndTransactionRollback() throws InterruptedException { final ConcurrentMap<Long, String> STORE = new ConcurrentHashMap<Long, String>(); for (long i = 1; i < 7; i++) { STORE.put(i, "Event" + i); } final CountDownLatch latch = new CountDownLatch(1); Config config = new Config(); config .getMapConfig("queue-map") .setMapStoreConfig(new MapStoreConfig() .setWriteDelaySeconds(1) .setImplementation(new MapStore<Long, String>() { public String load(Long key) { return STORE.get(key); } public Map<Long, String> loadAll(Collection<Long> keys) { Map<Long, String> result = new HashMap<Long, String>(); for (Long key : keys) { String value = load(key); if (value != null) { result.put(key, value); } } return result; } public Set<Long> loadAllKeys() { return STORE.keySet(); } public void store(Long key, String value) { latch.countDown(); } public void storeAll(Map<Long, String> map) { for (Map.Entry<Long, String> entry : map.entrySet()) { store(entry.getKey(), entry.getValue()); } } public void delete(Long key) { STORE.remove(key); } public void deleteAll(Collection<Long> keys) { for (Long key : STORE.keySet()) { delete(key); } } })); config.getQueueConfig("tasks").setBackingMapRef("queue-map"); HazelcastInstance h = Hazelcast.newHazelcastInstance(config); IQueue q = h.getQueue("tasks"); assertEquals(STORE.size(), q.size()); Transaction t = h.getTransaction(); t.begin(); assertEquals(STORE.get(1L), q.poll()); assertEquals(STORE.get(2L), q.take()); CMap cmap = TestUtil.getCMap(h, "q:tasks"); assertEquals(2, cmap.mapRecords.size()); for (Record record : cmap.mapRecords.values()) { assertTrue(record.isActive()); assertFalse(record.isRemovable()); assertNotNull(record.getValueData()); if (record.getKey().equals(1L)) { assertEquals("Event1", record.getValue()); } else if (record.getKey().equals(2L)) { assertEquals("Event2", record.getValue()); } else { fail("Invalid key: " + record.getKey()); } } t.rollback(); assertFalse(latch.await(5, TimeUnit.SECONDS)); assertEquals(2, cmap.mapRecords.size()); assertEquals(6, STORE.size()); assertEquals(6, q.size()); for (int i = 1; i < 7; i++) { assertEquals("Event" + i, q.poll()); } assertEquals(0, cmap.size()); for (Record record : cmap.mapRecords.values()) { assertFalse(record.isActive()); } } }