mirror of https://github.com/apache/activemq.git
AMQ-7035 - use NonCachedMessageEvaluationContext in place of MessageEvaluationContext to avoid unnecessary reference count management and subsequent leaks. Rework AMQ-6465 with additional JMX related tests
(cherry picked from commit 50d27e7e54
)
This commit is contained in:
parent
d1746e4ade
commit
4a99103e70
|
@ -27,6 +27,7 @@ import org.apache.activemq.command.TransactionId;
|
||||||
import org.apache.activemq.command.WireFormatInfo;
|
import org.apache.activemq.command.WireFormatInfo;
|
||||||
import org.apache.activemq.command.XATransactionId;
|
import org.apache.activemq.command.XATransactionId;
|
||||||
import org.apache.activemq.filter.MessageEvaluationContext;
|
import org.apache.activemq.filter.MessageEvaluationContext;
|
||||||
|
import org.apache.activemq.filter.NonCachedMessageEvaluationContext;
|
||||||
import org.apache.activemq.security.MessageAuthorizationPolicy;
|
import org.apache.activemq.security.MessageAuthorizationPolicy;
|
||||||
import org.apache.activemq.security.SecurityContext;
|
import org.apache.activemq.security.SecurityContext;
|
||||||
import org.apache.activemq.state.ConnectionState;
|
import org.apache.activemq.state.ConnectionState;
|
||||||
|
@ -64,7 +65,7 @@ public class ConnectionContext {
|
||||||
private XATransactionId xid;
|
private XATransactionId xid;
|
||||||
|
|
||||||
public ConnectionContext() {
|
public ConnectionContext() {
|
||||||
this.messageEvaluationContext = new MessageEvaluationContext();
|
this.messageEvaluationContext = new NonCachedMessageEvaluationContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConnectionContext(MessageEvaluationContext messageEvaluationContext) {
|
public ConnectionContext(MessageEvaluationContext messageEvaluationContext) {
|
||||||
|
|
|
@ -51,7 +51,7 @@ import org.apache.activemq.command.ActiveMQMessage;
|
||||||
import org.apache.activemq.command.ActiveMQTextMessage;
|
import org.apache.activemq.command.ActiveMQTextMessage;
|
||||||
import org.apache.activemq.command.Message;
|
import org.apache.activemq.command.Message;
|
||||||
import org.apache.activemq.filter.BooleanExpression;
|
import org.apache.activemq.filter.BooleanExpression;
|
||||||
import org.apache.activemq.filter.MessageEvaluationContext;
|
import org.apache.activemq.filter.NonCachedMessageEvaluationContext;
|
||||||
import org.apache.activemq.selector.SelectorParser;
|
import org.apache.activemq.selector.SelectorParser;
|
||||||
import org.apache.activemq.store.MessageStore;
|
import org.apache.activemq.store.MessageStore;
|
||||||
import org.apache.activemq.util.URISupport;
|
import org.apache.activemq.util.URISupport;
|
||||||
|
@ -213,7 +213,7 @@ public class DestinationView implements DestinationViewMBean {
|
||||||
Message[] messages = destination.browse();
|
Message[] messages = destination.browse();
|
||||||
ArrayList<CompositeData> c = new ArrayList<CompositeData>();
|
ArrayList<CompositeData> c = new ArrayList<CompositeData>();
|
||||||
|
|
||||||
MessageEvaluationContext ctx = new MessageEvaluationContext();
|
NonCachedMessageEvaluationContext ctx = new NonCachedMessageEvaluationContext();
|
||||||
ctx.setDestination(destination.getActiveMQDestination());
|
ctx.setDestination(destination.getActiveMQDestination());
|
||||||
BooleanExpression selectorExpression = selector == null ? null : SelectorParser.parse(selector);
|
BooleanExpression selectorExpression = selector == null ? null : SelectorParser.parse(selector);
|
||||||
|
|
||||||
|
@ -256,7 +256,7 @@ public class DestinationView implements DestinationViewMBean {
|
||||||
Message[] messages = destination.browse();
|
Message[] messages = destination.browse();
|
||||||
ArrayList<Object> answer = new ArrayList<Object>();
|
ArrayList<Object> answer = new ArrayList<Object>();
|
||||||
|
|
||||||
MessageEvaluationContext ctx = new MessageEvaluationContext();
|
NonCachedMessageEvaluationContext ctx = new NonCachedMessageEvaluationContext();
|
||||||
ctx.setDestination(destination.getActiveMQDestination());
|
ctx.setDestination(destination.getActiveMQDestination());
|
||||||
BooleanExpression selectorExpression = selector == null ? null : SelectorParser.parse(selector);
|
BooleanExpression selectorExpression = selector == null ? null : SelectorParser.parse(selector);
|
||||||
|
|
||||||
|
@ -297,7 +297,7 @@ public class DestinationView implements DestinationViewMBean {
|
||||||
TabularType tt = new TabularType("MessageList", "MessageList", ct, new String[] { "JMSMessageID" });
|
TabularType tt = new TabularType("MessageList", "MessageList", ct, new String[] { "JMSMessageID" });
|
||||||
TabularDataSupport rc = new TabularDataSupport(tt);
|
TabularDataSupport rc = new TabularDataSupport(tt);
|
||||||
|
|
||||||
MessageEvaluationContext ctx = new MessageEvaluationContext();
|
NonCachedMessageEvaluationContext ctx = new NonCachedMessageEvaluationContext();
|
||||||
ctx.setDestination(destination.getActiveMQDestination());
|
ctx.setDestination(destination.getActiveMQDestination());
|
||||||
BooleanExpression selectorExpression = selector == null ? null : SelectorParser.parse(selector);
|
BooleanExpression selectorExpression = selector == null ? null : SelectorParser.parse(selector);
|
||||||
|
|
||||||
|
|
|
@ -841,7 +841,7 @@ public abstract class BaseDestination implements Destination {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConnectionContext createConnectionContext() {
|
public ConnectionContext createConnectionContext() {
|
||||||
ConnectionContext answer = new ConnectionContext(new NonCachedMessageEvaluationContext());
|
ConnectionContext answer = new ConnectionContext();
|
||||||
answer.setBroker(this.broker);
|
answer.setBroker(this.broker);
|
||||||
answer.getMessageEvaluationContext().setDestination(getActiveMQDestination());
|
answer.getMessageEvaluationContext().setDestination(getActiveMQDestination());
|
||||||
answer.setSecurityContext(SecurityContext.BROKER_SECURITY_CONTEXT);
|
answer.setSecurityContext(SecurityContext.BROKER_SECURITY_CONTEXT);
|
||||||
|
|
|
@ -484,7 +484,7 @@ public class FilePendingMessageCursor extends AbstractPendingMessageCursor imple
|
||||||
private void discardExpiredMessage(MessageReference reference) {
|
private void discardExpiredMessage(MessageReference reference) {
|
||||||
LOG.debug("Discarding expired message {}", reference);
|
LOG.debug("Discarding expired message {}", reference);
|
||||||
if (reference.isExpired() && broker.isExpired(reference)) {
|
if (reference.isExpired() && broker.isExpired(reference)) {
|
||||||
ConnectionContext context = new ConnectionContext(new NonCachedMessageEvaluationContext());
|
ConnectionContext context = new ConnectionContext();
|
||||||
context.setBroker(broker);
|
context.setBroker(broker);
|
||||||
((Destination)reference.getRegionDestination()).messageExpired(context, null, new IndirectMessageReference(reference.getMessage()));
|
((Destination)reference.getRegionDestination()).messageExpired(context, null, new IndirectMessageReference(reference.getMessage()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ import org.apache.activemq.command.ShutdownInfo;
|
||||||
import org.apache.activemq.command.SubscriptionInfo;
|
import org.apache.activemq.command.SubscriptionInfo;
|
||||||
import org.apache.activemq.command.WireFormatInfo;
|
import org.apache.activemq.command.WireFormatInfo;
|
||||||
import org.apache.activemq.filter.DestinationFilter;
|
import org.apache.activemq.filter.DestinationFilter;
|
||||||
import org.apache.activemq.filter.MessageEvaluationContext;
|
import org.apache.activemq.filter.NonCachedMessageEvaluationContext;
|
||||||
import org.apache.activemq.security.SecurityContext;
|
import org.apache.activemq.security.SecurityContext;
|
||||||
import org.apache.activemq.transport.DefaultTransportListener;
|
import org.apache.activemq.transport.DefaultTransportListener;
|
||||||
import org.apache.activemq.transport.FutureResponse;
|
import org.apache.activemq.transport.FutureResponse;
|
||||||
|
@ -1303,13 +1303,10 @@ public abstract class DemandForwardingBridgeSupport implements NetworkBridge, Br
|
||||||
// for durable subs, suppression via filter leaves dangling acks so we
|
// for durable subs, suppression via filter leaves dangling acks so we
|
||||||
// need to check here and allow the ack irrespective
|
// need to check here and allow the ack irrespective
|
||||||
if (sub.getLocalInfo().isDurable()) {
|
if (sub.getLocalInfo().isDurable()) {
|
||||||
MessageEvaluationContext messageEvalContext = new MessageEvaluationContext();
|
NonCachedMessageEvaluationContext messageEvalContext = new NonCachedMessageEvaluationContext();
|
||||||
messageEvalContext.setMessageReference(md.getMessage());
|
messageEvalContext.setMessageReference(md.getMessage());
|
||||||
messageEvalContext.setDestination(md.getDestination());
|
messageEvalContext.setDestination(md.getDestination());
|
||||||
suppress = !sub.getNetworkBridgeFilter().matches(messageEvalContext);
|
suppress = !sub.getNetworkBridgeFilter().matches(messageEvalContext);
|
||||||
//AMQ-6465 - Need to decrement the reference count after checking matches() as
|
|
||||||
//the call above will increment the reference count by 1
|
|
||||||
messageEvalContext.getMessageReference().decrementReferenceCount();
|
|
||||||
}
|
}
|
||||||
return suppress;
|
return suppress;
|
||||||
}
|
}
|
||||||
|
|
|
@ -452,15 +452,19 @@ public class MBeanTest extends EmbeddedBrokerTestSupport {
|
||||||
|
|
||||||
queueViewMBeanName = assertRegisteredObjectName(domain + ":type=Broker,brokerName=localhost,destinationType=Queue,destinationName=" + newDestination);
|
queueViewMBeanName = assertRegisteredObjectName(domain + ":type=Broker,brokerName=localhost,destinationType=Queue,destinationName=" + newDestination);
|
||||||
|
|
||||||
queue = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, queueViewMBeanName, QueueViewMBean.class, true);
|
QueueViewMBean queueNew = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, queueViewMBeanName, QueueViewMBean.class, true);
|
||||||
int movedSize = MESSAGE_COUNT-3;
|
int movedSize = MESSAGE_COUNT-3;
|
||||||
assertEquals("Unexpected number of messages ",movedSize,queue.getQueueSize());
|
assertEquals("Unexpected number of messages ",movedSize,queueNew.getQueueSize());
|
||||||
|
|
||||||
// now lets remove them by selector
|
// now lets remove them by selector
|
||||||
queue.removeMatchingMessages("counter > 2");
|
queueNew.removeMatchingMessages("counter > 2");
|
||||||
|
|
||||||
assertEquals("Should have no more messages in the queue: " + queueViewMBeanName, 0, queue.getQueueSize());
|
assertEquals("Should have no more messages in the queue: " + queueViewMBeanName, 0, queueNew.getQueueSize());
|
||||||
assertEquals("dest has no memory usage", 0, queue.getMemoryPercentUsage());
|
assertEquals("dest has no memory usage", 0, queueNew.getMemoryPercentUsage());
|
||||||
|
assertEquals("dest has 0 memory usage", 0, queueNew.getMemoryUsageByteCount());
|
||||||
|
|
||||||
|
queue.purge();
|
||||||
|
assertEquals("dest has 0 memory usage", 0, queue.getMemoryUsageByteCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCopyMessagesBySelector() throws Exception {
|
public void testCopyMessagesBySelector() throws Exception {
|
||||||
|
@ -478,17 +482,47 @@ public class MBeanTest extends EmbeddedBrokerTestSupport {
|
||||||
|
|
||||||
queueViewMBeanName = assertRegisteredObjectName(domain + ":type=Broker,brokerName=localhost,destinationType=Queue,destinationName=" + newDestination);
|
queueViewMBeanName = assertRegisteredObjectName(domain + ":type=Broker,brokerName=localhost,destinationType=Queue,destinationName=" + newDestination);
|
||||||
|
|
||||||
queue = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, queueViewMBeanName, QueueViewMBean.class, true);
|
QueueViewMBean queueTwo = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, queueViewMBeanName, QueueViewMBean.class, true);
|
||||||
|
|
||||||
LOG.info("Queue: " + queueViewMBeanName + " now has: " + queue.getQueueSize() + " message(s)");
|
LOG.info("Queue: " + queueViewMBeanName + " now has: " + queueTwo.getQueueSize() + " message(s)");
|
||||||
assertEquals("Expected messages in a queue: " + queueViewMBeanName, MESSAGE_COUNT-3, queue.getQueueSize());
|
assertEquals("Expected messages in a queue: " + queueViewMBeanName, MESSAGE_COUNT-3, queueTwo.getQueueSize());
|
||||||
// now lets remove them by selector
|
// now lets remove them by selector
|
||||||
queue.removeMatchingMessages("counter > 2");
|
queueTwo.removeMatchingMessages("counter > 2");
|
||||||
|
|
||||||
assertEquals("Should have no more messages in the queue: " + queueViewMBeanName, 0, queue.getQueueSize());
|
assertEquals("Should have no more messages in the queue: " + queueViewMBeanName, 0, queueTwo.getQueueSize());
|
||||||
assertEquals("dest has no memory usage", 0, queue.getMemoryPercentUsage());
|
assertEquals("dest has no memory usage", 0, queueTwo.getMemoryPercentUsage());
|
||||||
|
assertEquals("dest has 0 memory usage", 0, queueTwo.getMemoryUsageByteCount());
|
||||||
|
|
||||||
|
queue.purge();
|
||||||
|
assertEquals("dest has 0 memory usage", 0, queue.getMemoryUsageByteCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testSelectorBrowseUsage() throws Exception {
|
||||||
|
connection = connectionFactory.createConnection();
|
||||||
|
useConnection(connection);
|
||||||
|
|
||||||
|
ObjectName queueViewMBeanName = assertRegisteredObjectName(domain + ":type=Broker,brokerName=localhost,destinationType=Queue,destinationName=" + getDestinationString());
|
||||||
|
|
||||||
|
final String someSelectorExp = "JMSType = '22'";
|
||||||
|
QueueViewMBean queue = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, queueViewMBeanName, QueueViewMBean.class, true);
|
||||||
|
queue.browse(someSelectorExp);
|
||||||
|
queue.purge();
|
||||||
|
assertEquals("dest has 0 memory usage", 0, queue.getMemoryUsageByteCount());
|
||||||
|
|
||||||
|
connection.close();
|
||||||
|
connection = connectionFactory.createConnection();
|
||||||
|
useConnection(connection);
|
||||||
|
queue.browseMessages(someSelectorExp);
|
||||||
|
queue.purge();
|
||||||
|
assertEquals("dest has 0 memory usage", 0, queue.getMemoryUsageByteCount());
|
||||||
|
|
||||||
|
connection.close();
|
||||||
|
connection = connectionFactory.createConnection();
|
||||||
|
useConnection(connection);
|
||||||
|
queue.browseAsTable(someSelectorExp);
|
||||||
|
queue.purge();
|
||||||
|
assertEquals("dest has 0 memory usage", 0, queue.getMemoryUsageByteCount());
|
||||||
|
}
|
||||||
|
|
||||||
public void testCopyPurgeCopyBack() throws Exception {
|
public void testCopyPurgeCopyBack() throws Exception {
|
||||||
connection = connectionFactory.createConnection();
|
connection = connectionFactory.createConnection();
|
||||||
|
|
|
@ -405,7 +405,9 @@ public class SelectorTest extends TestCase {
|
||||||
MessageEvaluationContext context = new MessageEvaluationContext();
|
MessageEvaluationContext context = new MessageEvaluationContext();
|
||||||
context.setMessageReference((org.apache.activemq.command.Message)message);
|
context.setMessageReference((org.apache.activemq.command.Message)message);
|
||||||
boolean value = selector.matches(context);
|
boolean value = selector.matches(context);
|
||||||
|
context.clear();
|
||||||
assertEquals("Selector for: " + text, expected, value);
|
assertEquals("Selector for: " + text, expected, value);
|
||||||
|
assertEquals("ref 0", 0, ((ActiveMQMessage)message).getReferenceCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Message createMessage(String subject) throws JMSException {
|
protected Message createMessage(String subject) throws JMSException {
|
||||||
|
|
|
@ -25,7 +25,7 @@ import javax.jms.Message;
|
||||||
import org.apache.activemq.command.ActiveMQMessage;
|
import org.apache.activemq.command.ActiveMQMessage;
|
||||||
import org.apache.activemq.command.ActiveMQTopic;
|
import org.apache.activemq.command.ActiveMQTopic;
|
||||||
import org.apache.activemq.filter.BooleanExpression;
|
import org.apache.activemq.filter.BooleanExpression;
|
||||||
import org.apache.activemq.filter.MessageEvaluationContext;
|
import org.apache.activemq.filter.NonCachedMessageEvaluationContext;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -170,10 +170,11 @@ public class UnknownHandlingSelectorTest {
|
||||||
protected void assertSelector(String text, boolean matches) throws JMSException {
|
protected void assertSelector(String text, boolean matches) throws JMSException {
|
||||||
BooleanExpression selector = SelectorParser.parse(text);
|
BooleanExpression selector = SelectorParser.parse(text);
|
||||||
assertTrue("Created a valid selector", selector != null);
|
assertTrue("Created a valid selector", selector != null);
|
||||||
MessageEvaluationContext context = new MessageEvaluationContext();
|
NonCachedMessageEvaluationContext context = new NonCachedMessageEvaluationContext();
|
||||||
context.setMessageReference((org.apache.activemq.command.Message)message);
|
context.setMessageReference((org.apache.activemq.command.Message)message);
|
||||||
boolean value = selector.matches(context);
|
boolean value = selector.matches(context);
|
||||||
assertEquals("Selector for: " + text, matches, value);
|
assertEquals("Selector for: " + text, matches, value);
|
||||||
|
assertEquals("ref 0", 0, ((ActiveMQMessage)message).getReferenceCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String not(String selector) {
|
private static String not(String selector) {
|
||||||
|
|
|
@ -84,8 +84,7 @@ public class LargeQueueSparseDeleteTest extends EmbeddedBrokerTestSupport {
|
||||||
Queue queue = (Queue) broker.getRegionBroker().getDestinationMap().get(
|
Queue queue = (Queue) broker.getRegionBroker().getDestinationMap().get(
|
||||||
destination);
|
destination);
|
||||||
|
|
||||||
ConnectionContext context = new ConnectionContext(
|
ConnectionContext context = new ConnectionContext();
|
||||||
new NonCachedMessageEvaluationContext());
|
|
||||||
context.setBroker(broker.getBroker());
|
context.setBroker(broker.getBroker());
|
||||||
context.getMessageEvaluationContext().setDestination(destination);
|
context.getMessageEvaluationContext().setDestination(destination);
|
||||||
|
|
||||||
|
@ -133,8 +132,7 @@ public class LargeQueueSparseDeleteTest extends EmbeddedBrokerTestSupport {
|
||||||
Queue queue = (Queue) broker.getRegionBroker().getDestinationMap().get(
|
Queue queue = (Queue) broker.getRegionBroker().getDestinationMap().get(
|
||||||
destination);
|
destination);
|
||||||
|
|
||||||
ConnectionContext context = new ConnectionContext(
|
ConnectionContext context = new ConnectionContext();
|
||||||
new NonCachedMessageEvaluationContext());
|
|
||||||
context.setBroker(broker.getBroker());
|
context.setBroker(broker.getBroker());
|
||||||
context.getMessageEvaluationContext().setDestination(destination);
|
context.getMessageEvaluationContext().setDestination(destination);
|
||||||
|
|
||||||
|
@ -179,8 +177,7 @@ public class LargeQueueSparseDeleteTest extends EmbeddedBrokerTestSupport {
|
||||||
Queue queue = (Queue) broker.getRegionBroker().getDestinationMap().get(
|
Queue queue = (Queue) broker.getRegionBroker().getDestinationMap().get(
|
||||||
destination);
|
destination);
|
||||||
|
|
||||||
ConnectionContext context = new ConnectionContext(
|
ConnectionContext context = new ConnectionContext();
|
||||||
new NonCachedMessageEvaluationContext());
|
|
||||||
context.setBroker(broker.getBroker());
|
context.setBroker(broker.getBroker());
|
||||||
context.getMessageEvaluationContext().setDestination(destination);
|
context.getMessageEvaluationContext().setDestination(destination);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue