You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by cl...@apache.org on 2018/09/11 20:34:18 UTC

activemq-artemis git commit: ARTEMIS-2082 Reset buffer valid flag after re-encoding the message

Repository: activemq-artemis
Updated Branches:
  refs/heads/2.6.x fda739c50 -> 6a64f4e7a


ARTEMIS-2082 Reset buffer valid flag after re-encoding the message

Once a re-encode of the message is done the buffer is not being marked
as valid and so subsequent checks on the buffer are all assuming the
message data is not valid and re-encoding over and over.  This can lead
to poor performance in some cases and corrupted data in others.

(cherry picked from commit e065e3e960ac8cc6505a71ec4f67b58b4ffb5990)


Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/6a64f4e7
Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/6a64f4e7
Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/6a64f4e7

Branch: refs/heads/2.6.x
Commit: 6a64f4e7a270f83c735200d6ef29561ef4927535
Parents: fda739c
Author: Timothy Bish <ta...@gmail.com>
Authored: Tue Sep 11 15:42:24 2018 -0400
Committer: Clebert Suconic <cl...@apache.org>
Committed: Tue Sep 11 16:34:11 2018 -0400

----------------------------------------------------------------------
 .../protocol/amqp/broker/AMQPMessage.java       |   3 +-
 .../amqp/AmqpExpiredMessageTest.java            |  65 +++++++--
 .../amqp/JMSTransactedRedeliveryBugTest.java    | 132 +++++++++++++++++++
 3 files changed, 191 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6a64f4e7/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessage.java
----------------------------------------------------------------------
diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessage.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessage.java
index 27d571e..c0f9d10 100644
--- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessage.java
+++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessage.java
@@ -694,7 +694,8 @@ public class AMQPMessage extends RefCountMessage {
          getProtonMessage().encode(new NettyWritable(buffer));
          byte[] bytes = new byte[buffer.writerIndex()];
          buffer.readBytes(bytes);
-         this.data = ReadableBuffer.ByteBufferReader.wrap(ByteBuffer.wrap(bytes));
+         data = ReadableBuffer.ByteBufferReader.wrap(ByteBuffer.wrap(bytes));
+         bufferValid = true;
       } finally {
          buffer.release();
       }

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6a64f4e7/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/AmqpExpiredMessageTest.java
----------------------------------------------------------------------
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/AmqpExpiredMessageTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/AmqpExpiredMessageTest.java
index f5795b6..b130ba8 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/AmqpExpiredMessageTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/AmqpExpiredMessageTest.java
@@ -16,9 +16,9 @@
  */
 package org.apache.activemq.artemis.tests.integration.amqp;
 
+import java.util.UUID;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.activemq.artemis.api.core.SimpleString;
 import org.apache.activemq.artemis.core.server.Queue;
 import org.apache.activemq.artemis.tests.util.Wait;
 import org.apache.activemq.transport.amqp.client.AmqpClient;
@@ -339,11 +339,10 @@ public class AmqpExpiredMessageTest extends AmqpClientTestSupport {
          message.setDurable(true);
          message.setText("Test-Message");
          message.setDeliveryAnnotation("shouldDisappear", 1);
-         message.setAbsoluteExpiryTime(System.currentTimeMillis() + 1000);
+         message.setAbsoluteExpiryTime(System.currentTimeMillis() + 250);
          sender.send(message);
 
-         org.apache.activemq.artemis.core.server.Queue dlq = server.locateQueue(SimpleString.toSimpleString(getDeadLetterAddress()));
-
+         Queue dlq = getProxyToQueue(getDeadLetterAddress());
          assertTrue("Message not movied to DLQ", Wait.waitFor(() -> dlq.getMessageCount() > 0, 5000, 500));
 
          connection.close();
@@ -361,11 +360,61 @@ public class AmqpExpiredMessageTest extends AmqpClientTestSupport {
          receiver.flow(20);
 
          message = receiver.receive(5, TimeUnit.SECONDS);
-         Assert.assertNotNull(message);
-         Assert.assertEquals(getQueueName(), message.getMessageAnnotation(org.apache.activemq.artemis.api.core.Message.HDR_ORIGINAL_ADDRESS.toString()));
-         Assert.assertNull(message.getDeliveryAnnotation("shouldDisappear"));
-         Assert.assertNull(receiver.receiveNoWait());
+         assertNotNull(message);
+         assertEquals(getQueueName(), message.getMessageAnnotation(org.apache.activemq.artemis.api.core.Message.HDR_ORIGINAL_ADDRESS.toString()));
+         assertNull(message.getDeliveryAnnotation("shouldDisappear"));
+         assertNull(receiver.receiveNoWait());
+      } finally {
+         connection.close();
+      }
+   }
+
+   @Test(timeout = 60000)
+   public void testDLQdMessageCanBeRedeliveredMultipleTimes() throws Throwable {
+      AmqpClient client = createAmqpClient();
+      AmqpConnection connection = client.connect();
+
+      try {
+         AmqpSession session = connection.createSession();
+         AmqpSender sender = session.createSender(getQueueName());
+
+         AmqpMessage message = new AmqpMessage();
+         message.setDurable(true);
+         message.setTimeToLive(250);
+         message.setText("Test-Message");
+         message.setMessageId(UUID.randomUUID().toString());
+         message.setApplicationProperty("key", "value");
 
+         sender.send(message);
+
+         Queue dlqView = getProxyToQueue(getDeadLetterAddress());
+         assertTrue("Message not movied to DLQ", Wait.waitFor(() -> dlqView.getMessageCount() > 0, 5000, 200));
+
+         // Read and Modify the message for redelivery repeatedly
+         AmqpReceiver receiver = session.createReceiver(getDeadLetterAddress());
+         receiver.flow(20);
+
+         message = receiver.receive(5, TimeUnit.SECONDS);
+         assertNotNull(message);
+         assertEquals(0, message.getWrappedMessage().getDeliveryCount());
+
+         message.modified(true, false);
+
+         message = receiver.receive(5, TimeUnit.SECONDS);
+         assertNotNull(message);
+         assertEquals(1, message.getWrappedMessage().getDeliveryCount());
+
+         message.modified(true, false);
+
+         message = receiver.receive(5, TimeUnit.SECONDS);
+         assertNotNull(message);
+         assertEquals(2, message.getWrappedMessage().getDeliveryCount());
+
+         message.modified(true, false);
+
+         message = receiver.receive(5, TimeUnit.SECONDS);
+         assertNotNull(message);
+         assertEquals(3, message.getWrappedMessage().getDeliveryCount());
       } finally {
          connection.close();
       }

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6a64f4e7/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/JMSTransactedRedeliveryBugTest.java
----------------------------------------------------------------------
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/JMSTransactedRedeliveryBugTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/JMSTransactedRedeliveryBugTest.java
new file mode 100644
index 0000000..9066a20
--- /dev/null
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/JMSTransactedRedeliveryBugTest.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.activemq.artemis.tests.integration.amqp;
+
+import javax.jms.Connection;
+import javax.jms.DeliveryMode;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.activemq.artemis.api.core.RoutingType;
+import org.apache.activemq.artemis.api.core.SimpleString;
+import org.apache.activemq.artemis.core.server.ActiveMQServer;
+import org.apache.activemq.artemis.core.server.impl.AddressInfo;
+import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
+import org.apache.activemq.artemis.junit.Wait;
+import org.junit.Test;
+
+public class JMSTransactedRedeliveryBugTest extends JMSClientTestSupport {
+
+   private static final String INITIAL_QUEUE_NAME = "InitialQueue";
+   private static final String FINAL_QUEUE_NAME = "FinalQueue";
+
+   private static final SimpleString INITIAL_QUEUE_SS = new SimpleString(INITIAL_QUEUE_NAME);
+   private static final SimpleString FINAL_QUEUE_SS = new SimpleString(FINAL_QUEUE_NAME);
+
+   @Override
+   protected void addConfiguration(ActiveMQServer server) {
+      server.getAddressSettingsRepository().addMatch(INITIAL_QUEUE_NAME, new AddressSettings().setExpiryAddress(FINAL_QUEUE_SS));
+   }
+
+   @Override
+   protected void createAddressAndQueues(ActiveMQServer server) throws Exception {
+      super.createAddressAndQueues(server);
+      server.addAddressInfo(new AddressInfo(INITIAL_QUEUE_SS, RoutingType.ANYCAST));
+      server.createQueue(INITIAL_QUEUE_SS, RoutingType.ANYCAST, INITIAL_QUEUE_SS, null, true, false, -1, false, true);
+      server.addAddressInfo(new AddressInfo(FINAL_QUEUE_SS, RoutingType.ANYCAST));
+      server.createQueue(FINAL_QUEUE_SS, RoutingType.ANYCAST, FINAL_QUEUE_SS, null, true, false, -1, false, true);
+   }
+
+   @Override
+   protected String getJmsConnectionURIOptions() {
+      return "amqp.traceFrames=true";
+   }
+
+   @Test
+   public void testAMQPProducerAMQPConsumer() throws Exception {
+      Connection producerConnection = createConnection();
+      Connection consumerConnection = createConnection();
+
+      try {
+         Session producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         Queue producerQueue = producerSession.createQueue(INITIAL_QUEUE_NAME);
+         MessageProducer producer = producerSession.createProducer(producerQueue);
+
+         TextMessage sentMessage = producerSession.createTextMessage();
+         sentMessage.setStringProperty("something", "KEY");
+         sentMessage.setText("how are you");
+         producer.send(sentMessage, DeliveryMode.PERSISTENT, 4, 10);
+
+         // Simulate a small pause, else both messages could be consumed if
+         // consumer is fast enough
+         Wait.assertTrue("Message should have expired", () -> getProxyToQueue(FINAL_QUEUE_NAME).getMessageCount() == 1);
+
+         Session consumerSession = consumerConnection.createSession(true, Session.SESSION_TRANSACTED);
+         Queue consumerQueue = consumerSession.createQueue(FINAL_QUEUE_NAME);
+         MessageConsumer consumer = consumerSession.createConsumer(consumerQueue);
+
+         Message msg = consumer.receive(1_000);
+         assertNotNull(msg);
+         assertEquals("1", msg.getStringProperty("JMSXDeliveryCount"));
+         assertEquals("KEY", msg.getStringProperty("something"));
+         assertEquals("how are you", ((TextMessage) msg).getText());
+
+         consumerSession.rollback();
+
+         msg = consumer.receive(1_000);
+         assertNotNull(msg);
+         assertEquals("2", msg.getStringProperty("JMSXDeliveryCount"));
+         assertEquals("KEY", msg.getStringProperty("something"));
+         assertEquals("how are you", ((TextMessage) msg).getText());
+
+         consumerSession.rollback();
+
+         msg = consumer.receive(1_000);
+         assertNotNull(msg);
+         assertEquals("3", msg.getStringProperty("JMSXDeliveryCount"));
+         assertEquals("KEY", msg.getStringProperty("something"));
+         assertEquals("how are you", ((TextMessage) msg).getText());
+
+         consumerSession.rollback();
+
+         msg = consumer.receive(1_000);
+         assertNotNull(msg);
+         assertEquals("4", msg.getStringProperty("JMSXDeliveryCount"));
+         assertEquals("KEY", msg.getStringProperty("something"));
+         assertEquals("how are you", ((TextMessage) msg).getText());
+
+         consumerSession.rollback();
+
+         msg = consumer.receive(1_000);
+         assertNotNull(msg);
+         assertEquals("5", msg.getStringProperty("JMSXDeliveryCount"));
+         assertEquals("KEY", msg.getStringProperty("something"));
+         assertEquals("how are you", ((TextMessage) msg).getText());
+
+         consumerSession.commit();
+
+         consumer.close();
+      } finally {
+         producerConnection.close();
+         consumerConnection.close();
+      }
+   }
+}
\ No newline at end of file