View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.util.queue;
8   
9   import org.mule.tck.junit4.AbstractMuleContextTestCase;
10  import org.mule.util.concurrent.Latch;
11  import org.mule.util.xa.AbstractResourceManager;
12  
13  import java.util.Random;
14  
15  import org.apache.commons.logging.Log;
16  import org.apache.commons.logging.LogFactory;
17  import org.junit.Test;
18  
19  import static org.junit.Assert.assertEquals;
20  import static org.junit.Assert.assertFalse;
21  import static org.junit.Assert.assertNotNull;
22  import static org.junit.Assert.assertNull;
23  import static org.junit.Assert.assertTrue;
24  
25  public abstract class AbstractTransactionQueueManagerTestCase extends AbstractMuleContextTestCase
26  {
27  
28      /**
29       * logger used by this class
30       */
31      protected transient Log logger = LogFactory.getLog(getClass());
32  
33      protected abstract TransactionalQueueManager createQueueManager() throws Exception;
34  
35      protected abstract boolean isPersistent();
36  
37      @Test
38      public void testPutTake() throws Exception
39      {
40          TransactionalQueueManager mgr = createQueueManager();
41          mgr.start();
42  
43          QueueSession s = mgr.getQueueSession();
44          Queue q = s.getQueue("queue1");
45  
46          assertEquals("Queue size", 0, q.size());
47          q.put("String1");
48          assertEquals("Queue size", 1, q.size());
49          Object o = q.take();
50          assertNotNull(o);
51          assertEquals("Queue content", "String1", o);
52          assertEquals("Queue size", 0, q.size());
53  
54          purgeQueue(q);
55          
56          mgr.stop(AbstractResourceManager.SHUTDOWN_MODE_NORMAL);
57      }
58  
59      @Test
60      public void testTakePut() throws Exception
61      {
62          final TransactionalQueueManager mgr = createQueueManager();
63          mgr.start();
64  
65          final Latch latch = new Latch();
66  
67          Thread t = new Thread()
68          {
69              @Override
70              public void run()
71              {
72                  try
73                  {
74                      latch.countDown();
75                      Thread.sleep(200);
76                      QueueSession s = mgr.getQueueSession();
77                      Queue q = s.getQueue("queue1");
78                      assertEquals("Queue size", 0, q.size());
79                      q.put("String1");
80                  }
81                  catch (Exception e)
82                  {
83                      // ignore, let test fail
84                  }
85              }
86          };
87          t.start();
88          latch.await();
89          long t0 = System.currentTimeMillis();
90          QueueSession s = mgr.getQueueSession();
91          Queue q = s.getQueue("queue1");
92          assertEquals("Queue size", 0, q.size());
93          Object o = q.take();
94          long t1 = System.currentTimeMillis();
95          t.join();
96          assertNotNull(o);
97          assertEquals("Queue content", "String1", o);
98          assertEquals("Queue size", 0, q.size());
99          assertTrue(t1 - t0 > 100);
100 
101         purgeQueue(q);
102         
103         mgr.stop(AbstractResourceManager.SHUTDOWN_MODE_NORMAL);
104     }
105     
106     @Test
107     public void testPutTakeUntake() throws Exception
108     {
109         final TransactionalQueueManager mgr = createQueueManager();
110         mgr.start();
111 
112         final Latch latch = new Latch();
113 
114         Thread t = new Thread()
115         {
116             @Override
117             public void run()
118             {
119                 try
120                 {
121                     latch.countDown();
122                     Thread.sleep(200);
123                     QueueSession s = mgr.getQueueSession();
124                     Queue q = s.getQueue("queue1");
125                     assertEquals("Queue size", 0, q.size());
126                     q.put("String1");
127                     q.put("String2");
128                 }
129                 catch (Exception e)
130                 {
131                     // ignore, let test fail
132                 }
133             }
134         };
135         t.start();
136         latch.await();
137         long t0 = System.currentTimeMillis();
138         QueueSession s = mgr.getQueueSession();
139         Queue q = s.getQueue("queue1");
140         assertEquals("Queue size", 0, q.size());
141         Object o = q.take();
142         long t1 = System.currentTimeMillis();
143         t.join();
144         assertNotNull(o);
145         assertEquals("Queue content", "String1", o);
146         assertEquals("Queue size", 1, q.size());
147         assertTrue(t1 - t0 > 100);
148 
149         // Same as put/take until now, but now we do an untake
150         q.untake(o);
151         // Ensure queue size is now 2
152         assertEquals("Queue size", 2, q.size());
153         // Take to ensure order is correct
154         Object o2 = q.take();
155         assertEquals("Queue content", "String1", o2);
156         assertEquals("Queue size", 1, q.size());
157         
158         purgeQueue(q);
159         
160         mgr.stop(AbstractResourceManager.SHUTDOWN_MODE_NORMAL);
161 
162     }
163 
164     @Test
165     public void testTakePutRollbackPut() throws Exception
166     {
167         final TransactionalQueueManager mgr = createQueueManager();
168         mgr.start();
169 
170         final Latch latch = new Latch();
171 
172         Thread t = new Thread()
173         {
174             @Override
175             public void run()
176             {
177                 try
178                 {
179                     latch.countDown();
180                     Thread.sleep(200);
181                     QueueSession s = mgr.getQueueSession();
182                     Queue q = s.getQueue("queue1");
183                     assertEquals("Queue size", 0, q.size());
184                     s.begin();
185                     q.put("String1");
186                     s.rollback();
187                     s.begin();
188                     q.put("String2");
189                     s.commit();
190                 }
191                 catch (Exception e)
192                 {
193                     // ignore, let test fail
194                 }
195             }
196         };
197         t.start();
198         latch.await();
199         long t0 = System.currentTimeMillis();
200         QueueSession s = mgr.getQueueSession();
201         Queue q = s.getQueue("queue1");
202         assertEquals("Queue size", 0, q.size());
203         Object o = q.take();
204         long t1 = System.currentTimeMillis();
205         t.join();
206         assertNotNull(o);
207         assertEquals("Queue content", "String2", o);
208         assertEquals("Queue size", 0, q.size());
209         assertTrue(t1 - t0 > 100);
210 
211         purgeQueue(q);
212         
213         mgr.stop(AbstractResourceManager.SHUTDOWN_MODE_NORMAL);
214     }
215 
216     @Test
217     public void testPutTakeUntakeRollbackUntake() throws Exception
218     {
219         final TransactionalQueueManager mgr = createQueueManager();
220         mgr.start();
221 
222         final Latch latch = new Latch();
223 
224         final Object object1 = "string1";
225         final Object object2 = "string2";
226         
227         Thread t = new Thread()
228         {
229             @Override
230             public void run()
231             {
232                 try
233                 {
234                     latch.countDown();
235                     Thread.sleep(200);
236                     QueueSession s = mgr.getQueueSession();
237                     Queue q = s.getQueue("queue1");
238                     assertEquals("Queue size", 0, q.size());
239                     
240                     s.begin();
241                     q.put(object1);
242                     q.put(object2);
243                     q.take();
244                     q.take();
245                     s.commit();
246 
247                     s.begin();
248                     q.untake(object1);
249                     s.commit();
250                     
251                     s.begin();
252                     q.untake(object2);
253                     s.rollback();
254                 }
255                 catch (Exception e)
256                 {
257                     // ignore, let test fail
258                 }
259             }
260         };
261         t.start();
262         latch.await();
263         long t0 = System.currentTimeMillis();
264         QueueSession s = mgr.getQueueSession();
265         Queue q = s.getQueue("queue1");
266         assertEquals("Queue size", 0, q.size());
267         Object o = q.take();
268         long t1 = System.currentTimeMillis();
269         t.join();
270         assertNotNull(o);
271         assertEquals("Queue content", object1, o);
272         assertEquals("Queue size", 0, q.size());
273         assertTrue(t1 - t0 > 100);
274 
275         purgeQueue(q);
276         
277         mgr.stop(AbstractResourceManager.SHUTDOWN_MODE_NORMAL);
278     }
279 
280     @Test
281     public void testTakePutOverCapacity() throws Exception
282     {
283         final TransactionalQueueManager mgr = createQueueManager();
284         mgr.start();
285         mgr.setDefaultQueueConfiguration(new QueueConfiguration(2));
286 
287         final Latch latch = new Latch();
288 
289         Thread t = new Thread()
290         {
291             @Override
292             public void run()
293             {
294                 try
295                 {
296                     latch.await();
297                     Thread.sleep(200);
298                     QueueSession s = mgr.getQueueSession();
299                     Queue q = s.getQueue("queue1");
300                     Object o = q.take();
301                     assertEquals("Queue content", "String1", o);
302                 }
303                 catch (Exception e)
304                 {
305                     // ignore, let test fail
306                 }
307             }
308         };
309         t.start();
310         QueueSession s = mgr.getQueueSession();
311         Queue q = s.getQueue("queue1");
312         assertEquals("Queue size", 0, q.size());
313         q.put("String1");
314         q.put("String2");
315         latch.countDown();
316         long t0 = System.currentTimeMillis();
317         q.put("String3");
318         long t1 = System.currentTimeMillis();
319         t.join();
320         assertEquals("Queue size", 2, q.size());
321         assertTrue(t1 - t0 > 100);
322 
323         purgeQueue(q);
324         
325         mgr.stop(AbstractResourceManager.SHUTDOWN_MODE_NORMAL);
326     }
327 
328     @Test
329     public void testPutWithPersistence() throws Exception
330     {
331         if (isPersistent())
332         {
333             TransactionalQueueManager mgr = createQueueManager();
334 
335             try
336             {
337                 mgr.start();
338 
339                 QueueSession s = mgr.getQueueSession();
340                 Queue q = s.getQueue("queue1");
341                 q.put("String1");
342                 assertEquals("Queue size", 1, q.size());
343 
344                 q = s.getQueue("queue1");
345                 assertEquals("Queue size", 1, q.size());
346             }
347             finally
348             {
349                 mgr.stop(AbstractResourceManager.SHUTDOWN_MODE_NORMAL);
350             }
351 
352             mgr = createQueueManager();
353             try
354             {
355                 mgr.start();
356                 QueueSession s = mgr.getQueueSession();
357                 Queue q = s.getQueue("queue1");
358                 assertEquals("Queue size", 1, q.size());
359                 
360                 purgeQueue(q);
361             }
362             finally
363             {
364                 mgr.stop(AbstractResourceManager.SHUTDOWN_MODE_NORMAL);
365             }
366         }
367         else
368         {
369             logger.info("Ignoring test because queue manager is not persistent");
370         }
371     }
372 
373     @Test
374     public void testTransactedPutCommitWithPersistence() throws Exception
375     {
376         if (isPersistent())
377         {
378             TransactionalQueueManager mgr = createQueueManager();
379 
380             try
381             {
382                 mgr.start();
383 
384                 QueueSession s = mgr.getQueueSession();
385                 Queue q = s.getQueue("queue1");
386                 s.begin();
387                 q.put("String1");
388                 assertEquals("Queue size", 1, q.size());
389                 s.commit();
390                 assertEquals("Queue size", 1, q.size());
391 
392                 s = mgr.getQueueSession();
393                 q = s.getQueue("queue1");
394                 assertEquals("Queue size", 1, q.size());
395 
396                 mgr.stop(AbstractResourceManager.SHUTDOWN_MODE_NORMAL);
397 
398                 mgr = createQueueManager();
399                 mgr.start();
400                 s = mgr.getQueueSession();
401                 q = s.getQueue("queue1");
402                 assertEquals("Queue size", 1, q.size());
403 
404                 purgeQueue(q);
405             }
406             finally
407             {
408                 mgr.stop(AbstractResourceManager.SHUTDOWN_MODE_NORMAL);
409             }
410         }
411         else
412         {
413             logger.info("Ignoring test because queue manager is not persistent");
414         }
415     }
416 
417     @Test
418     public void testTransactedPutRollbackWithPersistence() throws Exception
419     {
420         if (isPersistent())
421         {
422             TransactionalQueueManager mgr = createQueueManager();
423 
424             try
425             {
426                 mgr.start();
427 
428                 QueueSession s = mgr.getQueueSession();
429                 Queue q = s.getQueue("queue1");
430                 s.begin();
431                 q.put("String1");
432                 assertEquals("Queue size", 1, q.size());
433                 s.rollback();
434                 assertEquals("Queue size", 0, q.size());
435 
436                 s = mgr.getQueueSession();
437                 q = s.getQueue("queue1");
438                 assertEquals("Queue size", 0, q.size());
439 
440                 mgr.stop(AbstractResourceManager.SHUTDOWN_MODE_NORMAL);
441 
442                 mgr = createQueueManager();
443                 mgr.start();
444                 s = mgr.getQueueSession();
445                 q = s.getQueue("queue1");
446                 assertEquals("Queue size", 0, q.size());
447 
448                 purgeQueue(q);
449             }
450             finally
451             {
452 
453                 mgr.stop(AbstractResourceManager.SHUTDOWN_MODE_NORMAL);
454 
455             }
456         }
457         else
458         {
459             logger.info("Ignoring test because queue manager is not persistent");
460         }
461     }
462 
463     @Test
464     public void testPutTake_RespectsOrderOnPersistence() throws Exception
465     {
466         if (isPersistent())
467         {
468             TransactionalQueueManager mgr1 = createQueueManager();
469             mgr1.start();
470 
471             QueueSession s1 = mgr1.getQueueSession();
472             Queue q1 = s1.getQueue("queue1");
473 
474             assertEquals("Queue size", 0, q1.size());
475             final int numberOfElements = 10;
476             for (int i = 1; i <= numberOfElements; i++)
477             {
478                 q1.put("String" + i);
479                 assertEquals("Queue size", i, q1.size());
480             }
481 
482             mgr1.stop(AbstractResourceManager.SHUTDOWN_MODE_NORMAL);
483 
484             TransactionalQueueManager mgr2 = createQueueManager();
485             mgr2.start();
486 
487             QueueSession s2 = mgr2.getQueueSession();
488             Queue q2 = s2.getQueue("queue1");
489 
490             for (int i = 1; i <= numberOfElements; i++)
491             {
492                 Object o = q2.take();
493                 assertNotNull(o);
494                 assertEquals("Queue content", "String" + i, o);
495             }
496             assertEquals("Queue size", 0, q2.size());
497 
498             purgeQueue(q2);
499 
500             mgr2.stop(AbstractResourceManager.SHUTDOWN_MODE_NORMAL);
501         }
502     }
503 
504     @Test
505     public void testTransactionsOnMultipleQueues() throws Exception
506     {
507 
508         TransactionalQueueManager mgr = createQueueManager();
509 
510         try
511         {
512             mgr.start();
513 
514             QueueSession s1 = mgr.getQueueSession();
515             QueueSession s2 = mgr.getQueueSession();
516 
517             Queue q1s1 = s1.getQueue("queue1");
518             Queue q1s2 = s2.getQueue("queue1");
519             Queue q2s1 = s1.getQueue("queue2");
520             Queue q2s2 = s2.getQueue("queue2");
521 
522             q1s1.put("String1");
523             assertEquals("Queue size", 1, q1s1.size());
524             assertEquals("Queue size", 1, q1s2.size());
525 
526             s1.begin();
527 
528             Object o = q1s1.take();
529             assertNotNull(o);
530             assertEquals("String1", o);
531             assertEquals("Queue size", 0, q1s1.size());
532             assertEquals("Queue size", 0, q1s2.size());
533             q2s1.put("String2");
534             assertEquals("Queue size", 1, q2s1.size());
535             assertEquals("Queue size", 0, q2s2.size());
536 
537             s1.commit();
538 
539             assertEquals("Queue size", 0, q1s1.size());
540             assertEquals("Queue size", 0, q1s2.size());
541             assertEquals("Queue size", 1, q2s1.size());
542             assertEquals("Queue size", 1, q2s2.size());
543 
544             s1.begin();
545 
546             o = q2s1.take();
547             assertNotNull(o);
548             assertEquals("String2", o);
549             assertEquals("Queue size", 0, q1s1.size());
550             assertEquals("Queue size", 0, q1s2.size());
551             assertEquals("Queue size", 0, q2s1.size());
552             assertEquals("Queue size", 0, q2s2.size());
553 
554             q1s1.put("String1");
555 
556             assertEquals("Queue size", 1, q1s1.size());
557             assertEquals("Queue size", 0, q1s2.size());
558             assertEquals("Queue size", 0, q2s1.size());
559             assertEquals("Queue size", 0, q2s2.size());
560 
561             s1.rollback();
562 
563             assertEquals("Queue size", 0, q1s1.size());
564             assertEquals("Queue size", 0, q1s2.size());
565             assertEquals("Queue size", 1, q2s1.size());
566             assertEquals("Queue size", 1, q2s2.size());
567             
568             purgeQueue(q1s1);
569             purgeQueue(q1s2);
570             purgeQueue(q2s1);
571             purgeQueue(q2s2);
572         }
573         finally
574         {
575             mgr.stop(AbstractResourceManager.SHUTDOWN_MODE_NORMAL);
576         }
577     }
578 
579     @Test
580     public void testPoll() throws Exception
581     {
582 
583         final TransactionalQueueManager mgr = createQueueManager();
584 
585         try
586         {
587             mgr.start();
588 
589             QueueSession s = mgr.getQueueSession();
590             Queue q = s.getQueue("queue1");
591 
592             assertEquals("Queue size", 0, q.size());
593             Object o = q.poll(0);
594             assertEquals("Queue size", 0, q.size());
595             assertNull(o);
596             o = q.poll(1000);
597             assertEquals("Queue size", 0, q.size());
598             assertNull(o);
599             q.put("String1");
600             assertEquals("Queue size", 1, q.size());
601             o = q.poll(0);
602             assertEquals("Queue size", 0, q.size());
603             assertEquals("Queue content", "String1", o);
604 
605             new Thread(new Runnable()
606             {
607                 public void run()
608                 {
609                     try
610                     {
611                         Thread.sleep(500);
612                         QueueSession s = mgr.getQueueSession();
613                         Queue q = s.getQueue("queue1");
614                         q.put("String1");
615                     }
616                     catch (Exception e)
617                     {
618                         e.printStackTrace();
619                     }
620                 }
621             }).start();
622             o = q.poll(1000);
623             assertEquals("Queue size", q.size(), 0);
624             assertEquals("Queue content", "String1", o);
625         
626             purgeQueue(q);
627         }
628         finally
629         {
630             mgr.stop(AbstractResourceManager.SHUTDOWN_MODE_NORMAL);
631         }
632     }
633 
634     @Test
635     public void testPeek() throws Exception
636     {
637 
638         TransactionalQueueManager mgr = createQueueManager();
639 
640         try
641         {
642             mgr.start();
643 
644             QueueSession s = mgr.getQueueSession();
645             Queue q = s.getQueue("queue1");
646 
647             assertEquals("Queue size", 0, q.size());
648             Object o = q.peek();
649             assertEquals("Queue size", 0, q.size());
650             assertNull(o);
651             q.put("String1");
652             assertEquals("Queue size", 1, q.size());
653             o = q.peek();
654             assertEquals("Queue size", 1, q.size());
655             assertEquals("Queue content", "String1", o);
656             o = q.poll(1000);
657             assertEquals("Queue size", 0, q.size());
658             assertEquals("Queue content", "String1", o);
659             
660             purgeQueue(q);
661         }
662         finally
663         {
664             mgr.stop(AbstractResourceManager.SHUTDOWN_MODE_NORMAL);
665         }
666     }
667 
668     @Test
669     public void testOffer() throws Exception
670     {
671 
672         final TransactionalQueueManager mgr = createQueueManager();
673         mgr.setDefaultQueueConfiguration(new QueueConfiguration(1));
674         try
675         {
676             mgr.start();
677 
678             QueueSession s = mgr.getQueueSession();
679             Queue q = s.getQueue("queue1");
680 
681             assertEquals("Queue size", 0, q.size());
682             assertTrue(q.offer("String1", 0L));
683             assertEquals("Queue size", 1, q.size());
684             assertFalse(q.offer("String2", 1000));
685             assertEquals("Queue size", 1, q.size());
686 
687             new Thread(new Runnable()
688             {
689                 public void run()
690                 {
691                     try
692                     {
693                         Thread.sleep(500);
694                         QueueSession s = mgr.getQueueSession();
695                         Queue q = s.getQueue("queue1");
696                         assertEquals("Queue content", "String1", q.take());
697                     }
698                     catch (Exception e)
699                     {
700                         e.printStackTrace();
701                     }
702                 }
703             }).start();
704             assertTrue(q.offer("String2", 1000));
705             assertEquals("Queue size", 1, q.size());
706             
707             purgeQueue(q);
708         }
709         finally
710         {
711             mgr.stop(AbstractResourceManager.SHUTDOWN_MODE_NORMAL);
712         }
713     }
714 
715     @Test
716     public void testBench() throws Exception
717     {
718 
719         TransactionalQueueManager mgr = createQueueManager();
720 
721         try
722         {
723             mgr.start();
724 
725             QueueSession s = mgr.getQueueSession();
726             Queue q = s.getQueue("queue1");
727 
728             Random rnd = new Random();
729             long t0 = System.currentTimeMillis();
730             for (int i = 0; i < 1; i++)
731             {
732                 for (int j = 0; j < 500; j++)
733                 {
734                     byte[] o = new byte[2048];
735                     rnd.nextBytes(o);
736                     q.put(o);
737                 }
738                 while (q.size() > 0)
739                 {
740                     q.take();
741                 }
742             }
743             long t1 = System.currentTimeMillis();
744 
745             logger.info("Time: " + (t1 - t0) + " ms");
746             
747             purgeQueue(q);
748         }
749         finally
750         {
751             mgr.stop(AbstractResourceManager.SHUTDOWN_MODE_NORMAL);
752         }
753     }
754     
755     protected void purgeQueue(Queue queue) throws InterruptedException
756     {
757         while(queue.size() > 0)
758         {
759             queue.poll(1000);
760         }
761         assertEquals("Queue must be fully consumed after successful test run. Queue size:", 0, queue.size());
762     }
763 
764     @Test
765     public void testRecoverWarmRestart() throws Exception
766     {
767         TransactionalQueueManager mgr = createQueueManager();
768         mgr.start();
769         QueueSession s = mgr.getQueueSession();
770         Queue q = s.getQueue("warmRecoverQueue");
771 
772         int toPopulate = 500;
773 
774         // Populate queue
775         Random rnd = new Random();
776         for (int j = 0; j < toPopulate; j++)
777         {
778             byte[] o = new byte[2048];
779             rnd.nextBytes(o);
780             q.put(o);
781         }
782         assertEquals(q.size(), toPopulate);
783 
784         // Stop and start TransactionalQueueManager
785         mgr.stop();
786         mgr.start();
787 
788         assertEquals(toPopulate, q.size());
789     }
790 
791     @Test
792     public void testRecoverColdRestart() throws Exception
793     {
794         TransactionalQueueManager mgr = createQueueManager();
795         mgr.start();
796         QueueSession s = mgr.getQueueSession();
797         Queue q = s.getQueue("warmRecoverQueue");
798 
799         int toPopulate = 500;
800 
801         // Populate queue
802         Random rnd = new Random();
803         for (int j = 0; j < toPopulate; j++)
804         {
805             byte[] o = new byte[2048];
806             rnd.nextBytes(o);
807             q.put(o);
808         }
809         assertEquals(toPopulate, q.size());
810 
811         // Stop and recreate TransactionalQueueManager simulating a cold restart
812         mgr.stop();
813         mgr = createQueueManager();
814         mgr.start();
815         s = mgr.getQueueSession();
816         q = s.getQueue("warmRecoverQueue");
817 
818         if (isPersistent())
819         {
820             assertEquals(toPopulate, q.size());
821         }
822         else
823         {
824             assertEquals(0, q.size());
825         }
826 
827     }
828     
829 }