mirror of https://github.com/apache/activemq.git
AMQ-2091: Add a cache to the jms selector parser for speed improvements
git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@740375 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
5e2eedcac0
commit
1ab76f775d
|
@ -57,6 +57,7 @@ import java.util.*;
|
||||||
import javax.jms.InvalidSelectorException;
|
import javax.jms.InvalidSelectorException;
|
||||||
|
|
||||||
import org.apache.activemq.filter.*;
|
import org.apache.activemq.filter.*;
|
||||||
|
import org.apache.activemq.util.LRUCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JMS Selector Parser generated by JavaCC
|
* JMS Selector Parser generated by JavaCC
|
||||||
|
@ -65,20 +66,44 @@ import org.apache.activemq.filter.*;
|
||||||
*/
|
*/
|
||||||
public class SelectorParser {
|
public class SelectorParser {
|
||||||
|
|
||||||
public SelectorParser() {
|
private static final LRUCache cache = new LRUCache(100);
|
||||||
this(new StringReader(""));
|
|
||||||
|
public static BooleanExpression parse(String sql) throws InvalidSelectorException {
|
||||||
|
Object result = cache.get(sql);
|
||||||
|
if (result instanceof InvalidSelectorException) {
|
||||||
|
throw (InvalidSelectorException) result;
|
||||||
|
} else if (result instanceof BooleanExpression) {
|
||||||
|
return (BooleanExpression) result;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
BooleanExpression e = new SelectorParser(sql).parse();
|
||||||
|
cache.put(sql, e);
|
||||||
|
return e;
|
||||||
|
} catch (InvalidSelectorException t) {
|
||||||
|
cache.put(sql, t);
|
||||||
|
throw t;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BooleanExpression parse(String sql) throws InvalidSelectorException {
|
public static void clearCache() {
|
||||||
this.ReInit(new StringReader(sql));
|
cache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String sql;
|
||||||
|
|
||||||
|
protected SelectorParser(String sql) {
|
||||||
|
this(new StringReader(sql));
|
||||||
|
this.sql = sql;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BooleanExpression parse() throws InvalidSelectorException {
|
||||||
try {
|
try {
|
||||||
return this.JmsSelector();
|
return this.JmsSelector();
|
||||||
}
|
}
|
||||||
catch (Throwable e) {
|
catch (Throwable e) {
|
||||||
throw (InvalidSelectorException)new InvalidSelectorException(sql).initCause(e);
|
throw (InvalidSelectorException) new InvalidSelectorException(sql).initCause(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private BooleanExpression asBooleanExpression(Expression value) throws ParseException {
|
private BooleanExpression asBooleanExpression(Expression value) throws ParseException {
|
||||||
|
|
|
@ -91,7 +91,7 @@ public class ActiveMQInputStream extends InputStream implements ActiveMQDispatch
|
||||||
selector = "JMSType='org.apache.activemq.Stream'";
|
selector = "JMSType='org.apache.activemq.Stream'";
|
||||||
}
|
}
|
||||||
|
|
||||||
new SelectorParser().parse(selector);
|
SelectorParser.parse(selector);
|
||||||
this.info.setSelector(selector);
|
this.info.setSelector(selector);
|
||||||
|
|
||||||
this.info.setPrefetchSize(prefetch);
|
this.info.setPrefetchSize(prefetch);
|
||||||
|
|
|
@ -200,12 +200,12 @@ public class ActiveMQMessageConsumer implements MessageAvailableConsumer, StatsC
|
||||||
this.info.setBrowser(browser);
|
this.info.setBrowser(browser);
|
||||||
if (selector != null && selector.trim().length() != 0) {
|
if (selector != null && selector.trim().length() != 0) {
|
||||||
// Validate the selector
|
// Validate the selector
|
||||||
new SelectorParser().parse(selector);
|
SelectorParser.parse(selector);
|
||||||
this.info.setSelector(selector);
|
this.info.setSelector(selector);
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
} else if (info.getSelector() != null) {
|
} else if (info.getSelector() != null) {
|
||||||
// Validate the selector
|
// Validate the selector
|
||||||
new SelectorParser().parse(this.info.getSelector());
|
SelectorParser.parse(this.info.getSelector());
|
||||||
this.selector = this.info.getSelector();
|
this.selector = this.info.getSelector();
|
||||||
} else {
|
} else {
|
||||||
this.selector = null;
|
this.selector = null;
|
||||||
|
|
|
@ -35,6 +35,7 @@ import javax.management.MalformedObjectNameException;
|
||||||
import javax.management.ObjectName;
|
import javax.management.ObjectName;
|
||||||
import org.apache.activemq.ActiveMQConnectionMetaData;
|
import org.apache.activemq.ActiveMQConnectionMetaData;
|
||||||
import org.apache.activemq.Service;
|
import org.apache.activemq.Service;
|
||||||
|
import org.apache.activemq.selector.SelectorParser;
|
||||||
import org.apache.activemq.advisory.AdvisoryBroker;
|
import org.apache.activemq.advisory.AdvisoryBroker;
|
||||||
import org.apache.activemq.broker.cluster.ConnectionSplitBroker;
|
import org.apache.activemq.broker.cluster.ConnectionSplitBroker;
|
||||||
import org.apache.activemq.broker.ft.MasterConnector;
|
import org.apache.activemq.broker.ft.MasterConnector;
|
||||||
|
@ -530,6 +531,8 @@ public class BrokerService implements Service {
|
||||||
}
|
}
|
||||||
stopper.stop(getManagementContext());
|
stopper.stop(getManagementContext());
|
||||||
}
|
}
|
||||||
|
// Clear SelectorParser cache to free memory
|
||||||
|
SelectorParser.clearCache();
|
||||||
stopped.set(true);
|
stopped.set(true);
|
||||||
stoppedLatch.countDown();
|
stoppedLatch.countDown();
|
||||||
LOG.info("ActiveMQ JMS Message Broker (" + getBrokerName() + ", " + brokerId + ") stopped");
|
LOG.info("ActiveMQ JMS Message Broker (" + getBrokerName() + ", " + brokerId + ") stopped");
|
||||||
|
|
|
@ -141,7 +141,7 @@ public class DestinationView implements DestinationViewMBean {
|
||||||
|
|
||||||
MessageEvaluationContext ctx = new MessageEvaluationContext();
|
MessageEvaluationContext ctx = new MessageEvaluationContext();
|
||||||
ctx.setDestination(destination.getActiveMQDestination());
|
ctx.setDestination(destination.getActiveMQDestination());
|
||||||
BooleanExpression selectorExpression = selector == null ? null : new SelectorParser().parse(selector);
|
BooleanExpression selectorExpression = selector == null ? null : SelectorParser.parse(selector);
|
||||||
|
|
||||||
for (int i = 0; i < messages.length; i++) {
|
for (int i = 0; i < messages.length; i++) {
|
||||||
try {
|
try {
|
||||||
|
@ -186,7 +186,7 @@ public class DestinationView implements DestinationViewMBean {
|
||||||
|
|
||||||
MessageEvaluationContext ctx = new MessageEvaluationContext();
|
MessageEvaluationContext ctx = new MessageEvaluationContext();
|
||||||
ctx.setDestination(destination.getActiveMQDestination());
|
ctx.setDestination(destination.getActiveMQDestination());
|
||||||
BooleanExpression selectorExpression = selector == null ? null : new SelectorParser().parse(selector);
|
BooleanExpression selectorExpression = selector == null ? null : SelectorParser.parse(selector);
|
||||||
|
|
||||||
for (int i = 0; i < messages.length; i++) {
|
for (int i = 0; i < messages.length; i++) {
|
||||||
try {
|
try {
|
||||||
|
@ -224,7 +224,7 @@ public class DestinationView implements DestinationViewMBean {
|
||||||
|
|
||||||
MessageEvaluationContext ctx = new MessageEvaluationContext();
|
MessageEvaluationContext ctx = new MessageEvaluationContext();
|
||||||
ctx.setDestination(destination.getActiveMQDestination());
|
ctx.setDestination(destination.getActiveMQDestination());
|
||||||
BooleanExpression selectorExpression = selector == null ? null : new SelectorParser().parse(selector);
|
BooleanExpression selectorExpression = selector == null ? null : SelectorParser.parse(selector);
|
||||||
|
|
||||||
for (int i = 0; i < messages.length; i++) {
|
for (int i = 0; i < messages.length; i++) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -60,7 +60,7 @@ public abstract class AbstractSubscription implements Subscription {
|
||||||
private static BooleanExpression parseSelector(ConsumerInfo info) throws InvalidSelectorException {
|
private static BooleanExpression parseSelector(ConsumerInfo info) throws InvalidSelectorException {
|
||||||
BooleanExpression rc = null;
|
BooleanExpression rc = null;
|
||||||
if (info.getSelector() != null) {
|
if (info.getSelector() != null) {
|
||||||
rc = new SelectorParser().parse(info.getSelector());
|
rc = SelectorParser.parse(info.getSelector());
|
||||||
}
|
}
|
||||||
if (info.isNoLocal()) {
|
if (info.isNoLocal()) {
|
||||||
if (rc == null) {
|
if (rc == null) {
|
||||||
|
|
|
@ -1105,7 +1105,7 @@ public class Queue extends BaseDestination implements Task {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected MessageReferenceFilter createSelectorFilter(String selector) throws InvalidSelectorException {
|
protected MessageReferenceFilter createSelectorFilter(String selector) throws InvalidSelectorException {
|
||||||
final BooleanExpression selectorExpression = new SelectorParser().parse(selector);
|
final BooleanExpression selectorExpression = SelectorParser.parse(selector);
|
||||||
|
|
||||||
return new MessageReferenceFilter() {
|
return new MessageReferenceFilter() {
|
||||||
public boolean evaluate(ConnectionContext context, MessageReference r) throws JMSException {
|
public boolean evaluate(ConnectionContext context, MessageReference r) throws JMSException {
|
||||||
|
|
|
@ -66,7 +66,7 @@ public class FilteredDestination {
|
||||||
*/
|
*/
|
||||||
public void setSelector(String selector) throws InvalidSelectorException {
|
public void setSelector(String selector) throws InvalidSelectorException {
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
setFilter(new SelectorParser().parse(selector));
|
setFilter(SelectorParser.parse(selector));
|
||||||
}
|
}
|
||||||
|
|
||||||
public BooleanExpression getFilter() {
|
public BooleanExpression getFilter() {
|
||||||
|
|
|
@ -68,6 +68,6 @@ public class SelectorParserTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected BooleanExpression parse(String text) throws Exception {
|
protected BooleanExpression parse(String text) throws Exception {
|
||||||
return new SelectorParser().parse(text);
|
return SelectorParser.parse(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -352,14 +352,14 @@ public class SelectorTest extends TestCase {
|
||||||
|
|
||||||
protected void assertInvalidSelector(Message message, String text) throws JMSException {
|
protected void assertInvalidSelector(Message message, String text) throws JMSException {
|
||||||
try {
|
try {
|
||||||
new SelectorParser().parse(text);
|
SelectorParser.parse(text);
|
||||||
fail("Created a valid selector");
|
fail("Created a valid selector");
|
||||||
} catch (InvalidSelectorException e) {
|
} catch (InvalidSelectorException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertSelector(Message message, String text, boolean expected) throws JMSException {
|
protected void assertSelector(Message message, String text, boolean expected) throws JMSException {
|
||||||
BooleanExpression selector = new 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();
|
MessageEvaluationContext context = new MessageEvaluationContext();
|
||||||
context.setMessageReference((org.apache.activemq.command.Message)message);
|
context.setMessageReference((org.apache.activemq.command.Message)message);
|
||||||
|
|
|
@ -165,7 +165,7 @@ public class ActiveMQActivationSpec implements MessageActivationSpec, Serializab
|
||||||
public boolean isValidMessageSelector(List<String> errorMessages) {
|
public boolean isValidMessageSelector(List<String> errorMessages) {
|
||||||
try {
|
try {
|
||||||
if (!isEmpty(messageSelector)) {
|
if (!isEmpty(messageSelector)) {
|
||||||
new SelectorParser().parse(messageSelector);
|
SelectorParser.parse(messageSelector);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
|
Loading…
Reference in New Issue