- 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:
Hiram R. Chirino 2007-07-26 18:07:16 +00:00
parent 3b88ba0c47
commit 6a928d5cfe
1 changed files with 54 additions and 41 deletions

View File

@ -19,10 +19,12 @@ package org.apache.activemq.broker.region;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.jms.InvalidSelectorException;
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.MessageId;
import org.apache.activemq.command.ProducerAck;
import org.apache.activemq.command.Response;
import org.apache.activemq.filter.BooleanExpression;
import org.apache.activemq.filter.MessageEvaluationContext;
import org.apache.activemq.kaha.Store;
@ -217,28 +220,31 @@ public class Queue implements Destination, Task {
// duplicates
// etc.
dispatchValve.turnOff();
msgContext.setDestination(destination);
synchronized(pagedInMessages){
// Add all the matching messages in the queue to the
// subscription.
for(Iterator i=pagedInMessages.iterator();i.hasNext();){
QueueMessageReference node=(QueueMessageReference)i.next();
if(node.isDropped()){
continue;
}
try{
msgContext.setMessageReference(node);
if(sub.matches(node,msgContext)){
sub.add(node);
}
}catch(IOException e){
log.warn("Could not load message: "+e,e);
}
}
try {
msgContext.setDestination(destination);
synchronized(pagedInMessages){
// Add all the matching messages in the queue to the
// subscription.
for(Iterator i=pagedInMessages.iterator();i.hasNext();){
QueueMessageReference node=(QueueMessageReference)i.next();
if(node.isDropped()){
continue;
}
try{
msgContext.setMessageReference(node);
if(sub.matches(node,msgContext)){
sub.add(node);
}
}catch(IOException e){
log.warn("Could not load message: "+e,e);
}
}
}
} finally {
dispatchValve.turnOn();
}
}finally{
msgContext.clear();
dispatchValve.turnOn();
}
}
@ -251,7 +257,6 @@ public class Queue implements Destination, Task {
// while
// removing up a subscription.
dispatchValve.turnOff();
try {
synchronized (consumers) {
@ -353,10 +358,12 @@ public class Queue implements Destination, Task {
final ConnectionContext context = producerExchange.getConnectionContext();
// There is delay between the client sending it and it arriving at the
// destination.. it may have expired.
final boolean sendProducerAck = ( !message.isResponseRequired() || producerExchange.getProducerState().getInfo().getWindowSize() > 0 ) && !context.isInRecoveryMode();
if(message.isExpired()){
broker.messageExpired(context,message);
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());
context.getConnection().dispatchAsync(ack);
}
@ -374,23 +381,27 @@ public class Queue implements Destination, Task {
messagesWaitingForSpace.add(new Runnable() {
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 {
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) {
if( message.isResponseRequired() && !context.isInRecoveryMode() ) {
if( !sendProducerAck && !context.isInRecoveryMode() ) {
ExceptionResponse response = new ExceptionResponse(e);
response.setCorrelationId(message.getCommandId());
context.getConnection().dispatchAsync(response);
@ -428,6 +439,10 @@ public class Queue implements Destination, Task {
}
}
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 {
@ -436,10 +451,6 @@ public class Queue implements Destination, Task {
if(store!=null&&message.isPersistent()){
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 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..
@ -986,6 +997,7 @@ public class Queue implements Destination, Task {
}
private List doPageIn(boolean force) throws Exception{
final int toPageIn=maximumPagedInMessages-pagedInMessages.size();
List result=null;
if((force||!consumers.isEmpty())&&toPageIn>0){
@ -995,6 +1007,7 @@ public class Queue implements Destination, Task {
int count=0;
result=new ArrayList(toPageIn);
synchronized(messages){
try{
messages.reset();
while(messages.hasNext()&&count<toPageIn){