mirror of https://github.com/apache/activemq.git
git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@599129 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
987ad27449
commit
9dd11cb71f
|
@ -33,8 +33,8 @@ import org.apache.activemq.util.LRUCache;
|
||||||
*/
|
*/
|
||||||
public class ActiveMQMessageAudit {
|
public class ActiveMQMessageAudit {
|
||||||
|
|
||||||
private static final int DEFAULT_WINDOW_SIZE = 1024;
|
private static final int DEFAULT_WINDOW_SIZE = 2048;
|
||||||
private static final int MAXIMUM_PRODUCER_COUNT = 128;
|
private static final int MAXIMUM_PRODUCER_COUNT = 64;
|
||||||
private int auditDepth;
|
private int auditDepth;
|
||||||
private int maximumNumberOfProducersToTrack;
|
private int maximumNumberOfProducersToTrack;
|
||||||
private LRUCache<Object, BitArrayBin> map;
|
private LRUCache<Object, BitArrayBin> map;
|
||||||
|
@ -218,25 +218,35 @@ public class ActiveMQMessageAudit {
|
||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the MessageId is in order
|
||||||
|
* @param message
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public synchronized boolean isInOrder(final MessageReference message) {
|
||||||
|
return isInOrder(message.getMessageId());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the MessageId is in order
|
* Check the MessageId is in order
|
||||||
* @param id
|
* @param id
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public synchronized boolean isInOrder(final MessageId id) {
|
public synchronized boolean isInOrder(final MessageId id) {
|
||||||
boolean answer = true;
|
boolean answer = false;
|
||||||
|
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
ProducerId pid = id.getProducerId();
|
ProducerId pid = id.getProducerId();
|
||||||
if (pid != null) {
|
if (pid != null) {
|
||||||
BitArrayBin bab = map.get(pid);
|
BitArrayBin bab = map.get(pid);
|
||||||
if (bab != null) {
|
if (bab == null) {
|
||||||
answer = bab.isInOrder(id.getProducerSequenceId());
|
bab = new BitArrayBin(auditDepth);
|
||||||
|
map.put(pid, bab);
|
||||||
}
|
}
|
||||||
|
answer = bab.isInOrder(id.getProducerSequenceId());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,7 +113,7 @@ public class BrokerService implements Service {
|
||||||
private TaskRunnerFactory persistenceTaskRunnerFactory;
|
private TaskRunnerFactory persistenceTaskRunnerFactory;
|
||||||
private SystemUsage systemUsage;
|
private SystemUsage systemUsage;
|
||||||
private SystemUsage producerSystemUsage;
|
private SystemUsage producerSystemUsage;
|
||||||
private SystemUsage consumerSystemUsage;
|
private SystemUsage storeSystemUsage;
|
||||||
private PersistenceAdapter persistenceAdapter;
|
private PersistenceAdapter persistenceAdapter;
|
||||||
private PersistenceAdapterFactory persistenceFactory;
|
private PersistenceAdapterFactory persistenceFactory;
|
||||||
private DestinationFactory destinationFactory;
|
private DestinationFactory destinationFactory;
|
||||||
|
@ -668,23 +668,23 @@ public class BrokerService implements Service {
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public SystemUsage getConsumerSystemUsage() throws IOException {
|
public SystemUsage getConsumerSystemUsage() throws IOException {
|
||||||
if (consumerSystemUsage == null) {
|
if (this.storeSystemUsage == null) {
|
||||||
consumerSystemUsage = new SystemUsage(getSystemUsage(), "Consumer");
|
this.storeSystemUsage = new SystemUsage(getSystemUsage(), "Store");
|
||||||
consumerSystemUsage.getMemoryUsage().setUsagePortion(0.5f);
|
this.storeSystemUsage.getMemoryUsage().setUsagePortion(0.5f);
|
||||||
addService(consumerSystemUsage);
|
addService(this.storeSystemUsage);
|
||||||
}
|
}
|
||||||
return consumerSystemUsage;
|
return this.storeSystemUsage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param consumerUsageManager the consumerUsageManager to set
|
* @param storeSystemUsage the storeSystemUsage to set
|
||||||
*/
|
*/
|
||||||
public void setConsumerSystemUsage(SystemUsage consumerUsageManager) {
|
public void setConsumerSystemUsage(SystemUsage storeSystemUsage) {
|
||||||
if (this.consumerSystemUsage != null) {
|
if (this.storeSystemUsage != null) {
|
||||||
removeService(this.consumerSystemUsage);
|
removeService(this.storeSystemUsage);
|
||||||
}
|
}
|
||||||
this.consumerSystemUsage = consumerUsageManager;
|
this.storeSystemUsage = storeSystemUsage;
|
||||||
addService(this.producerSystemUsage);
|
addService(this.storeSystemUsage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -56,7 +56,7 @@ public abstract class AbstractRegion implements Region {
|
||||||
protected final Map<ActiveMQDestination, Destination> destinations = new ConcurrentHashMap<ActiveMQDestination, Destination>();
|
protected final Map<ActiveMQDestination, Destination> destinations = new ConcurrentHashMap<ActiveMQDestination, Destination>();
|
||||||
protected final DestinationMap destinationMap = new DestinationMap();
|
protected final DestinationMap destinationMap = new DestinationMap();
|
||||||
protected final Map<ConsumerId, Subscription> subscriptions = new ConcurrentHashMap<ConsumerId, Subscription>();
|
protected final Map<ConsumerId, Subscription> subscriptions = new ConcurrentHashMap<ConsumerId, Subscription>();
|
||||||
protected final SystemUsage memoryManager;
|
protected final SystemUsage usageManager;
|
||||||
protected final DestinationFactory destinationFactory;
|
protected final DestinationFactory destinationFactory;
|
||||||
protected final DestinationStatistics destinationStatistics;
|
protected final DestinationStatistics destinationStatistics;
|
||||||
protected final RegionBroker broker;
|
protected final RegionBroker broker;
|
||||||
|
@ -73,7 +73,7 @@ public abstract class AbstractRegion implements Region {
|
||||||
}
|
}
|
||||||
this.broker = broker;
|
this.broker = broker;
|
||||||
this.destinationStatistics = destinationStatistics;
|
this.destinationStatistics = destinationStatistics;
|
||||||
this.memoryManager = memoryManager;
|
this.usageManager = memoryManager;
|
||||||
this.taskRunnerFactory = taskRunnerFactory;
|
this.taskRunnerFactory = taskRunnerFactory;
|
||||||
if (broker == null) {
|
if (broker == null) {
|
||||||
throw new IllegalArgumentException("null destinationFactory");
|
throw new IllegalArgumentException("null destinationFactory");
|
||||||
|
|
|
@ -43,14 +43,13 @@ public class DurableTopicSubscription extends PrefetchSubscription implements Us
|
||||||
private final ConcurrentHashMap<ActiveMQDestination, Destination> destinations = new ConcurrentHashMap<ActiveMQDestination, Destination>();
|
private final ConcurrentHashMap<ActiveMQDestination, Destination> destinations = new ConcurrentHashMap<ActiveMQDestination, Destination>();
|
||||||
private final SubscriptionKey subscriptionKey;
|
private final SubscriptionKey subscriptionKey;
|
||||||
private final boolean keepDurableSubsActive;
|
private final boolean keepDurableSubsActive;
|
||||||
private final SystemUsage usageManager;
|
|
||||||
private boolean active;
|
private boolean active;
|
||||||
|
|
||||||
public DurableTopicSubscription(Broker broker, SystemUsage usageManager, ConnectionContext context, ConsumerInfo info, boolean keepDurableSubsActive)
|
public DurableTopicSubscription(Broker broker, SystemUsage usageManager, ConnectionContext context, ConsumerInfo info, boolean keepDurableSubsActive)
|
||||||
throws InvalidSelectorException {
|
throws InvalidSelectorException {
|
||||||
super(broker, context, info);
|
super(broker,usageManager, context, info);
|
||||||
this.pending = new StoreDurableSubscriberCursor(context.getClientId(), info.getSubscriptionName(), broker.getTempDataStore(), info.getPrefetchSize(), this);
|
this.pending = new StoreDurableSubscriberCursor(context.getClientId(), info.getSubscriptionName(), broker.getTempDataStore(), info.getPrefetchSize(), this);
|
||||||
this.usageManager = usageManager;
|
this.pending.setSystemUsage(usageManager);
|
||||||
this.keepDurableSubsActive = keepDurableSubsActive;
|
this.keepDurableSubsActive = keepDurableSubsActive;
|
||||||
subscriptionKey = new SubscriptionKey(context.getClientId(), info.getSubscriptionName());
|
subscriptionKey = new SubscriptionKey(context.getClientId(), info.getSubscriptionName());
|
||||||
}
|
}
|
||||||
|
@ -191,7 +190,7 @@ public class DurableTopicSubscription extends PrefetchSubscription implements Us
|
||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized void acknowledge(ConnectionContext context, MessageAck ack, MessageReference node) throws IOException {
|
protected void acknowledge(ConnectionContext context, MessageAck ack, MessageReference node) throws IOException {
|
||||||
node.getRegionDestination().acknowledge(context, this, ack, node);
|
node.getRegionDestination().acknowledge(context, this, ack, node);
|
||||||
redeliveredMessages.remove(node.getMessageId());
|
redeliveredMessages.remove(node.getMessageId());
|
||||||
node.decrementReferenceCount();
|
node.decrementReferenceCount();
|
||||||
|
@ -238,7 +237,7 @@ public class DurableTopicSubscription extends PrefetchSubscription implements Us
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param memoryManager
|
* @param usageManager
|
||||||
* @param oldPercentUsage
|
* @param oldPercentUsage
|
||||||
* @param newPercentUsage
|
* @param newPercentUsage
|
||||||
* @see org.apache.activemq.usage.UsageListener#onMemoryUseChanged(org.apache.activemq.usage.SystemUsage,
|
* @see org.apache.activemq.usage.UsageListener#onMemoryUseChanged(org.apache.activemq.usage.SystemUsage,
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.util.LinkedList;
|
||||||
import javax.jms.InvalidSelectorException;
|
import javax.jms.InvalidSelectorException;
|
||||||
import javax.jms.JMSException;
|
import javax.jms.JMSException;
|
||||||
|
|
||||||
|
import org.apache.activemq.ActiveMQMessageAudit;
|
||||||
import org.apache.activemq.broker.Broker;
|
import org.apache.activemq.broker.Broker;
|
||||||
import org.apache.activemq.broker.ConnectionContext;
|
import org.apache.activemq.broker.ConnectionContext;
|
||||||
import org.apache.activemq.broker.region.cursors.PendingMessageCursor;
|
import org.apache.activemq.broker.region.cursors.PendingMessageCursor;
|
||||||
|
@ -38,6 +39,7 @@ import org.apache.activemq.command.MessagePull;
|
||||||
import org.apache.activemq.command.Response;
|
import org.apache.activemq.command.Response;
|
||||||
import org.apache.activemq.thread.Scheduler;
|
import org.apache.activemq.thread.Scheduler;
|
||||||
import org.apache.activemq.transaction.Synchronization;
|
import org.apache.activemq.transaction.Synchronization;
|
||||||
|
import org.apache.activemq.usage.SystemUsage;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
@ -55,14 +57,20 @@ public abstract class PrefetchSubscription extends AbstractSubscription {
|
||||||
protected long enqueueCounter;
|
protected long enqueueCounter;
|
||||||
protected long dispatchCounter;
|
protected long dispatchCounter;
|
||||||
protected long dequeueCounter;
|
protected long dequeueCounter;
|
||||||
|
protected boolean optimizedDispatch=false;
|
||||||
|
private int maxProducersToAudit=32;
|
||||||
|
private int maxAuditDepth=2048;
|
||||||
|
protected final SystemUsage usageManager;
|
||||||
|
protected ActiveMQMessageAudit audit = new ActiveMQMessageAudit();
|
||||||
|
|
||||||
public PrefetchSubscription(Broker broker, ConnectionContext context, ConsumerInfo info, PendingMessageCursor cursor) throws InvalidSelectorException {
|
public PrefetchSubscription(Broker broker, SystemUsage usageManager, ConnectionContext context, ConsumerInfo info, PendingMessageCursor cursor) throws InvalidSelectorException {
|
||||||
super(broker, context, info);
|
super(broker, context, info);
|
||||||
|
this.usageManager=usageManager;
|
||||||
pending = cursor;
|
pending = cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PrefetchSubscription(Broker broker, ConnectionContext context, ConsumerInfo info) throws InvalidSelectorException {
|
public PrefetchSubscription(Broker broker, SystemUsage usageManager, ConnectionContext context, ConsumerInfo info) throws InvalidSelectorException {
|
||||||
this(broker, context, info, new VMPendingMessageCursor());
|
this(broker,usageManager,context, info, new VMPendingMessageCursor());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -118,8 +126,7 @@ public abstract class PrefetchSubscription extends AbstractSubscription {
|
||||||
boolean pendingEmpty = false;
|
boolean pendingEmpty = false;
|
||||||
pendingEmpty = pending.isEmpty();
|
pendingEmpty = pending.isEmpty();
|
||||||
enqueueCounter++;
|
enqueueCounter++;
|
||||||
|
if (optimizedDispatch && !isFull() && pendingEmpty && !isSlave()) {
|
||||||
if (!isFull() && pendingEmpty && !isSlave()) {
|
|
||||||
dispatch(node);
|
dispatch(node);
|
||||||
} else {
|
} else {
|
||||||
optimizePrefetch();
|
optimizePrefetch();
|
||||||
|
@ -128,6 +135,7 @@ public abstract class PrefetchSubscription extends AbstractSubscription {
|
||||||
LOG.debug("Prefetch limit.");
|
LOG.debug("Prefetch limit.");
|
||||||
}
|
}
|
||||||
pending.addMessageLast(node);
|
pending.addMessageLast(node);
|
||||||
|
dispatchMatched();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -364,6 +372,9 @@ public abstract class PrefetchSubscription extends AbstractSubscription {
|
||||||
|
|
||||||
public synchronized void setPending(PendingMessageCursor pending) {
|
public synchronized void setPending(PendingMessageCursor pending) {
|
||||||
this.pending = pending;
|
this.pending = pending;
|
||||||
|
if (this.pending!=null) {
|
||||||
|
this.pending.setSystemUsage(usageManager);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -440,6 +451,9 @@ public abstract class PrefetchSubscription extends AbstractSubscription {
|
||||||
if (node != QueueMessageReference.NULL_MESSAGE) {
|
if (node != QueueMessageReference.NULL_MESSAGE) {
|
||||||
dispatchCounter++;
|
dispatchCounter++;
|
||||||
dispatched.addLast(node);
|
dispatched.addLast(node);
|
||||||
|
if(pending != null) {
|
||||||
|
pending.dispatched(message);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
prefetchExtension = Math.max(0, prefetchExtension - 1);
|
prefetchExtension = Math.max(0, prefetchExtension - 1);
|
||||||
}
|
}
|
||||||
|
@ -459,8 +473,6 @@ public abstract class PrefetchSubscription extends AbstractSubscription {
|
||||||
context.getConnection().dispatchSync(md);
|
context.getConnection().dispatchSync(md);
|
||||||
onDispatch(node, message);
|
onDispatch(node, message);
|
||||||
}
|
}
|
||||||
// System.err.println(broker.getBrokerName() + " " + this + " (" +
|
|
||||||
// enqueueCounter + ", " + dispatchCounter +") " + node);
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -536,4 +548,28 @@ public abstract class PrefetchSubscription extends AbstractSubscription {
|
||||||
protected void acknowledge(ConnectionContext context, final MessageAck ack, final MessageReference node) throws IOException {
|
protected void acknowledge(ConnectionContext context, final MessageAck ack, final MessageReference node) throws IOException {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isOptimizedDispatch() {
|
||||||
|
return optimizedDispatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOptimizedDispatch(boolean optimizedDispatch) {
|
||||||
|
this.optimizedDispatch = optimizedDispatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxProducersToAudit() {
|
||||||
|
return maxProducersToAudit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxProducersToAudit(int maxProducersToAudit) {
|
||||||
|
this.maxProducersToAudit = maxProducersToAudit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxAuditDepth() {
|
||||||
|
return maxAuditDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxAuditDepth(int maxAuditDepth) {
|
||||||
|
this.maxAuditDepth = maxAuditDepth;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ public class Queue extends BaseDestination implements Task {
|
||||||
private int maximumPagedInMessages = garbageSizeBeforeCollection * 2;
|
private int maximumPagedInMessages = garbageSizeBeforeCollection * 2;
|
||||||
private final MessageEvaluationContext queueMsgConext = new MessageEvaluationContext();
|
private final MessageEvaluationContext queueMsgConext = new MessageEvaluationContext();
|
||||||
private final Object exclusiveLockMutex = new Object();
|
private final Object exclusiveLockMutex = new Object();
|
||||||
private TaskRunner taskRunner;
|
private final TaskRunner taskRunner;
|
||||||
|
|
||||||
private final LinkedList<Runnable> messagesWaitingForSpace = new LinkedList<Runnable>();
|
private final LinkedList<Runnable> messagesWaitingForSpace = new LinkedList<Runnable>();
|
||||||
private final Runnable sendMessagesWaitingForSpaceTask = new Runnable() {
|
private final Runnable sendMessagesWaitingForSpaceTask = new Runnable() {
|
||||||
|
|
|
@ -25,14 +25,15 @@ import org.apache.activemq.command.Message;
|
||||||
import org.apache.activemq.command.MessageAck;
|
import org.apache.activemq.command.MessageAck;
|
||||||
import org.apache.activemq.command.MessageDispatch;
|
import org.apache.activemq.command.MessageDispatch;
|
||||||
import org.apache.activemq.filter.MessageEvaluationContext;
|
import org.apache.activemq.filter.MessageEvaluationContext;
|
||||||
|
import org.apache.activemq.usage.SystemUsage;
|
||||||
|
|
||||||
public class QueueBrowserSubscription extends QueueSubscription {
|
public class QueueBrowserSubscription extends QueueSubscription {
|
||||||
|
|
||||||
boolean browseDone;
|
boolean browseDone;
|
||||||
|
|
||||||
public QueueBrowserSubscription(Broker broker, ConnectionContext context, ConsumerInfo info)
|
public QueueBrowserSubscription(Broker broker, SystemUsage usageManager, ConnectionContext context, ConsumerInfo info)
|
||||||
throws InvalidSelectorException {
|
throws InvalidSelectorException {
|
||||||
super(broker, context, info);
|
super(broker,usageManager, context, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean canDispatch(MessageReference node) {
|
protected boolean canDispatch(MessageReference node) {
|
||||||
|
|
|
@ -41,15 +41,15 @@ public class QueueRegion extends AbstractRegion {
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "QueueRegion: destinations=" + destinations.size() + ", subscriptions=" + subscriptions.size()
|
return "QueueRegion: destinations=" + destinations.size() + ", subscriptions=" + subscriptions.size()
|
||||||
+ ", memory=" + memoryManager.getMemoryUsage().getPercentUsage() + "%";
|
+ ", memory=" + usageManager.getMemoryUsage().getPercentUsage() + "%";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Subscription createSubscription(ConnectionContext context, ConsumerInfo info)
|
protected Subscription createSubscription(ConnectionContext context, ConsumerInfo info)
|
||||||
throws InvalidSelectorException {
|
throws InvalidSelectorException {
|
||||||
if (info.isBrowser()) {
|
if (info.isBrowser()) {
|
||||||
return new QueueBrowserSubscription(broker, context, info);
|
return new QueueBrowserSubscription(broker,usageManager, context, info);
|
||||||
} else {
|
} else {
|
||||||
return new QueueSubscription(broker, context, info);
|
return new QueueSubscription(broker, usageManager,context, info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.apache.activemq.command.ConsumerInfo;
|
||||||
import org.apache.activemq.command.Message;
|
import org.apache.activemq.command.Message;
|
||||||
import org.apache.activemq.command.MessageAck;
|
import org.apache.activemq.command.MessageAck;
|
||||||
import org.apache.activemq.transaction.Synchronization;
|
import org.apache.activemq.transaction.Synchronization;
|
||||||
|
import org.apache.activemq.usage.SystemUsage;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
@ -35,8 +36,8 @@ public class QueueSubscription extends PrefetchSubscription implements LockOwner
|
||||||
|
|
||||||
private static final Log LOG = LogFactory.getLog(QueueSubscription.class);
|
private static final Log LOG = LogFactory.getLog(QueueSubscription.class);
|
||||||
|
|
||||||
public QueueSubscription(Broker broker, ConnectionContext context, ConsumerInfo info) throws InvalidSelectorException {
|
public QueueSubscription(Broker broker, SystemUsage usageManager, ConnectionContext context, ConsumerInfo info) throws InvalidSelectorException {
|
||||||
super(broker, context, info);
|
super(broker,usageManager, context, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class TempQueueRegion extends AbstractRegion {
|
||||||
|
|
||||||
protected Destination createDestination(ConnectionContext context, ActiveMQDestination destination) throws Exception {
|
protected Destination createDestination(ConnectionContext context, ActiveMQDestination destination) throws Exception {
|
||||||
final ActiveMQTempDestination tempDest = (ActiveMQTempDestination)destination;
|
final ActiveMQTempDestination tempDest = (ActiveMQTempDestination)destination;
|
||||||
return new Queue(broker.getRoot(), destination, memoryManager, null, destinationStatistics, taskRunnerFactory, null) {
|
return new Queue(broker.getRoot(), destination, usageManager, null, destinationStatistics, taskRunnerFactory, null) {
|
||||||
|
|
||||||
public void addSubscription(ConnectionContext context, Subscription sub) throws Exception {
|
public void addSubscription(ConnectionContext context, Subscription sub) throws Exception {
|
||||||
|
|
||||||
|
@ -58,14 +58,14 @@ public class TempQueueRegion extends AbstractRegion {
|
||||||
|
|
||||||
protected Subscription createSubscription(ConnectionContext context, ConsumerInfo info) throws InvalidSelectorException {
|
protected Subscription createSubscription(ConnectionContext context, ConsumerInfo info) throws InvalidSelectorException {
|
||||||
if (info.isBrowser()) {
|
if (info.isBrowser()) {
|
||||||
return new QueueBrowserSubscription(broker, context, info);
|
return new QueueBrowserSubscription(broker,usageManager,context, info);
|
||||||
} else {
|
} else {
|
||||||
return new QueueSubscription(broker, context, info);
|
return new QueueSubscription(broker, usageManager,context, info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "TempQueueRegion: destinations=" + destinations.size() + ", subscriptions=" + subscriptions.size() + ", memory=" + memoryManager.getMemoryUsage().getPercentUsage() + "%";
|
return "TempQueueRegion: destinations=" + destinations.size() + ", subscriptions=" + subscriptions.size() + ", memory=" + usageManager.getMemoryUsage().getPercentUsage() + "%";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeDestination(ConnectionContext context, ActiveMQDestination destination, long timeout) throws Exception {
|
public void removeDestination(ConnectionContext context, ActiveMQDestination destination, long timeout) throws Exception {
|
||||||
|
|
|
@ -47,13 +47,13 @@ public class TempTopicRegion extends AbstractRegion {
|
||||||
throw new JMSException("A durable subscription cannot be created for a temporary topic.");
|
throw new JMSException("A durable subscription cannot be created for a temporary topic.");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
TopicSubscription answer = new TopicSubscription(broker, context, info, memoryManager);
|
TopicSubscription answer = new TopicSubscription(broker, context, info, usageManager);
|
||||||
// lets configure the subscription depending on the destination
|
// lets configure the subscription depending on the destination
|
||||||
ActiveMQDestination destination = info.getDestination();
|
ActiveMQDestination destination = info.getDestination();
|
||||||
if (destination != null && broker.getDestinationPolicy() != null) {
|
if (destination != null && broker.getDestinationPolicy() != null) {
|
||||||
PolicyEntry entry = broker.getDestinationPolicy().getEntryFor(destination);
|
PolicyEntry entry = broker.getDestinationPolicy().getEntryFor(destination);
|
||||||
if (entry != null) {
|
if (entry != null) {
|
||||||
entry.configure(broker, memoryManager, answer);
|
entry.configure(broker, usageManager, answer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
answer.init();
|
answer.init();
|
||||||
|
@ -67,7 +67,7 @@ public class TempTopicRegion extends AbstractRegion {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "TempTopicRegion: destinations=" + destinations.size() + ", subscriptions=" + subscriptions.size() + ", memory=" + memoryManager.getMemoryUsage().getPercentUsage() + "%";
|
return "TempTopicRegion: destinations=" + destinations.size() + ", subscriptions=" + subscriptions.size() + ", memory=" + usageManager.getMemoryUsage().getPercentUsage() + "%";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeDestination(ConnectionContext context, ActiveMQDestination destination, long timeout) throws Exception {
|
public void removeDestination(ConnectionContext context, ActiveMQDestination destination, long timeout) throws Exception {
|
||||||
|
|
|
@ -50,6 +50,8 @@ import org.apache.activemq.state.ProducerState;
|
||||||
import org.apache.activemq.store.MessageRecoveryListener;
|
import org.apache.activemq.store.MessageRecoveryListener;
|
||||||
import org.apache.activemq.store.MessageStore;
|
import org.apache.activemq.store.MessageStore;
|
||||||
import org.apache.activemq.store.TopicMessageStore;
|
import org.apache.activemq.store.TopicMessageStore;
|
||||||
|
import org.apache.activemq.thread.Task;
|
||||||
|
import org.apache.activemq.thread.TaskRunner;
|
||||||
import org.apache.activemq.thread.TaskRunnerFactory;
|
import org.apache.activemq.thread.TaskRunnerFactory;
|
||||||
import org.apache.activemq.thread.Valve;
|
import org.apache.activemq.thread.Valve;
|
||||||
import org.apache.activemq.transaction.Synchronization;
|
import org.apache.activemq.transaction.Synchronization;
|
||||||
|
@ -65,7 +67,7 @@ import org.apache.commons.logging.LogFactory;
|
||||||
*
|
*
|
||||||
* @version $Revision: 1.21 $
|
* @version $Revision: 1.21 $
|
||||||
*/
|
*/
|
||||||
public class Topic extends BaseDestination {
|
public class Topic extends BaseDestination implements Task{
|
||||||
private static final Log LOG = LogFactory.getLog(Topic.class);
|
private static final Log LOG = LogFactory.getLog(Topic.class);
|
||||||
protected final ActiveMQDestination destination;
|
protected final ActiveMQDestination destination;
|
||||||
protected final CopyOnWriteArrayList<Subscription> consumers = new CopyOnWriteArrayList<Subscription>();
|
protected final CopyOnWriteArrayList<Subscription> consumers = new CopyOnWriteArrayList<Subscription>();
|
||||||
|
@ -81,28 +83,20 @@ public class Topic extends BaseDestination {
|
||||||
private boolean sendAdvisoryIfNoConsumers;
|
private boolean sendAdvisoryIfNoConsumers;
|
||||||
private DeadLetterStrategy deadLetterStrategy = new SharedDeadLetterStrategy();
|
private DeadLetterStrategy deadLetterStrategy = new SharedDeadLetterStrategy();
|
||||||
private final ConcurrentHashMap<SubscriptionKey, DurableTopicSubscription> durableSubcribers = new ConcurrentHashMap<SubscriptionKey, DurableTopicSubscription>();
|
private final ConcurrentHashMap<SubscriptionKey, DurableTopicSubscription> durableSubcribers = new ConcurrentHashMap<SubscriptionKey, DurableTopicSubscription>();
|
||||||
|
private final TaskRunner taskRunner;
|
||||||
private final LinkedList<Runnable> messagesWaitingForSpace = new LinkedList<Runnable>();
|
private final LinkedList<Runnable> messagesWaitingForSpace = new LinkedList<Runnable>();
|
||||||
private final Runnable sendMessagesWaitingForSpaceTask = new Runnable() {
|
private final Runnable sendMessagesWaitingForSpaceTask = new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
try {
|
||||||
// We may need to do this in async thread since this is run for
|
Topic.this.taskRunner.wakeup();
|
||||||
// within a synchronization
|
} catch (InterruptedException e) {
|
||||||
// that the UsageManager is holding.
|
|
||||||
|
|
||||||
synchronized (messagesWaitingForSpace) {
|
|
||||||
while (!memoryUsage.isFull() && !messagesWaitingForSpace.isEmpty()) {
|
|
||||||
Runnable op = messagesWaitingForSpace.removeFirst();
|
|
||||||
op.run();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
private final Broker broker;
|
private final Broker broker;
|
||||||
|
|
||||||
public Topic(Broker broker, ActiveMQDestination destination, TopicMessageStore store, SystemUsage systemUsage, DestinationStatistics parentStats,
|
public Topic(Broker broker, ActiveMQDestination destination, TopicMessageStore store, SystemUsage systemUsage, DestinationStatistics parentStats,
|
||||||
TaskRunnerFactory taskFactory) {
|
TaskRunnerFactory taskFactory) throws Exception {
|
||||||
this.broker = broker;
|
this.broker = broker;
|
||||||
this.destination = destination;
|
this.destination = destination;
|
||||||
this.store = store; // this could be NULL! (If an advisory)
|
this.store = store; // this could be NULL! (If an advisory)
|
||||||
|
@ -116,6 +110,7 @@ public class Topic extends BaseDestination {
|
||||||
//set the default
|
//set the default
|
||||||
subscriptionRecoveryPolicy= new FixedSizedSubscriptionRecoveryPolicy();
|
subscriptionRecoveryPolicy= new FixedSizedSubscriptionRecoveryPolicy();
|
||||||
}
|
}
|
||||||
|
this.taskRunner = taskFactory.createTaskRunner(this, "Topic " + destination.getPhysicalName());
|
||||||
// Let the store know what usage manager we are using so that he can
|
// Let the store know what usage manager we are using so that he can
|
||||||
// flush messages to disk
|
// flush messages to disk
|
||||||
// when usage gets high.
|
// when usage gets high.
|
||||||
|
@ -463,6 +458,9 @@ public class Topic extends BaseDestination {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() throws Exception {
|
public void stop() throws Exception {
|
||||||
|
if (taskRunner != null) {
|
||||||
|
taskRunner.shutdown();
|
||||||
|
}
|
||||||
this.subscriptionRecoveryPolicy.stop();
|
this.subscriptionRecoveryPolicy.stop();
|
||||||
if (memoryUsage != null) {
|
if (memoryUsage != null) {
|
||||||
memoryUsage.stop();
|
memoryUsage.stop();
|
||||||
|
@ -500,6 +498,15 @@ public class Topic extends BaseDestination {
|
||||||
return result.toArray(new Message[result.size()]);
|
return result.toArray(new Message[result.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean iterate() {
|
||||||
|
while (!memoryUsage.isFull() && !messagesWaitingForSpace.isEmpty()) {
|
||||||
|
Runnable op = messagesWaitingForSpace.removeFirst();
|
||||||
|
op.run();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ public class TopicRegion extends AbstractRegion {
|
||||||
+ " subscriberName: " + key.getSubscriptionName());
|
+ " subscriberName: " + key.getSubscriptionName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sub.activate(memoryManager, context, info);
|
sub.activate(usageManager, context, info);
|
||||||
return sub;
|
return sub;
|
||||||
} else {
|
} else {
|
||||||
return super.addConsumer(context, info);
|
return super.addConsumer(context, info);
|
||||||
|
@ -140,7 +140,7 @@ public class TopicRegion extends AbstractRegion {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "TopicRegion: destinations=" + destinations.size() + ", subscriptions=" + subscriptions.size() + ", memory=" + memoryManager.getMemoryUsage().getPercentUsage() + "%";
|
return "TopicRegion: destinations=" + destinations.size() + ", subscriptions=" + subscriptions.size() + ", memory=" + usageManager.getMemoryUsage().getPercentUsage() + "%";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -230,12 +230,12 @@ public class TopicRegion extends AbstractRegion {
|
||||||
SubscriptionKey key = new SubscriptionKey(context.getClientId(), info.getSubscriptionName());
|
SubscriptionKey key = new SubscriptionKey(context.getClientId(), info.getSubscriptionName());
|
||||||
DurableTopicSubscription sub = durableSubscriptions.get(key);
|
DurableTopicSubscription sub = durableSubscriptions.get(key);
|
||||||
if (sub == null) {
|
if (sub == null) {
|
||||||
sub = new DurableTopicSubscription(broker, memoryManager, context, info, keepDurableSubsActive);
|
sub = new DurableTopicSubscription(broker, usageManager, context, info, keepDurableSubsActive);
|
||||||
ActiveMQDestination destination = info.getDestination();
|
ActiveMQDestination destination = info.getDestination();
|
||||||
if (destination != null && broker.getDestinationPolicy() != null) {
|
if (destination != null && broker.getDestinationPolicy() != null) {
|
||||||
PolicyEntry entry = broker.getDestinationPolicy().getEntryFor(destination);
|
PolicyEntry entry = broker.getDestinationPolicy().getEntryFor(destination);
|
||||||
if (entry != null) {
|
if (entry != null) {
|
||||||
entry.configure(broker, memoryManager, sub);
|
entry.configure(broker, usageManager, sub);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
durableSubscriptions.put(key, sub);
|
durableSubscriptions.put(key, sub);
|
||||||
|
@ -245,13 +245,13 @@ public class TopicRegion extends AbstractRegion {
|
||||||
return sub;
|
return sub;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
TopicSubscription answer = new TopicSubscription(broker, context, info, memoryManager);
|
TopicSubscription answer = new TopicSubscription(broker, context, info, usageManager);
|
||||||
// lets configure the subscription depending on the destination
|
// lets configure the subscription depending on the destination
|
||||||
ActiveMQDestination destination = info.getDestination();
|
ActiveMQDestination destination = info.getDestination();
|
||||||
if (destination != null && broker.getDestinationPolicy() != null) {
|
if (destination != null && broker.getDestinationPolicy() != null) {
|
||||||
PolicyEntry entry = broker.getDestinationPolicy().getEntryFor(destination);
|
PolicyEntry entry = broker.getDestinationPolicy().getEntryFor(destination);
|
||||||
if (entry != null) {
|
if (entry != null) {
|
||||||
entry.configure(broker, memoryManager, answer);
|
entry.configure(broker, usageManager, answer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
answer.init();
|
answer.init();
|
||||||
|
|
|
@ -50,6 +50,7 @@ public class AbstractPendingMessageCursor implements PendingMessageCursor {
|
||||||
|
|
||||||
public synchronized void stop() throws Exception {
|
public synchronized void stop() throws Exception {
|
||||||
started=false;
|
started=false;
|
||||||
|
audit=null;
|
||||||
gc();
|
gc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,6 +240,13 @@ public class AbstractPendingMessageCursor implements PendingMessageCursor {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark a message as already dispatched
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
public void dispatched(MessageReference message) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected synchronized boolean isDuplicate(MessageId messageId) {
|
protected synchronized boolean isDuplicate(MessageId messageId) {
|
||||||
if (!this.enableAudit || this.audit==null) {
|
if (!this.enableAudit || this.audit==null) {
|
||||||
|
@ -247,6 +255,11 @@ public class AbstractPendingMessageCursor implements PendingMessageCursor {
|
||||||
return this.audit.isDuplicate(messageId);
|
return this.audit.isDuplicate(messageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected synchronized void rollback(MessageId id) {
|
||||||
|
if (this.audit != null) {
|
||||||
|
audit.rollback(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,6 +142,7 @@ public class FilePendingMessageCursor extends AbstractPendingMessageCursor imple
|
||||||
for (Iterator<MessageReference> i = getDiskList().iterator(); i.hasNext() && count < maxItems;) {
|
for (Iterator<MessageReference> i = getDiskList().iterator(); i.hasNext() && count < maxItems;) {
|
||||||
Message message = (Message)i.next();
|
Message message = (Message)i.next();
|
||||||
message.setRegionDestination(regionDestination);
|
message.setRegionDestination(regionDestination);
|
||||||
|
message.setMemoryUsage(this.getSystemUsage().getMemoryUsage());
|
||||||
message.incrementReferenceCount();
|
message.incrementReferenceCount();
|
||||||
result.add(message);
|
result.add(message);
|
||||||
count++;
|
count++;
|
||||||
|
@ -210,6 +211,7 @@ public class FilePendingMessageCursor extends AbstractPendingMessageCursor imple
|
||||||
if (!isDiskListEmpty()) {
|
if (!isDiskListEmpty()) {
|
||||||
// got from disk
|
// got from disk
|
||||||
message.setRegionDestination(regionDestination);
|
message.setRegionDestination(regionDestination);
|
||||||
|
message.setMemoryUsage(this.getSystemUsage().getMemoryUsage());
|
||||||
message.incrementReferenceCount();
|
message.incrementReferenceCount();
|
||||||
}
|
}
|
||||||
return message;
|
return message;
|
||||||
|
|
|
@ -248,5 +248,11 @@ public interface PendingMessageCursor extends Service {
|
||||||
*/
|
*/
|
||||||
public boolean isTransient();
|
public boolean isTransient();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark a message as already dispatched
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
public void dispatched(MessageReference message);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,6 +119,7 @@ class QueueStorePrefetch extends AbstractPendingMessageCursor implements Message
|
||||||
Message result = batchList.removeFirst();
|
Message result = batchList.removeFirst();
|
||||||
result.decrementReferenceCount();
|
result.decrementReferenceCount();
|
||||||
result.setRegionDestination(regionDestination);
|
result.setRegionDestination(regionDestination);
|
||||||
|
result.setMemoryUsage(this.getSystemUsage().getMemoryUsage());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +134,7 @@ class QueueStorePrefetch extends AbstractPendingMessageCursor implements Message
|
||||||
throws Exception {
|
throws Exception {
|
||||||
if (!isDuplicate(message.getMessageId())) {
|
if (!isDuplicate(message.getMessageId())) {
|
||||||
message.setRegionDestination(regionDestination);
|
message.setRegionDestination(regionDestination);
|
||||||
|
message.setMemoryUsage(this.getSystemUsage().getMemoryUsage());
|
||||||
message.incrementReferenceCount();
|
message.incrementReferenceCount();
|
||||||
batchList.addLast(message);
|
batchList.addLast(message);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -289,6 +289,20 @@ public class StoreDurableSubscriberCursor extends AbstractPendingMessageCursor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark a message as already dispatched
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
public void dispatched(MessageReference message) {
|
||||||
|
super.dispatched(message);
|
||||||
|
for (PendingMessageCursor cursor : storePrefetches) {
|
||||||
|
cursor.dispatched(message);
|
||||||
|
}
|
||||||
|
if (nonPersistent != null) {
|
||||||
|
nonPersistent.dispatched(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected synchronized PendingMessageCursor getNextCursor() throws Exception {
|
protected synchronized PendingMessageCursor getNextCursor() throws Exception {
|
||||||
if (currentCursor == null || currentCursor.isEmpty()) {
|
if (currentCursor == null || currentCursor.isEmpty()) {
|
||||||
currentCursor = null;
|
currentCursor = null;
|
||||||
|
|
|
@ -18,7 +18,9 @@ package org.apache.activemq.broker.region.cursors;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.activemq.broker.region.Destination;
|
import org.apache.activemq.broker.region.Destination;
|
||||||
import org.apache.activemq.broker.region.MessageReference;
|
import org.apache.activemq.broker.region.MessageReference;
|
||||||
import org.apache.activemq.broker.region.Subscription;
|
import org.apache.activemq.broker.region.Subscription;
|
||||||
|
@ -28,6 +30,9 @@ import org.apache.activemq.command.MessageId;
|
||||||
import org.apache.activemq.filter.MessageEvaluationContext;
|
import org.apache.activemq.filter.MessageEvaluationContext;
|
||||||
import org.apache.activemq.store.MessageRecoveryListener;
|
import org.apache.activemq.store.MessageRecoveryListener;
|
||||||
import org.apache.activemq.store.TopicMessageStore;
|
import org.apache.activemq.store.TopicMessageStore;
|
||||||
|
import org.apache.activemq.usage.SystemUsage;
|
||||||
|
import org.apache.activemq.usage.Usage;
|
||||||
|
import org.apache.activemq.usage.UsageListener;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
@ -37,16 +42,14 @@ import org.apache.commons.logging.LogFactory;
|
||||||
*
|
*
|
||||||
* @version $Revision$
|
* @version $Revision$
|
||||||
*/
|
*/
|
||||||
class TopicStorePrefetch extends AbstractPendingMessageCursor implements MessageRecoveryListener {
|
class TopicStorePrefetch extends AbstractPendingMessageCursor implements MessageRecoveryListener, UsageListener {
|
||||||
|
|
||||||
private static final Log LOG = LogFactory.getLog(TopicStorePrefetch.class);
|
private static final Log LOG = LogFactory.getLog(TopicStorePrefetch.class);
|
||||||
private TopicMessageStore store;
|
private TopicMessageStore store;
|
||||||
private final LinkedList<Message> batchList = new LinkedList<Message>();
|
private final LinkedHashMap<MessageId,Message> batchList = new LinkedHashMap<MessageId,Message> ();
|
||||||
private String clientId;
|
private String clientId;
|
||||||
private String subscriberName;
|
private String subscriberName;
|
||||||
private Destination regionDestination;
|
private Destination regionDestination;
|
||||||
private MessageId firstMessageId;
|
|
||||||
private MessageId lastMessageId;
|
|
||||||
private boolean batchResetNeeded = true;
|
private boolean batchResetNeeded = true;
|
||||||
private boolean storeMayHaveMoreMessages = true;
|
private boolean storeMayHaveMoreMessages = true;
|
||||||
private boolean started;
|
private boolean started;
|
||||||
|
@ -63,12 +66,15 @@ class TopicStorePrefetch extends AbstractPendingMessageCursor implements Message
|
||||||
this.store = (TopicMessageStore)topic.getMessageStore();
|
this.store = (TopicMessageStore)topic.getMessageStore();
|
||||||
this.clientId = clientId;
|
this.clientId = clientId;
|
||||||
this.subscriberName = subscriberName;
|
this.subscriberName = subscriberName;
|
||||||
|
this.maxProducersToAudit=32;
|
||||||
|
this.maxAuditDepth=10000;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void start() throws Exception {
|
public synchronized void start() throws Exception {
|
||||||
if (!started) {
|
if (!started) {
|
||||||
started = true;
|
started = true;
|
||||||
super.start();
|
super.start();
|
||||||
|
getSystemUsage().getMemoryUsage().addUsageListener(this);
|
||||||
safeFillBatch();
|
safeFillBatch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,6 +82,7 @@ class TopicStorePrefetch extends AbstractPendingMessageCursor implements Message
|
||||||
public synchronized void stop() throws Exception {
|
public synchronized void stop() throws Exception {
|
||||||
if (started) {
|
if (started) {
|
||||||
started = false;
|
started = false;
|
||||||
|
getSystemUsage().getMemoryUsage().removeUsageListener(this);
|
||||||
super.stop();
|
super.stop();
|
||||||
store.resetBatching(clientId, subscriberName);
|
store.resetBatching(clientId, subscriberName);
|
||||||
gc();
|
gc();
|
||||||
|
@ -97,22 +104,16 @@ class TopicStorePrefetch extends AbstractPendingMessageCursor implements Message
|
||||||
|
|
||||||
public synchronized void addMessageLast(MessageReference node) throws Exception {
|
public synchronized void addMessageLast(MessageReference node) throws Exception {
|
||||||
if (node != null) {
|
if (node != null) {
|
||||||
if (isEmpty() && started) {
|
|
||||||
firstMessageId = node.getMessageId();
|
|
||||||
}
|
|
||||||
lastMessageId = node.getMessageId();
|
|
||||||
node.decrementReferenceCount();
|
|
||||||
storeMayHaveMoreMessages=true;
|
storeMayHaveMoreMessages=true;
|
||||||
|
node.decrementReferenceCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void addMessageFirst(MessageReference node) throws Exception {
|
public synchronized void addMessageFirst(MessageReference node) throws Exception {
|
||||||
if (node != null) {
|
if (node != null) {
|
||||||
if (started) {
|
|
||||||
firstMessageId = node.getMessageId();
|
|
||||||
}
|
|
||||||
node.decrementReferenceCount();
|
|
||||||
storeMayHaveMoreMessages=true;
|
storeMayHaveMoreMessages=true;
|
||||||
|
node.decrementReferenceCount();
|
||||||
|
rollback(node.getMessageId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +128,8 @@ class TopicStorePrefetch extends AbstractPendingMessageCursor implements Message
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean hasNext() {
|
public synchronized boolean hasNext() {
|
||||||
return !isEmpty();
|
boolean result = !isEmpty();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized MessageReference next() {
|
public synchronized MessageReference next() {
|
||||||
|
@ -136,13 +138,11 @@ class TopicStorePrefetch extends AbstractPendingMessageCursor implements Message
|
||||||
if (batchList.isEmpty()) {
|
if (batchList.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
result = batchList.removeFirst();
|
Iterator i = batchList.entrySet().iterator();
|
||||||
if (lastMessageId != null) {
|
result = (Message) ((Map.Entry)i.next()).getValue();
|
||||||
if (result.getMessageId().equals(lastMessageId)) {
|
i.remove();
|
||||||
// pendingCount=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.setRegionDestination(regionDestination);
|
result.setRegionDestination(regionDestination);
|
||||||
|
result.setMemoryUsage(this.getSystemUsage().getMemoryUsage());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -154,16 +154,23 @@ class TopicStorePrefetch extends AbstractPendingMessageCursor implements Message
|
||||||
public void finished() {
|
public void finished() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean recoverMessage(Message message) throws Exception {
|
public synchronized boolean recoverMessage(Message message)
|
||||||
|
throws Exception {
|
||||||
MessageEvaluationContext messageEvaluationContext = new MessageEvaluationContext();
|
MessageEvaluationContext messageEvaluationContext = new MessageEvaluationContext();
|
||||||
messageEvaluationContext.setMessageReference(message);
|
messageEvaluationContext.setMessageReference(message);
|
||||||
if( subscription.matches(message, messageEvaluationContext) ) {
|
if (subscription.matches(message, messageEvaluationContext)) {
|
||||||
message.setRegionDestination(regionDestination);
|
message.setRegionDestination(regionDestination);
|
||||||
// only increment if count is zero (could have been cached)
|
if (!isDuplicate(message.getMessageId())) {
|
||||||
if (message.getReferenceCount() == 0) {
|
// only increment if count is zero (could have been cached)
|
||||||
message.incrementReferenceCount();
|
if (message.getReferenceCount() == 0) {
|
||||||
|
message.setMemoryUsage(this.getSystemUsage().getMemoryUsage());
|
||||||
|
message.incrementReferenceCount();
|
||||||
|
|
||||||
|
}
|
||||||
|
batchList.put(message.getMessageId(), message);
|
||||||
|
}else {
|
||||||
|
this.storeMayHaveMoreMessages=true;
|
||||||
}
|
}
|
||||||
batchList.addLast(message);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -173,8 +180,22 @@ class TopicStorePrefetch extends AbstractPendingMessageCursor implements Message
|
||||||
throw new RuntimeException("Not supported");
|
throw new RuntimeException("Not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark a message as already dispatched
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
public synchronized void dispatched(MessageReference message) {
|
||||||
|
if (this.audit != null) {
|
||||||
|
isDuplicate(message.getMessageId());
|
||||||
|
Message removed = this.batchList.remove(message.getMessageId());
|
||||||
|
if (removed != null) {
|
||||||
|
removed.decrementReferenceCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// implementation
|
// implementation
|
||||||
protected void safeFillBatch() {
|
protected synchronized void safeFillBatch() {
|
||||||
try {
|
try {
|
||||||
fillBatch();
|
fillBatch();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -184,29 +205,17 @@ class TopicStorePrefetch extends AbstractPendingMessageCursor implements Message
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized void fillBatch() throws Exception {
|
protected synchronized void fillBatch() throws Exception {
|
||||||
if( batchResetNeeded ) {
|
if (batchResetNeeded) {
|
||||||
store.resetBatching(clientId, subscriberName);
|
this.store.resetBatching(clientId, subscriberName);
|
||||||
batchResetNeeded=false;
|
this.batchResetNeeded = false;
|
||||||
storeMayHaveMoreMessages=true;
|
this.storeMayHaveMoreMessages = true;
|
||||||
}
|
}
|
||||||
|
while (this.batchList.isEmpty() && this.storeMayHaveMoreMessages) {
|
||||||
while( batchList.isEmpty() && storeMayHaveMoreMessages ) {
|
this.storeMayHaveMoreMessages = false;
|
||||||
store.recoverNextMessages(clientId, subscriberName, maxBatchSize, this);
|
this.store.recoverNextMessages(clientId, subscriberName,
|
||||||
if( batchList.isEmpty() ) {
|
maxBatchSize, this);
|
||||||
storeMayHaveMoreMessages = false;
|
if (!this.batchList.isEmpty()) {
|
||||||
} else {
|
this.storeMayHaveMoreMessages=true;
|
||||||
if (firstMessageId != null) {
|
|
||||||
int pos = 0;
|
|
||||||
for (Iterator<Message> iter = batchList.iterator(); iter.hasNext();) {
|
|
||||||
Message msg = iter.next();
|
|
||||||
if (msg.getMessageId().equals(firstMessageId)) {
|
|
||||||
firstMessageId = null;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
iter.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,13 +230,24 @@ class TopicStorePrefetch extends AbstractPendingMessageCursor implements Message
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void gc() {
|
public synchronized void gc() {
|
||||||
for (Message msg : batchList) {
|
for (Message msg : batchList.values()) {
|
||||||
msg.decrementReferenceCount();
|
msg.decrementReferenceCount();
|
||||||
}
|
}
|
||||||
batchList.clear();
|
batchList.clear();
|
||||||
batchResetNeeded = true;
|
batchResetNeeded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onUsageChanged(Usage usage, int oldPercentUsage,int newPercentUsage) {
|
||||||
|
if (oldPercentUsage > newPercentUsage && oldPercentUsage >= 90) {
|
||||||
|
storeMayHaveMoreMessages = true;
|
||||||
|
try {
|
||||||
|
fillBatch();
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error("Failed to fill batch ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "TopicStorePrefetch" + System.identityHashCode(this) + "(" + clientId + "," + subscriberName + ")";
|
return "TopicStorePrefetch" + System.identityHashCode(this) + "(" + clientId + "," + subscriberName + ")";
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,10 +51,12 @@ public class PolicyEntry extends DestinationMapEntry {
|
||||||
private PendingQueueMessageStoragePolicy pendingQueuePolicy;
|
private PendingQueueMessageStoragePolicy pendingQueuePolicy;
|
||||||
private PendingDurableSubscriberMessageStoragePolicy pendingDurableSubscriberPolicy;
|
private PendingDurableSubscriberMessageStoragePolicy pendingDurableSubscriberPolicy;
|
||||||
private PendingSubscriberMessageStoragePolicy pendingSubscriberPolicy;
|
private PendingSubscriberMessageStoragePolicy pendingSubscriberPolicy;
|
||||||
private int maxProducersToAudit=1024;
|
private int maxProducersToAudit=32;
|
||||||
private int maxAuditDepth=1;
|
private int maxAuditDepth=1024;
|
||||||
|
private int maxQueueAuditDepth=1;
|
||||||
private boolean enableAudit=true;
|
private boolean enableAudit=true;
|
||||||
private boolean producerFlowControl = true;
|
private boolean producerFlowControl = true;
|
||||||
|
private boolean optimizedDispatch=false;
|
||||||
|
|
||||||
public void configure(Queue queue, Store tmpStore) {
|
public void configure(Queue queue, Store tmpStore) {
|
||||||
if (dispatchPolicy != null) {
|
if (dispatchPolicy != null) {
|
||||||
|
@ -73,7 +75,7 @@ public class PolicyEntry extends DestinationMapEntry {
|
||||||
}
|
}
|
||||||
queue.setProducerFlowControl(isProducerFlowControl());
|
queue.setProducerFlowControl(isProducerFlowControl());
|
||||||
queue.setEnableAudit(isEnableAudit());
|
queue.setEnableAudit(isEnableAudit());
|
||||||
queue.setMaxAuditDepth(getMaxAuditDepth());
|
queue.setMaxAuditDepth(getMaxQueueAuditDepth());
|
||||||
queue.setMaxProducersToAudit(getMaxProducersToAudit());
|
queue.setMaxProducersToAudit(getMaxProducersToAudit());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,6 +134,8 @@ public class PolicyEntry extends DestinationMapEntry {
|
||||||
cursor.setSystemUsage(memoryManager);
|
cursor.setSystemUsage(memoryManager);
|
||||||
sub.setPending(cursor);
|
sub.setPending(cursor);
|
||||||
}
|
}
|
||||||
|
sub.setMaxAuditDepth(getMaxAuditDepth());
|
||||||
|
sub.setMaxProducersToAudit(getMaxProducersToAudit());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
|
@ -331,4 +335,20 @@ public class PolicyEntry extends DestinationMapEntry {
|
||||||
this.enableAudit = enableAudit;
|
this.enableAudit = enableAudit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxQueueAuditDepth() {
|
||||||
|
return maxQueueAuditDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxQueueAuditDepth(int maxQueueAuditDepth) {
|
||||||
|
this.maxQueueAuditDepth = maxQueueAuditDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOptimizedDispatch() {
|
||||||
|
return optimizedDispatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOptimizedDispatch(boolean optimizedDispatch) {
|
||||||
|
this.optimizedDispatch = optimizedDispatch;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import java.util.Map;
|
||||||
import org.apache.activemq.ActiveMQConnection;
|
import org.apache.activemq.ActiveMQConnection;
|
||||||
import org.apache.activemq.advisory.AdvisorySupport;
|
import org.apache.activemq.advisory.AdvisorySupport;
|
||||||
import org.apache.activemq.broker.region.MessageReference;
|
import org.apache.activemq.broker.region.MessageReference;
|
||||||
|
import org.apache.activemq.usage.MemoryUsage;
|
||||||
import org.apache.activemq.util.ByteArrayInputStream;
|
import org.apache.activemq.util.ByteArrayInputStream;
|
||||||
import org.apache.activemq.util.ByteArrayOutputStream;
|
import org.apache.activemq.util.ByteArrayOutputStream;
|
||||||
import org.apache.activemq.util.ByteSequence;
|
import org.apache.activemq.util.ByteSequence;
|
||||||
|
@ -81,6 +82,7 @@ public abstract class Message extends BaseCommand implements MarshallAware, Mess
|
||||||
private transient short referenceCount;
|
private transient short referenceCount;
|
||||||
private transient ActiveMQConnection connection;
|
private transient ActiveMQConnection connection;
|
||||||
private transient org.apache.activemq.broker.region.Destination regionDestination;
|
private transient org.apache.activemq.broker.region.Destination regionDestination;
|
||||||
|
private transient MemoryUsage memoryUsage;
|
||||||
|
|
||||||
private BrokerId[] brokerPath;
|
private BrokerId[] brokerPath;
|
||||||
private BrokerId[] cluster;
|
private BrokerId[] cluster;
|
||||||
|
@ -127,6 +129,7 @@ public abstract class Message extends BaseCommand implements MarshallAware, Mess
|
||||||
copy.regionDestination = regionDestination;
|
copy.regionDestination = regionDestination;
|
||||||
copy.brokerInTime = brokerInTime;
|
copy.brokerInTime = brokerInTime;
|
||||||
copy.brokerOutTime = brokerOutTime;
|
copy.brokerOutTime = brokerOutTime;
|
||||||
|
copy.memoryUsage=this.memoryUsage;
|
||||||
// copying the broker path breaks networks - if a consumer re-uses a
|
// copying the broker path breaks networks - if a consumer re-uses a
|
||||||
// consumed
|
// consumed
|
||||||
// message and forwards it on
|
// message and forwards it on
|
||||||
|
@ -567,6 +570,17 @@ public abstract class Message extends BaseCommand implements MarshallAware, Mess
|
||||||
|
|
||||||
public void setRegionDestination(org.apache.activemq.broker.region.Destination destination) {
|
public void setRegionDestination(org.apache.activemq.broker.region.Destination destination) {
|
||||||
this.regionDestination = destination;
|
this.regionDestination = destination;
|
||||||
|
if(this.memoryUsage==null) {
|
||||||
|
this.memoryUsage=regionDestination.getBrokerMemoryUsage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemoryUsage getMemoryUsage() {
|
||||||
|
return this.memoryUsage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemoryUsage(MemoryUsage usage) {
|
||||||
|
this.memoryUsage=usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMarshallAware() {
|
public boolean isMarshallAware() {
|
||||||
|
@ -581,16 +595,15 @@ public abstract class Message extends BaseCommand implements MarshallAware, Mess
|
||||||
size = getSize();
|
size = getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc == 1 && regionDestination != null) {
|
if (rc == 1 && getMemoryUsage() != null) {
|
||||||
regionDestination.getBrokerMemoryUsage().increaseUsage(size);
|
getMemoryUsage().increaseUsage(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// System.out.println(" + "+getDestination()+" :::: "+getMessageId()+"
|
//System.out.println(" + "+getMemoryUsage().getName()+" :::: "+getMessageId()+"rc="+rc);
|
||||||
// "+rc);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized int decrementReferenceCount() {
|
public int decrementReferenceCount() {
|
||||||
int rc;
|
int rc;
|
||||||
int size;
|
int size;
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
|
@ -598,11 +611,10 @@ public abstract class Message extends BaseCommand implements MarshallAware, Mess
|
||||||
size = getSize();
|
size = getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc == 0 && regionDestination != null) {
|
if (rc == 0 && getMemoryUsage() != null) {
|
||||||
regionDestination.getBrokerMemoryUsage().decreaseUsage(size);
|
getMemoryUsage().decreaseUsage(size);
|
||||||
}
|
}
|
||||||
// System.out.println(" - "+getDestination()+" :::: "+getMessageId()+"
|
//System.out.println(" - "+getMemoryUsage().getName()+" :::: "+getMessageId()+"rc="+rc);
|
||||||
// "+rc);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,13 +59,15 @@ public class AMQTopicMessageStore extends AMQMessageStore implements TopicMessag
|
||||||
topicReferenceStore.recoverSubscription(clientId, subscriptionName, new RecoveryListenerAdapter(this, listener));
|
topicReferenceStore.recoverSubscription(clientId, subscriptionName, new RecoveryListenerAdapter(this, listener));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void recoverNextMessages(String clientId, String subscriptionName, int maxReturned, final MessageRecoveryListener listener) throws Exception {
|
public void recoverNextMessages(String clientId, String subscriptionName,
|
||||||
|
int maxReturned, final MessageRecoveryListener listener)
|
||||||
|
throws Exception {
|
||||||
RecoveryListenerAdapter recoveryListener = new RecoveryListenerAdapter(this, listener);
|
RecoveryListenerAdapter recoveryListener = new RecoveryListenerAdapter(this, listener);
|
||||||
topicReferenceStore.recoverNextMessages(clientId, subscriptionName, maxReturned, recoveryListener);
|
topicReferenceStore.recoverNextMessages(clientId, subscriptionName,maxReturned, recoveryListener);
|
||||||
if (recoveryListener.size() == 0) {
|
if (recoveryListener.size() == 0) {
|
||||||
flush();
|
flush();
|
||||||
topicReferenceStore.recoverNextMessages(clientId, subscriptionName, maxReturned, recoveryListener);
|
topicReferenceStore.recoverNextMessages(clientId,subscriptionName, maxReturned, recoveryListener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SubscriptionInfo lookupSubscription(String clientId, String subscriptionName) throws IOException {
|
public SubscriptionInfo lookupSubscription(String clientId, String subscriptionName) throws IOException {
|
||||||
|
@ -145,14 +147,18 @@ public class AMQTopicMessageStore extends AMQMessageStore implements TopicMessag
|
||||||
* @param key
|
* @param key
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
protected void acknowledge(ConnectionContext context,MessageId messageId, Location location, String clientId,String subscriptionName) throws IOException {
|
protected void acknowledge(ConnectionContext context, MessageId messageId,
|
||||||
|
Location location, String clientId, String subscriptionName)
|
||||||
|
throws IOException {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
lastLocation = location;
|
lastLocation = location;
|
||||||
if (topicReferenceStore.acknowledgeReference(context, clientId, subscriptionName, messageId)){
|
}
|
||||||
MessageAck ack = new MessageAck();
|
if (topicReferenceStore.acknowledgeReference(context, clientId,
|
||||||
ack.setLastMessageId(messageId);
|
subscriptionName, messageId)) {
|
||||||
removeMessage(context, ack);
|
MessageAck ack = new MessageAck();
|
||||||
}
|
ack.setLastMessageId(messageId);
|
||||||
|
removeMessage(context, ack);
|
||||||
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
asyncWriteTask.wakeup();
|
asyncWriteTask.wakeup();
|
||||||
|
|
|
@ -63,10 +63,14 @@ public class KahaReferenceStore implements ReferenceStore {
|
||||||
throw new RuntimeException("Use addMessageReference instead");
|
throw new RuntimeException("Use addMessageReference instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final boolean recoverReference(MessageRecoveryListener listener, ReferenceRecord record)
|
protected final boolean recoverReference(MessageRecoveryListener listener,
|
||||||
throws Exception {
|
ReferenceRecord record) throws Exception {
|
||||||
listener.recoverMessageReference(new MessageId(record.getMessageId()));
|
MessageId id = new MessageId(record.getMessageId());
|
||||||
return listener.hasSpace();
|
if (listener.hasSpace()) {
|
||||||
|
listener.recoverMessageReference(id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void recover(MessageRecoveryListener listener) throws Exception {
|
public synchronized void recover(MessageRecoveryListener listener) throws Exception {
|
||||||
|
@ -94,10 +98,11 @@ public class KahaReferenceStore implements ReferenceStore {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
do {
|
do {
|
||||||
ReferenceRecord msg = messageContainer.getValue(entry);
|
ReferenceRecord msg = messageContainer.getValue(entry);
|
||||||
if (msg != null) {
|
if (msg != null ) {
|
||||||
recoverReference(listener, msg);
|
if ( recoverReference(listener, msg)) {
|
||||||
count++;
|
count++;
|
||||||
lastBatchId = msg.getMessageId();
|
lastBatchId = msg.getMessageId();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
lastBatchId = null;
|
lastBatchId = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -249,11 +249,15 @@ public class KahaTopicReferenceStore extends KahaReferenceStore implements Topic
|
||||||
if (entry != null) {
|
if (entry != null) {
|
||||||
do {
|
do {
|
||||||
ConsumerMessageRef consumerRef = container.get(entry);
|
ConsumerMessageRef consumerRef = container.get(entry);
|
||||||
ReferenceRecord msg = messageContainer.getValue(consumerRef.getMessageEntry());
|
ReferenceRecord msg = messageContainer.getValue(consumerRef
|
||||||
|
.getMessageEntry());
|
||||||
if (msg != null) {
|
if (msg != null) {
|
||||||
recoverReference(listener, msg);
|
if (recoverReference(listener, msg)) {
|
||||||
count++;
|
count++;
|
||||||
container.setBatchEntry(msg.getMessageId(), entry);
|
container.setBatchEntry(msg.getMessageId(), entry);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
container.reset();
|
container.reset();
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,17 +68,20 @@ public class TopicSubContainer {
|
||||||
StoreEntry entry = listContainer.getFirst();
|
StoreEntry entry = listContainer.getFirst();
|
||||||
while (entry != null) {
|
while (entry != null) {
|
||||||
ConsumerMessageRef ref = (ConsumerMessageRef)listContainer.get(entry);
|
ConsumerMessageRef ref = (ConsumerMessageRef)listContainer.get(entry);
|
||||||
listContainer.remove(entry);
|
|
||||||
if (listContainer != null && batchEntry != null && (listContainer.isEmpty() || batchEntry.equals(entry))) {
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
if (ref != null && ref.getMessageId().equals(id)) {
|
if (ref != null && ref.getMessageId().equals(id)) {
|
||||||
result = ref;
|
result = ref;
|
||||||
|
listContainer.remove(entry);
|
||||||
|
if (batchEntry != null && batchEntry.equals(entry)) {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
entry = listContainer.getFirst();
|
entry = listContainer.getNext(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (listContainer != null && (listContainer.isEmpty() )) {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,15 +118,15 @@ public class MemoryUsage extends Usage<MemoryUsage> {
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (parent != null) {
|
|
||||||
((MemoryUsage)parent).increaseUsage(value);
|
|
||||||
}
|
|
||||||
int percentUsage;
|
int percentUsage;
|
||||||
synchronized (usageMutex) {
|
synchronized (usageMutex) {
|
||||||
usage += value;
|
usage += value;
|
||||||
percentUsage = caclPercentUsage();
|
percentUsage = caclPercentUsage();
|
||||||
}
|
}
|
||||||
setPercentUsage(percentUsage);
|
setPercentUsage(percentUsage);
|
||||||
|
if (parent != null) {
|
||||||
|
((MemoryUsage)parent).increaseUsage(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -138,15 +138,15 @@ public class MemoryUsage extends Usage<MemoryUsage> {
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (parent != null) {
|
|
||||||
parent.decreaseUsage(value);
|
|
||||||
}
|
|
||||||
int percentUsage;
|
int percentUsage;
|
||||||
synchronized (usageMutex) {
|
synchronized (usageMutex) {
|
||||||
usage -= value;
|
usage -= value;
|
||||||
percentUsage = caclPercentUsage();
|
percentUsage = caclPercentUsage();
|
||||||
}
|
}
|
||||||
setPercentUsage(percentUsage);
|
setPercentUsage(percentUsage);
|
||||||
|
if (parent != null) {
|
||||||
|
parent.decreaseUsage(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected long retrieveUsage() {
|
protected long retrieveUsage() {
|
||||||
|
|
|
@ -30,6 +30,7 @@ public class BitArrayBin {
|
||||||
private int firstIndex = -1;
|
private int firstIndex = -1;
|
||||||
private int firstBin = -1;
|
private int firstBin = -1;
|
||||||
private long lastBitSet=-1;
|
private long lastBitSet=-1;
|
||||||
|
private long lastInOrderBit=-1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a BitArrayBin to a certain window size (number of messages to
|
* Create a BitArrayBin to a certain window size (number of messages to
|
||||||
|
@ -76,10 +77,15 @@ public class BitArrayBin {
|
||||||
* @return true if next message is in order
|
* @return true if next message is in order
|
||||||
*/
|
*/
|
||||||
public boolean isInOrder(long index) {
|
public boolean isInOrder(long index) {
|
||||||
if (lastBitSet== -1) {
|
boolean result = false;
|
||||||
return true;
|
if (lastInOrderBit == -1) {
|
||||||
|
result = true;
|
||||||
|
} else {
|
||||||
|
result = lastInOrderBit + 1 == index;
|
||||||
}
|
}
|
||||||
return lastBitSet+1==index;
|
lastInOrderBit = index;
|
||||||
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -105,6 +105,7 @@ public class ActiveMQMessageAuditTest extends TestCase {
|
||||||
String id = idGen.generateId();
|
String id = idGen.generateId();
|
||||||
if (i==0) {
|
if (i==0) {
|
||||||
assertFalse(audit.isDuplicate(id));
|
assertFalse(audit.isDuplicate(id));
|
||||||
|
assertTrue(audit.isInOrder(id));
|
||||||
}
|
}
|
||||||
if (i > 1 && i%2 != 0) {
|
if (i > 1 && i%2 != 0) {
|
||||||
list.add(id);
|
list.add(id);
|
||||||
|
|
|
@ -63,6 +63,8 @@ public class DurableConsumerTest extends TestCase {
|
||||||
MessageConsumer consumer = consumerSession.createDurableSubscriber(topic, CONSUMER_NAME);
|
MessageConsumer consumer = consumerSession.createDurableSubscriber(topic, CONSUMER_NAME);
|
||||||
consumerConnection.start();
|
consumerConnection.start();
|
||||||
consumerConnection.close();
|
consumerConnection.close();
|
||||||
|
broker.stop();
|
||||||
|
broker =createBroker();
|
||||||
|
|
||||||
Connection producerConnection = factory.createConnection();
|
Connection producerConnection = factory.createConnection();
|
||||||
|
|
||||||
|
@ -79,7 +81,8 @@ public class DurableConsumerTest extends TestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
producerConnection.close();
|
producerConnection.close();
|
||||||
|
broker.stop();
|
||||||
|
broker =createBroker();
|
||||||
|
|
||||||
consumerConnection = factory.createConnection();
|
consumerConnection = factory.createConnection();
|
||||||
consumerConnection.setClientID(CONSUMER_NAME);
|
consumerConnection.setClientID(CONSUMER_NAME);
|
||||||
|
|
Loading…
Reference in New Issue