3 Replies Latest reply on Mar 27, 2009 8:09 AM by Andy Taylor

    bug in session.rollback()

    Andy Taylor Master

      Ive added a test to ClientCommitRollbackTest to show this (commented out).

      basically, if you have a session with 2 consumers receiving from 2 different queues, receive x messages and rollback. All the rolled back messages end up in the sane queue.

      This is because of getRefsOperation(final Transaction tx) in queueimpl. the first time this is called it creates a RefsOperation it and adds it to the tx. the second time it uses the cached one on the tx, but this could be for a different queue. i.e. if you have

      queueA.getRefsOperation( tx);
      queueB.getRefsOperation( tx);
      


      the second line would return the refsOperation for queueA

        • 1. Re: bug in session.rollback()
          Tim Fox Master

          That's fine there should only ever be one GetRefsOperation per tx.

          • 2. Re: bug in session.rollback()
            Tim Fox Master

            Probably the real bug is that it's not using the queue from the reference, it's using the owner queue of the inner class, i.e. something like:

            void postRollback(LinkedList<MessageReference> refs) throws Exception
             {
             synchronized (this)
             {
             for (MessageReference ref : refs)
             {
             ServerMessage msg = ref.getMessage();
            
             if (!scheduledDeliveryHandler.checkAndSchedule(ref, backup))
             {
             messageReferences.addFirst(ref, msg.getPriority());
             }
             }
            
             deliver();
             }
             }
            


            Should really be:

            void postRollback(LinkedList<MessageReference> refs) throws Exception
             {
             synchronized (this)
             {
             for (MessageReference ref : refs)
             {
             ServerMessage msg = ref.getMessage();
            
             if (!scheduledDeliveryHandler.checkAndSchedule(ref, backup))
             {
             ref.getQueue().messageReferences.addFirst(ref, msg.getPriority());
             }
             }
            
             deliver();
             }
             }
            


            • 3. Re: bug in session.rollback()
              Andy Taylor Master

              actually the error was this piece of code

               if (checkDLQ(ref))
               {
               LinkedList<MessageReference> toCancel = queueMap.get(ref.getQueue());
              
               if (toCancel == null)
               {
               toCancel = new LinkedList<MessageReference>();
              
               queueMap.put((QueueImpl)ref.getQueue(), toCancel);
               }
              
               toCancel.addFirst(ref);
               }


              actually it should be
              if (ref.getQueue().checkDLQ(ref))
               {
               LinkedList<MessageReference> toCancel = queueMap.get(ref.getQueue());
              
               if (toCancel == null)
               {
               toCancel = new LinkedList<MessageReference>();
              
               queueMap.put((QueueImpl)ref.getQueue(), toCancel);
               }
              
               toCancel.addFirst(ref);
               }

              We always call the checkDLQ(..) method is always called for the same queue not the queue for the ref.


              This explains the errors with the AddressSettings tests I'm currently writing as well.