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:
Guillaume Nodet 2009-02-03 19:05:07 +00:00
parent 5e2eedcac0
commit 1ab76f775d
11 changed files with 50 additions and 22 deletions

View File

@ -57,6 +57,7 @@ import java.util.*;
import javax.jms.InvalidSelectorException;
import org.apache.activemq.filter.*;
import org.apache.activemq.util.LRUCache;
/**
* JMS Selector Parser generated by JavaCC
@ -65,22 +66,46 @@ import org.apache.activemq.filter.*;
*/
public class SelectorParser {
public SelectorParser() {
this(new StringReader(""));
private static final LRUCache cache = new LRUCache(100);
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 {
this.ReInit(new StringReader(sql));
public static void clearCache() {
cache.clear();
}
private String sql;
protected SelectorParser(String sql) {
this(new StringReader(sql));
this.sql = sql;
}
protected BooleanExpression parse() throws InvalidSelectorException {
try {
return this.JmsSelector();
}
catch (Throwable e) {
throw (InvalidSelectorException)new InvalidSelectorException(sql).initCause(e);
}
catch (Throwable e) {
throw (InvalidSelectorException) new InvalidSelectorException(sql).initCause(e);
}
}
private BooleanExpression asBooleanExpression(Expression value) throws ParseException {
if (value instanceof BooleanExpression) {
return (BooleanExpression) value;

View File

@ -91,7 +91,7 @@ public class ActiveMQInputStream extends InputStream implements ActiveMQDispatch
selector = "JMSType='org.apache.activemq.Stream'";
}
new SelectorParser().parse(selector);
SelectorParser.parse(selector);
this.info.setSelector(selector);
this.info.setPrefetchSize(prefetch);

View File

@ -200,12 +200,12 @@ public class ActiveMQMessageConsumer implements MessageAvailableConsumer, StatsC
this.info.setBrowser(browser);
if (selector != null && selector.trim().length() != 0) {
// Validate the selector
new SelectorParser().parse(selector);
SelectorParser.parse(selector);
this.info.setSelector(selector);
this.selector = selector;
} else if (info.getSelector() != null) {
// Validate the selector
new SelectorParser().parse(this.info.getSelector());
SelectorParser.parse(this.info.getSelector());
this.selector = this.info.getSelector();
} else {
this.selector = null;

View File

@ -35,6 +35,7 @@ import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import org.apache.activemq.ActiveMQConnectionMetaData;
import org.apache.activemq.Service;
import org.apache.activemq.selector.SelectorParser;
import org.apache.activemq.advisory.AdvisoryBroker;
import org.apache.activemq.broker.cluster.ConnectionSplitBroker;
import org.apache.activemq.broker.ft.MasterConnector;
@ -530,6 +531,8 @@ public class BrokerService implements Service {
}
stopper.stop(getManagementContext());
}
// Clear SelectorParser cache to free memory
SelectorParser.clearCache();
stopped.set(true);
stoppedLatch.countDown();
LOG.info("ActiveMQ JMS Message Broker (" + getBrokerName() + ", " + brokerId + ") stopped");

View File

@ -141,7 +141,7 @@ public class DestinationView implements DestinationViewMBean {
MessageEvaluationContext ctx = new MessageEvaluationContext();
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++) {
try {
@ -186,7 +186,7 @@ public class DestinationView implements DestinationViewMBean {
MessageEvaluationContext ctx = new MessageEvaluationContext();
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++) {
try {
@ -224,7 +224,7 @@ public class DestinationView implements DestinationViewMBean {
MessageEvaluationContext ctx = new MessageEvaluationContext();
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++) {
try {

View File

@ -60,7 +60,7 @@ public abstract class AbstractSubscription implements Subscription {
private static BooleanExpression parseSelector(ConsumerInfo info) throws InvalidSelectorException {
BooleanExpression rc = null;
if (info.getSelector() != null) {
rc = new SelectorParser().parse(info.getSelector());
rc = SelectorParser.parse(info.getSelector());
}
if (info.isNoLocal()) {
if (rc == null) {

View File

@ -1105,7 +1105,7 @@ public class Queue extends BaseDestination implements Task {
}
protected MessageReferenceFilter createSelectorFilter(String selector) throws InvalidSelectorException {
final BooleanExpression selectorExpression = new SelectorParser().parse(selector);
final BooleanExpression selectorExpression = SelectorParser.parse(selector);
return new MessageReferenceFilter() {
public boolean evaluate(ConnectionContext context, MessageReference r) throws JMSException {

View File

@ -66,7 +66,7 @@ public class FilteredDestination {
*/
public void setSelector(String selector) throws InvalidSelectorException {
this.selector = selector;
setFilter(new SelectorParser().parse(selector));
setFilter(SelectorParser.parse(selector));
}
public BooleanExpression getFilter() {

View File

@ -68,6 +68,6 @@ public class SelectorParserTest extends TestCase {
}
protected BooleanExpression parse(String text) throws Exception {
return new SelectorParser().parse(text);
return SelectorParser.parse(text);
}
}

View File

@ -352,14 +352,14 @@ public class SelectorTest extends TestCase {
protected void assertInvalidSelector(Message message, String text) throws JMSException {
try {
new SelectorParser().parse(text);
SelectorParser.parse(text);
fail("Created a valid selector");
} catch (InvalidSelectorException e) {
}
}
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);
MessageEvaluationContext context = new MessageEvaluationContext();
context.setMessageReference((org.apache.activemq.command.Message)message);

View File

@ -165,7 +165,7 @@ public class ActiveMQActivationSpec implements MessageActivationSpec, Serializab
public boolean isValidMessageSelector(List<String> errorMessages) {
try {
if (!isEmpty(messageSelector)) {
new SelectorParser().parse(messageSelector);
SelectorParser.parse(messageSelector);
}
return true;
} catch (Throwable e) {