mirror of https://github.com/apache/activemq.git
- Made the dispatchValve handling a little safer.. it was previously possible that an exception could cause the broker to miss turning it off before trying to turn it on.
- better producer flow control logic, was not working for sync send producers without a window git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@559915 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
3b88ba0c47
commit
6a928d5cfe
|
@ -19,10 +19,12 @@ package org.apache.activemq.broker.region;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import javax.jms.InvalidSelectorException;
|
import javax.jms.InvalidSelectorException;
|
||||||
import javax.jms.JMSException;
|
import javax.jms.JMSException;
|
||||||
|
@ -48,6 +50,7 @@ import org.apache.activemq.command.Message;
|
||||||
import org.apache.activemq.command.MessageAck;
|
import org.apache.activemq.command.MessageAck;
|
||||||
import org.apache.activemq.command.MessageId;
|
import org.apache.activemq.command.MessageId;
|
||||||
import org.apache.activemq.command.ProducerAck;
|
import org.apache.activemq.command.ProducerAck;
|
||||||
|
import org.apache.activemq.command.Response;
|
||||||
import org.apache.activemq.filter.BooleanExpression;
|
import org.apache.activemq.filter.BooleanExpression;
|
||||||
import org.apache.activemq.filter.MessageEvaluationContext;
|
import org.apache.activemq.filter.MessageEvaluationContext;
|
||||||
import org.apache.activemq.kaha.Store;
|
import org.apache.activemq.kaha.Store;
|
||||||
|
@ -217,28 +220,31 @@ public class Queue implements Destination, Task {
|
||||||
// duplicates
|
// duplicates
|
||||||
// etc.
|
// etc.
|
||||||
dispatchValve.turnOff();
|
dispatchValve.turnOff();
|
||||||
msgContext.setDestination(destination);
|
try {
|
||||||
synchronized(pagedInMessages){
|
msgContext.setDestination(destination);
|
||||||
// Add all the matching messages in the queue to the
|
synchronized(pagedInMessages){
|
||||||
// subscription.
|
// Add all the matching messages in the queue to the
|
||||||
for(Iterator i=pagedInMessages.iterator();i.hasNext();){
|
// subscription.
|
||||||
QueueMessageReference node=(QueueMessageReference)i.next();
|
for(Iterator i=pagedInMessages.iterator();i.hasNext();){
|
||||||
if(node.isDropped()){
|
QueueMessageReference node=(QueueMessageReference)i.next();
|
||||||
continue;
|
if(node.isDropped()){
|
||||||
}
|
continue;
|
||||||
try{
|
}
|
||||||
msgContext.setMessageReference(node);
|
try{
|
||||||
if(sub.matches(node,msgContext)){
|
msgContext.setMessageReference(node);
|
||||||
sub.add(node);
|
if(sub.matches(node,msgContext)){
|
||||||
}
|
sub.add(node);
|
||||||
}catch(IOException e){
|
}
|
||||||
log.warn("Could not load message: "+e,e);
|
}catch(IOException e){
|
||||||
}
|
log.warn("Could not load message: "+e,e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
dispatchValve.turnOn();
|
||||||
}
|
}
|
||||||
}finally{
|
}finally{
|
||||||
msgContext.clear();
|
msgContext.clear();
|
||||||
dispatchValve.turnOn();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,7 +257,6 @@ public class Queue implements Destination, Task {
|
||||||
// while
|
// while
|
||||||
// removing up a subscription.
|
// removing up a subscription.
|
||||||
dispatchValve.turnOff();
|
dispatchValve.turnOff();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
synchronized (consumers) {
|
synchronized (consumers) {
|
||||||
|
@ -353,10 +358,12 @@ public class Queue implements Destination, Task {
|
||||||
final ConnectionContext context = producerExchange.getConnectionContext();
|
final ConnectionContext context = producerExchange.getConnectionContext();
|
||||||
// There is delay between the client sending it and it arriving at the
|
// There is delay between the client sending it and it arriving at the
|
||||||
// destination.. it may have expired.
|
// destination.. it may have expired.
|
||||||
|
|
||||||
|
final boolean sendProducerAck = ( !message.isResponseRequired() || producerExchange.getProducerState().getInfo().getWindowSize() > 0 ) && !context.isInRecoveryMode();
|
||||||
if(message.isExpired()){
|
if(message.isExpired()){
|
||||||
broker.messageExpired(context,message);
|
broker.messageExpired(context,message);
|
||||||
destinationStatistics.getMessages().decrement();
|
destinationStatistics.getMessages().decrement();
|
||||||
if( ( !message.isResponseRequired() || producerExchange.getProducerState().getInfo().getWindowSize() > 0 ) && !context.isInRecoveryMode() ) {
|
if( sendProducerAck ) {
|
||||||
ProducerAck ack = new ProducerAck(producerExchange.getProducerState().getInfo().getProducerId(), message.getSize());
|
ProducerAck ack = new ProducerAck(producerExchange.getProducerState().getInfo().getProducerId(), message.getSize());
|
||||||
context.getConnection().dispatchAsync(ack);
|
context.getConnection().dispatchAsync(ack);
|
||||||
}
|
}
|
||||||
|
@ -373,24 +380,28 @@ public class Queue implements Destination, Task {
|
||||||
synchronized( messagesWaitingForSpace ) {
|
synchronized( messagesWaitingForSpace ) {
|
||||||
messagesWaitingForSpace.add(new Runnable() {
|
messagesWaitingForSpace.add(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
// While waiting for space to free up... the message may have expired.
|
|
||||||
if(message.isExpired()){
|
|
||||||
broker.messageExpired(context,message);
|
|
||||||
destinationStatistics.getMessages().decrement();
|
|
||||||
|
|
||||||
if( !message.isResponseRequired() && !context.isInRecoveryMode() ) {
|
|
||||||
ProducerAck ack = new ProducerAck(producerExchange.getProducerState().getInfo().getProducerId(), message.getSize());
|
|
||||||
context.getConnection().dispatchAsync(ack);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
doMessageSend(producerExchange, message);
|
|
||||||
|
// While waiting for space to free up... the message may have expired.
|
||||||
|
if(message.isExpired()) {
|
||||||
|
broker.messageExpired(context,message);
|
||||||
|
destinationStatistics.getMessages().decrement();
|
||||||
|
} else {
|
||||||
|
doMessageSend(producerExchange, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sendProducerAck ) {
|
||||||
|
ProducerAck ack = new ProducerAck(producerExchange.getProducerState().getInfo().getProducerId(), message.getSize());
|
||||||
|
context.getConnection().dispatchAsync(ack);
|
||||||
|
} else {
|
||||||
|
Response response = new Response();
|
||||||
|
response.setCorrelationId(message.getCommandId());
|
||||||
|
context.getConnection().dispatchAsync(response);
|
||||||
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if( message.isResponseRequired() && !context.isInRecoveryMode() ) {
|
if( !sendProducerAck && !context.isInRecoveryMode() ) {
|
||||||
ExceptionResponse response = new ExceptionResponse(e);
|
ExceptionResponse response = new ExceptionResponse(e);
|
||||||
response.setCorrelationId(message.getCommandId());
|
response.setCorrelationId(message.getCommandId());
|
||||||
context.getConnection().dispatchAsync(response);
|
context.getConnection().dispatchAsync(response);
|
||||||
|
@ -428,6 +439,10 @@ public class Queue implements Destination, Task {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
doMessageSend(producerExchange, message);
|
doMessageSend(producerExchange, message);
|
||||||
|
if( sendProducerAck ) {
|
||||||
|
ProducerAck ack = new ProducerAck(producerExchange.getProducerState().getInfo().getProducerId(), message.getSize());
|
||||||
|
context.getConnection().dispatchAsync(ack);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void doMessageSend(final ProducerBrokerExchange producerExchange, final Message message) throws IOException, Exception {
|
void doMessageSend(final ProducerBrokerExchange producerExchange, final Message message) throws IOException, Exception {
|
||||||
|
@ -436,10 +451,6 @@ public class Queue implements Destination, Task {
|
||||||
if(store!=null&&message.isPersistent()){
|
if(store!=null&&message.isPersistent()){
|
||||||
store.addMessage(context,message);
|
store.addMessage(context,message);
|
||||||
}
|
}
|
||||||
if( ( !message.isResponseRequired() || producerExchange.getProducerState().getInfo().getWindowSize() > 0 ) && !context.isInRecoveryMode() ) {
|
|
||||||
ProducerAck ack = new ProducerAck(producerExchange.getProducerState().getInfo().getProducerId(), message.getSize());
|
|
||||||
context.getConnection().dispatchAsync(ack);
|
|
||||||
}
|
|
||||||
if(context.isInTransaction()){
|
if(context.isInTransaction()){
|
||||||
// If this is a transacted message.. increase the usage now so that a big TX does not blow up
|
// If this is a transacted message.. increase the usage now so that a big TX does not blow up
|
||||||
// our memory. This increment is decremented once the tx finishes..
|
// our memory. This increment is decremented once the tx finishes..
|
||||||
|
@ -986,6 +997,7 @@ public class Queue implements Destination, Task {
|
||||||
}
|
}
|
||||||
|
|
||||||
private List doPageIn(boolean force) throws Exception{
|
private List doPageIn(boolean force) throws Exception{
|
||||||
|
|
||||||
final int toPageIn=maximumPagedInMessages-pagedInMessages.size();
|
final int toPageIn=maximumPagedInMessages-pagedInMessages.size();
|
||||||
List result=null;
|
List result=null;
|
||||||
if((force||!consumers.isEmpty())&&toPageIn>0){
|
if((force||!consumers.isEmpty())&&toPageIn>0){
|
||||||
|
@ -995,6 +1007,7 @@ public class Queue implements Destination, Task {
|
||||||
int count=0;
|
int count=0;
|
||||||
result=new ArrayList(toPageIn);
|
result=new ArrayList(toPageIn);
|
||||||
synchronized(messages){
|
synchronized(messages){
|
||||||
|
|
||||||
try{
|
try{
|
||||||
messages.reset();
|
messages.reset();
|
||||||
while(messages.hasNext()&&count<toPageIn){
|
while(messages.hasNext()&&count<toPageIn){
|
||||||
|
|
Loading…
Reference in New Issue