Uploaded image for project: 'Qpid'
  1. Qpid
  2. QPID-7811

[Java Broker] Asynchronous message store recoverer can delete message content for the message enqueued after broker startup

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Critical
    • Resolution: Fixed
    • Affects Version/s: qpid-java-6.0, qpid-java-6.0.1, qpid-java-6.0.2, qpid-java-6.0.3, qpid-java-6.0.4, qpid-java-6.0.5, qpid-java-6.1, qpid-java-6.0.6, qpid-java-6.1.1, qpid-java-6.1.2, qpid-java-6.0.7, qpid-java-6.1.3
    • Component/s: Broker-J
    • Labels:
      None

      Description

      The recoverer in the Broker is used to bring existing messages from disk following a restart of either the Broker as a whole or virtualhost. The following defect affects only the asynchronous recoverer (one that allows the virtualhost to come back to service whilst recovery continues). The default synchronous recoverer is unaffected by this defect.

      AsynchronousMessageStoreRecoverer recovers messages with ID values less than "max message id" evaluated on broker startup. On completion of queue recovery, the AsynchronousMessageStoreRecoverer iterates over the orphan messages and deletes them. The message is considered orphan when enqueuing record is not found among recovered enqueuing records and the message id is less than "max message id evaluated on broker startup".

      When queues have huge backlogs (millions of messages), the recovery can take time. The messages on other queues can be consumed and published during this time. When messages with message id equals to ("max message id" - 1) is consumed, the recoverer can mistakenly put message with id greater than or equal to "max message id evaluated on broker startup" into orphan messages and the content of such message could be deleted.

      The following code causes such mistaken orphan message detection:

      getStoreReader().visitMessages(new MessageHandler()
                  {
                      @Override
                      public boolean handle(final StoredMessage<?> storedMessage)
                      {
      
                          long messageNumber = storedMessage.getMessageNumber();
                          if (!_recoveredMessages.containsKey(messageNumber))
                          {
                              messagesToDelete.add(storedMessage);
                          }
                          return _continueRecovery.get() && messageNumber < _maxMessageId - 1;
                      }
                  });
      

      The message id should be checked before putting message into collection "messagesToDelete"

        Attachments

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              alex.rufous Alex Rudyy
            • Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: